ancient-funicular
Version:
Just async mounting, updating and unmounting hierarchical carriages.
392 lines (340 loc) • 14.2 kB
HTML
<!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>