UNPKG

aurelia-templating-resources

Version:

A standard set of behaviors, converters and other resources for use with the Aurelia templating library.

1,241 lines (1,218 loc) 78.6 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var aureliaDependencyInjection = require('aurelia-dependency-injection'); var aureliaPal = require('aurelia-pal'); var aureliaTaskQueue = require('aurelia-task-queue'); var aureliaTemplating = require('aurelia-templating'); var aureliaBinding = require('aurelia-binding'); var aureliaLoader = require('aurelia-loader'); var aureliaPath = require('aurelia-path'); var aureliaMetadata = require('aurelia-metadata'); var aureliaLogging = require('aurelia-logging'); /*! ***************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } function __decorate(decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; } var ActivationStrategy; (function (ActivationStrategy) { ActivationStrategy["InvokeLifecycle"] = "invoke-lifecycle"; ActivationStrategy["Replace"] = "replace"; })(ActivationStrategy || (ActivationStrategy = {})); var Compose = (function () { function Compose(element, container, compositionEngine, viewSlot, viewResources, taskQueue) { this.activationStrategy = ActivationStrategy.InvokeLifecycle; this.element = element; this.container = container; this.compositionEngine = compositionEngine; this.viewSlot = viewSlot; this.viewResources = viewResources; this.taskQueue = taskQueue; this.currentController = null; this.currentViewModel = null; this.changes = Object.create(null); } Compose.inject = function () { return [aureliaPal.DOM.Element, aureliaDependencyInjection.Container, aureliaTemplating.CompositionEngine, aureliaTemplating.ViewSlot, aureliaTemplating.ViewResources, aureliaTaskQueue.TaskQueue]; }; Compose.prototype.created = function (owningView) { this.owningView = owningView; }; Compose.prototype.bind = function (bindingContext, overrideContext) { this.bindingContext = bindingContext; this.overrideContext = overrideContext; var changes = this.changes; changes.view = this.view; changes.viewModel = this.viewModel; changes.model = this.model; if (!this.pendingTask) { processChanges(this); } }; Compose.prototype.unbind = function () { this.changes = Object.create(null); this.bindingContext = null; this.overrideContext = null; var returnToCache = true; var skipAnimation = true; this.viewSlot.removeAll(returnToCache, skipAnimation); }; Compose.prototype.modelChanged = function (newValue, oldValue) { this.changes.model = newValue; requestUpdate(this); }; Compose.prototype.viewChanged = function (newValue, oldValue) { this.changes.view = newValue; requestUpdate(this); }; Compose.prototype.viewModelChanged = function (newValue, oldValue) { this.changes.viewModel = newValue; requestUpdate(this); }; __decorate([ aureliaTemplating.bindable ], Compose.prototype, "model", void 0); __decorate([ aureliaTemplating.bindable ], Compose.prototype, "view", void 0); __decorate([ aureliaTemplating.bindable ], Compose.prototype, "viewModel", void 0); __decorate([ aureliaTemplating.bindable ], Compose.prototype, "activationStrategy", void 0); __decorate([ aureliaTemplating.bindable ], Compose.prototype, "swapOrder", void 0); Compose = __decorate([ aureliaTemplating.noView, aureliaTemplating.customElement('compose') ], Compose); return Compose; }()); function isEmpty(obj) { for (var _ in obj) { return false; } return true; } function tryActivateViewModel(vm, model) { if (vm && typeof vm.activate === 'function') { return Promise.resolve(vm.activate(model)); } } function createInstruction(composer, instruction) { return Object.assign(instruction, { bindingContext: composer.bindingContext, overrideContext: composer.overrideContext, owningView: composer.owningView, container: composer.container, viewSlot: composer.viewSlot, viewResources: composer.viewResources, currentController: composer.currentController, host: composer.element, swapOrder: composer.swapOrder }); } function processChanges(composer) { var changes = composer.changes; composer.changes = Object.create(null); if (needsReInitialization(composer, changes)) { var instruction = { view: composer.view, viewModel: composer.currentViewModel || composer.viewModel, model: composer.model }; instruction = Object.assign(instruction, changes); instruction = createInstruction(composer, instruction); composer.pendingTask = composer.compositionEngine.compose(instruction).then(function (controller) { composer.currentController = controller; composer.currentViewModel = controller ? controller.viewModel : null; }); } else { composer.pendingTask = tryActivateViewModel(composer.currentViewModel, changes.model); if (!composer.pendingTask) { return; } } composer.pendingTask = composer.pendingTask .then(function () { completeCompositionTask(composer); }, function (reason) { completeCompositionTask(composer); throw reason; }); } function completeCompositionTask(composer) { composer.pendingTask = null; if (!isEmpty(composer.changes)) { processChanges(composer); } } function requestUpdate(composer) { if (composer.pendingTask || composer.updateRequested) { return; } composer.updateRequested = true; composer.taskQueue.queueMicroTask(function () { composer.updateRequested = false; processChanges(composer); }); } function needsReInitialization(composer, changes) { var activationStrategy = composer.activationStrategy; var vm = composer.currentViewModel; if (vm && typeof vm.determineActivationStrategy === 'function') { activationStrategy = vm.determineActivationStrategy(); } return 'view' in changes || 'viewModel' in changes || activationStrategy === ActivationStrategy.Replace; } var IfCore = (function () { function IfCore(viewFactory, viewSlot) { this.viewFactory = viewFactory; this.viewSlot = viewSlot; this.view = null; this.bindingContext = null; this.overrideContext = null; this.showing = false; this.cache = true; } IfCore.prototype.bind = function (bindingContext, overrideContext) { this.bindingContext = bindingContext; this.overrideContext = overrideContext; }; IfCore.prototype.unbind = function () { if (this.view === null) { return; } this.view.unbind(); if (!this.viewFactory.isCaching) { return; } if (this.showing) { this.showing = false; this.viewSlot.remove(this.view, true, true); } else { this.view.returnToCache(); } this.view = null; }; IfCore.prototype._show = function () { if (this.showing) { if (!this.view.isBound) { this.view.bind(this.bindingContext, this.overrideContext); } return; } if (this.view === null) { this.view = this.viewFactory.create(); } if (!this.view.isBound) { this.view.bind(this.bindingContext, this.overrideContext); } this.showing = true; return this.viewSlot.add(this.view); }; IfCore.prototype._hide = function () { var _this = this; if (!this.showing) { return; } this.showing = false; var removed = this.viewSlot.remove(this.view); if (removed instanceof Promise) { return removed.then(function () { _this._unbindView(); }); } this._unbindView(); }; IfCore.prototype._unbindView = function () { var cache = this.cache === 'false' ? false : !!this.cache; this.view.unbind(); if (!cache) { this.view = null; } }; return IfCore; }()); var If = (function (_super) { __extends(If, _super); function If() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.cache = true; return _this; } If.prototype.bind = function (bindingContext, overrideContext) { _super.prototype.bind.call(this, bindingContext, overrideContext); if (this.condition) { this._show(); } else { this._hide(); } }; If.prototype.conditionChanged = function (newValue) { this._update(newValue); }; If.prototype._update = function (show) { var _this = this; if (this.animating) { return; } var promise; if (this.elseVm) { promise = show ? this._swap(this.elseVm, this) : this._swap(this, this.elseVm); } else { promise = show ? this._show() : this._hide(); } if (promise) { this.animating = true; promise.then(function () { _this.animating = false; if (_this.condition !== _this.showing) { _this._update(_this.condition); } }); } }; If.prototype._swap = function (remove, add) { switch (this.swapOrder) { case 'before': return Promise.resolve(add._show()).then(function () { return remove._hide(); }); case 'with': return Promise.all([remove._hide(), add._show()]); default: var promise = remove._hide(); return promise ? promise.then(function () { return add._show(); }) : add._show(); } }; __decorate([ aureliaTemplating.bindable({ primaryProperty: true }) ], If.prototype, "condition", void 0); __decorate([ aureliaTemplating.bindable ], If.prototype, "swapOrder", void 0); __decorate([ aureliaTemplating.bindable ], If.prototype, "cache", void 0); If = __decorate([ aureliaTemplating.customAttribute('if'), aureliaTemplating.templateController, aureliaDependencyInjection.inject(aureliaTemplating.BoundViewFactory, aureliaTemplating.ViewSlot) ], If); return If; }(IfCore)); var Else = (function (_super) { __extends(Else, _super); function Else(viewFactory, viewSlot) { var _this = _super.call(this, viewFactory, viewSlot) || this; _this._registerInIf(); return _this; } Else.prototype.bind = function (bindingContext, overrideContext) { _super.prototype.bind.call(this, bindingContext, overrideContext); if (this.ifVm.condition) { this._hide(); } else { this._show(); } }; Else.prototype._registerInIf = function () { var previous = this.viewSlot.anchor.previousSibling; while (previous && !previous.au) { previous = previous.previousSibling; } if (!previous || !previous.au.if) { throw new Error("Can't find matching If for Else custom attribute."); } this.ifVm = previous.au.if.viewModel; this.ifVm.elseVm = this; }; Else = __decorate([ aureliaTemplating.customAttribute('else'), aureliaTemplating.templateController, aureliaDependencyInjection.inject(aureliaTemplating.BoundViewFactory, aureliaTemplating.ViewSlot) ], Else); return Else; }(IfCore)); var With = (function () { function With(viewFactory, viewSlot) { this.viewFactory = viewFactory; this.viewSlot = viewSlot; this.parentOverrideContext = null; this.view = null; } With.prototype.bind = function (bindingContext, overrideContext) { this.parentOverrideContext = overrideContext; this.valueChanged(this.value); }; With.prototype.valueChanged = function (newValue) { var overrideContext = aureliaBinding.createOverrideContext(newValue, this.parentOverrideContext); var view = this.view; if (!view) { view = this.view = this.viewFactory.create(); view.bind(newValue, overrideContext); this.viewSlot.add(view); } else { view.bind(newValue, overrideContext); } }; With.prototype.unbind = function () { var view = this.view; this.parentOverrideContext = null; if (view) { view.unbind(); } }; With = __decorate([ aureliaTemplating.customAttribute('with'), aureliaTemplating.templateController, aureliaDependencyInjection.inject(aureliaTemplating.BoundViewFactory, aureliaTemplating.ViewSlot) ], With); return With; }()); var oneTime = aureliaBinding.bindingMode.oneTime; function updateOverrideContexts(views, startIndex) { var length = views.length; if (startIndex > 0) { startIndex = startIndex - 1; } for (; startIndex < length; ++startIndex) { updateOverrideContext(views[startIndex].overrideContext, startIndex, length); } } function createFullOverrideContext(repeat, data, index, length, key) { var bindingContext = {}; var overrideContext = aureliaBinding.createOverrideContext(bindingContext, repeat.scope.overrideContext); if (typeof key !== 'undefined') { bindingContext[repeat.key] = key; bindingContext[repeat.value] = data; } else { bindingContext[repeat.local] = data; } updateOverrideContext(overrideContext, index, length); return overrideContext; } function updateOverrideContext(overrideContext, index, length) { var first = (index === 0); var last = (index === length - 1); var even = index % 2 === 0; overrideContext.$index = index; overrideContext.$first = first; overrideContext.$last = last; overrideContext.$middle = !(first || last); overrideContext.$odd = !even; overrideContext.$even = even; } function getItemsSourceExpression(instruction, attrName) { return instruction.behaviorInstructions .filter(function (bi) { return bi.originalAttrName === attrName; })[0] .attributes .items .sourceExpression; } function unwrapExpression(expression) { var unwrapped = false; while (expression instanceof aureliaBinding.BindingBehavior) { expression = expression.expression; } while (expression instanceof aureliaBinding.ValueConverter) { expression = expression.expression; unwrapped = true; } return unwrapped ? expression : null; } function isOneTime(expression) { while (expression instanceof aureliaBinding.BindingBehavior) { if (expression.name === 'oneTime') { return true; } expression = expression.expression; } return false; } function updateOneTimeBinding(binding) { if (binding.call && binding.mode === oneTime) { binding.call(aureliaBinding.sourceContext); } else if (binding.updateOneTimeBindings) { binding.updateOneTimeBindings(); } } function indexOf(array, item, matcher, startIndex) { if (!matcher) { return array.indexOf(item); } var length = array.length; for (var index = startIndex || 0; index < length; index++) { if (matcher(array[index], item)) { return index; } } return -1; } var ArrayRepeatStrategy = (function () { function ArrayRepeatStrategy() { } ArrayRepeatStrategy.prototype.getCollectionObserver = function (observerLocator, items) { return observerLocator.getArrayObserver(items); }; ArrayRepeatStrategy.prototype.instanceChanged = function (repeat, items) { var _this = this; var $repeat = repeat; var itemsLength = items.length; if (!items || itemsLength === 0) { $repeat.removeAllViews(true, !$repeat.viewsRequireLifecycle); return; } var children = $repeat.views(); var viewsLength = children.length; if (viewsLength === 0) { this._standardProcessInstanceChanged($repeat, items); return; } if ($repeat.viewsRequireLifecycle) { var childrenSnapshot = children.slice(0); var itemNameInBindingContext = $repeat.local; var matcher_1 = $repeat.matcher(); var itemsPreviouslyInViews_1 = []; var viewsToRemove = []; for (var index = 0; index < viewsLength; index++) { var view = childrenSnapshot[index]; var oldItem = view.bindingContext[itemNameInBindingContext]; if (indexOf(items, oldItem, matcher_1) === -1) { viewsToRemove.push(view); } else { itemsPreviouslyInViews_1.push(oldItem); } } var updateViews = void 0; var removePromise = void 0; if (itemsPreviouslyInViews_1.length > 0) { removePromise = $repeat.removeViews(viewsToRemove, true, !$repeat.viewsRequireLifecycle); updateViews = function () { for (var index = 0; index < itemsLength; index++) { var item = items[index]; var indexOfView = indexOf(itemsPreviouslyInViews_1, item, matcher_1, index); var view = void 0; if (indexOfView === -1) { var overrideContext = createFullOverrideContext($repeat, items[index], index, itemsLength); $repeat.insertView(index, overrideContext.bindingContext, overrideContext); itemsPreviouslyInViews_1.splice(index, 0, undefined); } else if (indexOfView === index) { view = children[indexOfView]; itemsPreviouslyInViews_1[indexOfView] = undefined; } else { view = children[indexOfView]; $repeat.moveView(indexOfView, index); itemsPreviouslyInViews_1.splice(indexOfView, 1); itemsPreviouslyInViews_1.splice(index, 0, undefined); } if (view) { updateOverrideContext(view.overrideContext, index, itemsLength); } } _this._inPlaceProcessItems($repeat, items); }; } else { removePromise = $repeat.removeAllViews(true, !$repeat.viewsRequireLifecycle); updateViews = function () { return _this._standardProcessInstanceChanged($repeat, items); }; } if (removePromise instanceof Promise) { removePromise.then(updateViews); } else { updateViews(); } } else { this._inPlaceProcessItems($repeat, items); } }; ArrayRepeatStrategy.prototype._standardProcessInstanceChanged = function (repeat, items) { for (var i = 0, ii = items.length; i < ii; i++) { var overrideContext = createFullOverrideContext(repeat, items[i], i, ii); repeat.addView(overrideContext.bindingContext, overrideContext); } }; ArrayRepeatStrategy.prototype._inPlaceProcessItems = function (repeat, items) { var itemsLength = items.length; var viewsLength = repeat.viewCount(); while (viewsLength > itemsLength) { viewsLength--; repeat.removeView(viewsLength, true, !repeat.viewsRequireLifecycle); } var local = repeat.local; for (var i = 0; i < viewsLength; i++) { var view = repeat.view(i); var last = i === itemsLength - 1; var middle = i !== 0 && !last; var bindingContext = view.bindingContext; var overrideContext = view.overrideContext; if (bindingContext[local] === items[i] && overrideContext.$middle === middle && overrideContext.$last === last) { continue; } bindingContext[local] = items[i]; overrideContext.$middle = middle; overrideContext.$last = last; repeat.updateBindings(view); } for (var i = viewsLength; i < itemsLength; i++) { var overrideContext = createFullOverrideContext(repeat, items[i], i, itemsLength); repeat.addView(overrideContext.bindingContext, overrideContext); } }; ArrayRepeatStrategy.prototype.instanceMutated = function (repeat, array, splices) { var _this = this; if (repeat.__queuedSplices) { for (var i = 0, ii = splices.length; i < ii; ++i) { var _a = splices[i], index = _a.index, removed = _a.removed, addedCount = _a.addedCount; aureliaBinding.mergeSplice(repeat.__queuedSplices, index, removed, addedCount); } repeat.__array = array.slice(0); return; } var maybePromise = this._runSplices(repeat, array.slice(0), splices); if (maybePromise instanceof Promise) { var queuedSplices_1 = repeat.__queuedSplices = []; var runQueuedSplices_1 = function () { if (!queuedSplices_1.length) { repeat.__queuedSplices = undefined; repeat.__array = undefined; return; } var nextPromise = _this._runSplices(repeat, repeat.__array, queuedSplices_1) || Promise.resolve(); queuedSplices_1 = repeat.__queuedSplices = []; nextPromise.then(runQueuedSplices_1); }; maybePromise.then(runQueuedSplices_1); } }; ArrayRepeatStrategy.prototype._runSplices = function (repeat, array, splices) { var _this = this; var removeDelta = 0; var rmPromises = []; for (var i = 0, ii = splices.length; i < ii; ++i) { var splice = splices[i]; var removed = splice.removed; for (var j = 0, jj = removed.length; j < jj; ++j) { var viewOrPromise = repeat.removeView(splice.index + removeDelta + rmPromises.length, true); if (viewOrPromise instanceof Promise) { rmPromises.push(viewOrPromise); } } removeDelta -= splice.addedCount; } if (rmPromises.length > 0) { return Promise.all(rmPromises).then(function () { var spliceIndexLow = _this._handleAddedSplices(repeat, array, splices); updateOverrideContexts(repeat.views(), spliceIndexLow); }); } var spliceIndexLow = this._handleAddedSplices(repeat, array, splices); updateOverrideContexts(repeat.views(), spliceIndexLow); return undefined; }; ArrayRepeatStrategy.prototype._handleAddedSplices = function (repeat, array, splices) { var spliceIndex; var spliceIndexLow; var arrayLength = array.length; for (var i = 0, ii = splices.length; i < ii; ++i) { var splice = splices[i]; var addIndex = spliceIndex = splice.index; var end = splice.index + splice.addedCount; if (typeof spliceIndexLow === 'undefined' || spliceIndexLow === null || spliceIndexLow > splice.index) { spliceIndexLow = spliceIndex; } for (; addIndex < end; ++addIndex) { var overrideContext = createFullOverrideContext(repeat, array[addIndex], addIndex, arrayLength); repeat.insertView(addIndex, overrideContext.bindingContext, overrideContext); } } return spliceIndexLow; }; return ArrayRepeatStrategy; }()); var MapRepeatStrategy = (function () { function MapRepeatStrategy() { } MapRepeatStrategy.prototype.getCollectionObserver = function (observerLocator, items) { return observerLocator.getMapObserver(items); }; MapRepeatStrategy.prototype.instanceChanged = function (repeat, items) { var _this = this; var removePromise = repeat.removeAllViews(true, !repeat.viewsRequireLifecycle); if (removePromise instanceof Promise) { removePromise.then(function () { return _this._standardProcessItems(repeat, items); }); return; } this._standardProcessItems(repeat, items); }; MapRepeatStrategy.prototype._standardProcessItems = function (repeat, items) { var index = 0; var overrideContext; items.forEach(function (value, key) { overrideContext = createFullOverrideContext(repeat, value, index, items.size, key); repeat.addView(overrideContext.bindingContext, overrideContext); ++index; }); }; MapRepeatStrategy.prototype.instanceMutated = function (repeat, map, records) { var key; var i; var ii; var overrideContext; var removeIndex; var addIndex; var record; var rmPromises = []; var viewOrPromise; for (i = 0, ii = records.length; i < ii; ++i) { record = records[i]; key = record.key; switch (record.type) { case 'update': removeIndex = this._getViewIndexByKey(repeat, key); viewOrPromise = repeat.removeView(removeIndex, true, !repeat.viewsRequireLifecycle); if (viewOrPromise instanceof Promise) { rmPromises.push(viewOrPromise); } overrideContext = createFullOverrideContext(repeat, map.get(key), removeIndex, map.size, key); repeat.insertView(removeIndex, overrideContext.bindingContext, overrideContext); break; case 'add': addIndex = repeat.viewCount() <= map.size - 1 ? repeat.viewCount() : map.size - 1; overrideContext = createFullOverrideContext(repeat, map.get(key), addIndex, map.size, key); repeat.insertView(map.size - 1, overrideContext.bindingContext, overrideContext); break; case 'delete': if (record.oldValue === undefined) { return; } removeIndex = this._getViewIndexByKey(repeat, key); viewOrPromise = repeat.removeView(removeIndex, true, !repeat.viewsRequireLifecycle); if (viewOrPromise instanceof Promise) { rmPromises.push(viewOrPromise); } break; case 'clear': repeat.removeAllViews(true, !repeat.viewsRequireLifecycle); break; default: continue; } } if (rmPromises.length > 0) { Promise.all(rmPromises).then(function () { updateOverrideContexts(repeat.views(), 0); }); } else { updateOverrideContexts(repeat.views(), 0); } }; MapRepeatStrategy.prototype._getViewIndexByKey = function (repeat, key) { var i; var ii; var child; for (i = 0, ii = repeat.viewCount(); i < ii; ++i) { child = repeat.view(i); if (child.bindingContext[repeat.key] === key) { return i; } } return undefined; }; return MapRepeatStrategy; }()); var NullRepeatStrategy = (function () { function NullRepeatStrategy() { } NullRepeatStrategy.prototype.instanceChanged = function (repeat, items) { repeat.removeAllViews(true); }; NullRepeatStrategy.prototype.getCollectionObserver = function (observerLocator, items) { }; return NullRepeatStrategy; }()); var NumberRepeatStrategy = (function () { function NumberRepeatStrategy() { } NumberRepeatStrategy.prototype.getCollectionObserver = function () { return null; }; NumberRepeatStrategy.prototype.instanceChanged = function (repeat, value) { var _this = this; var removePromise = repeat.removeAllViews(true, !repeat.viewsRequireLifecycle); if (removePromise instanceof Promise) { removePromise.then(function () { return _this._standardProcessItems(repeat, value); }); return; } this._standardProcessItems(repeat, value); }; NumberRepeatStrategy.prototype._standardProcessItems = function (repeat, value) { var childrenLength = repeat.viewCount(); var i; var ii; var overrideContext; var viewsToRemove; value = Math.floor(value); viewsToRemove = childrenLength - value; if (viewsToRemove > 0) { if (viewsToRemove > childrenLength) { viewsToRemove = childrenLength; } for (i = 0, ii = viewsToRemove; i < ii; ++i) { repeat.removeView(childrenLength - (i + 1), true, !repeat.viewsRequireLifecycle); } return; } for (i = childrenLength, ii = value; i < ii; ++i) { overrideContext = createFullOverrideContext(repeat, i, i, ii); repeat.addView(overrideContext.bindingContext, overrideContext); } updateOverrideContexts(repeat.views(), 0); }; return NumberRepeatStrategy; }()); var SetRepeatStrategy = (function () { function SetRepeatStrategy() { } SetRepeatStrategy.prototype.getCollectionObserver = function (observerLocator, items) { return observerLocator.getSetObserver(items); }; SetRepeatStrategy.prototype.instanceChanged = function (repeat, items) { var _this = this; var removePromise = repeat.removeAllViews(true, !repeat.viewsRequireLifecycle); if (removePromise instanceof Promise) { removePromise.then(function () { return _this._standardProcessItems(repeat, items); }); return; } this._standardProcessItems(repeat, items); }; SetRepeatStrategy.prototype._standardProcessItems = function (repeat, items) { var index = 0; var overrideContext; items.forEach(function (value) { overrideContext = createFullOverrideContext(repeat, value, index, items.size); repeat.addView(overrideContext.bindingContext, overrideContext); ++index; }); }; SetRepeatStrategy.prototype.instanceMutated = function (repeat, set, records) { var value; var i; var ii; var overrideContext; var removeIndex; var record; var rmPromises = []; var viewOrPromise; for (i = 0, ii = records.length; i < ii; ++i) { record = records[i]; value = record.value; switch (record.type) { case 'add': var size = Math.max(set.size - 1, 0); overrideContext = createFullOverrideContext(repeat, value, size, set.size); repeat.insertView(size, overrideContext.bindingContext, overrideContext); break; case 'delete': removeIndex = this._getViewIndexByValue(repeat, value); viewOrPromise = repeat.removeView(removeIndex, true, !repeat.viewsRequireLifecycle); if (viewOrPromise instanceof Promise) { rmPromises.push(viewOrPromise); } break; case 'clear': repeat.removeAllViews(true, !repeat.viewsRequireLifecycle); break; default: continue; } } if (rmPromises.length > 0) { Promise.all(rmPromises).then(function () { updateOverrideContexts(repeat.views(), 0); }); } else { updateOverrideContexts(repeat.views(), 0); } }; SetRepeatStrategy.prototype._getViewIndexByValue = function (repeat, value) { var i; var ii; var child; for (i = 0, ii = repeat.viewCount(); i < ii; ++i) { child = repeat.view(i); if (child.bindingContext[repeat.local] === value) { return i; } } return undefined; }; return SetRepeatStrategy; }()); var RepeatStrategyLocator = (function () { function RepeatStrategyLocator() { this.matchers = []; this.strategies = []; this.addStrategy(function (items) { return items === null || items === undefined; }, new NullRepeatStrategy()); this.addStrategy(function (items) { return items instanceof Array; }, new ArrayRepeatStrategy()); this.addStrategy(function (items) { return items instanceof Map; }, new MapRepeatStrategy()); this.addStrategy(function (items) { return items instanceof Set; }, new SetRepeatStrategy()); this.addStrategy(function (items) { return typeof items === 'number'; }, new NumberRepeatStrategy()); } RepeatStrategyLocator.prototype.addStrategy = function (matcher, strategy) { this.matchers.push(matcher); this.strategies.push(strategy); }; RepeatStrategyLocator.prototype.getStrategy = function (items) { var matchers = this.matchers; for (var i = 0, ii = matchers.length; i < ii; ++i) { if (matchers[i](items)) { return this.strategies[i]; } } return null; }; return RepeatStrategyLocator; }()); var lifecycleOptionalBehaviors = ['focus', 'if', 'else', 'repeat', 'show', 'hide', 'with']; function behaviorRequiresLifecycle(instruction) { var t = instruction.type; var name = t.elementName !== null ? t.elementName : t.attributeName; return lifecycleOptionalBehaviors.indexOf(name) === -1 && (t.handlesAttached || t.handlesBind || t.handlesCreated || t.handlesDetached || t.handlesUnbind) || t.viewFactory && viewsRequireLifecycle(t.viewFactory) || instruction.viewFactory && viewsRequireLifecycle(instruction.viewFactory); } function targetRequiresLifecycle(instruction) { var behaviors = instruction.behaviorInstructions; if (behaviors) { var i = behaviors.length; while (i--) { if (behaviorRequiresLifecycle(behaviors[i])) { return true; } } } return instruction.viewFactory && viewsRequireLifecycle(instruction.viewFactory); } function viewsRequireLifecycle(viewFactory) { if ('_viewsRequireLifecycle' in viewFactory) { return viewFactory._viewsRequireLifecycle; } viewFactory._viewsRequireLifecycle = false; if (viewFactory.viewFactory) { viewFactory._viewsRequireLifecycle = viewsRequireLifecycle(viewFactory.viewFactory); return viewFactory._viewsRequireLifecycle; } if (viewFactory.template.querySelector('.au-animate')) { viewFactory._viewsRequireLifecycle = true; return true; } for (var id in viewFactory.instructions) { if (targetRequiresLifecycle(viewFactory.instructions[id])) { viewFactory._viewsRequireLifecycle = true; return true; } } viewFactory._viewsRequireLifecycle = false; return false; } var AbstractRepeater = (function () { function AbstractRepeater(options) { Object.assign(this, { local: 'items', viewsRequireLifecycle: true }, options); } AbstractRepeater.prototype.viewCount = function () { throw new Error('subclass must implement `viewCount`'); }; AbstractRepeater.prototype.views = function () { throw new Error('subclass must implement `views`'); }; AbstractRepeater.prototype.view = function (index) { throw new Error('subclass must implement `view`'); }; AbstractRepeater.prototype.matcher = function () { throw new Error('subclass must implement `matcher`'); }; AbstractRepeater.prototype.addView = function (bindingContext, overrideContext) { throw new Error('subclass must implement `addView`'); }; AbstractRepeater.prototype.insertView = function (index, bindingContext, overrideContext) { throw new Error('subclass must implement `insertView`'); }; AbstractRepeater.prototype.moveView = function (sourceIndex, targetIndex) { throw new Error('subclass must implement `moveView`'); }; AbstractRepeater.prototype.removeAllViews = function (returnToCache, skipAnimation) { throw new Error('subclass must implement `removeAllViews`'); }; AbstractRepeater.prototype.removeViews = function (viewsToRemove, returnToCache, skipAnimation) { throw new Error('subclass must implement `removeView`'); }; AbstractRepeater.prototype.removeView = function (index, returnToCache, skipAnimation) { throw new Error('subclass must implement `removeView`'); }; AbstractRepeater.prototype.updateBindings = function (view) { throw new Error('subclass must implement `updateBindings`'); }; return AbstractRepeater; }()); var matcherExtractionMarker = '__marker_extracted__'; var Repeat = (function (_super) { __extends(Repeat, _super); function Repeat(viewFactory, instruction, viewSlot, viewResources, observerLocator, strategyLocator) { var _this = _super.call(this, { local: 'item', viewsRequireLifecycle: viewsRequireLifecycle(viewFactory) }) || this; _this.viewFactory = viewFactory; _this.instruction = instruction; _this.viewSlot = viewSlot; _this.lookupFunctions = viewResources.lookupFunctions; _this.observerLocator = observerLocator; _this.key = 'key'; _this.value = 'value'; _this.strategyLocator = strategyLocator; _this.ignoreMutation = false; _this.sourceExpression = getItemsSourceExpression(_this.instruction, 'repeat.for'); _this.isOneTime = isOneTime(_this.sourceExpression); _this.viewsRequireLifecycle = viewsRequireLifecycle(viewFactory); return _this; } Repeat_1 = Repeat; Repeat.prototype.call = function (context, changes) { this[context](this.items, changes); }; Repeat.prototype.bind = function (bindingContext, overrideContext) { this.scope = { bindingContext: bindingContext, overrideContext: overrideContext }; var instruction = this.instruction; if (!(matcherExtractionMarker in instruction)) { instruction[matcherExtractionMarker] = this._captureAndRemoveMatcherBinding(); } this.matcherBinding = instruction[matcherExtractionMarker]; this.itemsChanged(); }; Repeat.prototype.unbind = function () { this.scope = null; this.items = null; this.matcherBinding = null; this.viewSlot.removeAll(true, true); this._unsubscribeCollection(); }; Repeat.prototype._unsubscribeCollection = function () { if (this.collectionObserver) { this.collectionObserver.unsubscribe(this.callContext, this); this.collectionObserver = null; this.callContext = null; } }; Repeat.prototype.itemsChanged = function () { var _this = this; this._unsubscribeCollection(); if (!this.scope) { return; } var items = this.items; this.strategy = this.strategyLocator.getStrategy(items); if (!this.strategy) { throw new Error("Value for '".concat(this.sourceExpression, "' is non-repeatable")); } if (!this.isOneTime && !this._observeInnerCollection()) { this._observeCollection(); } this.ignoreMutation = true; this.strategy.instanceChanged(this, items); this.observerLocator.taskQueue.queueMicroTask(function () { _this.ignoreMutation = false; }); }; Repeat.prototype._getInnerCollection = function () { var expression = unwrapExpression(this.sourceExpression); if (!expression) { return null; } return expression.evaluate(this.scope, null); }; Repeat.prototype.handleCollectionMutated = function (collection, changes) { if (!this.collectionObserver) { return; } if (this.ignoreMutation) { return; } this.strategy.instanceMutated(this, collection, changes); }; Repeat.prototype.handleInnerCollectionMutated = function (collection, changes) { var _this = this; if (!this.collectionObserver) { return; } if (this.ignoreMutation) { return; } this.ignoreMutation = true; var newItems = this.sourceExpression.evaluate(this.scope, this.lookupFunctions); this.observerLocator.taskQueue.queueMicroTask(function () { return _this.ignoreMutation = false; }); if (newItems === this.items) { this.itemsChanged(); } else { this.items = newItems; } }; Repeat.prototype._observeInnerCollection = function () { var items = this._getInnerCollection(); var strategy = this.strategyLocator.getStrategy(items); if (!strategy) { return false; } this.collectionObserver = strategy.getCollectionObserver(this.observerLocator, items); if (!this.collectionObserver) { return false; } this.callContext = 'handleInnerCollectionMutated'; this.collectionObserver.subscribe(this.callContext, this); return true; }; Repeat.prototype._observeCollection = function () { var items = this.items; this.collectionObserver = this.strategy.getCollectionObserver(this.observerLocator, items); if (this.collectionObserver) { this.callContext = 'handleCollectionMutated'; this.collectionObserver.subscribe(this.callContext, this); } }; Repeat.prototype._captureAndRemoveMatcherBinding = function () { var viewFactory = this.viewFactory.viewFactory; if (viewFactory) { var template = viewFactory.template; var instructions = viewFactory.instructions; if (Repeat_1.useInnerMatcher) { return extractMatcherBindingExpression(instructions); } if (getChildrenCount(template) > 1) { return undefined; } var repeatedElement = getFirstElementChild(template); if (!repeatedElement.hasAttribute('au-target-id')) { return undefined; } var repeatedElementTargetId = repeatedElement.getAttribute('au-target-id'); return extractMatcherBindingExpression(instructions, repeatedElementTargetId); } return undefined; }; Repeat.prototype.viewCount = function () { return this.viewSlot.children.length; }; Repeat.prototype.views = function () { return this.viewSlot.children; }; Repeat.prototype.view = function (index) { return this.viewSlot.children[index]; }; Repeat.prototype.matcher = function () { var matcherBinding = this.matcherBinding; return matcherBinding ? matcherBinding.sourceExpression.evaluate(this.scope, matcherBinding.lookupFunctions) : null; }; Repeat.prototype.addView = function (bindingContext, overrideContext) { var view = this.viewFactory.create(); view.bind(bindingContext, overrideContext); this.viewSlot.add(view); }; Repeat.prototype.insertView = function (index, bindingContext, overrideContext) { var view = this.viewFactory.create(); view.bind(bindingContext, overrideContext); this.viewSlot.insert(index, view); }; Repeat.prototype.moveView = function (sourceIndex, targetIndex) { this.viewSlot.move(sourceIndex, targetIndex); }; Repeat.prototype.removeAllViews = function (returnToCache, skipAnimation) { return this.viewSlot.removeAll(returnToCache, skipAnimation); }; Repeat.prototype.removeViews = function (viewsToRemove, returnToCache, skipAnimation) { return this.viewSlot.removeMany(viewsToRemove, returnToCache, skipAnimation); }; Repeat.prototype.removeView = function (index, returnToCache, skipAnimation) { return this.viewSlot.removeAt(index, returnToCache, skipAnimation); }; Repeat.prototype.updateBindings = function (view) { var $view = view; var j = $view.bindings.length; while (j--) { updateOneTimeBinding($view.bindings[j]); } j = $view.controllers.length; while (j--) { var k = $view.controllers[j].boundProperties.length; while (k--) { var binding = $view.controllers[j].boundProperties[k].binding; updateOneTimeBinding(binding); } } }; var Repeat_1; Repeat.useInnerMatcher = true; __decorate([ aureliaTemplating.bindable ], Repeat.prototype, "items", void 0); __decorate([ aureliaTemplating.bindable ], Repeat.prototype, "local", void 0); __decorate([ aureliaTemplating.bindable ], Repeat.prototype, "key", void 0); __decorate([ aureliaTemplating.bindable ], Repeat.prototype, "value", void 0); Repeat = Repeat_1 = __decorate([ aureliaTemplating.customAttribute('repeat'), aureliaTemplating.templateController, aureliaDependencyInjection.inject(aureliaTemplating.BoundViewFactory, aureliaTemplating.TargetInstruction, aureliaTemplating.ViewSlot, aureliaTemplating.ViewResources, aureliaBinding.ObserverLocator, RepeatStrategyLocator) ], Repeat); return Repeat