Bug 1442377 - Move fillSubviewFromMenuItems/clearSubview to CustomizableUI.jsm. r?Gijs draft
authorMark Banner <standard8@mozilla.com>
Thu, 01 Mar 2018 19:53:07 +0000
changeset 762078 4e624daf9bfb005fc7187c097a604310fb27c104
parent 761787 e33efdb3e1517d521deb949de3fcd6d9946ea440
child 762088 f55f67f1966746ffa159fb73bdb1442ed52c12a6
push id101076
push userbmo:standard8@mozilla.com
push dateThu, 01 Mar 2018 19:53:50 +0000
reviewersGijs
bugs1442377
milestone60.0a1
Bug 1442377 - Move fillSubviewFromMenuItems/clearSubview to CustomizableUI.jsm. r?Gijs MozReview-Commit-ID: BQ8V39C68WO
browser/components/customizableui/CustomizableUI.jsm
browser/components/customizableui/CustomizableWidgets.jsm
devtools/shim/devtools-startup.js
--- a/browser/components/customizableui/CustomizableUI.jsm
+++ b/browser/components/customizableui/CustomizableUI.jsm
@@ -3895,16 +3895,96 @@ var CustomizableUI = {
   /**
    * Create an instance of a spring, spacer or separator.
    * @param aId       the type of special widget (spring, spacer or separator)
    * @param aDocument the document in which to create it.
    */
   createSpecialWidget(aId, aDocument) {
     return CustomizableUIInternal.createSpecialWidget(aId, aDocument);
   },
+
+  /**
+   * Fills a submenu with menu items.
+   * @param aMenuItems the menu items to display.
+   * @param aSubview   the subview to fill.
+   */
+  fillSubviewFromMenuItems(aMenuItems, aSubview) {
+    let attrs = ["oncommand", "onclick", "label", "key", "disabled",
+                 "command", "observes", "hidden", "class", "origin",
+                 "image", "checked", "style"];
+
+    let doc = aSubview.ownerDocument;
+    let fragment = doc.createDocumentFragment();
+    for (let menuChild of aMenuItems) {
+      if (menuChild.hidden)
+        continue;
+
+      let subviewItem;
+      if (menuChild.localName == "menuseparator") {
+        // Don't insert duplicate or leading separators. This can happen if there are
+        // menus (which we don't copy) above the separator.
+        if (!fragment.lastChild || fragment.lastChild.localName == "menuseparator") {
+          continue;
+        }
+        subviewItem = doc.createElementNS(kNSXUL, "menuseparator");
+      } else if (menuChild.localName == "menuitem") {
+        subviewItem = doc.createElementNS(kNSXUL, "toolbarbutton");
+        CustomizableUI.addShortcut(menuChild, subviewItem);
+
+        let item = menuChild;
+        if (!item.hasAttribute("onclick")) {
+          subviewItem.addEventListener("click", event => {
+            let newEvent = new doc.defaultView.MouseEvent(event.type, event);
+            item.dispatchEvent(newEvent);
+          });
+        }
+
+        if (!item.hasAttribute("oncommand")) {
+          subviewItem.addEventListener("command", event => {
+            let newEvent = doc.createEvent("XULCommandEvent");
+            newEvent.initCommandEvent(
+              event.type, event.bubbles, event.cancelable, event.view,
+              event.detail, event.ctrlKey, event.altKey, event.shiftKey,
+              event.metaKey, event.sourceEvent, 0);
+            item.dispatchEvent(newEvent);
+          });
+        }
+      } else {
+        continue;
+      }
+      for (let attr of attrs) {
+        let attrVal = menuChild.getAttribute(attr);
+        if (attrVal)
+          subviewItem.setAttribute(attr, attrVal);
+      }
+      // We do this after so the .subviewbutton class doesn't get overriden.
+      if (menuChild.localName == "menuitem") {
+        subviewItem.classList.add("subviewbutton");
+      }
+      fragment.appendChild(subviewItem);
+    }
+    aSubview.appendChild(fragment);
+  },
+
+  /**
+   * A helper function for clearing subviews.
+   * @param aSubview the subview to clear.
+   */
+  clearSubview(aSubview) {
+    let parent = aSubview.parentNode;
+    // We'll take the container out of the document before cleaning it out
+    // to avoid reflowing each time we remove something.
+    parent.removeChild(aSubview);
+
+    while (aSubview.firstChild) {
+      aSubview.firstChild.remove();
+    }
+
+    parent.appendChild(aSubview);
+  },
 };
 Object.freeze(this.CustomizableUI);
 Object.freeze(this.CustomizableUI.windows);
 
 /**
  * All external consumers of widgets are really interacting with these wrappers
  * which provide a common interface.
  */
