From fdac0321d0f6f435e5f9652271b98842fdddc3a7 Mon Sep 17 00:00:00 2001 From: Ray Lin Date: Tue, 24 Jan 2017 23:32:36 +0800 Subject: [PATCH] Bug 1326138 - Refactor _appendCurrentResult to be more generic. r=adw MozReview-Commit-ID: LTDVtiOYbx6 --HG-- extra : rebase_source : 9d1efc92a18fdb00d82d1056a78aff2108cc0313 --- toolkit/content/widgets/autocomplete.xml | 170 +++++++++++++++-------- 1 file changed, 115 insertions(+), 55 deletions(-) diff --git a/toolkit/content/widgets/autocomplete.xml b/toolkit/content/widgets/autocomplete.xml index 837fcdfb9b16..d393341b453a 100644 --- a/toolkit/content/widgets/autocomplete.xml +++ b/toolkit/content/widgets/autocomplete.xml @@ -1304,66 +1304,66 @@ extends="chrome://global/content/bindings/popup.xml#popup"> // Process maxRows per chunk to improve performance and user experience for (let i = 0; i < this.maxRows; i++) { - if (this._currentIndex >= matchCount) + if (this._currentIndex >= matchCount) { break; + } + let item; + let reusable = false; + let itemExists = this._currentIndex < existingItemsCount; - var item; - + let originalValue, originalText; + let value = controller.getValueAt(this._currentIndex); + let label = controller.getLabelAt(this._currentIndex); + let comment = controller.getCommentAt(this._currentIndex); + let style = controller.getStyleAt(this._currentIndex); + let image = controller.getImageAt(this._currentIndex); // trim the leading/trailing whitespace - var trimmedSearchString = controller.searchString.replace(/^\s+/, "").replace(/\s+$/, ""); + let trimmedSearchString = controller.searchString.replace(/^\s+/, "").replace(/\s+$/, ""); - let url = controller.getValueAt(this._currentIndex); - - if (this._currentIndex < existingItemsCount) { - // re-use the existing item + if (itemExists) { item = this.richlistbox.childNodes[this._currentIndex]; - item.setAttribute("dir", this.style.direction); - // Completely reuse the existing richlistitem for invalidation - // due to new results, but only when: the item is the same, *OR* - // we are about to replace the currently mouse-selected item, to - // avoid surprising the user. - let iface = Components.interfaces.nsIAutoCompletePopup; - if (item.getAttribute("text") == trimmedSearchString && - invalidateReason == iface.INVALIDATE_REASON_NEW_RESULT && - (item.getAttribute("url") == url || - this.richlistbox.mouseSelectedIndex === this._currentIndex)) { - // Additionally, if the item is a searchengine action, then it - // should only be reused if the engine name is the same as the - // popup's override engine name, if any. - let action = item._parseActionUrl(url); - if (!action || - action.type != "searchengine" || - !this.overrideSearchEngineName || - action.params.engineName == this.overrideSearchEngineName) { - item.collapsed = false; - // Call adjustSiteIconStart only after setting collapsed= - // false. The calculations it does may be wrong otherwise. - item.adjustSiteIconStart(this._siteIconStart); - // The popup may have changed size between now and the last - // time the item was shown, so always handle over/underflow. - item.handleOverUnderflow(); - this._currentIndex++; - continue; - } - } + originalValue = item.getAttribute("ac-value"); + originalText = item.getAttribute("ac-text"); + + reusable = item.getAttribute("originaltype") === style; } else { // need to create a new item item = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "richlistitem"); - item.setAttribute("dir", this.style.direction); } - // set these attributes before we set the class - // so that we can use them from the constructor - let iconURI = controller.getImageAt(this._currentIndex); - item.setAttribute("image", iconURI); - item.setAttribute("url", url); - item.setAttribute("title", controller.getCommentAt(this._currentIndex)); - item.setAttribute("originaltype", controller.getStyleAt(this._currentIndex)); - item.setAttribute("text", trimmedSearchString); + item.setAttribute("dir", this.style.direction); + item.setAttribute("ac-image", image); + item.setAttribute("ac-value", value); + item.setAttribute("ac-comment", comment); + item.setAttribute("ac-text", trimmedSearchString); - if (this._currentIndex < existingItemsCount) { - // re-use the existing item + // Completely reuse the existing richlistitem for invalidation + // due to new results, but only when: the item is the same, *OR* + // we are about to replace the currently mouse-selected item, to + // avoid surprising the user. + let iface = Components.interfaces.nsIAutoCompletePopup; + if (reusable && + originalText == trimmedSearchString && + invalidateReason == iface.INVALIDATE_REASON_NEW_RESULT && + (originalValue == value || + this.richlistbox.mouseSelectedIndex === this._currentIndex)) { + + // try to re-use the existing item + let reused = item._reuseAcItem(); + if (reused) { + this._currentIndex++; + continue; + } + } else { + if (typeof item._cleanup == "function") { + item._cleanup(); + } + + item.setAttribute("originaltype", style); + } + + if (itemExists) { item._adjustAcItem(); item.collapsed = false; } else { @@ -1373,13 +1373,12 @@ extends="chrome://global/content/bindings/popup.xml#popup"> this.richlistbox.appendChild(item); } - // The binding may have not been applied yet. - setTimeout(() => { - let changed = item.adjustSiteIconStart(this._siteIconStart); - if (changed) { - item.handleOverUnderflow(); - } - }, 0); + if (typeof item.onChanged == "function") { + // The binding may have not been applied yet. + setTimeout(() => { + item.onChanged(); + }, 0); + } this._currentIndex++; } @@ -1646,6 +1645,18 @@ extends="chrome://global/content/bindings/popup.xml#popup"> ]]> + + + + + + + + + + + + + + + + + + + +