ancient-funicular
Version:
Abstract hierarchical life cycle of the mount.
194 lines • 8.24 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const _ = require("lodash");
const node_1 = require("ancient-mixins/lib/node");
const funiculars_manager_1 = require("./funiculars-manager");
var EFunicularState;
(function (EFunicularState) {
EFunicularState[EFunicularState["Constructed"] = 0] = "Constructed";
EFunicularState[EFunicularState["Mounting"] = 1] = "Mounting";
EFunicularState[EFunicularState["Mounted"] = 2] = "Mounted";
EFunicularState[EFunicularState["Remounting"] = 3] = "Remounting";
EFunicularState[EFunicularState["Unmounting"] = 4] = "Unmounting";
EFunicularState[EFunicularState["Unmounted"] = 5] = "Unmounted";
})(EFunicularState || (EFunicularState = {}));
exports.EFunicularState = EFunicularState;
function mixin(superClass, clone) {
return class FunicularMixed extends superClass {
constructor() {
super(...arguments);
this.clone = clone;
this.state = EFunicularState.Constructed;
this.childs = new funiculars_manager_1.FunicularsManager();
this.parents = new funiculars_manager_1.FunicularsManager();
this.needRemount = false;
this.needUnmount = false;
}
mount(cursor) {
return __awaiter(this, void 0, void 0, function* () {
if (this.state !== EFunicularState.Constructed) {
throw new Error(`Funicular ${this.id} is already mounted.`);
}
this.cursor = cursor;
this.state = EFunicularState.Mounting;
this.emit('mounting', { funicular: this });
yield this.register();
yield this.cursorFilling();
yield this.childsMounting();
yield this.start();
this.watchChildsEvents();
this.addParentToChilds();
this.state = EFunicularState.Mounted;
this.emit('mounted', { funicular: this });
if (this.needUnmount)
yield this.unmount();
else if (this.needRemount)
yield this.remount();
});
}
remount() {
return __awaiter(this, void 0, void 0, function* () {
if (this.state === EFunicularState.Mounted) {
this.state = EFunicularState.Remounting;
this.emit('remounting', { funicular: this });
yield this.unregister();
yield this.cloneAndMount();
this.emit('remounted', { funicular: this });
yield this.unmount();
}
else
this.needRemount = true;
});
}
unmount() {
return __awaiter(this, void 0, void 0, function* () {
if (this.state === EFunicularState.Mounted || this.state === EFunicularState.Remounting) {
this.state = EFunicularState.Unmounting;
this.emit('unmounting', { funicular: this });
yield this.stop();
yield this.childsUnmounting();
this.unwatchChildsEvents();
yield this.unregister();
this.state = EFunicularState.Unmounted;
this.emit('unmounted', { funicular: this });
yield this.destroy();
}
else
this.needUnmount = true;
});
}
register() {
throw new Error('Method register must defined in this class!');
}
unregister() {
throw new Error('Method unregister must defined in this class!');
}
cursorFilling() {
this.emit('cursorFilling', { funicular: this });
return new Promise((resolve) => {
if (_.isUndefined(this.cursor.data)) {
this.cursor.once('changed', () => __awaiter(this, void 0, void 0, function* () {
yield this.cursorFilling();
resolve();
}));
}
else {
this.cursor.once('changed', () => this.remount());
this.emit('cursorFilled', { funicular: this });
resolve();
}
});
}
childsMounting() {
return __awaiter(this, void 0, void 0, function* () {
this.emit('childsMounting', { funicular: this });
yield this.requestChilds();
this.emit('childsMounted', { funicular: this });
});
}
childsUnmounting() {
return __awaiter(this, void 0, void 0, function* () {
this.emit('childsUnmounting', { funicular: this });
yield this.abandonChilds();
this.emit('childsUnmounted', { funicular: this });
});
}
requestChilds() {
throw new Error('Method requestChilds must defined in this class!');
}
abandonChilds() {
throw new Error('Method abandonChilds must defined in this class!');
}
start() {
return __awaiter(this, void 0, void 0, function* () {
this.emit('starting', { funicular: this });
yield this.starting();
this.emit('started', { funicular: this });
});
}
stop() {
return __awaiter(this, void 0, void 0, function* () {
this.emit('stopping', { funicular: this });
yield this.stopping();
this.emit('stopped', { funicular: this });
});
}
starting() {
throw new Error('Method starting must defined in this class!');
}
stopping() {
throw new Error('Method stopping must defined in this class!');
}
watchChildsEvents() {
this.removedListener = ({ node }) => node.remounted || this.childDestroyed(node);
this.remountedListener = ({ funicular }) => this.childRemounted(funicular);
this.childs.on('removed', this.removedListener);
this.childs.list.on('remounted', this.remountedListener);
}
unwatchChildsEvents() {
this.childs.off('removed', this.removedListener);
this.childs.list.off('remounted', this.remountedListener);
}
childDestroyed(child) {
this.remount();
}
childRemounted(child) {
this.remount();
}
addParentToChilds() {
_.each(this.childs.list.nodes, (child) => child.parents.add(this));
}
cloneAndMount() {
return new Promise((resolve) => {
const clone = this.clone(this);
clone.once('mounted', () => {
this.remounted = clone;
resolve();
});
clone.mount(this.cursor);
});
}
destroy() {
if (this.state !== EFunicularState.Unmounted) {
throw new Error(`Not unmounted funicular ${this.id} cant be destroyed.`);
}
return super.destroy();
}
};
}
exports.default = mixin;
exports.mixin = mixin;
const MixedFunicular = mixin(node_1.Node, i => new Funicular(i.id));
exports.MixedFunicular = MixedFunicular;
class Funicular extends MixedFunicular {
}
exports.Funicular = Funicular;
//# sourceMappingURL=funicular.js.map