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

Side by Side 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: Tentatively fix xpath test on Windows bot 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2009, 2010 Google Inc. All rights reserved. 2 * Copyright (C) 2009, 2010 Google Inc. All rights reserved.
3 * Copyright (C) 2009 Joseph Pecoraro 3 * Copyright (C) 2009 Joseph Pecoraro
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are 6 * modification, are permitted provided that the following conditions are
7 * met: 7 * met:
8 * 8 *
9 * * Redistributions of source code must retain the above copyright 9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 WebInspector.DOMNode.PseudoElementNames = { 113 WebInspector.DOMNode.PseudoElementNames = {
114 Before: "before", 114 Before: "before",
115 After: "after" 115 After: "after"
116 } 116 }
117 117
118 WebInspector.DOMNode.ShadowRootTypes = { 118 WebInspector.DOMNode.ShadowRootTypes = {
119 UserAgent: "user-agent", 119 UserAgent: "user-agent",
120 Author: "author" 120 Author: "author"
121 } 121 }
122 122
123 /**
124 * @constructor
125 * @param {string} value
126 * @param {boolean} optimized
127 */
128 WebInspector.DOMNode.XPathStep = function(value, optimized)
129 {
130 this.value = value;
131 this.optimized = optimized;
132 }
133
134 WebInspector.DOMNode.XPathStep.prototype = {
135 toString: function()
136 {
137 return this.value;
138 }
139 }
140
141 WebInspector.DOMNode.prototype = { 123 WebInspector.DOMNode.prototype = {
142 /** 124 /**
143 * @return {Array.<WebInspector.DOMNode>} 125 * @return {Array.<WebInspector.DOMNode>}
144 */ 126 */
145 children: function() 127 children: function()
146 { 128 {
147 return this._children ? this._children.slice() : null; 129 return this._children ? this._children.slice() : null;
148 }, 130 },
149 131
150 /** 132 /**
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 { 403 {
422 function copy(error, text) 404 function copy(error, text)
423 { 405 {
424 if (!error) 406 if (!error)
425 InspectorFrontendHost.copyText(text); 407 InspectorFrontendHost.copyText(text);
426 } 408 }
427 DOMAgent.getOuterHTML(this.id, copy); 409 DOMAgent.getOuterHTML(this.id, copy);
428 }, 410 },
429 411
430 /** 412 /**
431 * @param {boolean} optimized
432 */
433 copyXPath: function(optimized)
434 {
435 InspectorFrontendHost.copyText(this.xPath(optimized));
436 },
437
438 /**
439 * @param {string} objectGroupId 413 * @param {string} objectGroupId
440 * @param {function(?Protocol.Error)=} callback 414 * @param {function(?Protocol.Error)=} callback
441 */ 415 */
442 eventListeners: function(objectGroupId, callback) 416 eventListeners: function(objectGroupId, callback)
443 { 417 {
444 DOMAgent.getEventListenersForNode(this.id, objectGroupId, callback); 418 DOMAgent.getEventListenersForNode(this.id, objectGroupId, callback);
445 }, 419 },
446 420
447 /** 421 /**
448 * @return {string} 422 * @return {string}
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 }, 622 },
649 623
650 /** 624 /**
651 * @return {boolean} 625 * @return {boolean}
652 */ 626 */
653 isXMLNode: function() 627 isXMLNode: function()
654 { 628 {
655 return !!this.ownerDocument && !!this.ownerDocument.xmlVersion; 629 return !!this.ownerDocument && !!this.ownerDocument.xmlVersion;
656 }, 630 },
657 631
658 /**
659 * @param {boolean} optimized
660 * @return {string}
661 */
662 xPath: function(optimized)
663 {
664 if (this._nodeType === Node.DOCUMENT_NODE)
665 return "/";
666
667 var steps = [];
668 var contextNode = this;
669 while (contextNode) {
670 var step = contextNode._xPathValue(optimized);
671 if (!step)
672 break; // Error - bail out early.
673 steps.push(step);
674 if (step.optimized)
675 break;
676 contextNode = contextNode.parentNode;
677 }
678
679 steps.reverse();
680 return (steps.length && steps[0].optimized ? "" : "/") + steps.join("/") ;
681 },
682
683 /**
684 * @param {boolean} optimized
685 * @return {WebInspector.DOMNode.XPathStep}
686 */
687 _xPathValue: function(optimized)
688 {
689 var ownValue;
690 var ownIndex = this._xPathIndex();
691 if (ownIndex === -1)
692 return null; // Error.
693
694 switch (this._nodeType) {
695 case Node.ELEMENT_NODE:
696 if (optimized && this.getAttribute("id"))
697 return new WebInspector.DOMNode.XPathStep("//*[@id=\"" + this.ge tAttribute("id") + "\"]", true);
698 ownValue = this._localName;
699 break;
700 case Node.ATTRIBUTE_NODE:
701 ownValue = "@" + this._nodeName;
702 break;
703 case Node.TEXT_NODE:
704 case Node.CDATA_SECTION_NODE:
705 ownValue = "text()";
706 break;
707 case Node.PROCESSING_INSTRUCTION_NODE:
708 ownValue = "processing-instruction()";
709 break;
710 case Node.COMMENT_NODE:
711 ownValue = "comment()";
712 break;
713 case Node.DOCUMENT_NODE:
714 ownValue = "";
715 break;
716 default:
717 ownValue = "";
718 break;
719 }
720
721 if (ownIndex > 0)
722 ownValue += "[" + ownIndex + "]";
723
724 return new WebInspector.DOMNode.XPathStep(ownValue, this._nodeType === N ode.DOCUMENT_NODE);
725 },
726
727 /**
728 * @return {number}
729 */
730 _xPathIndex: function()
731 {
732 // Returns -1 in case of error, 0 if no siblings matching the same expre ssion, <XPath index among the same expression-matching sibling nodes> otherwise.
733 function areNodesSimilar(left, right)
734 {
735 if (left === right)
736 return true;
737
738 if (left._nodeType === Node.ELEMENT_NODE && right._nodeType === Node .ELEMENT_NODE)
739 return left._localName === right._localName;
740
741 if (left._nodeType === right._nodeType)
742 return true;
743
744 // XPath treats CDATA as text nodes.
745 var leftType = left._nodeType === Node.CDATA_SECTION_NODE ? Node.TEX T_NODE : left._nodeType;
746 var rightType = right._nodeType === Node.CDATA_SECTION_NODE ? Node.T EXT_NODE : right._nodeType;
747 return leftType === rightType;
748 }
749
750 var siblings = this.parentNode ? this.parentNode._children : null;
751 if (!siblings)
752 return 0; // Root node - no siblings.
753 var hasSameNamedElements;
754 for (var i = 0; i < siblings.length; ++i) {
755 if (areNodesSimilar(this, siblings[i]) && siblings[i] !== this) {
756 hasSameNamedElements = true;
757 break;
758 }
759 }
760 if (!hasSameNamedElements)
761 return 0;
762 var ownIndex = 1; // XPath indices start with 1.
763 for (var i = 0; i < siblings.length; ++i) {
764 if (areNodesSimilar(this, siblings[i])) {
765 if (siblings[i] === this)
766 return ownIndex;
767 ++ownIndex;
768 }
769 }
770 return -1; // An error occurred: |this| not found in parent's children.
771 },
772
773 _updateChildUserPropertyCountsOnRemoval: function(parentNode) 632 _updateChildUserPropertyCountsOnRemoval: function(parentNode)
774 { 633 {
775 var result = {}; 634 var result = {};
776 if (this._userProperties) { 635 if (this._userProperties) {
777 for (var name in this._userProperties) 636 for (var name in this._userProperties)
778 result[name] = (result[name] || 0) + 1; 637 result[name] = (result[name] || 0) + 1;
779 } 638 }
780 639
781 if (this._descendantUserPropertyCounters) { 640 if (this._descendantUserPropertyCounters) {
782 for (var name in this._descendantUserPropertyCounters) { 641 for (var name in this._descendantUserPropertyCounters) {
(...skipping 940 matching lines...) Expand 10 before | Expand all | Expand 10 after
1723 setInspectModeEnabled: function(enabled, inspectShadowDOM, config, callback) 1582 setInspectModeEnabled: function(enabled, inspectShadowDOM, config, callback)
1724 { 1583 {
1725 DOMAgent.setInspectModeEnabled(enabled, inspectShadowDOM, config, callba ck); 1584 DOMAgent.setInspectModeEnabled(enabled, inspectShadowDOM, config, callba ck);
1726 } 1585 }
1727 } 1586 }
1728 1587
1729 /** 1588 /**
1730 * @type {?WebInspector.DOMAgent} 1589 * @type {?WebInspector.DOMAgent}
1731 */ 1590 */
1732 WebInspector.domAgent = null; 1591 WebInspector.domAgent = null;
OLDNEW
« no previous file with comments | « LayoutTests/inspector/elements/node-xpath-expected.txt ('k') | Source/devtools/front_end/DOMPresentationUtils.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698