diff --git a/cosmoz-data-nav.js b/cosmoz-data-nav.js index 3b52746..7fa3ec1 100644 --- a/cosmoz-data-nav.js +++ b/cosmoz-data-nav.js @@ -240,6 +240,7 @@ constructor() { super(); + this._previouslySelectedItem = null; this._cache = {}; this._preloadIdx = 0; this._boundOnTemplatesChange = this._onTemplatesChange.bind(this); @@ -268,6 +269,7 @@ this._selectDebouncer.cancel(); } + this._previouslySelectedItem = null; this._cache = {}; this._indexRenderQueue = []; window.removeEventListener('cosmoz-cache-purge', this._onCachePurgeHandler); @@ -445,10 +447,11 @@ _itemsChanged(items) { const length = items && items.length; - //Update readOnly queueLength + // update read-only properties this._setQueueLength(length >> 0); this._setHasItems(!!length); + // replace incomplete items with cached item data if (length) { items.forEach((item, index) => { if (this.isIncompleteFn(item) && this._cache[item]) { @@ -457,22 +460,31 @@ }); } + // synchronize `selected` with hash params if (this._updateSelectedFromHash()) { return; } + // reset queue to 0 or maintain selection let index = 0; - if (this.maintainSelection && this.selected > 0) { - const selectedId = this._getItemId(this.selectedItem); - index = Math.max(0, items.findIndex(item => this._getItemId(item) === selectedId)); - } + if (this.maintainSelection && this._previouslySelectedItem != null) { + // search for previously selected item by reference + index = items.indexOf(this._previouslySelectedItem); + + // if not found, search by id + if (index === -1) { + const prevId = this._getItemId(this._previouslySelectedItem); + index = items.findIndex(item => this._getItemId(item) === prevId); + } - if (this.selected === index) { - return this._updateSelected(); + // if still not found, remain on the selected index, but force re-render + if (index === -1) { + return this._updateSelected(); + } } - this.selected = index; - + // update selected or force re-render if selected did not change + return this.selected === index ? this._updateSelected() : this.selected = index; } /** @@ -487,6 +499,7 @@ const position = selected < this.items.length ? selected : selected - 1; this._setSelectedNext((position || 0) + 1); this._preload(position); + this._previouslySelectedItem = this.items[position]; const element = this._getElement(position); @@ -841,8 +854,8 @@ if (Polymer.flush) { Polymer.flush(); } - const instance = new this._elementCtor({}); - Object.assign(instance, { [this.as]: item }, this._getBaseProps(idx)); + const props = Object.assign({ [this.as]: item }, this._getBaseProps(idx)); + const instance = new this._elementCtor(props); element.__instance = instance; element.item = item; diff --git a/test/.eslintrc.json b/test/.eslintrc.json index 328c2ce..0c6b7b9 100644 --- a/test/.eslintrc.json +++ b/test/.eslintrc.json @@ -13,5 +13,8 @@ "MockInteractions": false, "sinon": true, "WCT": false + }, + "rules": { + "no-unused-expressions": "off" } } diff --git a/test/basic.html b/test/basic.html index 0984573..aa7ae92 100644 --- a/test/basic.html +++ b/test/basic.html @@ -339,10 +339,12 @@ assert.isTrue(nav.animating); assert.equal(nav.selected, 1); // wait for animation to end and check animating is false - nav.addEventListener('transitionend', () => { + const once = () => { + nav.removeEventListener('transitionend', once); assert.isFalse(nav.animating); done(); - }); + }; + nav.addEventListener('transitionend', once); }); }); diff --git a/test/helpers/utils.js b/test/helpers/utils.js new file mode 100644 index 0000000..99a62db --- /dev/null +++ b/test/helpers/utils.js @@ -0,0 +1,11 @@ +(() => { + const flushRenderQueue = nav => { + while (nav._indexRenderQueue.length) { + nav._renderQueue(); + } + }; + + Object.assign(window, { + flushRenderQueue + }); +})(); diff --git a/test/index.html b/test/index.html index 89aaea2..a5f016e 100644 --- a/test/index.html +++ b/test/index.html @@ -9,7 +9,8 @@ diff --git a/test/spec.html b/test/spec.html new file mode 100644 index 0000000..8de7fc6 --- /dev/null +++ b/test/spec.html @@ -0,0 +1,338 @@ + + + + + cosmoz-data-nav-basic + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +