Bug 718250 - Add the dimensions of the node in the NodeInfobar r=jwalker
authorMichael Ratcliffe <mratcliffe@mozilla.com>
Wed, 04 Jun 2014 16:38:41 +0100
changeset 206020 531774aeb6c2bc4ff3ea293b8a3ef96ad8cbc2b2
parent 206019 c2b9502bcf60cdcef586b837d983480a3ddb265a
child 206021 d0eff5655df235cc00dfcdd8520ccd6562c691b1
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalker
bugs718250
milestone32.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 718250 - Add the dimensions of the node in the NodeInfobar r=jwalker
browser/base/content/highlighter.css
browser/devtools/inspector/test/browser_inspector_infobar.js
browser/themes/shared/devtools/highlighter.inc.css
toolkit/devtools/server/actors/highlighter.js
--- a/browser/base/content/highlighter.css
+++ b/browser/base/content/highlighter.css
@@ -40,16 +40,17 @@ svg|line.box-model-guide-bottom[hidden] 
   white-space: nowrap;
   text-overflow: ellipsis;
   direction: ltr;
 }
 
 html|*.highlighter-nodeinfobar-id,
 html|*.highlighter-nodeinfobar-classes,
 html|*.highlighter-nodeinfobar-pseudo-classes,
+html|*.highlighter-nodeinfobar-dimensions,
 html|*.highlighter-nodeinfobar-tagname {
   -moz-user-select: text;
   -moz-user-focus: normal;
   cursor: text;
 }
 
 .highlighter-nodeinfobar-arrow {
   display: none;
--- a/browser/devtools/inspector/test/browser_inspector_infobar.js
+++ b/browser/devtools/inspector/test/browser_inspector_infobar.js
@@ -12,29 +12,68 @@ function test() {
 
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function onload() {
     gBrowser.selectedBrowser.removeEventListener("load", onload, true);
     doc = content.document;
     waitForFocus(setupInfobarTest, content);
   }, true);
 
-  let style = "body{width:100%;height: 100%} div {position: absolute;height: 100px;width: 500px}#bottom {bottom: 0px}#vertical {height: 100%}#farbottom{bottom: -200px}";
-  let html = "<style>" + style + "</style><div id=vertical></div><div id=top class='class1 class2'></div><div id=bottom></div><div id=farbottom></div>"
+  let style = "body{width:100%;height: 100%} div {position: absolute;" +
+              "height: 100px;width: 500px}#bottom {bottom: 0px}#vertical {"+
+              "height: 100%}#farbottom{bottom: -200px}";
+  let html = "<style>" + style + "</style><div id=vertical></div>" +
+             "<div id=top class='class1 class2'></div><div id=bottom></div>" +
+             "<div id=farbottom></div>"
 
-  content.location = "data:text/html," + encodeURIComponent(html);
+  content.location = "data:text/html;charset=utf-8," + encodeURIComponent(html);
 
   function setupInfobarTest() {
     nodes = [
-      {node: doc.querySelector("#top"), position: "bottom", tag: "DIV", id: "#top", classes: ".class1.class2"},
-      {node: doc.querySelector("#vertical"), position: "overlap", tag: "DIV", id: "#vertical", classes: ""},
-      {node: doc.querySelector("#bottom"), position: "top", tag: "DIV", id: "#bottom", classes: ""},
-      {node: doc.querySelector("body"), position: "overlap", tag: "BODY", id: "", classes: ""},
-      {node: doc.querySelector("#farbottom"), position: "top", tag: "DIV", id: "#farbottom", classes: ""},
-    ]
+      {
+        node: doc.querySelector("#top"),
+        position: "bottom",
+        tag: "DIV",
+        id: "#top",
+        classes: ".class1.class2",
+        dims: "500 x 100"
+      },
+      {
+        node: doc.querySelector("#vertical"),
+        position: "overlap",
+        tag: "DIV",
+        id: "#vertical",
+        classes: ""
+        // No dims as they will vary between computers
+      },
+      {
+        node: doc.querySelector("#bottom"),
+        position: "top",
+        tag: "DIV",
+        id: "#bottom",
+        classes: "",
+        dims: "500 x 100"
+      },
+      {
+        node: doc.querySelector("body"),
+        position: "overlap",
+        tag: "BODY",
+        id: "",
+        classes: ""
+        // No dims as they will vary between computers
+      },
+      {
+        node: doc.querySelector("#farbottom"),
+        position: "top",
+        tag: "DIV",
+        id: "#farbottom",
+        classes: "",
+        dims: "500 x 100"
+      },
+    ];
 
     for (let i = 0; i < nodes.length; i++) {
       ok(nodes[i].node, "node " + i + " found");
     }
 
     openInspector(runTests);
   }
 
