Web Inspector: Highlight currently edited CSS selector
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 20 Jun 2015 00:48:28 +0000 (00:48 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 20 Jun 2015 00:48:28 +0000 (00:48 +0000)
https://bugs.webkit.org/show_bug.cgi?id=145658

Patch by Devin Rousso <drousso@apple.com> on 2015-06-19
Reviewed by Joseph Pecoraro.

Source/JavaScriptCore:

* inspector/protocol/DOM.json: Added highlightSelector to show highlight over multiple nodes.

Source/WebCore:

Test: inspector/dom/highlight-multiple-shapes.html

* inspector/InspectorController.cpp:
(WebCore::InspectorController::buildObjectForHighlightedNode):
* inspector/InspectorController.h:
* inspector/InspectorDOMAgent.cpp:
(WebCore::InspectorDOMAgent::highlightSelector): Gets a list of all nodes matching a given selector string and highlights each of them.
* inspector/InspectorDOMAgent.h:
* inspector/InspectorOverlay.cpp:
(WebCore::InspectorOverlay::hideHighlight):
(WebCore::InspectorOverlay::highlightNodeList): Loops through a given NodeList to create highlightObjects for each of them.
(WebCore::InspectorOverlay::shouldShowOverlay):
(WebCore::buildObjectForElementData): Don't show flow fragments when highlighting multiple nodes.
(WebCore::InspectorOverlay::buildHighlightObjectForNode):
(WebCore::InspectorOverlay::buildObjectForHighlightedNode): Now returns an array containing the highlightObject for each highligthed node.
(WebCore::InspectorOverlay::drawNodeHighlight): Now sends an array to the InspectorOverlayPage.js to provide support for highlighting multiple nodes.
* inspector/InspectorOverlay.h:
* inspector/InspectorOverlayPage.js: Now expects an array as its parameter and loops through it to highlight each node given.
If the parameter array contains more than one element, do not draw the textbox containing info on that node.
(drawNodeHighlight):

Source/WebInspectorUI:

* UserInterface/Views/CSSStyleDeclarationSection.js:
(WebInspector.CSSStyleDeclarationSection): Added event listeners on the selector text for mouseover and mouseout.
(WebInspector.CSSStyleDeclarationSection.prototype._highlightNodesWithSelector): Selector text mouseover action that highlights all nodes that match the selector string in the corresponding frame.
(WebInspector.CSSStyleDeclarationSection.prototype._hideHighlightOnNodesWithSelector): Selector text mouseout action that clears all highlights on matching nodes.
* UserInterface/Views/DOMNode.js:
(WebInspector.DOMNode): If the payload contains a frameId, then save it.
(WebInspector.DOMNode.frameIdentifier):

LayoutTests:

* inspector/dom/highlightSelector-expected.txt: Added.
* inspector/dom/highlightSelector-iframe.html: Added.
* inspector/dom/highlightSelector.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@185784 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
LayoutTests/ChangeLog
LayoutTests/inspector/dom/highlightSelector-expected.txt [new file with mode: 0644]
LayoutTests/inspector/dom/highlightSelector-iframe.html [new file with mode: 0644]
LayoutTests/inspector/dom/highlightSelector.html [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/inspector/protocol/DOM.json
Source/WebCore/ChangeLog
Source/WebCore/inspector/InspectorController.cpp
Source/WebCore/inspector/InspectorController.h
Source/WebCore/inspector/InspectorDOMAgent.cpp
Source/WebCore/inspector/InspectorDOMAgent.h
Source/WebCore/inspector/InspectorOverlay.cpp
Source/WebCore/inspector/InspectorOverlay.h
Source/WebCore/inspector/InspectorOverlayPage.js
Source/WebCore/testing/Internals.cpp
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/UserInterface/Models/DOMNode.js
Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationSection.js

index 5c6a031..10dffeb 100644 (file)
@@ -1,3 +1,14 @@
+2015-06-19  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: Highlight currently edited CSS selector
+        https://bugs.webkit.org/show_bug.cgi?id=145658
+
+        Reviewed by Joseph Pecoraro.
+
+        * inspector/dom/highlightSelector-expected.txt: Added.
+        * inspector/dom/highlightSelector-iframe.html: Added.
+        * inspector/dom/highlightSelector.html: Added.
+
 2015-06-19  Dean Jackson  <dino@apple.com>
 
         Extremely large canvas crashes on pre-El Capitan machines
diff --git a/LayoutTests/inspector/dom/highlightSelector-expected.txt b/LayoutTests/inspector/dom/highlightSelector-expected.txt
new file mode 100644 (file)
index 0000000..b6b07e3
--- /dev/null
@@ -0,0 +1,1350 @@
+
+SELECTOR: div
+FRAMEID: 0.1
+FOUND: 3
+[
+  {
+    "scrollOffset": {
+      "x": 0,
+      "y": 0
+    },
+    "fragments": [
+      {
+        "quads": [
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 162
+            },
+            {
+              "x": 8,
+              "y": 162
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 162
+            },
+            {
+              "x": 8,
+              "y": 162
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 162
+            },
+            {
+              "x": 8,
+              "y": 162
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 162
+            },
+            {
+              "x": 8,
+              "y": 162
+            }
+          ]
+        ],
+        "contentColor": "#ffffff",
+        "contentOutlineColor": "rgba(0, 0, 0, 0)",
+        "paddingColor": "#ffffff",
+        "borderColor": "#ffffff",
+        "marginColor": "#ffffff"
+      }
+    ],
+    "elementData": {
+      "tagName": "div",
+      "idValue": "",
+      "size": {
+        "width": 784,
+        "height": 154
+      },
+      "role": ""
+    }
+  },
+  {
+    "scrollOffset": {
+      "x": 0,
+      "y": 0
+    },
+    "fragments": [
+      {
+        "quads": [
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ]
+        ],
+        "contentColor": "#ffffff",
+        "contentOutlineColor": "rgba(0, 0, 0, 0)",
+        "paddingColor": "#ffffff",
+        "borderColor": "#ffffff",
+        "marginColor": "#ffffff"
+      }
+    ],
+    "elementData": {
+      "tagName": "div",
+      "idValue": "",
+      "className": ".class-one",
+      "size": {
+        "width": 784,
+        "height": 0
+      },
+      "role": ""
+    }
+  },
+  {
+    "scrollOffset": {
+      "x": 0,
+      "y": 0
+    },
+    "fragments": [
+      {
+        "quads": [
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 8
+            },
+            {
+              "x": 792,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ]
+        ],
+        "contentColor": "#ffffff",
+        "contentOutlineColor": "rgba(0, 0, 0, 0)",
+        "paddingColor": "#ffffff",
+        "borderColor": "#ffffff",
+        "marginColor": "#ffffff"
+      }
+    ],
+    "elementData": {
+      "tagName": "div",
+      "idValue": "id-one",
+      "className": ".class-two",
+      "size": {
+        "width": 784,
+        "height": 0
+      },
+      "role": ""
+    }
+  }
+]
+
+
+SELECTOR: .class-one
+FRAMEID: 0.1
+FOUND: 2
+[
+  {
+    "scrollOffset": {
+      "x": 0,
+      "y": 0
+    },
+    "fragments": [
+      {
+        "quads": [
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ]
+        ],
+        "contentColor": "#ffffff",
+        "contentOutlineColor": "rgba(0, 0, 0, 0)",
+        "paddingColor": "#ffffff",
+        "borderColor": "#ffffff",
+        "marginColor": "#ffffff"
+      }
+    ],
+    "elementData": {
+      "tagName": "div",
+      "idValue": "",
+      "className": ".class-one",
+      "size": {
+        "width": 769,
+        "height": 0
+      },
+      "role": ""
+    }
+  },
+  {
+    "scrollOffset": {
+      "x": 0,
+      "y": 0
+    },
+    "fragments": [
+      {
+        "quads": [
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 312,
+              "y": 8
+            },
+            {
+              "x": 312,
+              "y": 162
+            },
+            {
+              "x": 8,
+              "y": 162
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 312,
+              "y": 8
+            },
+            {
+              "x": 312,
+              "y": 162
+            },
+            {
+              "x": 8,
+              "y": 162
+            }
+          ],
+          [
+            {
+              "x": 10,
+              "y": 10
+            },
+            {
+              "x": 310,
+              "y": 10
+            },
+            {
+              "x": 310,
+              "y": 160
+            },
+            {
+              "x": 10,
+              "y": 160
+            }
+          ],
+          [
+            {
+              "x": 10,
+              "y": 10
+            },
+            {
+              "x": 310,
+              "y": 10
+            },
+            {
+              "x": 310,
+              "y": 160
+            },
+            {
+              "x": 10,
+              "y": 160
+            }
+          ]
+        ],
+        "contentColor": "#ffffff",
+        "contentOutlineColor": "rgba(0, 0, 0, 0)",
+        "paddingColor": "#ffffff",
+        "borderColor": "#ffffff",
+        "marginColor": "#ffffff"
+      }
+    ],
+    "elementData": {
+      "tagName": "iframe",
+      "idValue": "",
+      "className": ".class-one",
+      "size": {
+        "width": 304,
+        "height": 154
+      },
+      "role": "group"
+    }
+  }
+]
+
+
+SELECTOR: #id-one
+FRAMEID: 0.1
+FOUND: 1
+[
+  {
+    "scrollOffset": {
+      "x": 0,
+      "y": 0
+    },
+    "fragments": [
+      {
+        "quads": [
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ]
+        ],
+        "contentColor": "#ffffff",
+        "contentOutlineColor": "rgba(0, 0, 0, 0)",
+        "paddingColor": "#ffffff",
+        "borderColor": "#ffffff",
+        "marginColor": "#ffffff"
+      }
+    ],
+    "elementData": {
+      "tagName": "div",
+      "idValue": "id-one",
+      "className": ".class-two",
+      "size": {
+        "width": 769,
+        "height": 0
+      },
+      "role": ""
+    }
+  }
+]
+
+
+SELECTOR: .class-one, .class-two
+FRAMEID: 0.1
+FOUND: 3
+[
+  {
+    "scrollOffset": {
+      "x": 0,
+      "y": 0
+    },
+    "fragments": [
+      {
+        "quads": [
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ]
+        ],
+        "contentColor": "#ffffff",
+        "contentOutlineColor": "rgba(0, 0, 0, 0)",
+        "paddingColor": "#ffffff",
+        "borderColor": "#ffffff",
+        "marginColor": "#ffffff"
+      }
+    ],
+    "elementData": {
+      "tagName": "div",
+      "idValue": "",
+      "className": ".class-one",
+      "size": {
+        "width": 769,
+        "height": 0
+      },
+      "role": ""
+    }
+  },
+  {
+    "scrollOffset": {
+      "x": 0,
+      "y": 0
+    },
+    "fragments": [
+      {
+        "quads": [
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 777,
+              "y": 8
+            },
+            {
+              "x": 8,
+              "y": 8
+            }
+          ]
+        ],
+        "contentColor": "#ffffff",
+        "contentOutlineColor": "rgba(0, 0, 0, 0)",
+        "paddingColor": "#ffffff",
+        "borderColor": "#ffffff",
+        "marginColor": "#ffffff"
+      }
+    ],
+    "elementData": {
+      "tagName": "div",
+      "idValue": "id-one",
+      "className": ".class-two",
+      "size": {
+        "width": 769,
+        "height": 0
+      },
+      "role": ""
+    }
+  },
+  {
+    "scrollOffset": {
+      "x": 0,
+      "y": 0
+    },
+    "fragments": [
+      {
+        "quads": [
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 312,
+              "y": 8
+            },
+            {
+              "x": 312,
+              "y": 162
+            },
+            {
+              "x": 8,
+              "y": 162
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 312,
+              "y": 8
+            },
+            {
+              "x": 312,
+              "y": 162
+            },
+            {
+              "x": 8,
+              "y": 162
+            }
+          ],
+          [
+            {
+              "x": 10,
+              "y": 10
+            },
+            {
+              "x": 310,
+              "y": 10
+            },
+            {
+              "x": 310,
+              "y": 160
+            },
+            {
+              "x": 10,
+              "y": 160
+            }
+          ],
+          [
+            {
+              "x": 10,
+              "y": 10
+            },
+            {
+              "x": 310,
+              "y": 10
+            },
+            {
+              "x": 310,
+              "y": 160
+            },
+            {
+              "x": 10,
+              "y": 160
+            }
+          ]
+        ],
+        "contentColor": "#ffffff",
+        "contentOutlineColor": "rgba(0, 0, 0, 0)",
+        "paddingColor": "#ffffff",
+        "borderColor": "#ffffff",
+        "marginColor": "#ffffff"
+      }
+    ],
+    "elementData": {
+      "tagName": "iframe",
+      "idValue": "",
+      "className": ".class-one",
+      "size": {
+        "width": 304,
+        "height": 154
+      },
+      "role": "group"
+    }
+  }
+]
+
+
+SELECTOR: iframe.class-one
+FRAMEID: undefined
+FOUND: 1
+[
+  {
+    "scrollOffset": {
+      "x": 0,
+      "y": 0
+    },
+    "fragments": [
+      {
+        "quads": [
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 312,
+              "y": 8
+            },
+            {
+              "x": 312,
+              "y": 162
+            },
+            {
+              "x": 8,
+              "y": 162
+            }
+          ],
+          [
+            {
+              "x": 8,
+              "y": 8
+            },
+            {
+              "x": 312,
+              "y": 8
+            },
+            {
+              "x": 312,
+              "y": 162
+            },
+            {
+              "x": 8,
+              "y": 162
+            }
+          ],
+          [
+            {
+              "x": 10,
+              "y": 10
+            },
+            {
+              "x": 310,
+              "y": 10
+            },
+            {
+              "x": 310,
+              "y": 160
+            },
+            {
+              "x": 10,
+              "y": 160
+            }
+          ],
+          [
+            {
+              "x": 10,
+              "y": 10
+            },
+            {
+              "x": 310,
+              "y": 10
+            },
+            {
+              "x": 310,
+              "y": 160
+            },
+            {
+              "x": 10,
+              "y": 160
+            }
+          ]
+        ],
+        "contentColor": "#ffffff",
+        "contentOutlineColor": "rgba(0, 0, 0, 0)",
+        "paddingColor": "#ffffff",
+        "borderColor": "#ffffff",
+        "marginColor": "#ffffff"
+      }
+    ],
+    "elementData": {
+      "tagName": "iframe",
+      "idValue": "",
+      "className": ".class-one",
+      "size": {
+        "width": 304,
+        "height": 154
+      },
+      "role": "group"
+    }
+  }
+]
+
+
+PASS: Expected error: No frame for given id found
+SELECTOR: div
+FRAMEID: 0.2
+
+
+SELECTOR: .no-elements
+FRAMEID: 0.1
+FOUND: 0
+[]
+
+
+PASS: Expected error: DOM Error while querying
+SELECTOR: $%foobar
+FRAMEID: 0.1
+
+
+SELECTOR: div
+FRAMEID: 0.3
+FOUND: 2
+[
+  {
+    "scrollOffset": {
+      "x": 0,
+      "y": 0
+    },
+    "fragments": [
+      {
+        "quads": [
+          [
+            {
+              "x": 18,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 18,
+              "y": 18
+            }
+          ],
+          [
+            {
+              "x": 18,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 18,
+              "y": 18
+            }
+          ],
+          [
+            {
+              "x": 18,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 18,
+              "y": 18
+            }
+          ],
+          [
+            {
+              "x": 18,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 18,
+              "y": 18
+            }
+          ]
+        ],
+        "contentColor": "#ffffff",
+        "contentOutlineColor": "rgba(0, 0, 0, 0)",
+        "paddingColor": "#ffffff",
+        "borderColor": "#ffffff",
+        "marginColor": "#ffffff"
+      }
+    ],
+    "elementData": {
+      "tagName": "div",
+      "idValue": "id-one",
+      "size": {
+        "width": 284,
+        "height": 0
+      },
+      "role": ""
+    }
+  },
+  {
+    "scrollOffset": {
+      "x": 0,
+      "y": 0
+    },
+    "fragments": [
+      {
+        "quads": [
+          [
+            {
+              "x": 18,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 18,
+              "y": 18
+            }
+          ],
+          [
+            {
+              "x": 18,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 18,
+              "y": 18
+            }
+          ],
+          [
+            {
+              "x": 18,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 18,
+              "y": 18
+            }
+          ],
+          [
+            {
+              "x": 18,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 18,
+              "y": 18
+            }
+          ]
+        ],
+        "contentColor": "#ffffff",
+        "contentOutlineColor": "rgba(0, 0, 0, 0)",
+        "paddingColor": "#ffffff",
+        "borderColor": "#ffffff",
+        "marginColor": "#ffffff"
+      }
+    ],
+    "elementData": {
+      "tagName": "div",
+      "idValue": "",
+      "size": {
+        "width": 284,
+        "height": 0
+      },
+      "role": ""
+    }
+  }
+]
+
+
+SELECTOR: #id-one
+FRAMEID: 0.3
+FOUND: 1
+[
+  {
+    "scrollOffset": {
+      "x": 0,
+      "y": 0
+    },
+    "fragments": [
+      {
+        "quads": [
+          [
+            {
+              "x": 18,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 18,
+              "y": 18
+            }
+          ],
+          [
+            {
+              "x": 18,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 18,
+              "y": 18
+            }
+          ],
+          [
+            {
+              "x": 18,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 18,
+              "y": 18
+            }
+          ],
+          [
+            {
+              "x": 18,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 302,
+              "y": 18
+            },
+            {
+              "x": 18,
+              "y": 18
+            }
+          ]
+        ],
+        "contentColor": "#ffffff",
+        "contentOutlineColor": "rgba(0, 0, 0, 0)",
+        "paddingColor": "#ffffff",
+        "borderColor": "#ffffff",
+        "marginColor": "#ffffff"
+      }
+    ],
+    "elementData": {
+      "tagName": "div",
+      "idValue": "id-one",
+      "size": {
+        "width": 284,
+        "height": 0
+      },
+      "role": ""
+    }
+  }
+]
+
+
+
diff --git a/LayoutTests/inspector/dom/highlightSelector-iframe.html b/LayoutTests/inspector/dom/highlightSelector-iframe.html
new file mode 100644 (file)
index 0000000..2fbf61e
--- /dev/null
@@ -0,0 +1,8 @@
+<html>
+    <head>
+    </head>
+    <body>
+        <div id="id-one"></div>
+        <div></div>
+    </body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/inspector/dom/highlightSelector.html b/LayoutTests/inspector/dom/highlightSelector.html
new file mode 100644 (file)
index 0000000..eb7d5a7
--- /dev/null
@@ -0,0 +1,86 @@
+<html>
+<head>
+<script type="text/javascript" src="../../http/tests/inspector/inspector-test.js"></script>
+<script>
+function test() {
+    var testcases = [
+        {'frameId': '0.1', 'selector': 'div'},
+        {'frameId': '0.1', 'selector': '.class-one'},
+        {'frameId': '0.1', 'selector': '#id-one'},
+        {'frameId': '0.1', 'selector': '.class-one, .class-two'},
+        {'selector': 'iframe.class-one'}, // No frame ID.
+        {'frameId': '0.2', 'selector': 'div', "error": true}, // Non-existing frame ID.
+        {'frameId': '0.1', 'selector': '.no-elements'}, // Non-matching selector.
+        {'frameId': '0.1', 'selector': '$%foobar', "error": true}, // Invalid selector.
+        {'frameId': '0.3', 'selector': 'div'},
+        {'frameId': '0.3', 'selector': '#id-one'},
+    ];
+
+    function getHighlightObjectForSelector(selector, frameId, errorExpected, callback) {
+        var highlightConfig = {
+            showInfo: true,
+            contentColor: {r: 255, g: 255, b: 255},
+            paddingColor: {r: 255, g: 255, b: 255},
+            borderColor: {r: 255, g: 255, b: 255},
+            marginColor: {r: 255, g: 255, b: 255},
+        };
+
+        DOMAgent.highlightSelector(highlightConfig, selector, frameId, highlightSelectorCallback);
+
+        function highlightSelectorCallback(error) {
+            if (errorExpected) {
+                InspectorTest.assert(error, "Missing expected error. Error: " + error);
+
+                if (error)
+                    InspectorTest.log("PASS: Expected error: " + error);
+
+                callback();
+                return;
+            } else
+                InspectorTest.assert(!error, "Error in callback for DOMAgent.highlightSelector: " + error);
+
+            InspectorTest.evaluateInPage("window.internals.inspectorHighlightObject()", receivedHighlightObject);
+        }
+
+        function receivedHighlightObject(error, payload, wasThrown) {
+            InspectorTest.assert(!error, "When evaluating code, received unexpected error:" + error);
+            InspectorTest.assert(!wasThrown, "When evaluating code, an exception was thrown:" + wasThrown);
+
+            var data = JSON.parse(payload.value);
+            callback(data);
+        }
+    }
+
+    function runNextTest(tests) {
+        var testcase = tests[0];
+
+        getHighlightObjectForSelector(testcase.selector, testcase.frameId, testcase.error, function(payload) {
+            InspectorTest.log("SELECTOR: " + testcase.selector);
+            InspectorTest.log("FRAMEID: " + testcase.frameId);
+
+            if (payload) {
+                InspectorTest.log("FOUND: " + payload.length);
+                InspectorTest.log(JSON.stringify(payload, null, 2));
+            }
+
+            InspectorTest.log("\n");
+        
+            if (tests.length > 1)
+                runNextTest(tests.splice(1));
+            else
+                InspectorTest.completeTest();
+        });
+    }
+
+    runNextTest(testcases);
+}
+</script>
+</head>
+<body onload="runTest()">
+    <div>
+        <div class="class-one"></div>
+        <div id="id-one" class="class-two"></div>
+        <iframe class="class-one" src="highlightSelector-iframe.html"></iframe>
+    </div>
+</body>
+</html>
\ No newline at end of file
index 7c4617b..93efb1b 100644 (file)
@@ -1,3 +1,12 @@
+2015-06-19  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: Highlight currently edited CSS selector
+        https://bugs.webkit.org/show_bug.cgi?id=145658
+
+        Reviewed by Joseph Pecoraro.
+
+        * inspector/protocol/DOM.json: Added highlightSelector to show highlight over multiple nodes.
+
 2015-06-19  Mark Lam  <mark.lam@apple.com>
 
         Gardening: fix build for EWS bots.
