Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(344)

Unified Diff: Source/devtools/front_end/DOMAgent.js

Issue 75253002: DevTools: [Elements] Implement "Copy CSS Path" context menu item for elements (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/devtools/front_end/DOMAgent.js
diff --git a/Source/devtools/front_end/DOMAgent.js b/Source/devtools/front_end/DOMAgent.js
index 45467bc785d2b124fa86413c1df121a4feaaf940..e514613674bae9b2f99c2ae9eb220c4c2d357018 100644
--- a/Source/devtools/front_end/DOMAgent.js
+++ b/Source/devtools/front_end/DOMAgent.js
@@ -119,13 +119,13 @@ WebInspector.DOMNode.PseudoElementNames = {
* @param {string} value
* @param {boolean} optimized
*/
-WebInspector.DOMNode.XPathStep = function(value, optimized)
+WebInspector.DOMNode.PathStep = function(value, optimized)
{
this.value = value;
this.optimized = optimized;
}
-WebInspector.DOMNode.XPathStep.prototype = {
+WebInspector.DOMNode.PathStep.prototype = {
toString: function()
{
return this.value;
@@ -416,6 +416,14 @@ WebInspector.DOMNode.prototype = {
/**
* @param {boolean} optimized
*/
+ copyCSSPath: function(optimized)
+ {
+ InspectorFrontendHost.copyText(this.cssPath(optimized));
+ },
+
+ /**
+ * @param {boolean} optimized
+ */
copyXPath: function(optimized)
{
InspectorFrontendHost.copyText(this.xPath(optimized));
@@ -671,6 +679,95 @@ WebInspector.DOMNode.prototype = {
* @param {boolean} optimized
* @return {string}
*/
+ cssPath: function(optimized)
+ {
+ if (this._nodeType !== Node.ELEMENT_NODE)
+ return "";
+
+ var steps = [];
+ var contextNode = this;
+ while (contextNode) {
+ var step = contextNode._cssPathValue(optimized);
+ if (!step)
+ break; // Error - bail out early.
+ steps.push(step);
+ if (step.optimized)
+ break;
+ contextNode = contextNode.parentNode;
+ }
+
+ steps.reverse();
+ return steps.join(" > ");
+ },
+
+ /**
+ * @param {boolean} optimized
+ * @return {WebInspector.DOMNode.PathStep}
+ */
+ _cssPathValue: function(optimized)
+ {
+ if (this._nodeType !== Node.ELEMENT_NODE)
+ return null;
+ if (optimized) {
+ if (this.getAttribute("id"))
+ return new WebInspector.DOMNode.PathStep("#" + this.getAttribute("id"), true);
+ var nodeNameLower = this._nodeName.toLowerCase();
+ if (nodeNameLower === "body" || nodeNameLower === "head" || nodeNameLower === "html")
+ return new WebInspector.DOMNode.PathStep(this.nodeNameInCorrectCase(), true);
+ }
+ var ownValue = this.nodeNameInCorrectCase();
+ var parent = this.parentNode;
+ if (!parent || parent._nodeType === Node.DOCUMENT_NODE)
+ return new WebInspector.DOMNode.PathStep(ownValue, true);
+
+ var nodeName = this.nodeNameInCorrectCase();
aandrey 2013/11/18 13:43:51 move above and get rid of ownValue
apavlov 2013/11/18 15:03:59 Done.
+ var uniqueClassNamesArray = (this.getAttribute("class") || "").split(/\s+/g);
aandrey 2013/11/18 13:43:51 this array is not unique, and can contain empty st
apavlov 2013/11/18 15:03:59 It is not unique, but it cannot contain empty stri
aandrey 2013/11/18 15:15:56 FYI. a = document.createElement("div"); a.classNa
+ var uniqueClassNamesLeft = uniqueClassNamesArray.length;
+ var uniqueClassNames = uniqueClassNamesArray.keySet();
+ var needsClassNames;
aandrey 2013/11/18 13:43:51 plz init (with "false" I believe?)
apavlov 2013/11/18 15:03:59 Done.
+ var needsNthChild;
aandrey 2013/11/18 13:43:51 ditto
apavlov 2013/11/18 15:03:59 Done.
+ var ownIndex = -1;
+ var siblings = parent.children();
+ for (var i = 0; (ownIndex === -1 || !needsNthChild) && i < siblings.length; ++i) {
+ var sibling = siblings[i];
+ if (sibling === this) {
+ ownIndex = i;
+ continue;
+ }
+ if (sibling.nodeNameInCorrectCase() !== nodeName)
+ continue;
+ if (!uniqueClassNamesLeft) {
+ needsNthChild = true;
+ continue;
+ }
+
+ needsClassNames = true;
+ var siblingClasses = (sibling.getAttribute("class") || "").split(/\s+/g).keySet();
aandrey 2013/11/18 13:43:51 code dup, plz extract
apavlov 2013/11/18 15:03:59 Done.
+ for (var siblingClass in siblingClasses) {
+ if (!uniqueClassNames.hasOwnProperty(siblingClass))
+ continue;
+ delete uniqueClassNames[siblingClass];
+ if (!--uniqueClassNamesLeft) {
aandrey 2013/11/18 13:43:51 Did you mean uniqueClassNamesLeft to be initialize
apavlov 2013/11/18 15:03:59 Yep. Fixed
+ needsNthChild = true;
+ break;
+ }
+ }
+ }
+
+ var result = nodeName;
+ if (needsClassNames && uniqueClassNamesLeft) {
+ for (var className in uniqueClassNames)
+ result += "." + className;
+ }
+ if (needsNthChild)
+ result += ":nth-child(" + (ownIndex + 1) + ")";
+ return new WebInspector.DOMNode.PathStep(result, false);
+ },
+
+ /**
+ * @param {boolean} optimized
+ * @return {string}
+ */
xPath: function(optimized)
{
if (this._nodeType === Node.DOCUMENT_NODE)
@@ -694,7 +791,7 @@ WebInspector.DOMNode.prototype = {
/**
* @param {boolean} optimized
- * @return {WebInspector.DOMNode.XPathStep}
+ * @return {WebInspector.DOMNode.PathStep}
*/
_xPathValue: function(optimized)
{
@@ -706,7 +803,7 @@ WebInspector.DOMNode.prototype = {
switch (this._nodeType) {
case Node.ELEMENT_NODE:
if (optimized && this.getAttribute("id"))
- return new WebInspector.DOMNode.XPathStep("//*[@id=\"" + this.getAttribute("id") + "\"]", true);
+ return new WebInspector.DOMNode.PathStep("//*[@id=\"" + this.getAttribute("id") + "\"]", true);
ownValue = this._localName;
break;
case Node.ATTRIBUTE_NODE:
@@ -733,7 +830,7 @@ WebInspector.DOMNode.prototype = {
if (ownIndex > 0)
ownValue += "[" + ownIndex + "]";
- return new WebInspector.DOMNode.XPathStep(ownValue, this._nodeType === Node.DOCUMENT_NODE);
+ return new WebInspector.DOMNode.PathStep(ownValue, this._nodeType === Node.DOCUMENT_NODE);
},
/**

Powered by Google App Engine
This is Rietveld 408576698