Bug 1459556 - Part 3 - Remove the "handlers" binding. r=bgrins
MozReview-Commit-ID: GOUOKuoR1rs
--- a/browser/components/preferences/handlers.css
+++ b/browser/components/preferences/handlers.css
@@ -1,16 +1,12 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#handlersView > richlistitem {
- -moz-binding: url("chrome://browser/content/preferences/handlers.xml#handler");
-}
-
#containersView > richlistitem {
-moz-binding: none;
}
/**
* Make the icons appear.
* Note: we display the icon box for every item whether or not it has an icon
* so the labels of all the items align vertically.
deleted file mode 100644
--- a/browser/components/preferences/handlers.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<!-- import-globals-from in-content/main.js -->
-
-<bindings id="handlerBindings"
- xmlns="http://www.mozilla.org/xbl"
- xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:xbl="http://www.mozilla.org/xbl">
-
- <binding id="handler" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
- <content>
- <!-- This has been copied to "main.js" -->
- <xul:hbox flex="1" equalsize="always">
- <xul:hbox flex="1" align="center" xbl:inherits="tooltiptext=typeDescription">
- <xul:image src="moz-icon://goat?size=16" class="typeIcon"
- xbl:inherits="src=typeIcon" height="16" width="16"/>
- <xul:label flex="1" crop="end" xbl:inherits="value=typeDescription"/>
- </xul:hbox>
- <xul:hbox anonid="not-selected" flex="1" align="center" xbl:inherits="tooltiptext=actionDescription">
- <xul:image xbl:inherits="src=actionIcon" height="16" width="16" class="actionIcon"/>
- <xul:label flex="1" crop="end" xbl:inherits="value=actionDescription"/>
- </xul:hbox>
- <xul:hbox hidden="true" anonid="selected" flex="1">
- <xul:menulist class="actionsMenu" flex="1" crop="end" selectedIndex="1"
- xbl:inherits="tooltiptext=actionDescription"
- oncommand="gMainPane.onSelectAction(event.originalTarget)">
- <xul:menupopup/>
- </xul:menulist>
- </xul:hbox>
- </xul:hbox>
- </content>
- </binding>
-
-</bindings>
--- a/browser/components/preferences/in-content/main.js
+++ b/browser/components/preferences/in-content/main.js
@@ -1537,18 +1537,17 @@ var gMainPane = {
var visibleTypes = this._visibleTypes;
// If the user is filtering the list, then only show matching types.
if (this._filter.value)
visibleTypes = visibleTypes.filter(this._matchesFilter, this);
for (let visibleType of visibleTypes) {
- let item = new HandlerListItem(visibleType);
- this._list.appendChild(item.node);
+ let item = new HandlerListItem(visibleType, this._list);
if (visibleType.type === lastSelectedType) {
this._list.selectedItem = item.node;
}
}
},
_matchesFilter(aType) {
@@ -1603,18 +1602,17 @@ var gMainPane = {
/**
* Rebuild the actions menu for the selected entry. Gets called by
* the richlistitem constructor when an entry in the list gets selected.
*/
rebuildActionsMenu() {
var typeItem = this._list.selectedItem;
var handlerInfo = this.selectedHandlerListItem.handlerInfoWrapper;
- var menu =
- document.getAnonymousElementByAttribute(typeItem, "class", "actionsMenu");
+ var menu = typeItem.querySelector("[class=actionsMenu]");
var menuPopup = menu.menupopup;
// Clear out existing items.
while (menuPopup.hasChildNodes())
menuPopup.removeChild(menuPopup.lastChild);
let internalMenuItem;
@@ -1998,18 +1996,17 @@ var gMainPane = {
// Rebuild the actions menu whether the user picked an app or canceled.
// If they picked an app, we want to add the app to the menu and select it.
// If they canceled, we want to go back to their previous selection.
this.rebuildActionsMenu();
// If the user picked a new app from the menu, select it.
if (aHandlerApp) {
let typeItem = this._list.selectedItem;
- let actionsMenu =
- document.getAnonymousElementByAttribute(typeItem, "class", "actionsMenu");
+ let actionsMenu = typeItem.querySelector("[class=actionsMenu]");
let menuItems = actionsMenu.menupopup.childNodes;
for (let i = 0; i < menuItems.length; i++) {
let menuItem = menuItems[i];
if (menuItem.handlerApp && menuItem.handlerApp.equals(aHandlerApp)) {
actionsMenu.selectedIndex = i;
this.onSelectAction(menuItem);
break;
}
@@ -2443,79 +2440,110 @@ ArrayEnumerator.prototype = {
return this._contents[this._index++];
}
};
function isFeedType(t) {
return t == TYPE_MAYBE_FEED || t == TYPE_MAYBE_VIDEO_FEED || t == TYPE_MAYBE_AUDIO_FEED;
}
+// Helper function needed to create a DOM that will still get XBL attached
+// when accessing DOM nodes. This is needed because:
+// If you do something like `textbox = document.createElement("textbox")`,
+// then `textbox` won't have a XBL binding attached, since the JS reflector
+// gets created before it's in the document. This is usually fine, since
+// the textbox will get a binding attached after layout, but if the
+// parent node is hidden, then the textbox never will get it.
+// Using this function, we append the elements into the DOM before accessing
+// them directly from JS, so the constructor will run eagerly on the next
+// JS access once it's appended into the parent.
+function parseDOM(str) {
+ const d = new DOMParser();
+ d.forceEnableXULXBL();
+ const doc = d.parseFromString(`
+ <box xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ ${str.replace(/>\s+</g, "><")}
+ </box>
+ `, "application/xml");
+ const range = doc.createRange();
+ range.selectNodeContents(doc.firstChild);
+ return range.extractContents();
+}
+
+let gHandlerListItemFragment = parseDOM(`
+ <xul:richlistitem>
+ <xul:hbox flex="1" equalsize="always">
+ <xul:hbox flex="1" align="center" inherits="tooltiptext=typeDescription">
+ <xul:image src="moz-icon://goat?size=16" class="typeIcon"
+ inherits="src=typeIcon" height="16" width="16"/>
+ <xul:label flex="1" crop="end" inherits="value=typeDescription"/>
+ </xul:hbox>
+ <xul:hbox anonid="not-selected" flex="1" align="center" inherits="tooltiptext=actionDescription">
+ <xul:image inherits="src=actionIcon" height="16" width="16" class="actionIcon"/>
+ <xul:label flex="1" crop="end" inherits="value=actionDescription"/>
+ </xul:hbox>
+ <xul:hbox hidden="true" anonid="selected" flex="1">
+ <xul:menulist class="actionsMenu" flex="1" crop="end" selectedIndex="1"
+ inherits="tooltiptext=actionDescription">
+ <xul:menupopup/>
+ </xul:menulist>
+ </xul:hbox>
+ </xul:hbox>
+ </xul:richlistitem>
+`);
+
/**
* This is associated to <richlistitem> elements in the handlers view.
*/
class HandlerListItem {
static forNode(node) {
return gNodeToObjectMap.get(node);
}
- constructor(handlerInfoWrapper) {
+ constructor(handlerInfoWrapper, list) {
this.handlerInfoWrapper = handlerInfoWrapper;
- this.node = document.createElement("richlistitem");
- /*
- <xul:hbox flex="1" equalsize="always">
- <xul:hbox flex="1" align="center" xbl:inherits="tooltiptext=typeDescription">
- <xul:image src="moz-icon://goat?size=16" class="typeIcon"
- xbl:inherits="src=typeIcon" height="16" width="16"/>
- <xul:label flex="1" crop="end" xbl:inherits="value=typeDescription"/>
- </xul:hbox>
- <xul:hbox anonid="not-selected" flex="1" align="center" xbl:inherits="tooltiptext=actionDescription">
- <xul:image xbl:inherits="src=actionIcon" height="16" width="16" class="actionIcon"/>
- <xul:label flex="1" crop="end" xbl:inherits="value=actionDescription"/>
- </xul:hbox>
- <xul:hbox hidden="true" anonid="selected" flex="1">
- <xul:menulist class="actionsMenu" flex="1" crop="end" selectedIndex="1"
- xbl:inherits="tooltiptext=actionDescription"
- oncommand="gMainPane.onSelectAction(event.originalTarget)">
- <xul:menupopup/>
- </xul:menulist>
- </xul:hbox>
- </xul:hbox>
- */
+
+ list.appendChild(document.importNode(gHandlerListItemFragment, true));
+ this.node = list.lastElementChild;
gNodeToObjectMap.set(this.node, this);
+ this.node.querySelector('[class="actionsMenu"]').addEventListener("command",
+ event => gMainPane.onSelectAction(event.originalTarget));
+
this.node.setAttribute("type", this.handlerInfoWrapper.type);
- this.node.setAttribute("typeDescription",
- this.handlerInfoWrapper.typeDescription);
+ this.node.querySelector('[inherits="value=typeDescription"]')
+ .setAttribute("value", this.handlerInfoWrapper.typeDescription);
if (this.handlerInfoWrapper.smallIcon) {
- this.node.setAttribute("typeIcon", this.handlerInfoWrapper.smallIcon);
- } else {
- this.node.removeAttribute("typeIcon");
+ this.node.querySelector('[inherits="src=typeIcon"]')
+ .setAttribute("src", this.handlerInfoWrapper.smallIcon);
}
this.refreshAction();
}
refreshAction() {
- this.node.setAttribute("actionDescription",
- this.handlerInfoWrapper.actionDescription);
+ this.node.querySelector('[inherits="value=actionDescription"]')
+ .setAttribute("value", this.handlerInfoWrapper.actionDescription);
if (this.handlerInfoWrapper.actionIconClass) {
this.node.setAttribute(APP_ICON_ATTR_NAME,
this.handlerInfoWrapper.actionIconClass);
- this.node.removeAttribute("actionIcon");
+ this.node.querySelector('[inherits="src=actionIcon"]')
+ .removeAttribute("src");
} else {
this.node.removeAttribute(APP_ICON_ATTR_NAME);
- this.node.setAttribute("actionIcon", this.handlerInfoWrapper.actionIcon);
+ this.node.querySelector('[inherits="src=actionIcon"]')
+ .setAttribute("src", this.handlerInfoWrapper.actionIcon);
}
}
set showActionsMenu(value) {
- document.getAnonymousElementByAttribute(this.node, "anonid", "selected")
- .setAttribute("hidden", !value);
- document.getAnonymousElementByAttribute(this.node, "anonid", "not-selected")
- .setAttribute("hidden", !!value);
+ this.node.querySelector('[anonid="selected"]')
+ .setAttribute("hidden", !value);
+ this.node.querySelector('[anonid="not-selected"]')
+ .setAttribute("hidden", !!value);
}
}
/**
* This object wraps nsIHandlerInfo with some additional functionality
* the Applications prefpane needs to display and allow modification of
* the list of handled types.
*
--- a/browser/components/preferences/jar.mn
+++ b/browser/components/preferences/jar.mn
@@ -11,17 +11,16 @@ browser.jar:
content/browser/preferences/clearSiteData.js
content/browser/preferences/clearSiteData.xul
* content/browser/preferences/colors.xul
content/browser/preferences/colors.js
content/browser/preferences/connection.xul
content/browser/preferences/connection.js
content/browser/preferences/fonts.xul
content/browser/preferences/fonts.js
- content/browser/preferences/handlers.xml
content/browser/preferences/handlers.css
content/browser/preferences/languages.xul
content/browser/preferences/languages.js
content/browser/preferences/permissions.xul
content/browser/preferences/sitePermissions.xul
content/browser/preferences/sitePermissions.js
content/browser/preferences/sitePermissions.css
content/browser/preferences/containers.xul