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 140 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 /** |
| 163 * @param {!WebInspector.DOMNode} node |
| 164 * @param {boolean=} optimized |
| 165 */ |
| 166 WebInspector.DOMPresentationUtils.cssPathValue = function(node, optimized) |
| 167 { |
| 168 if (node.nodeType() !== Node.ELEMENT_NODE) |
| 169 return null; |
| 170 |
| 171 var id = node.getAttribute("id"); |
| 172 if (optimized) { |
| 173 if (id) |
| 174 return new WebInspector.DOMNodePathStep(idSelector(id), true); |
| 175 var nodeNameLower = node.nodeName().toLowerCase(); |
| 176 if (nodeNameLower === "body" || nodeNameLower === "head" || nodeNameLowe
r === "html") |
| 177 return new WebInspector.DOMNodePathStep(node.nodeNameInCorrectCase()
, true); |
| 178 } |
| 179 var nodeName = node.nodeNameInCorrectCase(); |
| 180 |
| 181 if (id) |
| 182 return new WebInspector.DOMNodePathStep(nodeName + idSelector(id), true)
; |
| 183 var parent = node.parentNode; |
| 184 if (!parent || parent.nodeType() === Node.DOCUMENT_NODE) |
| 185 return new WebInspector.DOMNodePathStep(nodeName, true); |
| 186 |
| 187 /** |
| 188 * @param {WebInspector.DOMNode} node |
| 189 * @return {Array.<string>} |
| 190 */ |
| 191 function prefixedElementClassNames(node) |
| 192 { |
| 193 var classAttribute = node.getAttribute("class"); |
| 194 if (!classAttribute) |
| 195 return []; |
| 196 |
| 197 return classAttribute.split(/\s+/g).filter(Boolean).map(function(name) { |
| 198 // The prefix is required to store "__proto__" in a object-based map
. |
| 199 return "$" + name; |
| 200 }); |
| 201 } |
| 202 |
| 203 /** |
| 204 * @param {string} id |
| 205 * @return {string} |
| 206 */ |
| 207 function idSelector(id) |
| 208 { |
| 209 return "#" + escapeIdentifierIfNeeded(id); |
| 210 } |
| 211 |
| 212 /** |
| 213 * @param {string} ident |
| 214 * @return {string} |
| 215 */ |
| 216 function escapeIdentifierIfNeeded(ident) |
| 217 { |
| 218 if (isCSSIdentifier(ident)) |
| 219 return ident; |
| 220 var shouldEscapeFirst = /^(?:[0-9]|-[0-9-]?)/.test(ident); |
| 221 var lastIndex = ident.length - 1; |
| 222 return ident.replace(/./g, function(c, i) { |
| 223 return ((shouldEscapeFirst && i === 0) || !isCSSIdentChar(c)) ? esca
peAsciiChar(c, i === lastIndex) : c; |
| 224 }); |
| 225 } |
| 226 |
| 227 /** |
| 228 * @param {string} c |
| 229 * @param {boolean} isLast |
| 230 * @return {string} |
| 231 */ |
| 232 function escapeAsciiChar(c, isLast) |
| 233 { |
| 234 return "\\" + toHexByte(c) + (isLast ? "" : " "); |
| 235 } |
| 236 |
| 237 /** |
| 238 * @param {string} c |
| 239 */ |
| 240 function toHexByte(c) |
| 241 { |
| 242 var hexByte = c.charCodeAt(0).toString(16); |
| 243 if (hexByte.length === 1) |
| 244 hexByte = "0" + hexByte; |
| 245 return hexByte; |
| 246 } |
| 247 |
| 248 /** |
| 249 * @param {string} c |
| 250 * @return {boolean} |
| 251 */ |
| 252 function isCSSIdentChar(c) |
| 253 { |
| 254 if (/[a-zA-Z0-9_-]/.test(c)) |
| 255 return true; |
| 256 return c.charCodeAt(0) >= 0xA0; |
| 257 } |
| 258 |
| 259 /** |
| 260 * @param {string} value |
| 261 * @return {boolean} |
| 262 */ |
| 263 function isCSSIdentifier(value) |
| 264 { |
| 265 return /^-?[a-zA-Z_][a-zA-Z0-9_-]*$/.test(value); |
| 266 } |
| 267 |
| 268 var prefixedOwnClassNamesArray = prefixedElementClassNames(node); |
| 269 var needsClassNames = false; |
| 270 var needsNthChild = false; |
| 271 var ownIndex = -1; |
| 272 var siblings = parent.children(); |
| 273 for (var i = 0; (ownIndex === -1 || !needsNthChild) && i < siblings.length;
++i) { |
| 274 var sibling = siblings[i]; |
| 275 if (sibling === node) { |
| 276 ownIndex = i; |
| 277 continue; |
| 278 } |
| 279 if (needsNthChild) |
| 280 continue; |
| 281 if (sibling.nodeNameInCorrectCase() !== nodeName) |
| 282 continue; |
| 283 |
| 284 needsClassNames = true; |
| 285 var ownClassNames = prefixedOwnClassNamesArray.keySet(); |
| 286 var ownClassNameCount = 0; |
| 287 for (var name in ownClassNames) |
| 288 ++ownClassNameCount; |
| 289 if (ownClassNameCount === 0) { |
| 290 needsNthChild = true; |
| 291 continue; |
| 292 } |
| 293 var siblingClassNamesArray = prefixedElementClassNames(sibling); |
| 294 for (var j = 0; j < siblingClassNamesArray.length; ++j) { |
| 295 var siblingClass = siblingClassNamesArray[j]; |
| 296 if (!ownClassNames.hasOwnProperty(siblingClass)) |
| 297 continue; |
| 298 delete ownClassNames[siblingClass]; |
| 299 if (!--ownClassNameCount) { |
| 300 needsNthChild = true; |
| 301 break; |
| 302 } |
| 303 } |
| 304 } |
| 305 |
| 306 var result = nodeName; |
| 307 if (needsNthChild) { |
| 308 result += ":nth-child(" + (ownIndex + 1) + ")"; |
| 309 } else if (needsClassNames) { |
| 310 for (var prefixedName in prefixedOwnClassNamesArray.keySet()) |
| 311 result += "." + escapeIdentifierIfNeeded(prefixedName.substr(1)); |
| 312 } |
| 313 |
| 314 return new WebInspector.DOMNodePathStep(result, false); |
| 315 } |
| 316 |
| 317 /** |
| 318 * @constructor |
| 319 * @param {string} value |
| 320 * @param {boolean} optimized |
| 321 */ |
| 322 WebInspector.DOMNodePathStep = function(value, optimized) |
| 323 { |
| 324 this.value = value; |
| 325 this.optimized = optimized; |
| 326 } |
| 327 |
| 328 WebInspector.DOMNodePathStep.prototype = { |
| 329 /** |
| 330 * @return {string} |
| 331 */ |
| 332 toString: function() |
| 333 { |
| 334 return this.value; |
| 335 } |
| 336 } |
OLD | NEW |