| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
| 3 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. | 3 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. |
| 4 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> | 4 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> |
| 5 * Copyright (C) 2009 Joseph Pecoraro | 5 * Copyright (C) 2009 Joseph Pecoraro |
| 6 * | 6 * |
| 7 * Redistribution and use in source and binary forms, with or without | 7 * Redistribution and use in source and binary forms, with or without |
| 8 * modification, are permitted provided that the following conditions | 8 * modification, are permitted provided that the following conditions |
| 9 * are met: | 9 * are met: |
| 10 * | 10 * |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 23 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | 23 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
| 24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 */ | 30 */ |
| 31 | |
| 32 WebInspector.DOMPresentationUtils = {}; | 31 WebInspector.DOMPresentationUtils = {}; |
| 33 | 32 |
| 34 /** | 33 /** |
| 35 * @param {!WebInspector.DOMNode} node | 34 * @param {!WebInspector.DOMNode} node |
| 36 * @param {!Element} parentElement | 35 * @param {!Element} parentElement |
| 37 */ | 36 */ |
| 38 WebInspector.DOMPresentationUtils.decorateNodeLabel = function(node, parentEleme
nt) | 37 WebInspector.DOMPresentationUtils.decorateNodeLabel = function(node, parentEleme
nt) { |
| 39 { | 38 var originalNode = node; |
| 40 var originalNode = node; | 39 var isPseudo = node.nodeType() === Node.ELEMENT_NODE && node.pseudoType(); |
| 41 var isPseudo = node.nodeType() === Node.ELEMENT_NODE && node.pseudoType(); | 40 if (isPseudo && node.parentNode) |
| 42 if (isPseudo && node.parentNode) | 41 node = node.parentNode; |
| 43 node = node.parentNode; | |
| 44 | 42 |
| 45 var title = node.nodeNameInCorrectCase(); | 43 var title = node.nodeNameInCorrectCase(); |
| 46 | 44 |
| 47 var nameElement = parentElement.createChild("span", "node-label-name"); | 45 var nameElement = parentElement.createChild('span', 'node-label-name'); |
| 48 nameElement.textContent = title; | 46 nameElement.textContent = title; |
| 49 | 47 |
| 50 var idAttribute = node.getAttribute("id"); | 48 var idAttribute = node.getAttribute('id'); |
| 51 if (idAttribute) { | 49 if (idAttribute) { |
| 52 var idElement = parentElement.createChild("span", "node-label-id"); | 50 var idElement = parentElement.createChild('span', 'node-label-id'); |
| 53 var part = "#" + idAttribute; | 51 var part = '#' + idAttribute; |
| 54 title += part; | 52 title += part; |
| 55 idElement.createTextChild(part); | 53 idElement.createTextChild(part); |
| 56 | 54 |
| 57 // Mark the name as extra, since the ID is more important. | 55 // Mark the name as extra, since the ID is more important. |
| 58 nameElement.classList.add("extra"); | 56 nameElement.classList.add('extra'); |
| 57 } |
| 58 |
| 59 var classAttribute = node.getAttribute('class'); |
| 60 if (classAttribute) { |
| 61 var classes = classAttribute.split(/\s+/); |
| 62 var foundClasses = {}; |
| 63 |
| 64 if (classes.length) { |
| 65 var classesElement = parentElement.createChild('span', 'extra node-label-c
lass'); |
| 66 for (var i = 0; i < classes.length; ++i) { |
| 67 var className = classes[i]; |
| 68 if (className && !(className in foundClasses)) { |
| 69 var part = '.' + className; |
| 70 title += part; |
| 71 classesElement.createTextChild(part); |
| 72 foundClasses[className] = true; |
| 73 } |
| 74 } |
| 59 } | 75 } |
| 76 } |
| 60 | 77 |
| 61 var classAttribute = node.getAttribute("class"); | 78 if (isPseudo) { |
| 62 if (classAttribute) { | 79 var pseudoElement = parentElement.createChild('span', 'extra node-label-pseu
do'); |
| 63 var classes = classAttribute.split(/\s+/); | 80 var pseudoText = '::' + originalNode.pseudoType(); |
| 64 var foundClasses = {}; | 81 pseudoElement.createTextChild(pseudoText); |
| 65 | 82 title += pseudoText; |
| 66 if (classes.length) { | 83 } |
| 67 var classesElement = parentElement.createChild("span", "extra node-l
abel-class"); | 84 parentElement.title = title; |
| 68 for (var i = 0; i < classes.length; ++i) { | |
| 69 var className = classes[i]; | |
| 70 if (className && !(className in foundClasses)) { | |
| 71 var part = "." + className; | |
| 72 title += part; | |
| 73 classesElement.createTextChild(part); | |
| 74 foundClasses[className] = true; | |
| 75 } | |
| 76 } | |
| 77 } | |
| 78 } | |
| 79 | |
| 80 if (isPseudo) { | |
| 81 var pseudoElement = parentElement.createChild("span", "extra node-label-
pseudo"); | |
| 82 var pseudoText = "::" + originalNode.pseudoType(); | |
| 83 pseudoElement.createTextChild(pseudoText); | |
| 84 title += pseudoText; | |
| 85 } | |
| 86 parentElement.title = title; | |
| 87 }; | 85 }; |
| 88 | 86 |
| 89 /** | 87 /** |
| 90 * @param {!Element} container | 88 * @param {!Element} container |
| 91 * @param {string} nodeTitle | 89 * @param {string} nodeTitle |
| 92 */ | 90 */ |
| 93 WebInspector.DOMPresentationUtils.createSpansForNodeTitle = function(container,
nodeTitle) | 91 WebInspector.DOMPresentationUtils.createSpansForNodeTitle = function(container,
nodeTitle) { |
| 94 { | 92 var match = nodeTitle.match(/([^#.]+)(#[^.]+)?(\..*)?/); |
| 95 var match = nodeTitle.match(/([^#.]+)(#[^.]+)?(\..*)?/); | 93 container.createChild('span', 'webkit-html-tag-name').textContent = match[1]; |
| 96 container.createChild("span", "webkit-html-tag-name").textContent = match[1]
; | 94 if (match[2]) |
| 97 if (match[2]) | 95 container.createChild('span', 'webkit-html-attribute-value').textContent = m
atch[2]; |
| 98 container.createChild("span", "webkit-html-attribute-value").textContent
= match[2]; | 96 if (match[3]) |
| 99 if (match[3]) | 97 container.createChild('span', 'webkit-html-attribute-name').textContent = ma
tch[3]; |
| 100 container.createChild("span", "webkit-html-attribute-name").textContent
= match[3]; | |
| 101 }; | 98 }; |
| 102 | 99 |
| 103 /** | 100 /** |
| 104 * @param {?WebInspector.DOMNode} node | 101 * @param {?WebInspector.DOMNode} node |
| 105 * @param {string=} idref | 102 * @param {string=} idref |
| 106 * @return {!Node} | 103 * @return {!Node} |
| 107 */ | 104 */ |
| 108 WebInspector.DOMPresentationUtils.linkifyNodeReference = function(node, idref) | 105 WebInspector.DOMPresentationUtils.linkifyNodeReference = function(node, idref) { |
| 109 { | 106 if (!node) |
| 110 if (!node) | 107 return createTextNode(WebInspector.UIString('<node>')); |
| 111 return createTextNode(WebInspector.UIString("<node>")); | |
| 112 | 108 |
| 113 var root = createElementWithClass("span", "monospace"); | 109 var root = createElementWithClass('span', 'monospace'); |
| 114 var shadowRoot = WebInspector.createShadowRootWithCoreStyles(root, "componen
ts/domUtils.css"); | 110 var shadowRoot = WebInspector.createShadowRootWithCoreStyles(root, 'components
/domUtils.css'); |
| 115 var link = shadowRoot.createChild("div", "node-link"); | 111 var link = shadowRoot.createChild('div', 'node-link'); |
| 116 | 112 |
| 117 if (idref) | 113 if (idref) |
| 118 link.createChild("span", "node-label-id").createTextChild("#" + idref); | 114 link.createChild('span', 'node-label-id').createTextChild('#' + idref); |
| 119 else | 115 else |
| 120 WebInspector.DOMPresentationUtils.decorateNodeLabel(node, link); | 116 WebInspector.DOMPresentationUtils.decorateNodeLabel(node, link); |
| 121 | 117 |
| 122 link.addEventListener("click", WebInspector.Revealer.reveal.bind(WebInspecto
r.Revealer, node, undefined), false); | 118 link.addEventListener('click', WebInspector.Revealer.reveal.bind(WebInspector.
Revealer, node, undefined), false); |
| 123 link.addEventListener("mouseover", node.highlight.bind(node, undefined, unde
fined), false); | 119 link.addEventListener('mouseover', node.highlight.bind(node, undefined, undefi
ned), false); |
| 124 link.addEventListener("mouseleave", WebInspector.DOMModel.hideDOMNodeHighlig
ht.bind(WebInspector.DOMModel), false); | 120 link.addEventListener('mouseleave', WebInspector.DOMModel.hideDOMNodeHighlight
.bind(WebInspector.DOMModel), false); |
| 125 | 121 |
| 126 return root; | 122 return root; |
| 127 }; | 123 }; |
| 128 | 124 |
| 129 /** | 125 /** |
| 130 * @param {!WebInspector.DeferredDOMNode} deferredNode | 126 * @param {!WebInspector.DeferredDOMNode} deferredNode |
| 131 * @return {!Node} | 127 * @return {!Node} |
| 132 */ | 128 */ |
| 133 WebInspector.DOMPresentationUtils.linkifyDeferredNodeReference = function(deferr
edNode) | 129 WebInspector.DOMPresentationUtils.linkifyDeferredNodeReference = function(deferr
edNode) { |
| 134 { | 130 var root = createElement('div'); |
| 135 var root = createElement("div"); | 131 var shadowRoot = WebInspector.createShadowRootWithCoreStyles(root, 'components
/domUtils.css'); |
| 136 var shadowRoot = WebInspector.createShadowRootWithCoreStyles(root, "componen
ts/domUtils.css"); | 132 var link = shadowRoot.createChild('div', 'node-link'); |
| 137 var link = shadowRoot.createChild("div", "node-link"); | 133 link.createChild('content'); |
| 138 link.createChild("content"); | 134 link.addEventListener('click', deferredNode.resolve.bind(deferredNode, onDefer
redNodeResolved), false); |
| 139 link.addEventListener("click", deferredNode.resolve.bind(deferredNode, onDef
erredNodeResolved), false); | 135 link.addEventListener('mousedown', (e) => e.consume(), false); |
| 140 link.addEventListener("mousedown", (e) => e.consume(), false); | |
| 141 | 136 |
| 142 /** | 137 /** |
| 143 * @param {?WebInspector.DOMNode} node | 138 * @param {?WebInspector.DOMNode} node |
| 144 */ | 139 */ |
| 145 function onDeferredNodeResolved(node) | 140 function onDeferredNodeResolved(node) { |
| 146 { | 141 WebInspector.Revealer.reveal(node); |
| 147 WebInspector.Revealer.reveal(node); | 142 } |
| 148 } | |
| 149 | 143 |
| 150 return root; | 144 return root; |
| 151 }; | 145 }; |
| 152 | 146 |
| 153 /** | 147 /** |
| 154 * @param {!WebInspector.Target} target | 148 * @param {!WebInspector.Target} target |
| 155 * @param {string} originalImageURL | 149 * @param {string} originalImageURL |
| 156 * @param {boolean} showDimensions | 150 * @param {boolean} showDimensions |
| 157 * @param {function(!Element=)} userCallback | 151 * @param {function(!Element=)} userCallback |
| 158 * @param {!Object=} precomputedFeatures | 152 * @param {!Object=} precomputedFeatures |
| 159 */ | 153 */ |
| 160 WebInspector.DOMPresentationUtils.buildImagePreviewContents = function(target, o
riginalImageURL, showDimensions, userCallback, precomputedFeatures) | 154 WebInspector.DOMPresentationUtils.buildImagePreviewContents = function( |
| 161 { | 155 target, originalImageURL, showDimensions, userCallback, precomputedFeatures)
{ |
| 162 var resourceTreeModel = WebInspector.ResourceTreeModel.fromTarget(target); | 156 var resourceTreeModel = WebInspector.ResourceTreeModel.fromTarget(target); |
| 163 if (!resourceTreeModel) { | 157 if (!resourceTreeModel) { |
| 164 userCallback(); | 158 userCallback(); |
| 165 return; | 159 return; |
| 166 } | 160 } |
| 167 var resource = resourceTreeModel.resourceForURL(originalImageURL); | 161 var resource = resourceTreeModel.resourceForURL(originalImageURL); |
| 168 var imageURL = originalImageURL; | 162 var imageURL = originalImageURL; |
| 169 if (!isImageResource(resource) && precomputedFeatures && precomputedFeatures
.currentSrc) { | 163 if (!isImageResource(resource) && precomputedFeatures && precomputedFeatures.c
urrentSrc) { |
| 170 imageURL = precomputedFeatures.currentSrc; | 164 imageURL = precomputedFeatures.currentSrc; |
| 171 resource = resourceTreeModel.resourceForURL(imageURL); | 165 resource = resourceTreeModel.resourceForURL(imageURL); |
| 172 } | 166 } |
| 173 if (!isImageResource(resource)) { | 167 if (!isImageResource(resource)) { |
| 174 userCallback(); | 168 userCallback(); |
| 175 return; | 169 return; |
| 170 } |
| 171 |
| 172 var imageElement = createElement('img'); |
| 173 imageElement.addEventListener('load', buildContent, false); |
| 174 imageElement.addEventListener('error', errorCallback, false); |
| 175 resource.populateImageSource(imageElement); |
| 176 |
| 177 function errorCallback() { |
| 178 // Drop the event parameter when invoking userCallback. |
| 179 userCallback(); |
| 180 } |
| 181 |
| 182 /** |
| 183 * @param {?WebInspector.Resource} resource |
| 184 * @return {boolean} |
| 185 */ |
| 186 function isImageResource(resource) { |
| 187 return !!resource && resource.resourceType() === WebInspector.resourceTypes.
Image; |
| 188 } |
| 189 |
| 190 function buildContent() { |
| 191 var container = createElement('table'); |
| 192 container.className = 'image-preview-container'; |
| 193 var naturalWidth = precomputedFeatures ? precomputedFeatures.naturalWidth :
imageElement.naturalWidth; |
| 194 var naturalHeight = precomputedFeatures ? precomputedFeatures.naturalHeight
: imageElement.naturalHeight; |
| 195 var offsetWidth = precomputedFeatures ? precomputedFeatures.offsetWidth : na
turalWidth; |
| 196 var offsetHeight = precomputedFeatures ? precomputedFeatures.offsetHeight :
naturalHeight; |
| 197 var description; |
| 198 if (showDimensions) { |
| 199 if (offsetHeight === naturalHeight && offsetWidth === naturalWidth) |
| 200 description = WebInspector.UIString('%d \xd7 %d pixels', offsetWidth, of
fsetHeight); |
| 201 else |
| 202 description = WebInspector.UIString( |
| 203 '%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)', offsetWidth, offse
tHeight, naturalWidth, naturalHeight); |
| 176 } | 204 } |
| 177 | 205 |
| 178 var imageElement = createElement("img"); | 206 container.createChild('tr').createChild('td', 'image-container').appendChild
(imageElement); |
| 179 imageElement.addEventListener("load", buildContent, false); | 207 if (description) |
| 180 imageElement.addEventListener("error", errorCallback, false); | 208 container.createChild('tr').createChild('td').createChild('span', 'descrip
tion').textContent = description; |
| 181 resource.populateImageSource(imageElement); | 209 if (imageURL !== originalImageURL) |
| 182 | 210 container.createChild('tr').createChild('td').createChild('span', 'descrip
tion').textContent = |
| 183 function errorCallback() | 211 String.sprintf('currentSrc: %s', imageURL.trimMiddle(100)); |
| 184 { | 212 userCallback(container); |
| 185 // Drop the event parameter when invoking userCallback. | 213 } |
| 186 userCallback(); | |
| 187 } | |
| 188 | |
| 189 /** | |
| 190 * @param {?WebInspector.Resource} resource | |
| 191 * @return {boolean} | |
| 192 */ | |
| 193 function isImageResource(resource) | |
| 194 { | |
| 195 return !!resource && resource.resourceType() === WebInspector.resourceTy
pes.Image; | |
| 196 } | |
| 197 | |
| 198 function buildContent() | |
| 199 { | |
| 200 var container = createElement("table"); | |
| 201 container.className = "image-preview-container"; | |
| 202 var naturalWidth = precomputedFeatures ? precomputedFeatures.naturalWidt
h : imageElement.naturalWidth; | |
| 203 var naturalHeight = precomputedFeatures ? precomputedFeatures.naturalHei
ght : imageElement.naturalHeight; | |
| 204 var offsetWidth = precomputedFeatures ? precomputedFeatures.offsetWidth
: naturalWidth; | |
| 205 var offsetHeight = precomputedFeatures ? precomputedFeatures.offsetHeigh
t : naturalHeight; | |
| 206 var description; | |
| 207 if (showDimensions) { | |
| 208 if (offsetHeight === naturalHeight && offsetWidth === naturalWidth) | |
| 209 description = WebInspector.UIString("%d \xd7 %d pixels", offsetW
idth, offsetHeight); | |
| 210 else | |
| 211 description = WebInspector.UIString("%d \xd7 %d pixels (Natural:
%d \xd7 %d pixels)", offsetWidth, offsetHeight, naturalWidth, naturalHeight); | |
| 212 } | |
| 213 | |
| 214 container.createChild("tr").createChild("td", "image-container").appendC
hild(imageElement); | |
| 215 if (description) | |
| 216 container.createChild("tr").createChild("td").createChild("span", "d
escription").textContent = description; | |
| 217 if (imageURL !== originalImageURL) | |
| 218 container.createChild("tr").createChild("td").createChild("span", "d
escription").textContent = String.sprintf("currentSrc: %s", imageURL.trimMiddle(
100)); | |
| 219 userCallback(container); | |
| 220 } | |
| 221 }; | 214 }; |
| 222 | 215 |
| 223 /** | 216 /** |
| 224 * @param {!WebInspector.Target} target | 217 * @param {!WebInspector.Target} target |
| 225 * @param {!WebInspector.Linkifier} linkifier | 218 * @param {!WebInspector.Linkifier} linkifier |
| 226 * @param {!RuntimeAgent.StackTrace=} stackTrace | 219 * @param {!RuntimeAgent.StackTrace=} stackTrace |
| 227 * @return {!Element} | 220 * @return {!Element} |
| 228 */ | 221 */ |
| 229 WebInspector.DOMPresentationUtils.buildStackTracePreviewContents = function(targ
et, linkifier, stackTrace) | 222 WebInspector.DOMPresentationUtils.buildStackTracePreviewContents = function(targ
et, linkifier, stackTrace) { |
| 230 { | 223 var element = createElement('span'); |
| 231 var element = createElement("span"); | 224 element.style.display = 'inline-block'; |
| 232 element.style.display = "inline-block"; | 225 var shadowRoot = WebInspector.createShadowRootWithCoreStyles(element, 'compone
nts/domUtils.css'); |
| 233 var shadowRoot = WebInspector.createShadowRootWithCoreStyles(element, "compo
nents/domUtils.css"); | 226 var contentElement = shadowRoot.createChild('table', 'stack-preview-container'
); |
| 234 var contentElement = shadowRoot.createChild("table", "stack-preview-containe
r"); | |
| 235 | 227 |
| 236 /** | 228 /** |
| 237 * @param {!RuntimeAgent.StackTrace} stackTrace | 229 * @param {!RuntimeAgent.StackTrace} stackTrace |
| 238 */ | 230 */ |
| 239 function appendStackTrace(stackTrace) | 231 function appendStackTrace(stackTrace) { |
| 240 { | 232 for (var stackFrame of stackTrace.callFrames) { |
| 241 for (var stackFrame of stackTrace.callFrames) { | 233 var row = createElement('tr'); |
| 242 var row = createElement("tr"); | 234 row.createChild('td').textContent = '\n'; |
| 243 row.createChild("td").textContent = "\n"; | 235 row.createChild('td', 'function-name').textContent = WebInspector.beautify
FunctionName(stackFrame.functionName); |
| 244 row.createChild("td", "function-name").textContent = WebInspector.be
autifyFunctionName(stackFrame.functionName); | 236 var link = linkifier.maybeLinkifyConsoleCallFrame(target, stackFrame); |
| 245 var link = linkifier.maybeLinkifyConsoleCallFrame(target, stackFrame
); | 237 if (link) { |
| 246 if (link) { | 238 row.createChild('td').textContent = ' @ '; |
| 247 row.createChild("td").textContent = " @ "; | 239 row.createChild('td').appendChild(link); |
| 248 row.createChild("td").appendChild(link); | 240 } |
| 249 } | 241 contentElement.appendChild(row); |
| 250 contentElement.appendChild(row); | |
| 251 } | |
| 252 } | 242 } |
| 243 } |
| 253 | 244 |
| 254 if (!stackTrace) | 245 if (!stackTrace) |
| 255 return element; | 246 return element; |
| 256 | 247 |
| 257 appendStackTrace(stackTrace); | 248 appendStackTrace(stackTrace); |
| 258 | 249 |
| 259 var asyncStackTrace = stackTrace.parent; | 250 var asyncStackTrace = stackTrace.parent; |
| 260 while (asyncStackTrace) { | 251 while (asyncStackTrace) { |
| 261 if (!asyncStackTrace.callFrames.length) { | 252 if (!asyncStackTrace.callFrames.length) { |
| 262 asyncStackTrace = asyncStackTrace.parent; | 253 asyncStackTrace = asyncStackTrace.parent; |
| 263 continue; | 254 continue; |
| 264 } | |
| 265 var row = contentElement.createChild("tr"); | |
| 266 row.createChild("td").textContent = "\n"; | |
| 267 row.createChild("td", "stack-preview-async-description").textContent = W
ebInspector.asyncStackTraceLabel(asyncStackTrace.description); | |
| 268 row.createChild("td"); | |
| 269 row.createChild("td"); | |
| 270 appendStackTrace(asyncStackTrace); | |
| 271 asyncStackTrace = asyncStackTrace.parent; | |
| 272 } | 255 } |
| 256 var row = contentElement.createChild('tr'); |
| 257 row.createChild('td').textContent = '\n'; |
| 258 row.createChild('td', 'stack-preview-async-description').textContent = |
| 259 WebInspector.asyncStackTraceLabel(asyncStackTrace.description); |
| 260 row.createChild('td'); |
| 261 row.createChild('td'); |
| 262 appendStackTrace(asyncStackTrace); |
| 263 asyncStackTrace = asyncStackTrace.parent; |
| 264 } |
| 273 | 265 |
| 274 return element; | 266 return element; |
| 275 }; | 267 }; |
| 276 | 268 |
| 277 /** | 269 /** |
| 278 * @param {!WebInspector.DOMNode} node | 270 * @param {!WebInspector.DOMNode} node |
| 279 * @param {boolean=} justSelector | 271 * @param {boolean=} justSelector |
| 280 * @return {string} | 272 * @return {string} |
| 281 */ | 273 */ |
| 282 WebInspector.DOMPresentationUtils.fullQualifiedSelector = function(node, justSel
ector) | 274 WebInspector.DOMPresentationUtils.fullQualifiedSelector = function(node, justSel
ector) { |
| 283 { | 275 if (node.nodeType() !== Node.ELEMENT_NODE) |
| 284 if (node.nodeType() !== Node.ELEMENT_NODE) | 276 return node.localName() || node.nodeName().toLowerCase(); |
| 285 return node.localName() || node.nodeName().toLowerCase(); | 277 return WebInspector.DOMPresentationUtils.cssPath(node, justSelector); |
| 286 return WebInspector.DOMPresentationUtils.cssPath(node, justSelector); | |
| 287 }; | 278 }; |
| 288 | 279 |
| 289 /** | 280 /** |
| 290 * @param {!WebInspector.DOMNode} node | 281 * @param {!WebInspector.DOMNode} node |
| 291 * @return {string} | 282 * @return {string} |
| 292 */ | 283 */ |
| 293 WebInspector.DOMPresentationUtils.simpleSelector = function(node) | 284 WebInspector.DOMPresentationUtils.simpleSelector = function(node) { |
| 294 { | 285 var lowerCaseName = node.localName() || node.nodeName().toLowerCase(); |
| 295 var lowerCaseName = node.localName() || node.nodeName().toLowerCase(); | 286 if (node.nodeType() !== Node.ELEMENT_NODE) |
| 296 if (node.nodeType() !== Node.ELEMENT_NODE) | |
| 297 return lowerCaseName; | |
| 298 if (lowerCaseName === "input" && node.getAttribute("type") && !node.getAttri
bute("id") && !node.getAttribute("class")) | |
| 299 return lowerCaseName + "[type=\"" + node.getAttribute("type") + "\"]"; | |
| 300 if (node.getAttribute("id")) | |
| 301 return lowerCaseName + "#" + node.getAttribute("id"); | |
| 302 if (node.getAttribute("class")) | |
| 303 return (lowerCaseName === "div" ? "" : lowerCaseName) + "." + node.getAt
tribute("class").trim().replace(/\s+/g, "."); | |
| 304 return lowerCaseName; | 287 return lowerCaseName; |
| 288 if (lowerCaseName === 'input' && node.getAttribute('type') && !node.getAttribu
te('id') && !node.getAttribute('class')) |
| 289 return lowerCaseName + '[type="' + node.getAttribute('type') + '"]'; |
| 290 if (node.getAttribute('id')) |
| 291 return lowerCaseName + '#' + node.getAttribute('id'); |
| 292 if (node.getAttribute('class')) |
| 293 return (lowerCaseName === 'div' ? '' : lowerCaseName) + '.' + |
| 294 node.getAttribute('class').trim().replace(/\s+/g, '.'); |
| 295 return lowerCaseName; |
| 305 }; | 296 }; |
| 306 | 297 |
| 307 /** | 298 /** |
| 308 * @param {!WebInspector.DOMNode} node | 299 * @param {!WebInspector.DOMNode} node |
| 309 * @param {boolean=} optimized | 300 * @param {boolean=} optimized |
| 310 * @return {string} | 301 * @return {string} |
| 311 */ | 302 */ |
| 312 WebInspector.DOMPresentationUtils.cssPath = function(node, optimized) | 303 WebInspector.DOMPresentationUtils.cssPath = function(node, optimized) { |
| 313 { | 304 if (node.nodeType() !== Node.ELEMENT_NODE) |
| 314 if (node.nodeType() !== Node.ELEMENT_NODE) | 305 return ''; |
| 315 return ""; | |
| 316 | 306 |
| 317 var steps = []; | 307 var steps = []; |
| 318 var contextNode = node; | 308 var contextNode = node; |
| 319 while (contextNode) { | 309 while (contextNode) { |
| 320 var step = WebInspector.DOMPresentationUtils._cssPathStep(contextNode, !
!optimized, contextNode === node); | 310 var step = WebInspector.DOMPresentationUtils._cssPathStep(contextNode, !!opt
imized, contextNode === node); |
| 321 if (!step) | 311 if (!step) |
| 322 break; // Error - bail out early. | 312 break; // Error - bail out early. |
| 323 steps.push(step); | 313 steps.push(step); |
| 324 if (step.optimized) | 314 if (step.optimized) |
| 325 break; | 315 break; |
| 326 contextNode = contextNode.parentNode; | 316 contextNode = contextNode.parentNode; |
| 327 } | 317 } |
| 328 | 318 |
| 329 steps.reverse(); | 319 steps.reverse(); |
| 330 return steps.join(" > "); | 320 return steps.join(' > '); |
| 331 }; | 321 }; |
| 332 | 322 |
| 333 /** | 323 /** |
| 334 * @param {!WebInspector.DOMNode} node | 324 * @param {!WebInspector.DOMNode} node |
| 335 * @param {boolean} optimized | 325 * @param {boolean} optimized |
| 336 * @param {boolean} isTargetNode | 326 * @param {boolean} isTargetNode |
| 337 * @return {?WebInspector.DOMNodePathStep} | 327 * @return {?WebInspector.DOMNodePathStep} |
| 338 */ | 328 */ |
| 339 WebInspector.DOMPresentationUtils._cssPathStep = function(node, optimized, isTar
getNode) | 329 WebInspector.DOMPresentationUtils._cssPathStep = function(node, optimized, isTar
getNode) { |
| 340 { | 330 if (node.nodeType() !== Node.ELEMENT_NODE) |
| 341 if (node.nodeType() !== Node.ELEMENT_NODE) | 331 return null; |
| 342 return null; | |
| 343 | 332 |
| 344 var id = node.getAttribute("id"); | 333 var id = node.getAttribute('id'); |
| 345 if (optimized) { | 334 if (optimized) { |
| 346 if (id) | 335 if (id) |
| 347 return new WebInspector.DOMNodePathStep(idSelector(id), true); | 336 return new WebInspector.DOMNodePathStep(idSelector(id), true); |
| 348 var nodeNameLower = node.nodeName().toLowerCase(); | 337 var nodeNameLower = node.nodeName().toLowerCase(); |
| 349 if (nodeNameLower === "body" || nodeNameLower === "head" || nodeNameLowe
r === "html") | 338 if (nodeNameLower === 'body' || nodeNameLower === 'head' || nodeNameLower ==
= 'html') |
| 350 return new WebInspector.DOMNodePathStep(node.nodeNameInCorrectCase()
, true); | 339 return new WebInspector.DOMNodePathStep(node.nodeNameInCorrectCase(), true
); |
| 340 } |
| 341 var nodeName = node.nodeNameInCorrectCase(); |
| 342 |
| 343 if (id) |
| 344 return new WebInspector.DOMNodePathStep(nodeName + idSelector(id), true); |
| 345 var parent = node.parentNode; |
| 346 if (!parent || parent.nodeType() === Node.DOCUMENT_NODE) |
| 347 return new WebInspector.DOMNodePathStep(nodeName, true); |
| 348 |
| 349 /** |
| 350 * @param {!WebInspector.DOMNode} node |
| 351 * @return {!Array.<string>} |
| 352 */ |
| 353 function prefixedElementClassNames(node) { |
| 354 var classAttribute = node.getAttribute('class'); |
| 355 if (!classAttribute) |
| 356 return []; |
| 357 |
| 358 return classAttribute.split(/\s+/g).filter(Boolean).map(function(name) { |
| 359 // The prefix is required to store "__proto__" in a object-based map. |
| 360 return '$' + name; |
| 361 }); |
| 362 } |
| 363 |
| 364 /** |
| 365 * @param {string} id |
| 366 * @return {string} |
| 367 */ |
| 368 function idSelector(id) { |
| 369 return '#' + escapeIdentifierIfNeeded(id); |
| 370 } |
| 371 |
| 372 /** |
| 373 * @param {string} ident |
| 374 * @return {string} |
| 375 */ |
| 376 function escapeIdentifierIfNeeded(ident) { |
| 377 if (isCSSIdentifier(ident)) |
| 378 return ident; |
| 379 var shouldEscapeFirst = /^(?:[0-9]|-[0-9-]?)/.test(ident); |
| 380 var lastIndex = ident.length - 1; |
| 381 return ident.replace(/./g, function(c, i) { |
| 382 return ((shouldEscapeFirst && i === 0) || !isCSSIdentChar(c)) ? escapeAsci
iChar(c, i === lastIndex) : c; |
| 383 }); |
| 384 } |
| 385 |
| 386 /** |
| 387 * @param {string} c |
| 388 * @param {boolean} isLast |
| 389 * @return {string} |
| 390 */ |
| 391 function escapeAsciiChar(c, isLast) { |
| 392 return '\\' + toHexByte(c) + (isLast ? '' : ' '); |
| 393 } |
| 394 |
| 395 /** |
| 396 * @param {string} c |
| 397 */ |
| 398 function toHexByte(c) { |
| 399 var hexByte = c.charCodeAt(0).toString(16); |
| 400 if (hexByte.length === 1) |
| 401 hexByte = '0' + hexByte; |
| 402 return hexByte; |
| 403 } |
| 404 |
| 405 /** |
| 406 * @param {string} c |
| 407 * @return {boolean} |
| 408 */ |
| 409 function isCSSIdentChar(c) { |
| 410 if (/[a-zA-Z0-9_-]/.test(c)) |
| 411 return true; |
| 412 return c.charCodeAt(0) >= 0xA0; |
| 413 } |
| 414 |
| 415 /** |
| 416 * @param {string} value |
| 417 * @return {boolean} |
| 418 */ |
| 419 function isCSSIdentifier(value) { |
| 420 return /^-?[a-zA-Z_][a-zA-Z0-9_-]*$/.test(value); |
| 421 } |
| 422 |
| 423 var prefixedOwnClassNamesArray = prefixedElementClassNames(node); |
| 424 var needsClassNames = false; |
| 425 var needsNthChild = false; |
| 426 var ownIndex = -1; |
| 427 var elementIndex = -1; |
| 428 var siblings = parent.children(); |
| 429 for (var i = 0; (ownIndex === -1 || !needsNthChild) && i < siblings.length; ++
i) { |
| 430 var sibling = siblings[i]; |
| 431 if (sibling.nodeType() !== Node.ELEMENT_NODE) |
| 432 continue; |
| 433 elementIndex += 1; |
| 434 if (sibling === node) { |
| 435 ownIndex = elementIndex; |
| 436 continue; |
| 351 } | 437 } |
| 352 var nodeName = node.nodeNameInCorrectCase(); | 438 if (needsNthChild) |
| 439 continue; |
| 440 if (sibling.nodeNameInCorrectCase() !== nodeName) |
| 441 continue; |
| 353 | 442 |
| 354 if (id) | 443 needsClassNames = true; |
| 355 return new WebInspector.DOMNodePathStep(nodeName + idSelector(id), true)
; | 444 var ownClassNames = new Set(prefixedOwnClassNamesArray); |
| 356 var parent = node.parentNode; | 445 if (!ownClassNames.size) { |
| 357 if (!parent || parent.nodeType() === Node.DOCUMENT_NODE) | 446 needsNthChild = true; |
| 358 return new WebInspector.DOMNodePathStep(nodeName, true); | 447 continue; |
| 448 } |
| 449 var siblingClassNamesArray = prefixedElementClassNames(sibling); |
| 450 for (var j = 0; j < siblingClassNamesArray.length; ++j) { |
| 451 var siblingClass = siblingClassNamesArray[j]; |
| 452 if (!ownClassNames.has(siblingClass)) |
| 453 continue; |
| 454 ownClassNames.delete(siblingClass); |
| 455 if (!ownClassNames.size) { |
| 456 needsNthChild = true; |
| 457 break; |
| 458 } |
| 459 } |
| 460 } |
| 359 | 461 |
| 360 /** | 462 var result = nodeName; |
| 361 * @param {!WebInspector.DOMNode} node | 463 if (isTargetNode && nodeName.toLowerCase() === 'input' && node.getAttribute('t
ype') && !node.getAttribute('id') && |
| 362 * @return {!Array.<string>} | 464 !node.getAttribute('class')) |
| 363 */ | 465 result += '[type="' + node.getAttribute('type') + '"]'; |
| 364 function prefixedElementClassNames(node) | 466 if (needsNthChild) { |
| 365 { | 467 result += ':nth-child(' + (ownIndex + 1) + ')'; |
| 366 var classAttribute = node.getAttribute("class"); | 468 } else if (needsClassNames) { |
| 367 if (!classAttribute) | 469 for (var prefixedName of prefixedOwnClassNamesArray) |
| 368 return []; | 470 result += '.' + escapeIdentifierIfNeeded(prefixedName.substr(1)); |
| 471 } |
| 369 | 472 |
| 370 return classAttribute.split(/\s+/g).filter(Boolean).map(function(name) { | 473 return new WebInspector.DOMNodePathStep(result, false); |
| 371 // The prefix is required to store "__proto__" in a object-based map
. | |
| 372 return "$" + name; | |
| 373 }); | |
| 374 } | |
| 375 | |
| 376 /** | |
| 377 * @param {string} id | |
| 378 * @return {string} | |
| 379 */ | |
| 380 function idSelector(id) | |
| 381 { | |
| 382 return "#" + escapeIdentifierIfNeeded(id); | |
| 383 } | |
| 384 | |
| 385 /** | |
| 386 * @param {string} ident | |
| 387 * @return {string} | |
| 388 */ | |
| 389 function escapeIdentifierIfNeeded(ident) | |
| 390 { | |
| 391 if (isCSSIdentifier(ident)) | |
| 392 return ident; | |
| 393 var shouldEscapeFirst = /^(?:[0-9]|-[0-9-]?)/.test(ident); | |
| 394 var lastIndex = ident.length - 1; | |
| 395 return ident.replace(/./g, function(c, i) { | |
| 396 return ((shouldEscapeFirst && i === 0) || !isCSSIdentChar(c)) ? esca
peAsciiChar(c, i === lastIndex) : c; | |
| 397 }); | |
| 398 } | |
| 399 | |
| 400 /** | |
| 401 * @param {string} c | |
| 402 * @param {boolean} isLast | |
| 403 * @return {string} | |
| 404 */ | |
| 405 function escapeAsciiChar(c, isLast) | |
| 406 { | |
| 407 return "\\" + toHexByte(c) + (isLast ? "" : " "); | |
| 408 } | |
| 409 | |
| 410 /** | |
| 411 * @param {string} c | |
| 412 */ | |
| 413 function toHexByte(c) | |
| 414 { | |
| 415 var hexByte = c.charCodeAt(0).toString(16); | |
| 416 if (hexByte.length === 1) | |
| 417 hexByte = "0" + hexByte; | |
| 418 return hexByte; | |
| 419 } | |
| 420 | |
| 421 /** | |
| 422 * @param {string} c | |
| 423 * @return {boolean} | |
| 424 */ | |
| 425 function isCSSIdentChar(c) | |
| 426 { | |
| 427 if (/[a-zA-Z0-9_-]/.test(c)) | |
| 428 return true; | |
| 429 return c.charCodeAt(0) >= 0xA0; | |
| 430 } | |
| 431 | |
| 432 /** | |
| 433 * @param {string} value | |
| 434 * @return {boolean} | |
| 435 */ | |
| 436 function isCSSIdentifier(value) | |
| 437 { | |
| 438 return /^-?[a-zA-Z_][a-zA-Z0-9_-]*$/.test(value); | |
| 439 } | |
| 440 | |
| 441 var prefixedOwnClassNamesArray = prefixedElementClassNames(node); | |
| 442 var needsClassNames = false; | |
| 443 var needsNthChild = false; | |
| 444 var ownIndex = -1; | |
| 445 var elementIndex = -1; | |
| 446 var siblings = parent.children(); | |
| 447 for (var i = 0; (ownIndex === -1 || !needsNthChild) && i < siblings.length;
++i) { | |
| 448 var sibling = siblings[i]; | |
| 449 if (sibling.nodeType() !== Node.ELEMENT_NODE) | |
| 450 continue; | |
| 451 elementIndex += 1; | |
| 452 if (sibling === node) { | |
| 453 ownIndex = elementIndex; | |
| 454 continue; | |
| 455 } | |
| 456 if (needsNthChild) | |
| 457 continue; | |
| 458 if (sibling.nodeNameInCorrectCase() !== nodeName) | |
| 459 continue; | |
| 460 | |
| 461 needsClassNames = true; | |
| 462 var ownClassNames = new Set(prefixedOwnClassNamesArray); | |
| 463 if (!ownClassNames.size) { | |
| 464 needsNthChild = true; | |
| 465 continue; | |
| 466 } | |
| 467 var siblingClassNamesArray = prefixedElementClassNames(sibling); | |
| 468 for (var j = 0; j < siblingClassNamesArray.length; ++j) { | |
| 469 var siblingClass = siblingClassNamesArray[j]; | |
| 470 if (!ownClassNames.has(siblingClass)) | |
| 471 continue; | |
| 472 ownClassNames.delete(siblingClass); | |
| 473 if (!ownClassNames.size) { | |
| 474 needsNthChild = true; | |
| 475 break; | |
| 476 } | |
| 477 } | |
| 478 } | |
| 479 | |
| 480 var result = nodeName; | |
| 481 if (isTargetNode && nodeName.toLowerCase() === "input" && node.getAttribute(
"type") && !node.getAttribute("id") && !node.getAttribute("class")) | |
| 482 result += "[type=\"" + node.getAttribute("type") + "\"]"; | |
| 483 if (needsNthChild) { | |
| 484 result += ":nth-child(" + (ownIndex + 1) + ")"; | |
| 485 } else if (needsClassNames) { | |
| 486 for (var prefixedName of prefixedOwnClassNamesArray) | |
| 487 result += "." + escapeIdentifierIfNeeded(prefixedName.substr(1)); | |
| 488 } | |
| 489 | |
| 490 return new WebInspector.DOMNodePathStep(result, false); | |
| 491 }; | 474 }; |
| 492 | 475 |
| 493 /** | 476 /** |
| 494 * @param {!WebInspector.DOMNode} node | 477 * @param {!WebInspector.DOMNode} node |
| 495 * @param {boolean=} optimized | 478 * @param {boolean=} optimized |
| 496 * @return {string} | 479 * @return {string} |
| 497 */ | 480 */ |
| 498 WebInspector.DOMPresentationUtils.xPath = function(node, optimized) | 481 WebInspector.DOMPresentationUtils.xPath = function(node, optimized) { |
| 499 { | 482 if (node.nodeType() === Node.DOCUMENT_NODE) |
| 500 if (node.nodeType() === Node.DOCUMENT_NODE) | 483 return '/'; |
| 501 return "/"; | |
| 502 | 484 |
| 503 var steps = []; | 485 var steps = []; |
| 504 var contextNode = node; | 486 var contextNode = node; |
| 505 while (contextNode) { | 487 while (contextNode) { |
| 506 var step = WebInspector.DOMPresentationUtils._xPathValue(contextNode, op
timized); | 488 var step = WebInspector.DOMPresentationUtils._xPathValue(contextNode, optimi
zed); |
| 507 if (!step) | 489 if (!step) |
| 508 break; // Error - bail out early. | 490 break; // Error - bail out early. |
| 509 steps.push(step); | 491 steps.push(step); |
| 510 if (step.optimized) | 492 if (step.optimized) |
| 511 break; | 493 break; |
| 512 contextNode = contextNode.parentNode; | 494 contextNode = contextNode.parentNode; |
| 513 } | 495 } |
| 514 | 496 |
| 515 steps.reverse(); | 497 steps.reverse(); |
| 516 return (steps.length && steps[0].optimized ? "" : "/") + steps.join("/"); | 498 return (steps.length && steps[0].optimized ? '' : '/') + steps.join('/'); |
| 517 }; | 499 }; |
| 518 | 500 |
| 519 /** | 501 /** |
| 520 * @param {!WebInspector.DOMNode} node | 502 * @param {!WebInspector.DOMNode} node |
| 521 * @param {boolean=} optimized | 503 * @param {boolean=} optimized |
| 522 * @return {?WebInspector.DOMNodePathStep} | 504 * @return {?WebInspector.DOMNodePathStep} |
| 523 */ | 505 */ |
| 524 WebInspector.DOMPresentationUtils._xPathValue = function(node, optimized) | 506 WebInspector.DOMPresentationUtils._xPathValue = function(node, optimized) { |
| 525 { | 507 var ownValue; |
| 526 var ownValue; | 508 var ownIndex = WebInspector.DOMPresentationUtils._xPathIndex(node); |
| 527 var ownIndex = WebInspector.DOMPresentationUtils._xPathIndex(node); | 509 if (ownIndex === -1) |
| 528 if (ownIndex === -1) | 510 return null; // Error. |
| 529 return null; // Error. | |
| 530 | 511 |
| 531 switch (node.nodeType()) { | 512 switch (node.nodeType()) { |
| 532 case Node.ELEMENT_NODE: | 513 case Node.ELEMENT_NODE: |
| 533 if (optimized && node.getAttribute("id")) | 514 if (optimized && node.getAttribute('id')) |
| 534 return new WebInspector.DOMNodePathStep("//*[@id=\"" + node.getAttri
bute("id") + "\"]", true); | 515 return new WebInspector.DOMNodePathStep('//*[@id="' + node.getAttribute(
'id') + '"]', true); |
| 535 ownValue = node.localName(); | 516 ownValue = node.localName(); |
| 536 break; | 517 break; |
| 537 case Node.ATTRIBUTE_NODE: | 518 case Node.ATTRIBUTE_NODE: |
| 538 ownValue = "@" + node.nodeName(); | 519 ownValue = '@' + node.nodeName(); |
| 539 break; | 520 break; |
| 540 case Node.TEXT_NODE: | 521 case Node.TEXT_NODE: |
| 541 case Node.CDATA_SECTION_NODE: | 522 case Node.CDATA_SECTION_NODE: |
| 542 ownValue = "text()"; | 523 ownValue = 'text()'; |
| 543 break; | 524 break; |
| 544 case Node.PROCESSING_INSTRUCTION_NODE: | 525 case Node.PROCESSING_INSTRUCTION_NODE: |
| 545 ownValue = "processing-instruction()"; | 526 ownValue = 'processing-instruction()'; |
| 546 break; | 527 break; |
| 547 case Node.COMMENT_NODE: | 528 case Node.COMMENT_NODE: |
| 548 ownValue = "comment()"; | 529 ownValue = 'comment()'; |
| 549 break; | 530 break; |
| 550 case Node.DOCUMENT_NODE: | 531 case Node.DOCUMENT_NODE: |
| 551 ownValue = ""; | 532 ownValue = ''; |
| 552 break; | 533 break; |
| 553 default: | 534 default: |
| 554 ownValue = ""; | 535 ownValue = ''; |
| 555 break; | 536 break; |
| 556 } | 537 } |
| 557 | 538 |
| 558 if (ownIndex > 0) | 539 if (ownIndex > 0) |
| 559 ownValue += "[" + ownIndex + "]"; | 540 ownValue += '[' + ownIndex + ']'; |
| 560 | 541 |
| 561 return new WebInspector.DOMNodePathStep(ownValue, node.nodeType() === Node.D
OCUMENT_NODE); | 542 return new WebInspector.DOMNodePathStep(ownValue, node.nodeType() === Node.DOC
UMENT_NODE); |
| 562 }; | 543 }; |
| 563 | 544 |
| 564 /** | 545 /** |
| 565 * @param {!WebInspector.DOMNode} node | 546 * @param {!WebInspector.DOMNode} node |
| 566 * @return {number} | 547 * @return {number} |
| 567 */ | 548 */ |
| 568 WebInspector.DOMPresentationUtils._xPathIndex = function(node) | 549 WebInspector.DOMPresentationUtils._xPathIndex = function(node) { |
| 569 { | 550 // Returns -1 in case of error, 0 if no siblings matching the same expression,
<XPath index among the same expression-matching sibling nodes> otherwise. |
| 570 // Returns -1 in case of error, 0 if no siblings matching the same expressio
n, <XPath index among the same expression-matching sibling nodes> otherwise. | 551 function areNodesSimilar(left, right) { |
| 571 function areNodesSimilar(left, right) | 552 if (left === right) |
| 572 { | 553 return true; |
| 573 if (left === right) | |
| 574 return true; | |
| 575 | 554 |
| 576 if (left.nodeType() === Node.ELEMENT_NODE && right.nodeType() === Node.E
LEMENT_NODE) | 555 if (left.nodeType() === Node.ELEMENT_NODE && right.nodeType() === Node.ELEME
NT_NODE) |
| 577 return left.localName() === right.localName(); | 556 return left.localName() === right.localName(); |
| 578 | 557 |
| 579 if (left.nodeType() === right.nodeType()) | 558 if (left.nodeType() === right.nodeType()) |
| 580 return true; | 559 return true; |
| 581 | 560 |
| 582 // XPath treats CDATA as text nodes. | 561 // XPath treats CDATA as text nodes. |
| 583 var leftType = left.nodeType() === Node.CDATA_SECTION_NODE ? Node.TEXT_N
ODE : left.nodeType(); | 562 var leftType = left.nodeType() === Node.CDATA_SECTION_NODE ? Node.TEXT_NODE
: left.nodeType(); |
| 584 var rightType = right.nodeType() === Node.CDATA_SECTION_NODE ? Node.TEXT
_NODE : right.nodeType(); | 563 var rightType = right.nodeType() === Node.CDATA_SECTION_NODE ? Node.TEXT_NOD
E : right.nodeType(); |
| 585 return leftType === rightType; | 564 return leftType === rightType; |
| 565 } |
| 566 |
| 567 var siblings = node.parentNode ? node.parentNode.children() : null; |
| 568 if (!siblings) |
| 569 return 0; // Root node - no siblings. |
| 570 var hasSameNamedElements; |
| 571 for (var i = 0; i < siblings.length; ++i) { |
| 572 if (areNodesSimilar(node, siblings[i]) && siblings[i] !== node) { |
| 573 hasSameNamedElements = true; |
| 574 break; |
| 586 } | 575 } |
| 587 | 576 } |
| 588 var siblings = node.parentNode ? node.parentNode.children() : null; | 577 if (!hasSameNamedElements) |
| 589 if (!siblings) | 578 return 0; |
| 590 return 0; // Root node - no siblings. | 579 var ownIndex = 1; // XPath indices start with 1. |
| 591 var hasSameNamedElements; | 580 for (var i = 0; i < siblings.length; ++i) { |
| 592 for (var i = 0; i < siblings.length; ++i) { | 581 if (areNodesSimilar(node, siblings[i])) { |
| 593 if (areNodesSimilar(node, siblings[i]) && siblings[i] !== node) { | 582 if (siblings[i] === node) |
| 594 hasSameNamedElements = true; | 583 return ownIndex; |
| 595 break; | 584 ++ownIndex; |
| 596 } | |
| 597 } | 585 } |
| 598 if (!hasSameNamedElements) | 586 } |
| 599 return 0; | 587 return -1; // An error occurred: |node| not found in parent's children. |
| 600 var ownIndex = 1; // XPath indices start with 1. | |
| 601 for (var i = 0; i < siblings.length; ++i) { | |
| 602 if (areNodesSimilar(node, siblings[i])) { | |
| 603 if (siblings[i] === node) | |
| 604 return ownIndex; | |
| 605 ++ownIndex; | |
| 606 } | |
| 607 } | |
| 608 return -1; // An error occurred: |node| not found in parent's children. | |
| 609 }; | 588 }; |
| 610 | 589 |
| 611 /** | 590 /** |
| 612 * @constructor | 591 * @unrestricted |
| 613 * @param {string} value | |
| 614 * @param {boolean} optimized | |
| 615 */ | 592 */ |
| 616 WebInspector.DOMNodePathStep = function(value, optimized) | 593 WebInspector.DOMNodePathStep = class { |
| 617 { | 594 /** |
| 595 * @param {string} value |
| 596 * @param {boolean} optimized |
| 597 */ |
| 598 constructor(value, optimized) { |
| 618 this.value = value; | 599 this.value = value; |
| 619 this.optimized = optimized || false; | 600 this.optimized = optimized || false; |
| 620 }; | 601 } |
| 621 | 602 |
| 622 WebInspector.DOMNodePathStep.prototype = { | 603 /** |
| 623 /** | 604 * @override |
| 624 * @override | 605 * @return {string} |
| 625 * @return {string} | 606 */ |
| 626 */ | 607 toString() { |
| 627 toString: function() | 608 return this.value; |
| 628 { | 609 } |
| 629 return this.value; | |
| 630 } | |
| 631 }; | 610 }; |
| 632 | 611 |
| 633 /** | 612 /** |
| 634 * @interface | 613 * @interface |
| 635 */ | 614 */ |
| 636 WebInspector.DOMPresentationUtils.MarkerDecorator = function() | 615 WebInspector.DOMPresentationUtils.MarkerDecorator = function() {}; |
| 637 { | |
| 638 }; | |
| 639 | 616 |
| 640 WebInspector.DOMPresentationUtils.MarkerDecorator.prototype = { | 617 WebInspector.DOMPresentationUtils.MarkerDecorator.prototype = { |
| 641 /** | 618 /** |
| 642 * @param {!WebInspector.DOMNode} node | 619 * @param {!WebInspector.DOMNode} node |
| 643 * @return {?{title: string, color: string}} | 620 * @return {?{title: string, color: string}} |
| 644 */ | 621 */ |
| 645 decorate: function(node) { } | 622 decorate: function(node) {} |
| 646 }; | 623 }; |
| 647 | 624 |
| 648 /** | 625 /** |
| 649 * @constructor | |
| 650 * @implements {WebInspector.DOMPresentationUtils.MarkerDecorator} | 626 * @implements {WebInspector.DOMPresentationUtils.MarkerDecorator} |
| 651 * @param {!Runtime.Extension} extension | 627 * @unrestricted |
| 652 */ | 628 */ |
| 653 WebInspector.DOMPresentationUtils.GenericDecorator = function(extension) | 629 WebInspector.DOMPresentationUtils.GenericDecorator = class { |
| 654 { | 630 /** |
| 631 * @param {!Runtime.Extension} extension |
| 632 */ |
| 633 constructor(extension) { |
| 655 this._title = WebInspector.UIString(extension.title()); | 634 this._title = WebInspector.UIString(extension.title()); |
| 656 this._color = extension.descriptor()["color"]; | 635 this._color = extension.descriptor()['color']; |
| 636 } |
| 637 |
| 638 /** |
| 639 * @override |
| 640 * @param {!WebInspector.DOMNode} node |
| 641 * @return {?{title: string, color: string}} |
| 642 */ |
| 643 decorate(node) { |
| 644 return {title: this._title, color: this._color}; |
| 645 } |
| 657 }; | 646 }; |
| 658 | |
| 659 WebInspector.DOMPresentationUtils.GenericDecorator.prototype = { | |
| 660 /** | |
| 661 * @override | |
| 662 * @param {!WebInspector.DOMNode} node | |
| 663 * @return {?{title: string, color: string}} | |
| 664 */ | |
| 665 decorate: function(node) | |
| 666 { | |
| 667 return { title: this._title, color: this._color }; | |
| 668 } | |
| 669 }; | |
| OLD | NEW |