diff --git a/browser/devtools/styleinspector/rule-view.js b/browser/devtools/styleinspector/rule-view.js
index 648aa840f01e..ce3387f46ddf 100644
--- a/browser/devtools/styleinspector/rule-view.js
+++ b/browser/devtools/styleinspector/rule-view.js
@@ -1116,7 +1116,7 @@ function CssRuleView(aInspector, aDoc, aStore, aPageStyle) {
this.store = aStore || {};
this.pageStyle = aPageStyle;
- this._highlightedElements = [];
+ this._editorsExpandedForFilter = [];
this._outputParser = new OutputParser();
this._buildContextMenu = this._buildContextMenu.bind(this);
@@ -1640,6 +1640,7 @@ CssRuleView.prototype = {
this.searchField.removeAttribute("filled");
}
+ this._clearHighlights();
this._clearRules();
this._createEditors();
@@ -1701,7 +1702,7 @@ CssRuleView.prototype = {
this._prefObserver.destroy();
this._outputParser = null;
- this._highlightedElements = null;
+ this._editorsExpandedForFilter = null;
// Remove context menu
if (this._contextmenu) {
@@ -1995,10 +1996,6 @@ CssRuleView.prototype = {
return;
}
- if (this._highlightedElements.length > 0) {
- this.clearHighlight();
- }
-
for (let rule of this._elementStyle.rules) {
if (rule.domRule.system) {
continue;
@@ -2087,7 +2084,6 @@ CssRuleView.prototype = {
for (let selectorNode of selectorNodes) {
if (selectorNode.textContent.toLowerCase().includes(aValue)) {
selectorNode.classList.add("ruleview-highlight");
- this._highlightedElements.push(selectorNode);
isHighlighted = true;
}
}
@@ -2105,37 +2101,106 @@ CssRuleView.prototype = {
let propertyValue = textProp.editor.valueSpan.textContent.toLowerCase();
let propertyName = textProp.name.toLowerCase();
- // If the input value matches a property line like `font-family: arial`,
- // then check to make sure the name and value match. Otherwise, just
- // compare the input string directly against the name and value elements.
- let matches = false;
- if (propertyMatch && name && value) {
- matches = propertyName.includes(name) && propertyValue.includes(value);
- } else {
- matches = (name && propertyName.includes(name)) ||
- (value && propertyValue.includes(value));
+ let editor = textProp.editor;
+
+ let isPropertyHighlighted = this._highlightMatches(editor.container, {
+ searchName: name,
+ searchValue: value,
+ propertyName: propertyName,
+ propertyValue: propertyValue,
+ propertyMatch: propertyMatch
+ });
+
+ let isComputedHighlighted = false;
+
+ // Highlight search matches in the computed list of properties
+ for (let computed of textProp.computed) {
+ if (computed.element) {
+ let computedName = computed.name;
+ let computedValue = computed.value;
+
+ isComputedHighlighted = this._highlightMatches(computed.element, {
+ searchName: name,
+ searchValue: value,
+ propertyName: computedName,
+ propertyValue: computedValue,
+ propertyMatch: propertyMatch
+ }) ? true : isComputedHighlighted;
+ }
}
- if (matches) {
- // if (matchTextProperty || matchNameOrValue) {
- textProp.editor.element.classList.add("ruleview-highlight");
- this._highlightedElements.push(textProp.editor.element);
+ if (isPropertyHighlighted || isComputedHighlighted) {
isHighlighted = true;
}
+
+ // Expand the computed list if a computed rule is highlighted and the
+ // property rule is not highlighted
+ if (!isPropertyHighlighted && isComputedHighlighted &&
+ !editor.computed.classList.contains("styleinspector-open")) {
+ editor.expandForFilter();
+ this._editorsExpandedForFilter.push(editor);
+ }
}
return isHighlighted;
},
/**
- * Clear all search filter highlights in the panel.
+ * Helper function for highlightRules that carries out highlighting the given
+ * element if the provided search terms match the property, and returns
+ * a boolean indicating whether or not the search terms match.
+ *
+ * @param {DOMNode} aElement
+ * The node to highlight if search terms match
+ * @param {String} searchName
+ * The parsed search name
+ * @param {String} searchValue
+ * The parsed search value
+ * @param {String} propertyName
+ * The property name of a rule
+ * @param {String} propertyValue
+ * The property value of a rule
+ * @param {Boolean} propertyMatch
+ * Whether or not the search term matches a property line like
+ * `font-family: arial`
*/
- clearHighlight: function() {
- for (let element of this._highlightedElements) {
+ _highlightMatches: function(aElement, { searchName, searchValue, propertyName,
+ propertyValue, propertyMatch }) {
+ let matches = false;
+
+ // If the inputted search value matches a property line like
+ // `font-family: arial`, then check to make sure the name and value match.
+ // Otherwise, just compare the inputted search string directly against the
+ // name and value of the rule property.
+ if (propertyMatch && searchName && searchValue) {
+ matches = propertyName.includes(searchName) &&
+ propertyValue.includes(searchValue);
+ } else {
+ matches = (searchName && propertyName.includes(searchName)) ||
+ (searchValue && propertyValue.includes(searchValue));
+ }
+
+ if (matches) {
+ aElement.classList.add("ruleview-highlight");
+ }
+
+ return matches;
+ },
+
+ /**
+ * Clear all search filter highlights in the panel, and close the computed
+ * list if toggled opened
+ */
+ _clearHighlights: function() {
+ for (let element of this.element.querySelectorAll(".ruleview-highlight")) {
element.classList.remove("ruleview-highlight");
}
- this._highlightedElements = [];
+ for (let editor of this._editorsExpandedForFilter) {
+ editor.collapseForFilter();
+ }
+
+ this._editorsExpandedForFilter = [];
}
};
@@ -2593,19 +2658,23 @@ TextPropertyEditor.prototype = {
this.element = this.doc.createElementNS(HTML_NS, "li");
this.element.classList.add("ruleview-property");
+ this.container = createChild(this.element, "div", {
+ class: "ruleview-propertycontainer"
+ });
+
// The enable checkbox will disable or enable the rule.
- this.enable = createChild(this.element, "div", {
+ this.enable = createChild(this.container, "div", {
class: "ruleview-enableproperty theme-checkbox",
tabindex: "-1"
});
// Click to expand the computed properties of the text property.
- this.expander = createChild(this.element, "span", {
+ this.expander = createChild(this.container, "span", {
class: "ruleview-expander theme-twisty"
});
this.expander.addEventListener("click", this._onExpandClicked, true);
- this.nameContainer = createChild(this.element, "span", {
+ this.nameContainer = createChild(this.container, "span", {
class: "ruleview-namecontainer"
});
@@ -2621,8 +2690,8 @@ TextPropertyEditor.prototype = {
// Create a span that will hold the property and semicolon.
// Use this span to create a slightly larger click target
// for the value.
- let propertyContainer = createChild(this.element, "span", {
- class: "ruleview-propertycontainer"
+ let propertyContainer = createChild(this.container, "span", {
+ class: "ruleview-propertyvaluecontainer"
});
@@ -2655,7 +2724,7 @@ TextPropertyEditor.prototype = {
appendText(propertyContainer, ";");
- this.warning = createChild(this.element, "div", {
+ this.warning = createChild(this.container, "div", {
class: "ruleview-warning",
hidden: "",
title: CssLogic.l10n("rule.warning.title"),
@@ -2948,6 +3017,10 @@ 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.
@@ -2973,16 +3046,46 @@ TextPropertyEditor.prototype = {
},
/**
- * Handles clicks on the computed property expander.
+ * Handles clicks on the computed property expander. If the computed list is
+ * open due to user expanding or style filtering, collapse the computed list
+ * and close the expander. Otherwise, add .styleinspector-open class which
+ * is used to expand the computed list and tracks whether or not the computed
+ * list is expanded by manually by the user.
*/
_onExpandClicked: function(aEvent) {
- this.computed.classList.toggle("styleinspector-open");
- if (this.computed.classList.contains("styleinspector-open")) {
- this.expander.setAttribute("open", "true");
+ if (this.computed.classList.contains("filter-open") ||
+ this.computed.classList.contains("styleinspector-open")) {
+ this.expander.removeAttribute("open");
+ this.computed.classList.remove("filter-open");
+ this.computed.classList.remove("styleinspector-open");
} else {
+ this.expander.setAttribute("open", "true");
+ this.computed.classList.add("styleinspector-open");
+ }
+
+ aEvent.stopPropagation();
+ },
+
+ /**
+ * Expands the computed list when a computed property is matched by the style
+ * filtering. The .filter-open class is used to track whether or not the
+ * computed list was toggled opened by the filter.
+ */
+ expandForFilter: function() {
+ if (!this.computed.classList.contains("styleinspector-open")) {
+ this.computed.classList.add("filter-open");
+ this.expander.setAttribute("open", "true");
+ }
+ },
+
+ /**
+ * Collapses the computed list that was expanded by style filtering.
+ */
+ collapseForFilter: function() {
+ this.computed.classList.remove("filter-open");
+ if (!this.computed.classList.contains("styleinspector-open")) {
this.expander.removeAttribute("open");
}
- aEvent.stopPropagation();
},
/**
diff --git a/browser/devtools/styleinspector/ruleview.css b/browser/devtools/styleinspector/ruleview.css
index 398850079859..25c88f7d3c02 100644
--- a/browser/devtools/styleinspector/ruleview.css
+++ b/browser/devtools/styleinspector/ruleview.css
@@ -47,12 +47,12 @@ body {
cursor: text;
}
-.ruleview-propertycontainer {
+.ruleview-propertyvaluecontainer {
cursor: text;
padding-right: 15px;
}
-.ruleview-propertycontainer a {
+.ruleview-propertyvaluecontainer a {
cursor: pointer;
}
@@ -61,6 +61,10 @@ body {
display: none;
}
+.ruleview-computedlist.filter-open {
+ display: block;
+}
+
.ruleview-expandable-container {
display: none;
}
diff --git a/browser/devtools/styleinspector/test/browser.ini b/browser/devtools/styleinspector/test/browser.ini
index c536c6edeb9d..51c2c4eef203 100644
--- a/browser/devtools/styleinspector/test/browser.ini
+++ b/browser/devtools/styleinspector/test/browser.ini
@@ -112,6 +112,14 @@ skip-if = e10s # Bug 1090340
[browser_ruleview_refresh-on-attribute-change_01.js]
[browser_ruleview_refresh-on-attribute-change_02.js]
[browser_ruleview_refresh-on-style-change.js]
+[browser_ruleview_search-filter-computed-list_01.js]
+[browser_ruleview_search-filter-computed-list_02.js]
+[browser_ruleview_search-filter-computed-list_03.js]
+[browser_ruleview_search-filter-computed-list_04.js]
+[browser_ruleview_search-filter-computed-list_05.js]
+[browser_ruleview_search-filter-computed-list_06.js]
+[browser_ruleview_search-filter-computed-list_clear.js]
+[browser_ruleview_search-filter-computed-list_expander.js]
[browser_ruleview_search-filter_01.js]
[browser_ruleview_search-filter_02.js]
[browser_ruleview_search-filter_03.js]
diff --git a/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_01.js b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_01.js
new file mode 100644
index 000000000000..adfbcc215d2d
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_01.js
@@ -0,0 +1,66 @@
+/* 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 search filter works properly in the computed list
+// for property values.
+
+const SEARCH = "0px"
+
+let TEST_URI = [
+ '',
+ '
Styled Node
'
+].join("\n");
+
+add_task(function*() {
+ yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+ let {toolbox, inspector, view} = yield openRuleView();
+ yield selectNode("#testid", inspector);
+ yield testAddTextInFilter(inspector, view);
+});
+
+function* testAddTextInFilter(inspector, ruleView) {
+ info("Setting filter text to \"" + SEARCH + "\"");
+
+ let win = ruleView.doc.defaultView;
+ let searchField = ruleView.searchField;
+ let onRuleViewFiltered = inspector.once("ruleview-filtered");
+
+ searchField.focus();
+ synthesizeKeys(SEARCH, win);
+ yield onRuleViewFiltered;
+
+ info("Check that the correct rules are visible");
+ is(ruleView.element.children.length, 2, "Should have 2 rules.");
+ is(getRuleViewRuleEditor(ruleView, 0).rule.selectorText, "element",
+ "First rule is inline element.");
+
+ let rule = getRuleViewRuleEditor(ruleView, 1).rule;
+ let ruleEditor = rule.textProps[0].editor;
+ let computed = ruleEditor.computed;
+
+ is(rule.selectorText, "#testid", "Second rule is #testid.");
+ ok(!ruleEditor.expander.getAttribute("open"), "Expander is closed.");
+ ok(ruleEditor.container.classList.contains("ruleview-highlight"),
+ "margin text property is correctly highlighted.");
+ ok(!computed.classList.contains("filter-open"),
+ "margin computed list is closed.");
+
+ ok(!computed.children[0].classList.contains("ruleview-highlight"),
+ "margin-top computed property is not highlighted.");
+ ok(computed.children[1].classList.contains("ruleview-highlight"),
+ "margin-right computed property is correctly highlighted.");
+ ok(!computed.children[2].classList.contains("ruleview-highlight"),
+ "margin-bottom computed property is not highlighted.");
+ ok(computed.children[3].classList.contains("ruleview-highlight"),
+ "margin-left computed property is correctly highlighted.");
+}
diff --git a/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_02.js b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_02.js
new file mode 100644
index 000000000000..9c5b4f0397dd
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_02.js
@@ -0,0 +1,66 @@
+/* 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 search filter works properly in the computed list
+// for property names.
+
+const SEARCH = "margin"
+
+let TEST_URI = [
+ '',
+ 'Styled Node
'
+].join("\n");
+
+add_task(function*() {
+ yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+ let {toolbox, inspector, view} = yield openRuleView();
+ yield selectNode("#testid", inspector);
+ yield testAddTextInFilter(inspector, view);
+});
+
+function* testAddTextInFilter(inspector, ruleView) {
+ info("Setting filter text to \"" + SEARCH + "\"");
+
+ let win = ruleView.doc.defaultView;
+ let searchField = ruleView.searchField;
+ let onRuleViewFiltered = inspector.once("ruleview-filtered");
+
+ searchField.focus();
+ synthesizeKeys(SEARCH, win);
+ yield onRuleViewFiltered;
+
+ info("Check that the correct rules are visible");
+ is(ruleView.element.children.length, 2, "Should have 2 rules.");
+ is(getRuleViewRuleEditor(ruleView, 0).rule.selectorText, "element",
+ "First rule is inline element.");
+
+ let rule = getRuleViewRuleEditor(ruleView, 1).rule;
+ let ruleEditor = rule.textProps[0].editor;
+ let computed = ruleEditor.computed;
+
+ is(rule.selectorText, "#testid", "Second rule is #testid.");
+ ok(!ruleEditor.expander.getAttribute("open"), "Expander is closed.");
+ ok(ruleEditor.container.classList.contains("ruleview-highlight"),
+ "margin text property is correctly highlighted.");
+ ok(!computed.classList.contains("filter-open"),
+ "margin computed list is closed.");
+
+ ok(computed.children[0].classList.contains("ruleview-highlight"),
+ "margin-top computed property is correctly highlighted.");
+ ok(computed.children[1].classList.contains("ruleview-highlight"),
+ "margin-right computed property is correctly highlighted.");
+ ok(computed.children[2].classList.contains("ruleview-highlight"),
+ "margin-bottom computed property is correctly highlighted.");
+ ok(computed.children[3].classList.contains("ruleview-highlight"),
+ "margin-left computed property is correctly highlighted.");
+}
diff --git a/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_03.js b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_03.js
new file mode 100644
index 000000000000..7034a8496fa1
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_03.js
@@ -0,0 +1,66 @@
+/* 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 search filter works properly in the computed list
+// for property line input.
+
+const SEARCH = "margin-top:4px"
+
+let TEST_URI = [
+ '',
+ 'Styled Node
'
+].join("\n");
+
+add_task(function*() {
+ yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+ let {toolbox, inspector, view} = yield openRuleView();
+ yield selectNode("#testid", inspector);
+ yield testAddTextInFilter(inspector, view);
+});
+
+function* testAddTextInFilter(inspector, ruleView) {
+ info("Setting filter text to \"" + SEARCH + "\"");
+
+ let win = ruleView.doc.defaultView;
+ let searchField = ruleView.searchField;
+ let onRuleViewFiltered = inspector.once("ruleview-filtered");
+
+ searchField.focus();
+ synthesizeKeys(SEARCH, win);
+ yield onRuleViewFiltered;
+
+ info("Check that the correct rules are visible");
+ is(ruleView.element.children.length, 2, "Should have 2 rules.");
+ is(getRuleViewRuleEditor(ruleView, 0).rule.selectorText, "element",
+ "First rule is inline element.");
+
+ let rule = getRuleViewRuleEditor(ruleView, 1).rule;
+ let ruleEditor = rule.textProps[0].editor;
+ let computed = ruleEditor.computed;
+
+ is(rule.selectorText, "#testid", "Second rule is #testid.");
+ ok(ruleEditor.expander.getAttribute("open"), "Expander is open.");
+ ok(!ruleEditor.container.classList.contains("ruleview-highlight"),
+ "margin text property is not highlighted.");
+ ok(computed.classList.contains("filter-open"),
+ "margin computed list is open.");
+
+ ok(computed.children[0].classList.contains("ruleview-highlight"),
+ "margin-top computed property is not highlighted.");
+ ok(!computed.children[1].classList.contains("ruleview-highlight"),
+ "margin-right computed property is not highlighted.");
+ ok(!computed.children[2].classList.contains("ruleview-highlight"),
+ "margin-bottom computed property is not highlighted.");
+ ok(!computed.children[3].classList.contains("ruleview-highlight"),
+ "margin-left computed property is not highlighted.");
+}
diff --git a/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_04.js b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_04.js
new file mode 100644
index 000000000000..a0e92886f739
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_04.js
@@ -0,0 +1,66 @@
+/* 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 search filter works properly in the computed list
+// for parsed property value.
+
+const SEARCH = ":4px"
+
+let TEST_URI = [
+ '',
+ 'Styled Node
'
+].join("\n");
+
+add_task(function*() {
+ yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+ let {toolbox, inspector, view} = yield openRuleView();
+ yield selectNode("#testid", inspector);
+ yield testAddTextInFilter(inspector, view);
+});
+
+function* testAddTextInFilter(inspector, ruleView) {
+ info("Setting filter text to \"" + SEARCH + "\"");
+
+ let win = ruleView.doc.defaultView;
+ let searchField = ruleView.searchField;
+ let onRuleViewFiltered = inspector.once("ruleview-filtered");
+
+ searchField.focus();
+ synthesizeKeys(SEARCH, win);
+ yield onRuleViewFiltered;
+
+ info("Check that the correct rules are visible");
+ is(ruleView.element.children.length, 2, "Should have 2 rules.");
+ is(getRuleViewRuleEditor(ruleView, 0).rule.selectorText, "element",
+ "First rule is inline element.");
+
+ let rule = getRuleViewRuleEditor(ruleView, 1).rule;
+ let ruleEditor = rule.textProps[0].editor;
+ let computed = ruleEditor.computed;
+
+ is(rule.selectorText, "#testid", "Second rule is #testid.");
+ ok(!ruleEditor.expander.getAttribute("open"), "Expander is closed.");
+ ok(ruleEditor.container.classList.contains("ruleview-highlight"),
+ "margin text property is correctly highlighted.");
+ ok(!computed.classList.contains("filter-open"),
+ "margin computed list is closed.");
+
+ ok(computed.children[0].classList.contains("ruleview-highlight"),
+ "margin-top computed property is correctly highlighted.");
+ ok(!computed.children[1].classList.contains("ruleview-highlight"),
+ "margin-right computed property is not highlighted.");
+ ok(computed.children[2].classList.contains("ruleview-highlight"),
+ "margin-bottom computed property is correctly highlighted.");
+ ok(!computed.children[3].classList.contains("ruleview-highlight"),
+ "margin-left computed property is not highlighted.");
+}
diff --git a/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_05.js b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_05.js
new file mode 100644
index 000000000000..c3987d977e5c
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_05.js
@@ -0,0 +1,66 @@
+/* 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 search filter works properly in the computed list
+// for parsed property name.
+
+const SEARCH = "margin-top:"
+
+let TEST_URI = [
+ '',
+ 'Styled Node
'
+].join("\n");
+
+add_task(function*() {
+ yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+ let {toolbox, inspector, view} = yield openRuleView();
+ yield selectNode("#testid", inspector);
+ yield testAddTextInFilter(inspector, view);
+});
+
+function* testAddTextInFilter(inspector, ruleView) {
+ info("Setting filter text to \"" + SEARCH + "\"");
+
+ let win = ruleView.doc.defaultView;
+ let searchField = ruleView.searchField;
+ let onRuleViewFiltered = inspector.once("ruleview-filtered");
+
+ searchField.focus();
+ synthesizeKeys(SEARCH, win);
+ yield onRuleViewFiltered;
+
+ info("Check that the correct rules are visible");
+ is(ruleView.element.children.length, 2, "Should have 2 rules.");
+ is(getRuleViewRuleEditor(ruleView, 0).rule.selectorText, "element",
+ "First rule is inline element.");
+
+ let rule = getRuleViewRuleEditor(ruleView, 1).rule;
+ let ruleEditor = rule.textProps[0].editor;
+ let computed = ruleEditor.computed;
+
+ is(rule.selectorText, "#testid", "Second rule is #testid.");
+ ok(ruleEditor.expander.getAttribute("open"), "Expander is open.");
+ ok(!ruleEditor.container.classList.contains("ruleview-highlight"),
+ "margin text property is not highlighted.");
+ ok(computed.classList.contains("filter-open"),
+ "margin computed list is open.");
+
+ ok(computed.children[0].classList.contains("ruleview-highlight"),
+ "margin-top computed property is correctly highlighted.");
+ ok(!computed.children[1].classList.contains("ruleview-highlight"),
+ "margin-right computed property is not highlighted.");
+ ok(!computed.children[2].classList.contains("ruleview-highlight"),
+ "margin-bottom computed property is not highlighted.");
+ ok(!computed.children[3].classList.contains("ruleview-highlight"),
+ "margin-left computed property is not highlighted.");
+}
diff --git a/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_06.js b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_06.js
new file mode 100644
index 000000000000..4884cc9e0205
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_06.js
@@ -0,0 +1,104 @@
+/* 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 search filter works properly in the computed list
+// when modifying the existing search filter value
+
+const SEARCH = "margin-"
+
+let TEST_URI = [
+ '',
+ 'Styled Node
'
+].join("\n");
+
+add_task(function*() {
+ yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+ let {toolbox, inspector, view} = yield openRuleView();
+ yield selectNode("#testid", inspector);
+ yield testAddTextInFilter(inspector, view);
+ yield testRemoveTextInFilter(inspector, view);
+});
+
+function* testAddTextInFilter(inspector, ruleView) {
+ info("Setting filter text to \"" + SEARCH + "\"");
+
+ let win = ruleView.doc.defaultView;
+ let searchField = ruleView.searchField;
+ let onRuleViewFiltered = inspector.once("ruleview-filtered");
+
+ searchField.focus();
+ synthesizeKeys(SEARCH, win);
+ yield onRuleViewFiltered;
+
+ info("Check that the correct rules are visible");
+ is(ruleView.element.children.length, 2, "Should have 2 rules.");
+ is(getRuleViewRuleEditor(ruleView, 0).rule.selectorText, "element",
+ "First rule is inline element.");
+
+ let rule = getRuleViewRuleEditor(ruleView, 1).rule;
+ let ruleEditor = rule.textProps[0].editor;
+ let computed = ruleEditor.computed;
+
+ is(rule.selectorText, "#testid", "Second rule is #testid.");
+ ok(ruleEditor.expander.getAttribute("open"), "Expander is open.");
+ ok(!ruleEditor.container.classList.contains("ruleview-highlight"),
+ "margin text property is not highlighted.");
+ ok(computed.classList.contains("filter-open"),
+ "margin computed list is open.");
+
+ ok(computed.children[0].classList.contains("ruleview-highlight"),
+ "margin-top computed property is correctly highlighted.");
+ ok(computed.children[1].classList.contains("ruleview-highlight"),
+ "margin-right computed property is correctly highlighted.");
+ ok(computed.children[2].classList.contains("ruleview-highlight"),
+ "margin-bottom computed property is correctly highlighted.");
+ ok(computed.children[3].classList.contains("ruleview-highlight"),
+ "margin-left computed property is correctly highlighted.");
+}
+
+function* testRemoveTextInFilter(inspector, ruleView) {
+ info("Press backspace and set filter text to \"margin\"");
+
+ let win = ruleView.doc.defaultView;
+ let searchField = ruleView.searchField;
+ let onRuleViewFiltered = inspector.once("ruleview-filtered");
+
+ searchField.focus();
+ EventUtils.synthesizeKey("VK_BACK_SPACE", {}, win);
+ yield inspector.once("ruleview-filtered");
+
+ info("Check that the correct rules are visible");
+ is(ruleView.element.children.length, 2, "Should have 2 rules.");
+ is(getRuleViewRuleEditor(ruleView, 0).rule.selectorText, "element",
+ "First rule is inline element.");
+
+ let rule = getRuleViewRuleEditor(ruleView, 1).rule;
+ let ruleEditor = rule.textProps[0].editor;
+ let computed = ruleEditor.computed;
+
+ is(rule.selectorText, "#testid", "Second rule is #testid.");
+ ok(!ruleEditor.expander.getAttribute("open"), "Expander is closed.");
+ ok(ruleEditor.container.classList.contains("ruleview-highlight"),
+ "margin text property is correctly highlighted.");
+ ok(!computed.classList.contains("filter-open"),
+ "margin computed list is closed.");
+
+ ok(computed.children[0].classList.contains("ruleview-highlight"),
+ "margin-top computed property is correctly highlighted.");
+ ok(computed.children[1].classList.contains("ruleview-highlight"),
+ "margin-right computed property is correctly highlighted.");
+ ok(computed.children[2].classList.contains("ruleview-highlight"),
+ "margin-bottom computed property is correctly highlighted.");
+ ok(computed.children[3].classList.contains("ruleview-highlight"),
+ "margin-left computed property is correctly highlighted.");
+}
diff --git a/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_clear.js b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_clear.js
new file mode 100644
index 000000000000..1364793d3e3f
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_clear.js
@@ -0,0 +1,94 @@
+/* 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 search filter clear button works properly and clears
+// the highlighted rules in the computed list.
+
+const SEARCH = "0px"
+
+let TEST_URI = [
+ '',
+ 'Styled Node
'
+].join("\n");
+
+add_task(function*() {
+ yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+ let {toolbox, inspector, view} = yield openRuleView();
+ yield selectNode("#testid", inspector);
+ yield testAddTextInFilter(inspector, view);
+ yield testClearSearchFilter(inspector, view);
+});
+
+function* testAddTextInFilter(inspector, ruleView) {
+ info("Setting filter text to \"" + SEARCH + "\"");
+
+ let win = ruleView.doc.defaultView;
+ let searchField = ruleView.searchField;
+ let onRuleViewFiltered = inspector.once("ruleview-filtered");
+
+ searchField.focus();
+ synthesizeKeys(SEARCH, win);
+ yield onRuleViewFiltered;
+
+ info("Check that the correct rules are visible");
+ is(ruleView.element.children.length, 2, "Should have 2 rules.");
+ is(getRuleViewRuleEditor(ruleView, 0).rule.selectorText, "element",
+ "First rule is inline element.");
+
+ let rule = getRuleViewRuleEditor(ruleView, 1).rule;
+ let ruleEditor = rule.textProps[0].editor;
+ let computed = ruleEditor.computed;
+
+ is(rule.selectorText, "#testid", "Second rule is #testid.");
+ ok(!ruleEditor.expander.getAttribute("open"), "Expander is closed.");
+ ok(ruleEditor.container.classList.contains("ruleview-highlight"),
+ "margin text property is correctly highlighted.");
+ ok(!computed.classList.contains("filter-open"),
+ "margin computed list is closed.");
+
+ ok(!computed.children[0].classList.contains("ruleview-highlight"),
+ "margin-top computed property is not highlighted.");
+ ok(computed.children[1].classList.contains("ruleview-highlight"),
+ "margin-right computed property is correctly highlighted.");
+ ok(!computed.children[2].classList.contains("ruleview-highlight"),
+ "margin-bottom computed property is not highlighted.");
+ ok(computed.children[3].classList.contains("ruleview-highlight"),
+ "margin-left computed property is correctly highlighted.");
+}
+
+function* testClearSearchFilter(inspector, ruleView) {
+ info("Clearing the search filter");
+
+ let doc = ruleView.doc;
+ let win = ruleView.doc.defaultView;
+ let searchField = ruleView.searchField;
+ let searchClearButton = ruleView.searchClearButton;
+ let onRuleViewFiltered = inspector.once("ruleview-filtered");
+
+ EventUtils.synthesizeMouseAtCenter(searchClearButton, {}, win);
+
+ yield onRuleViewFiltered;
+
+ info("Check the search filter is cleared and no rules are highlighted");
+ is(ruleView.element.children.length, 3, "Should have 3 rules.");
+ ok(!searchField.value, "Search filter is cleared");
+ ok(!doc.querySelectorAll(".ruleview-highlight").length,
+ "No rules are higlighted");
+
+ let ruleEditor = getRuleViewRuleEditor(ruleView, 1).rule.textProps[0].editor;
+ let computed = ruleEditor.computed;
+
+ ok(!ruleEditor.expander.getAttribute("open"), "Expander is closed.");
+ ok(!computed.classList.contains("filter-open"),
+ "margin computed list is closed.");
+}
diff --git a/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_expander.js b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_expander.js
new file mode 100644
index 000000000000..ae13c0f9d6bc
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_expander.js
@@ -0,0 +1,99 @@
+/* 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 expanded computed list for a property remains open after
+// clearing the rule view search filter.
+
+const SEARCH = "0px"
+
+let TEST_URI = [
+ '',
+ 'Styled Node
'
+].join("\n");
+
+add_task(function*() {
+ yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+ let {toolbox, inspector, view} = yield openRuleView();
+ yield selectNode("#testid", inspector);
+ yield testOpenExpanderAndAddTextInFilter(inspector, view);
+ yield testClearSearchFilter(inspector, view);
+});
+
+function* testOpenExpanderAndAddTextInFilter(inspector, ruleView) {
+ let win = ruleView.doc.defaultView;
+ let searchField = ruleView.searchField;
+ let onRuleViewFiltered = inspector.once("ruleview-filtered");
+ let rule = getRuleViewRuleEditor(ruleView, 1).rule;
+ let ruleEditor = rule.textProps[0].editor;
+ let computed = ruleEditor.computed;
+
+ info("Opening the computed list of margin property")
+ ruleEditor.expander.click();
+
+ info("Setting filter text to \"" + SEARCH + "\"");
+ searchField.focus();
+ synthesizeKeys(SEARCH, win);
+ yield onRuleViewFiltered;
+
+ info("Check that the correct rules are visible");
+ is(ruleView.element.children.length, 2, "Should have 2 rules.");
+ is(getRuleViewRuleEditor(ruleView, 0).rule.selectorText, "element",
+ "First rule is inline element.");
+
+ is(rule.selectorText, "#testid", "Second rule is #testid.");
+ ok(ruleEditor.expander.getAttribute("open"), "Expander is open.");
+ ok(ruleEditor.container.classList.contains("ruleview-highlight"),
+ "margin text property is correctly highlighted.");
+ ok(!computed.classList.contains("filter-open"),
+ "margin computed list does not contain filter-open class.");
+ ok(computed.classList.contains("styleinspector-open"),
+ "margin computed list contains styleinspector-open class.");
+
+ ok(!computed.children[0].classList.contains("ruleview-highlight"),
+ "margin-top computed property is not highlighted.");
+ ok(computed.children[1].classList.contains("ruleview-highlight"),
+ "margin-right computed property is correctly highlighted.");
+ ok(!computed.children[2].classList.contains("ruleview-highlight"),
+ "margin-bottom computed property is not highlighted.");
+ ok(computed.children[3].classList.contains("ruleview-highlight"),
+ "margin-left computed property is correctly highlighted.");
+}
+
+function* testClearSearchFilter(inspector, ruleView) {
+ info("Clearing the search filter");
+
+ let doc = ruleView.doc;
+ let win = ruleView.doc.defaultView;
+ let searchField = ruleView.searchField;
+ let searchClearButton = ruleView.searchClearButton;
+ let onRuleViewFiltered = inspector.once("ruleview-filtered");
+
+ EventUtils.synthesizeMouseAtCenter(searchClearButton, {}, win);
+
+ yield onRuleViewFiltered;
+
+ info("Check the search filter is cleared and no rules are highlighted");
+ is(ruleView.element.children.length, 3, "Should have 3 rules.");
+ ok(!searchField.value, "Search filter is cleared");
+ ok(!doc.querySelectorAll(".ruleview-highlight").length,
+ "No rules are higlighted");
+
+ let ruleEditor = getRuleViewRuleEditor(ruleView, 1).rule.textProps[0].editor;
+ let computed = ruleEditor.computed;
+
+ ok(ruleEditor.expander.getAttribute("open"), "Expander is open.");
+ ok(!computed.classList.contains("filter-open"),
+ "margin computed list does not contain filter-open class.");
+ ok(computed.classList.contains("styleinspector-open"),
+ "margin computed list contains styleinspector-open class.");
+}
diff --git a/browser/devtools/styleinspector/test/browser_ruleview_search-filter_01.js b/browser/devtools/styleinspector/test/browser_ruleview_search-filter_01.js
index b07a37056c4a..4e29d2ca77dc 100644
--- a/browser/devtools/styleinspector/test/browser_ruleview_search-filter_01.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_search-filter_01.js
@@ -6,6 +6,8 @@
// Tests that the rule view search filter works properly for property values.
+const SEARCH = "00F";
+
let TEST_URI = [
'