var Replaceable = (function () { function Replaceable(viewFactory, viewSlot) { _classCallCheck(this, _Replaceable); viewSlot.add(viewFactory.create()); } var _Replaceable = Replaceable; Replaceable = _aureliaDependencyInjection.inject(_aureliaTemplating.BoundViewFactory, _aureliaTemplating.ViewSlot)(Replaceable) || Replaceable; Replaceable = _aureliaTemplating.templateController(Replaceable) || Replaceable; Replaceable = _aureliaTemplating.customAttribute('replaceable')(Replaceable) || Replaceable; return Replaceable; })();
var With = (function () { function With(viewFactory, viewSlot) { _classCallCheck(this, _With); this.viewFactory = viewFactory; this.viewSlot = viewSlot; } var _With = With; _With.prototype.valueChanged = function valueChanged(newValue) { if (!this.view) { this.view = this.viewFactory.create(newValue); this.viewSlot.add(this.view); } else { this.view.bind(newValue); } }; With = _inject.inject(_BoundViewFactory$ViewSlot$customAttribute$templateController.BoundViewFactory, _BoundViewFactory$ViewSlot$customAttribute$templateController.ViewSlot)(With) || With; With = _BoundViewFactory$ViewSlot$customAttribute$templateController.templateController(With) || With; With = _BoundViewFactory$ViewSlot$customAttribute$templateController.customAttribute('with')(With) || With; return With; })();
var Repeat = (function () { var _instanceInitializers = {}; _createDecoratedClass(Repeat, [{ key: 'items', decorators: [_aureliaTemplating.bindable], initializer: null, enumerable: true }, { key: 'local', decorators: [_aureliaTemplating.bindable], initializer: null, enumerable: true }, { key: 'key', decorators: [_aureliaTemplating.bindable], initializer: null, enumerable: true }, { key: 'value', decorators: [_aureliaTemplating.bindable], initializer: null, enumerable: true }], null, _instanceInitializers); function Repeat(viewFactory, viewSlot, observerLocator) { _classCallCheck(this, _Repeat); _defineDecoratedPropertyDescriptor(this, 'items', _instanceInitializers); _defineDecoratedPropertyDescriptor(this, 'local', _instanceInitializers); _defineDecoratedPropertyDescriptor(this, 'key', _instanceInitializers); _defineDecoratedPropertyDescriptor(this, 'value', _instanceInitializers); this.viewFactory = viewFactory; this.viewSlot = viewSlot; this.observerLocator = observerLocator; this.local = 'item'; this.key = 'key'; this.value = 'value'; } Repeat.prototype.bind = function bind(executionContext) { var _this = this; var items = this.items, observer; this.executionContext = executionContext; if (!items) { if (this.oldItems) { this.removeAll(); } return; } if (this.oldItems === items) { if (items instanceof Map) { var records = _aureliaBinding.getChangeRecords(items); observer = this.observerLocator.getMapObserver(items); this.handleMapChangeRecords(items, records); this.disposeSubscription = observer.subscribe(function (records) { _this.handleMapChangeRecords(items, records); }); } else { var splices = _aureliaBinding.calcSplices(items, 0, items.length, this.lastBoundItems, 0, this.lastBoundItems.length); observer = this.observerLocator.getArrayObserver(items); this.handleSplices(items, splices); this.lastBoundItems = this.oldItems = null; this.disposeSubscription = observer.subscribe(function (splices) { _this.handleSplices(items, splices); }); return; } } else if (this.oldItems) { this.removeAll(); } this.processItems(); }; Repeat.prototype.unbind = function unbind() { this.oldItems = this.items; if (this.items instanceof Array) { this.lastBoundItems = this.items.slice(0); } if (this.disposeSubscription) { this.disposeSubscription(); this.disposeSubscription = null; } }; Repeat.prototype.itemsChanged = function itemsChanged() { this.processItems(); }; Repeat.prototype.processItems = function processItems() { var items = this.items; if (this.disposeSubscription) { this.disposeSubscription(); this.removeAll(); } if (!items && items !== 0) { return; } if (items instanceof Array) { this.processArrayItems(items); } else if (items instanceof Map) { this.processMapEntries(items); } else if (typeof items === 'number') { this.processNumber(items); } else { throw new Error('Object in "repeat" must be of type Array, Map or Number'); } }; Repeat.prototype.processArrayItems = function processArrayItems(items) { var _this2 = this; var viewFactory = this.viewFactory, viewSlot = this.viewSlot, i, ii, row, view, observer; observer = this.observerLocator.getArrayObserver(items); for (i = 0, ii = items.length; i < ii; ++i) { row = this.createFullExecutionContext(items[i], i, ii); view = viewFactory.create(row); viewSlot.add(view); } this.disposeSubscription = observer.subscribe(function (splices) { _this2.handleSplices(items, splices); }); }; Repeat.prototype.processMapEntries = function processMapEntries(items) { var _this3 = this; var viewFactory = this.viewFactory, viewSlot = this.viewSlot, index = 0, row, view, observer; observer = this.observerLocator.getMapObserver(items); items.forEach(function (value, key) { row = _this3.createFullExecutionKvpContext(key, value, index, items.size); view = viewFactory.create(row); viewSlot.add(view); ++index; }); this.disposeSubscription = observer.subscribe(function (record) { _this3.handleMapChangeRecords(items, record); }); }; Repeat.prototype.processNumber = function processNumber(value) { var viewFactory = this.viewFactory, viewSlot = this.viewSlot, childrenLength = viewSlot.children.length, i, ii, row, view, viewsToRemove; value = Math.floor(value); viewsToRemove = childrenLength - value; if (viewsToRemove > 0) { if (viewsToRemove > childrenLength) { viewsToRemove = childrenLength; } for (i = 0, ii = viewsToRemove; i < ii; ++i) { viewSlot.removeAt(childrenLength - (i + 1)); } return; } for (i = childrenLength, ii = value; i < ii; ++i) { row = this.createFullExecutionContext(i, i, ii); view = viewFactory.create(row); viewSlot.add(view); } }; Repeat.prototype.createBaseExecutionContext = function createBaseExecutionContext(data) { var context = {}; context[this.local] = data; context.$parent = this.executionContext; return context; }; Repeat.prototype.createBaseExecutionKvpContext = function createBaseExecutionKvpContext(key, value) { var context = {}; context[this.key] = key; context[this.value] = value; context.$parent = this.executionContext; return context; }; Repeat.prototype.createFullExecutionContext = function createFullExecutionContext(data, index, length) { var context = this.createBaseExecutionContext(data); return this.updateExecutionContext(context, index, length); }; Repeat.prototype.createFullExecutionKvpContext = function createFullExecutionKvpContext(key, value, index, length) { var context = this.createBaseExecutionKvpContext(key, value); return this.updateExecutionContext(context, index, length); }; Repeat.prototype.updateExecutionContext = function updateExecutionContext(context, index, length) { var first = index === 0, last = index === length - 1, even = index % 2 === 0; context.$index = index; context.$first = first; context.$last = last; context.$middle = !(first || last); context.$odd = !even; context.$even = even; return context; }; Repeat.prototype.handleSplices = function handleSplices(array, splices) { var viewLookup = new Map(), viewSlot = this.viewSlot, spliceIndexLow, viewOrPromise, view, i, ii, j, jj, row, splice, addIndex, end, itemsLeftToAdd, removed, model, children, length, context, spliceIndex; for (i = 0, ii = splices.length; i < ii; ++i) { splice = splices[i]; addIndex = spliceIndex = splice.index; itemsLeftToAdd = splice.addedCount; end = splice.index + splice.addedCount; removed = splice.removed; if (typeof spliceIndexLow === 'undefined' || spliceIndexLow === null || spliceIndexLow > splice.index) { spliceIndexLow = spliceIndex; } for (j = 0, jj = removed.length; j < jj; ++j) { if (itemsLeftToAdd > 0) { view = viewSlot.children[spliceIndex + j]; view.detached(); context = this.createFullExecutionContext(array[addIndex + j], spliceIndex + j, array.length); view.bind(context); view.attached(); --itemsLeftToAdd; } else { viewOrPromise = viewSlot.removeAt(addIndex + splice.addedCount); if (viewOrPromise) { viewLookup.set(removed[j], viewOrPromise); } } } addIndex += removed.length; for (; 0 < itemsLeftToAdd; ++addIndex) { model = array[addIndex]; viewOrPromise = viewLookup.get(model); if (viewOrPromise instanceof Promise) { (function (localAddIndex, localModel) { viewOrPromise.then(function (view) { viewLookup['delete'](localModel); viewSlot.insert(localAddIndex, view); }); })(addIndex, model); } else if (viewOrPromise) { viewLookup['delete'](model); viewSlot.insert(addIndex, viewOrPromise); } else { row = this.createBaseExecutionContext(model); view = this.viewFactory.create(row); viewSlot.insert(addIndex, view); } --itemsLeftToAdd; } } children = this.viewSlot.children; length = children.length; if (spliceIndexLow > 0) { spliceIndexLow = spliceIndexLow - 1; } for (; spliceIndexLow < length; ++spliceIndexLow) { this.updateExecutionContext(children[spliceIndexLow].executionContext, spliceIndexLow, length); } viewLookup.forEach(function (x) { if (x instanceof Promise) { x.then(function (y) { return y.unbind(); }); } else { x.unbind(); } }); }; Repeat.prototype.handleMapChangeRecords = function handleMapChangeRecords(map, records) { var viewSlot = this.viewSlot, key, i, ii, view, children, length, row, removeIndex, record; for (i = 0, ii = records.length; i < ii; ++i) { record = records[i]; key = record.key; switch (record.type) { case 'update': removeIndex = this.getViewIndexByKey(key); viewSlot.removeAt(removeIndex); row = this.createBaseExecutionKvpContext(key, map.get(key)); view = this.viewFactory.create(row); viewSlot.insert(removeIndex, view); break; case 'add': row = this.createBaseExecutionKvpContext(key, map.get(key)); view = this.viewFactory.create(row); viewSlot.insert(map.size, view); break; case 'delete': if (!record.oldValue) { return; } removeIndex = this.getViewIndexByKey(key); viewSlot.removeAt(removeIndex); break; case 'clear': viewSlot.removeAll(); } } children = viewSlot.children; length = children.length; for (i = 0; i < length; i++) { this.updateExecutionContext(children[i].executionContext, i, length); } }; Repeat.prototype.getViewIndexByKey = function getViewIndexByKey(key) { var viewSlot = this.viewSlot, i, ii, child; for (i = 0, ii = viewSlot.children.length; i < ii; ++i) { child = viewSlot.children[i]; if (child.bindings[0].source[this.key] === key) { return i; } } }; Repeat.prototype.removeAll = function removeAll() { var viewSlot = this.viewSlot, views, i; views = viewSlot.children; viewSlot.removeAll(); i = views.length; while (i--) { views[i].unbind(); } }; var _Repeat = Repeat; Repeat = _aureliaDependencyInjection.inject(_aureliaTemplating.BoundViewFactory, _aureliaTemplating.ViewSlot, _aureliaBinding.ObserverLocator)(Repeat) || Repeat; Repeat = _aureliaTemplating.templateController(Repeat) || Repeat; Repeat = _aureliaTemplating.customAttribute('repeat')(Repeat) || Repeat; return Repeat; })();
export var VirtualRepeat = (_dec = customAttribute('virtual-repeat'), _dec2 = inject(DOM.Element, BoundViewFactory, TargetInstruction, ViewSlot, ViewResources, ObserverLocator, VirtualRepeatStrategyLocator, TemplateStrategyLocator, DomHelper), _dec(_class = templateController(_class = _dec2(_class = (_class2 = function (_AbstractRepeater) { _inherits(VirtualRepeat, _AbstractRepeater); function VirtualRepeat(element, viewFactory, instruction, viewSlot, viewResources, observerLocator, strategyLocator, templateStrategyLocator, domHelper) { var _this = _possibleConstructorReturn(this, _AbstractRepeater.call(this, { local: 'item', viewsRequireLifecycle: viewsRequireLifecycle(viewFactory) })); _this._first = 0; _this._previousFirst = 0; _this._viewsLength = 0; _this._lastRebind = 0; _this._topBufferHeight = 0; _this._bottomBufferHeight = 0; _this._bufferSize = 5; _this._scrollingDown = false; _this._scrollingUp = false; _this._switchedDirection = false; _this._isAttached = false; _this._ticking = false; _this._fixedHeightContainer = false; _this._hasCalculatedSizes = false; _this._isAtTop = true; _this._calledGetMore = false; _initDefineProp(_this, 'items', _descriptor, _this); _initDefineProp(_this, 'local', _descriptor2, _this); _this.element = element; _this.viewFactory = viewFactory; _this.instruction = instruction; _this.viewSlot = viewSlot; _this.lookupFunctions = viewResources.lookupFunctions; _this.observerLocator = observerLocator; _this.strategyLocator = strategyLocator; _this.templateStrategyLocator = templateStrategyLocator; _this.sourceExpression = getItemsSourceExpression(_this.instruction, 'virtual-repeat.for'); _this.isOneTime = isOneTime(_this.sourceExpression); _this.domHelper = domHelper; return _this; } VirtualRepeat.prototype.attached = function attached() { var _this2 = this; this._isAttached = true; var element = this.element; this._itemsLength = this.items.length; this.templateStrategy = this.templateStrategyLocator.getStrategy(element); this.scrollContainer = this.templateStrategy.getScrollContainer(element); this.topBuffer = this.templateStrategy.createTopBufferElement(element); this.bottomBuffer = this.templateStrategy.createBottomBufferElement(element); this.itemsChanged(); this.scrollListener = function () { return _this2._onScroll(); }; this.calcDistanceToTopInterval = setInterval(function () { var distanceToTop = _this2.distanceToTop; _this2.distanceToTop = _this2.domHelper.getElementDistanceToTopOfDocument(_this2.topBuffer); _this2.distanceToTop += _this2.topBufferDistance; if (distanceToTop !== _this2.distanceToTop) { _this2._handleScroll(); } }, 500); this.distanceToTop = this.domHelper.getElementDistanceToTopOfDocument(this.templateStrategy.getFirstElement(this.topBuffer)); this.topBufferDistance = this.templateStrategy.getTopBufferDistance(this.topBuffer); if (this.domHelper.hasOverflowScroll(this.scrollContainer)) { this._fixedHeightContainer = true; this.scrollContainer.addEventListener('scroll', this.scrollListener); } else { document.addEventListener('scroll', this.scrollListener); } }; VirtualRepeat.prototype.bind = function bind(bindingContext, overrideContext) { this.scope = { bindingContext: bindingContext, overrideContext: overrideContext }; if (this._isAttached) { this.itemsChanged(); } }; VirtualRepeat.prototype.call = function call(context, changes) { this[context](this.items, changes); }; VirtualRepeat.prototype.detached = function detached() { this.scrollContainer.removeEventListener('scroll', this.scrollListener); this._first = 0; this._previousFirst = 0; this._viewsLength = 0; this._lastRebind = 0; this._topBufferHeight = 0; this._bottomBufferHeight = 0; this._scrollingDown = false; this._scrollingUp = false; this._switchedDirection = false; this._isAttached = false; this._ticking = false; this._hasCalculatedSizes = false; this.templateStrategy.removeBufferElements(this.element, this.topBuffer, this.bottomBuffer); this.isLastIndex = false; this.scrollContainer = null; this.scrollContainerHeight = null; this.distanceToTop = null; this.removeAllViews(true); if (this.scrollHandler) { this.scrollHandler.dispose(); } this._unsubscribeCollection(); clearInterval(this.calcDistanceToTopInterval); if (this._sizeInterval) { clearInterval(this._sizeInterval); } }; VirtualRepeat.prototype.itemsChanged = function itemsChanged() { this._unsubscribeCollection(); if (!this.scope) { return; } var reducingItems = false; var previousLastViewIndex = this._getIndexOfLastView(); var items = this.items; this.strategy = this.strategyLocator.getStrategy(items); if (items.length > 0 && this.viewCount() === 0) { this.strategy.createFirstItem(this); } if (this._itemsLength >= items.length) { this._skipNextScrollHandle = true; reducingItems = true; } this._checkFixedHeightContainer(); this._calcInitialHeights(items.length); if (!this.isOneTime && !this._observeInnerCollection()) { this._observeCollection(); } this.strategy.instanceChanged(this, items, this._first); this._lastRebind = this._first; if (reducingItems && previousLastViewIndex > this.items.length - 1) { if (this.scrollContainer.tagName === 'TBODY') { var realScrollContainer = this.scrollContainer.parentNode.parentNode; realScrollContainer.scrollTop = realScrollContainer.scrollTop + this.viewCount() * this.itemHeight; } else { this.scrollContainer.scrollTop = this.scrollContainer.scrollTop + this.viewCount() * this.itemHeight; } } if (!reducingItems) { this._previousFirst = this._first; this._scrollingDown = true; this._scrollingUp = false; this.isLastIndex = this._getIndexOfLastView() >= this.items.length - 1; } this._handleScroll(); }; VirtualRepeat.prototype.unbind = function unbind() { this.scope = null; this.items = null; this._itemsLength = null; }; VirtualRepeat.prototype.handleCollectionMutated = function handleCollectionMutated(collection, changes) { this._handlingMutations = true; this._itemsLength = collection.length; this.strategy.instanceMutated(this, collection, changes); }; VirtualRepeat.prototype.handleInnerCollectionMutated = function handleInnerCollectionMutated(collection, changes) { var _this3 = this; if (this.ignoreMutation) { return; } this.ignoreMutation = true; var newItems = this.sourceExpression.evaluate(this.scope, this.lookupFunctions); this.observerLocator.taskQueue.queueMicroTask(function () { return _this3.ignoreMutation = false; }); if (newItems === this.items) { this.itemsChanged(); } else { this.items = newItems; } }; VirtualRepeat.prototype._onScroll = function _onScroll() { var _this4 = this; if (!this._ticking && !this._handlingMutations) { requestAnimationFrame(function () { return _this4._handleScroll(); }); this._ticking = true; } if (this._handlingMutations) { this._handlingMutations = false; } }; VirtualRepeat.prototype._handleScroll = function _handleScroll() { if (!this._isAttached) { return; } if (this._skipNextScrollHandle) { this._skipNextScrollHandle = false; return; } var itemHeight = this.itemHeight; var scrollTop = this._fixedHeightContainer ? this.scrollContainer.scrollTop : pageYOffset - this.distanceToTop; this._first = Math.floor(scrollTop / itemHeight); this._first = this._first < 0 ? 0 : this._first; if (this._first > this.items.length - this.elementsInView) { this._first = this.items.length - this.elementsInView; this._first = this._first < 0 ? 0 : this._first; } this._checkScrolling(); if (this._scrollingDown) { var viewsToMove = this._first - this._lastRebind; if (this._switchedDirection) { viewsToMove = this._isAtTop ? this._first : this._bufferSize - (this._lastRebind - this._first); } this._isAtTop = false; this._lastRebind = this._first; var movedViewsCount = this._moveViews(viewsToMove); var adjustHeight = movedViewsCount < viewsToMove ? this._bottomBufferHeight : itemHeight * movedViewsCount; if (viewsToMove > 0) { this._getMore(); } this._switchedDirection = false; this._topBufferHeight = this._topBufferHeight + adjustHeight; this._bottomBufferHeight = this._bottomBufferHeight - adjustHeight; if (this._bottomBufferHeight >= 0) { this._adjustBufferHeights(); } } else if (this._scrollingUp) { var _viewsToMove = this._lastRebind - this._first; var initialScrollState = this.isLastIndex === undefined; if (this._switchedDirection) { if (this.isLastIndex) { _viewsToMove = this.items.length - this._first - this.elementsInView; } else { _viewsToMove = this._bufferSize - (this._first - this._lastRebind); } } this.isLastIndex = false; this._lastRebind = this._first; var _movedViewsCount = this._moveViews(_viewsToMove); this.movedViewsCount = _movedViewsCount; var _adjustHeight = _movedViewsCount < _viewsToMove ? this._topBufferHeight : itemHeight * _movedViewsCount; if (_viewsToMove > 0) { var force = this.movedViewsCount === 0 && initialScrollState && this._first <= 0 ? true : false; this._getMore(force); } this._switchedDirection = false; this._topBufferHeight = this._topBufferHeight - _adjustHeight; this._bottomBufferHeight = this._bottomBufferHeight + _adjustHeight; if (this._topBufferHeight >= 0) { this._adjustBufferHeights(); } } this._previousFirst = this._first; this._ticking = false; }; VirtualRepeat.prototype._getMore = function _getMore(force) { var _this5 = this; if (this.isLastIndex || this._first === 0 || force) { if (!this._calledGetMore) { var executeGetMore = function executeGetMore() { _this5._calledGetMore = true; var func = _this5.view(0) && _this5.view(0).firstChild && _this5.view(0).firstChild.au && _this5.view(0).firstChild.au['infinite-scroll-next'] ? _this5.view(0).firstChild.au['infinite-scroll-next'].instruction.attributes['infinite-scroll-next'] : undefined; var topIndex = _this5._first; var isAtBottom = _this5._bottomBufferHeight === 0; var isAtTop = _this5._isAtTop; var scrollContext = { topIndex: topIndex, isAtBottom: isAtBottom, isAtTop: isAtTop }; _this5.scope.overrideContext.$scrollContext = scrollContext; if (func === undefined) { return null; } else if (typeof func === 'string') { var getMoreFuncName = _this5.view(0).firstChild.getAttribute('infinite-scroll-next'); var funcCall = _this5.scope.overrideContext.bindingContext[getMoreFuncName]; if (typeof funcCall === 'function') { var result = funcCall.call(_this5.scope.overrideContext.bindingContext, topIndex, isAtBottom, isAtTop); if (!(result instanceof Promise)) { _this5._calledGetMore = false; } else { return result.then(function () { _this5._calledGetMore = false; }); } } else { throw new Error("'infinite-scroll-next' must be a function or evaluate to one"); } } else if (func.sourceExpression) { _this5._calledGetMore = false; return func.sourceExpression.evaluate(_this5.scope); } else { throw new Error("'infinite-scroll-next' must be a function or evaluate to one"); } return null; }; this.observerLocator.taskQueue.queueMicroTask(executeGetMore); } } }; VirtualRepeat.prototype._checkScrolling = function _checkScrolling() { if (this._first > this._previousFirst && (this._bottomBufferHeight > 0 || !this.isLastIndex)) { if (!this._scrollingDown) { this._scrollingDown = true; this._scrollingUp = false; this._switchedDirection = true; } else { this._switchedDirection = false; } this._isScrolling = true; } else if (this._first < this._previousFirst && (this._topBufferHeight >= 0 || !this._isAtTop)) { if (!this._scrollingUp) { this._scrollingDown = false; this._scrollingUp = true; this._switchedDirection = true; } else { this._switchedDirection = false; } this._isScrolling = true; } else { this._isScrolling = false; } }; VirtualRepeat.prototype._checkFixedHeightContainer = function _checkFixedHeightContainer() { if (this.domHelper.hasOverflowScroll(this.scrollContainer)) { this._fixedHeightContainer = true; } }; VirtualRepeat.prototype._adjustBufferHeights = function _adjustBufferHeights() { this.topBuffer.style.height = this._topBufferHeight + 'px'; this.bottomBuffer.style.height = this._bottomBufferHeight + 'px'; }; VirtualRepeat.prototype._unsubscribeCollection = function _unsubscribeCollection() { if (this.collectionObserver) { this.collectionObserver.unsubscribe(this.callContext, this); this.collectionObserver = null; this.callContext = null; } }; VirtualRepeat.prototype._moveViews = function _moveViews(length) { var _this6 = this; var getNextIndex = this._scrollingDown ? function (index, i) { return index + i; } : function (index, i) { return index - i; }; var isAtFirstOrLastIndex = function isAtFirstOrLastIndex() { return _this6._scrollingDown ? _this6.isLastIndex : _this6._isAtTop; }; var childrenLength = this.viewCount(); var viewIndex = this._scrollingDown ? 0 : childrenLength - 1; var items = this.items; var index = this._scrollingDown ? this._getIndexOfLastView() + 1 : this._getIndexOfFirstView() - 1; var i = 0; var viewToMoveLimit = length - childrenLength * 2; while (i < length && !isAtFirstOrLastIndex()) { var view = this.view(viewIndex); var nextIndex = getNextIndex(index, i); this.isLastIndex = nextIndex >= items.length - 1; this._isAtTop = nextIndex <= 0; if (!(isAtFirstOrLastIndex() && childrenLength >= items.length)) { if (i > viewToMoveLimit) { rebindAndMoveView(this, view, nextIndex, this._scrollingDown); } i++; } } return length - (length - i); }; VirtualRepeat.prototype._getIndexOfLastView = function _getIndexOfLastView() { var view = this.view(this.viewCount() - 1); if (view) { return view.overrideContext.$index; } return -1; }; VirtualRepeat.prototype._getLastViewItem = function _getLastViewItem() { var children = this.viewSlot.children; if (!children.length) { return undefined; } var lastViewItem = children[children.length - 1].bindingContext[this.local]; return lastViewItem; }; VirtualRepeat.prototype._getIndexOfFirstView = function _getIndexOfFirstView() { return this.view(0) ? this.view(0).overrideContext.$index : -1; }; VirtualRepeat.prototype._calcInitialHeights = function _calcInitialHeights(itemsLength) { var _this7 = this; if (this._viewsLength > 0 && this._itemsLength === itemsLength || this._viewsLength > 0 && itemsLength < 0) { return; } this._hasCalculatedSizes = true; var firstViewElement = this.view(0).lastChild; this.itemHeight = calcOuterHeight(firstViewElement); if (this.itemHeight <= 0) { this._sizeInterval = setInterval(function () { var newCalcSize = calcOuterHeight(firstViewElement); if (newCalcSize > 0) { clearInterval(_this7._sizeInterval); _this7.itemsChanged(); } }, 500); return; } this._itemsLength = itemsLength; this.scrollContainerHeight = this._fixedHeightContainer ? this._calcScrollHeight(this.scrollContainer) : document.documentElement.clientHeight; this.elementsInView = Math.ceil(this.scrollContainerHeight / this.itemHeight) + 1; this._viewsLength = this.elementsInView * 2 + this._bufferSize; var newBottomBufferHeight = this.itemHeight * itemsLength - this.itemHeight * this._viewsLength; if (newBottomBufferHeight < 0) { newBottomBufferHeight = 0; } if (this._topBufferHeight >= newBottomBufferHeight) { this._topBufferHeight = newBottomBufferHeight; this._bottomBufferHeight = 0; this._first = this._itemsLength - this._viewsLength; if (this._first < 0) { this._first = 0; } } else { this._first = this._getIndexOfFirstView(); var adjustedTopBufferHeight = this._first * this.itemHeight; this._topBufferHeight = adjustedTopBufferHeight; this._bottomBufferHeight = newBottomBufferHeight - adjustedTopBufferHeight; if (this._bottomBufferHeight < 0) { this._bottomBufferHeight = 0; } } this._adjustBufferHeights(); return; }; VirtualRepeat.prototype._calcScrollHeight = function _calcScrollHeight(element) { var height = void 0; height = element.getBoundingClientRect().height; height -= getStyleValue(element, 'borderTopWidth'); height -= getStyleValue(element, 'borderBottomWidth'); return height; }; VirtualRepeat.prototype._observeInnerCollection = function _observeInnerCollection() { 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; }; VirtualRepeat.prototype._getInnerCollection = function _getInnerCollection() { var expression = unwrapExpression(this.sourceExpression); if (!expression) { return null; } return expression.evaluate(this.scope, null); }; VirtualRepeat.prototype._observeCollection = function _observeCollection() { var items = this.items; this.collectionObserver = this.strategy.getCollectionObserver(this.observerLocator, items); if (this.collectionObserver) { this.callContext = 'handleCollectionMutated'; this.collectionObserver.subscribe(this.callContext, this); } }; VirtualRepeat.prototype.viewCount = function viewCount() { return this.viewSlot.children.length; }; VirtualRepeat.prototype.views = function views() { return this.viewSlot.children; }; VirtualRepeat.prototype.view = function view(index) { return this.viewSlot.children[index]; }; VirtualRepeat.prototype.addView = function addView(bindingContext, overrideContext) { var view = this.viewFactory.create(); view.bind(bindingContext, overrideContext); this.viewSlot.add(view); }; VirtualRepeat.prototype.insertView = function insertView(index, bindingContext, overrideContext) { var view = this.viewFactory.create(); view.bind(bindingContext, overrideContext); this.viewSlot.insert(index, view); }; VirtualRepeat.prototype.removeAllViews = function removeAllViews(returnToCache, skipAnimation) { return this.viewSlot.removeAll(returnToCache, skipAnimation); }; VirtualRepeat.prototype.removeView = function removeView(index, returnToCache, skipAnimation) { return this.viewSlot.removeAt(index, returnToCache, skipAnimation); }; VirtualRepeat.prototype.updateBindings = function updateBindings(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); } } }; return VirtualRepeat; }(AbstractRepeater), (_descriptor = _applyDecoratedDescriptor(_class2.prototype, 'items', [bindable], { enumerable: true, initializer: null }), _descriptor2 = _applyDecoratedDescriptor(_class2.prototype, 'local', [bindable], { enumerable: true, initializer: null })), _class2)) || _class) || _class) || _class);
var Repeat = (function () { var _instanceInitializers = {}; _createDecoratedClass(Repeat, [{ key: 'items', decorators: [_aureliaTemplating.bindable], initializer: null, enumerable: true }, { key: 'local', decorators: [_aureliaTemplating.bindable], initializer: null, enumerable: true }, { key: 'key', decorators: [_aureliaTemplating.bindable], initializer: null, enumerable: true }, { key: 'value', decorators: [_aureliaTemplating.bindable], initializer: null, enumerable: true }], null, _instanceInitializers); function Repeat(viewFactory, instruction, viewSlot, viewResources, observerLocator, strategyLocator) { _classCallCheck(this, _Repeat); _defineDecoratedPropertyDescriptor(this, 'items', _instanceInitializers); _defineDecoratedPropertyDescriptor(this, 'local', _instanceInitializers); _defineDecoratedPropertyDescriptor(this, 'key', _instanceInitializers); _defineDecoratedPropertyDescriptor(this, 'value', _instanceInitializers); this.viewFactory = viewFactory; this.instruction = instruction; this.viewSlot = viewSlot; this.lookupFunctions = viewResources.lookupFunctions; this.observerLocator = observerLocator; this.local = 'item'; this.key = 'key'; this.value = 'value'; this.strategyLocator = strategyLocator; this.ignoreMutation = false; this.sourceExpression = _repeatUtilities.getItemsSourceExpression(this.instruction, 'repeat.for'); this.isOneTime = _repeatUtilities.isOneTime(this.sourceExpression); this.viewsRequireLifecycle = _analyzeViewFactory.viewsRequireLifecycle(viewFactory); } Repeat.prototype.call = function call(context, changes) { this[context](this.items, changes); }; Repeat.prototype.bind = function bind(bindingContext, overrideContext) { this.scope = { bindingContext: bindingContext, overrideContext: overrideContext }; this.itemsChanged(); }; Repeat.prototype.unbind = function unbind() { this.scope = null; this.items = null; this.viewSlot.removeAll(true); this._unsubscribeCollection(); }; Repeat.prototype._unsubscribeCollection = function _unsubscribeCollection() { if (this.collectionObserver) { this.collectionObserver.unsubscribe(this.callContext, this); this.collectionObserver = null; this.callContext = null; } }; Repeat.prototype.itemsChanged = function itemsChanged() { this._unsubscribeCollection(); if (!this.scope) { return; } var items = this.items; this.strategy = this.strategyLocator.getStrategy(items); if (!this.isOneTime && !this._observeInnerCollection()) { this._observeCollection(); } this.strategy.instanceChanged(this, items); }; Repeat.prototype._getInnerCollection = function _getInnerCollection() { var expression = _repeatUtilities.unwrapExpression(this.sourceExpression); if (!expression) { return null; } return expression.evaluate(this.scope, null); }; Repeat.prototype.handleCollectionMutated = function handleCollectionMutated(collection, changes) { this.strategy.instanceMutated(this, collection, changes); }; Repeat.prototype.handleInnerCollectionMutated = function handleInnerCollectionMutated(collection, changes) { var _this = this; 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 _observeInnerCollection() { 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 _observeCollection() { var items = this.items; this.collectionObserver = this.strategy.getCollectionObserver(this.observerLocator, items); if (this.collectionObserver) { this.callContext = 'handleCollectionMutated'; this.collectionObserver.subscribe(this.callContext, this); } }; var _Repeat = Repeat; Repeat = _aureliaDependencyInjection.inject(_aureliaTemplating.BoundViewFactory, _aureliaTemplating.TargetInstruction, _aureliaTemplating.ViewSlot, _aureliaTemplating.ViewResources, _aureliaBinding.ObserverLocator, _repeatStrategyLocator.RepeatStrategyLocator)(Repeat) || Repeat; Repeat = _aureliaTemplating.templateController(Repeat) || Repeat; Repeat = _aureliaTemplating.customAttribute('repeat')(Repeat) || Repeat; return Repeat; })();
var _dec, _dec2, _class; import { inject } from 'aurelia-dependency-injection'; import { BoundViewFactory, ViewSlot, customAttribute, templateController } from 'aurelia-templating'; export var Replaceable = (_dec = customAttribute('replaceable'), _dec2 = inject(BoundViewFactory, ViewSlot), _dec(_class = templateController(_class = _dec2(_class = function () { function Replaceable(viewFactory, viewSlot) { this.viewFactory = viewFactory; this.viewSlot = viewSlot; this.view = null; } Replaceable.prototype.bind = function bind(bindingContext, overrideContext) { if (this.view === null) { this.view = this.viewFactory.create(); this.viewSlot.add(this.view); } this.view.bind(bindingContext, overrideContext); }; Replaceable.prototype.unbind = function unbind() { this.view.unbind(); }; return Replaceable; }()) || _class) || _class) || _class);
export let VirtualRepeat = (_dec = customAttribute('virtual-repeat'), _dec2 = inject(DOM.Element, BoundViewFactory, TargetInstruction, ViewSlot, ViewResources, ObserverLocator, VirtualRepeatStrategyLocator, ViewStrategyLocator, DomHelper), _dec(_class = templateController(_class = _dec2(_class = (_class2 = class VirtualRepeat extends AbstractRepeater { constructor(element, viewFactory, instruction, viewSlot, viewResources, observerLocator, strategyLocator, viewStrategyLocator, domHelper) { super({ local: 'item', viewsRequireLifecycle: viewsRequireLifecycle(viewFactory) }); this._first = 0; this._previousFirst = 0; this._viewsLength = 0; this._lastRebind = 0; this._topBufferHeight = 0; this._bottomBufferHeight = 0; this._bufferSize = 5; this._scrollingDown = false; this._scrollingUp = false; this._switchedDirection = false; this._isAttached = false; this._ticking = false; this._fixedHeightContainer = false; this._hasCalculatedSizes = false; this._isAtTop = true; _initDefineProp(this, 'items', _descriptor, this); _initDefineProp(this, 'local', _descriptor2, this); this.element = element; this.viewFactory = viewFactory; this.instruction = instruction; this.viewSlot = viewSlot; this.lookupFunctions = viewResources.lookupFunctions; this.observerLocator = observerLocator; this.strategyLocator = strategyLocator; this.viewStrategyLocator = viewStrategyLocator; this.sourceExpression = getItemsSourceExpression(this.instruction, 'virtual-repeat.for'); this.isOneTime = isOneTime(this.sourceExpression); this.domHelper = domHelper; } attached() { this._isAttached = true; let element = this.element; this._itemsLength = this.items.length; this.viewStrategy = this.viewStrategyLocator.getStrategy(element); this.scrollContainer = this.viewStrategy.getScrollContainer(element); this.topBuffer = this.viewStrategy.createTopBufferElement(element); this.bottomBuffer = this.viewStrategy.createBottomBufferElement(element); this.itemsChanged(); this.scrollListener = () => this._onScroll(); this.calcDistanceToTopInterval = setInterval(() => { let distanceToTop = this.distanceToTop; this.distanceToTop = this.domHelper.getElementDistanceToTopOfDocument(this.topBuffer); if (distanceToTop !== this.distanceToTop) { this._handleScroll(); } }, 500); this.distanceToTop = this.domHelper.getElementDistanceToTopOfDocument(this.viewStrategy.getFirstElement(this.topBuffer)); if (this.domHelper.hasOverflowScroll(this.scrollContainer)) { this._fixedHeightContainer = true; this.scrollContainer.addEventListener('scroll', this.scrollListener); } else { document.addEventListener('scroll', this.scrollListener); } } bind(bindingContext, overrideContext) { this.scope = { bindingContext, overrideContext }; } call(context, changes) { this[context](this.items, changes); } detached() { this.scrollContainer.removeEventListener('scroll', this.scrollListener); this._first = 0; this._previousFirst = 0; this._viewsLength = 0; this._lastRebind = 0; this._topBufferHeight = 0; this._bottomBufferHeight = 0; this._scrollingDown = false; this._scrollingUp = false; this._switchedDirection = false; this._isAttached = false; this._ticking = false; this._hasCalculatedSizes = false; this.viewStrategy.removeBufferElements(this.element, this.topBuffer, this.bottomBuffer); this.isLastIndex = false; this.scrollContainer = null; this.scrollContainerHeight = null; this.distanceToTop = null; this.removeAllViews(true); if (this.scrollHandler) { this.scrollHandler.dispose(); } this._unsubscribeCollection(); clearInterval(this.calcDistanceToTopInterval); } itemsChanged() { this._unsubscribeCollection(); if (!this.scope) { return; } let items = this.items; this.strategy = this.strategyLocator.getStrategy(items); if (items.length > 0 && this.viewCount() === 0) { this.strategy.createFirstItem(this); } this._calcInitialHeights(items.length); if (!this.isOneTime && !this._observeInnerCollection()) { this._observeCollection(); } this.strategy.instanceChanged(this, items, this._viewsLength); } unbind() { this.scope = null; this.items = null; this._itemsLength = null; } handleCollectionMutated(collection, changes) { this._handlingMutations = true; this._itemsLength = collection.length; this.strategy.instanceMutated(this, collection, changes); } handleInnerCollectionMutated(collection, changes) { if (this.ignoreMutation) { return; } this.ignoreMutation = true; let newItems = this.sourceExpression.evaluate(this.scope, this.lookupFunctions); this.observerLocator.taskQueue.queueMicroTask(() => this.ignoreMutation = false); if (newItems === this.items) { this.itemsChanged(); } else { this.items = newItems; } } _onScroll() { if (!this._ticking && !this._handlingMutations) { requestAnimationFrame(() => this._handleScroll()); this._ticking = true; } if (this._handlingMutations) { this._handlingMutations = false; } } _handleScroll() { if (!this._isAttached) { return; } let itemHeight = this.itemHeight; let scrollTop = this._fixedHeightContainer ? this.scrollContainer.scrollTop : pageYOffset - this.distanceToTop; this._first = Math.floor(scrollTop / itemHeight); this._first = this._first < 0 ? 0 : this._first; if (this._first > this.items.length - this.elementsInView) { this._first = this.items.length - this.elementsInView; } this._checkScrolling(); if (this._scrollingDown) { let viewsToMove = this._first - this._lastRebind; if (this._switchedDirection) { viewsToMove = this._isAtTop ? this._first : this._bufferSize - (this._lastRebind - this._first); } this._isAtTop = false; this._lastRebind = this._first; let movedViewsCount = this._moveViews(viewsToMove); let adjustHeight = movedViewsCount < viewsToMove ? this._bottomBufferHeight : itemHeight * movedViewsCount; this._switchedDirection = false; this._topBufferHeight = this._topBufferHeight + adjustHeight; this._bottomBufferHeight = this._bottomBufferHeight - adjustHeight; if (this._bottomBufferHeight >= 0) { this._adjustBufferHeights(); } } else if (this._scrollingUp) { let viewsToMove = this._lastRebind - this._first; if (this._switchedDirection) { if (this.isLastIndex) { viewsToMove = this.items.length - this._first - this.elementsInView; } else { viewsToMove = this._bufferSize - (this._first - this._lastRebind); } } this.isLastIndex = false; this._lastRebind = this._first; let movedViewsCount = this._moveViews(viewsToMove); this.movedViewsCount = movedViewsCount; let adjustHeight = movedViewsCount < viewsToMove ? this._topBufferHeight : itemHeight * movedViewsCount; this._switchedDirection = false; this._topBufferHeight = this._topBufferHeight - adjustHeight; this._bottomBufferHeight = this._bottomBufferHeight + adjustHeight; if (this._topBufferHeight >= 0) { this._adjustBufferHeights(); } } this._previousFirst = this._first; this._ticking = false; } _checkScrolling() { if (this._first > this._previousFirst && (this._bottomBufferHeight > 0 || !this.isLastIndex)) { if (!this._scrollingDown) { this._scrollingDown = true; this._scrollingUp = false; this._switchedDirection = true; } else { this._switchedDirection = false; } this._isScrolling = true; } else if (this._first < this._previousFirst && (this._topBufferHeight >= 0 || !this._isAtTop)) { if (!this._scrollingUp) { this._scrollingDown = false; this._scrollingUp = true; this._switchedDirection = true; } else { this._switchedDirection = false; } this._isScrolling = true; } else { this._isScrolling = false; } } _adjustBufferHeights() { this.topBuffer.style.height = `${ this._topBufferHeight }px`; this.bottomBuffer.style.height = `${ this._bottomBufferHeight }px`; } _unsubscribeCollection() { if (this.collectionObserver) { this.collectionObserver.unsubscribe(this.callContext, this); this.collectionObserver = null; this.callContext = null; } } _moveViews(length) { let getNextIndex = this._scrollingDown ? (index, i) => index + i : (index, i) => index - i; let isAtFirstOrLastIndex = () => this._scrollingDown ? this.isLastIndex : this._isAtTop; let childrenLength = this.viewCount(); let viewIndex = this._scrollingDown ? 0 : childrenLength - 1; let items = this.items; let index = this._scrollingDown ? this._getIndexOfLastView() + 1 : this._getIndexOfFirstView() - 1; let i = 0; let viewToMoveLimit = length - childrenLength * 2; while (i < length && !isAtFirstOrLastIndex()) { let view = this.view(viewIndex); let nextIndex = getNextIndex(index, i); this.isLastIndex = nextIndex >= items.length - 1; this._isAtTop = nextIndex <= 0; if (!(isAtFirstOrLastIndex() && childrenLength >= items.length)) { if (i > viewToMoveLimit) { rebindAndMoveView(this, view, nextIndex, this._scrollingDown); } i++; } } return length - (length - i); } _getIndexOfLastView() { const view = this.view(this.viewCount() - 1); if (view) { return view.overrideContext.$index; } return -1; } _getLastViewItem() { let children = this.viewSlot.children; if (!children.length) { return undefined; } let lastViewItem = children[children.length - 1].bindingContext[this.local]; return lastViewItem; } _getIndexOfFirstView() { return this.view(0) ? this.view(0).overrideContext.$index : -1; } _calcInitialHeights(itemsLength) { if (this._viewsLength > 0 && this._itemsLength === itemsLength || itemsLength <= 0) { return; } this._hasCalculatedSizes = true; this._itemsLength = itemsLength; let firstViewElement = DOM.nextElementSibling(this.view(0).firstChild); this.itemHeight = calcOuterHeight(firstViewElement); if (this.itemHeight <= 0) { throw new Error('Could not calculate item height'); } this.scrollContainerHeight = this._fixedHeightContainer ? this._calcScrollHeight(this.scrollContainer) : document.documentElement.clientHeight; this.elementsInView = Math.ceil(this.scrollContainerHeight / this.itemHeight) + 1; this._viewsLength = this.elementsInView * 2 + this._bufferSize; this._bottomBufferHeight = this.itemHeight * itemsLength - this.itemHeight * this._viewsLength; if (this._bottomBufferHeight < 0) { this._bottomBufferHeight = 0; } this.bottomBuffer.style.height = `${ this._bottomBufferHeight }px`; this._topBufferHeight = 0; this.topBuffer.style.height = `${ this._topBufferHeight }px`; this.scrollContainer.scrollTop = 0; this._first = 0; } _calcScrollHeight(element) { let height; height = element.getBoundingClientRect().height; height -= getStyleValue(element, 'borderTopWidth'); height -= getStyleValue(element, 'borderBottomWidth'); return height; } _observeInnerCollection() { let items = this._getInnerCollection(); let 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; } _getInnerCollection() { let expression = unwrapExpression(this.sourceExpression); if (!expression) { return null; } return expression.evaluate(this.scope, null); } _observeCollection() { let items = this.items; this.collectionObserver = this.strategy.getCollectionObserver(this.observerLocator, items); if (this.collectionObserver) { this.callContext = 'handleCollectionMutated'; this.collectionObserver.subscribe(this.callContext, this); } } viewCount() { return this.viewSlot.children.length; } views() { return this.viewSlot.children; } view(index) { return this.viewSlot.children[index]; } addView(bindingContext, overrideContext) { let view = this.viewFactory.create(); view.bind(bindingContext, overrideContext); this.viewSlot.add(view); } insertView(index, bindingContext, overrideContext) { let view = this.viewFactory.create(); view.bind(bindingContext, overrideContext); this.viewSlot.insert(index, view); } removeAllViews(returnToCache, skipAnimation) { return this.viewSlot.removeAll(returnToCache, skipAnimation); } removeView(index, returnToCache, skipAnimation) { return this.viewSlot.removeAt(index, returnToCache, skipAnimation); } updateBindings(view) { let j = view.bindings.length; while (j--) { updateOneTimeBinding(view.bindings[j]); } j = view.controllers.length; while (j--) { let k = view.controllers[j].boundProperties.length; while (k--) { let binding = view.controllers[j].boundProperties[k].binding; updateOneTimeBinding(binding); } } } }, (_descriptor = _applyDecoratedDescriptor(_class2.prototype, 'items', [bindable], { enumerable: true, initializer: null }), _descriptor2 = _applyDecoratedDescriptor(_class2.prototype, 'local', [bindable], { enumerable: true, initializer: null })), _class2)) || _class) || _class) || _class);
var If = (function () { function If(viewFactory, viewSlot, taskQueue) { _classCallCheck(this, _If); this.viewFactory = viewFactory; this.viewSlot = viewSlot; this.showing = false; this.taskQueue = taskQueue; this.view = null; this.bindingContext = null; this.overrideContext = null; } If.prototype.bind = function bind(bindingContext, overrideContext) { this.bindingContext = bindingContext; this.overrideContext = overrideContext; this.valueChanged(this.value); }; If.prototype.valueChanged = function valueChanged(newValue) { var _this = this; if (!newValue) { if (this.view !== null && this.showing) { this.taskQueue.queueMicroTask(function () { var viewOrPromise = _this.viewSlot.remove(_this.view); if (viewOrPromise instanceof Promise) { viewOrPromise.then(function () { return _this.view.unbind(); }); } else { _this.view.unbind(); } }); } this.showing = false; return; } if (this.view === null) { this.view = this.viewFactory.create(); } if (!this.view.isBound) { this.view.bind(this.bindingContext, this.overrideContext); } if (!this.showing) { this.showing = true; this.viewSlot.add(this.view); } }; If.prototype.unbind = function unbind() { 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); } this.view.returnToCache(); this.view = null; }; var _If = If; If = _aureliaDependencyInjection.inject(_aureliaTemplating.BoundViewFactory, _aureliaTemplating.ViewSlot, _aureliaTaskQueue.TaskQueue)(If) || If; If = _aureliaTemplating.templateController(If) || If; If = _aureliaTemplating.customAttribute('if')(If) || If; return If; })();