You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
278 lines
6.1 KiB
278 lines
6.1 KiB
(function (root, factory){ |
|
'use strict'; |
|
|
|
/*istanbul ignore next:cant test*/ |
|
if (typeof module === 'object' && typeof module.exports === 'object') { |
|
module.exports = factory(); |
|
} else if (typeof define === 'function' && define.amd) { |
|
// AMD. Register as an anonymous module. |
|
define([], factory); |
|
} else { |
|
// Browser globals |
|
root.objectPath = factory(); |
|
} |
|
})(this, function(){ |
|
'use strict'; |
|
|
|
var |
|
toStr = Object.prototype.toString, |
|
_hasOwnProperty = Object.prototype.hasOwnProperty; |
|
|
|
function isEmpty(value){ |
|
if (!value) { |
|
return true; |
|
} |
|
if (isArray(value) && value.length === 0) { |
|
return true; |
|
} else if (!isString(value)) { |
|
for (var i in value) { |
|
if (_hasOwnProperty.call(value, i)) { |
|
return false; |
|
} |
|
} |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
function toString(type){ |
|
return toStr.call(type); |
|
} |
|
|
|
function isNumber(value){ |
|
return typeof value === 'number' || toString(value) === "[object Number]"; |
|
} |
|
|
|
function isString(obj){ |
|
return typeof obj === 'string' || toString(obj) === "[object String]"; |
|
} |
|
|
|
function isObject(obj){ |
|
return typeof obj === 'object' && toString(obj) === "[object Object]"; |
|
} |
|
|
|
function isArray(obj){ |
|
return typeof obj === 'object' && typeof obj.length === 'number' && toString(obj) === '[object Array]'; |
|
} |
|
|
|
function isBoolean(obj){ |
|
return typeof obj === 'boolean' || toString(obj) === '[object Boolean]'; |
|
} |
|
|
|
function getKey(key){ |
|
var intKey = parseInt(key); |
|
if (intKey.toString() === key) { |
|
return intKey; |
|
} |
|
return key; |
|
} |
|
|
|
function set(obj, path, value, doNotReplace){ |
|
if (isNumber(path)) { |
|
path = [path]; |
|
} |
|
if (isEmpty(path)) { |
|
return obj; |
|
} |
|
if (isString(path)) { |
|
return set(obj, path.split('.').map(getKey), value, doNotReplace); |
|
} |
|
var currentPath = path[0]; |
|
|
|
if (path.length === 1) { |
|
var oldVal = obj[currentPath]; |
|
if (oldVal === void 0 || !doNotReplace) { |
|
obj[currentPath] = value; |
|
} |
|
return oldVal; |
|
} |
|
|
|
if (obj[currentPath] === void 0) { |
|
//check if we assume an array |
|
if(isNumber(path[1])) { |
|
obj[currentPath] = []; |
|
} else { |
|
obj[currentPath] = {}; |
|
} |
|
} |
|
|
|
return set(obj[currentPath], path.slice(1), value, doNotReplace); |
|
} |
|
|
|
function del(obj, path) { |
|
if (isNumber(path)) { |
|
path = [path]; |
|
} |
|
|
|
if (isEmpty(obj)) { |
|
return void 0; |
|
} |
|
|
|
if (isEmpty(path)) { |
|
return obj; |
|
} |
|
if(isString(path)) { |
|
return del(obj, path.split('.')); |
|
} |
|
|
|
var currentPath = getKey(path[0]); |
|
var oldVal = obj[currentPath]; |
|
|
|
if(path.length === 1) { |
|
if (oldVal !== void 0) { |
|
if (isArray(obj)) { |
|
obj.splice(currentPath, 1); |
|
} else { |
|
delete obj[currentPath]; |
|
} |
|
} |
|
} else { |
|
if (obj[currentPath] !== void 0) { |
|
return del(obj[currentPath], path.slice(1)); |
|
} |
|
} |
|
|
|
return obj; |
|
} |
|
|
|
var objectPath = function(obj) { |
|
return Object.keys(objectPath).reduce(function(proxy, prop) { |
|
if (typeof objectPath[prop] === 'function') { |
|
proxy[prop] = objectPath[prop].bind(objectPath, obj); |
|
} |
|
|
|
return proxy; |
|
}, {}); |
|
}; |
|
|
|
objectPath.has = function (obj, path) { |
|
if (isEmpty(obj)) { |
|
return false; |
|
} |
|
|
|
if (isNumber(path)) { |
|
path = [path]; |
|
} else if (isString(path)) { |
|
path = path.split('.'); |
|
} |
|
|
|
if (isEmpty(path) || path.length === 0) { |
|
return false; |
|
} |
|
|
|
for (var i = 0; i < path.length; i++) { |
|
var j = path[i]; |
|
if ((isObject(obj) || isArray(obj)) && _hasOwnProperty.call(obj, j)) { |
|
obj = obj[j]; |
|
} else { |
|
return false; |
|
} |
|
} |
|
|
|
return true; |
|
}; |
|
|
|
objectPath.ensureExists = function (obj, path, value){ |
|
return set(obj, path, value, true); |
|
}; |
|
|
|
objectPath.set = function (obj, path, value, doNotReplace){ |
|
return set(obj, path, value, doNotReplace); |
|
}; |
|
|
|
objectPath.insert = function (obj, path, value, at){ |
|
var arr = objectPath.get(obj, path); |
|
at = ~~at; |
|
if (!isArray(arr)) { |
|
arr = []; |
|
objectPath.set(obj, path, arr); |
|
} |
|
arr.splice(at, 0, value); |
|
}; |
|
|
|
objectPath.empty = function(obj, path) { |
|
if (isEmpty(path)) { |
|
return obj; |
|
} |
|
if (isEmpty(obj)) { |
|
return void 0; |
|
} |
|
|
|
var value, i; |
|
if (!(value = objectPath.get(obj, path))) { |
|
return obj; |
|
} |
|
|
|
if (isString(value)) { |
|
return objectPath.set(obj, path, ''); |
|
} else if (isBoolean(value)) { |
|
return objectPath.set(obj, path, false); |
|
} else if (isNumber(value)) { |
|
return objectPath.set(obj, path, 0); |
|
} else if (isArray(value)) { |
|
value.length = 0; |
|
} else if (isObject(value)) { |
|
for (i in value) { |
|
if (_hasOwnProperty.call(value, i)) { |
|
delete value[i]; |
|
} |
|
} |
|
} else { |
|
return objectPath.set(obj, path, null); |
|
} |
|
}; |
|
|
|
objectPath.push = function (obj, path /*, values */){ |
|
var arr = objectPath.get(obj, path); |
|
if (!isArray(arr)) { |
|
arr = []; |
|
objectPath.set(obj, path, arr); |
|
} |
|
|
|
arr.push.apply(arr, Array.prototype.slice.call(arguments, 2)); |
|
}; |
|
|
|
objectPath.coalesce = function (obj, paths, defaultValue) { |
|
var value; |
|
|
|
for (var i = 0, len = paths.length; i < len; i++) { |
|
if ((value = objectPath.get(obj, paths[i])) !== void 0) { |
|
return value; |
|
} |
|
} |
|
|
|
return defaultValue; |
|
}; |
|
|
|
objectPath.get = function (obj, path, defaultValue){ |
|
if (isNumber(path)) { |
|
path = [path]; |
|
} |
|
if (isEmpty(path)) { |
|
return obj; |
|
} |
|
if (isEmpty(obj)) { |
|
return defaultValue; |
|
} |
|
if (isString(path)) { |
|
return objectPath.get(obj, path.split('.'), defaultValue); |
|
} |
|
|
|
var currentPath = getKey(path[0]); |
|
|
|
if (path.length === 1) { |
|
if (obj[currentPath] === void 0) { |
|
return defaultValue; |
|
} |
|
return obj[currentPath]; |
|
} |
|
|
|
return objectPath.get(obj[currentPath], path.slice(1), defaultValue); |
|
}; |
|
|
|
objectPath.del = function(obj, path) { |
|
return del(obj, path); |
|
}; |
|
|
|
return objectPath; |
|
});
|
|
|