'use strict'; /*@ Ox.extend Extends an object with one or more other objects > Ox.extend({a: 1, b: 1, c: 1}, {b: 2, c: 2}, {c: 3}) {a: 1, b: 2, c: 3} @*/ Ox.extend = function(obj) { Ox.forEach(Ox.slice(arguments, 1), function(arg, i) { Ox.forEach(arg, function(val, key) { obj[key] = val; }); }); return obj; }; /*@ Ox.getset Generic getter and setter function See examples for details. # Usage -------------------------------------------------------------------- Ox.getset(options, args=[]) -> all options Ox.getset(options, args=[key]) -> <*> options[key] Ox.getset(options, args=[key, value], callback, that) -> context sets options[key] to value and calls fn(key, value) if the key/value pair was added or modified Ox.getset(options, args=[{key: value}], callback, that) -> that sets multiple options and calls fn(key, value) for every key/value pair that was added or modified # Arguments ---------------------------------------------------------------- options Options object (key/value pairs) args The arguments "array" of the caller function callback Callback function The callback is called for every key/value pair that was added or modified. key Key value <*> Value that The this object of the caller function (for chaining) # Examples ----------------------------------------------------------------- > Ox.test.object.options("key", "val").options("key") "val" > Ox.test.object.options({foo: "foo", bar: "bar"}).options() {"key": "val", "foo": "foo", "bar": "bar"} @*/ Ox.getset = function(object, args, callback, that) { var object_ = Ox.clone(object), ret; if (args.length == 0) { // [] ret = object_; } else if (args.length == 1 && !Ox.isObject(args[0])) { // [key] ret = Ox.clone(object[args[0]]); } else { // [key, val] or [{key: val, ...}] args = Ox.makeObject(args); object = Ox.extend(object, args); Ox.forEach(args, function(value, key) { if (!object_ || !Ox.isEqual(object_[key], value)) { callback && callback(key, value); } }); ret = that; } return ret; }; Ox.hasOwn = function(obj, val) { return Object.prototype.hasOwnProperty.call(obj, val) }; /*@ Ox.keyOf Equivalent of [].indexOf for objects > Ox.keyOf({a: 1, b: 2, c: 3}, 1) 'a' @*/ Ox.keyOf = function(obj, val) { var key; Ox.forEach(obj, function(v, k) { if (v === val) { key = k; Ox.Break(); } }); return key; }; /*@ Ox.makeObject Takes an array and returns an object Ox.makeObject is a helper for functions with two alternative signatures like ('key', 'val') and ({key: 'val'}). > (function() { return Ox.makeObject(arguments); }({foo: 1, bar: 2})) {foo: 1, bar: 2} > (function() { return Ox.makeObject(arguments); }('foo', 1)) {foo: 1} > (function() { return Ox.makeObject(arguments); }('foo')) {foo: void 0} > (function() { return Ox.makeObject(arguments); }()) {} @*/ Ox.makeObject = function(array) { var ret = {}; if (Ox.isObject(array[0])) { // ({foo: 'bar'}) ret = array[0]; } else if (array.length) { // ('foo', 'bar') ret[array[0]] = array[1]; } return ret; }; /*@ Ox.methods Returns a sorted list of all method names of an object > Ox.methods({a: [], b: false, f: function() {}, n: 0, o: {}, s: ''}) ['f'] @*/ Ox.methods = function(obj, includePrototype) { var key, keys; if (includePrototype) { keys = []; for (var key in obj) { keys.push(key); } } else { keys = Object.keys(obj); } return keys.filter(function(key) { return Ox.isFunction(obj[key]); }).sort(); }; /*@ Ox.serialize Parses an object into query parameters > Ox.serialize({a: 1, b: 2, c: 3}) 'a=1&b=2&c=3' > Ox.serialize({a: -1, b: 2.3, c: [4, 5]}) 'a=-1&b=2.3&c=4,5' > Ox.serialize({string: 'foo', empty: {}, null: null, undefined: void 0}) 'string=foo' @*/ Ox.serialize = function(obj) { var arr = []; Ox.forEach(obj, function(val, key) { if (!Ox.isEmpty(val) && !Ox.isNull(val) && !Ox.isUndefined(val)) { arr.push(key + '=' + val); } }); return arr.join('&'); }; /*@ Ox.unserialize Parses query parameters into an object > Ox.unserialize('a=1&b=2&c=3') {a: '1', b: '2', c: '3'} > Ox.unserialize('a=-1&b=2.3&c=4,5', true) {a: -1, b: 2.3, c: [4, 5]} > Ox.unserialize('a=1&b=&c&a=0', true) {a: 0} @*/ Ox.unserialize = function(str, toNumber) { var obj = {}; str.split('&').forEach(function(val) { if (val) { var arr = val.split('='); if (arr[1]) { obj[arr[0]] = !toNumber ? arr[1] : arr[1].indexOf(',') == -1 ? +arr[1] : arr[1].split(',').map(function(val) { return +val; }); } } }); return obj; };