Chromium Code Reviews| 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 |