mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backout part 2 - Bug 689759 rev b73aa0bd2b4e, Bug 698762 rev 2967e93cdb44, a=bustage
This commit is contained in:
parent
71a79442ad
commit
f008e40078
@ -81,9 +81,6 @@ function CssHtmlTree(aStyleInspector)
|
|||||||
this.templateProperty = this.styleDocument.getElementById("templateProperty");
|
this.templateProperty = this.styleDocument.getElementById("templateProperty");
|
||||||
this.panel = aStyleInspector.panel;
|
this.panel = aStyleInspector.panel;
|
||||||
|
|
||||||
// No results text.
|
|
||||||
this.noResults = this.styleDocument.getElementById("noResults");
|
|
||||||
|
|
||||||
// The element that we're inspecting, and the document that it comes from.
|
// The element that we're inspecting, and the document that it comes from.
|
||||||
this.viewedElement = null;
|
this.viewedElement = null;
|
||||||
this.createStyleViews();
|
this.createStyleViews();
|
||||||
@ -136,8 +133,9 @@ XPCOMUtils.defineLazyGetter(CssHtmlTree, "_strings", function() Services.strings
|
|||||||
.createBundle("chrome://browser/locale/devtools/styleinspector.properties"));
|
.createBundle("chrome://browser/locale/devtools/styleinspector.properties"));
|
||||||
|
|
||||||
CssHtmlTree.prototype = {
|
CssHtmlTree.prototype = {
|
||||||
// Cache the list of properties that have matched properties.
|
// Cache the list of properties that have matched and unmatched properties.
|
||||||
_matchedProperties: null,
|
_matchedProperties: null,
|
||||||
|
_unmatchedProperties: null,
|
||||||
|
|
||||||
htmlComplete: false,
|
htmlComplete: false,
|
||||||
|
|
||||||
@ -156,9 +154,6 @@ CssHtmlTree.prototype = {
|
|||||||
// Toggle for zebra striping
|
// Toggle for zebra striping
|
||||||
_darkStripe: true,
|
_darkStripe: true,
|
||||||
|
|
||||||
// Number of visible properties
|
|
||||||
numVisibleProperties: 0,
|
|
||||||
|
|
||||||
get showOnlyUserStyles()
|
get showOnlyUserStyles()
|
||||||
{
|
{
|
||||||
return this.onlyUserStylesCheckbox.checked;
|
return this.onlyUserStylesCheckbox.checked;
|
||||||
@ -176,6 +171,7 @@ CssHtmlTree.prototype = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.viewedElement = aElement;
|
this.viewedElement = aElement;
|
||||||
|
this._unmatchedProperties = null;
|
||||||
this._matchedProperties = null;
|
this._matchedProperties = null;
|
||||||
|
|
||||||
CssHtmlTree.processTemplate(this.templatePath, this.path, this);
|
CssHtmlTree.processTemplate(this.templatePath, this.path, this);
|
||||||
@ -202,10 +198,7 @@ CssHtmlTree.prototype = {
|
|||||||
let propView = new PropertyView(this, name);
|
let propView = new PropertyView(this, name);
|
||||||
CssHtmlTree.processTemplate(this.templateProperty,
|
CssHtmlTree.processTemplate(this.templateProperty,
|
||||||
this.propertyContainer, propView, true);
|
this.propertyContainer, propView, true);
|
||||||
if (propView.visible) {
|
propView.refreshAllSelectors();
|
||||||
this.numVisibleProperties++;
|
|
||||||
}
|
|
||||||
propView.refreshMatchedSelectors();
|
|
||||||
this.propertyViews.push(propView);
|
this.propertyViews.push(propView);
|
||||||
}
|
}
|
||||||
if (i < max) {
|
if (i < max) {
|
||||||
@ -216,7 +209,6 @@ CssHtmlTree.prototype = {
|
|||||||
} else {
|
} else {
|
||||||
this.htmlComplete = true;
|
this.htmlComplete = true;
|
||||||
this._panelRefreshTimeout = null;
|
this._panelRefreshTimeout = null;
|
||||||
this.noResults.hidden = this.numVisibleProperties ? true : false;
|
|
||||||
Services.obs.notifyObservers(null, "StyleInspector-populated", null);
|
Services.obs.notifyObservers(null, "StyleInspector-populated", null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -235,11 +227,6 @@ CssHtmlTree.prototype = {
|
|||||||
this.win.clearTimeout(this._panelRefreshTimeout);
|
this.win.clearTimeout(this._panelRefreshTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.noResults.hidden = true;
|
|
||||||
|
|
||||||
// Reset visible property count
|
|
||||||
this.numVisibleProperties = 0;
|
|
||||||
|
|
||||||
// Reset zebra striping.
|
// Reset zebra striping.
|
||||||
this._darkStripe = true;
|
this._darkStripe = true;
|
||||||
|
|
||||||
@ -259,7 +246,6 @@ CssHtmlTree.prototype = {
|
|||||||
this._panelRefreshTimeout = this.win.setTimeout(refreshView.bind(this), 15);
|
this._panelRefreshTimeout = this.win.setTimeout(refreshView.bind(this), 15);
|
||||||
} else {
|
} else {
|
||||||
this._panelRefreshTimeout = null;
|
this._panelRefreshTimeout = null;
|
||||||
this.noResults.hidden = this.numVisibleProperties ? true : false;
|
|
||||||
Services.obs.notifyObservers(null, "StyleInspector-populated", null);
|
Services.obs.notifyObservers(null, "StyleInspector-populated", null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -373,6 +359,41 @@ CssHtmlTree.prototype = {
|
|||||||
return this._matchedProperties;
|
return this._matchedProperties;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a property has unmatched selectors. Result is cached.
|
||||||
|
*
|
||||||
|
* @param {string} aProperty the name of the property you want to check.
|
||||||
|
* @return {boolean} true if the property has unmatched selectors, false
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
hasUnmatchedSelectors: function CssHtmlTree_hasUnmatchedSelectors(aProperty)
|
||||||
|
{
|
||||||
|
// Initially check all of the properties that return false for
|
||||||
|
// hasMatchedSelectors(). This speeds-up the UI.
|
||||||
|
if (!this._unmatchedProperties) {
|
||||||
|
let properties = [];
|
||||||
|
CssHtmlTree.propertyNames.forEach(function(aName) {
|
||||||
|
if (!this.matchedProperties[aName]) {
|
||||||
|
properties.push(aName);
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
if (properties.indexOf(aProperty) == -1) {
|
||||||
|
properties.push(aProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._unmatchedProperties = this.cssLogic.hasUnmatchedSelectors(properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lazy-get the result for properties we do not have cached.
|
||||||
|
if (!(aProperty in this._unmatchedProperties)) {
|
||||||
|
let result = this.cssLogic.hasUnmatchedSelectors([aProperty]);
|
||||||
|
this._unmatchedProperties[aProperty] = result[aProperty];
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._unmatchedProperties[aProperty];
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor for CssHtmlTree.
|
* Destructor for CssHtmlTree.
|
||||||
*/
|
*/
|
||||||
@ -423,6 +444,7 @@ function PropertyView(aTree, aName)
|
|||||||
this.link = "https://developer.mozilla.org/en/CSS/" + aName;
|
this.link = "https://developer.mozilla.org/en/CSS/" + aName;
|
||||||
|
|
||||||
this.templateMatchedSelectors = aTree.styleDocument.getElementById("templateMatchedSelectors");
|
this.templateMatchedSelectors = aTree.styleDocument.getElementById("templateMatchedSelectors");
|
||||||
|
this.templateUnmatchedSelectors = aTree.styleDocument.getElementById("templateUnmatchedSelectors");
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyView.prototype = {
|
PropertyView.prototype = {
|
||||||
@ -438,15 +460,33 @@ PropertyView.prototype = {
|
|||||||
// Are matched rules expanded?
|
// Are matched rules expanded?
|
||||||
matchedExpanded: false,
|
matchedExpanded: false,
|
||||||
|
|
||||||
|
// Are unmatched rules expanded?
|
||||||
|
unmatchedExpanded: false,
|
||||||
|
|
||||||
|
// Unmatched selector table
|
||||||
|
unmatchedSelectorTable: null,
|
||||||
|
|
||||||
// Matched selector container
|
// Matched selector container
|
||||||
matchedSelectorsContainer: null,
|
matchedSelectorsContainer: null,
|
||||||
|
|
||||||
// Matched selector expando
|
// Matched selector expando
|
||||||
matchedExpander: null,
|
matchedExpander: null,
|
||||||
|
|
||||||
|
// Unmatched selector expando
|
||||||
|
unmatchedExpander: null,
|
||||||
|
|
||||||
|
// Unmatched selector container
|
||||||
|
unmatchedSelectorsContainer: null,
|
||||||
|
|
||||||
|
// Unmatched title block
|
||||||
|
unmatchedTitleBlock: null,
|
||||||
|
|
||||||
// Cache for matched selector views
|
// Cache for matched selector views
|
||||||
_matchedSelectorViews: null,
|
_matchedSelectorViews: null,
|
||||||
|
|
||||||
|
// Cache for unmatched selector views
|
||||||
|
_unmatchedSelectorViews: null,
|
||||||
|
|
||||||
// The previously selected element used for the selector view caches
|
// The previously selected element used for the selector view caches
|
||||||
prevViewedElement: null,
|
prevViewedElement: null,
|
||||||
|
|
||||||
@ -477,6 +517,14 @@ PropertyView.prototype = {
|
|||||||
return this.tree.matchedProperties[this.name];
|
return this.tree.matchedProperties[this.name];
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the property have any unmatched selectors?
|
||||||
|
*/
|
||||||
|
get hasUnmatchedSelectors()
|
||||||
|
{
|
||||||
|
return this.tree.hasUnmatchedSelectors(this.name);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should this property be visible?
|
* Should this property be visible?
|
||||||
*/
|
*/
|
||||||
@ -520,20 +568,23 @@ PropertyView.prototype = {
|
|||||||
|
|
||||||
if (this.prevViewedElement != this.tree.viewedElement) {
|
if (this.prevViewedElement != this.tree.viewedElement) {
|
||||||
this._matchedSelectorViews = null;
|
this._matchedSelectorViews = null;
|
||||||
|
this._unmatchedSelectorViews = null;
|
||||||
this.prevViewedElement = this.tree.viewedElement;
|
this.prevViewedElement = this.tree.viewedElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.tree.viewedElement || !this.visible) {
|
if (!this.tree.viewedElement || !this.visible) {
|
||||||
this.valueNode.innerHTML = "";
|
this.valueNode.innerHTML = "";
|
||||||
this.matchedSelectorsContainer.hidden = true;
|
this.matchedSelectorsContainer.hidden = true;
|
||||||
|
this.unmatchedSelectorsContainer.hidden = true;
|
||||||
|
this.unmatchedSelectorTable.innerHTML = "";
|
||||||
this.matchedSelectorsContainer.innerHTML = "";
|
this.matchedSelectorsContainer.innerHTML = "";
|
||||||
this.matchedExpander.removeAttribute("open");
|
this.matchedExpander.removeAttribute("open");
|
||||||
|
this.unmatchedExpander.removeAttribute("open");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.tree.numVisibleProperties++;
|
|
||||||
this.valueNode.innerHTML = this.propertyInfo.value;
|
this.valueNode.innerHTML = this.propertyInfo.value;
|
||||||
this.refreshMatchedSelectors();
|
this.refreshAllSelectors();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -544,7 +595,7 @@ PropertyView.prototype = {
|
|||||||
let hasMatchedSelectors = this.hasMatchedSelectors;
|
let hasMatchedSelectors = this.hasMatchedSelectors;
|
||||||
this.matchedSelectorsContainer.hidden = !hasMatchedSelectors;
|
this.matchedSelectorsContainer.hidden = !hasMatchedSelectors;
|
||||||
|
|
||||||
if (hasMatchedSelectors) {
|
if (hasMatchedSelectors || this.hasUnmatchedSelectors) {
|
||||||
this.propertyHeader.classList.add("expandable");
|
this.propertyHeader.classList.add("expandable");
|
||||||
} else {
|
} else {
|
||||||
this.propertyHeader.classList.remove("expandable");
|
this.propertyHeader.classList.remove("expandable");
|
||||||
@ -560,6 +611,52 @@ PropertyView.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh the panel unmatched rules.
|
||||||
|
*/
|
||||||
|
refreshUnmatchedSelectors: function PropertyView_refreshUnmatchedSelectors()
|
||||||
|
{
|
||||||
|
let hasMatchedSelectors = this.hasMatchedSelectors;
|
||||||
|
|
||||||
|
this.unmatchedSelectorTable.hidden = !this.unmatchedExpanded;
|
||||||
|
|
||||||
|
if (hasMatchedSelectors) {
|
||||||
|
this.unmatchedSelectorsContainer.hidden = !this.matchedExpanded ||
|
||||||
|
!this.hasUnmatchedSelectors;
|
||||||
|
this.unmatchedTitleBlock.hidden = false;
|
||||||
|
} else {
|
||||||
|
this.unmatchedSelectorsContainer.hidden = !this.unmatchedExpanded;
|
||||||
|
this.unmatchedTitleBlock.hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.unmatchedExpanded && this.hasUnmatchedSelectors) {
|
||||||
|
CssHtmlTree.processTemplate(this.templateUnmatchedSelectors,
|
||||||
|
this.unmatchedSelectorTable, this);
|
||||||
|
if (!hasMatchedSelectors) {
|
||||||
|
this.matchedExpander.setAttribute("open", "");
|
||||||
|
this.unmatchedSelectorTable.classList.add("only-unmatched");
|
||||||
|
} else {
|
||||||
|
this.unmatchedExpander.setAttribute("open", "");
|
||||||
|
this.unmatchedSelectorTable.classList.remove("only-unmatched");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!hasMatchedSelectors) {
|
||||||
|
this.matchedExpander.removeAttribute("open");
|
||||||
|
}
|
||||||
|
this.unmatchedExpander.removeAttribute("open");
|
||||||
|
this.unmatchedSelectorTable.innerHTML = "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh the panel matched and unmatched rules
|
||||||
|
*/
|
||||||
|
refreshAllSelectors: function PropertyView_refreshAllSelectors()
|
||||||
|
{
|
||||||
|
this.refreshMatchedSelectors();
|
||||||
|
this.refreshUnmatchedSelectors();
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide access to the matched SelectorViews that we are currently
|
* Provide access to the matched SelectorViews that we are currently
|
||||||
* displaying.
|
* displaying.
|
||||||
@ -573,9 +670,27 @@ PropertyView.prototype = {
|
|||||||
this._matchedSelectorViews.push(new SelectorView(this.tree, aSelectorInfo));
|
this._matchedSelectorViews.push(new SelectorView(this.tree, aSelectorInfo));
|
||||||
}, this);
|
}, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._matchedSelectorViews;
|
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(this.tree, aSelectorInfo));
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._unmatchedSelectorViews;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The action when a user expands matched selectors.
|
* The action when a user expands matched selectors.
|
||||||
*
|
*
|
||||||
@ -587,11 +702,24 @@ PropertyView.prototype = {
|
|||||||
{
|
{
|
||||||
if (aEvent.target.className != "helplink") {
|
if (aEvent.target.className != "helplink") {
|
||||||
this.matchedExpanded = !this.matchedExpanded;
|
this.matchedExpanded = !this.matchedExpanded;
|
||||||
this.refreshMatchedSelectors();
|
if (!this.hasMatchedSelectors && this.hasUnmatchedSelectors) {
|
||||||
|
this.unmatchedExpanded = !this.unmatchedExpanded;
|
||||||
|
}
|
||||||
|
this.refreshAllSelectors();
|
||||||
aEvent.preventDefault();
|
aEvent.preventDefault();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The action when a user expands unmatched selectors.
|
||||||
|
*/
|
||||||
|
unmatchedSelectorsClick: function PropertyView_unmatchedSelectorsClick(aEvent)
|
||||||
|
{
|
||||||
|
this.unmatchedExpanded = !this.unmatchedExpanded;
|
||||||
|
this.refreshUnmatchedSelectors();
|
||||||
|
aEvent.preventDefault();
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The action when a user clicks on the MDN help link for a property.
|
* The action when a user clicks on the MDN help link for a property.
|
||||||
*/
|
*/
|
||||||
@ -620,11 +748,11 @@ function SelectorView(aTree, aSelectorInfo)
|
|||||||
* @see CssLogic.STATUS
|
* @see CssLogic.STATUS
|
||||||
*/
|
*/
|
||||||
SelectorView.STATUS_NAMES = [
|
SelectorView.STATUS_NAMES = [
|
||||||
// "Parent Match", "Matched", "Best Match"
|
// "Unmatched", "Parent Match", "Matched", "Best Match"
|
||||||
];
|
];
|
||||||
|
|
||||||
SelectorView.CLASS_NAMES = [
|
SelectorView.CLASS_NAMES = [
|
||||||
"parentmatch", "matched", "bestmatch"
|
"unmatched", "parentmatch", "matched", "bestmatch"
|
||||||
];
|
];
|
||||||
|
|
||||||
SelectorView.prototype = {
|
SelectorView.prototype = {
|
||||||
@ -645,7 +773,7 @@ SelectorView.prototype = {
|
|||||||
|
|
||||||
for (let status in CssLogic.STATUS) {
|
for (let status in CssLogic.STATUS) {
|
||||||
let i = CssLogic.STATUS[status];
|
let i = CssLogic.STATUS[status];
|
||||||
if (i > CssLogic.STATUS.UNKNOWN) {
|
if (i > -1) {
|
||||||
let value = CssHtmlTree.l10n("rule.status." + status);
|
let value = CssHtmlTree.l10n("rule.status." + status);
|
||||||
// Replace normal spaces with non-breaking spaces
|
// Replace normal spaces with non-breaking spaces
|
||||||
SelectorView.STATUS_NAMES[i] = value.replace(/ /g, '\u00A0');
|
SelectorView.STATUS_NAMES[i] = value.replace(/ /g, '\u00A0');
|
||||||
|
@ -58,7 +58,8 @@
|
|||||||
* standard DOM API, but more inline with the definition in the spec.
|
* standard DOM API, but more inline with the definition in the spec.
|
||||||
*
|
*
|
||||||
* - CssPropertyInfo contains style information for a single property for the
|
* - CssPropertyInfo contains style information for a single property for the
|
||||||
* highlighted element. It contains the matched CSS rules on the page.
|
* highlighted element. It divides the CSS rules on the page into matched and
|
||||||
|
* unmatched rules.
|
||||||
* - CssSelectorInfo is a wrapper around CssSelector, which adds sorting with
|
* - CssSelectorInfo is a wrapper around CssSelector, which adds sorting with
|
||||||
* reference to the selected element.
|
* reference to the selected element.
|
||||||
*/
|
*/
|
||||||
@ -115,9 +116,10 @@ CssLogic.MEDIA = {
|
|||||||
* @see csshtmltree.js RuleView._cacheStatusNames()
|
* @see csshtmltree.js RuleView._cacheStatusNames()
|
||||||
*/
|
*/
|
||||||
CssLogic.STATUS = {
|
CssLogic.STATUS = {
|
||||||
BEST: 2,
|
BEST: 3,
|
||||||
MATCHED: 1,
|
MATCHED: 2,
|
||||||
PARENT_MATCH: 0,
|
PARENT_MATCH: 1,
|
||||||
|
UNMATCHED: 0,
|
||||||
UNKNOWN: -1,
|
UNKNOWN: -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -145,11 +147,13 @@ CssLogic.prototype = {
|
|||||||
// processMatchedSelectors().
|
// processMatchedSelectors().
|
||||||
_passId: 0,
|
_passId: 0,
|
||||||
|
|
||||||
// Used for tracking matched CssSelector objects.
|
// Used for tracking matched CssSelector objects, such that we can skip them
|
||||||
|
// in processUnmatchedSelectors().
|
||||||
_matchId: 0,
|
_matchId: 0,
|
||||||
|
|
||||||
_matchedRules: null,
|
_matchedRules: null,
|
||||||
_matchedSelectors: null,
|
_matchedSelectors: null,
|
||||||
|
_unmatchedSelectors: null,
|
||||||
|
|
||||||
domUtils: Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils),
|
domUtils: Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils),
|
||||||
|
|
||||||
@ -165,6 +169,7 @@ CssLogic.prototype = {
|
|||||||
this._sheetsCached = false;
|
this._sheetsCached = false;
|
||||||
this._matchedRules = null;
|
this._matchedRules = null;
|
||||||
this._matchedSelectors = null;
|
this._matchedSelectors = null;
|
||||||
|
this._unmatchedSelectors = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -199,6 +204,7 @@ CssLogic.prototype = {
|
|||||||
|
|
||||||
this._matchedRules = null;
|
this._matchedRules = null;
|
||||||
this._matchedSelectors = null;
|
this._matchedSelectors = null;
|
||||||
|
this._unmatchedSelectors = null;
|
||||||
let win = this.viewedDocument.defaultView;
|
let win = this.viewedDocument.defaultView;
|
||||||
this._computedStyle = win.getComputedStyle(this.viewedElement, "");
|
this._computedStyle = win.getComputedStyle(this.viewedElement, "");
|
||||||
},
|
},
|
||||||
@ -213,7 +219,8 @@ CssLogic.prototype = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Source filter. Only display properties coming from the given source (web
|
* Source filter. Only display properties coming from the given source (web
|
||||||
* address).
|
* address). Note that in order to avoid information overload we DO NOT show
|
||||||
|
* unmatched system rules.
|
||||||
* @see CssLogic.FILTER.*
|
* @see CssLogic.FILTER.*
|
||||||
*/
|
*/
|
||||||
set sourceFilter(aValue) {
|
set sourceFilter(aValue) {
|
||||||
@ -240,6 +247,7 @@ CssLogic.prototype = {
|
|||||||
if (needFullUpdate) {
|
if (needFullUpdate) {
|
||||||
this._matchedRules = null;
|
this._matchedRules = null;
|
||||||
this._matchedSelectors = null;
|
this._matchedSelectors = null;
|
||||||
|
this._unmatchedSelectors = null;
|
||||||
this._propertyInfos = {};
|
this._propertyInfos = {};
|
||||||
} else {
|
} else {
|
||||||
// Update the CssPropertyInfo objects.
|
// Update the CssPropertyInfo objects.
|
||||||
@ -487,6 +495,7 @@ CssLogic.prototype = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._matchedSelectors = [];
|
this._matchedSelectors = [];
|
||||||
|
this._unmatchedSelectors = null;
|
||||||
this._passId++;
|
this._passId++;
|
||||||
|
|
||||||
for (let i = 0; i < this._matchedRules.length; i++) {
|
for (let i = 0; i < this._matchedRules.length; i++) {
|
||||||
@ -531,6 +540,52 @@ CssLogic.prototype = {
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the CssSelector object that do not match the highlighted elements,
|
||||||
|
* nor its parents. Your callback function is invoked for every such
|
||||||
|
* CssSelector object. You receive one argument: the CssSelector object.
|
||||||
|
*
|
||||||
|
* The list of unmatched selectors is cached.
|
||||||
|
*
|
||||||
|
* @param {function} aCallback the function you want to execute for each of
|
||||||
|
* the unmatched selectors.
|
||||||
|
* @param {object} aScope the scope you want for the callback function. aScope
|
||||||
|
* will be the this object when aCallback executes.
|
||||||
|
*/
|
||||||
|
processUnmatchedSelectors: function CL_processUnmatchedSelectors(aCallback, aScope)
|
||||||
|
{
|
||||||
|
if (this._unmatchedSelectors) {
|
||||||
|
if (aCallback) {
|
||||||
|
this._unmatchedSelectors.forEach(aCallback, aScope);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this._matchedSelectors) {
|
||||||
|
this.processMatchedSelectors();
|
||||||
|
}
|
||||||
|
|
||||||
|
this._unmatchedSelectors = [];
|
||||||
|
|
||||||
|
this.forEachSheet(function (aSheet) {
|
||||||
|
// We do not show unmatched selectors from system stylesheets
|
||||||
|
if (aSheet.systemSheet || aSheet.disabled || !aSheet.mediaMatches) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
aSheet.forEachRule(function (aRule) {
|
||||||
|
aRule.selectors.forEach(function (aSelector) {
|
||||||
|
if (aSelector._matchId !== this._matchId) {
|
||||||
|
this._unmatchedSelectors.push(aSelector);
|
||||||
|
if (aCallback) {
|
||||||
|
aCallback.call(aScope, aSelector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
}, this);
|
||||||
|
}, this);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the highlighted element or it's parents have matched selectors.
|
* Check if the highlighted element or it's parents have matched selectors.
|
||||||
*
|
*
|
||||||
@ -631,6 +686,95 @@ CssLogic.prototype = {
|
|||||||
element.nodeType === Ci.nsIDOMNode.ELEMENT_NODE);
|
element.nodeType === Ci.nsIDOMNode.ELEMENT_NODE);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the highlighted element or it's parents have unmatched selectors.
|
||||||
|
*
|
||||||
|
* Please note that this method is far slower than hasMatchedSelectors()
|
||||||
|
* because it needs to do a lot more checks in the DOM.
|
||||||
|
*
|
||||||
|
* @param {array} aProperties The list of properties you want to check if they
|
||||||
|
* have unmatched selectors or not.
|
||||||
|
* @return {object} An object that tells for each property if it has unmatched
|
||||||
|
* selectors or not. Object keys are property names and values are booleans.
|
||||||
|
*/
|
||||||
|
hasUnmatchedSelectors: function CL_hasUnmatchedSelectors(aProperties)
|
||||||
|
{
|
||||||
|
if (!this._matchedRules) {
|
||||||
|
this._buildMatchedRules();
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = {};
|
||||||
|
|
||||||
|
this.forSomeSheets(function (aSheet) {
|
||||||
|
if (aSheet.systemSheet || aSheet.disabled || !aSheet.mediaMatches) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return aSheet.forSomeRules(function (aRule) {
|
||||||
|
let unmatched = aRule._matchId !== this._matchId ||
|
||||||
|
this._ruleHasUnmatchedSelector(aRule);
|
||||||
|
if (!unmatched) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aProperties = aProperties.filter(function(aProperty) {
|
||||||
|
if (!aRule.getPropertyValue(aProperty)) {
|
||||||
|
// Keep this property for the next rule. We need to find a rule
|
||||||
|
// which has the property.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
result[aProperty] = true;
|
||||||
|
|
||||||
|
// We found a rule that has the current property while it does not
|
||||||
|
// match the current element. We can remove this property from the
|
||||||
|
// array.
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
return aProperties.length == 0;
|
||||||
|
}, this);
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
aProperties.forEach(function(aProperty) { result[aProperty] = false; });
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a CssRule has an unmatched selector for the highlighted element or
|
||||||
|
* its parents.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {CssRule} aRule The rule you want to check if it has an unmatched
|
||||||
|
* selector.
|
||||||
|
* @return {boolean} True if the rule has an unmatched selector, false
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
_ruleHasUnmatchedSelector: function CL__ruleHasUnmatchedSelector(aRule)
|
||||||
|
{
|
||||||
|
if (!aRule._cssSheet && aRule.sourceElement) {
|
||||||
|
// CssRule wraps element.style, which never has unmatched selectors.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let element = this.viewedElement;
|
||||||
|
let selectors = aRule.selectors;
|
||||||
|
|
||||||
|
do {
|
||||||
|
selectors = selectors.filter(function(aSelector) {
|
||||||
|
return !element.mozMatchesSelector(aSelector);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (selectors.length == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while ((element = element.parentNode) &&
|
||||||
|
element.nodeType === Ci.nsIDOMNode.ELEMENT_NODE);
|
||||||
|
|
||||||
|
return selectors.length > 0;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells if the given DOM CSS object matches the current view media.
|
* Tells if the given DOM CSS object matches the current view media.
|
||||||
*
|
*
|
||||||
@ -1350,9 +1494,10 @@ CssSelector.prototype = {
|
|||||||
* A cache of information about the matched rules, selectors and values attached
|
* A cache of information about the matched rules, selectors and values attached
|
||||||
* to a CSS property, for the highlighted element.
|
* to a CSS property, for the highlighted element.
|
||||||
*
|
*
|
||||||
* The heart of the CssPropertyInfo object is the _findMatchedSelectors()
|
* The heart of the CssPropertyInfo object is the _findMatchedSelectors() and
|
||||||
* method. This is invoked when the PropertyView tries to access the
|
* _findUnmatchedSelectors() methods. These are invoked when the PropertyView
|
||||||
* .matchedSelectors array. Results are cached, for later reuse.
|
* tries to access the .matchedSelectors and .unmatchedSelectors arrays.
|
||||||
|
* Results are cached, for later reuse.
|
||||||
*
|
*
|
||||||
* @param {CssLogic} aCssLogic Reference to the parent CssLogic instance
|
* @param {CssLogic} aCssLogic Reference to the parent CssLogic instance
|
||||||
* @param {string} aProperty The CSS property we are gathering information for
|
* @param {string} aProperty The CSS property we are gathering information for
|
||||||
@ -1373,6 +1518,7 @@ function CssPropertyInfo(aCssLogic, aProperty)
|
|||||||
// counted. This includes rules that come from filtered stylesheets (those
|
// counted. This includes rules that come from filtered stylesheets (those
|
||||||
// that have sheetAllowed = false).
|
// that have sheetAllowed = false).
|
||||||
this._matchedSelectors = null;
|
this._matchedSelectors = null;
|
||||||
|
this._unmatchedSelectors = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
CssPropertyInfo.prototype = {
|
CssPropertyInfo.prototype = {
|
||||||
@ -1415,6 +1561,23 @@ CssPropertyInfo.prototype = {
|
|||||||
return this._matchedRuleCount;
|
return this._matchedRuleCount;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the number of unmatched rules.
|
||||||
|
*
|
||||||
|
* @return {number} the number of rules that do not match the highlighted
|
||||||
|
* element or its parents.
|
||||||
|
*/
|
||||||
|
get unmatchedRuleCount()
|
||||||
|
{
|
||||||
|
if (!this._unmatchedSelectors) {
|
||||||
|
this._findUnmatchedSelectors();
|
||||||
|
} else if (this.needRefilter) {
|
||||||
|
this._refilterSelectors();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._unmatchedRuleCount;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the array holding CssSelectorInfo objects for each of the matched
|
* Retrieve the array holding CssSelectorInfo objects for each of the matched
|
||||||
* selectors, from each of the matched rules. Only selectors coming from
|
* selectors, from each of the matched rules. Only selectors coming from
|
||||||
@ -1434,6 +1597,25 @@ CssPropertyInfo.prototype = {
|
|||||||
return this._matchedSelectors;
|
return this._matchedSelectors;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the array holding CssSelectorInfo objects for each of the
|
||||||
|
* unmatched selectors, from each of the unmatched rules. Only selectors
|
||||||
|
* coming from allowed stylesheets are included in the array.
|
||||||
|
*
|
||||||
|
* @return {array} the list of CssSelectorInfo objects of selectors that do
|
||||||
|
* not match the highlighted element or its parents.
|
||||||
|
*/
|
||||||
|
get unmatchedSelectors()
|
||||||
|
{
|
||||||
|
if (!this._unmatchedSelectors) {
|
||||||
|
this._findUnmatchedSelectors();
|
||||||
|
} else if (this.needRefilter) {
|
||||||
|
this._refilterSelectors();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._unmatchedSelectors;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the selectors that match the highlighted element and its parents.
|
* Find the selectors that match the highlighted element and its parents.
|
||||||
* Uses CssLogic.processMatchedSelectors() to find the matched selectors,
|
* Uses CssLogic.processMatchedSelectors() to find the matched selectors,
|
||||||
@ -1462,7 +1644,7 @@ CssPropertyInfo.prototype = {
|
|||||||
|
|
||||||
// Now we know which of the matches is best, we can mark it BEST_MATCH.
|
// Now we know which of the matches is best, we can mark it BEST_MATCH.
|
||||||
if (this._matchedSelectors.length > 0 &&
|
if (this._matchedSelectors.length > 0 &&
|
||||||
this._matchedSelectors[0].status > CssLogic.STATUS.UNKNOWN) {
|
this._matchedSelectors[0].status > CssLogic.STATUS.UNMATCHED) {
|
||||||
this._matchedSelectors[0].status = CssLogic.STATUS.BEST;
|
this._matchedSelectors[0].status = CssLogic.STATUS.BEST;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1489,8 +1671,53 @@ CssPropertyInfo.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refilter the matched selectors array when the CssLogic.sourceFilter
|
* Find the selectors that do not match the highlighted element and its
|
||||||
* changes. This allows for quick filter changes.
|
* parents.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_findUnmatchedSelectors: function CssPropertyInfo_findUnmatchedSelectors()
|
||||||
|
{
|
||||||
|
this._unmatchedSelectors = [];
|
||||||
|
this._unmatchedRuleCount = 0;
|
||||||
|
this.needRefilter = false;
|
||||||
|
this._cssLogic._passId++;
|
||||||
|
|
||||||
|
this._cssLogic.processUnmatchedSelectors(this._processUnmatchedSelector,
|
||||||
|
this);
|
||||||
|
|
||||||
|
// Sort the selectors by specificity.
|
||||||
|
this._unmatchedSelectors.sort(function(aSelectorInfo1, aSelectorInfo2) {
|
||||||
|
return aSelectorInfo1.compareTo(aSelectorInfo2);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process an unmatched CssSelector object. Note that in order to avoid
|
||||||
|
* information overload we DO NOT show unmatched system rules.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {CssSelector} aSelector the unmatched CssSelector object.
|
||||||
|
*/
|
||||||
|
_processUnmatchedSelector: function CPI_processUnmatchedSelector(aSelector)
|
||||||
|
{
|
||||||
|
let cssRule = aSelector._cssRule;
|
||||||
|
let value = cssRule.getPropertyValue(this.property);
|
||||||
|
if (value) {
|
||||||
|
let selectorInfo = new CssSelectorInfo(aSelector, this.property, value,
|
||||||
|
CssLogic.STATUS.UNMATCHED);
|
||||||
|
this._unmatchedSelectors.push(selectorInfo);
|
||||||
|
if (this._cssLogic._passId != cssRule._passId) {
|
||||||
|
if (cssRule.sheetAllowed) {
|
||||||
|
this._unmatchedRuleCount++;
|
||||||
|
}
|
||||||
|
cssRule._passId = this._cssLogic._passId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refilter the matched and unmatched selectors arrays when the
|
||||||
|
* CssLogic.sourceFilter changes. This allows for quick filter changes.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_refilterSelectors: function CssPropertyInfo_refilterSelectors()
|
_refilterSelectors: function CssPropertyInfo_refilterSelectors()
|
||||||
@ -1513,6 +1740,12 @@ CssPropertyInfo.prototype = {
|
|||||||
this._matchedRuleCount = ruleCount;
|
this._matchedRuleCount = ruleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this._unmatchedSelectors) {
|
||||||
|
ruleCount = 0;
|
||||||
|
this._unmatchedSelectors.forEach(iterator);
|
||||||
|
this._unmatchedRuleCount = ruleCount;
|
||||||
|
}
|
||||||
|
|
||||||
this.needRefilter = false;
|
this.needRefilter = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1525,10 +1758,10 @@ CssPropertyInfo.prototype = {
|
|||||||
/**
|
/**
|
||||||
* A class that holds information about a given CssSelector object.
|
* A class that holds information about a given CssSelector object.
|
||||||
*
|
*
|
||||||
* Instances of this class are given to CssHtmlTree in the array of matched
|
* Instances of this class are given to CssHtmlTree in the arrays of matched and
|
||||||
* selectors. Each such object represents a displayable row in the PropertyView
|
* unmatched selectors. Each such object represents a displayable row in the
|
||||||
* objects. The information given by this object blends data coming from the
|
* PropertyView objects. The information given by this object blends data coming
|
||||||
* CssSheet, CssRule and from the CssSelector that own this object.
|
* from the CssSheet, CssRule and from the CssSelector that own this object.
|
||||||
*
|
*
|
||||||
* @param {CssSelector} aSelector The CssSelector object for which to present information.
|
* @param {CssSelector} aSelector The CssSelector object for which to present information.
|
||||||
* @param {string} aProperty The property for which information should be retrieved.
|
* @param {string} aProperty The property for which information should be retrieved.
|
||||||
|
@ -69,11 +69,6 @@
|
|||||||
<div id="path">
|
<div id="path">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- When no properties are found the following block is displayed. -->
|
|
||||||
<div id="noResults" hidden="">
|
|
||||||
&noPropertiesFound;
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- The output from #templateProperty (below) is appended here. -->
|
<!-- The output from #templateProperty (below) is appended here. -->
|
||||||
<div id="propertyContainer">
|
<div id="propertyContainer">
|
||||||
</div>
|
</div>
|
||||||
@ -82,6 +77,7 @@
|
|||||||
<xul:label class="legendKey bestmatch">&bestMatch;</xul:label>
|
<xul:label class="legendKey bestmatch">&bestMatch;</xul:label>
|
||||||
<xul:label class="legendKey matched">&matched;</xul:label>
|
<xul:label class="legendKey matched">&matched;</xul:label>
|
||||||
<xul:label class="legendKey parentmatch">&parentMatch;</xul:label>
|
<xul:label class="legendKey parentmatch">&parentMatch;</xul:label>
|
||||||
|
<xul:label class="legendKey unmatched">&unmatched;</xul:label>
|
||||||
<xul:spacer flex="1"/>
|
<xul:spacer flex="1"/>
|
||||||
<xul:resizer dir="bottomright"/>
|
<xul:resizer dir="bottomright"/>
|
||||||
</xul:hbox>
|
</xul:hbox>
|
||||||
@ -146,6 +142,15 @@ To visually debug the templates without running firefox, alter the display:none
|
|||||||
|
|
||||||
<div save="${matchedSelectorsContainer}" class="rulelink" dir="${getRTLAttr}">
|
<div save="${matchedSelectorsContainer}" class="rulelink" dir="${getRTLAttr}">
|
||||||
</div>
|
</div>
|
||||||
|
<div save="${unmatchedSelectorsContainer}" class="rulelink" dir="${getRTLAttr}">
|
||||||
|
<div save="${unmatchedTitleBlock}" onclick="${unmatchedSelectorsClick}"
|
||||||
|
class="rule-unmatched">
|
||||||
|
<div save="${unmatchedExpander}" class="expander" dir="${getRTLAttr}"></div>
|
||||||
|
<div save="${unmatchedSelectorsTitleNode}">&unmatchedSelectors;</div>
|
||||||
|
</div>
|
||||||
|
<div save="${unmatchedSelectorTable}" class="unmatchedSelectorTable"
|
||||||
|
dir="${getRTLAttr}"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -173,6 +178,32 @@ To visually debug the templates without running firefox, alter the display:none
|
|||||||
</loop>
|
</loop>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
A templateUnmatchedSelectors sits inside each templateProperties showing the
|
||||||
|
list of selectors that do not 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 ${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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -51,7 +51,6 @@ _BROWSER_TEST_FILES = \
|
|||||||
browser_bug683672.js \
|
browser_bug683672.js \
|
||||||
browser_styleinspector_bug_672746_default_styles.js \
|
browser_styleinspector_bug_672746_default_styles.js \
|
||||||
browser_styleinspector_bug_672744_search_filter.js \
|
browser_styleinspector_bug_672744_search_filter.js \
|
||||||
browser_styleinspector_bug_689759_no_results_placeholder.js \
|
|
||||||
browser_bug_692400_element_style.js \
|
browser_bug_692400_element_style.js \
|
||||||
browser_ruleview_editor.js \
|
browser_ruleview_editor.js \
|
||||||
browser_ruleview_inherit.js \
|
browser_ruleview_inherit.js \
|
||||||
|
@ -7,6 +7,10 @@
|
|||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.unmatched1, .unmatched2, .unmatched3, .unmatched4, .unmatched5, .unmatched6, .unmatched7 {
|
||||||
|
color: #f00;
|
||||||
|
}
|
||||||
|
|
||||||
div {
|
div {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 40px;
|
top: 40px;
|
||||||
|
@ -38,6 +38,7 @@ function runTests()
|
|||||||
ok(stylePanel.isOpen(), "style inspector is open");
|
ok(stylePanel.isOpen(), "style inspector is open");
|
||||||
|
|
||||||
testMatchedSelectors();
|
testMatchedSelectors();
|
||||||
|
testUnmatchedSelectors();
|
||||||
|
|
||||||
info("finishing up");
|
info("finishing up");
|
||||||
Services.obs.addObserver(finishUp, "StyleInspector-closed", false);
|
Services.obs.addObserver(finishUp, "StyleInspector-closed", false);
|
||||||
@ -68,6 +69,30 @@ function testMatchedSelectors()
|
|||||||
"hasMatchedSelectors returns true");
|
"hasMatchedSelectors returns true");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testUnmatchedSelectors()
|
||||||
|
{
|
||||||
|
info("checking selector counts, unmatched rules and titles");
|
||||||
|
let body = content.document.body;
|
||||||
|
ok(body, "captain, we have a body");
|
||||||
|
|
||||||
|
info("selecting content.document.body");
|
||||||
|
stylePanel.selectNode(body);
|
||||||
|
|
||||||
|
let htmlTree = stylePanel.cssHtmlTree;
|
||||||
|
|
||||||
|
is(body, htmlTree.viewedElement,
|
||||||
|
"style inspector node matches the selected node");
|
||||||
|
|
||||||
|
let propertyView = new PropertyView(htmlTree, "color");
|
||||||
|
let numUnmatchedSelectors = propertyView.propertyInfo.unmatchedSelectors.length;
|
||||||
|
|
||||||
|
is(numUnmatchedSelectors, 13,
|
||||||
|
"CssLogic returns the correct number of unmatched selectors for body");
|
||||||
|
|
||||||
|
is(propertyView.hasUnmatchedSelectors, true,
|
||||||
|
"hasUnmatchedSelectors returns true");
|
||||||
|
}
|
||||||
|
|
||||||
function finishUp()
|
function finishUp()
|
||||||
{
|
{
|
||||||
Services.obs.removeObserver(finishUp, "StyleInspector-closed", false);
|
Services.obs.removeObserver(finishUp, "StyleInspector-closed", false);
|
||||||
|
@ -64,6 +64,7 @@ function SI_CheckProperty()
|
|||||||
let cssLogic = stylePanel.cssLogic;
|
let cssLogic = stylePanel.cssLogic;
|
||||||
let propertyInfo = cssLogic.getPropertyInfo("color");
|
let propertyInfo = cssLogic.getPropertyInfo("color");
|
||||||
ok(propertyInfo.matchedRuleCount > 0, "color property has matching rules");
|
ok(propertyInfo.matchedRuleCount > 0, "color property has matching rules");
|
||||||
|
ok(propertyInfo.unmatchedRuleCount > 0, "color property has unmatched rules");
|
||||||
}
|
}
|
||||||
|
|
||||||
function finishUp()
|
function finishUp()
|
||||||
|
@ -1,118 +0,0 @@
|
|||||||
/* 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/ */
|
|
||||||
|
|
||||||
// Tests that the no results placeholder works properly.
|
|
||||||
|
|
||||||
let doc;
|
|
||||||
let stylePanel;
|
|
||||||
|
|
||||||
function createDocument()
|
|
||||||
{
|
|
||||||
doc.body.innerHTML = '<style type="text/css"> ' +
|
|
||||||
'.matches {color: #F00;}</style>' +
|
|
||||||
'<span id="matches" class="matches">Some styled text</span>';
|
|
||||||
doc.title = "Tests that the no results placeholder works properly";
|
|
||||||
ok(window.StyleInspector, "StyleInspector exists");
|
|
||||||
stylePanel = new StyleInspector(window);
|
|
||||||
Services.obs.addObserver(runStyleInspectorTests, "StyleInspector-opened", false);
|
|
||||||
stylePanel.createPanel(false, function() {
|
|
||||||
stylePanel.open(doc.body);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function runStyleInspectorTests()
|
|
||||||
{
|
|
||||||
Services.obs.removeObserver(runStyleInspectorTests, "StyleInspector-opened", false);
|
|
||||||
|
|
||||||
ok(stylePanel.isOpen(), "style inspector is open");
|
|
||||||
|
|
||||||
Services.obs.addObserver(SI_AddFilterText, "StyleInspector-populated", false);
|
|
||||||
|
|
||||||
let span = doc.querySelector("#matches");
|
|
||||||
ok(span, "captain, we have the matches span");
|
|
||||||
|
|
||||||
let htmlTree = stylePanel.cssHtmlTree;
|
|
||||||
stylePanel.selectNode(span);
|
|
||||||
|
|
||||||
is(span, htmlTree.viewedElement,
|
|
||||||
"style inspector node matches the selected node");
|
|
||||||
is(htmlTree.viewedElement, stylePanel.cssLogic.viewedElement,
|
|
||||||
"cssLogic node matches the cssHtmlTree node");
|
|
||||||
}
|
|
||||||
|
|
||||||
function SI_AddFilterText()
|
|
||||||
{
|
|
||||||
Services.obs.removeObserver(SI_AddFilterText, "StyleInspector-populated", false);
|
|
||||||
|
|
||||||
let iframe = stylePanel.iframe;
|
|
||||||
let searchbar = stylePanel.cssHtmlTree.searchField;
|
|
||||||
let searchTerm = "xxxxx";
|
|
||||||
|
|
||||||
Services.obs.addObserver(SI_checkPlaceholderVisible, "StyleInspector-populated", false);
|
|
||||||
info("setting filter text to \"" + searchTerm + "\"");
|
|
||||||
searchbar.focus();
|
|
||||||
for each (let c in searchTerm) {
|
|
||||||
EventUtils.synthesizeKey(c, {}, iframe.contentWindow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function SI_checkPlaceholderVisible()
|
|
||||||
{
|
|
||||||
Services.obs.removeObserver(SI_checkPlaceholderVisible, "StyleInspector-populated", false);
|
|
||||||
info("SI_checkPlaceholderVisible called");
|
|
||||||
let placeholder = stylePanel.cssHtmlTree.noResults;
|
|
||||||
let iframe = stylePanel.iframe;
|
|
||||||
let display = iframe.contentWindow.getComputedStyle(placeholder).display;
|
|
||||||
|
|
||||||
is(display, "block", "placeholder is visible");
|
|
||||||
|
|
||||||
SI_ClearFilterText();
|
|
||||||
}
|
|
||||||
|
|
||||||
function SI_ClearFilterText()
|
|
||||||
{
|
|
||||||
let iframe = stylePanel.iframe;
|
|
||||||
let searchbar = stylePanel.cssHtmlTree.searchField;
|
|
||||||
|
|
||||||
Services.obs.addObserver(SI_checkPlaceholderHidden, "StyleInspector-populated", false);
|
|
||||||
info("clearing filter text");
|
|
||||||
searchbar.focus();
|
|
||||||
searchbar.value = "";
|
|
||||||
EventUtils.synthesizeKey("c", {}, iframe.contentWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
function SI_checkPlaceholderHidden()
|
|
||||||
{
|
|
||||||
Services.obs.removeObserver(SI_checkPlaceholderHidden, "StyleInspector-populated", false);
|
|
||||||
let placeholder = stylePanel.cssHtmlTree.noResults;
|
|
||||||
let iframe = stylePanel.iframe;
|
|
||||||
let display = iframe.contentWindow.getComputedStyle(placeholder).display;
|
|
||||||
|
|
||||||
is(display, "none", "placeholder is hidden");
|
|
||||||
|
|
||||||
Services.obs.addObserver(finishUp, "StyleInspector-closed", false);
|
|
||||||
stylePanel.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
function finishUp()
|
|
||||||
{
|
|
||||||
Services.obs.removeObserver(finishUp, "StyleInspector-closed", false);
|
|
||||||
ok(!stylePanel.isOpen(), "style inspector is closed");
|
|
||||||
doc = stylePanel = null;
|
|
||||||
gBrowser.removeCurrentTab();
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
function test()
|
|
||||||
{
|
|
||||||
waitForExplicitFinish();
|
|
||||||
gBrowser.selectedTab = gBrowser.addTab();
|
|
||||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
|
|
||||||
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
|
|
||||||
doc = content.document;
|
|
||||||
waitForFocus(createDocument, content);
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
content.location = "data:text/html,no results placeholder test";
|
|
||||||
}
|
|
@ -179,6 +179,7 @@
|
|||||||
<span id="text" lang="en" class="text">Use inspectstyle($('text')) to inspect me</span><br />
|
<span id="text" lang="en" class="text">Use inspectstyle($('text')) to inspect me</span><br />
|
||||||
<span id="text2" class="text2">Use inspectstyle($('text2'))</span><br />
|
<span id="text2" class="text2">Use inspectstyle($('text2'))</span><br />
|
||||||
<a class="link" href="#">Some Link</a>
|
<a class="link" href="#">Some Link</a>
|
||||||
|
<h2>font-family has a single unmatched rule</h2>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -18,16 +18,17 @@
|
|||||||
- This is the link title shown in the hover tooltip. -->
|
- This is the link title shown in the hover tooltip. -->
|
||||||
<!ENTITY helpLinkTitle "Read the documentation for this property">
|
<!ENTITY helpLinkTitle "Read the documentation for this property">
|
||||||
|
|
||||||
<!-- LOCALIZATION NOTE (noPropertiesFound): In the case where there are no CSS
|
<!-- LOCALIZATION NOTE (unmatchedSelectors): For each style property
|
||||||
- properties to display e.g. due to search criteria this message is
|
- the panel shows whether there are any selectors that do not match the
|
||||||
- displayed. -->
|
- currently selected element. -->
|
||||||
<!ENTITY noPropertiesFound "No CSS properties found.">
|
<!ENTITY unmatchedSelectors "Unmatched selectors">
|
||||||
|
|
||||||
<!-- LOCALIZATION NOTE (bestMatch, matched & parentMatch): For each style
|
<!-- LOCALIZATION NOTE (bestMatch, matched, parentMatch & unmatched): For each
|
||||||
- property the panel shows the rules which hold that specific property. For
|
- style property the panel shows the rules which hold that specific property.
|
||||||
- every rule, the rule status is also displayed: a rule can be the best
|
- For every rule, the rule status is also displayed: a rule can be the best
|
||||||
- match, a match, a parent match, or a rule did not match the element the
|
- match, a match, a parent match, or a rule did not match the element the
|
||||||
- user has highlighted. -->
|
- user has highlighted. -->
|
||||||
<!ENTITY bestMatch "Best Match">
|
<!ENTITY bestMatch "Best Match">
|
||||||
<!ENTITY matched "Matched">
|
<!ENTITY matched "Matched">
|
||||||
<!ENTITY parentMatch "Parent Match">
|
<!ENTITY parentMatch "Parent Match">
|
||||||
|
<!ENTITY unmatched "Unmatched">
|
||||||
|
@ -10,6 +10,7 @@ panelTitle=Style Inspector
|
|||||||
rule.status.BEST=Best Match
|
rule.status.BEST=Best Match
|
||||||
rule.status.MATCHED=Matched
|
rule.status.MATCHED=Matched
|
||||||
rule.status.PARENT_MATCH=Parent Match
|
rule.status.PARENT_MATCH=Parent Match
|
||||||
|
rule.status.UNMATCHED=Unmatched
|
||||||
|
|
||||||
# LOCALIZATION NOTE (rule.sourceElement, rule.sourceInline): For each
|
# LOCALIZATION NOTE (rule.sourceElement, rule.sourceInline): For each
|
||||||
# style property the panel shows the rules which hold that specific property.
|
# style property the panel shows the rules which hold that specific property.
|
||||||
|
@ -92,6 +92,14 @@ body {
|
|||||||
-moz-padding-end: 5px;
|
-moz-padding-end: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rule-unmatched {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 2px;
|
||||||
|
-moz-padding-start: 4px;
|
||||||
|
-moz-padding-end: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
/* Take away these two :visited rules to get a core dumper */
|
/* Take away these two :visited rules to get a core dumper */
|
||||||
/* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
|
/* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
|
||||||
.link,
|
.link,
|
||||||
@ -125,6 +133,10 @@ body {
|
|||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.unmatchedSelectorTable {
|
||||||
|
-moz-margin-start: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
.rulelink {
|
.rulelink {
|
||||||
color: -moz-dialogtext;
|
color: -moz-dialogtext;
|
||||||
-moz-margin-start: 12px;
|
-moz-margin-start: 12px;
|
||||||
@ -162,6 +174,10 @@ body {
|
|||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.only-unmatched {
|
||||||
|
-moz-margin-start: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.property-name {
|
.property-name {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@ -198,6 +214,9 @@ body {
|
|||||||
.parentmatch {
|
.parentmatch {
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
.unmatched {
|
||||||
|
color: brown;
|
||||||
|
}
|
||||||
|
|
||||||
#propertyContainer {
|
#propertyContainer {
|
||||||
display: -moz-box;
|
display: -moz-box;
|
||||||
@ -214,12 +233,6 @@ body {
|
|||||||
background-color: rgba(0,0,0,.022);
|
background-color: rgba(0,0,0,.022);
|
||||||
}
|
}
|
||||||
|
|
||||||
#noResults {
|
|
||||||
font-size: 18px;
|
|
||||||
margin-top: 5px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
color: -moz-dialogtext;
|
color: -moz-dialogtext;
|
||||||
background-color: -moz-dialog;
|
background-color: -moz-dialog;
|
||||||
|
@ -92,6 +92,14 @@ body {
|
|||||||
-moz-padding-end: 5px;
|
-moz-padding-end: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rule-unmatched {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 2px;
|
||||||
|
-moz-padding-start: 4px;
|
||||||
|
-moz-padding-end: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
/* Take away these two :visited rules to get a core dumper */
|
/* Take away these two :visited rules to get a core dumper */
|
||||||
/* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
|
/* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
|
||||||
.link,
|
.link,
|
||||||
@ -125,28 +133,30 @@ body {
|
|||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.unmatchedSelectorTable {
|
||||||
|
-moz-margin-start: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
.rulelink {
|
.rulelink {
|
||||||
color: -moz-dialogtext;
|
color: -moz-dialogtext;
|
||||||
-moz-margin-start: 12px;
|
-moz-margin-start: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.expander {
|
.expander {
|
||||||
width: 8px;
|
-moz-appearance: treetwisty;
|
||||||
height: 8px;
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
float: left;
|
float: left;
|
||||||
-moz-margin-start: 15px;
|
-moz-margin-start: 5px;
|
||||||
-moz-margin-end: 5px;
|
-moz-margin-end: 5px;
|
||||||
margin-top: 3px;
|
|
||||||
background: url("chrome://browser/skin/devtools/arrows.png") 48px 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.expander[dir="rtl"] {
|
.expander[dir="rtl"] {
|
||||||
float: right;
|
float: right;
|
||||||
background-position: 40px 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.expander[open] {
|
.expander[open] {
|
||||||
background-position: 32px 0;
|
-moz-appearance: treetwistyopen;
|
||||||
}
|
}
|
||||||
|
|
||||||
.expandable {
|
.expandable {
|
||||||
@ -162,6 +172,10 @@ body {
|
|||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.only-unmatched {
|
||||||
|
-moz-margin-start: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.property-name {
|
.property-name {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@ -198,6 +212,9 @@ body {
|
|||||||
.parentmatch {
|
.parentmatch {
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
.unmatched {
|
||||||
|
color: brown;
|
||||||
|
}
|
||||||
|
|
||||||
#propertyContainer {
|
#propertyContainer {
|
||||||
display: -moz-box;
|
display: -moz-box;
|
||||||
@ -214,12 +231,6 @@ body {
|
|||||||
background-color: rgba(0,0,0,.022);
|
background-color: rgba(0,0,0,.022);
|
||||||
}
|
}
|
||||||
|
|
||||||
#noResults {
|
|
||||||
font-size: 18px;
|
|
||||||
margin-top: 5px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
color: -moz-dialogtext;
|
color: -moz-dialogtext;
|
||||||
background-color: -moz-dialog;
|
background-color: -moz-dialog;
|
||||||
|
@ -92,6 +92,14 @@ body {
|
|||||||
-moz-padding-end: 5px;
|
-moz-padding-end: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rule-unmatched {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 2px;
|
||||||
|
-moz-padding-start: 4px;
|
||||||
|
-moz-padding-end: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
/* Take away these two :visited rules to get a core dumper */
|
/* Take away these two :visited rules to get a core dumper */
|
||||||
/* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
|
/* See https://bugzilla.mozilla.org/show_bug.cgi?id=575675#c30 */
|
||||||
.link,
|
.link,
|
||||||
@ -125,6 +133,10 @@ body {
|
|||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.unmatchedSelectorTable {
|
||||||
|
-moz-margin-start: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
.rulelink {
|
.rulelink {
|
||||||
color: -moz-dialogtext;
|
color: -moz-dialogtext;
|
||||||
-moz-margin-start: 12px;
|
-moz-margin-start: 12px;
|
||||||
@ -161,6 +173,10 @@ body {
|
|||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.only-unmatched {
|
||||||
|
-moz-margin-start: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.property-name {
|
.property-name {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@ -197,6 +213,9 @@ body {
|
|||||||
.parentmatch {
|
.parentmatch {
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
.unmatched {
|
||||||
|
color: brown;
|
||||||
|
}
|
||||||
|
|
||||||
#propertyContainer {
|
#propertyContainer {
|
||||||
display: -moz-box;
|
display: -moz-box;
|
||||||
@ -213,12 +232,6 @@ body {
|
|||||||
background-color: rgba(0,0,0,.022);
|
background-color: rgba(0,0,0,.022);
|
||||||
}
|
}
|
||||||
|
|
||||||
#noResults {
|
|
||||||
font-size: 18px;
|
|
||||||
margin-top: 5px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
color: -moz-dialogtext;
|
color: -moz-dialogtext;
|
||||||
background-color: -moz-dialog;
|
background-color: -moz-dialog;
|
||||||
|
Loading…
Reference in New Issue
Block a user