Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
|
aandrey
2013/11/20 16:20:49
should we also move XPath to this file (maybe in a
apavlov
2013/11/21 07:31:35
XPath building deals equally much with DOM and pre
| |
| 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 * |
| 11 * 1. Redistributions of source code must retain the above copyright | 11 * 1. Redistributions of source code must retain the above copyright |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 151 else | 151 else |
| 152 description = WebInspector.UIString("%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)", offsetWidth, offsetHeight, naturalWidth, naturalHeight); | 152 description = WebInspector.UIString("%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)", offsetWidth, offsetHeight, naturalWidth, naturalHeight); |
| 153 } | 153 } |
| 154 | 154 |
| 155 container.createChild("tr").createChild("td", "image-container").appendC hild(imageElement); | 155 container.createChild("tr").createChild("td", "image-container").appendC hild(imageElement); |
| 156 if (description) | 156 if (description) |
| 157 container.createChild("tr").createChild("td").createChild("span", "d escription").textContent = description; | 157 container.createChild("tr").createChild("td").createChild("span", "d escription").textContent = description; |
| 158 userCallback(container); | 158 userCallback(container); |
| 159 } | 159 } |
| 160 } | 160 } |
| 161 | |
| 162 WebInspector.DOMPresentationUtils.cssPathValue = function(node, optimized) | |
|
aandrey
2013/11/20 16:20:49
jsdocs plz
apavlov
2013/11/21 07:31:35
Done.
| |
| 163 { | |
| 164 if (node.nodeType() !== Node.ELEMENT_NODE) | |
| 165 return null; | |
| 166 | |
| 167 var id = node.getAttribute("id"); | |
| 168 if (optimized) { | |
| 169 if (id) | |
| 170 return new WebInspector.DOMNodePathStep(idSelector(id), true); | |
| 171 var nodeNameLower = node.nodeName().toLowerCase(); | |
| 172 if (nodeNameLower === "body" || nodeNameLower === "head" || nodeNameLowe r === "html") | |
| 173 return new WebInspector.DOMNodePathStep(node.nodeNameInCorrectCase() , true); | |
| 174 } | |
| 175 var nodeName = node.nodeNameInCorrectCase(); | |
| 176 | |
| 177 // The "id" presence should terminate the traversal, hence |true|. | |
|
aandrey
2013/11/20 16:20:49
sound obvious to me... maybe remove?
apavlov
2013/11/21 07:31:35
Done.
| |
| 178 if (id) | |
| 179 return new WebInspector.DOMNodePathStep(nodeName + idSelector(id), true) ; | |
| 180 var parent = node.parentNode; | |
| 181 if (!parent || parent.nodeType() === Node.DOCUMENT_NODE) | |
| 182 return new WebInspector.DOMNodePathStep(nodeName, true); | |
| 183 | |
| 184 /** | |
| 185 * @param {WebInspector.DOMNode} node | |
| 186 * @return {Array.<string>} | |
| 187 */ | |
| 188 function elementClassNames(node) | |
| 189 { | |
| 190 var classAttribute = node.getAttribute("class"); | |
| 191 if (!classAttribute) | |
| 192 return []; | |
| 193 | |
| 194 return classAttribute.split(/\s+/g).filter(Boolean); | |
| 195 } | |
| 196 | |
| 197 /** | |
| 198 * @param {string} id | |
| 199 * @return {string} | |
| 200 */ | |
| 201 function idSelector(id) | |
| 202 { | |
| 203 return "#" + escapeIdentifierIfNeeded(id); | |
| 204 } | |
| 205 | |
| 206 /** | |
| 207 * @param {string} ident | |
| 208 * @return {string} | |
| 209 */ | |
| 210 function escapeIdentifierIfNeeded(ident) | |
| 211 { | |
| 212 if (isCSSIdentifier(ident)) | |
| 213 return ident; | |
| 214 var shouldEscapeFirst = /^(?:[0-9]|-[0-9-]?)/.test(ident); | |
| 215 var lastIndex = ident.length - 1; | |
| 216 return ident.replace(/./g, function(c, i) { | |
| 217 return ((shouldEscapeFirst && i === 0) || !isCSSIdentChar(c)) ? esca peAsciiChar(c, i === lastIndex) : c; | |
| 218 }); | |
| 219 } | |
| 220 | |
| 221 /** | |
| 222 * @param {string} c | |
| 223 * @param {boolean} isLast | |
| 224 * @return {string} | |
| 225 */ | |
| 226 function escapeAsciiChar(c, isLast) | |
| 227 { | |
| 228 return "\\" + toHexByte(c) + (isLast ? "" : " "); | |
| 229 } | |
| 230 | |
| 231 /** | |
| 232 * @param {string} c | |
| 233 */ | |
| 234 function toHexByte(c) | |
| 235 { | |
| 236 var hexByte = c.charCodeAt(0).toString(16); | |
| 237 if (hexByte.length === 1) | |
| 238 hexByte = "0" + hexByte; | |
| 239 return hexByte; | |
| 240 } | |
| 241 | |
| 242 /** | |
| 243 * @param {string} c | |
| 244 * @return {boolean} | |
| 245 */ | |
| 246 function isCSSIdentChar(c) | |
| 247 { | |
| 248 if (/[a-zA-Z0-9_-]/.test(c)) | |
| 249 return true; | |
| 250 return c.charCodeAt(0) >= 0xA0; | |
| 251 } | |
| 252 | |
| 253 /** | |
| 254 * @param {string} value | |
| 255 * @return {boolean} | |
| 256 */ | |
| 257 function isCSSIdentifier(value) | |
| 258 { | |
| 259 return /^-?[a-zA-Z_][a-zA-Z0-9_-]*$/.test(value); | |
| 260 } | |
| 261 | |
| 262 var uniqueClassNamesArray = elementClassNames(node); | |
|
aandrey
2013/11/20 16:20:49
they are no longer unique, once you removed keySet
apavlov
2013/11/21 07:31:35
Done.
| |
| 263 var needsClassNames = false; | |
| 264 var needsNthChild = false; | |
| 265 var ownIndex = -1; | |
| 266 var siblings = parent.children(); | |
| 267 for (var i = 0; (ownIndex === -1 || !needsNthChild) && i < siblings.length; ++i) { | |
| 268 var sibling = siblings[i]; | |
| 269 if (sibling === node) { | |
| 270 ownIndex = i; | |
| 271 continue; | |
| 272 } | |
| 273 if (needsNthChild) | |
| 274 continue; | |
| 275 if (sibling.nodeNameInCorrectCase() !== nodeName) | |
| 276 continue; | |
| 277 | |
| 278 needsClassNames = true; | |
| 279 var ownClassNames = uniqueClassNamesArray.keySet(); | |
|
aandrey
2013/11/20 16:20:49
maybe write a utility method to remove a given arr
apavlov
2013/11/21 07:31:35
The problem is that we still need to know how many
| |
| 280 var ownClassNameCount = 0; | |
| 281 for (var name in ownClassNames) | |
| 282 ++ownClassNameCount; | |
| 283 if (ownClassNameCount === 0) { | |
| 284 needsNthChild = true; | |
| 285 continue; | |
| 286 } | |
| 287 var siblingClassNames = elementClassNames(sibling).keySet(); | |
| 288 for (var siblingClass in siblingClassNames) { | |
| 289 if (!ownClassNames.hasOwnProperty(siblingClass)) | |
| 290 continue; | |
| 291 delete ownClassNames[siblingClass]; | |
| 292 if (!--ownClassNameCount) { | |
| 293 needsNthChild = true; | |
| 294 break; | |
| 295 } | |
| 296 } | |
| 297 } | |
| 298 | |
| 299 var result = nodeName; | |
| 300 if (needsNthChild) { | |
| 301 result += ":nth-child(" + (ownIndex + 1) + ")"; | |
| 302 } else if (needsClassNames) { | |
| 303 for (var name in uniqueClassNamesArray.keySet()) | |
| 304 result += "." + escapeIdentifierIfNeeded(name); | |
| 305 } | |
| 306 | |
| 307 return new WebInspector.DOMNodePathStep(result, false); | |
| 308 } | |
| 309 | |
| 310 /** | |
| 311 * @constructor | |
| 312 * @param {string} value | |
| 313 * @param {boolean} optimized | |
| 314 */ | |
| 315 WebInspector.DOMNodePathStep = function(value, optimized) | |
| 316 { | |
| 317 this.value = value; | |
| 318 this.optimized = optimized; | |
| 319 } | |
| 320 | |
| 321 WebInspector.DOMNodePathStep.prototype = { | |
| 322 toString: function() | |
| 323 { | |
| 324 return this.value; | |
| 325 } | |
| 326 } | |
| OLD | NEW |