oxjs/source/Ox/js/Object.js

187 lines
No EOL
5.7 KiB
JavaScript

'use strict';
/*@
Ox.extend <function> 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 <f> Generic getter and setter function
See examples for details.
# Usage --------------------------------------------------------------------
Ox.getset(options, args=[]) -> <o> all options
Ox.getset(options, args=[key]) -> <*> options[key]
Ox.getset(options, args=[key, value], callback, that) -> <f|o> 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) -> <f|o> that
sets multiple options and calls fn(key, value)
for every key/value pair that was added or modified
# Arguments ----------------------------------------------------------------
options <obj> Options object (key/value pairs)
args <arr> The arguments "array" of the caller function
callback <fun> Callback function
The callback is called for every key/value pair that was added or
modified.
key <s> Key
value <*> Value
that <obj> The this object of the caller function (for chaining)
# Examples -----------------------------------------------------------------
<script>
Ox.test.object = new function() {
var options = {},
setOption = function(key, value) {
// handle added or modified options
},
that = this;
that.options = function() {
return Ox.getset(options, arguments, setOption, that);
};
return that;
};
</script>
> 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 <f> 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 <f> Takes an array and returns an object
<code>Ox.makeObject</code> is a helper for functions with two alternative
signatures like <code>('key', 'val')</code> and <code>({key: 'val'})</code>.
> (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 <f> 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 <f> 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 <f> 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;
};