@@ -69,26 +108,34 @@ function test() {
     });
   }
 
   function performTest() {
     let browser = gBrowser.selectedBrowser;
     let stack = browser.parentNode;
 
     let container = stack.querySelector(".highlighter-nodeinfobar-positioner");
-    is(container.getAttribute("position"), nodes[cursor].position, "node " + cursor + ": position matches.");
+    is(container.getAttribute("position"),
+      nodes[cursor].position, "node " + cursor + ": position matches.");
 
     let tagNameLabel = stack.querySelector(".highlighter-nodeinfobar-tagname");
-    is(tagNameLabel.textContent, nodes[cursor].tag, "node " + cursor  + ": tagName matches.");
+    is(tagNameLabel.textContent, nodes[cursor].tag,
+      "node " + cursor  + ": tagName matches.");
 
     let idLabel = stack.querySelector(".highlighter-nodeinfobar-id");
     is(idLabel.textContent, nodes[cursor].id, "node " + cursor  + ": id matches.");
 
     let classesBox = stack.querySelector(".highlighter-nodeinfobar-classes");
-    is(classesBox.textContent, nodes[cursor].classes, "node " + cursor  + ": classes match.");
+    is(classesBox.textContent, nodes[cursor].classes,
+      "node " + cursor  + ": classes match.");
+
+    if (nodes[cursor].dims) {
+      let dimBox = stack.querySelector(".highlighter-nodeinfobar-dimensions");
+      is(dimBox.textContent, nodes[cursor].dims, "node " + cursor  + ": dims match.");
+    }
   }
 
   function finishUp() {
     doc = nodes = null;
     gBrowser.removeCurrentTab();
     finish();
   }
 }
--- a/browser/themes/shared/devtools/highlighter.inc.css
+++ b/browser/themes/shared/devtools/highlighter.inc.css
@@ -69,16 +69,23 @@ html|*.highlighter-nodeinfobar-id {
   color: hsl(103,46%,54%);
 }
 
 html|*.highlighter-nodeinfobar-classes,
 html|*.highlighter-nodeinfobar-pseudo-classes {
   color: hsl(200,74%,57%);
 }
 
