Bug 674856 - The style inspector should not redraw the whole UI every time it is used; r=mihai.sucan

This commit is contained in:
Michael Ratcliffe 2011-09-15 13:30:00 +03:00
Родитель 7c8221c720
Коммит 0134d5eed5
8 изменённых файлов: 350 добавлений и 349 удалений

Просмотреть файл

@ -65,6 +65,7 @@ function CssHtmlTree(aStyleWin, aCssLogic, aPanel)
this.doc = aPanel.ownerDocument;
this.win = this.doc.defaultView;
this.getRTLAttr = CssHtmlTree.getRTLAttr;
this.propertyViews = {};
// The document in which we display the results (csshtmltree.xhtml).
this.styleDocument = this.styleWin.contentWindow.document;
@ -78,8 +79,6 @@ function CssHtmlTree(aStyleWin, aCssLogic, aPanel)
// The element that we're inspecting, and the document that it comes from.
this.viewedElement = null;
this.viewedDocument = null;
this.createStyleViews();
}
@ -148,8 +147,11 @@ XPCOMUtils.defineLazyGetter(CssHtmlTree, "_strings", function() Services.strings
.createBundle("chrome://browser/locale/styleinspector.properties"));
CssHtmlTree.prototype = {
htmlComplete: false,
/**
* Focus the output display on a specific element.
* Update the highlighted element. The CssHtmlTree panel will show the style
* information for the given element.
* @param {nsIDOMElement} aElement The highlighted node to get styles for.
*/
highlight: function CssHtmlTree_highlight(aElement)
@ -160,38 +162,49 @@ CssHtmlTree.prototype = {
this.viewedElement = aElement;
if (this.viewedElement) {
this.viewedDocument = this.viewedElement.ownerDocument;
CssHtmlTree.processTemplate(this.templateRoot, this.root, this);
CssHtmlTree.processTemplate(this.templateRoot, this.root, this);
if (this.htmlComplete) {
this.refreshPanel();
} else {
this.viewedDocument = null;
this.root.innerHTML = "";
}
this.propertyContainer.innerHTML = "";
// We use a setTimeout loop to display the properties in batches of 25 at a
// time. This gives a perceptibly more responsive UI and allows us to cancel
// the displaying of properties in the case that a new element is selected.
let i = 0;
let batchSize = 25;
let max = CssHtmlTree.propertyNames.length - 1;
function displayProperties() {
if (this.viewedElement == aElement && this.panel.isOpen()) {
// Display the next 25 properties
for (let step = i + batchSize; i < step && i <= max; i++) {
let propView = new PropertyView(this, CssHtmlTree.propertyNames[i]);
CssHtmlTree.processTemplate(
this.templateProperty, this.propertyContainer, propView, true);
}
if (i < max) {
// There are still some properties to display. We loop here to display
// the next batch of 25.
this.win.setTimeout(displayProperties.bind(this), 0);
// We use a setTimeout loop to display the properties in batches of 15 at a
// time. This results in a perceptibly more responsive UI.
let i = 0;
let batchSize = 15;
let max = CssHtmlTree.propertyNames.length - 1;
function displayProperties() {
if (this.viewedElement == aElement && this.panel.isOpen()) {
// Display the next 15 properties
for (let step = i + batchSize; i < step && i <= max; i++) {
let name = CssHtmlTree.propertyNames[i];
let propView = new PropertyView(this, name);
CssHtmlTree.processTemplate(this.templateProperty,
this.propertyContainer, propView, true);
propView.refreshMatchedSelectors();
propView.refreshUnmatchedSelectors();
this.propertyViews[name] = propView;
}
if (i < max) {
// There are still some properties to display. We loop here to display
// the next batch of 15.
this.win.setTimeout(displayProperties.bind(this), 50);
} else {
this.htmlComplete = true;
}
}
}
this.win.setTimeout(displayProperties.bind(this), 50);
}
},
/**
* Refresh the panel content.
*/
refreshPanel: function CssHtmlTree_refreshPanel()
{
for each(let propView in this.propertyViews) {
propView.refresh();
}
this.win.setTimeout(displayProperties.bind(this), 0);
},
/**
@ -204,7 +217,6 @@ CssHtmlTree.prototype = {
{
aEvent.preventDefault();
if (aEvent.target && this.viewedElement != aEvent.target.pathElement) {
this.propertyContainer.innerHTML = "";
if (this.win.InspectorUI.selection) {
if (aEvent.target.pathElement != this.win.InspectorUI.selection) {
let elt = aEvent.target.pathElement;
@ -273,53 +285,57 @@ function PropertyView(aTree, aName)
this.name = aName;
this.getRTLAttr = CssHtmlTree.getRTLAttr;
this.populated = false;
this.showUnmatched = false;
this.link = "https://developer.mozilla.org/en/CSS/" + aName;
this.templateRules = aTree.styleDocument.getElementById("templateRules");
// The parent element which contains the open attribute
this.element = null;
// Destination for templateRules.
this.rules = null;
this.str = {};
this.templateMatchedSelectors = aTree.styleDocument.getElementById("templateMatchedSelectors");
this.templateUnmatchedSelectors = aTree.styleDocument.getElementById("templateUnmatchedSelectors");
}
PropertyView.prototype = {
/**
* The click event handler for the property name of the property view. If
* there are >0 rules then the rules are expanded. If there are 0 rules and
* >0 unmatched rules then the unmatched rules are expanded instead.
*
* @param {Event} aEvent the DOM event
*/
click: function PropertyView_click(aEvent)
{
// Clicking on the property link itself is already handled
if (aEvent.target.tagName.toLowerCase() == "a") {
return;
}
// The parent element which contains the open attribute
element: null,
if (this.element.hasAttribute("open")) {
this.element.removeAttribute("open");
return;
}
// Destination for property values
valueNode: null,
if (!this.populated) {
let matchedRuleCount = this.propertyInfo.matchedRuleCount;
// Are matched rules expanded?
matchedExpanded: false,
if (matchedRuleCount == 0 && this.showUnmatchedLink) {
this.showUnmatchedLinkClick(aEvent);
} else {
CssHtmlTree.processTemplate(this.templateRules, this.rules, this);
}
this.populated = true;
}
this.element.setAttribute("open", "");
},
// Are unmatched rules expanded?
unmatchedExpanded: false,
// Matched selector container
matchedSelectorsContainer: null,
// Unmatched selector container
unmatchedSelectorsContainer: null,
// Matched selector expando
matchedExpander: null,
// Unmatched selector expando
unmatchedExpander: null,
// Container for X matched selectors
matchedSelectorsTitleNode: null,
// Container for X unmatched selectors
unmatchedSelectorsTitleNode: null,
// Matched selectors table
matchedSelectorTable: null,
// Unmatched selectors table
unmatchedSelectorTable: null,
// Cache for matched selector views
_matchedSelectorViews: null,
// Cache for unmatched selector views
_unmatchedSelectorViews: null,
// The previously selected element used for the selector view caches
prevViewedElement: null,
/**
* Get the computed style for the current property.
@ -333,7 +349,7 @@ PropertyView.prototype = {
},
/**
* An easy way to access the CssPropertyInfo behind this PropertyView
* An easy way to access the CssPropertyInfo behind this PropertyView.
*/
get propertyInfo()
{
@ -341,106 +357,171 @@ PropertyView.prototype = {
},
/**
* Compute the title of the property view. The title includes the number of
* selectors that match the currently selected element.
* The number of matched selectors.
*/
get matchedSelectorCount()
{
return this.propertyInfo.matchedSelectors.length;
},
/**
* The number of unmatched selectors.
*/
get unmatchedSelectorCount()
{
return this.propertyInfo.unmatchedSelectors.length;
},
/**
* Refresh the panel's CSS property value.
*/
refresh: function PropertyView_refresh()
{
if (!this.tree.viewedElement) {
this.valueNode.innerHTML = "";
this.matchedSelectorsContainer.hidden = true;
this.unmatchedSelectorsContainer.hidden = true;
this.matchedSelectorTable.innerHTML = "";
this.unmatchedSelectorTable.innerHTML = "";
this.matchedExpander.removeAttribute("open");
this.unmatchedExpander.removeAttribute("open");
return;
}
this.valueNode.innerHTML = this.propertyInfo.value;
if (this.prevViewedElement != this.tree.viewedElement) {
this._matchedSelectorViews = null;
this._unmatchedSelectorViews = null;
this.prevViewedElement = this.tree.viewedElement;
}
this.refreshMatchedSelectors();
this.refreshUnmatchedSelectors();
},
/**
* Refresh the panel matched rules.
*/
refreshMatchedSelectors: function PropertyView_refreshMatchedSelectors()
{
this.matchedSelectorsTitleNode.innerHTML = this.matchedSelectorTitle();
this.matchedSelectorsContainer.hidden = this.matchedSelectorCount == 0;
if (this.matchedExpanded && this.matchedSelectorCount > 0) {
CssHtmlTree.processTemplate(this.templateMatchedSelectors,
this.matchedSelectorTable, this);
this.matchedExpander.setAttribute("open", "");
} else {
this.matchedSelectorTable.innerHTML = "";
this.matchedExpander.removeAttribute("open");
}
},
/**
* Refresh the panel unmatched rules.
*/
refreshUnmatchedSelectors: function PropertyView_refreshUnmatchedSelectors() {
this.unmatchedSelectorsTitleNode.innerHTML = this.unmatchedSelectorTitle();
this.unmatchedSelectorsContainer.hidden = this.unmatchedSelectorCount == 0;
if (this.unmatchedExpanded && this.unmatchedSelectorCount > 0) {
CssHtmlTree.processTemplate(this.templateUnmatchedSelectors,
this.unmatchedSelectorTable, this);
this.unmatchedExpander.setAttribute("open", "");
} else {
this.unmatchedSelectorTable.innerHTML = "";
this.unmatchedExpander.removeAttribute("open");
}
},
/**
* Compute the title of the matched selector expander. The title includes the
* number of selectors that match the currently selected element.
*
* @param {nsIDOMElement} aElement reference to the DOM element where the rule
* title needs to be displayed.
* @return {string} The rule title.
*/
ruleTitle: function PropertyView_ruleTitle(aElement)
matchedSelectorTitle: function PropertyView_matchedSelectorTitle()
{
let result = "";
let matchedSelectorCount = this.propertyInfo.matchedSelectors.length;
if (matchedSelectorCount > 0) {
aElement.classList.add("rule-count");
aElement.firstElementChild.className = "expander";
let str = CssHtmlTree.l10n("property.numberOfSelectors");
result = PluralForm.get(matchedSelectorCount, str)
.replace("#1", matchedSelectorCount);
} else if (this.showUnmatchedLink) {
aElement.classList.add("rule-unmatched");
aElement.firstElementChild.className = "expander";
let unmatchedSelectorCount = this.propertyInfo.unmatchedSelectors.length;
let str = CssHtmlTree.l10n("property.numberOfUnmatchedSelectors");
result = PluralForm.get(unmatchedSelectorCount, str)
.replace("#1", unmatchedSelectorCount);
if (this.matchedSelectorCount > 0) {
let str = CssHtmlTree.l10n("property.numberOfMatchedSelectors");
result = PluralForm.get(this.matchedSelectorCount, str)
.replace("#1", this.matchedSelectorCount);
}
return result;
},
/**
* Close the property view.
* Compute the title of the unmatched selector expander. The title includes
* the number of selectors that match the currently selected element.
*
* @return {string} The rule title.
*/
close: function PropertyView_close()
unmatchedSelectorTitle: function PropertyView_unmatchedSelectorTitle()
{
if (this.rules && this.element) {
this.element.removeAttribute("open");
let result = "";
if (this.unmatchedSelectorCount > 0) {
let str = CssHtmlTree.l10n("property.numberOfUnmatchedSelectors");
result = PluralForm.get(this.unmatchedSelectorCount, str)
.replace("#1", this.unmatchedSelectorCount);
}
return result;
},
/**
* Reset the property view.
* Provide access to the matched SelectorViews that we are currently
* displaying.
*/
reset: function PropertyView_reset()
get matchedSelectorViews()
{
this.close();
this.populated = false;
this.showUnmatched = false;
this.element = false;
},
/**
* Provide access to the SelectorViews that we are currently displaying
*/
get selectorViews()
{
var all = [];
function convert(aSelectorInfo) {
all.push(new SelectorView(aSelectorInfo));
if (!this._matchedSelectorViews) {
this._matchedSelectorViews = [];
this.propertyInfo.matchedSelectors.forEach(
function matchedSelectorViews_convert(aSelectorInfo) {
this._matchedSelectorViews.push(new SelectorView(aSelectorInfo));
}, this);
}
this.propertyInfo.matchedSelectors.forEach(convert);
if (this.showUnmatched) {
this.propertyInfo.unmatchedSelectors.forEach(convert);
return this._matchedSelectorViews;
},
/**
* Provide access to the unmatched SelectorViews that we are currently
* displaying.
*/
get unmatchedSelectorViews()
{
if (!this._unmatchedSelectorViews) {
this._unmatchedSelectorViews = [];
this.propertyInfo.unmatchedSelectors.forEach(
function unmatchedSelectorViews_convert(aSelectorInfo) {
this._unmatchedSelectorViews.push(new SelectorView(aSelectorInfo));
}, this);
}
return all;
return this._unmatchedSelectorViews;
},
/**
* Should we display a 'X unmatched rules' link?
* @return {boolean} false if we are already showing the unmatched links or
* if there are none to display, true otherwise.
* The action when a user expands matched selectors.
*/
get showUnmatchedLink()
matchedSelectorsClick: function PropertyView_matchedSelectorsClick(aEvent)
{
return !this.showUnmatched && this.propertyInfo.unmatchedRuleCount > 0;
this.matchedExpanded = !this.matchedExpanded;
this.refreshMatchedSelectors();
aEvent.preventDefault();
},
/**
* The UI has a link to allow the user to display unmatched selectors.
* This provides localized link text.
* The action when a user expands unmatched selectors.
*/
get showUnmatchedLinkText()
unmatchedSelectorsClick: function PropertyView_unmatchedSelectorsClick(aEvent)
{
let smur = CssHtmlTree.l10n("rule.showUnmatchedLink");
let unmatchedSelectorCount = this.propertyInfo.unmatchedSelectors.length;
let plural = PluralForm.get(unmatchedSelectorCount, smur);
return plural.replace("#1", unmatchedSelectorCount);
},
/**
* The action when a user clicks the 'show unmatched' link.
*/
showUnmatchedLinkClick: function PropertyView_showUnmatchedLinkClick(aEvent)
{
this.showUnmatched = true;
CssHtmlTree.processTemplate(this.templateRules, this.rules, this);
this.unmatchedExpanded = !this.unmatchedExpanded;
this.refreshUnmatchedSelectors();
aEvent.preventDefault();
},
};

Просмотреть файл

@ -99,54 +99,85 @@ To visually debug the templates without running firefox, alter the display:none
-->
<div id="templateProperty">
<div class="property-view" save="${element}" dir="${getRTLAttr}">
<div class="property-header" onclick="${click}">
<div class="property-header">
<div class="property-name" dir="${getRTLAttr}">
<a class="link" target="_blank" title="&helpLinkTitle;"
href="${link}">${name}</a>
</div>
<div class="property-value" dir="ltr">${value}</div>
<div class="link" dir="${getRTLAttr}">
<div></div>${ruleTitle(__element)}
</div>
<div save="${valueNode}" class="property-value" dir="ltr">${value}</div>
</div>
<div save="${matchedSelectorsContainer}" class="rulelink" dir="${getRTLAttr}">
<div onclick="${matchedSelectorsClick}" class="rule-matched">
<div save="${matchedExpander}" class="expander"></div>
<div save="${matchedSelectorsTitleNode}">
${matchedSelectorTitle(__element)}
</div>
</div>
<table save="${matchedSelectorTable}" dir="${getRTLAttr}"></table>
</div>
<div save="${unmatchedSelectorsContainer}" class="rulelink" dir="${getRTLAttr}">
<div onclick="${unmatchedSelectorsClick}" class="rule-unmatched">
<div save="${unmatchedExpander}" class="expander"></div>
<div save="${unmatchedSelectorsTitleNode}">
${unmatchedSelectorTitle(__element)}
</div>
</div>
<table save="${unmatchedSelectorTable}" dir="${getRTLAttr}"></table>
</div>
<table class="rules" save="${rules}" dir="${getRTLAttr}"></table>
</div>
</div>
<!--
A templateRules sits inside each templateProperties showing the list of rules
that affect that property. Each needs data like this:
A templateMatchedSelectors sits inside each templateProperties showing the
list of selectors that affect that property. Each needs data like this:
{
selectors: ..., // from cssLogic.getPropertyInfo(x).[un]matchedSelectors
statusText: function(status) {}, // convert rule.status to readable text
showUnmatchedRules: true / false, // show a "more unmatched rules" link
showUnmatchedRulesClick: function() {}, // click event handler for the
"show more unmatched rules"
matchedSelectorViews: ..., // from cssHtmlTree.propertyViews[name].matchedSelectorViews
}
This is a template so the parent does not need to be a table, except that
using a div as the parent causes the DOM to muck with the tr elements
-->
<table id="templateRules">
<loop foreach="selector in ${selectorViews}" if="${selector.selectorInfo.sheetAllowed}">
<tr>
<td dir="ltr" class="rule-text ${selector.statusClass}">
${selector.humanReadableText(__element)}
</td>
<td class="rule-link">
<a target="_blank" href="view-source:${selector.selectorInfo.href}" class="link"
title="${selector.selectorInfo.href}">${selector.selectorInfo.source}</a>
</td>
</tr>
</loop>
<tr if="${showUnmatchedLink}">
<td colspan="4">
<div class="expander unmatched-rule"></div>
<div class="unmatched">
<a href="#" onclick="${showUnmatchedLinkClick}" class="unmatchedlink">${showUnmatchedLinkText}</a>
</div>
</td>
</tr>
</table>
<div id="templateMatchedSelectors">
<table>
<loop foreach="selector in ${matchedSelectorViews}">
<tr>
<td dir="ltr" class="rule-text ${selector.statusClass}">
${selector.humanReadableText(__element)}
</td>
<td class="rule-link">
<a target="_blank" href="view-source:${selector.selectorInfo.href}" class="link"
title="${selector.selectorInfo.href}">${selector.selectorInfo.source}</a>
</td>
</tr>
</loop>
</table>
</div>
<!--
A templateUnmatchedSelectors sits inside each templateProperties showing the
list of selectors that fail to affect that property. Each needs data like this:
{
unmatchedSelectorViews: ..., // from cssHtmlTree.propertyViews[name].unmatchedSelectorViews
}
This is a template so the parent does not need to be a table, except that
using a div as the parent causes the DOM to muck with the tr elements
-->
<div id="templateUnmatchedSelectors">
<table>
<loop foreach="selector in ${unmatchedSelectorViews}">
<tr>
<td dir="ltr" class="rule-text unmatched">
${selector.humanReadableText(__element)}
</td>
<td class="rule-link">
<a target="_blank" href="view-source:${selector.selectorInfo.href}" class="link"
title="${selector.selectorInfo.href}">${selector.selectorInfo.source}</a>
</td>
</tr>
</loop>
</table>
</div>
</div>
</body>

Просмотреть файл

@ -61,16 +61,15 @@ function testMatchedSelectors()
is(numMatchedSelectors, 6,
"CssLogic returns the correct number of matched selectors for div");
let dummy = content.document.getElementById("dummy");
let returnedRuleTitle = propertyView.ruleTitle(dummy);
let str = CssHtmlTree.l10n("property.numberOfSelectors");
let calculatedRuleTitle = PluralForm.get(numMatchedSelectors, str)
let returnedSelectorTitle = propertyView.matchedSelectorTitle();
let str = CssHtmlTree.l10n("property.numberOfMatchedSelectors");
let calculatedSelectorTitle = PluralForm.get(numMatchedSelectors, str)
.replace("#1", numMatchedSelectors);
info("returnedRuleTitle: '" + returnedRuleTitle + "'");
info("returnedSelectorTitle: '" + returnedSelectorTitle + "'");
is(returnedRuleTitle, calculatedRuleTitle,
"returned title for matched rules is correct");
is(returnedSelectorTitle, calculatedSelectorTitle,
"returned title for matched selectors is correct");
}
function testUnmatchedSelectors()
@ -93,16 +92,15 @@ function testUnmatchedSelectors()
is(numUnmatchedSelectors, 13,
"CssLogic returns the correct number of unmatched selectors for body");
let dummy = content.document.getElementById("dummy");
let returnedRuleTitle = propertyView.ruleTitle(dummy);
let returnedSelectorTitle = propertyView.unmatchedSelectorTitle();
let str = CssHtmlTree.l10n("property.numberOfUnmatchedSelectors");
let calculatedRuleTitle = PluralForm.get(numUnmatchedSelectors, str)
let calculatedSelectorTitle = PluralForm.get(numUnmatchedSelectors, str)
.replace("#1", numUnmatchedSelectors);
info("returnedRuleTitle: '" + returnedRuleTitle + "'");
info("returnedSelectorTitle: '" + returnedSelectorTitle + "'");
is(returnedRuleTitle, calculatedRuleTitle,
"returned title for unmatched rules is correct");
is(returnedSelectorTitle, calculatedSelectorTitle,
"returned title for unmatched selectors is correct");
}
function finishUp()

Просмотреть файл

@ -4438,7 +4438,7 @@ function JSTermHelper(aJSTerm)
if (!errstr) {
let stylePanel = StyleInspector.createPanel();
stylePanel.setAttribute("hudToolId", aJSTerm.hudId);
stylePanel.selectNode(aNode, true);
stylePanel.selectNode(aNode);
} else {
aJSTerm.writeOutput(errstr + "\n", CATEGORY_OUTPUT, SEVERITY_ERROR);
}

Просмотреть файл

@ -3,11 +3,11 @@
# LOCALIZATION NOTE (panelTitle): This is the panel title
panelTitle=Style Inspector
# LOCALIZATION NOTE (property.numberOfSelectors): For each style property the
# LOCALIZATION NOTE (property.numberOfMatchedSelectors): For each style property the
# panel shows the number of selectors which match the currently selected
# element, counted from all stylesheets in the web page inspected.
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
property.numberOfSelectors=1 selector;#1 selectors
property.numberOfMatchedSelectors=1 matched selector;#1 matched selectors
# LOCALIZATION NOTE (property.numberOfUnmatchedSelectors): For each style
# property the panel shows the number of selectors which do not match the
@ -32,13 +32,6 @@ rule.status.UNMATCHED=Unmatched
rule.sourceInline=inline
rule.sourceElement=element
# LOCALIZATION NOTE (rule.showUnmatchedLink): For each style
# property the panel shows the number of selectors which do not match the
# currently selected element, counted from all stylesheets in the web page
# inspected.
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
rule.showUnmatchedLink=1 unmatched selector…;#1 unmatched selectors…
# LOCALIZATION NOTE (group): Style properties are displayed in categories and
# these are the category names.
group.Text_Fonts_and_Color=Text, Fonts & Color

Просмотреть файл

@ -71,15 +71,6 @@ body {
content: "";
}
#header,
#footer {
padding: 5px;
}
#header label {
font-weight: bold;
}
.property-header {
padding: 2px 5px;
background: -moz-linear-gradient(top, #F8F8F8, #E8E8E8);
@ -87,63 +78,52 @@ body {
}
.property-name,
.property-value,
.rule-count,
.rule-matched,
.rule-unmatched {
cursor: pointer;
}
/* Take away these two :visited rules to get a core dumper */
/* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
.link,
.unmatchedlink {
.link {
color: #55A;
}
.link:visited,
.unmatchedlink:visited {
.link:visited {
color: #55A;
}
a.link,
a.unmatchedlink {
a.link {
text-decoration: none;
cursor: pointer;
}
a.link:visited,
a.unmatchedlink:visited {
a.link:visited {
text-decoration: none;
}
.rule-count,
.rule-matched,
.rule-unmatched {
padding: 5px 0 0 15px;
padding: 2px 0;
white-space: nowrap;
}
.unmatched {
display: inline-block;
.rulelink {
color: #55A;
}
.expander {
width: 8px;
height: 8px;
display: inline-block;
float: left;
-moz-margin-start: 15px;
-moz-margin-end: 5px;
margin-bottom: 1px;
margin-top: 3px;
background: url("chrome://browser/skin/devtools/arrows.png");
}
.unmatched-rule {
-moz-margin-start: 25px;
background-position: 24px 0;
}
.property-view .rule-count .expander,
.property-view .rule-unmatched .expander {
background-position: 24px 0;
}
.property-view[dir="rtl"] .rule-count .expander,
.property-view[dir="rtl"] .rule-unmatched .expander {
.expander[dir="rtl"] {
background-position: 16px 0;
}
.property-view[open] .rule-count .expander,
.property-view[open] .rule-unmatched .expander {
.expander[open] {
background-position: 8px 0;
}
@ -158,20 +138,6 @@ a.unmatchedlink:visited {
font-size: 10px;
}
.property-view > .rules {
display: none;
}
.property-view[open] > .rules {
display: table;
}
.rules {
-moz-margin-start: 32px;
max-height: 350px;
overflow-y: auto;
}
.rule-status {
white-space: nowrap;
}
.rule-link {
text-align: end;
-moz-padding-start: 10px;

Просмотреть файл

@ -71,15 +71,6 @@ body {
content: "";
}
#header,
#footer {
padding: 5px;
}
#header label {
font-weight: bold;
}
.property-header {
padding: 2px 5px;
background: -moz-linear-gradient(top, #F8F8F8, #E8E8E8);
@ -87,63 +78,52 @@ body {
}
.property-name,
.property-value,
.rule-count,
.rule-matched,
.rule-unmatched {
cursor: pointer;
}
/* Take away these two :visited rules to get a core dumper */
/* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
.link,
.unmatchedlink {
.link {
color: #55A;
}
.link:visited,
.unmatchedlink:visited {
.link:visited {
color: #55A;
}
a.link,
a.unmatchedlink {
a.link {
text-decoration: none;
cursor: pointer;
}
a.link:visited,
a.unmatchedlink:visited {
a.link:visited {
text-decoration: none;
}
.rule-count,
.rule-matched,
.rule-unmatched {
padding: 5px 0 0 15px;
padding: 2px 0;
white-space: nowrap;
}
.unmatched {
display: inline-block;
.rulelink {
color: #55A;
}
.expander {
width: 8px;
height: 8px;
display: inline-block;
float: left;
-moz-margin-start: 15px;
-moz-margin-end: 5px;
margin-bottom: 1px;
margin-top: 3px;
background: url("chrome://browser/skin/devtools/arrows.png");
}
.unmatched-rule {
-moz-margin-start: 25px;
background-position: 24px 0;
}
.property-view .rule-count .expander,
.property-view .rule-unmatched .expander {
background-position: 24px 0;
}
.property-view[dir="rtl"] .rule-count .expander,
.property-view[dir="rtl"] .rule-unmatched .expander {
.expander[dir="rtl"] {
background-position: 16px 0;
}
.property-view[open] .rule-count .expander,
.property-view[open] .rule-unmatched .expander {
.expander[open] {
background-position: 8px 0;
}
@ -158,20 +138,6 @@ a.unmatchedlink:visited {
font-size: 10px;
}
.property-view > .rules {
display: none;
}
.property-view[open] > .rules {
display: table;
}
.rules {
-moz-margin-start: 32px;
max-height: 350px;
overflow-y: auto;
}
.rule-status {
white-space: nowrap;
}
.rule-link {
text-align: end;
-moz-padding-start: 10px;

Просмотреть файл

@ -71,15 +71,6 @@ body {
content: "";
}
#header,
#footer {
padding: 5px;
}
#header label {
font-weight: bold;
}
.property-header {
padding: 2px 5px;
background: -moz-linear-gradient(top, #F8F8F8, #E8E8E8);
@ -87,63 +78,52 @@ body {
}
.property-name,
.property-value,
.rule-count,
.rule-matched,
.rule-unmatched {
cursor: pointer;
}
/* Take away these two :visited rules to get a core dumper */
/* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
.link,
.unmatchedlink {
.link {
color: #55A;
}
.link:visited,
.unmatchedlink:visited {
.link:visited {
color: #55A;
}
a.link,
a.unmatchedlink {
a.link {
text-decoration: none;
cursor: pointer;
}
a.link:visited,
a.unmatchedlink:visited {
a.link:visited {
text-decoration: none;
}
.rule-count,
.rule-matched,
.rule-unmatched {
padding: 5px 0 0 15px;
padding: 2px 0;
white-space: nowrap;
}
.unmatched {
display: inline-block;
.rulelink {
color: #55A;
}
.expander {
width: 8px;
height: 8px;
display: inline-block;
float: left;
-moz-margin-start: 15px;
-moz-margin-end: 5px;
margin-bottom: 1px;
margin-top: 3px;
background: url("chrome://browser/skin/devtools/arrows.png");
}
.unmatched-rule {
-moz-margin-start: 25px;
background-position: 24px 0;
}
.property-view .rule-count .expander,
.property-view .rule-unmatched .expander {
background-position: 24px 0;
}
.property-view[dir="rtl"] .rule-count .expander,
.property-view[dir="rtl"] .rule-unmatched .expander {
.expander[dir="rtl"] {
background-position: 16px 0;
}
.property-view[open] .rule-count .expander,
.property-view[open] .rule-unmatched .expander {
.expander[open] {
background-position: 8px 0;
}
@ -158,20 +138,6 @@ a.unmatchedlink:visited {
font-size: 10px;
}
.property-view > .rules {
display: none;
}
.property-view[open] > .rules {
display: table;
}
.rules {
-moz-margin-start: 32px;
max-height: 350px;
overflow-y: auto;
}
.rule-status {
white-space: nowrap;
}
.rule-link {
text-align: end;
-moz-padding-start: 10px;