index 1763c14..5e28dda 100644 (file)
             "description": "Highlights given quad. Coordinates are absolute with respect to the main frame viewport."
         },
         {
+            "name": "highlightSelector",
+            "parameters": [
+                { "name": "highlightConfig", "$ref": "HighlightConfig", "description": "A descriptor for the highlight appearance." },
+                { "name": "selectorString", "type": "string", "description": "A CSS selector for finding matching nodes to highlight." },
+                { "name": "frameId", "type": "string", "optional": true, "description": "Identifier of the frame which will be searched using the selector.  If not provided, the main frame will be used." }
+            ],
+            "description": "Highlights all DOM nodes that match a given selector. A string containing a CSS selector must be specified."
+        },
+        {
             "name": "highlightNode",
             "parameters": [
                 { "name": "highlightConfig", "$ref": "HighlightConfig", "description": "A descriptor for the highlight appearance." },
index 9065972..8eba2c0 100644 (file)
@@ -1,3 +1,31 @@
+2015-06-19  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: Highlight currently edited CSS selector
+        https://bugs.webkit.org/show_bug.cgi?id=145658
+
+        Reviewed by Joseph Pecoraro.
+
+        Test: inspector/dom/highlight-multiple-shapes.html
+
+        * inspector/InspectorController.cpp:
+        (WebCore::InspectorController::buildObjectForHighlightedNode):
+        * inspector/InspectorController.h:
+        * inspector/InspectorDOMAgent.cpp:
+        (WebCore::InspectorDOMAgent::highlightSelector): Gets a list of all nodes matching a given selector string and highlights each of them.
+        * inspector/InspectorDOMAgent.h:
+        * inspector/InspectorOverlay.cpp:
+        (WebCore::InspectorOverlay::hideHighlight):
+        (WebCore::InspectorOverlay::highlightNodeList): Loops through a given NodeList to create highlightObjects for each of them.
+        (WebCore::InspectorOverlay::shouldShowOverlay):
+        (WebCore::buildObjectForElementData): Don't show flow fragments when highlighting multiple nodes.
+        (WebCore::InspectorOverlay::buildHighlightObjectForNode):
+        (WebCore::InspectorOverlay::buildObjectForHighlightedNode): Now returns an array containing the highlightObject for each highligthed node.
+        (WebCore::InspectorOverlay::drawNodeHighlight): Now sends an array to the InspectorOverlayPage.js to provide support for highlighting multiple nodes.
+        * inspector/InspectorOverlay.h:
+        * inspector/InspectorOverlayPage.js: Now expects an array as its parameter and loops through it to highlight each node given.
+        If the parameter array contains more than one element, do not draw the textbox containing info on that node.
+        (drawNodeHighlight):
+
 2015-06-19  Joseph Pecoraro  <pecoraro@apple.com>
 
         Crash under WebCore::PageConsoleClient::addMessage attempting to log insecure content message in ImageDocument
index a19ba4a..1779ffd 100644 (file)
@@ -324,9 +324,9 @@ void InspectorController::getHighlight(Highlight& highlight, InspectorOverlay::C
     m_overlay->getHighlight(highlight, coordinateSystem);
 }
 
-RefPtr<Inspector::Protocol::OverlayTypes::NodeHighlightData> InspectorController::buildObjectForHighlightedNode() const
+Ref<Inspector::Protocol::Array<Inspector::Protocol::OverlayTypes::NodeHighlightData>> InspectorController::buildObjectForHighlightedNodes() const
 {
-    return m_overlay->buildObjectForHighlightedNode();
+    return m_overlay->buildObjectForHighlightedNodes();
 }
 
 void InspectorController::inspect(Node* node)
index 5c43071..2dfc346 100644 (file)
@@ -114,7 +114,7 @@ public:
 
     void setIndicating(bool);
 
-    WEBCORE_EXPORT RefPtr<Inspector::Protocol::OverlayTypes::NodeHighlightData> buildObjectForHighlightedNode() const;
+    WEBCORE_EXPORT Ref<Inspector::Protocol::Array<Inspector::Protocol::OverlayTypes::NodeHighlightData>> buildObjectForHighlightedNodes() const;
 
     bool isUnderTest() const { return m_isUnderTest; }
     void setIsUnderTest(bool isUnderTest) { m_isUnderTest = isUnderTest; }
index 7fa42bb..0ed2c5c 100644 (file)
@@ -1075,6 +1075,41 @@ void InspectorDOMAgent::innerHighlightQuad(std::unique_ptr<FloatQuad> quad, cons
     m_overlay->highlightQuad(WTF::move(quad), *highlightConfig);
 }
 
+void InspectorDOMAgent::highlightSelector(ErrorString& errorString, const InspectorObject& highlightInspectorObject, const String& selectorString, const String* frameId)
+{
+    RefPtr<Document> document;
+
+    if (frameId) {
+        Frame* frame = m_pageAgent->frameForId(*frameId);
+        if (!frame) {
+            errorString = ASCIILiteral("No frame for given id found");
+            return;
+        }
+
+        document = frame->document();
+    } else
+        document = m_document;
+
+    if (!document) {
+        errorString = ASCIILiteral("Document could not be found");
+        return;
+    }
+
+    ExceptionCode ec = 0;
+    RefPtr<NodeList> nodes = document->querySelectorAll(selectorString, ec);
+    // FIXME: <https://webkit.org/b/146161> Web Inspector: DOM.highlightSelector should work for "a:visited"
+    if (ec) {
+        errorString = ASCIILiteral("DOM Error while querying");
+        return;
+    }
+
+    std::unique_ptr<HighlightConfig> highlightConfig = highlightConfigFromInspectorObject(errorString, &highlightInspectorObject);
+    if (!highlightConfig)
+        return;
+
+    m_overlay->highlightNodeList(nodes, *highlightConfig);
+}
+
 void InspectorDOMAgent::highlightNode(ErrorString& errorString, const InspectorObject& highlightInspectorObject, const int* nodeId, const String* objectId)
 {
     Node* node = 0;
@@ -1294,6 +1329,7 @@ Ref<Inspector::Protocol::DOM::Node> InspectorDOMAgent::buildObjectForNode(Node*
 
     } else if (is<Document>(*node)) {
         Document& document = downcast<Document>(*node);
+        value->setFrameId(m_pageAgent->frameId(document.frame()));
         value->setDocumentURL(documentURLString(&document));
         value->setBaseURL(documentBaseURLString(&document));
         value->setXmlVersion(document.xmlVersion());
index f4e2960..a8a5531 100644 (file)
@@ -143,6 +143,7 @@ public:
     virtual void hideHighlight(ErrorString&) override;
     virtual void highlightRect(ErrorString&, int x, int y, int width, int height, const Inspector::InspectorObject* color, const Inspector::InspectorObject* outlineColor, const bool* usePageCoordinates) override;
     virtual void highlightQuad(ErrorString&, const Inspector::InspectorArray& quad, const Inspector::InspectorObject* color, const Inspector::InspectorObject* outlineColor, const bool* usePageCoordinates) override;
+    virtual void highlightSelector(ErrorString&, const Inspector::InspectorObject& highlightConfig, const String& selectorString, const String* frameId) override;
     virtual void highlightNode(ErrorString&, const Inspector::InspectorObject& highlightConfig, const int* nodeId, const String* objectId) override;
     virtual void highlightFrame(ErrorString&, const String& frameId, const Inspector::InspectorObject* color, const Inspector::InspectorObject* outlineColor) override;
 
index 25ed16b..6d3a0f3 100644 (file)
@@ -244,14 +244,24 @@ void InspectorOverlay::setPausedInDebuggerMessage(const String* message)
 void InspectorOverlay::hideHighlight()
 {
     m_highlightNode.clear();
+    m_highlightNodeList.clear();
     m_highlightQuad.reset();
     update();
 }
 
+void InspectorOverlay::highlightNodeList(PassRefPtr<NodeList> nodes, const HighlightConfig& highlightConfig)
+{
+    m_nodeHighlightConfig = highlightConfig;
+    m_highlightNodeList = nodes;
+    m_highlightNode.clear();
+    update();
+}
+
 void InspectorOverlay::highlightNode(Node* node, const HighlightConfig& highlightConfig)
 {
     m_nodeHighlightConfig = highlightConfig;
     m_highlightNode = node;
+    m_highlightNodeList.clear();
     update();
 }
 
@@ -289,7 +299,7 @@ void InspectorOverlay::setIndicating(bool indicating)
 
 bool InspectorOverlay::shouldShowOverlay() const
 {
-    return m_highlightNode || m_highlightQuad || m_indicating || m_showingPaintRects || !m_pausedInDebuggerMessage.isNull();
+    return m_highlightNode || m_highlightNodeList || m_highlightQuad || m_indicating || m_showingPaintRects || !m_pausedInDebuggerMessage.isNull();
 }
 
 void InspectorOverlay::update()
@@ -673,7 +683,7 @@ static RefPtr<Inspector::Protocol::OverlayTypes::ShapeOutsideData> buildObjectFo
 }
 #endif
 
-static RefPtr<Inspector::Protocol::OverlayTypes::ElementData> buildObjectForElementData(Node* node)
+static RefPtr<Inspector::Protocol::OverlayTypes::ElementData> buildObjectForElementData(Node* node, HighlightType type)
 {
     if (!is<Element>(node) || !node->document().frame())
         return nullptr;
@@ -716,7 +726,7 @@ static RefPtr<Inspector::Protocol::OverlayTypes::ElementData> buildObjectForElem
         .release();
     elementData->setSize(WTF::move(sizeObject));
 
-    if (renderer->isRenderNamedFlowFragmentContainer()) {
+    if (type != HighlightType::NodeList && renderer->isRenderNamedFlowFragmentContainer()) {
         RenderNamedFlowFragment& region = *downcast<RenderBlockFlow>(*renderer).renderNamedFlowFragment();
         if (region.isValid()) {
             RenderFlowThread* flowThread = region.flowThread();
@@ -757,12 +767,11 @@ static RefPtr<Inspector::Protocol::OverlayTypes::ElementData> buildObjectForElem
     return WTF::move(elementData);
 }
 
-RefPtr<Inspector::Protocol::OverlayTypes::NodeHighlightData> InspectorOverlay::buildObjectForHighlightedNode() const
+RefPtr<Inspector::Protocol::OverlayTypes::NodeHighlightData> InspectorOverlay::buildHighlightObjectForNode(Node* node, HighlightType type) const
 {
-    if (!m_highlightNode)
+    if (!node)
         return nullptr;
 
-    Node* node = m_highlightNode.get();
     RenderObject* renderer = node->renderer();
     if (!renderer)
         return nullptr;
@@ -780,17 +789,34 @@ RefPtr<Inspector::Protocol::OverlayTypes::NodeHighlightData> InspectorOverlay::b
         .release();
 
     if (m_nodeHighlightConfig.showInfo) {
-        if (RefPtr<Inspector::Protocol::OverlayTypes::ElementData> elementData = buildObjectForElementData(node))
+        if (RefPtr<Inspector::Protocol::OverlayTypes::ElementData> elementData = buildObjectForElementData(node, type))
             nodeHighlightObject->setElementData(WTF::move(elementData));
     }
 
     return WTF::move(nodeHighlightObject);
 }
 
+Ref<Inspector::Protocol::Array<Inspector::Protocol::OverlayTypes::NodeHighlightData>> InspectorOverlay::buildObjectForHighlightedNodes() const
+{
+    auto highlights = Inspector::Protocol::Array<Inspector::Protocol::OverlayTypes::NodeHighlightData>::create();
+
+    if (m_highlightNode) {
+        if (RefPtr<Inspector::Protocol::OverlayTypes::NodeHighlightData> nodeHighlightData = buildHighlightObjectForNode(m_highlightNode.get(), HighlightType::Node))
+            highlights->addItem(WTF::move(nodeHighlightData));
+    } else if (m_highlightNodeList) {
+        for (unsigned i = 0; i < m_highlightNodeList->length(); ++i) {
+            if (RefPtr<Inspector::Protocol::OverlayTypes::NodeHighlightData> nodeHighlightData = buildHighlightObjectForNode(m_highlightNodeList->item(i), HighlightType::NodeList))
+                highlights->addItem(WTF::move(nodeHighlightData));
+        }
+    }
+
+    return WTF::move(highlights);
+}
+
 void InspectorOverlay::drawNodeHighlight()
 {
-    if (RefPtr<Inspector::Protocol::OverlayTypes::NodeHighlightData> highlightObject = buildObjectForHighlightedNode())
-        evaluateInOverlay("drawNodeHighlight", WTF::move(highlightObject));
+    if (m_highlightNode || m_highlightNodeList)
+        evaluateInOverlay("drawNodeHighlight", buildObjectForHighlightedNodes());
 }
 
 void InspectorOverlay::drawQuadHighlight()
index 4326a10..011464e 100644 (file)
@@ -32,7 +32,9 @@
 #include "Color.h"
 #include "FloatQuad.h"
 #include "LayoutRect.h"
+#include "NodeList.h"
 #include "Timer.h"
+#include <inspector/InspectorProtocolObjects.h>
 #include <wtf/Deque.h>
 #include <wtf/RefPtr.h>
 #include <wtf/Vector.h>
@@ -72,6 +74,7 @@ public:
 
 enum class HighlightType {
     Node, // Provides 4 quads: margin, border, padding, content.
+    NodeList, // Provides a list of nodes.
     Rects, // Provides a list of quads.
 };
 
@@ -117,6 +120,7 @@ public:
     void setPausedInDebuggerMessage(const String*);
 
     void hideHighlight();
+    void highlightNodeList(PassRefPtr<NodeList>, const HighlightConfig&);
     void highlightNode(Node*, const HighlightConfig&);
     void highlightQuad(std::unique_ptr<FloatQuad>, const HighlightConfig&);
     
@@ -129,7 +133,8 @@ public:
 
     void setIndicating(bool indicating);
 
-    RefPtr<Inspector::Protocol::OverlayTypes::NodeHighlightData> buildObjectForHighlightedNode() const;
+    RefPtr<Inspector::Protocol::OverlayTypes::NodeHighlightData> buildHighlightObjectForNode(Node*, HighlightType) const;
+    Ref<Inspector::Protocol::Array<Inspector::Protocol::OverlayTypes::NodeHighlightData>> buildObjectForHighlightedNodes() const;
 
     void freePage();
 private:
@@ -153,6 +158,7 @@ private:
     InspectorClient* m_client;
     String m_pausedInDebuggerMessage;
     RefPtr<Node> m_highlightNode;
+    RefPtr<NodeList> m_highlightNodeList;
     HighlightConfig m_nodeHighlightConfig;
     std::unique_ptr<FloatQuad> m_highlightQuad;
     std::unique_ptr<Page> m_overlayPage;
index ca5b398..651ce3d 100644 (file)
@@ -487,26 +487,32 @@ function hidePageIndication()
     document.body.classList.remove("indicate");
 }
 
-function drawNodeHighlight(highlight)
+function drawNodeHighlight(allHighlights)
 {
-    context.save();
-    context.translate(-highlight.scrollOffset.x, -highlight.scrollOffset.y);
+    var elementTitleContainer = document.getElementById("element-title-container");
+    while (elementTitleContainer.hasChildNodes())
+        elementTitleContainer.removeChild(elementTitleContainer.lastChild);
 
-    for (var i = 0; i < highlight.fragments.length; ++i)
-        _drawFragmentHighlight(highlight.fragments[i]);
+    for (var highlight of allHighlights) {
+        context.save();
+        context.translate(-highlight.scrollOffset.x, -highlight.scrollOffset.y);
 
-    if (highlight.elementData && highlight.elementData.regionFlowData)
-        _drawRegionsHighlight(highlight.elementData.regionFlowData.regions);
+        for (var fragment of highlight.fragments)
+            _drawFragmentHighlight(fragment);
 
-    if (highlight.elementData && highlight.elementData.shapeOutsideData)
-        _drawShapeHighlight(highlight.elementData.shapeOutsideData);
+        if (highlight.elementData && highlight.elementData.regionFlowData)
+            _drawRegionsHighlight(highlight.elementData.regionFlowData.regions);
 
-    context.restore();
+        if (highlight.elementData && highlight.elementData.shapeOutsideData)
+            _drawShapeHighlight(highlight.elementData.shapeOutsideData);
 
-    var elementTitleContainer = document.getElementById("element-title-container");
-    elementTitleContainer.innerHTML = "";
-    for (var i = 0; i < highlight.fragments.length; ++i)
-        _drawElementTitle(highlight.elementData, highlight.fragments[i], highlight.scrollOffset);
+        context.restore();
+
+        if (allHighlights.length === 1) {
+            for (var fragment of highlight.fragments)
+                _drawElementTitle(highlight.elementData, fragment, highlight.scrollOffset);
+        }
+    }
 }
 
 function drawQuadHighlight(highlight)
index 7501967..1a10517 100644 (file)
@@ -926,8 +926,8 @@ String Internals::inspectorHighlightObject(ExceptionCode& ec)
         ec = INVALID_ACCESS_ERR;
         return String();
     }
-    auto object = document->page()->inspectorController().buildObjectForHighlightedNode();
-    return object ? object->toJSONString() : String();
+
+    return document->page()->inspectorController().buildObjectForHighlightedNodes()->toJSONString();
 }
 
 unsigned Internals::markerCountForNode(Node* node, const String& markerType, ExceptionCode& ec)
index 1709529..ae009d7 100644 (file)
@@ -1,3 +1,18 @@
+2015-06-19  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: Highlight currently edited CSS selector
+        https://bugs.webkit.org/show_bug.cgi?id=145658
+
+        Reviewed by Joseph Pecoraro.
+
+        * UserInterface/Views/CSSStyleDeclarationSection.js:
+        (WebInspector.CSSStyleDeclarationSection): Added event listeners on the selector text for mouseover and mouseout.
+        (WebInspector.CSSStyleDeclarationSection.prototype._highlightNodesWithSelector): Selector text mouseover action that highlights all nodes that match the selector string in the corresponding frame.
+        (WebInspector.CSSStyleDeclarationSection.prototype._hideHighlightOnNodesWithSelector): Selector text mouseout action that clears all highlights on matching nodes.
+        * UserInterface/Views/DOMNode.js:
+        (WebInspector.DOMNode): If the payload contains a frameId, then save it.
+        (WebInspector.DOMNode.frameIdentifier):
+
 2015-06-19  Joseph Pecoraro  <pecoraro@apple.com>
 
         Web Inspector: Overlapping dashboard views causing lots of layers in source view
index bd5d3bd..e064626 100644 (file)
@@ -87,6 +87,9 @@ WebInspector.DOMNode = class DOMNode extends WebInspector.Object
             this._renumber();
         }
 
+        if (payload.frameId)
+            this._frameIdentifier = payload.frameId;
+
         if (this._nodeType === Node.ELEMENT_NODE) {
             // HTML and BODY from internal iframes should not overwrite top-level ones.
             if (this.ownerDocument && !this.ownerDocument.documentElement && this._nodeName === "HTML")
@@ -582,6 +585,11 @@ WebInspector.DOMNode = class DOMNode extends WebInspector.Object
                 callback.apply(null, arguments);
         };
     }
+
+    get frameIdentifier()
+    {
+        return this._frameIdentifier;
+    }
 };
 
 WebInspector.DOMNode.Event = {
index 4fb0d01..3bdc400 100644 (file)
@@ -48,6 +48,8 @@ WebInspector.CSSStyleDeclarationSection = function(delegate, style)
     this._selectorElement = document.createElement("span");
     this._selectorElement.className = "selector";
     this._selectorElement.setAttribute("spellcheck", "false");
+    this._selectorElement.addEventListener("mouseover", this._highlightNodesWithSelector.bind(this));
+    this._selectorElement.addEventListener("mouseout", this._hideHighlightOnNodesWithSelector.bind(this));
     this._headerElement.appendChild(this._selectorElement);
 
     this._originElement = document.createElement("span");
@@ -391,6 +393,31 @@ WebInspector.CSSStyleDeclarationSection.prototype = {
         this._element.classList.toggle("rule-disabled", this._ruleDisabled);
     },
 
+    _highlightNodesWithSelector: function()
+    {
+        var highlightConfig = {
+            borderColor: {r: 255, g: 229, b: 153, a: 0.66},
+            contentColor: {r: 111, g: 168, b: 220, a: 0.66},
+            marginColor: {r: 246, g: 178, b: 107, a: 0.66},
+            paddingColor: {r: 147, g: 196, b: 125, a: 0.66},
+            showInfo: true
+        };
+
+        if (!this._style.ownerRule) {
+            // COMPATIBILITY (iOS 6): Order of parameters changed in iOS 7.
+            DOMAgent.highlightNode.invoke({nodeId: this._style.node.id, highlightConfig});
+            return;
+        }
+
+        if (DOMAgent.highlightSelector)
+            DOMAgent.highlightSelector(highlightConfig, this._style.ownerRule.selectorText, this._style.node.ownerDocument.frameIdentifier);
+    },
+
+    _hideHighlightOnNodesWithSelector: function()
+    {
+        DOMAgent.hideHighlight();
+    },
+
     _commitSelector: function(mutations)
     {
         console.assert(this._style.ownerRule);