Bug 1151956 - Add tooltips with refs to source css rules in the layout-view; r=miker

This commit is contained in:
Patrick Brosset 2015-04-16 18:40:40 +02:00
parent 4cc6d065ad
commit b903d84270
4 changed files with 165 additions and 3 deletions

View File

@ -15,6 +15,7 @@ support-files =
[browser_layoutview_editablemodel_stylerules.js]
[browser_layoutview_guides.js]
[browser_layoutview_rotate-labels-on-sides.js]
[browser_layoutview_tooltips.js]
[browser_layoutview_update-after-navigation.js]
[browser_layoutview_update-after-reload.js]
# [browser_layoutview_update-in-iframes.js]

View File

@ -0,0 +1,126 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that the regions in the layout-view have tooltips, and that individual
// values too. Also test that values that are set from a css rule have tooltips
// referencing the rule.
const TEST_URI = "<style>" +
"#div1 { color: red; margin: 3em; }\n" +
"#div2 { border-bottom: 1px solid black; background: red; }\n" +
"html, body, #div3 { box-sizing: border-box; padding: 0 2em; }" +
"</style>" +
"<div id='div1'></div><div id='div2'></div><div id='div3'></div>";
// Test data for the tooltips over individual values.
// Each entry should contain:
// - selector: The selector for the node to be selected before starting to test
// - values: An array containing objects for each of the values that are defined
// by css rules. Each entry should contain:
// - name: the name of the property that is set by the css rule
// - ruleSelector: the selector of the rule
// - styleSheetLocation: the fileName:lineNumber
const VALUES_TEST_DATA = [{
selector: "#div1",
values: [{
name: "margin-top",
ruleSelector: "#div1",
styleSheetLocation: "null:1"
}, {
name: "margin-right",
ruleSelector: "#div1",
styleSheetLocation: "null:1"
}, {
name: "margin-bottom",
ruleSelector: "#div1",
styleSheetLocation: "null:1"
}, {
name: "margin-left",
ruleSelector: "#div1",
styleSheetLocation: "null:1"
}]
},{
selector: "#div2",
values: [{
name: "border-bottom-width",
ruleSelector: "#div2",
styleSheetLocation: "null:2"
}]
},{
selector: "#div3",
values: [{
name: "padding-top",
ruleSelector: "html, body, #div3",
styleSheetLocation: "null:3"
}, {
name: "padding-right",
ruleSelector: "html, body, #div3",
styleSheetLocation: "null:3"
}, {
name: "padding-bottom",
ruleSelector: "html, body, #div3",
styleSheetLocation: "null:3"
}, {
name: "padding-left",
ruleSelector: "html, body, #div3",
styleSheetLocation: "null:3"
}]
}];
add_task(function*() {
yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
let {toolbox, inspector, view} = yield openLayoutView();
info("Checking the regions tooltips");
ok(view.doc.querySelector("#margins").hasAttribute("title"),
"The margin region has a tooltip");
is(view.doc.querySelector("#margins").getAttribute("title"), "margin",
"The margin region has the correct tooltip content");
ok(view.doc.querySelector("#borders").hasAttribute("title"),
"The border region has a tooltip");
is(view.doc.querySelector("#borders").getAttribute("title"), "border",
"The border region has the correct tooltip content");
ok(view.doc.querySelector("#padding").hasAttribute("title"),
"The padding region has a tooltip");
is(view.doc.querySelector("#padding").getAttribute("title"), "padding",
"The padding region has the correct tooltip content");
ok(view.doc.querySelector("#content").hasAttribute("title"),
"The content region has a tooltip");
is(view.doc.querySelector("#content").getAttribute("title"), "content",
"The content region has the correct tooltip content");
for (let {selector, values} of VALUES_TEST_DATA) {
info("Selecting " + selector + " and checking the values tooltips");
yield selectNode(selector, inspector);
info("Iterate over all values");
for (let key in view.map) {
if (key === "position") {
continue;
}
let name = view.map[key].property;
let expectedTooltipData = values.find(o => o.name === name);
let el = view.doc.querySelector(view.map[key].selector);
ok(el.hasAttribute("title"), "The " + name + " value has a tooltip");
if (expectedTooltipData) {
info("The " + name + " value comes from a css rule");
let expectedTooltip = name + "\n" + expectedTooltipData.ruleSelector +
"\n" + expectedTooltipData.styleSheetLocation;
is(el.getAttribute("title"), expectedTooltip, "The tooltip is correct");
} else {
info("The " + name + " isn't set by a css rule");
is(el.getAttribute("title"), name, "The tooltip is correct");
}
}
}
});

View File

@ -441,6 +441,7 @@ LayoutView.prototype = {
for (let i in this.map) {
let selector = this.map[i].selector;
let span = this.doc.querySelector(selector);
this.updateSourceRuleTooltip(span, this.map[i].property, styleEntries);
if (span.textContent.length > 0 &&
span.textContent == this.map[i].value) {
continue;
@ -469,6 +470,40 @@ LayoutView.prototype = {
return this._lastRequest = lastRequest;
},
/**
* Update the text in the tooltip shown when hovering over a value to provide
* information about the source CSS rule that sets this value.
* @param {DOMNode} el The element that will receive the tooltip.
* @param {String} property The name of the CSS property for the tooltip.
* @param {Array} rules An array of applied rules retrieved by
* styleActor.getApplied.
*/
updateSourceRuleTooltip: function(el, property, rules) {
// Dummy element used to parse the cssText of applied rules.
let dummyEl = this.doc.createElement("div");
// Rules are in order of priority so iterate until we find the first that
// defines a value for the property.
let sourceRule, value;
for (let {rule} of rules) {
dummyEl.style.cssText = rule.cssText;
value = dummyEl.style.getPropertyValue(property);
if (value !== "") {
sourceRule = rule;
break;
}
}
let title = property;
if (sourceRule && sourceRule.selectors) {
title += "\n" + sourceRule.selectors.join(", ");
}
if (sourceRule && sourceRule.parentStyleSheet) {
title += "\n" + sourceRule.parentStyleSheet.href + ":" + sourceRule.line;
}
el.setAttribute("title", title);
},
/**
* Show the box-model highlighter on the currently selected element
* @param {Object} options Options passed to the highlighter actor

View File

@ -30,11 +30,11 @@
<div id="main">
<span class="legend" data-box="margin">&margin.tooltip;</span>
<span class="legend" data-box="margin" title="&margin.tooltip;">&margin.tooltip;</span>
<div id="margins" data-box="margin" title="&margin.tooltip;">
<span class="legend" data-box="border">&border.tooltip;</span>
<span class="legend" data-box="border" title="&border.tooltip;">&border.tooltip;</span>
<div id="borders" data-box="border" title="&border.tooltip;">
<span class="legend" data-box="padding">&padding.tooltip;</span>
<span class="legend" data-box="padding" title="&padding.tooltip;">&padding.tooltip;</span>
<div id="padding" data-box="padding" title="&padding.tooltip;">
<div id="content" data-box="content" title="&content.tooltip;">
</div>