UNPKG

@wider/utils_proto

Version:

A set of extensions to basic objects giving uniform behaviour in various technical environments

320 lines (269 loc) 23.1 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Source: proto_object/index.js | YDR</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/bootstrap.min.css"> <link type="text/css" rel="stylesheet" href="styles/prettify-jsdoc.css"> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/tui-doc.css"> </head> <body> <nav class="lnb" id="lnb"> <div class="logo" style="width: 50px"> <a href="http://y-d-r.co.uk" rel="noopener noreferrer" target="_blank"> <img src="http://y-d-r.co.uk/favicon.ico" width="100%" height="100%"> </a> </div> <div class="title"> <h1><a href="index.html" class="link">YDR</a></h1> <span class="version">v1.0.23</span> </div> <div class="search-container" id="search-container"> <input type="text" placeholder="Search"> <ul></ul> </div> <ol class="lnb-tab"> <li id="api-tab"> <a href="#"><h4>API</h4></a> </li> <li id="examples-tab"> <a href="#"><h4>Examples</h4></a> </li> </ol> <div class="lnb-examples hidden"><h3>Examples</h3><ul><li><a href="tutorial-Using Markdown with ydr_HTMLencode.html">Using Markdown with ydr_HTMLencode</a><button type="button" class="hidden toggle-subnav btn btn-link"> <span class="glyphicon glyphicon-plus"></span></button><div class="hidden" id="Using Markdown with ydr_HTMLencode_sub"></div></li><li><a href="tutorial-Using Object Prototype extensions.html">Using Object Prototype extensions</a><button type="button" class="hidden toggle-subnav btn btn-link"> <span class="glyphicon glyphicon-plus"></span></button><div class="hidden" id="Using Object Prototype extensions_sub"></div></li></ul></div><div class="lnb-api hidden"><h3>Modules</h3><ul><li><a href="module-@wider_utils_proto.html">@wider/utils_proto</a><button type="button" class="hidden toggle-subnav btn btn-link"> <span class="glyphicon glyphicon-plus"></span></button><div class="hidden" id="module:@wider/utils_proto_sub"><div class="member-type">Methods</div><ul class="inner"><li><a href="module-@wider_utils_proto.html#~init">init</a></li></ul></div></li><li><a href="module-@wider_utils_proto_proto_array.html">@wider/utils_proto/proto_array</a><button type="button" class="hidden toggle-subnav btn btn-link"> <span class="glyphicon glyphicon-plus"></span></button><div class="hidden" id="module:@wider/utils_proto/proto_array_sub"><div class="member-type">Methods</div><ul class="inner"><li><a href="module-@wider_utils_proto_proto_array.html#~keySort()">keySort()</a></li><li><a href="module-@wider_utils_proto_proto_array.html#~numericSortAsc()">numericSortAsc()</a></li><li><a href="module-@wider_utils_proto_proto_array.html#~permute()">permute()</a></li><li><a href="module-@wider_utils_proto_proto_array.html#~plainSortAsc()">plainSortAsc()</a></li><li><a href="module-@wider_utils_proto_proto_array.html#~plainSortDesc()">plainSortDesc()</a></li><li><a href="module-@wider_utils_proto_proto_array.html#~pushUnique()">pushUnique()</a></li></ul></div></li><li><a href="module-@wider_utils_proto_proto_array_test.html">@wider/utils_proto/proto_array/test</a><button type="button" class="hidden toggle-subnav btn btn-link"> <span class="glyphicon glyphicon-plus"></span></button><div class="hidden" id="module:@wider/utils_proto/proto_array/test_sub"></div></li><li><a href="module-@wider_utils_proto_proto_date.html">@wider/utils_proto/proto_date</a><button type="button" class="hidden toggle-subnav btn btn-link"> <span class="glyphicon glyphicon-plus"></span></button><div class="hidden" id="module:@wider/utils_proto/proto_date_sub"><div class="member-type">Methods</div><ul class="inner"><li><a href="module-@wider_utils_proto_proto_date.html#~toISOString">toISOString</a></li></ul></div></li><li><a href="module-@wider_utils_proto_proto_date_test.html">@wider/utils_proto/proto_date/test</a><button type="button" class="hidden toggle-subnav btn btn-link"> <span class="glyphicon glyphicon-plus"></span></button><div class="hidden" id="module:@wider/utils_proto/proto_date/test_sub"></div></li><li><a href="module-@wider_utils_proto_proto_function.html">@wider/utils_proto/proto_function</a><button type="button" class="hidden toggle-subnav btn btn-link"> <span class="glyphicon glyphicon-plus"></span></button><div class="hidden" id="module:@wider/utils_proto/proto_function_sub"><div class="member-type">Methods</div><ul class="inner"><li><a href="module-@wider_utils_proto_proto_function.html#~describe()">describe()</a></li></ul></div></li><li><a href="module-@wider_utils_proto_proto_function_test.html">@wider/utils_proto/proto_function/test</a><button type="button" class="hidden toggle-subnav btn btn-link"> <span class="glyphicon glyphicon-plus"></span></button><div class="hidden" id="module:@wider/utils_proto/proto_function/test_sub"></div></li><li><a href="module-@wider_utils_proto_proto_number.html">@wider/utils_proto/proto_number</a><button type="button" class="hidden toggle-subnav btn btn-link"> <span class="glyphicon glyphicon-plus"></span></button><div class="hidden" id="module:@wider/utils_proto/proto_number_sub"><div class="member-type">Methods</div><ul class="inner"><li><a href="module-@wider_utils_proto_proto_number.html#~bitsUpTo()">bitsUpTo()</a></li><li><a href="module-@wider_utils_proto_proto_number.html#~two()">two()</a></li></ul></div></li><li><a href="module-@wider_utils_proto_proto_number_test.html">@wider/utils_proto/proto_number/test</a><button type="button" class="hidden toggle-subnav btn btn-link"> <span class="glyphicon glyphicon-plus"></span></button><div class="hidden" id="module:@wider/utils_proto/proto_number/test_sub"></div></li><li><a href="module-@wider_utils_proto_proto_object.html">@wider/utils_proto/proto_object</a><button type="button" class="hidden toggle-subnav btn btn-link"> <span class="glyphicon glyphicon-plus"></span></button><div class="hidden" id="module:@wider/utils_proto/proto_object_sub"><div class="member-type">Methods</div><ul class="inner"><li><a href="module-@wider_utils_proto_proto_object.html#~assign()">assign()</a></li><li><a href="module-@wider_utils_proto_proto_object.html#~deepMerge()">deepMerge()</a></li></ul></div></li><li><a href="module-@wider_utils_proto_proto_object_test.html">@wider/utils_proto/proto_object/test</a><button type="button" class="hidden toggle-subnav btn btn-link"> <span class="glyphicon glyphicon-plus"></span></button><div class="hidden" id="module:@wider/utils_proto/proto_object/test_sub"></div></li><li><a href="module-@wider_utils_proto_proto_string.html">@wider/utils_proto/proto_string</a><button type="button" class="hidden toggle-subnav btn btn-link"> <span class="glyphicon glyphicon-plus"></span></button><div class="hidden" id="module:@wider/utils_proto/proto_string_sub"><div class="member-type">Methods</div><ul class="inner"><li><a href="module-@wider_utils_proto_proto_string.html#~asHTML()">asHTML()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~attrEncode()">attrEncode()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~camelIse()">camelIse()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~checkSum()">checkSum()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~checkSumValidate()">checkSumValidate()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~contextParse()">contextParse()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~deCamelIse()">deCamelIse()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~ellipses()">ellipses()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~escape()">escape()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~extendedCharCodeFixer()">extendedCharCodeFixer()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~formStrToXMLattr()">formStrToXMLattr()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~fuzzyValue()">fuzzyValue()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~HTMLencode()">HTMLencode()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~HTMLencodeInit">HTMLencodeInit</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~isHTML()">isHTML()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~isHTMLerror()">isHTMLerror()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~proper()">proper()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~regExpEncode()">regExpEncode()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~replaceSafe()">replaceSafe()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~searchEncode()">searchEncode()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~selectorEncode()">selectorEncode()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~simpleHTMLtoPlain()">simpleHTMLtoPlain()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~standardMarkups()">standardMarkups()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~stringEncode()">stringEncode()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~textSignature()">textSignature ()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~trim()">trim()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~unescape()">unescape()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~unHTMLencode()">unHTMLencode()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~wrapAsError()">wrapAsError()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~wrapAsOK()">wrapAsOK()</a></li><li><a href="module-@wider_utils_proto_proto_string.html#~XMLverify()">XMLverify()</a></li></ul></div></li><li><a href="module-@wider_utils_proto_proto_string_contextParse.html">@wider/utils_proto/proto_string/contextParse</a><button type="button" class="hidden toggle-subnav btn btn-link"> <span class="glyphicon glyphicon-plus"></span></button><div class="hidden" id="module:@wider/utils_proto/proto_string/contextParse_sub"><div class="member-type">Typedef</div><ul class="inner"><li><a href="module-@wider_utils_proto_proto_string_contextParse.html#~rowId">rowId</a></li><li><a href="module-@wider_utils_proto_proto_string_contextParse.html#~wider_context">wider_context</a></li></ul></div></li><li><a href="module-@wider_utils_proto_proto_string_test.html">@wider/utils_proto/proto_string/test</a><button type="button" class="hidden toggle-subnav btn btn-link"> <span class="glyphicon glyphicon-plus"></span></button><div class="hidden" id="module:@wider/utils_proto/proto_string/test_sub"></div></li></ul></div><div class="lnb-api hidden"><h3>Classes</h3><ul><li><a href="module-@wider_utils_proto_proto_string_contextParse-ContextParse.html">ContextParse</a><button type="button" class="hidden toggle-subnav btn btn-link"> <span class="glyphicon glyphicon-plus"></span></button><div class="hidden" id="module:@wider/utils_proto/proto_string/contextParse~ContextParse_sub"><div class="member-type">Methods</div><ul class="inner"><li><a href="module-@wider_utils_proto_proto_string_contextParse-ContextParse.html#toString">toString</a></li></ul></div></li></ul></div> </nav> <div id="resizer"></div> <div class="main" id="main"> <section> <article> <pre class="prettyprint source linenums"><code>'use strict'; /** * Additional methods for the javascript **Function** object * @module @wider/utils_proto/proto_object * * @copyright Copyright (C) 1985..2021 Martin Baker. http://y-d-r.co.uk * @author Martin W Baker * @license ISC Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ const $moduleName = "@wider/utils_proto/proto_object"; const objectPrototype = {}; /** * Perform a deep merge of the current object with another object revising the current object * * A scan is made of all the [enumerable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/propertyIsEnumerable) [own properties](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty) of the given ** mergeItems ** and the action is chosen as below for each result found * * * if the result is ***undefined*** the value is deleted from the current object if it already exists * * * if the result is another native {Object} it will also have a `wider_deepMerge()` method - this is called recursively to merge into the matching keyName of the current item (creating the keyName's empty object first if one does not yet exist) * * * if the result is any other object the object itself is placed as this current value * * * for any other value, eg string or function, the keyName is set to the value, retaining the defined properties of the new value (eg immutability, readonly, etc) * * Important, child objects being deepMerged are never linked as the entire object - only enumerable members are processed. This means that the **mergeItems** object will never reflect changes in the current item and changes in the current item will not be reflected into the **mergeItems** * * This does not perform the same impact as the package "npm install deepMerge" - the main differences are that object.wider_deepMerge(): * * * is this faster or significantly faster * * * updates your original object in situ so that any prior references to objects in it now refer to same object with possibly amended properties * * * has control as to whether matching keyNames defer or overwrite * * * has control over error handling * * * has different management of merging arrays * @function deepMerge() * @param {Object} mergeItems new items to merge into the current object. * @param {object} [settings] settings that impact the behaviour - to use more than one value on the same key use a space separated list * * `{ array : "push"}` if the new and the old values are arrays the new values are pushed into the array. As this always creates new elements in the array, this overrides the action of **mode** for arrays * * `{ array : "pushUnique"}` as for ***push*** except that duplicate values are discarded * * `{ array : "unshift"}` if the new and the old values are arrays the new values are unshifted into the array. This overrides the action of **mode** for arrays * * `{ array : "unshiftUnique"}` as for ***push*** except that duplicate values are discarded * * `{ error : fn(Error) } if an error occurs it is sent to the function (eg ***console.error***) and not, as per default, thrown. The value passes is the same error object that would have been thrown * * `{ mode : 'defer' } if a value appears in the **mergeItems** that is already in original object, the original object is not updated - the default is **overwrite*** * * '{ custom : {handler : fn(path,value), pattern : regExp]}` if the path to the item matches the regExp the callback is used to process the behaviour * @returns {Object} the current object - use of this return value is optional * @throws {Error} when any of the following occur * * if the **mergeItem** is not a javascript native {Object} * * if the value of a **mergeItem** keyName is write only * * if the value in the current object of keyName is immutable or readOnly AND is different from the value being supplied * * if you use a combination of settings that when used are incompatible * * If an error is thrown and not trapped by your error setting function, your initial object will have been left partially updated */ const methods = { "wider_deepMerge": { enumerable: false, value: function (mergeItems = {}, settings = {}, path = "") { const $functionName = "object.prototype.wider_deepMerge"; if (!mergeItems.wider_deepMerge) throw new Error($functionName + " - mergeItems must be a constructed from the javascript `Object` object"); for (const key in mergeItems) { if (Object.hasOwnProperty.call(mergeItems, key)) { const valuePath = path + "/" + key; const value = mergeItems[key]; //TODO if the given getProperties obedience try { if (value === undefined) delete this[key]; else if (settings.custom &amp;&amp; settings.custom.pattern.test(valuePath)) this[key] = settings.custom.handler(valuePath, value); else if (this[key] === undefined) this[key] = value; else if (this[key] === value || settings.mode === "defer" &amp;&amp; !settings.array ) { /* skip if already exists and we are in defer mode or is already the same object */ } // else if (Array.isArray(this[key])) { switch (settings.array) { case "push": if (Array.isArray(value)) value.forEach(element => { this[key].push(element); }); else this[key].push(value); break; case "unshift": if (Array.isArray(value)) this[key].unshift(...value); else this[key].unshift(value); break; case "pushUnique": case "unshiftUnique": if (Array.isArray(value)) /* jshint -W083 */ value.forEach(element => { this[key].wider_pushUnique(element, settings.array === "unshiftUnique"); }); /* jshint +W083 */ else this[key].wider_pushUnique(value, settings.array === "unshiftUnique"); break; case undefined: case null: Object.defineProperty(this, key, Object.getOwnPropertyDescriptor(mergeItems, key)); break; default: throw new Error("settings.array='" + settings.array + "' is not a recognised array setting"); } } // else if (typeof value === "object") { if (settings.mode === "overwrite" || this[key] === undefined) { if (value.wider_deepMerge) { if (this[key] == null) this[key] = {}; if (!this[key].wider_deepMerge) this[key] = { "&lt;anonymous>": this[key] }; else if (value.constructor === Object) this[key].wider_deepMerge(value, settings, path); else this[key] = value; } else Object.defineProperty(this, key, Object.getOwnPropertyDescriptor(mergeItems, key)); } else if (value.constructor === Object) { this[key].wider_deepMerge(value, settings, path); } } // everything else just gets direct assigned it that were possible else if (settings.mode === "overwrite") Object.defineProperty(this, key, Object.getOwnPropertyDescriptor(mergeItems, key)); // above is clever version of this[key] = value; that preserves the properties } // catch (err) { err.path = valuePath; err.code = objectPrototype.wider_deepMerge.ERR_CANNOT_UPDATE_AT_PATH; if (settings.error) settings.error(err); else throw err; } } } return this; } }, /** * perform an assign of all the [enumerable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/propertyIsEnumerable) [own properties](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty) of the given **object** * * Unlike `Object.assign()` this will copy all the defined properties of the submitted items - so eg if your submitted object is writeOnly, it will still be copied leaving a write only result. You should not include the `this`object in the arguments list. * * Beware that when assigning functions, getters and setters, that they still remain those functions in their original objects but being called with `this` being the current object into which they are now also inserted. * * If a key in the current object is updated, then any defined properties you have already set are also overwritten. * @function assign() * @param {...objects} objects any number of objects whose members are to be assigned to this current object * @returns {Object} being the same as this current object * @throws {Error} if a key in this current object cannot be updated because the key is already in use and is not updatable */ wider_assign: { enumerable: false, value: function (...objects) { for (let index = 0; index &lt; objects.length; index++) { const object = objects[index]; for (const key in object) { if (Object.hasOwnProperty.call(object, key)) { Object.defineProperty(this, key, Object.getOwnPropertyDescriptor(object, key)); } } } return this; } } }; /** * @private * @param {object} target - this will normally be the javascript Function object - but if you dont want to change that object then provide your own equivalent */ function assignObject(target = Object) { /* set the prototype of the javascript Function object or if it already exists then extend it */ methods.wider_deepMerge.ERR_CANNOT_UPDATE_AT_PATH = assignObject.$moduleName + ":ERR_CANNOT_UPDATE_AT_PATH"; Object.defineProperties(target.prototype, methods); } assignObject.$moduleName = $moduleName; if (global.$wider) global.$wider.registry.register($moduleName, assignObject, "protoObject", "utils"); export default assignObject;</code></pre> </article> </section> </div> <footer> <img class="logo" src="http://y-d-r.co.uk/favicon.ico" style="width: 50px"> <div class="footer-text">Copyright Dr. Martin W. Baker 1985 onwards - MIT License</div> </footer> <script>prettyPrint();</script> <script src="scripts/jquery.min.js"></script> <script src="scripts/tui-doc.js"></script> <script src="scripts/linenumber.js"></script> <script> var id = '_sub'.replace(/"/g, '_'); var selectedApi = document.getElementById(id); // do not use jquery selector var $selectedApi = $(selectedApi); $selectedApi.removeClass('hidden'); $selectedApi.parent().find('.glyphicon').removeClass('glyphicon-plus').addClass('glyphicon-minus'); showLnbApi(); </script> </body> </html>