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 |