Uninstall events (#191)

* Move event handlers to a handleEvent function to simplify removal, Remove event handlers to remove uninstall issue. Fixes #182

* Neatening up element and tooltip caches to reduce duplication in add button config and shutdown.

* Simplify further using Maps to remove string key
This commit is contained in:
Jonathan Kingston 2017-02-16 16:17:50 +00:00 committed by GitHub
parent 82d051c858
commit a4ca6a7742

150
index.js
View file

@ -865,15 +865,17 @@ ContainerWindow.prototype = {
_style: null, _style: null,
_panelElement: null, _panelElement: null,
_timeoutId: 0, _timeoutId: 0,
_fileMenuElements: [], _elementCache: new Map(),
_contextMenuElements: [], _tooltipCache: new Map(),
_plusButtonElements: [], _plusButton: null,
_plusButtonTooltip: "", _overflowPlusButton: null,
_overflowPlusButtonElements: [], _tabsElement: null,
_overflowPlusButtonTooltip: "",
_init(window) { _init(window) {
this._window = window; this._window = window;
this._tabsElement = this._window.document.getElementById("tabbrowser-tabs");
this._plusButton = this._window.document.getAnonymousElementByAttribute(this._tabsElement, "anonid", "tabs-newtab-button");
this._overflowPlusButton = this._window.document.getElementById("new-tab-button");
this._style = Style({ uri: self.data.url("usercontext.css") }); this._style = Style({ uri: self.data.url("usercontext.css") });
attachTo(this._style, this._window); attachTo(this._style, this._window);
}, },
@ -888,22 +890,47 @@ ContainerWindow.prototype = {
]); ]);
}, },
_configurePlusButtonMenu() { handleEvent(e) {
const tabsElement = this._window.document.getElementById("tabbrowser-tabs"); let el = e.target;
switch (e.type) {
case "mouseover":
this.showPopup(el);
break;
case "click":
this.hidePanel();
break;
case "mouseout":
while(el) {
if (el === this._panelElement ||
el === this._plusButton ||
el === this._overflowPlusButton) {
this._createTimeout();
return;
}
el = el.parentElement;
}
break;
}
},
const mainPopupSetElement = this._window.document.getElementById("mainPopupSet"); showPopup(buttonElement) {
const button = this._window.document.getAnonymousElementByAttribute(tabsElement, "anonid", "tabs-newtab-button"); this._cleanTimeout();
this._disableElement(button, "_plusButtonElements"); this._panelElement.openPopup(buttonElement);
},
const overflowButton = this._window.document.getElementById("new-tab-button");
this._disableElement(overflowButton, "_overflowPlusButtonElements");
_configurePlusButtonMenuElement(buttonElement) {
// Let's remove the tooltip because it can go over our panel. // Let's remove the tooltip because it can go over our panel.
this._plusButtonTooltip = button.getAttribute("tooltip"); this._tooltipCache.set(buttonElement, buttonElement.getAttribute("tooltip"));
button.setAttribute("tooltip", ""); buttonElement.setAttribute("tooltip", "");
this._disableElement(buttonElement);
this._overflowPlusButtonTooltip = overflowButton.getAttribute("tooltip"); buttonElement.addEventListener("mouseover", this);
overflowButton.setAttribute("tooltip", ""); buttonElement.addEventListener("click", this);
buttonElement.addEventListener("mouseout", this);
},
_configurePlusButtonMenu() {
const mainPopupSetElement = this._window.document.getElementById("mainPopupSet");
// Let's remove all the previous panels. // Let's remove all the previous panels.
if (this._panelElement) { if (this._panelElement) {
@ -920,35 +947,10 @@ ContainerWindow.prototype = {
this._panelElement.setAttribute("consumeoutsideclicks", "never"); this._panelElement.setAttribute("consumeoutsideclicks", "never");
mainPopupSetElement.appendChild(this._panelElement); mainPopupSetElement.appendChild(this._panelElement);
const showPopup = (buttonElement) => { this._configurePlusButtonMenuElement(this._plusButton);
this._cleanTimeout(); this._configurePlusButtonMenuElement(this._overflowPlusButton);
this._panelElement.openPopup(buttonElement);
};
const mouseoutHandle = (e) => { this._panelElement.addEventListener("mouseout", this);
let el = e.target;
while(el) {
if (el === this._panelElement ||
el === button ||
el === overflowButton) {
this._createTimeout();
return;
}
el = el.parentElement;
}
};
[button, overflowButton].forEach((buttonElement) => {
buttonElement.addEventListener("mouseover", () => {
showPopup(buttonElement);
});
buttonElement.addEventListener("click", () => {
this.hidePanel();
});
buttonElement.addEventListener("mouseout", mouseoutHandle);
});
this._panelElement.addEventListener("mouseout", mouseoutHandle);
this._panelElement.addEventListener("mouseover", () => { this._panelElement.addEventListener("mouseover", () => {
this._cleanTimeout(); this._cleanTimeout();
@ -976,7 +978,7 @@ ContainerWindow.prototype = {
this._cleanTimeout(); this._cleanTimeout();
}); });
menuItemElement.addEventListener("mouseout", mouseoutHandle); menuItemElement.addEventListener("mouseout", this);
this._panelElement.appendChild(menuItemElement); this._panelElement.appendChild(menuItemElement);
}); });
@ -1005,7 +1007,7 @@ ContainerWindow.prototype = {
userContextId: userContextId, userContextId: userContextId,
source: "file-menu" source: "file-menu"
}); });
}, "_fileMenuElements"); });
}, },
_configureContextMenu() { _configureContextMenu() {
@ -1019,16 +1021,15 @@ ContainerWindow.prototype = {
// This is a super internal method. Hopefully it will be stable in the // This is a super internal method. Hopefully it will be stable in the
// next FF releases. // next FF releases.
this._window.gContextMenu.openLinkInTab(e); this._window.gContextMenu.openLinkInTab(e);
}, }
"_contextMenuElements"
); );
}, },
// Generic menu configuration. // Generic menu configuration.
_configureMenu(menuId, excludedContainerCb, clickCb, arrayName) { _configureMenu(menuId, excludedContainerCb, clickCb) {
const menu = this._window.document.getElementById(menuId); const menu = this._window.document.getElementById(menuId);
this._disableElement(menu, arrayName); this._disableElement(menu);
if (!this._disableElement(menu, arrayName)) { if (!this._disableElement(menu)) {
// Delete stale menu that isn't native elements // Delete stale menu that isn't native elements
while (menu.firstChild) { while (menu.firstChild) {
menu.removeChild(menu.firstChild); menu.removeChild(menu.firstChild);
@ -1118,54 +1119,61 @@ ContainerWindow.prototype = {
this._shutdownContextMenu(); this._shutdownContextMenu();
}, },
_shutdownPlusButtonMenu() { _shutDownPlusButtonMenuElement(buttonElement) {
const tabsElement = this._window.document.getElementById("tabbrowser-tabs"); this._shutdownElement(buttonElement);
const button = this._window.document.getAnonymousElementByAttribute(tabsElement, "anonid", "tabs-newtab-button"); buttonElement.setAttribute("tooltip", this._tooltipCache.get(buttonElement));
this._shutdownElement(button, "_plusButtonElements");
button.setAttribute("tooltip", this._plusButtonTooltip);
const overflowButton = this._window.document.getElementById("new-tab-button"); buttonElement.removeEventListener("mouseover", this);
this._shutdownElement(overflowButton, "_overflowPlusButtonElements"); buttonElement.removeEventListener("click", this);
overflowButton.setAttribute("tooltip", this._overflowPlusButtonTooltip); buttonElement.removeEventListener("mouseout", this);
},
_shutdownPlusButtonMenu() {
this._shutDownPlusButtonMenuElement(this._plusButton);
this._shutDownPlusButtonMenuElement(this._overflowPlusButton);
}, },
_shutdownFileMenu() { _shutdownFileMenu() {
this._shutdownMenu("menu_newUserContext", "_fileMenuElements"); this._shutdownMenu("menu_newUserContext");
}, },
_shutdownContextMenu() { _shutdownContextMenu() {
this._shutdownMenu("context-openlinkinusercontext-menu", this._shutdownMenu("context-openlinkinusercontext-menu");
"_contextMenuElements");
}, },
_shutdownMenu(menuId, arrayName) { _shutdownMenu(menuId) {
const menu = this._window.document.getElementById(menuId); const menu = this._window.document.getElementById(menuId);
this._shutdownElement(menu, arrayName); this._shutdownElement(menu);
}, },
_shutdownElement(element, arrayName) { _shutdownElement(element) {
// Let's remove our elements. // Let's remove our elements.
while (element.firstChild) { while (element.firstChild) {
element.firstChild.remove(); element.firstChild.remove();
} }
for (let e of this[arrayName]) { // eslint-disable-line prefer-const const elementCache = this._elementCache.get(element);
for (let e of elementCache) { // eslint-disable-line prefer-const
element.appendChild(e); element.appendChild(e);
} }
}, },
_disableElement(element, arrayName) { _disableElement(element) {
// Nothing to disable. // Nothing to disable.
if (!element || this[arrayName].length) { if (!element || this._elementCache.has(element)) {
return false; return false;
} }
const cacheArray = [];
// Let's store the previous elements so that we can repopulate it in case // Let's store the previous elements so that we can repopulate it in case
// the addon is uninstalled. // the addon is uninstalled.
while (element.firstChild) { while (element.firstChild) {
this[arrayName].push(element.removeChild(element.firstChild)); cacheArray.push(element.removeChild(element.firstChild));
} }
this._elementCache.set(element, cacheArray);
return true; return true;
}, },
}; };