OLD | NEW |
---|---|
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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 /** | 123 /** |
124 * @constructor | 124 * @constructor |
125 * @param {string} value | 125 * @param {string} value |
126 * @param {boolean} optimized | 126 * @param {boolean} optimized |
127 */ | 127 */ |
128 WebInspector.DOMNode.XPathStep = function(value, optimized) | 128 WebInspector.DOMNode.PathStep = function(value, optimized) |
129 { | 129 { |
130 this.value = value; | 130 this.value = value; |
131 this.optimized = optimized; | 131 this.optimized = optimized; |
132 } | 132 } |
133 | 133 |
134 WebInspector.DOMNode.XPathStep.prototype = { | 134 WebInspector.DOMNode.PathStep.prototype = { |
135 toString: function() | 135 toString: function() |
136 { | 136 { |
137 return this.value; | 137 return this.value; |
138 } | 138 } |
139 } | 139 } |
140 | 140 |
141 WebInspector.DOMNode.prototype = { | 141 WebInspector.DOMNode.prototype = { |
142 /** | 142 /** |
143 * @return {Array.<WebInspector.DOMNode>} | 143 * @return {Array.<WebInspector.DOMNode>} |
144 */ | 144 */ |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
423 { | 423 { |
424 if (!error) | 424 if (!error) |
425 InspectorFrontendHost.copyText(text); | 425 InspectorFrontendHost.copyText(text); |
426 } | 426 } |
427 DOMAgent.getOuterHTML(this.id, copy); | 427 DOMAgent.getOuterHTML(this.id, copy); |
428 }, | 428 }, |
429 | 429 |
430 /** | 430 /** |
431 * @param {boolean} optimized | 431 * @param {boolean} optimized |
432 */ | 432 */ |
433 copyCSSPath: function(optimized) | |
434 { | |
435 InspectorFrontendHost.copyText(this.cssPath(optimized)); | |
436 }, | |
437 | |
438 /** | |
439 * @param {boolean} optimized | |
440 */ | |
433 copyXPath: function(optimized) | 441 copyXPath: function(optimized) |
434 { | 442 { |
435 InspectorFrontendHost.copyText(this.xPath(optimized)); | 443 InspectorFrontendHost.copyText(this.xPath(optimized)); |
436 }, | 444 }, |
437 | 445 |
438 /** | 446 /** |
439 * @param {string} objectGroupId | 447 * @param {string} objectGroupId |
440 * @param {function(?Protocol.Error)=} callback | 448 * @param {function(?Protocol.Error)=} callback |
441 */ | 449 */ |
442 eventListeners: function(objectGroupId, callback) | 450 eventListeners: function(objectGroupId, callback) |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
678 */ | 686 */ |
679 isXMLNode: function() | 687 isXMLNode: function() |
680 { | 688 { |
681 return !!this.ownerDocument && !!this.ownerDocument.xmlVersion; | 689 return !!this.ownerDocument && !!this.ownerDocument.xmlVersion; |
682 }, | 690 }, |
683 | 691 |
684 /** | 692 /** |
685 * @param {boolean} optimized | 693 * @param {boolean} optimized |
686 * @return {string} | 694 * @return {string} |
687 */ | 695 */ |
696 cssPath: function(optimized) | |
697 { | |
698 if (this._nodeType !== Node.ELEMENT_NODE) | |
699 return ""; | |
700 | |
701 var steps = []; | |
702 var contextNode = this; | |
703 while (contextNode) { | |
704 var step = contextNode._cssPathValue(optimized); | |
705 if (!step) | |
706 break; // Error - bail out early. | |
707 steps.push(step); | |
708 if (step.optimized) | |
709 break; | |
710 contextNode = contextNode.parentNode; | |
711 } | |
712 | |
713 steps.reverse(); | |
714 return steps.join(" > "); | |
715 }, | |
716 | |
717 /** | |
718 * @param {boolean} optimized | |
719 * @return {WebInspector.DOMNode.PathStep} | |
720 */ | |
721 _cssPathValue: function(optimized) | |
722 { | |
723 if (this._nodeType !== Node.ELEMENT_NODE) | |
724 return null; | |
725 if (optimized) { | |
726 var id = this.getAttribute("id"); | |
727 if (id) | |
728 return new WebInspector.DOMNode.PathStep(idSelector(id), true); | |
729 var nodeNameLower = this._nodeName.toLowerCase(); | |
730 if (nodeNameLower === "body" || nodeNameLower === "head" || nodeName Lower === "html") | |
731 return new WebInspector.DOMNode.PathStep(this.nodeNameInCorrectC ase(), true); | |
732 } | |
733 var nodeName = this.nodeNameInCorrectCase(); | |
734 var parent = this.parentNode; | |
735 if (!parent || parent._nodeType === Node.DOCUMENT_NODE) | |
736 return new WebInspector.DOMNode.PathStep(nodeName, true); | |
737 | |
738 /** | |
739 * @param {WebInspector.DOMNode} node | |
740 * @return {Object.<string, boolean>} | |
741 */ | |
742 function elementClassNames(node) | |
743 { | |
744 var classAttribute = node.getAttribute("class"); | |
745 if (!classAttribute) | |
746 return {}; | |
747 | |
748 return classAttribute.split(/\s+/g).filter(Boolean).keySet(); | |
749 } | |
750 | |
751 /** | |
752 * @param {string} id | |
753 * @return {string} | |
754 */ | |
755 function idSelector(id) | |
756 { | |
757 if (/^[A-Za-z0-9_-]+$/.test(id)) | |
aandrey
2013/11/19 11:15:09
FYI.
document.querySelectorAll("#---")
===> Synta
| |
758 return "#" + id; | |
759 | |
760 var quoteChar = "\""; | |
761 var hasQuotes = /"/.test(id); | |
aandrey
2013/11/19 11:11:18
indexOf
| |
762 var hasApostrophes = /'/.test(id); | |
aandrey
2013/11/19 11:11:18
indexOf
| |
763 if (hasQuotes) { | |
764 if (!hasApostrophes) | |
765 quoteChar = "'"; | |
766 else | |
767 id = id.replace(/"/g, "\\\\\""); | |
aandrey
2013/11/19 11:11:18
this code path is not tested, and quite hard to re
| |
768 } | |
769 return "[id=" + quoteChar + id + quoteChar + "]"; | |
770 } | |
771 | |
772 var uniqueClassNames = elementClassNames(this); | |
773 var uniqueClassNamesLeft = 0; | |
774 for (var name in uniqueClassNames) | |
775 ++uniqueClassNamesLeft; | |
776 var needsClassNames = false; | |
777 var needsNthChild = false; | |
778 var ownIndex = -1; | |
779 var siblings = parent.children(); | |
780 for (var i = 0; (ownIndex === -1 || !needsNthChild) && i < siblings.leng th; ++i) { | |
781 var sibling = siblings[i]; | |
782 if (sibling === this) { | |
783 ownIndex = i; | |
784 continue; | |
785 } | |
786 if (sibling.nodeNameInCorrectCase() !== nodeName) | |
787 continue; | |
788 if (!uniqueClassNamesLeft) { | |
789 needsNthChild = true; | |
790 continue; | |
791 } | |
792 | |
793 needsClassNames = true; | |
794 var siblingClassNames = elementClassNames(sibling); | |
795 for (var siblingClass in siblingClassNames) { | |
796 if (!uniqueClassNames.hasOwnProperty(siblingClass)) | |
797 continue; | |
798 delete uniqueClassNames[siblingClass]; | |
799 if (!--uniqueClassNamesLeft) { | |
800 needsNthChild = true; | |
801 break; | |
802 } | |
803 } | |
804 } | |
805 | |
806 var result = nodeName; | |
807 if (needsClassNames && uniqueClassNamesLeft) { | |
808 for (var className in uniqueClassNames) | |
809 result += "." + className; | |
aandrey
2013/11/19 11:11:18
And what about className containing odd characters
| |
810 } | |
811 if (needsNthChild) | |
812 result += ":nth-child(" + (ownIndex + 1) + ")"; | |
813 return new WebInspector.DOMNode.PathStep(result, false); | |
814 }, | |
815 | |
816 /** | |
817 * @param {boolean} optimized | |
818 * @return {string} | |
819 */ | |
688 xPath: function(optimized) | 820 xPath: function(optimized) |
689 { | 821 { |
690 if (this._nodeType === Node.DOCUMENT_NODE) | 822 if (this._nodeType === Node.DOCUMENT_NODE) |
691 return "/"; | 823 return "/"; |
692 | 824 |
693 var steps = []; | 825 var steps = []; |
694 var contextNode = this; | 826 var contextNode = this; |
695 while (contextNode) { | 827 while (contextNode) { |
696 var step = contextNode._xPathValue(optimized); | 828 var step = contextNode._xPathValue(optimized); |
697 if (!step) | 829 if (!step) |
698 break; // Error - bail out early. | 830 break; // Error - bail out early. |
699 steps.push(step); | 831 steps.push(step); |
700 if (step.optimized) | 832 if (step.optimized) |
701 break; | 833 break; |
702 contextNode = contextNode.parentNode; | 834 contextNode = contextNode.parentNode; |
703 } | 835 } |
704 | 836 |
705 steps.reverse(); | 837 steps.reverse(); |
706 return (steps.length && steps[0].optimized ? "" : "/") + steps.join("/") ; | 838 return (steps.length && steps[0].optimized ? "" : "/") + steps.join("/") ; |
707 }, | 839 }, |
708 | 840 |
709 /** | 841 /** |
710 * @param {boolean} optimized | 842 * @param {boolean} optimized |
711 * @return {WebInspector.DOMNode.XPathStep} | 843 * @return {WebInspector.DOMNode.PathStep} |
712 */ | 844 */ |
713 _xPathValue: function(optimized) | 845 _xPathValue: function(optimized) |
714 { | 846 { |
715 var ownValue; | 847 var ownValue; |
716 var ownIndex = this._xPathIndex(); | 848 var ownIndex = this._xPathIndex(); |
717 if (ownIndex === -1) | 849 if (ownIndex === -1) |
718 return null; // Error. | 850 return null; // Error. |
719 | 851 |
720 switch (this._nodeType) { | 852 switch (this._nodeType) { |
721 case Node.ELEMENT_NODE: | 853 case Node.ELEMENT_NODE: |
722 if (optimized && this.getAttribute("id")) | 854 if (optimized && this.getAttribute("id")) |
723 return new WebInspector.DOMNode.XPathStep("//*[@id=\"" + this.ge tAttribute("id") + "\"]", true); | 855 return new WebInspector.DOMNode.PathStep("//*[@id=\"" + this.get Attribute("id") + "\"]", true); |
724 ownValue = this._localName; | 856 ownValue = this._localName; |
725 break; | 857 break; |
726 case Node.ATTRIBUTE_NODE: | 858 case Node.ATTRIBUTE_NODE: |
727 ownValue = "@" + this._nodeName; | 859 ownValue = "@" + this._nodeName; |
728 break; | 860 break; |
729 case Node.TEXT_NODE: | 861 case Node.TEXT_NODE: |
730 case Node.CDATA_SECTION_NODE: | 862 case Node.CDATA_SECTION_NODE: |
731 ownValue = "text()"; | 863 ownValue = "text()"; |
732 break; | 864 break; |
733 case Node.PROCESSING_INSTRUCTION_NODE: | 865 case Node.PROCESSING_INSTRUCTION_NODE: |
734 ownValue = "processing-instruction()"; | 866 ownValue = "processing-instruction()"; |
735 break; | 867 break; |
736 case Node.COMMENT_NODE: | 868 case Node.COMMENT_NODE: |
737 ownValue = "comment()"; | 869 ownValue = "comment()"; |
738 break; | 870 break; |
739 case Node.DOCUMENT_NODE: | 871 case Node.DOCUMENT_NODE: |
740 ownValue = ""; | 872 ownValue = ""; |
741 break; | 873 break; |
742 default: | 874 default: |
743 ownValue = ""; | 875 ownValue = ""; |
744 break; | 876 break; |
745 } | 877 } |
746 | 878 |
747 if (ownIndex > 0) | 879 if (ownIndex > 0) |
748 ownValue += "[" + ownIndex + "]"; | 880 ownValue += "[" + ownIndex + "]"; |
749 | 881 |
750 return new WebInspector.DOMNode.XPathStep(ownValue, this._nodeType === N ode.DOCUMENT_NODE); | 882 return new WebInspector.DOMNode.PathStep(ownValue, this._nodeType === No de.DOCUMENT_NODE); |
751 }, | 883 }, |
752 | 884 |
753 /** | 885 /** |
754 * @return {number} | 886 * @return {number} |
755 */ | 887 */ |
756 _xPathIndex: function() | 888 _xPathIndex: function() |
757 { | 889 { |
758 // 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. | 890 // 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. |
759 function areNodesSimilar(left, right) | 891 function areNodesSimilar(left, right) |
760 { | 892 { |
(...skipping 988 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1749 setInspectModeEnabled: function(enabled, inspectShadowDOM, config, callback) | 1881 setInspectModeEnabled: function(enabled, inspectShadowDOM, config, callback) |
1750 { | 1882 { |
1751 DOMAgent.setInspectModeEnabled(enabled, inspectShadowDOM, config, callba ck); | 1883 DOMAgent.setInspectModeEnabled(enabled, inspectShadowDOM, config, callba ck); |
1752 } | 1884 } |
1753 } | 1885 } |
1754 | 1886 |
1755 /** | 1887 /** |
1756 * @type {?WebInspector.DOMAgent} | 1888 * @type {?WebInspector.DOMAgent} |
1757 */ | 1889 */ |
1758 WebInspector.domAgent = null; | 1890 WebInspector.domAgent = null; |
OLD | NEW |