(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; });