handsontable
Version:
Handsontable is a JavaScript Spreadsheet Component available for React, Angular and Vue.
428 lines (357 loc) • 11.9 kB
JavaScript
;
exports.__esModule = true;
exports.clone = clone;
exports.createObjectPropListener = createObjectPropListener;
exports.deepClone = deepClone;
exports.deepExtend = deepExtend;
exports.deepObjectSize = deepObjectSize;
exports.defineGetter = defineGetter;
exports.duckSchema = duckSchema;
exports.extend = extend;
exports.getProperty = getProperty;
exports.hasOwnProperty = hasOwnProperty;
exports.inherit = inherit;
exports.isObject = isObject;
exports.isObjectEqual = isObjectEqual;
exports.mixin = mixin;
exports.objectEach = objectEach;
exports.setProperty = setProperty;
require("core-js/modules/es.array.includes.js");
require("core-js/modules/es.string.includes.js");
require("core-js/modules/es.object.to-string.js");
require("core-js/modules/es.regexp.exec.js");
require("core-js/modules/es.string.split.js");
require("core-js/modules/web.dom-collections.for-each.js");
require("core-js/modules/es.symbol.js");
require("core-js/modules/es.symbol.description.js");
require("core-js/modules/es.symbol.iterator.js");
require("core-js/modules/es.array.iterator.js");
require("core-js/modules/es.string.iterator.js");
require("core-js/modules/web.dom-collections.iterator.js");
var _array = require("./array");
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
/**
* Generate schema for passed object.
*
* @param {Array|object} object An object to analyze.
* @returns {Array|object}
*/
function duckSchema(object) {
var schema;
if (Array.isArray(object)) {
schema = [];
} else {
schema = {};
objectEach(object, function (value, key) {
if (key === '__children') {
return;
}
if (value && _typeof(value) === 'object' && !Array.isArray(value)) {
schema[key] = duckSchema(value);
} else if (Array.isArray(value)) {
if (value.length && _typeof(value[0]) === 'object' && !Array.isArray(value[0])) {
schema[key] = [duckSchema(value[0])];
} else {
schema[key] = [];
}
} else {
schema[key] = null;
}
});
}
return schema;
}
/**
* Inherit without without calling parent constructor, and setting `Child.prototype.constructor` to `Child` instead of `Parent`.
* Creates temporary dummy function to call it as constructor.
* Described in ticket: https://github.com/handsontable/handsontable/pull/516.
*
* @param {object} Child The child class.
* @param {object} Parent The parent class.
* @returns {object}
*/
function inherit(Child, Parent) {
Parent.prototype.constructor = Parent;
Child.prototype = new Parent();
Child.prototype.constructor = Child;
return Child;
}
/**
* Perform shallow extend of a target object with extension's own properties.
*
* @param {object} target An object that will receive the new properties.
* @param {object} extension An object containing additional properties to merge into the target.
* @param {string[]} [writableKeys] An array of keys that are writable to target object.
* @returns {object}
*/
function extend(target, extension, writableKeys) {
var hasWritableKeys = Array.isArray(writableKeys);
objectEach(extension, function (value, key) {
if (hasWritableKeys === false || writableKeys.includes(key)) {
target[key] = value;
}
});
return target;
}
/**
* Perform deep extend of a target object with extension's own properties.
*
* @param {object} target An object that will receive the new properties.
* @param {object} extension An object containing additional properties to merge into the target.
*/
function deepExtend(target, extension) {
objectEach(extension, function (value, key) {
if (extension[key] && _typeof(extension[key]) === 'object') {
if (!target[key]) {
if (Array.isArray(extension[key])) {
target[key] = [];
} else if (Object.prototype.toString.call(extension[key]) === '[object Date]') {
target[key] = extension[key];
} else {
target[key] = {};
}
}
deepExtend(target[key], extension[key]);
} else {
target[key] = extension[key];
}
});
}
/**
* Perform deep clone of an object.
* WARNING! Only clones JSON properties. Will cause error when `obj` contains a function, Date, etc.
*
* @param {object} obj An object that will be cloned.
* @returns {object}
*/
function deepClone(obj) {
if (_typeof(obj) === 'object') {
return JSON.parse(JSON.stringify(obj));
}
return obj;
}
/**
* Shallow clone object.
*
* @param {object} object An object to clone.
* @returns {object}
*/
function clone(object) {
var result = {};
objectEach(object, function (value, key) {
result[key] = value;
});
return result;
}
/**
* Extend the Base object (usually prototype) of the functionality the `mixins` objects.
*
* @param {object} Base Base object which will be extended.
* @param {object} mixins The object of the functionality will be "copied".
* @returns {object}
*/
function mixin(Base) {
if (!Base.MIXINS) {
Base.MIXINS = [];
}
for (var _len = arguments.length, mixins = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
mixins[_key - 1] = arguments[_key];
}
(0, _array.arrayEach)(mixins, function (mixinItem) {
Base.MIXINS.push(mixinItem.MIXIN_NAME);
objectEach(mixinItem, function (value, key) {
if (Base.prototype[key] !== void 0) {
throw new Error("Mixin conflict. Property '".concat(key, "' already exist and cannot be overwritten."));
}
if (typeof value === 'function') {
Base.prototype[key] = value;
} else {
var getter = function _getter(property, initialValue) {
var propertyName = "_".concat(property);
var initValue = function initValue(newValue) {
var result = newValue;
if (Array.isArray(result) || isObject(result)) {
result = deepClone(result);
}
return result;
};
return function () {
if (this[propertyName] === void 0) {
this[propertyName] = initValue(initialValue);
}
return this[propertyName];
};
};
var setter = function _setter(property) {
var propertyName = "_".concat(property);
return function (newValue) {
this[propertyName] = newValue;
};
};
Object.defineProperty(Base.prototype, key, {
get: getter(key, value),
set: setter(key),
configurable: true
});
}
});
});
return Base;
}
/**
* Checks if two objects or arrays are (deep) equal.
*
* @param {object|Array} object1 The first object to compare.
* @param {object|Array} object2 The second object to compare.
* @returns {boolean}
*/
function isObjectEqual(object1, object2) {
return JSON.stringify(object1) === JSON.stringify(object2);
}
/**
* Determines whether given object is a plain Object.
* Note: String and Array are not plain Objects.
*
* @param {*} object An object to check.
* @returns {boolean}
*/
function isObject(object) {
return Object.prototype.toString.call(object) === '[object Object]';
}
/**
* @param {object} object The object on which to define the property.
* @param {string} property The name of the property to be defined or modified.
* @param {*} value The value associated with the property.
* @param {object} options The descriptor for the property being defined or modified.
*/
function defineGetter(object, property, value, options) {
options.value = value;
options.writable = options.writable !== false;
options.enumerable = options.enumerable !== false;
options.configurable = options.configurable !== false;
Object.defineProperty(object, property, options);
}
/**
* A specialized version of `.forEach` for objects.
*
* @param {object} object The object to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @returns {object} Returns `object`.
*/
function objectEach(object, iteratee) {
// eslint-disable-next-line no-restricted-syntax
for (var key in object) {
if (!object.hasOwnProperty || object.hasOwnProperty && Object.prototype.hasOwnProperty.call(object, key)) {
if (iteratee(object[key], key, object) === false) {
break;
}
}
}
return object;
}
/**
* Get object property by its name. Access to sub properties can be achieved by dot notation (e.q. `'foo.bar.baz'`).
*
* @param {object} object Object which value will be exported.
* @param {string} name Object property name.
* @returns {*}
*/
function getProperty(object, name) {
var names = name.split('.');
var result = object;
objectEach(names, function (nameItem) {
result = result[nameItem];
if (result === void 0) {
result = void 0;
return false;
}
});
return result;
}
/**
* Set a property value on the provided object. Works on nested object prop names as well (e.g. `first.name`).
*
* @param {object} object Object to work on.
* @param {string} name Prop name.
* @param {*} value Value to be assigned at the provided property.
*/
function setProperty(object, name, value) {
var names = name.split('.');
var workingObject = object;
names.forEach(function (propName, index) {
if (index !== names.length - 1) {
if (!hasOwnProperty(workingObject, propName)) {
workingObject[propName] = {};
}
workingObject = workingObject[propName];
} else {
workingObject[propName] = value;
}
});
}
/**
* Return object length (recursively).
*
* @param {*} object Object for which we want get length.
* @returns {number}
*/
function deepObjectSize(object) {
if (!isObject(object)) {
return 0;
}
var recursObjLen = function recursObjLen(obj) {
var result = 0;
if (isObject(obj)) {
objectEach(obj, function (value, key) {
if (key === '__children') {
return;
}
result += recursObjLen(value);
});
} else {
result += 1;
}
return result;
};
return recursObjLen(object);
}
/**
* Create object with property where its value change will be observed.
*
* @param {*} [defaultValue=undefined] Default value.
* @param {string} [propertyToListen='value'] Property to listen.
* @returns {object}
*/
function createObjectPropListener(defaultValue) {
var _holder;
var propertyToListen = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'value';
var privateProperty = "_".concat(propertyToListen);
var holder = (_holder = {
_touched: false
}, _defineProperty(_holder, privateProperty, defaultValue), _defineProperty(_holder, "isTouched", function isTouched() {
return this._touched;
}), _holder);
Object.defineProperty(holder, propertyToListen, {
get: function get() {
return this[privateProperty];
},
set: function set(value) {
this._touched = true;
this[privateProperty] = value;
},
enumerable: true,
configurable: true
});
return holder;
}
/**
* Check if at specified `key` there is any value for `object`.
*
* @param {object} object Object to search value at specyfic key.
* @param {string} key String key to check.
* @returns {boolean}
*/
function hasOwnProperty(object, key) {
return Object.prototype.hasOwnProperty.call(object, key);
}