b374k
m1n1 1.01
Apache/2.4.41 (Ubuntu)
Linux vmi616275.contaboserver.net 5.4.0-84-generic #94-Ubuntu SMP Thu Aug 26 20:27:37 UTC 2021 x86_64
uid=33(www-data) gid=33(www-data) groups=33(www-data)
server ip : 62.171.164.128 | your ip : 127.0.0.1
safemode OFF
 >  / home / a / home / dev2.destoffenstraat.com / lib / web / mage / utils /
Filename/home/a/home/dev2.destoffenstraat.com/lib/web/mage/utils/objects.js
Size12.76 kb
Permissionrw-r--r--
Ownerroot : root
Create time21-Aug-2025 12:26
Last modified28-Jan-2025 06:45
Last accessed22-Aug-2025 21:42
Actionsedit | rename | delete | download (gzip)
Viewtext | code | image
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
define([
'ko',
'jquery',
'underscore'
], function (ko, $, _) {
'use strict';

var primitives = [
'undefined',
'boolean',
'number',
'string'
];

/**
* Sets nested property of a specified object.
* @private
*
* @param {Object} parent - Object to look inside for the properties.
* @param {Array} path - Splitted path the property.
* @param {*} value - Value of the last property in 'path' array.
* returns {*} New value for the property.
*/
function setNested(parent, path, value) {
var last = path.pop(),
len = path.length,
pi = 0,
part = path[pi];

for (; pi < len; part = path[++pi]) {
if (!_.isObject(parent[part])) {
parent[part] = {};
}

parent = parent[part];
}

if (typeof parent[last] === 'function') {
parent[last](value);
} else {
parent[last] = value;
}

return value;
}

/**
* Retrieves value of a nested property.
* @private
*
* @param {Object} parent - Object to look inside for the properties.
* @param {Array} path - Splitted path the property.
* @returns {*} Value of the property.
*/
function getNested(parent, path) {
var exists = true,
len = path.length,
pi = 0;

for (; pi < len && exists; pi++) {
parent = parent[path[pi]];

if (typeof parent === 'undefined') {
exists = false;
}
}

if (exists) {
if (ko.isObservable(parent)) {
parent = parent();
}

return parent;
}
}

/**
* Removes property from a specified object.
* @private
*
* @param {Object} parent - Object from which to remove property.
* @param {Array} path - Splitted path to the property.
*/
function removeNested(parent, path) {
var field = path.pop();

parent = getNested(parent, path);

if (_.isObject(parent)) {
delete parent[field];
}
}

return {

/**
* Retrieves or defines objects' property by a composite path.
*
* @param {Object} data - Container for the properties specified in path.
* @param {String} path - Objects' properties divided by dots.
* @param {*} [value] - New value for the last property.
* @returns {*} Returns value of the last property in chain.
*
* @example
* utils.nested({}, 'one.two', 3);
* => { one: {two: 3} }
*/
nested: function (data, path, value) {
var action = arguments.length > 2 ? setNested : getNested;

path = path ? path.split('.') : [];

return action(data, path, value);
},

/**
* Removes nested property from an object.
*
* @param {Object} data - Data source.
* @param {String} path - Path to the property e.g. 'one.two.three'
*/
nestedRemove: function (data, path) {
path = path.split('.');

removeNested(data, path);
},

/**
* Flattens objects' nested properties.
*
* @param {Object} data - Object to flatten.
* @param {String} [separator='.'] - Objects' keys separator.
* @returns {Object} Flattened object.
*
* @example Example with a default separator.
* utils.flatten({one: { two: { three: 'value'} }});
* => { 'one.two.three': 'value' };
*
* @example Example with a custom separator.
* utils.flatten({one: { two: { three: 'value'} }}, '=>');
* => {'one=>two=>three': 'value'};
*/
flatten: function (data, separator, parent, result) {
separator = separator || '.';
result = result || {};

if (!data) {
return result;
}

// UnderscoreJS each breaks when an object has a length property so we use Object.keys
_.each(Object.keys(data), function (name) {
var node = data[name];

if ({}.toString.call(node) === '[object Function]') {
return;
}

if (parent) {
name = parent + separator + name;
}

typeof node === 'object' ?
this.flatten(node, separator, name, result) :
result[name] = node;

}, this);

return result;
},

/**
* Opposite operation of the 'flatten' method.
*
* @param {Object} data - Previously flattened object.
* @param {String} [separator='.'] - Keys separator.
* @returns {Object} Object with nested properties.
*
* @example Example using custom separator.
* utils.unflatten({'one=>two': 'value'}, '=>');
* => {
* one: { two: 'value' }
* };
*/
unflatten: function (data, separator) {
var result = {};

separator = separator || '.';

_.each(data, function (value, nodes) {
nodes = nodes.split(separator);

setNested(result, nodes, value);
});

return result;
},

/**
* Same operation as 'flatten' method,
* but returns objects' keys wrapped in '[]'.
*
* @param {Object} data - Object that should be serialized.
* @returns {Object} Serialized data.
*
* @example
* utils.serialize({one: { two: { three: 'value'} }});
* => { 'one[two][three]': 'value' }
*/
serialize: function (data) {
var result = {};

data = this.flatten(data);

_.each(data, function (value, keys) {
keys = this.serializeName(keys);
value = _.isUndefined(value) ? '' : value;

result[keys] = value;
}, this);

return result;
},

/**
* Performs deep extend of specified objects.
*
* @returns {Object|Array} Extended object.
*/
extend: function () {
var args = _.toArray(arguments);

args.unshift(true);

return $.extend.apply($, args);
},

/**
* Performs a deep clone of a specified object.
*
* @param {(Object|Array)} data - Data that should be copied.
* @returns {Object|Array} Cloned object.
*/
copy: function (data) {
var result = data,
isArray = Array.isArray(data),
placeholder;

if (this.isObject(data) || isArray) {
placeholder = isArray ? [] : {};
result = this.extend(placeholder, data);
}

return result;
},

/**
* Performs a deep clone of a specified object.
* Doesn't save links to original object.
*
* @param {*} original - Object to clone
* @returns {*}
*/
hardCopy: function (original) {
if (original === null || typeof original !== 'object') {
return original;
}

return JSON.parse(JSON.stringify(original));
},

/**
* Removes specified nested properties from the target object.
*
* @param {Object} target - Object whose properties should be removed.
* @param {(...String|Array|Object)} list - List that specifies properties to be removed.
* @returns {Object} Modified object.
*
* @example Basic usage
* var obj = {a: {b: 2}, c: 'a'};
*
* omit(obj, 'a.b');
* => {'a.b': 2};
* obj => {a: {}, c: 'a'};
*
* @example Various syntaxes that would return same result
* omit(obj, ['a.b', 'c']);
* omit(obj, 'a.b', 'c');
* omit(obj, {'a.b': true, 'c': true});
*/
omit: function (target, list) {
var removed = {},
ignored = list;

if (this.isObject(list)) {
ignored = [];

_.each(list, function (value, key) {
if (value) {
ignored.push(key);
}
});
} else if (_.isString(list)) {
ignored = _.toArray(arguments).slice(1);
}

_.each(ignored, function (path) {
var value = this.nested(target, path);

if (!_.isUndefined(value)) {
removed[path] = value;

this.nestedRemove(target, path);
}
}, this);

return removed;
},

/**
* Checks if provided value is a plain object.
*
* @param {*} value - Value to be checked.
* @returns {Boolean}
*/
isObject: function (value) {
var objProto = Object.prototype;

return typeof value == 'object' ?
objProto.toString.call(value) === '[object Object]' :
false;
},

/**
*
* @param {*} value
* @returns {Boolean}
*/
isPrimitive: function (value) {
return value === null || ~primitives.indexOf(typeof value);
},

/**
* Iterates over obj props/array elems recursively, applying action to each one
*
* @param {Object|Array} data - Data to be iterated.
* @param {Function} action - Callback to be called with each item as an argument.
* @param {Number} [maxDepth=7] - Max recursion depth.
*/
forEachRecursive: function (data, action, maxDepth) {
maxDepth = typeof maxDepth === 'number' && !isNaN(maxDepth) ? maxDepth - 1 : 7;

if (!_.isFunction(action) || _.isFunction(data) || maxDepth < 0) {
return;
}

if (!_.isObject(data)) {
action(data);

return;
}

_.each(data, function (value) {
this.forEachRecursive(value, action, maxDepth);
}, this);

action(data);
},

/**
* Maps obj props/array elems recursively
*
* @param {Object|Array} data - Data to be iterated.
* @param {Function} action - Callback to transform each item.
* @param {Number} [maxDepth=7] - Max recursion depth.
*
* @returns {Object|Array}
*/
mapRecursive: function (data, action, maxDepth) {
var newData;

maxDepth = typeof maxDepth === 'number' && !isNaN(maxDepth) ? maxDepth - 1 : 7;

if (!_.isFunction(action) || _.isFunction(data) || maxDepth < 0) {
return data;
}

if (!_.isObject(data)) {
return action(data);
}

if (_.isArray(data)) {
newData = _.map(data, function (item) {
return this.mapRecursive(item, action, maxDepth);
}, this);

return action(newData);
}

newData = _.mapObject(data, function (val, key) {
if (data.hasOwnProperty(key)) {
return this.mapRecursive(val, action, maxDepth);
}

return val;
}, this);

return action(newData);
},

/**
* Removes empty(in common sence) obj props/array elems
*
* @param {*} data - Data to be cleaned.
* @returns {*}
*/
removeEmptyValues: function (data) {
if (!_.isObject(data)) {
return data;
}

if (_.isArray(data)) {
return data.filter(function (item) {
return !this.isEmptyObj(item);
}, this);
}

return _.omit(data, this.isEmptyObj.bind(this));
},

/**
* Checks that argument of any type is empty in common sence:
* empty string, string with spaces only, object without own props, empty array, null or undefined
*
* @param {*} val - Value to be checked.
* @returns {Boolean}
*/
isEmptyObj: function (val) {

return _.isObject(val) && _.isEmpty(val) ||
this.isEmpty(val) ||
val && val.trim && this.isEmpty(val.trim());
}
};
});