Bug 1139186 - 1 - Refactor to the native anon nodes manipulation in highlighters; r=bgrins
authorPatrick Brosset <pbrosset@mozilla.com>
Tue, 10 Mar 2015 16:28:57 +0100
changeset 251867 fe3a966d78e23cc9e5913ad7841f0cdf12e014fb
parent 251866 886cea0bebeff696910e63ea54f492492e54eea3
child 251868 ad230a491176bd5e01c6c8fbb9fc41a45c584cbb
push id1156
push userpbrosset@mozilla.com
push dateFri, 20 Mar 2015 16:00:24 +0000
reviewersbgrins
bugs1139186
milestone39.0a1
Bug 1139186 - 1 - Refactor to the native anon nodes manipulation in highlighters; r=bgrins
toolkit/devtools/server/actors/highlighter.js
--- a/toolkit/devtools/server/actors/highlighter.js
+++ b/toolkit/devtools/server/actors/highlighter.js
@@ -1066,16 +1066,20 @@ BoxModelHighlighter.prototype = Heritage
   destroy: function() {
     AutoRefreshHighlighter.prototype.destroy.call(this);
 
     this.markup.destroy();
 
     this._currentNode = null;
   },
 
+  getElement: function(id) {
+    return this.markup.getElement(this.ID_CLASS_PREFIX + id);
+  },
+
   /**
    * Show the highlighter on a given node
    */
   _show: function() {
     if (BOX_MODEL_REGIONS.indexOf(this.options.region) == -1)  {
       this.options.region = "content";
     }
 
@@ -1138,43 +1142,39 @@ BoxModelHighlighter.prototype = Heritage
 
     setIgnoreLayoutChanges(false, this.currentNode.ownerDocument.documentElement);
   },
 
   /**
    * Hide the infobar
    */
   _hideInfobar: function() {
-    this.markup.setAttributeForElement(
-      this.ID_CLASS_PREFIX + "nodeinfobar-container", "hidden", "true");
+    this.getElement("nodeinfobar-container").setAttribute("hidden", "true");
   },
 
   /**
    * Show the infobar
    */
   _showInfobar: function() {
-    this.markup.removeAttributeForElement(
-      this.ID_CLASS_PREFIX + "nodeinfobar-container", "hidden");
+    this.getElement("nodeinfobar-container").removeAttribute("hidden");
     this._updateInfobar();
   },
 
   /**
    * Hide the box model
    */
   _hideBoxModel: function() {
-    this.markup.setAttributeForElement(this.ID_CLASS_PREFIX + "elements",
-      "hidden", "true");
+    this.getElement("elements").setAttribute("hidden", "true");
   },
 
   /**
    * Show the box model
    */
   _showBoxModel: function() {
-    this.markup.removeAttributeForElement(this.ID_CLASS_PREFIX + "elements",
-      "hidden");
+    this.getElement("elements").removeAttribute("hidden");
   },
 
   /**
    * Calculate an outer quad based on the quads returned by getAdjustedQuads.
    * The BoxModelHighlighter may highlight more than one boxes, so in this case
    * create a new quad that "contains" all of these quads.
    * This is useful to position the guides and nodeinfobar.
    * This may happen if the BoxModelHighlighter is used to highlight an inline
@@ -1234,38 +1234,37 @@ BoxModelHighlighter.prototype = Heritage
    * @return {boolean}
    *         True if the current node has a box model to be highlighted
    */
   _updateBoxModel: function() {
     this.options.region = this.options.region || "content";
 
     if (this._nodeNeedsHighlighting()) {
       for (let boxType of BOX_MODEL_REGIONS) {
+        let box = this.getElement(boxType);
+
         if (this.regionFill[boxType]) {
-          this.markup.setAttributeForElement(this.ID_CLASS_PREFIX + boxType,
-            "style", "fill:" + this.regionFill[boxType]);
+          box.setAttribute("style", "fill:" + this.regionFill[boxType]);
         } else {
-          this.markup.setAttributeForElement(this.ID_CLASS_PREFIX + boxType,
-            "style", "");
+          box.setAttribute("style", "");
         }
 
         if (!this.options.showOnly || this.options.showOnly === boxType) {
           // Highlighting all quads.
           let path = [];
           for (let {p1, p2, p3, p4} of this.currentQuads[boxType]) {
             path.push("M" + p1.x + "," + p1.y + " " +
                       "L" + p2.x + "," + p2.y + " " +
                       "L" + p3.x + "," + p3.y + " " +
                       "L" + p4.x + "," + p4.y);
           }
 
-          this.markup.setAttributeForElement(this.ID_CLASS_PREFIX + boxType,
-            "d", path.join(" "));
+          box.setAttribute("d", path.join(" "));
         } else {
-          this.markup.removeAttributeForElement(this.ID_CLASS_PREFIX + boxType, "d");
+          box.removeAttribute("d");
         }
 
         if (boxType === this.options.region && !this.options.hideGuides) {
           this._showGuides(boxType);
         } else if (this.options.hideGuides) {
           this._hideGuides();
         }
       }
@@ -1362,51 +1361,50 @@ BoxModelHighlighter.prototype = Heritage
     this._updateGuide("top", toShowY[0]);
     this._updateGuide("right", toShowX[1]);
     this._updateGuide("bottom", toShowY[1]);
     this._updateGuide("left", toShowX[0]);
   },
 
   _hideGuides: function() {
     for (let side of BOX_MODEL_SIDES) {
-      this.markup.setAttributeForElement(
-        this.ID_CLASS_PREFIX + "guide-" + side, "hidden", "true");
+      this.getElement("guide-" + side).setAttribute("hidden", "true");
     }
   },
 
   /**
    * Move a guide to the appropriate position and display it. If no point is
    * passed then the guide is hidden.
    *
    * @param  {String} side
    *         The guide to update
    * @param  {Integer} point
    *         x or y co-ordinate. If this is undefined we hide the guide.
    */
   _updateGuide: function(side, point=-1) {
-    let guideId = this.ID_CLASS_PREFIX + "guide-" + side;
+    let guide = this.getElement("guide-" + side);
 
     if (point <= 0) {
-      this.markup.setAttributeForElement(guideId, "hidden", "true");
+      guide.setAttribute("hidden", "true");
       return false;
     }
 
     if (side === "top" || side === "bottom") {
-      this.markup.setAttributeForElement(guideId, "x1", "0");
-      this.markup.setAttributeForElement(guideId, "y1", point + "");
-      this.markup.setAttributeForElement(guideId, "x2", "100%");
-      this.markup.setAttributeForElement(guideId, "y2", point + "");
+      guide.setAttribute("x1", "0");
+      guide.setAttribute("y1", point + "");
+      guide.setAttribute("x2", "100%");
+      guide.setAttribute("y2", point + "");
     } else {
-      this.markup.setAttributeForElement(guideId, "x1", point + "");
-      this.markup.setAttributeForElement(guideId, "y1", "0");
-      this.markup.setAttributeForElement(guideId, "x2", point + "");
-      this.markup.setAttributeForElement(guideId, "y2", "100%");
+      guide.setAttribute("x1", point + "");
+      guide.setAttribute("y1", "0");
+      guide.setAttribute("x2", point + "");
+      guide.setAttribute("y2", "100%");
     }
 
-    this.markup.removeAttributeForElement(guideId, "hidden");
+    guide.removeAttribute("hidden");
 
     return true;
   },
 
   /**
    * Update node information (tagName#id.class)
    */
   _updateInfobar: function() {
@@ -1430,75 +1428,74 @@ BoxModelHighlighter.prototype = Heritage
     if (pseudo) {
       // Display :after as ::after
       pseudos += ":" + pseudo;
     }
 
     let rect = this._getOuterQuad("border").bounds;
     let dim = parseFloat(rect.width.toPrecision(6)) + " \u00D7 " + parseFloat(rect.height.toPrecision(6));
 
-    let elementId = this.ID_CLASS_PREFIX + "nodeinfobar-";
-    this.markup.setTextContentForElement(elementId + "tagname", tagName);
-    this.markup.setTextContentForElement(elementId + "id", id);
-    this.markup.setTextContentForElement(elementId + "classes", classList);
-    this.markup.setTextContentForElement(elementId + "pseudo-classes", pseudos);
-    this.markup.setTextContentForElement(elementId + "dimensions", dim);
+    this.getElement("nodeinfobar-tagname").setTextContent(tagName);
+    this.getElement("nodeinfobar-id").setTextContent(id);
+    this.getElement("nodeinfobar-classes").setTextContent(classList);
+    this.getElement("nodeinfobar-pseudo-classes").setTextContent(pseudos);
+    this.getElement("nodeinfobar-dimensions").setTextContent(dim);
 
     this._moveInfobar();
   },
 
   /**
    * Move the Infobar to the right place in the highlighter.
    */
   _moveInfobar: function() {
     let bounds = this._getOuterBounds();
     let winHeight = this.win.innerHeight * this.zoom;
     let winWidth = this.win.innerWidth * this.zoom;
 
     // Ensure that containerBottom and containerTop are at least zero to avoid
     // showing tooltips outside the viewport.
     let containerBottom = Math.max(0, bounds.bottom) + NODE_INFOBAR_ARROW_SIZE;
     let containerTop = Math.min(winHeight, bounds.top);
-    let containerId = this.ID_CLASS_PREFIX + "nodeinfobar-container";
+    let container = this.getElement("nodeinfobar-container");
 
     // Can the bar be above the node?
     let top;
     if (containerTop < NODE_INFOBAR_HEIGHT) {
       // No. Can we move the bar under the node?
       if (containerBottom + NODE_INFOBAR_HEIGHT > winHeight) {
         // No. Let's move it inside.
         top = containerTop;
-        this.markup.setAttributeForElement(containerId, "position", "overlap");
+        container.setAttribute("position", "overlap");
       } else {
         // Yes. Let's move it under the node.
         top = containerBottom;
-        this.markup.setAttributeForElement(containerId, "position", "bottom");
+        container.setAttribute("position", "bottom");
       }
     } else {
       // Yes. Let's move it on top of the node.
       top = containerTop - NODE_INFOBAR_HEIGHT;
-      this.markup.setAttributeForElement(containerId, "position", "top");
+      container.setAttribute("position", "top");
     }
 
     // Align the bar with the box's center if possible.
     let left = bounds.right - bounds.width / 2;
     // Make sure the while infobar is visible.
     let buffer = 100;
     if (left < buffer) {
       left = buffer;
-      this.markup.setAttributeForElement(containerId, "hide-arrow", "true");
+      container.setAttribute("hide-arrow", "true");
     } else if (left > winWidth - buffer) {
       left = winWidth - buffer;
-      this.markup.setAttributeForElement(containerId, "hide-arrow", "true");
+      container.setAttribute("hide-arrow", "true");
     } else {
-      this.markup.removeAttributeForElement(containerId, "hide-arrow");
+      container.removeAttribute("hide-arrow");
     }
 
     let style = "top:" + top + "px;left:" + left + "px;";
-    this.markup.setAttributeForElement(containerId, "style", style);
+    container.setAttribute("style", style);
   }
 });
 register(BoxModelHighlighter);
 exports.BoxModelHighlighter = BoxModelHighlighter;
 
 /**
  * The CssTransformHighlighter is the class that draws an outline around a
  * transformed element and an outline around where it would be if untransformed
@@ -1621,16 +1618,20 @@ CssTransformHighlighter.prototype = Heri
   /**
    * Destroy the nodes. Remove listeners.
    */
   destroy: function() {
     AutoRefreshHighlighter.prototype.destroy.call(this);
     this.markup.destroy();
   },
 