--- a/browser/components/customizableui/CustomizableWidgets.jsm
+++ b/browser/components/customizableui/CustomizableWidgets.jsm
@@ -70,87 +70,16 @@ function setAttributes(aNode, aAttrs) {
         }
         value = CustomizableUI.getLocalizedProperty({id: aAttrs.id}, stringId, additionalArgs);
       }
       aNode.setAttribute(name, value);
     }
   }
 }
 
-function fillSubviewFromMenuItems(aMenuItems, aSubview) {
-  let attrs = ["oncommand", "onclick", "label", "key", "disabled",
-               "command", "observes", "hidden", "class", "origin",
-               "image", "checked", "style"];
-
-  let doc = aSubview.ownerDocument;
-  let fragment = doc.createDocumentFragment();
-  for (let menuChild of aMenuItems) {
-    if (menuChild.hidden)
-      continue;
-
-    let subviewItem;
-    if (menuChild.localName == "menuseparator") {
-      // Don't insert duplicate or leading separators. This can happen if there are
-      // menus (which we don't copy) above the separator.
-      if (!fragment.lastChild || fragment.lastChild.localName == "menuseparator") {
-        continue;
-      }
-      subviewItem = doc.createElementNS(kNSXUL, "menuseparator");
-    } else if (menuChild.localName == "menuitem") {
-      subviewItem = doc.createElementNS(kNSXUL, "toolbarbutton");
-      CustomizableUI.addShortcut(menuChild, subviewItem);
-
-      let item = menuChild;
-      if (!item.hasAttribute("onclick")) {
-        subviewItem.addEventListener("click", event => {
-          let newEvent = new doc.defaultView.MouseEvent(event.type, event);
-          item.dispatchEvent(newEvent);
-        });
-      }
-
-      if (!item.hasAttribute("oncommand")) {
-        subviewItem.addEventListener("command", event => {
-          let newEvent = doc.createEvent("XULCommandEvent");
-          newEvent.initCommandEvent(
-            event.type, event.bubbles, event.cancelable, event.view,
-            event.detail, event.ctrlKey, event.altKey, event.shiftKey,
-            event.metaKey, event.sourceEvent, 0);
-          item.dispatchEvent(newEvent);
-        });
-      }
-    } else {
-      continue;
-    }
-    for (let attr of attrs) {
-      let attrVal = menuChild.getAttribute(attr);
-      if (attrVal)
-        subviewItem.setAttribute(attr, attrVal);
-    }
-    // We do this after so the .subviewbutton class doesn't get overriden.
-    if (menuChild.localName == "menuitem") {
-      subviewItem.classList.add("subviewbutton");
-    }
-    fragment.appendChild(subviewItem);
-  }
-  aSubview.appendChild(fragment);
-}
-
-function clearSubview(aSubview) {
-  let parent = aSubview.parentNode;
-  // We'll take the container out of the document before cleaning it out
-  // to avoid reflowing each time we remove something.
-  parent.removeChild(aSubview);
-
-  while (aSubview.firstChild) {
-    aSubview.firstChild.remove();
-  }
-
-  parent.appendChild(aSubview);
-}
-
 const CustomizableWidgets = [
   {
     id: "history-panelmenu",
     type: "view",
     viewId: "PanelUI-history",
     shortcutId: "key_gotoHistory",
     tooltiptext: "history-panelmenu.tooltiptext2",
     recentlyClosedTabsPanel: "appMenu-library-recentlyClosedTabs",
--- a/devtools/shim/devtools-startup.js
+++ b/devtools/shim/devtools-startup.js
@@ -392,21 +392,18 @@ DevToolsStartup.prototype = {
         let menu = doc.getElementById("menuWebDeveloperPopup");
 
         let itemsToDisplay = [...menu.children];
         // Hardcode the addition of the "work offline" menuitem at the bottom:
         itemsToDisplay.push({localName: "menuseparator", getAttribute: () => {}});
         itemsToDisplay.push(doc.getElementById("goOfflineMenuitem"));
 
         let developerItems = doc.getElementById("PanelUI-developerItems");
-        // Import private helpers from CustomizableWidgets
-        let { clearSubview, fillSubviewFromMenuItems } =
-          ChromeUtils.import("resource:///modules/CustomizableWidgets.jsm", {});
-        clearSubview(developerItems);
-        fillSubviewFromMenuItems(itemsToDisplay, developerItems);
+        CustomizableUI.clearSubview(developerItems);
+        CustomizableUI.fillSubviewFromMenuItems(itemsToDisplay, developerItems);
       },
       onInit(anchor) {
         // Since onBeforeCreated already bails out when initialized, we can call
         // it right away.
         this.onBeforeCreated(anchor.ownerDocument);
       },
       onBeforeCreated: (doc) => {
         // The developer toggle needs the "key_toggleToolbox" <key> element.