UNPKG

ancient-funicular

Version:

Just async mounting, updating and unmounting hierarchical carriages.

392 lines (340 loc) 14.2 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>carriage.js - Documentation</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="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css"> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <input type="checkbox" id="nav-trigger" class="nav-trigger" /> <label for="nav-trigger" class="navicon-button x"> <div class="navicon"></div> </label> <label for="nav-trigger" class="overlay"></label> <nav> <li class="nav-link nav-home-link"><a href="index.html">Home</a></li><li class="nav-heading">Classes</li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="ancient-funicular.Carriage.html">Carriage</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ancient-funicular.Carriage.html#disable">disable</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ancient-funicular.Carriage.html#enable">enable</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ancient-funicular.Carriage.html#mount">mount</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ancient-funicular.Carriage.html#mountChild">mountChild</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ancient-funicular.Carriage.html#remount">remount</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ancient-funicular.Carriage.html#shouldRemount">shouldRemount</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ancient-funicular.Carriage.html#tieChild">tieChild</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ancient-funicular.Carriage.html#unique">unique</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ancient-funicular.Carriage.html#unmount">unmount</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ancient-funicular.Carriage.html#unmountChilds">unmountChilds</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ancient-funicular.Carriage.html#untieChild">untieChild</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="ancient-funicular.Funicular.html">Funicular</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ancient-funicular.Funicular.html#mount">mount</a></span></li><li class="nav-heading">Modules</li><li class="nav-heading"><span class="nav-item-type type-module">M</span><span class="nav-item-name"><a href="module-ancient-funicular.html">ancient-funicular</a></span></li><li class="nav-heading">Interfaces</li><li class="nav-heading"><span class="nav-item-type type-interface">I</span><span class="nav-item-name"><a href="module-ancient-funicular-CarriageListsByNames.html">CarriageListsByNames</a></span></li><li class="nav-heading"><span class="nav-item-type type-interface">I</span><span class="nav-item-name"><a href="module-ancient-funicular-CarriagesByIds.html">CarriagesByIds</a></span></li><li class="nav-heading"><span class="nav-item-type type-interface">I</span><span class="nav-item-name"><a href="module-ancient-funicular-CarriagesByNames.html">CarriagesByNames</a></span></li> </nav> <div id="main"> <h1 class="page-title">carriage.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>import each from 'async/each'; /** * Universal basic carriage for funicular. * @memberof ancient-funicular */ class Carriage { /** * @param {Funicular} funicular - Link to instance of {@link Funicular}, used as namespace of carriages for this carriage. * @param {String} name - Unique name of this carriage. * @param data - Any outer system data needed for mounting one carriage. */ constructor(funicular, name, data) { /** * Link to instance of {@link Funicular}, used as namespace of carriages for this carriage. * @type {Funicular} * @memberof Carriage * @protected */ this.funicular = funicular; /** * Unique id of carriages in funicular instance. * @type {Number} * @memberof Carriage * @protected */ this.id = funicular.lastCarriageId++; /** * Unique name of this carriage. * @type {String} * @memberof Carriage * @protected */ this.name = name; /** * Any outer system data needed for mounting one carriage. * @memberof Carriage * @protected */ this.data = data; /** * String stage of carriage. Used for place carriage in execution space. * @type {String} * @memberof Carriage * @protected */ this.stage = 'constructed'; /** * Object with childs carriages by names. * @type {CarriagesByNames} * @memberof Carriage * @protected */ this.childs = {}; /** * Object with parents carriages by names. * @type {CarriagesByIds} * @memberof Carriage * @protected */ this.parents = {}; /** * Callbacks after mount. * @type {Carriage~mountCallback[]} * @memberof Carriage * @private */ this.mountedCallbacks = []; /** * @callback Carriage~mountedCallback * @param [error] * @param {Carriage} carriage */ /** * Callbacks after remount. * @type {Carriage~remountedCallbacks[]} * @memberof Carriage * @private */ this.remountedCallbacks = []; /** * @callback Carriage~remountedCallbacks * @param [unmountError] * @param {Carriage} oldCarriage * @param [mountError] * @param {Carriage} [newCarriage] */ /** * Callbacks after unmount. * @type {Carriage~unmountCallback[]} * @memberof Carriage * @private */ this.unmountedCallbacks = []; /** * @callback Carriage~unmountedCallback * @param [error] * @param {Carriage} carriage */ /** * Last error. It is recorded if an error was received while mounting or unmounting. * Can be recorded anywhere, it is worth considering that it can be and check it before important actions. * @memberof Carriage * @protected */ this.error; } /** * Get unique state. If sended argument `state` returns boolean. * @param {Boolean} [state] - if sended, set this carriage as unique primary of this name. * @returns {Boolean} */ unique(state) { if (this.name) { if (typeof(state) == 'boolean') { if (state) { this.funicular.namedCarriages[this.name][0] = this; } else { delete this.funicular.namedCarriages[this.name][0]; } } return this.funicular.namedCarriages[this.name][0] == this; } else return false; } /** * Tie one child with this carriage parent. * @param {Carriage} child */ tieChild(child) { this.childs[child.name] = child; child.parents[this.id] = this; } /** * Untie one child with this carriage parent. * @param {Carriage} child */ untieChild(child) { delete this.childs[child.name]; delete child.parents[this.id]; } /** * Based on data, mount this carriage. * Use {@link Carriage.enable} for useful functionality. * Calls all functions from {@link Carriage.mountedCallbacks}, if this carriage did unmount. */ mount() { this.enable((error) => { this.error = error; this.stage = error?'error':'mounted'; if (!error) { if (typeof(this.name) == 'string') { this.funicular.namedCarriages[this.name] = this.funicular.namedCarriages[this.name] || {}; this.funicular.namedCarriages[this.name][this.id] = this; this.unique(true); } else { this.funicular.unnamedCarriages[this.id] = this; } } for (var c in this.mountedCallbacks) { this.mountedCallbacks[c].call(this, error, this); } }); } /** * Mount carriage as child for this carriage. * @param {String} name * @param data * @param {Carriage~mountCallback} [callback] */ mountChild(name, data, callback) { this.funicular.mount( name, data, (error, child) => { if (this.stage != 'unmounted') { this.tieChild(child); callback(); } }, (unmountError, oldChild, mountError, newChild) => { this.untieChild(oldChild); this.tieChild(newChild); }, (error, child) => { this.untieChild(child); } ); } /** * You must override it with useful functionality. * Can gets and mount childs carriages into {@link Carriage.childs}. * It method must added, enable, run and write all that was forgeted, disabled, stoped and erased at {@link Carriage.disable}. * It must call callback! Otherwise, the demounting chain may break. * @param {Carriage~enableCallback} callback */ enable(callback) { callback(); } /** * @callback Carriage~enableCallback * @param error */ /** * Remount this carriage. * @todo * If {@link Carriage.invalid} is `true`, mount new carriage based on this name and data and unmount this carriage. */ remount() { var tempMountedCallback = (mountError, carriage) => { carriage.mountedCallbacks.splice(carriage.mountedCallbacks.indexOf(tempMountedCallback), 1); carriage.mountedCallbacks = this.mountedCallbacks; this.mountedCallbacks = []; carriage.remountedCallbacks = this.remountedCallbacks; carriage.unmountedCallbacks = this.unmountedCallbacks; this.unmountedCallbacks = []; this.unmount((unmountError) => { for (var c in this.remountedCallbacks) { this.remountedCallbacks[c].call(this, unmountError, this, mountError, carriage); } this.remountedCallbacks = []; for (var parent in this.parents) { this.parents[parent].childDidRemount(unmountError, this, mountError, carriage); } }); }; this.funicular.mount( this.name, this.data, tempMountedCallback, undefined, undefined, true ); } /** * Sort unmount this carriage with childs. * The carriages necessary for some other carriages will not be unmounted. * Calls all functions from {@link Carriage.unmountedCallbacks}, if this carriage did unmount. * Calls argument callback in any case, even if the unmount did not happen. * @param {Carriage~unmountCallback} [callback] */ unmount(callback) { for (var p in this.parents) { if (callback) callback(undefined, this); return; // If parents exists, umount cannot be done. } if (this.stage == 'mounted') { this.unmountChilds(); this.disable((error) => { this.error = error; this.stage = this.error?'error':'unmounted'; if (typeof(this.name) == 'string') { delete this.funicular.namedCarriages[this.name][this.id]; if (this.funicular.namedCarriages[this.name][0] == this) { delete this.funicular.namedCarriages[this.name][0]; }; } else { delete this.funicular.unnamedCarriages[this.id]; } for (var c in this.unmountedCallbacks) { this.unmountedCallbacks[c].call(this, error, this); } if (callback) callback(error, this); }); } else { if (callback) callback(undefined, this); } } /** * Cicle for sort unmount childs of this carriage. * Not asynchronously and with callback, because there is no sense in waiting for the end of the unmounting childs. * If you do not agree please describe the reason in the issues. */ unmountChilds() { for (var c in this.childs) { var child = this.childs[c]; this.untieChild(child); child.unmount(); } } /** * You must override it with useful functionality. * It method must forget, disable, stop and erase all that was added, enabled, runned and writed at {@link Carriage.enable}. * It must call callback! Otherwise, the demounting chain may break. * @param {Carriage~disableCallback} callback */ disable(callback) { callback(); } /** * @callback Carriage~disableCallback * @param error */ /** * You can override it with useful functionality. * Synchronously answers the question - is it necessary to remount this parent while remounting the child? * @param [unmountError] * @param {Carriage} oldCarriage * @param [mountError] * @param {Carriage} [newCarriage] */ shouldRemount(unmountError, olda, mountError, newa) { return false; } } export default Carriage;</code></pre> </article> </section> </div> <br class="clear"> <footer> Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Thu May 11 2017 11:27:05 GMT+0000 (UTC) using the Minami theme. </footer> <script>prettyPrint();</script> <script src="scripts/linenumber.js"></script> </body> </html>