+html|*.highlighter-nodeinfobar-dimensions {
+  color: hsl(210,30%,85%);
+  -moz-border-start: 1px solid #5a6169;
+  -moz-margin-start: 6px;
+  -moz-padding-start: 6px;
+}
+
 /* Highlighter - Node Infobar - box & arrow */
 
 .highlighter-nodeinfobar-arrow {
   width: 14px;
   height: 14px;
   -moz-margin-start: calc(50% - 7px);
   transform: rotate(-45deg);
   background-clip: padding-box;
--- a/toolkit/devtools/server/actors/highlighter.js
+++ b/toolkit/devtools/server/actors/highlighter.js
@@ -393,45 +393,50 @@ BoxModelHighlighter.prototype = {
     idLabel.className = "highlighter-nodeinfobar-id";
 
     let classesBox = this.chromeDoc.createElementNS(XHTML_NS, "span");
     classesBox.className = "highlighter-nodeinfobar-classes";
 
     let pseudoClassesBox = this.chromeDoc.createElementNS(XHTML_NS, "span");
     pseudoClassesBox.className = "highlighter-nodeinfobar-pseudo-classes";
 
+    let dimensionBox = this.chromeDoc.createElementNS(XHTML_NS, "span");
+    dimensionBox.className = "highlighter-nodeinfobar-dimensions";
+
     // Add some content to force a better boundingClientRect
     pseudoClassesBox.textContent = "&nbsp;";
 
     // <hbox class="highlighter-nodeinfobar-text"/>
     let texthbox = this.chromeDoc.createElement("hbox");
     texthbox.className = "highlighter-nodeinfobar-text";
     texthbox.setAttribute("align", "center");
     texthbox.setAttribute("flex", "1");
 
     texthbox.appendChild(tagNameLabel);
     texthbox.appendChild(idLabel);
     texthbox.appendChild(classesBox);
     texthbox.appendChild(pseudoClassesBox);
+    texthbox.appendChild(dimensionBox);
 
     nodeInfobar.appendChild(texthbox);
 
     infobarPositioner.appendChild(arrowBoxTop);
     infobarPositioner.appendChild(nodeInfobar);
     infobarPositioner.appendChild(arrowBoxBottom);
 
     infobarContainer.appendChild(infobarPositioner);
 
     let barHeight = infobarPositioner.getBoundingClientRect().height;
 
     this.nodeInfo = {
       tagNameLabel: tagNameLabel,
       idLabel: idLabel,
       classesBox: classesBox,
       pseudoClassesBox: pseudoClassesBox,
+      dimensionBox: dimensionBox,
       positioner: infobarPositioner,
       barHeight: barHeight,
     };
   },
 
   _createSVGNode: function(classPostfix, nodeType, parent) {
     let node = this.chromeDoc.createElementNS(SVG_NS, nodeType);
     node.setAttribute("class", "box-model-" + classPostfix);
@@ -697,39 +702,46 @@ BoxModelHighlighter.prototype = {
       return false;
     }
   },
 
   /**
    * Update node information (tagName#id.class)
    */
   _updateInfobar: function() {
-    if (this.currentNode) {
-      // Tag name
-      this.nodeInfo.tagNameLabel.textContent = this.currentNode.tagName;
+    if (!this.currentNode) {
+      return;
+    }
 
-      // ID
-      this.nodeInfo.idLabel.textContent = this.currentNode.id ? "#" + this.currentNode.id : "";
+    // Tag name
+    this.nodeInfo.tagNameLabel.textContent = this.currentNode.tagName;
 
-      // Classes
-      let classes = this.nodeInfo.classesBox;
+    // ID
+    this.nodeInfo.idLabel.textContent = this.currentNode.id ? "#" + this.currentNode.id : "";
+
+    // Classes
+    let classes = this.nodeInfo.classesBox;
 
-      classes.textContent = this.currentNode.classList.length ?
-                              "." + Array.join(this.currentNode.classList, ".") : "";
+    classes.textContent = this.currentNode.classList.length ?
+                            "." + Array.join(this.currentNode.classList, ".") : "";
+
+    // Pseudo-classes
+    let pseudos = PSEUDO_CLASSES.filter(pseudo => {
+      return DOMUtils.hasPseudoClassLock(this.currentNode, pseudo);
+    }, this);
 
-      // Pseudo-classes
-      let pseudos = PSEUDO_CLASSES.filter(pseudo => {
-        return DOMUtils.hasPseudoClassLock(this.currentNode, pseudo);
-      }, this);
+    let pseudoBox = this.nodeInfo.pseudoClassesBox;
+    pseudoBox.textContent = pseudos.join("");
 
-      let pseudoBox = this.nodeInfo.pseudoClassesBox;
-      pseudoBox.textContent = pseudos.join("");
-
-      this._moveInfobar();
-    }
+    // Dimensions
+    let dimensionBox = this.nodeInfo.dimensionBox;
+    let rect = this.currentNode.getBoundingClientRect();
+    dimensionBox.textContent = Math.ceil(rect.width) + " x " +
+                               Math.ceil(rect.height);
+    this._moveInfobar();
   },
 
   /**
    * Move the Infobar to the right place in the highlighter.
    */
   _moveInfobar: function() {
     if (this.rect) {
       let bounds = this.rect.bounds;