Bug 734934 - [rule view] ability to disable a rule r=gl
MozReview-Commit-ID: 7CA0aGF4R4Y
--- a/devtools/client/inspector/rules/rules.js
+++ b/devtools/client/inspector/rules/rules.js
@@ -973,17 +973,17 @@ CssRuleView.prototype = {
* @return {DOMNode} The container element
*/
createExpandableContainer: function (label, isPseudo = false) {
let header = this.styleDocument.createElementNS(HTML_NS, "div");
header.className = this._getRuleViewHeaderClassName(true);
header.textContent = label;
let twisty = this.styleDocument.createElementNS(HTML_NS, "span");
- twisty.className = "ruleview-expander theme-twisty";
+ twisty.className = "theme-twisty";
twisty.setAttribute("open", "true");
header.insertBefore(twisty, header.firstChild);
this.element.appendChild(header);
let container = this.styleDocument.createElementNS(HTML_NS, "div");
container.classList.add("ruleview-expandable-container");
container.hidden = false;
--- a/devtools/client/inspector/rules/test/browser.ini
+++ b/devtools/client/inspector/rules/test/browser.ini
@@ -243,14 +243,15 @@ skip-if = (os == 'linux' && bits == 32 &
[browser_rules_shapes-toggle_05.js]
[browser_rules_shapes-toggle_06.js]
[browser_rules_shorthand-overridden-lists.js]
[browser_rules_strict-search-filter-computed-list_01.js]
[browser_rules_strict-search-filter_01.js]
[browser_rules_strict-search-filter_02.js]
[browser_rules_strict-search-filter_03.js]
[browser_rules_style-editor-link.js]
+[browser_rules_uncheck_all_rules.js]
skip-if = true # Bug 1309759
[browser_rules_url-click-opens-new-tab.js]
[browser_rules_urls-clickable.js]
[browser_rules_user-agent-styles.js]
[browser_rules_user-agent-styles-uneditable.js]
[browser_rules_user-property-reset.js]
--- a/devtools/client/inspector/rules/test/browser_rules_pseudo-element_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_pseudo-element_01.js
@@ -34,17 +34,17 @@ function* testTopLeft(inspector, view) {
afterRulesNb: 1,
beforeRulesNb: 2
}
);
let gutters = assertGutters(view);
info("Make sure that clicking on the twisty hides pseudo elements");
- let expander = gutters[0].querySelector(".ruleview-expander");
+ let expander = gutters[0].querySelector(".theme-twisty");
ok(!view.element.children[1].hidden, "Pseudo Elements are expanded");
expander.click();
ok(view.element.children[1].hidden,
"Pseudo Elements are collapsed by twisty");
expander.click();
ok(!view.element.children[1].hidden, "Pseudo Elements are expanded again");
@@ -124,17 +124,17 @@ function* testTopRight(inspector, view)
firstLetterRulesNb: 1,
selectionRulesNb: 0,
beforeRulesNb: 2,
afterRulesNb: 1
});
let gutters = assertGutters(view);
- let expander = gutters[0].querySelector(".ruleview-expander");
+ let expander = gutters[0].querySelector(".theme-twisty");
ok(!view.element.firstChild.classList.contains("show-expandable-container"),
"Pseudo Elements remain collapsed after switching element");
expander.scrollIntoView();
expander.click();
ok(!view.element.children[1].hidden,
"Pseudo Elements are shown again after clicking twisty");
}
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/rules/test/browser_rules_uncheck_all_rules.js
@@ -0,0 +1,80 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+// Tests unnchecking and rechecking all rules using select all checkbox
+
+const TEST_URI = `
+ <style type="text/css">
+ #testid {
+ background-color: blue;
+ margin-left: 3px;
+ margin-right: 4px;
+ border-color: black;
+ }
+ .testclass, .unmatched {
+ background-color: green;
+ }
+ </style>
+ <div id="testid" class="testclass">Styled Node</div>
+`;
+
+add_task(function* () {
+ yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+ let {inspector, view} = yield openRuleView();
+ yield selectNode("#testid", inspector);
+ yield testDisableProperty(inspector, view);
+});
+
+function* testDisableProperty(inspector, ruleView) {
+ let enableRule = getRuleViewRuleEditor(ruleView, 1);
+
+ info("Disabling the whole rule");
+ let onRuleViewRefreshed = ruleView.once("ruleview-changed");
+ enableRule.enable.click();
+ yield onRuleViewRefreshed;
+ let newValue = yield executeInContent("Test:GetRulePropertyValue", {
+ styleSheetIndex: 0,
+ ruleIndex: 0,
+ name: "background-color"
+ });
+ is(newValue, "", "background-color should have been unset.");
+ let newValue2 = yield executeInContent("Test:GetRulePropertyValue", {
+ styleSheetIndex: 0,
+ ruleIndex: 0,
+ name: "border-color"
+ });
+ is(newValue2, "", "border-color should have been unset.");
+
+ info("Enabling the whole rule again");
+ onRuleViewRefreshed = ruleView.once("ruleview-changed");
+ enableRule.enable.click();
+ yield onRuleViewRefreshed;
+ newValue = yield executeInContent("Test:GetRulePropertyValue", {
+ styleSheetIndex: 0,
+ ruleIndex: 0,
+ name: "background-color"
+ });
+ is(newValue, "blue", "background-color should have been reset.");
+ newValue2 = yield executeInContent("Test:GetRulePropertyValue", {
+ styleSheetIndex: 0,
+ ruleIndex: 0,
+ name: "border-color"
+ });
+ is(newValue2, "black", "border-color should have been reset.");
+
+ info("Disabling the whole rule again");
+ onRuleViewRefreshed = ruleView.once("ruleview-changed");
+ enableRule.enable.click();
+ yield onRuleViewRefreshed;
+ let idRule = enableRule.rule;
+ let prop = idRule.textProps[0];
+
+ info("Reenabling an individual property");
+ yield togglePropStatus(ruleView, prop);
+
+ let checked = enableRule.enable.hasAttribute("checked");
+ is(checked, false, "Making sure rule checkbox is still unchecked");
+}
--- a/devtools/client/inspector/rules/views/rule-editor.js
+++ b/devtools/client/inspector/rules/views/rule-editor.js
@@ -57,16 +57,17 @@ function RuleEditor(ruleView, rule) {
this.sourceMapURLService = this.toolbox.sourceMapURLService;
this.rule = rule;
this.isEditable = !rule.isSystem;
// Flag that blocks updates of the selector and properties when it is
// being edited
this.isEditing = false;
+ this._onEnableClicked = this._onEnableClicked.bind(this);
this._onNewProperty = this._onNewProperty.bind(this);
this._newPropertyDestroy = this._newPropertyDestroy.bind(this);
this._onSelectorDone = this._onSelectorDone.bind(this);
this._locationChanged = this._locationChanged.bind(this);
this.updateSourceLink = this.updateSourceLink.bind(this);
this._onToolChanged = this._onToolChanged.bind(this);
this._updateLocation = this._updateLocation.bind(this);
this._onSourceClick = this._onSourceClick.bind(this);
@@ -133,16 +134,22 @@ RuleEditor.prototype = {
this.updateSourceLink();
let code = createChild(this.element, "div", {
class: "ruleview-code"
});
let header = createChild(code, "div", {});
+ this.enable = createChild(header, "div", {
+ class: "ruleview-enablerule theme-checkbox"
+ });
+
+ this.enable.setAttribute("checked", "");
+
this.selectorText = createChild(header, "span", {
class: "ruleview-selectorcontainer",
tabindex: this.isSelectorEditable ? "0" : "-1",
});
if (this.isSelectorEditable) {
this.selectorText.addEventListener("click", event => {
// Clicks within the selector shouldn't propagate any further.
@@ -205,16 +212,18 @@ RuleEditor.prototype = {
});
if (this.isEditable) {
// A newProperty editor should only be created when no editor was
// previously displayed. Since the editors are cleared on blur,
// check this.ruleview.isEditing on mousedown
this._ruleViewIsEditing = false;
+ this.enable.addEventListener("click", this._onEnableClicked, true);
+
code.addEventListener("mousedown", () => {
this._ruleViewIsEditing = this.ruleView.isEditing;
});
code.addEventListener("click", () => {
let selection = this.doc.defaultView.getSelection();
if (selection.isCollapsed && !this._ruleViewIsEditing) {
this.newProperty();
@@ -595,16 +604,34 @@ RuleEditor.prototype = {
// If the last new property has no value, focus the value on it.
// Otherwise, start a new property and focus that field.
if (this.multipleAddedProperties && this.multipleAddedProperties.length) {
this.addProperties(this.multipleAddedProperties);
}
},
/**
+ * Handles clicks on the disabled property.
+ */
+ _onEnableClicked: function (event) {
+ let checked = this.enable.hasAttribute("checked");
+ if (checked) {
+ this.enable.removeAttribute("checked");
+ this.enable.style.visibility = "visible";
+ } else {
+ this.enable.setAttribute("checked", "");
+ this.enable.style.removeProperty("visibility");
+ }
+ for (let prop of this.rule.textProps) {
+ prop.setEnabled(!checked);
+ }
+ event.stopPropagation();
+ },
+
+ /**
* Called when the selector's inplace editor is closed.
* Ignores the change if the user pressed escape, otherwise
* commits it.
*
* @param {String} value
* The value contained in the editor.
* @param {Boolean} commit
* True if the change should be applied.
--- a/devtools/client/themes/rules.css
+++ b/devtools/client/themes/rules.css
@@ -140,16 +140,20 @@
visibility: collapse;
transition: visibility 0.25s;
}
.ruleview-code {
direction: ltr;
}
+.ruleview-enablerule:not(:hover) > .ruleview-enablerule {
+ pointer-events: none;
+}
+
.ruleview-property:not(:hover) > .ruleview-enableproperty {
pointer-events: none;
}
.ruleview-expandable-container {
display: block;
}
@@ -241,30 +245,24 @@
color: inherit;
border: none;
margin: 4px 0;
padding: 3px 4px 2px 4px;
line-height: inherit;
min-height: 0;
}
-:root[platform="win"] .ruleview-header,
-:root[platform="linux"] .ruleview-header {
- margin-top: 4px;
-}
-
.ruleview-expandable-header {
cursor: pointer;
}
.ruleview-expandable-header:hover {
background-color: var(--theme-toolbar-background-hover);
}
-
.ruleview-rule-pseudo-element {
padding-left:20px;
border-left: solid 10px;
}
.ruleview-rule {
border-bottom: 1px solid var(--theme-splitter-color);
padding: 2px 4px;
@@ -378,49 +376,62 @@
padding: 0;
margin: 0;
}
.ruleview-rule:not(:hover) .ruleview-enableproperty {
visibility: hidden;
}
+.ruleview-rule:not(:hover) .ruleview-enablerule {
+ visibility: hidden;
+}
+
.ruleview-expander {
- vertical-align: middle;
- display: inline-block;
+ position: relative;
+ float: left;
+ left: -26px;
+ top: 1px;
}
.ruleview-rule .ruleview-expander.theme-twisty:dir(rtl) {
/* for preventing .theme-twisty's wrong direction in rtl; Bug 1296648 */
transform: none;
}
.ruleview-newproperty {
- /* (enable checkbox width: 12px) + (expander width: 15px) */
- margin-inline-start: 27px;
+ margin-inline-start: 2px;
+}
+
+.ruleview-enableproperty {
+ position: relative;
+ float: left;
+ left: -26px;
+ top: 1px;
+}
+
+.ruleview-namecontainer {
+ margin-left: -26px;
}
.ruleview-namecontainer,
.ruleview-propertyvaluecontainer,
.ruleview-propertyname,
.ruleview-propertyvalue {
text-decoration: inherit;
}
.ruleview-computedlist {
+ margin: 0px 0px 0px 10px;
list-style: none;
padding: 0;
}
-.ruleview-computed {
- margin-inline-start: 35px;
-}
-
.ruleview-overridden-items {
- margin: 0px 0px 0px 5px;
+ margin: 0px 0px 0px -21px;
list-style: none;
line-height: 1.5em;
}
.ruleview-overridden-item {
position: relative;
}
@@ -533,16 +544,17 @@
}
.theme-firebug .styleinspector-propertyeditor {
border: 1px solid var(--theme-splitter-color);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.5);
}
.ruleview-property {
+ padding-left: 38px;
border-left: 3px solid transparent;
clear: right;
}
.ruleview-propertycontainer > * {
vertical-align: middle;
}
@@ -560,16 +572,22 @@
border-bottom: 1px dashed transparent;
}
.ruleview-namecontainer:hover > .ruleview-propertyname,
.ruleview-propertyvaluecontainer:hover > .ruleview-propertyvalue {
border-bottom-color: hsl(0,0%,50%);
}
+.ruleview-enablerule {
+ margin-right: 5px;
+ margin-left: 2px;
+ vertical-align: middle;
+}
+
.ruleview-selectorcontainer {
word-wrap: break-word;
cursor: text;
}
.ruleview-selector-separator,
.ruleview-selector-unmatched,
.ruleview-variable-unmatched {