Modified: trunk/LayoutTests/http/tests/inspector/elements-test.js (128745 => 128746)
--- trunk/LayoutTests/http/tests/inspector/elements-test.js 2012-09-17 12:45:44 UTC (rev 128745)
+++ trunk/LayoutTests/http/tests/inspector/elements-test.js 2012-09-17 12:46:57 UTC (rev 128746)
@@ -118,7 +118,7 @@
InspectorTest.selectNodeAndWaitForStyles(idValue, stylesCallback);
}
-InspectorTest.dumpSelectedElementStyles = function(excludeComputed, excludeMatched, omitLonghands)
+InspectorTest.dumpSelectedElementStyles = function(excludeComputed, excludeMatched, omitLonghands, includeSelectorGroupMarks)
{
function extractText(element)
{
@@ -129,6 +129,18 @@
return element ? element.getAttribute("data-uncopyable") : "";
}
+ function buildMarkedSelectors(element)
+ {
+ var result = "";
+ for (var node = element.firstChild; node; node = node.nextSibling) {
+ if (node.nodeType === Node.ELEMENT_NODE && node.className === "selector-matches")
+ result += "[$" + node.textContent + "$]";
+ else
+ result += node.textContent;
+ }
+ return result;
+ }
+
var styleSections = WebInspector.panels.elements.sidebarPanes.styles.sections;
for (var pseudoId in styleSections) {
var pseudoName = WebInspector.StylesSidebarPane.PseudoIdNames[pseudoId];
@@ -145,7 +157,7 @@
var chainEntries = section.titleElement.children;
for (var j = 0; j < chainEntries.length; ++j) {
var chainEntry = chainEntries[j];
- var entryLine = chainEntry.children[1].textContent;
+ var entryLine = includeSelectorGroupMarks ? buildMarkedSelectors(chainEntry.children[1]) : chainEntry.children[1].textContent;
if (chainEntry.children[2])
entryLine += " " + chainEntry.children[2].textContent;
entryLine += " (" + extractText(chainEntry.children[0]) + ")";
Modified: trunk/LayoutTests/inspector/styles/styles-add-new-rule.html (128745 => 128746)
--- trunk/LayoutTests/inspector/styles/styles-add-new-rule.html 2012-09-17 12:45:44 UTC (rev 128745)
+++ trunk/LayoutTests/inspector/styles/styles-add-new-rule.html 2012-09-17 12:46:57 UTC (rev 128746)
@@ -18,6 +18,7 @@
// Click "Add new rule".
document.getElementById("add-style-button-test-id").click();
var section = WebInspector.panels.elements.sidebarPanes.styles.sections[0][2];
+ section._selectorElement.textContent = "foo, " + section._selectorElement.textContent + ", bar";
section._selectorElement.dispatchEvent(InspectorTest.createKeyEvent("Enter"));
InspectorTest.runAfterPendingDispatches(step2);
}
@@ -44,7 +45,7 @@
function step4()
{
InspectorTest.addResult("After adding new rule (inspected):");
- InspectorTest.dumpSelectedElementStyles(true, false, true);
+ InspectorTest.dumpSelectedElementStyles(true, false, true, true);
InspectorTest.selectNodeAndWaitForStyles("other", step5);
}
Modified: trunk/Source/WebCore/inspector/front-end/StylesSidebarPane.js (128745 => 128746)
--- trunk/Source/WebCore/inspector/front-end/StylesSidebarPane.js 2012-09-17 12:45:44 UTC (rev 128745)
+++ trunk/Source/WebCore/inspector/front-end/StylesSidebarPane.js 2012-09-17 12:46:57 UTC (rev 128746)
@@ -358,6 +358,7 @@
var usedProperties = {};
this._markUsedProperties(styleRules, usedProperties);
this.sections[0] = this._rebuildSectionsForStyleRules(styleRules, usedProperties, 0, null);
+ var responsesLeft = this.sections[0].length;
var anchorElement = this.sections[0].inheritedPropertiesSeparatorElement;
if (styles.computedStyle)
@@ -380,9 +381,28 @@
usedProperties = {};
this._markUsedProperties(styleRules, usedProperties);
this.sections[pseudoId] = this._rebuildSectionsForStyleRules(styleRules, usedProperties, pseudoId, anchorElement);
+ responsesLeft += this.sections[pseudoId].length;
}
- this._nodeStylesUpdatedForTest(node, true);
+ // Mark matching selectors in comma-delimited selector groups.
+ var boundMarkCallback = markCallback.bind(this);
+ for (var id in this.sections) {
+ var sectionsForPseudoId = this.sections[id].slice();
+ for (var j = 0; j < sectionsForPseudoId.length; ++j) {
+ var section = sectionsForPseudoId[j];
+ if (!section.styleRule || section.isBlank || section.styleRule.computedStyle || section.styleRule.isAttribute) {
+ boundMarkCallback();
+ continue;
+ }
+ section._markMatchedSelectorsInGroup(boundMarkCallback);
+ }
+ }
+
+ function markCallback()
+ {
+ if (!(--responsesLeft))
+ this._nodeStylesUpdatedForTest(node, true);
+ }
},
_nodeStylesUpdatedForTest: function(node, rebuild)
@@ -464,7 +484,7 @@
var separatorInserted = false;
if (parentStyles.inlineStyle) {
if (this._containsInherited(parentStyles.inlineStyle)) {
- var inlineStyle = { selectorText: WebInspector.UIString("Style Attribute"), style: parentStyles.inlineStyle, isAttribute: true, isInherited: true };
+ var inlineStyle = { selectorText: WebInspector.UIString("Style Attribute"), style: parentStyles.inlineStyle, isAttribute: true, isInherited: true, parentNode: parentNode };
if (!separatorInserted) {
insertInheritedNodeSeparator(parentNode);
separatorInserted = true;
@@ -485,7 +505,7 @@
insertInheritedNodeSeparator(parentNode);
separatorInserted = true;
}
- styleRules.push({ style: rule.style, selectorText: rule.selectorText, media: rule.media, sourceURL: rule.sourceURL, rule: rule, isInherited: true, editable: !!(rule.style && rule.style.id) });
+ styleRules.push({ style: rule.style, selectorText: rule.selectorText, media: rule.media, sourceURL: rule.sourceURL, rule: rule, isInherited: true, parentNode: parentNode, editable: !!(rule.style && rule.style.id) });
}
parentNode = parentNode.parentNode;
}
@@ -873,6 +893,7 @@
var selectorContainer = document.createElement("div");
this._selectorElement = document.createElement("span");
+ this._selectorElement.addStyleClass("selector-matches");
this._selectorElement.textContent = styleRule.selectorText;
selectorContainer.appendChild(this._selectorElement);
@@ -913,7 +934,7 @@
this._selectorContainer = selectorContainer;
if (isInherited)
- this.element.addStyleClass("show-inherited"); // This one is related to inherited rules, not compted style.
+ this.element.addStyleClass("show-inherited"); // This one is related to inherited rules, not computed style.
if (!this.editable)
this.element.addStyleClass("read-only");
@@ -1103,6 +1124,91 @@
return null;
},
+ /**
+ * @param {function()=} callback
+ */
+ _markMatchedSelectorsInGroup: function(callback)
+ {
+ var self = this;
+ function mycallback()
+ {
+ if (callback)
+ callback();
+ }
+
+ var selectorText = this._selectorElement.textContent;
+ if (!selectorText || selectorText.indexOf(",") === -1) {
+ mycallback();
+ return;
+ }
+
+ var paneNode = this._parentPane.node;
+ var relatedNode = this.styleRule.parentNode || paneNode;
+ if (!relatedNode) {
+ mycallback();
+ return;
+ }
+
+ function trim(text)
+ {
+ return text.trim();
+ }
+ var selectors = selectorText.split(",").map(trim);
+
+ WebInspector.RemoteObject.resolveNode(relatedNode, "", resolvedCallback);
+ function resolvedCallback(object)
+ {
+ if (!object) {
+ mycallback();
+ return;
+ }
+
+ for (var i = 0, size = selectors.length; i < size; ++i) {
+ var selector = selectors[i];
+ object.callFunctionJSON(matchesSelector, [{ value: selectors[i] }], matchesCallback.bind(this, i));
+ }
+ }
+
+ function matchesSelector(selector)
+ {
+ return this.webkitMatchesSelector(selector);
+ }
+
+ var result = [];
+ var matchFound;
+ function matchesCallback(selectorIndex, matches)
+ {
+ var isLast = selectorIndex === selectors.length - 1;
+ var fragment = document.createDocumentFragment();
+ result[selectorIndex] = fragment;
+
+ var selectorNode;
+ if (matches && paneNode === self._parentPane.node) {
+ selectorNode = document.createElement("span");
+ selectorNode.className = "selector-matches";
+ selectorNode.appendChild(document.createTextNode(selectors[selectorIndex]));
+ matchFound = true;
+ } else
+ selectorNode = document.createTextNode(selectors[selectorIndex]);
+
+ fragment.appendChild(selectorNode);
+ if (!isLast) {
+ fragment.appendChild(document.createTextNode(", "));
+ return;
+ }
+
+ // This check is here in case the element class has been changed from JS during the roundtrip,
+ // so the element matches none of the distinct selectors. Fall back to "all selectors match".
+ if (matchFound) {
+ self._selectorElement.className = "selector";
+ self._selectorElement.removeChildren();
+ for (var i = 0; i < result.length; ++i)
+ self._selectorElement.appendChild(result[i]);
+ }
+ mycallback();
+ }
+ },
+
_checkWillCancelEditing: function()
{
var willCauseCancelEditing = this._willCauseCancelEditing;
@@ -1233,7 +1339,8 @@
if (WebInspector.isBeingEdited(element))
return;
- this._selectorElement.scrollIntoViewIfNeeded(false);
+ element.scrollIntoViewIfNeeded(false);
+ element.textContent = element.textContent; // Reset selector marks in group.
var config = new WebInspector.EditingConfig(this.editingSelectorCommitted.bind(this), this.editingSelectorCancelled.bind(this));
WebInspector.startEditing(this._selectorElement, config);
@@ -1243,25 +1350,32 @@
_moveEditorFromSelector: function(moveDirection)
{
- if (!moveDirection)
+
+ if (!moveDirection) {
+ this._markMatchedSelectorsInGroup();
return;
+ }
- if (moveDirection === "forward") {
- this.expand();
- var firstChild = this.propertiesTreeOutline.children[0];
- while (firstChild && firstChild.inherited)
- firstChild = firstChild.nextSibling;
- if (!firstChild)
- this.addNewBlankProperty().startEditing();
- else
- firstChild.startEditing(firstChild.nameElement);
- } else {
- var previousSection = this.previousEditableSibling();
- if (!previousSection)
- return;
+ this._markMatchedSelectorsInGroup(markCallback.bind(this));
- previousSection.expand();
- previousSection.addNewBlankProperty().startEditing();
+ function markCallback() {
+ if (moveDirection === "forward") {
+ this.expand();
+ var firstChild = this.propertiesTreeOutline.children[0];
+ while (firstChild && firstChild.inherited)
+ firstChild = firstChild.nextSibling;
+ if (!firstChild)
+ this.addNewBlankProperty().startEditing();
+ else
+ firstChild.startEditing(firstChild.nameElement);
+ } else {
+ var previousSection = this.previousEditableSibling();
+ if (!previousSection)
+ return;
+
+ previousSection.expand();
+ previousSection.addNewBlankProperty().startEditing();
+ }
}
},
@@ -1299,7 +1413,9 @@
editingSelectorCancelled: function()
{
- // Do nothing, this is overridden by BlankStylePropertiesSection.
+ // Do nothing but mark the selectors in group if necessary.
+ // This is overridden by BlankStylePropertiesSection.
+ this._markMatchedSelectorsInGroup();
}
}