diff --git a/toolkit/modules/SelectContentHelper.jsm b/toolkit/modules/SelectContentHelper.jsm index ae2d0a3ca009..9be94182e827 100644 --- a/toolkit/modules/SelectContentHelper.jsm +++ b/toolkit/modules/SelectContentHelper.jsm @@ -14,6 +14,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils", "resource://gre/modules/BrowserUtils.jsm"); XPCOMUtils.defineLazyServiceGetter(this, "DOMUtils", "@mozilla.org/inspector/dom-utils;1", "inIDOMUtils"); +XPCOMUtils.defineLazyModuleGetter(this, "DeferredTask", + "resource://gre/modules/DeferredTask.jsm"); const kStateHover = 0x00000004; // NS_EVENT_STATE_HOVER @@ -27,6 +29,7 @@ this.SelectContentHelper = function (aElement, aGlobal) { this.global = aGlobal; this.init(); this.showDropDown(); + this._updateTimer = new DeferredTask(this._update.bind(this), 0); } this.SelectContentHelper.prototype = { @@ -36,7 +39,14 @@ this.SelectContentHelper.prototype = { this.global.addMessageListener("Forms:MouseOver", this); this.global.addMessageListener("Forms:MouseOut", this); this.global.addEventListener("pagehide", this); - this.global.addEventListener("mozhidedropdown", this); + let MutationObserver = this.element.ownerDocument.defaultView.MutationObserver; + this.mut = new MutationObserver(mutations => { + // Something changed the was updated while the dropdown was open. + // Let's send up a new list of options. + this.global.sendAsyncMessage("Forms:UpdateDropDown", { + options: this._buildOptionList(), + selectedIndex: this.element.selectedIndex, + }); + }, + receiveMessage: function(message) { switch (message.name) { case "Forms:SelectDropDownItem": diff --git a/toolkit/modules/SelectParentHelper.jsm b/toolkit/modules/SelectParentHelper.jsm index 17691313f653..9ea58458c8c3 100644 --- a/toolkit/modules/SelectParentHelper.jsm +++ b/toolkit/modules/SelectParentHelper.jsm @@ -9,18 +9,22 @@ this.EXPORTED_SYMBOLS = [ ]; var currentBrowser = null; +var currentMenulist = null; +var currentZoom = 1; this.SelectParentHelper = { populate: function(menulist, items, selectedIndex, zoom) { // Clear the current contents of the popup menulist.menupopup.textContent = ""; + currentZoom = zoom; + currentMenulist = menulist; populateChildren(menulist, items, selectedIndex, zoom); }, open: function(browser, menulist, rect) { menulist.hidden = false; currentBrowser = browser; - this._registerListeners(menulist.menupopup); + this._registerListeners(browser, menulist.menupopup); menulist.menupopup.openPopupAtScreenRect("after_start", rect.left, rect.top, rect.width, rect.height, false, false); menulist.selectedItem.scrollIntoView(); @@ -52,26 +56,44 @@ this.SelectParentHelper = { case "popuphidden": currentBrowser.messageManager.sendAsyncMessage("Forms:DismissedDropDown", {}); - currentBrowser = null; let popup = event.target; - this._unregisterListeners(popup); + this._unregisterListeners(currentBrowser, popup); popup.parentNode.hidden = true; + currentBrowser = null; + currentMenulist = null; + currentZoom = 1; break; } }, - _registerListeners: function(popup) { + receiveMessage(msg) { + if (msg.name == "Forms:UpdateDropDown") { + // Sanity check - we'd better know what the currently + // opened menulist is, and what browser it belongs to... + if (!currentMenulist || !currentBrowser) { + return; + } + + let options = msg.data.options; + let selectedIndex = msg.data.selectedIndex; + this.populate(currentMenulist, options, selectedIndex, currentZoom); + } + }, + + _registerListeners: function(browser, popup) { popup.addEventListener("command", this); popup.addEventListener("popuphidden", this); popup.addEventListener("mouseover", this); popup.addEventListener("mouseout", this); + browser.messageManager.addMessageListener("Forms:UpdateDropDown", this); }, - _unregisterListeners: function(popup) { + _unregisterListeners: function(browser, popup) { popup.removeEventListener("command", this); popup.removeEventListener("popuphidden", this); popup.removeEventListener("mouseover", this); popup.removeEventListener("mouseout", this); + browser.messageManager.removeMessageListener("Forms:UpdateDropDown", this); }, };