Bug 733612 - Add a pseudo-class lock menu to the infobar node menu. r=paul
authorHeather Arthur <fayearthur@gmail.com>
Tue, 17 Apr 2012 14:25:05 +0100
changeset 95147 0ba7e290a08ff754cb49e26b82da6a50102054ad
parent 95146 b8b2b94ae5e5b545526b860f9818384195902f4d
child 95148 f95f46afce27e36177cff467933ed82582913a52
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspaul
bugs733612
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 733612 - Add a pseudo-class lock menu to the infobar node menu. r=paul
browser/devtools/highlighter/highlighter.jsm
browser/devtools/highlighter/test/Makefile.in
browser/devtools/highlighter/test/browser_inspector_pseudoClass_menu.js
--- a/browser/devtools/highlighter/highlighter.jsm
+++ b/browser/devtools/highlighter/highlighter.jsm
@@ -252,16 +252,17 @@ Highlighter.prototype = {
    * Notify that a pseudo-class lock was toggled on the highlighted element
    *
    * @param aPseudo - The pseudo-class to toggle, e.g. ":hover".
    */
   pseudoClassLockToggled: function Highlighter_pseudoClassLockToggled(aPseudo)
   {
     this.emitEvent("pseudoclasstoggled", [aPseudo]);
     this.updateInfobar();
+    this.moveInfobar();
   },
 
   /**
    * Update the highlighter size and position.
    */
   invalidateSize: function Highlighter_invalidateSize(aScroll)
   {
     let rect = null;
@@ -496,16 +497,30 @@ Highlighter.prototype = {
     nodemenu.className = "highlighter-nodeinfobar-button"
     nodemenu.setAttribute("tooltiptext",
                           this.strings.GetStringFromName("nodeMenu.tooltiptext"));
 
     let menu = this.chromeDoc.getElementById("inspector-node-popup");
     menu = menu.cloneNode(true);
     menu.id = "highlighter-node-menu";
 
+    let separator = this.chromeDoc.createElement("menuseparator");
+    menu.appendChild(separator);
+
+    menu.addEventListener("popupshowing", function() {
+      let items = menu.getElementsByClassName("highlighter-pseudo-class-menuitem");
+      let i = items.length;
+      while (i--) {
+        menu.removeChild(items[i]);
+      }
+
+      let fragment = this.buildPseudoClassMenu();
+      menu.appendChild(fragment);
+    }.bind(this), true);
+
     nodemenu.appendChild(menu);
 
     // <hbox id="highlighter-nodeinfobar-text"/>
     let texthbox = this.chromeDoc.createElement("hbox");
     texthbox.id = "highlighter-nodeinfobar-text";
     texthbox.setAttribute("align", "center");
     texthbox.setAttribute("flex", "1");
 
@@ -519,68 +534,47 @@ Highlighter.prototype = {
     nodeInfobar.appendChild(nodemenu);
 
     container.appendChild(arrowBoxTop);
     container.appendChild(nodeInfobar);
     container.appendChild(arrowBoxBottom);
 
     aParent.appendChild(container);
 
-    nodeInfobar.onclick = (function _onInfobarRightClick(aEvent) {
-      if (aEvent.button == 2) {
-        this.openPseudoClassMenu();
-      }
-    }).bind(this);
-
     let barHeight = container.getBoundingClientRect().height;
 
     this.nodeInfo = {
       tagNameLabel: tagNameLabel,
       idLabel: idLabel,
       classesBox: classesBox,
       pseudoClassesBox: pseudoClassesBox,
       container: container,
       barHeight: barHeight,
     };
   },
 
   /**
-   * Open the infobar's pseudo-class context menu.
-   */
-  openPseudoClassMenu: function Highlighter_openPseudoClassMenu()
-  {
-    let menu = this.chromeDoc.createElement("menupopup");
-    menu.id = "infobar-context-menu";
-
-    let popupSet = this.chromeDoc.getElementById("mainPopupSet");
-    popupSet.appendChild(menu);
-
-    let fragment = this.buildPseudoClassMenu();
-    menu.appendChild(fragment);
-
-    menu.openPopup(this.nodeInfo.pseudoClassesBox, "end_before", 0, 0, true, false);
-  },
-
-  /**
    * Create the menuitems for toggling the selection's pseudo-class state
    *
    * @returns DocumentFragment. The menuitems for toggling pseudo-classes.
    */
   buildPseudoClassMenu: function IUI_buildPseudoClassesMenu()
   {
     let fragment = this.chromeDoc.createDocumentFragment();
     for (let i = 0; i < PSEUDO_CLASSES.length; i++) {
       let pseudo = PSEUDO_CLASSES[i];
       let item = this.chromeDoc.createElement("menuitem");
+      item.id = "highlighter-pseudo-class-menuitem-" + pseudo;
       item.setAttribute("type", "checkbox");
       item.setAttribute("label", pseudo);
+      item.className = "highlighter-pseudo-class-menuitem";
+      item.setAttribute("checked", DOMUtils.hasPseudoClassLock(this.node,
+                        pseudo));
       item.addEventListener("command",
                             this.pseudoClassLockToggled.bind(this, pseudo), false);
-      item.setAttribute("checked", DOMUtils.hasPseudoClassLock(this.node,
-                         pseudo));
       fragment.appendChild(item);
     }
     return fragment;
   },
 
   /**
    * Highlight a rectangular region.
    *
--- a/browser/devtools/highlighter/test/Makefile.in
+++ b/browser/devtools/highlighter/test/Makefile.in
@@ -69,16 +69,17 @@ include $(topsrcdir)/config/rules.mk
 		browser_inspector_bug_699308_iframe_navigation.js \
 		browser_inspector_changes.js \
 		browser_inspector_ruleviewstore.js \
 		browser_inspector_duplicate_ruleview.js \
 		browser_inspector_invalidate.js \
 		browser_inspector_sidebarstate.js \
 		browser_inspector_treePanel_menu.js \
 		browser_inspector_pseudoclass_lock.js \
+		browser_inspector_pseudoClass_menu.js \
 		head.js \
 		$(NULL)
 
 # Disabled due to constant failures
 # 		browser_inspector_treePanel_click.js \
 
 libs::	$(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/devtools/highlighter/test/browser_inspector_pseudoClass_menu.js
@@ -0,0 +1,87 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let DOMUtils = Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
+
+let pseudos = [":hover", ":active", ":focus"];
+
+let doc;
+let div;
+let menu;
+
+function test()
+{
+  waitForExplicitFinish();
+  ignoreAllUncaughtExceptions();
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function() {
+    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+    doc = content.document;
+    waitForFocus(createDocument, content);
+  }, true);
+
+  content.location = "data:text/html,pseudo-class lock node menu tests";
+}
+
+function createDocument()
+{
+  div = doc.createElement("div");
+  div.textContent = "test div";
+
+  doc.body.appendChild(div);
+
+  setupTests();
+}
+
+function setupTests()
+{
+  Services.obs.addObserver(selectNode,
+    InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
+  InspectorUI.openInspectorUI();
+}
+
+function selectNode()
+{
+  Services.obs.removeObserver(selectNode,
+    InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED);
+
+  executeSoon(function() {
+    InspectorUI.highlighter.addListener("nodeselected", performTests);
+    InspectorUI.inspectNode(div);
+  });
+}
+
+function performTests()
+{
+  InspectorUI.highlighter.removeListener("nodeselected", performTests);
+
+  menu = document.getElementById("highlighter-node-menu");
+  menu.addEventListener("popupshowing", testMenuItems, true);
+
+  menu.openPopup();
+}
+
+function testMenuItems()
+{
+  menu.removeEventListener("popupshowing", testMenuItems, true);
+
+  for each (let pseudo in pseudos) {
+    let menuitem = document.getElementById("highlighter-pseudo-class-menuitem-"
+                   + pseudo);
+    ok(menuitem, pseudo + " menuitem exists");
+
+    menuitem.doCommand();
+
+    is(DOMUtils.hasPseudoClassLock(div, pseudo), true,
+       "pseudo-class lock has been applied");
+  }
+  finishUp();
+}
+
+function finishUp()
+{
+  InspectorUI.closeInspectorUI();
+  doc = div = null;
+  gBrowser.removeCurrentTab();
+  finish();
+}