Bug 1187777 - Lazily create computed styles list. r=bgrins
authorSimon Lindholm <simon.lindholm10@gmail.com>
Fri, 07 Aug 2015 18:16:32 -0700
changeset 288586 6e532fe19bb77bfa6965ffcd360d33bfc417ce41
parent 288585 380be310da45a5b810ab47035588dbb2345cee9d
child 288587 7fe4321e40bc819001710904408dd7dac59ff7eb
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgrins
bugs1187777, 100644
milestone42.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 1187777 - Lazily create computed styles list. r=bgrins --- browser/devtools/styleinspector/rule-view.js | 38 +++++++----- browser/devtools/styleinspector/test/browser.ini | 2 + .../test/browser_ruleview_computed_01.js | 47 +++++++++++++++ .../test/browser_ruleview_computed_02.js | 68 ++++++++++++++++++++++ .../browser_ruleview_edit-property-computed.js | 8 +++ 5 files changed, 149 insertions(+), 14 deletions(-) create mode 100644 browser/devtools/styleinspector/test/browser_ruleview_computed_01.js create mode 100644 browser/devtools/styleinspector/test/browser_ruleview_computed_02.js
browser/devtools/styleinspector/rule-view.js
browser/devtools/styleinspector/test/browser.ini
browser/devtools/styleinspector/test/browser_ruleview_computed_01.js
browser/devtools/styleinspector/test/browser_ruleview_computed_02.js
browser/devtools/styleinspector/test/browser_ruleview_edit-property-computed.js
--- a/browser/devtools/styleinspector/rule-view.js
+++ b/browser/devtools/styleinspector/rule-view.js
@@ -2207,16 +2207,17 @@ CssRuleView.prototype = {
    *         The rule property TextPropertyEditor object.
    * @return {bool} true if the computed property was highlighted, false
    *         otherwise.
    */
   _highlightComputedProperty: function(editor) {
     let isComputedHighlighted = false;
 
     // Highlight search matches in the computed list of properties
+    editor._populateComputed();
     for (let computed of editor.prop.computed) {
       if (computed.element) {
         // Get the actual property value displayed in the computed list
         let computedName = computed.name.toLowerCase();
         let computedValue = computed.parsedValue.toLowerCase();
 
         isComputedHighlighted = this._highlightMatches(computed.element, {
           searchName: this.searchPropertyName,
@@ -2836,16 +2837,17 @@ RuleEditor.prototype = {
 function TextPropertyEditor(aRuleEditor, aProperty) {
   this.ruleEditor = aRuleEditor;
   this.ruleView = this.ruleEditor.ruleView;
   this.doc = this.ruleEditor.doc;
   this.popup = this.ruleView.popup;
   this.prop = aProperty;
   this.prop.editor = this;
   this.browserWindow = this.doc.defaultView.top;
+  this._populatedComputed = false;
 
   this._onEnableClicked = this._onEnableClicked.bind(this);
   this._onExpandClicked = this._onExpandClicked.bind(this);
   this._onStartEditing = this._onStartEditing.bind(this);
   this._onNameDone = this._onNameDone.bind(this);
   this._onValueDone = this._onValueDone.bind(this);
   this._onSwatchCommit = this._onSwatchCommit.bind(this);
   this._onSwatchPreview = this._onSwatchPreview.bind(this);
@@ -3178,34 +3180,47 @@ TextPropertyEditor.prototype = {
   },
 
   _onStartEditing: function() {
     this.element.classList.remove("ruleview-overridden");
     this.enable.style.visibility = "hidden";
   },
 
   /**
-   * Populate the list of computed styles.
+   * Update the indicator for computed styles. The computed styles themselves
+   * are populated on demand, when they become visible.
    */
   _updateComputed: function() {
-    // Clear out existing viewers.
-    while (this.computed.hasChildNodes()) {
-      this.computed.removeChild(this.computed.lastChild);
+    this.computed.innerHTML = "";
+
+    let showExpander = this.prop.computed.some(c => c.name !== this.prop.name);
+    this.expander.style.visibility = showExpander ? "visible" : "hidden";
+
+    this._populatedComputed = false;
+    if (this.expander.hasAttribute("open")) {
+      this._populateComputed();
     }
-
-    let showExpander = false;
+  },
+
+  /**
+   * Populate the list of computed styles.
+   */
+  _populateComputed: function() {
+    if (this._populatedComputed) {
+      return;
+    }
+    this._populatedComputed = true;
+
     for (let computed of this.prop.computed) {
       // Don't bother to duplicate information already
       // shown in the text property.
       if (computed.name === this.prop.name) {
         continue;
       }
 
-      showExpander = true;
-
       let li = createChild(this.computed, "li", {
         class: "ruleview-computed"
       });
 
       if (computed.overridden) {
         li.classList.add("ruleview-overridden");
       }
 
@@ -3233,23 +3248,16 @@ TextPropertyEditor.prototype = {
       });
 
       appendText(li, ";");
 
       // Store the computed style element for easy access when highlighting
       // styles
       computed.element = li;
     }
-
-    // Show or hide the expander as needed.
-    if (showExpander) {
-      this.expander.style.visibility = "visible";
-    } else {
-      this.expander.style.visibility = "hidden";
-    }
   },
 
   /**
    * Handles clicks on the disabled property.
    */
   _onEnableClicked: function(aEvent) {
     let checked = this.enable.hasAttribute("checked");
     if (checked) {
@@ -3272,30 +3280,32 @@ TextPropertyEditor.prototype = {
     if (this.computed.hasAttribute("filter-open") ||
         this.computed.hasAttribute("user-open")) {
       this.expander.removeAttribute("open");
       this.computed.removeAttribute("filter-open");
       this.computed.removeAttribute("user-open");
     } else {
       this.expander.setAttribute("open", "true");
       this.computed.setAttribute("user-open", "");
+      this._populateComputed();
     }
 
     aEvent.stopPropagation();
   },
 
   /**
    * Expands the computed list when a computed property is matched by the style
    * filtering. The filter-open attribute is used to track whether or not the
    * computed list was toggled opened by the filter.
    */
   expandForFilter: function() {
     if (!this.computed.hasAttribute("user-open")) {
       this.expander.setAttribute("open", "true");
       this.computed.setAttribute("filter-open", "");
+      this._populateComputed();
     }
   },
 
   /**
    * Collapses the computed list that was expanded by style filtering.
    */
   collapseForFilter: function() {
     this.computed.removeAttribute("filter-open");
--- a/browser/devtools/styleinspector/test/browser.ini
+++ b/browser/devtools/styleinspector/test/browser.ini
@@ -69,16 +69,18 @@ support-files =
 [browser_ruleview_colorpicker-multiple-changes.js]
 [browser_ruleview_colorpicker-release-outside-frame.js]
 [browser_ruleview_colorpicker-revert-on-ESC.js]
 [browser_ruleview_colorpicker-swatch-displayed.js]
 [browser_ruleview_completion-existing-property_01.js]
 [browser_ruleview_completion-existing-property_02.js]
 [browser_ruleview_completion-new-property_01.js]
 [browser_ruleview_completion-new-property_02.js]
+[browser_ruleview_computed_01.js]
+[browser_ruleview_computed_02.js]
 [browser_ruleview_completion-popup-hidden-after-navigation.js]
 [browser_ruleview_content_01.js]
 [browser_ruleview_content_02.js]
 skip-if = e10s # Bug 1039528: "inspect element" contextual-menu doesn't work with e10s
 [browser_ruleview_context-menu-show-mdn-docs-01.js]
 [browser_ruleview_context-menu-show-mdn-docs-02.js]
 [browser_ruleview_context-menu-show-mdn-docs-03.js]
 [browser_ruleview_copy_styles.js]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_ruleview_computed_01.js
@@ -0,0 +1,47 @@
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Tests that the rule view shows expanders for properties with computed lists.
+
+let TEST_URI = `
+  <style type="text/css">
+    #testid {
+      margin: 4px;
+      top: 0px;
+    }
+  </style>
+  <h1 id="testid">Styled Node</h1>
+`;
+
+add_task(function*() {
+  yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+  let {inspector, view} = yield openRuleView();
+  yield selectNode("#testid", inspector);
+  yield testExpandersShown(inspector, view);
+});
+
+function* testExpandersShown(inspector, view) {
+  let rule = getRuleViewRuleEditor(view, 1).rule;
+
+  info("Check that the correct rules are visible");
+  is(rule.selectorText, "#testid", "Second rule is #testid.");
+  is(rule.textProps[0].name, "margin", "First property is margin.");
+  is(rule.textProps[1].name, "top", "Second property is top.");
+
+  info("Check that the expanders are shown correctly");
+  is(rule.textProps[0].editor.expander.style.visibility, "visible",
+      "margin expander is visible.");
+  is(rule.textProps[1].editor.expander.style.visibility, "hidden",
+      "top expander is hidden.");
+  ok(!rule.textProps[0].editor.expander.hasAttribute("open"),
+      "margin computed list is closed.");
+  ok(!rule.textProps[1].editor.expander.hasAttribute("open"),
+      "top computed list is closed.");
+  ok(!rule.textProps[0].editor.computed.hasChildNodes(),
+      "margin computed list is empty before opening.");
+  ok(!rule.textProps[1].editor.computed.hasChildNodes(),
+      "top computed list is empty.");
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_ruleview_computed_02.js
@@ -0,0 +1,68 @@
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Tests that the rule view computed lists can be expanded/collapsed,
+// and contain the right subproperties.
+
+let TEST_URI = `
+  <style type="text/css">
+    #testid {
+      margin: 0px 1px 2px 3px;
+      top: 0px;
+    }
+  </style>
+  <h1 id="testid">Styled Node</h1>
+`;
+
+add_task(function*() {
+  yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+  let {inspector, view} = yield openRuleView();
+  yield selectNode("#testid", inspector);
+  yield testComputedList(inspector, view);
+});
+
+function* testComputedList(inspector, view) {
+  let rule = getRuleViewRuleEditor(view, 1).rule;
+  let propEditor = rule.textProps[0].editor;
+  let expander = propEditor.expander;
+
+  ok(!expander.hasAttribute("open"), "margin computed list is closed");
+
+  info("Opening the computed list of margin property")
+  expander.click();
+  ok(expander.hasAttribute("open"), "margin computed list is open");
+
+  let computed = propEditor.prop.computed;
+  let computedDom = propEditor.computed;
+  let propNames = [
+    "margin-top",
+    "margin-right",
+    "margin-bottom",
+    "margin-left"
+  ];
+
+  is(computed.length, propNames.length, "There should be 4 computed values");
+  is(computedDom.children.length, propNames.length, "There should be 4 nodes in the DOM");
+  propNames.forEach((propName, i) => {
+    let propValue = i + "px";
+    is(computed[i].name, propName, "Computed property #" + i + " has name " + propName);
+    is(computed[i].value, propValue, "Computed property #" + i + " has value " + propValue);
+    is(computedDom.getElementsByClassName("ruleview-propertyname")[i].textContent, propName,
+        "Computed property #" + i + " in DOM has correct name");
+    is(computedDom.getElementsByClassName("ruleview-propertyvalue")[i].textContent, propValue,
+        "Computed property #" + i + " in DOM has correct value");
+  });
+
+  info("Closing the computed list of margin property")
+  expander.click();
+  ok(!expander.hasAttribute("open"), "margin computed list is closed");
+
+  info("Opening the computed list of margin property")
+  expander.click();
+  ok(expander.hasAttribute("open"), "margin computed list is open");
+  is(computed.length, propNames.length, "Still 4 computed values");
+  is(computedDom.children.length, propNames.length, "Still 4 nodes in the DOM");
+}
--- a/browser/devtools/styleinspector/test/browser_ruleview_edit-property-computed.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_edit-property-computed.js
@@ -59,9 +59,17 @@ function* editAndCheck(view) {
     "padding-left"
   ];
 
   is(computed.length, propNames.length, "There should be 4 computed values");
   propNames.forEach((propName, i) => {
     is(computed[i].name, propName, "Computed property #" + i + " has name " + propName);
     is(computed[i].value, newPaddingValue, "Computed value of " + propName + " is as expected");
   });
+
+  propEditor.expander.click();
+  let computedDom = propEditor.computed;
+  is(computedDom.children.length, propNames.length, "There should be 4 nodes in the DOM");
+  propNames.forEach((propName, i) => {
+    is(computedDom.getElementsByClassName("ruleview-propertyvalue")[i].textContent,
+        newPaddingValue, "Computed value of " + propName + " in DOM is as expected");
+  });
 }