+  getElement: function(id) {
+    return this.markup.getElement(this.ID_CLASS_PREFIX + id);
+  },
+
   /**
    * Show the highlighter on a given node
    * @param {DOMNode} node
    */
   _show: function() {
     if (!this._isTransformed(this.currentNode)) {
       this.hide();
       return;
@@ -1647,33 +1648,31 @@ CssTransformHighlighter.prototype = Heri
     return style && (style.transform !== "none" && style.display !== "inline");
   },
 
   _setPolygonPoints: function(quad, id) {
     let points = [];
     for (let point of ["p1","p2", "p3", "p4"]) {
       points.push(quad[point].x + "," + quad[point].y);
     }
-    this.markup.setAttributeForElement(this.ID_CLASS_PREFIX + id,
-                                       "points",
-                                       points.join(" "));
+    this.getElement(id).setAttribute("points", points.join(" "));
   },
 
   _setLinePoints: function(p1, p2, id) {
-    this.markup.setAttributeForElement(this.ID_CLASS_PREFIX + id, "x1", p1.x);
-    this.markup.setAttributeForElement(this.ID_CLASS_PREFIX + id, "y1", p1.y);
-    this.markup.setAttributeForElement(this.ID_CLASS_PREFIX + id, "x2", p2.x);
-    this.markup.setAttributeForElement(this.ID_CLASS_PREFIX + id, "y2", p2.y);
+    let line = this.getElement(id);
+    line.setAttribute("x1", p1.x);
+    line.setAttribute("y1", p1.y);
+    line.setAttribute("x2", p2.x);
+    line.setAttribute("y2", p2.y);
 
     let dist = Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
     if (dist < ARROW_LINE_MIN_DISTANCE) {
-      this.markup.removeAttributeForElement(this.ID_CLASS_PREFIX + id, "marker-end");
+      line.removeAttribute("marker-end");
     } else {
-      this.markup.setAttributeForElement(this.ID_CLASS_PREFIX + id, "marker-end",
-                                         "url(#" + this.markerId + ")");
+      line.setAttribute("marker-end", "url(#" + this.markerId + ")");
     }
   },
 
   /**
    * Update the highlighter on the current highlighted node (the one that was
    * passed as an argument to show(node)).
    * Should be called whenever node size or attributes change
    */
@@ -1712,23 +1711,21 @@ CssTransformHighlighter.prototype = Heri
    */
   _hide: function() {
     setIgnoreLayoutChanges(true);
     this._hideShapes();
     setIgnoreLayoutChanges(false, this.currentNode.ownerDocument.documentElement);
   },
 
   _hideShapes: function() {
-    this.markup.setAttributeForElement(this.ID_CLASS_PREFIX + "elements",
-      "hidden", "true");
+    this.getElement("elements").setAttribute("hidden", "true");
   },
 
   _showShapes: function() {
-    this.markup.removeAttributeForElement(this.ID_CLASS_PREFIX + "elements",
-      "hidden");
+    this.getElement("elements").removeAttribute("hidden");
   }
 });
 register(CssTransformHighlighter);
 exports.CssTransformHighlighter = CssTransformHighlighter;
 
 
 /**
  * The SelectorHighlighter runs a given selector through querySelectorAll on the
@@ -1825,16 +1822,20 @@ RectHighlighter.prototype = {
   },
 
   destroy: function() {
     this.win = null;
     this.layoutHelpers = null;
     this.markup.destroy();
   },
 
+  getElement: function(id) {
+    return this.markup.getElement(id);
+  },
+
   _hasValidOptions: function(options) {
     let isValidNb = n => typeof n === "number" && n >= 0 && isFinite(n);
     return options && options.rect &&
            isValidNb(options.rect.x) &&
            isValidNb(options.rect.y) &&
            options.rect.width && isValidNb(options.rect.width) &&
            options.rect.height && isValidNb(options.rect.height);
   },
@@ -1870,22 +1871,23 @@ RectHighlighter.prototype = {
     let height = "height:" + options.rect.height + "px;";
 
     let style = x + y + width + height;
     if (options.fill) {
       style += "background:" + options.fill + ";";
     }
 
     // Set the coordinates of the highlighter and show it
-    this.markup.setAttributeForElement("highlighted-rect", "style", style);
-    this.markup.removeAttributeForElement("highlighted-rect", "hidden");
+    let rect = this.getElement("highlighted-rect");
+    rect.setAttribute("style", style);
+    rect.removeAttribute("hidden");
   },
 
   hide: function() {
-    this.markup.setAttributeForElement("highlighted-rect", "hidden", "true");
+    this.getElement("highlighted-rect").setAttribute("hidden", "true");
   }
 };
 register(RectHighlighter);
 exports.RectHighlighter = RectHighlighter;
 
 /**
  * Element geometry properties helper that gives names of position and size
  * properties.
@@ -2140,16 +2142,20 @@ GeometryEditorHighlighter.prototype = He
     AutoRefreshHighlighter.prototype.destroy.call(this);
 
     this.markup.destroy();
     this.definedProperties.clear();
     this.definedProperties = null;
     this.offsetParent = null;
   },
 
+  getElement: function(id) {
+    return this.markup.getElement(this.ID_CLASS_PREFIX + id);
+  },
+
   /**
    * Get the list of geometry properties that are actually set on the current
    * node.
    * @return {Map} A map indexed by property name and where the value is an
    * object having the cssRule property.
    */
   getDefinedGeometryProperties: function() {
     let props = new Map();
@@ -2266,17 +2272,17 @@ GeometryEditorHighlighter.prototype = He
    */
   updateOffsetParent: function() {
     // Get the offsetParent, if any.
     this.offsetParent = getOffsetParent(this.currentNode);
     // And the offsetParent quads.
     this.parentQuads = this.layoutHelpers
                       .getAdjustedQuads(this.offsetParent.element, "padding");
 
-    let el = this.markup.getElement(this.ID_CLASS_PREFIX + "offset-parent");
+    let el = this.getElement("offset-parent");
 
     let isPositioned = this.computedStyle.position === "absolute" ||
                        this.computedStyle.position === "fixed";
     let isRelative = this.computedStyle.position === "relative";
     let isHighlighted = false;
 
     if (this.offsetParent.element && isPositioned) {
       let {p1, p2, p3, p4} = this.parentQuads[0];
@@ -2303,51 +2309,48 @@ GeometryEditorHighlighter.prototype = He
     if (isHighlighted) {
       el.removeAttribute("hidden");
     } else {
       el.setAttribute("hidden", "true");
     }
   },
 
   updateCurrentNode: function() {
-    let box = this.markup.getElement(this.ID_CLASS_PREFIX + "current-node");
+    let box = this.getElement("current-node");
     let {p1, p2, p3, p4} = this.currentQuads.margin[0];
     let attr = p1.x + "," + p1.y + " " +
                p2.x + "," + p2.y + " " +
                p3.x + "," + p3.y + " " +
                p4.x + "," + p4.y;
     box.setAttribute("points", attr);
     box.removeAttribute("hidden");
   },
 
   _hide: function() {
     setIgnoreLayoutChanges(true);
 
-    let id = this.ID_CLASS_PREFIX;
-    this.markup.setAttributeForElement(id + "current-node", "hidden", "true");
-    this.markup.setAttributeForElement(id + "offset-parent", "hidden", "true");
+    this.getElement("current-node").setAttribute("hidden", "true");
+    this.getElement("offset-parent").setAttribute("hidden", "true");
     this.hideArrows();
     this.hideSize();
 
     this.definedProperties.clear();
 
     setIgnoreLayoutChanges(false, this.currentNode.ownerDocument.documentElement);
   },
 
   hideArrows: function() {
     for (let side of GeoProp.SIDES) {
-      let id = this.ID_CLASS_PREFIX;
-      this.markup.setAttributeForElement(id + "arrow-" + side, "hidden", "true");
-      this.markup.setAttributeForElement(id + "label-" + side, "hidden", "true");
+      this.getElement("arrow-" + side).setAttribute("hidden", "true");
+      this.getElement("label-" + side).setAttribute("hidden", "true");
     }
   },
 
   hideSize: function() {
-    this.markup.setAttributeForElement(this.ID_CLASS_PREFIX + "label-size",
-      "hidden", "true");
+    this.getElement("label-size").setAttribute("hidden", "true");
   },
 
   updateSize: function() {
     this.hideSize();
 
     let labels = [];
     let width = this.definedProperties.get("width");
     let height = this.definedProperties.get("height");
@@ -2355,19 +2358,18 @@ GeometryEditorHighlighter.prototype = He
     if (width) {
       labels.push("↔ " + width.cssRule.style.getPropertyValue("width"));
     }
     if (height) {
       labels.push("↕ " + height.cssRule.style.getPropertyValue("height"));
     }
 
     if (labels.length) {
-      let id = this.ID_CLASS_PREFIX;
-      let labelEl = this.markup.getElement(id + "label-size");
-      let labelTextEl = this.markup.getElement(id + "label-text-size");
+      let labelEl = this.getElement("label-size");
+      let labelTextEl = this.getElement("label-text-size");
 
       let {bounds} = this.currentQuads.margin[0];
 
       labelEl.setAttribute("transform", "translate(" +
         (bounds.left + bounds.width/2) + " " +
         (bounds.top + bounds.height/2) + ")");
       labelEl.removeAttribute("hidden");
       labelTextEl.setTextContent(labels.join(" "));
@@ -2435,20 +2437,19 @@ GeometryEditorHighlighter.prototype = He
                          marginBox[GeoProp.crossAxisSize(side)] / 2;
 
       this.updateArrow(side, mainAxisStartPos, mainAxisEndPos, crossAxisPos,
                        sideProp.cssRule.style.getPropertyValue(side));
     }
   },
 
   updateArrow: function(side, mainStart, mainEnd, crossPos, labelValue) {
-    let id = this.ID_CLASS_PREFIX;
-    let arrowEl = this.markup.getElement(id + "arrow-" + side);
-    let labelEl = this.markup.getElement(id + "label-" + side);
-    let labelTextEl = this.markup.getElement(id + "label-text-" + side);
+    let arrowEl = this.getElement("arrow-" + side);
+    let labelEl = this.getElement("label-" + side);
+    let labelTextEl = this.getElement("label-text-" + side);
 
     // Position the arrow <line>.
     arrowEl.setAttribute(GeoProp.axis(side) + "1", mainStart);
     arrowEl.setAttribute(GeoProp.crossAxis(side) + "1", crossPos);
     arrowEl.setAttribute(GeoProp.axis(side) + "2", mainEnd);
     arrowEl.setAttribute(GeoProp.crossAxis(side) + "2", crossPos);
     arrowEl.removeAttribute("hidden");