UNPKG

derby

Version:

MVC framework making it easy to write realtime, collaborative applications that run in both Node.js and browsers.

244 lines (243 loc) 9.11 kB
Object.defineProperty(exports, "__esModule", { value: true }); exports.Context = exports.ContextMeta = void 0; function noop() { } /** * Properties and methods which are globally inherited for the entire page */ var ContextMeta = /** @class */ (function () { function ContextMeta() { this.addBinding = noop; this.removeBinding = noop; this.removeNode = noop; this.addItemContext = noop; this.removeItemContext = noop; this.views = null; this.idNamespace = ''; this.idCount = 0; this.pending = []; this.pauseCount = 0; } return ContextMeta; }()); exports.ContextMeta = ContextMeta; var Context = /** @class */ (function () { function Context(meta, controller, parent, unbound, expression) { // Required properties // // Properties which are globally inherited for the entire page this.meta = meta; // The page or component. Must have a `model` property with a `data` property this.controller = controller; // Optional properties // // Containing context this.parent = parent; // Boolean set to true when bindings should be ignored this.unbound = unbound; // The expression for a block this.expression = expression; // Alias name for the given expression this.alias = expression && expression.meta && expression.meta.as; // Alias name for the index or iterated key this.keyAlias = expression && expression.meta && expression.meta.keyAs; // For Context::eachChild // The context of the each at render time this.item = null; // For Context::viewChild // Reference to the current view this.view = null; // Attribute values passed to the view instance this.attributes = null; // MarkupHooks to be called after insert into DOM of component this.hooks = null; // MarkupHooks to be called immediately before init of component this.initHooks = null; // For Context::closureChild // Reference to another context established at render time by ContextClosure this.closure = null; // Used in EventModel this._id = null; this._eventModels = null; } /** * Generate unique Id * * @returns namespaced Id */ Context.prototype.id = function () { var count = ++this.meta.idCount; return this.meta.idNamespace + '_' + count.toString(36); }; Context.prototype.addBinding = function (binding) { // Don't add bindings that wrap list items. Only their outer range is needed if (binding.itemFor) return; var expression = binding.template.expression; // Don't rerender in unbound sections if (expression ? expression.isUnbound(this) : this.unbound) return; // Don't rerender to changes in a with expression if (expression && expression.meta && expression.meta.blockType === 'with') return; this.meta.addBinding(binding); }; Context.prototype.removeBinding = function (binding) { this.meta.removeBinding(binding); }; Context.prototype.removeNode = function (node) { var bindItemStart = node.$bindItemStart; if (bindItemStart) { this.meta.removeItemContext(bindItemStart.context); } var component = node.$component; if (component) { node.$component = null; if (!component.singleton) { component.destroy(); } } var destroyListeners = node.$destroyListeners; if (destroyListeners) { node.$destroyListeners = null; for (var i = 0, len = destroyListeners.length; i < len; i++) { destroyListeners[i](); } } }; Context.prototype.child = function (expression) { // Set or inherit the binding mode var blockType = expression.meta && expression.meta.blockType; var unbound = (blockType === 'unbound') ? true : (blockType === 'bound') ? false : this.unbound; return new Context(this.meta, this.controller, this, unbound, expression); }; Context.prototype.componentChild = function (component) { return new Context(this.meta, component, this, this.unbound); }; /** * Make a context for an item in an each block * * @param expression * @param item * @returns new Context */ Context.prototype.eachChild = function (expression, item) { var context = new Context(this.meta, this.controller, this, this.unbound, expression); context.item = item; this.meta.addItemContext(context); return context; }; Context.prototype.viewChild = function (view, attributes, hooks, initHooks) { var context = new Context(this.meta, this.controller, this, this.unbound); context.view = view; context.attributes = attributes; context.hooks = hooks; context.initHooks = initHooks; return context; }; Context.prototype.closureChild = function (closure) { var context = new Context(this.meta, this.controller, this, this.unbound); context.closure = closure; return context; }; Context.prototype.forRelative = function (expression) { // eslint-disable-next-line @typescript-eslint/no-this-alias var context = this; while (context && context.expression === expression || context.view) { context = context.parent; } return context; }; // Returns the closest context which defined the named alias Context.prototype.forAlias = function (alias) { // eslint-disable-next-line @typescript-eslint/no-this-alias var context = this; while (context) { if (context.alias === alias || context.keyAlias === alias) return context; context = context.parent; } }; // Returns the closest containing context for a view attribute name or nothing Context.prototype.forAttribute = function (attribute) { // eslint-disable-next-line @typescript-eslint/no-this-alias var context = this; while (context) { // Find the closest context associated with a view if (context.view) { var attributes = context.attributes; if (!attributes) return; if (Object.prototype.hasOwnProperty.call(attributes, attribute)) return context; // If the attribute isn't found, but the attributes inherit, continue // looking in the next closest view context if (!attributes.inherit && !attributes.extend) return; } context = context.parent; } }; Context.prototype.forViewParent = function () { // eslint-disable-next-line @typescript-eslint/no-this-alias var context = this; while (context) { // When a context with a `closure` property is encountered, skip to its // parent context rather than returning the nearest view's. This reference // is created by wrapping a template in a ContextClosure template if (context.closure) return context.closure.parent; // Find the closest view and return the containing context if (context.view) return context.parent; context = context.parent; } }; /** * Gets the current `context` view or closest `context.parent` view * * @returns view */ Context.prototype.getView = function () { // eslint-disable-next-line @typescript-eslint/no-this-alias var context = this; while (context) { // Find the closest view if (context.view) return context.view; context = context.parent; } }; // Returns the `this` value for a context Context.prototype.get = function () { var value = (this.expression) ? this.expression.get(this) : this.controller.model.data; if (this.item != null) { return value && value[this.item]; } return value; }; Context.prototype.pause = function () { this.meta.pauseCount++; }; Context.prototype.unpause = function () { if (--this.meta.pauseCount) return; this.flush(); }; Context.prototype.flush = function () { var pending = this.meta.pending; var len = pending.length; if (!len) return; this.meta.pending = []; for (var i = 0; i < len; i++) { pending[i](); } }; Context.prototype.queue = function (cb) { this.meta.pending.push(cb); }; return Context; }()); exports.Context = Context;