| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> | 3 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> |
| 4 * Copyright (C) 2009 Joseph Pecoraro |
| 4 * | 5 * |
| 5 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
| 7 * are met: | 8 * are met: |
| 8 * | 9 * |
| 9 * 1. Redistributions of source code must retain the above copyright | 10 * 1. Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 11 * notice, this list of conditions and the following disclaimer. |
| 11 * 2. Redistributions in binary form must reproduce the above copyright | 12 * 2. Redistributions in binary form must reproduce the above copyright |
| 12 * notice, this list of conditions and the following disclaimer in the | 13 * notice, this list of conditions and the following disclaimer in the |
| 13 * documentation and/or other materials provided with the distribution. | 14 * documentation and/or other materials provided with the distribution. |
| (...skipping 29 matching lines...) Expand all Loading... |
| 43 } | 44 } |
| 44 | 45 |
| 45 WebInspector.ElementsTreeOutline.prototype = { | 46 WebInspector.ElementsTreeOutline.prototype = { |
| 46 get rootDOMNode() | 47 get rootDOMNode() |
| 47 { | 48 { |
| 48 return this._rootDOMNode; | 49 return this._rootDOMNode; |
| 49 }, | 50 }, |
| 50 | 51 |
| 51 set rootDOMNode(x) | 52 set rootDOMNode(x) |
| 52 { | 53 { |
| 53 if (objectsAreSame(this._rootDOMNode, x)) | 54 if (this._rootDOMNode === x) |
| 54 return; | 55 return; |
| 55 | 56 |
| 56 this._rootDOMNode = x; | 57 this._rootDOMNode = x; |
| 57 | 58 |
| 58 this.update(); | 59 this.update(); |
| 59 }, | 60 }, |
| 60 | 61 |
| 61 get focusedDOMNode() | 62 get focusedDOMNode() |
| 62 { | 63 { |
| 63 return this._focusedDOMNode; | 64 return this._focusedDOMNode; |
| 64 }, | 65 }, |
| 65 | 66 |
| 66 set focusedDOMNode(x) | 67 set focusedDOMNode(x) |
| 67 { | 68 { |
| 68 if (objectsAreSame(this._focusedDOMNode, x)) { | 69 if (this._focusedDOMNode === x) { |
| 69 this.revealAndSelectNode(x); | 70 this.revealAndSelectNode(x); |
| 70 return; | 71 return; |
| 71 } | 72 } |
| 72 | 73 |
| 73 this._focusedDOMNode = x; | 74 this._focusedDOMNode = x; |
| 74 | 75 |
| 75 this.revealAndSelectNode(x); | 76 this.revealAndSelectNode(x); |
| 76 | 77 |
| 77 // The revealAndSelectNode() method might find a different element if th
ere is inlined text, | 78 // The revealAndSelectNode() method might find a different element if th
ere is inlined text, |
| 78 // and the select() call would change the focusedDOMNode and reenter thi
s setter. So to | 79 // and the select() call would change the focusedDOMNode and reenter thi
s setter. So to |
| 79 // avoid calling focusedNodeChanged() twice, first check if _focusedDOMN
ode is the same | 80 // avoid calling focusedNodeChanged() twice, first check if _focusedDOMN
ode is the same |
| 80 // node as the one passed in. | 81 // node as the one passed in. |
| 81 if (objectsAreSame(this._focusedDOMNode, x)) { | 82 if (this._focusedDOMNode === x) { |
| 82 this.focusedNodeChanged(); | 83 this.focusedNodeChanged(); |
| 83 | 84 |
| 84 if (x && !this.suppressSelectHighlight) { | 85 if (x && !this.suppressSelectHighlight) { |
| 85 InspectorController.highlightDOMNode(x); | 86 InspectorController.highlightDOMNode(x.id); |
| 86 | 87 |
| 87 if ("_restorePreviousHighlightNodeTimeout" in this) | 88 if ("_restorePreviousHighlightNodeTimeout" in this) |
| 88 clearTimeout(this._restorePreviousHighlightNodeTimeout); | 89 clearTimeout(this._restorePreviousHighlightNodeTimeout); |
| 89 | 90 |
| 90 function restoreHighlightToHoveredNode() | 91 function restoreHighlightToHoveredNode() |
| 91 { | 92 { |
| 92 var hoveredNode = WebInspector.hoveredDOMNode; | 93 var hoveredNode = WebInspector.hoveredDOMNode; |
| 93 if (hoveredNode) | 94 if (hoveredNode) |
| 94 InspectorController.highlightDOMNode(hoveredNode); | 95 InspectorController.highlightDOMNode(hoveredNode.id); |
| 95 else | 96 else |
| 96 InspectorController.hideDOMNodeHighlight(); | 97 InspectorController.hideDOMNodeHighlight(); |
| 97 } | 98 } |
| 98 | 99 |
| 99 this._restorePreviousHighlightNodeTimeout = setTimeout(restoreHi
ghlightToHoveredNode, 2000); | 100 this._restorePreviousHighlightNodeTimeout = setTimeout(restoreHi
ghlightToHoveredNode, 2000); |
| 100 } | 101 } |
| 101 } | 102 } |
| 102 }, | 103 }, |
| 103 | 104 |
| 104 update: function() | 105 update: function() |
| (...skipping 25 matching lines...) Expand all Loading... |
| 130 updateSelection: function() | 131 updateSelection: function() |
| 131 { | 132 { |
| 132 if (!this.selectedTreeElement) | 133 if (!this.selectedTreeElement) |
| 133 return; | 134 return; |
| 134 var element = this.treeOutline.selectedTreeElement; | 135 var element = this.treeOutline.selectedTreeElement; |
| 135 element.updateSelection(); | 136 element.updateSelection(); |
| 136 }, | 137 }, |
| 137 | 138 |
| 138 focusedNodeChanged: function(forceUpdate) {}, | 139 focusedNodeChanged: function(forceUpdate) {}, |
| 139 | 140 |
| 140 findTreeElement: function(node, isAncestor, getParent, equal) | 141 findTreeElement: function(node) |
| 141 { | 142 { |
| 142 if (typeof isAncestor === "undefined") | 143 var treeElement = TreeOutline.prototype.findTreeElement.call(this, node,
isAncestorNode, parentNode); |
| 143 isAncestor = isAncestorIncludingParentFrames; | |
| 144 if (typeof getParent === "undefined") | |
| 145 getParent = parentNodeOrFrameElement; | |
| 146 if (typeof equal === "undefined") | |
| 147 equal = objectsAreSame; | |
| 148 | |
| 149 var treeElement = TreeOutline.prototype.findTreeElement.call(this, node,
isAncestor, getParent, equal); | |
| 150 if (!treeElement && node.nodeType === Node.TEXT_NODE) { | 144 if (!treeElement && node.nodeType === Node.TEXT_NODE) { |
| 151 // The text node might have been inlined if it was short, so try to
find the parent element. | 145 // The text node might have been inlined if it was short, so try to
find the parent element. |
| 152 treeElement = TreeOutline.prototype.findTreeElement.call(this, node.
parentNode, isAncestor, getParent, equal); | 146 treeElement = TreeOutline.prototype.findTreeElement.call(this, node.
parentNode, isAncestorNode, parentNode); |
| 153 } | 147 } |
| 154 | 148 |
| 155 return treeElement; | 149 return treeElement; |
| 156 }, | 150 }, |
| 157 | 151 |
| 158 revealAndSelectNode: function(node) | 152 revealAndSelectNode: function(node) |
| 159 { | 153 { |
| 160 if (!node) | 154 if (!node) |
| 161 return; | 155 return; |
| 162 | 156 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 } | 234 } |
| 241 | 235 |
| 242 WebInspector.hoveredDOMNode = null; | 236 WebInspector.hoveredDOMNode = null; |
| 243 } | 237 } |
| 244 } | 238 } |
| 245 | 239 |
| 246 WebInspector.ElementsTreeOutline.prototype.__proto__ = TreeOutline.prototype; | 240 WebInspector.ElementsTreeOutline.prototype.__proto__ = TreeOutline.prototype; |
| 247 | 241 |
| 248 WebInspector.ElementsTreeElement = function(node) | 242 WebInspector.ElementsTreeElement = function(node) |
| 249 { | 243 { |
| 250 var hasChildren = node.contentDocument || (Preferences.ignoreWhitespace ? (f
irstChildSkippingWhitespace.call(node) ? true : false) : node.hasChildNodes()); | 244 var hasChildren = Preferences.ignoreWhitespace ? (firstChildSkippingWhitespa
ce.call(node) ? true : false) : node.hasChildNodes(); |
| 251 var titleInfo = nodeTitleInfo.call(node, hasChildren, WebInspector.linkifyUR
L); | 245 var titleInfo = nodeTitleInfo.call(node, hasChildren, WebInspector.linkifyUR
L); |
| 252 | 246 |
| 253 if (titleInfo.hasChildren) | 247 if (titleInfo.hasChildren) |
| 254 this.whitespaceIgnored = Preferences.ignoreWhitespace; | 248 this.whitespaceIgnored = Preferences.ignoreWhitespace; |
| 255 | 249 |
| 256 // The title will be updated in onattach. | 250 // The title will be updated in onattach. |
| 257 TreeElement.call(this, "", node, titleInfo.hasChildren); | 251 TreeElement.call(this, "", node, titleInfo.hasChildren); |
| 252 |
| 253 if (this.representedObject.nodeType == Node.ELEMENT_NODE) |
| 254 this._canAddAttributes = true; |
| 258 } | 255 } |
| 259 | 256 |
| 260 WebInspector.ElementsTreeElement.prototype = { | 257 WebInspector.ElementsTreeElement.prototype = { |
| 261 get highlighted() | 258 get highlighted() |
| 262 { | 259 { |
| 263 return this._highlighted; | 260 return this._highlighted; |
| 264 }, | 261 }, |
| 265 | 262 |
| 266 set highlighted(x) | 263 set highlighted(x) |
| 267 { | 264 { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 289 return; | 286 return; |
| 290 | 287 |
| 291 this._hovered = x; | 288 this._hovered = x; |
| 292 | 289 |
| 293 if (this.listItemElement) { | 290 if (this.listItemElement) { |
| 294 if (x) { | 291 if (x) { |
| 295 this.updateSelection(); | 292 this.updateSelection(); |
| 296 this.listItemElement.addStyleClass("hovered"); | 293 this.listItemElement.addStyleClass("hovered"); |
| 297 } else | 294 } else |
| 298 this.listItemElement.removeStyleClass("hovered"); | 295 this.listItemElement.removeStyleClass("hovered"); |
| 296 if (this._canAddAttributes) |
| 297 this.toggleNewAttributeButton(); |
| 299 } | 298 } |
| 300 }, | 299 }, |
| 301 | 300 |
| 301 toggleNewAttributeButton: function() |
| 302 { |
| 303 function removeWhenEditing(event) |
| 304 { |
| 305 if (this._addAttributeElement && this._addAttributeElement.parentNod
e) |
| 306 this._addAttributeElement.parentNode.removeChild(this._addAttrib
uteElement); |
| 307 delete this._addAttributeElement; |
| 308 } |
| 309 |
| 310 if (!this._addAttributeElement && this._hovered && !this._editing) { |
| 311 var span = document.createElement("span"); |
| 312 span.className = "add-attribute"; |
| 313 span.textContent = "\u2026"; |
| 314 span.addEventListener("dblclick", removeWhenEditing.bind(this), fals
e); |
| 315 this._addAttributeElement = span; |
| 316 |
| 317 var tag = this.listItemElement.getElementsByClassName("webkit-html-t
ag")[0]; |
| 318 this._insertInLastAttributePosition(tag, span); |
| 319 } else if (!this._hovered && this._addAttributeElement) { |
| 320 if (this._addAttributeElement.parentNode) |
| 321 this._addAttributeElement.parentNode.removeChild(this._addAttrib
uteElement); |
| 322 delete this._addAttributeElement; |
| 323 } |
| 324 }, |
| 325 |
| 302 updateSelection: function() | 326 updateSelection: function() |
| 303 { | 327 { |
| 304 var listItemElement = this.listItemElement; | 328 var listItemElement = this.listItemElement; |
| 305 if (!listItemElement) | 329 if (!listItemElement) |
| 306 return; | 330 return; |
| 307 | 331 |
| 308 if (document.body.offsetWidth <= 0) { | 332 if (document.body.offsetWidth <= 0) { |
| 309 // The stylesheet hasn't loaded yet or the window is closed, | 333 // The stylesheet hasn't loaded yet or the window is closed, |
| 310 // so we can't calculate what is need. Return early. | 334 // so we can't calculate what is need. Return early. |
| 311 return; | 335 return; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 | 373 |
| 350 onpopulate: function() | 374 onpopulate: function() |
| 351 { | 375 { |
| 352 if (this.children.length || this.whitespaceIgnored !== Preferences.ignor
eWhitespace) | 376 if (this.children.length || this.whitespaceIgnored !== Preferences.ignor
eWhitespace) |
| 353 return; | 377 return; |
| 354 | 378 |
| 355 this.whitespaceIgnored = Preferences.ignoreWhitespace; | 379 this.whitespaceIgnored = Preferences.ignoreWhitespace; |
| 356 | 380 |
| 357 this.updateChildren(); | 381 this.updateChildren(); |
| 358 }, | 382 }, |
| 383 |
| 384 updateChildren: function(fullRefresh) |
| 385 { |
| 386 WebInspector.domAgent.getChildNodesAsync(this.representedObject, this._u
pdateChildren.bind(this, fullRefresh)); |
| 387 }, |
| 359 | 388 |
| 360 updateChildren: function(fullRefresh) | 389 _updateChildren: function(fullRefresh) |
| 361 { | 390 { |
| 362 if (fullRefresh) { | 391 if (fullRefresh) { |
| 363 var selectedTreeElement = this.treeOutline.selectedTreeElement; | 392 var selectedTreeElement = this.treeOutline.selectedTreeElement; |
| 364 if (selectedTreeElement && selectedTreeElement.hasAncestor(this)) | 393 if (selectedTreeElement && selectedTreeElement.hasAncestor(this)) |
| 365 this.select(); | 394 this.select(); |
| 366 this.removeChildren(); | 395 this.removeChildren(); |
| 367 } | 396 } |
| 368 | 397 |
| 369 var treeElement = this; | 398 var treeElement = this; |
| 370 var treeChildIndex = 0; | 399 var treeChildIndex = 0; |
| 371 | 400 |
| 372 function updateChildrenOfNode(node) | 401 function updateChildrenOfNode(node) |
| 373 { | 402 { |
| 374 var treeOutline = treeElement.treeOutline; | 403 var treeOutline = treeElement.treeOutline; |
| 375 var child = (Preferences.ignoreWhitespace ? firstChildSkippingWhites
pace.call(node) : node.firstChild); | 404 var child = (Preferences.ignoreWhitespace ? firstChildSkippingWhites
pace.call(node) : node.firstChild); |
| 376 while (child) { | 405 while (child) { |
| 377 var currentTreeElement = treeElement.children[treeChildIndex]; | 406 var currentTreeElement = treeElement.children[treeChildIndex]; |
| 378 if (!currentTreeElement || !objectsAreSame(currentTreeElement.re
presentedObject, child)) { | 407 if (!currentTreeElement || currentTreeElement.representedObject
!== child) { |
| 379 // Find any existing element that is later in the children l
ist. | 408 // Find any existing element that is later in the children l
ist. |
| 380 var existingTreeElement = null; | 409 var existingTreeElement = null; |
| 381 for (var i = (treeChildIndex + 1); i < treeElement.children.
length; ++i) { | 410 for (var i = (treeChildIndex + 1); i < treeElement.children.
length; ++i) { |
| 382 if (objectsAreSame(treeElement.children[i].representedOb
ject, child)) { | 411 if (treeElement.children[i].representedObject === child)
{ |
| 383 existingTreeElement = treeElement.children[i]; | 412 existingTreeElement = treeElement.children[i]; |
| 384 break; | 413 break; |
| 385 } | 414 } |
| 386 } | 415 } |
| 387 | 416 |
| 388 if (existingTreeElement && existingTreeElement.parent === tr
eeElement) { | 417 if (existingTreeElement && existingTreeElement.parent === tr
eeElement) { |
| 389 // If an existing element was found and it has the same
parent, just move it. | 418 // If an existing element was found and it has the same
parent, just move it. |
| 390 var wasSelected = existingTreeElement.selected; | 419 var wasSelected = existingTreeElement.selected; |
| 391 treeElement.removeChild(existingTreeElement); | 420 treeElement.removeChild(existingTreeElement); |
| 392 treeElement.insertChild(existingTreeElement, treeChildIn
dex); | 421 treeElement.insertChild(existingTreeElement, treeChildIn
dex); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 407 | 436 |
| 408 // Remove any tree elements that no longer have this node (or this node'
s contentDocument) as their parent. | 437 // Remove any tree elements that no longer have this node (or this node'
s contentDocument) as their parent. |
| 409 for (var i = (this.children.length - 1); i >= 0; --i) { | 438 for (var i = (this.children.length - 1); i >= 0; --i) { |
| 410 if ("elementCloseTag" in this.children[i]) | 439 if ("elementCloseTag" in this.children[i]) |
| 411 continue; | 440 continue; |
| 412 | 441 |
| 413 var currentChild = this.children[i]; | 442 var currentChild = this.children[i]; |
| 414 var currentNode = currentChild.representedObject; | 443 var currentNode = currentChild.representedObject; |
| 415 var currentParentNode = currentNode.parentNode; | 444 var currentParentNode = currentNode.parentNode; |
| 416 | 445 |
| 417 if (objectsAreSame(currentParentNode, this.representedObject)) | 446 if (currentParentNode === this.representedObject) |
| 418 continue; | |
| 419 if (this.representedObject.contentDocument && objectsAreSame(current
ParentNode, this.representedObject.contentDocument)) | |
| 420 continue; | 447 continue; |
| 421 | 448 |
| 422 var selectedTreeElement = this.treeOutline.selectedTreeElement; | 449 var selectedTreeElement = this.treeOutline.selectedTreeElement; |
| 423 if (selectedTreeElement && (selectedTreeElement === currentChild ||
selectedTreeElement.hasAncestor(currentChild))) | 450 if (selectedTreeElement && (selectedTreeElement === currentChild ||
selectedTreeElement.hasAncestor(currentChild))) |
| 424 this.select(); | 451 this.select(); |
| 425 | 452 |
| 426 this.removeChildAtIndex(i); | 453 this.removeChildAtIndex(i); |
| 427 | |
| 428 if (this.treeOutline.panel && currentNode.contentDocument) | |
| 429 this.treeOutline.panel.unregisterMutationEventListeners(currentN
ode.contentDocument.defaultView); | |
| 430 } | 454 } |
| 431 | 455 |
| 432 if (this.representedObject.contentDocument) | |
| 433 updateChildrenOfNode(this.representedObject.contentDocument); | |
| 434 updateChildrenOfNode(this.representedObject); | 456 updateChildrenOfNode(this.representedObject); |
| 435 | 457 |
| 436 var lastChild = this.children[this.children.length - 1]; | 458 var lastChild = this.children[this.children.length - 1]; |
| 437 if (this.representedObject.nodeType == Node.ELEMENT_NODE && (!lastChild
|| !lastChild.elementCloseTag)) { | 459 if (this.representedObject.nodeType == Node.ELEMENT_NODE && (!lastChild
|| !lastChild.elementCloseTag)) { |
| 438 var title = "<span class=\"webkit-html-tag close\"></" + this.rep
resentedObject.nodeName.toLowerCase().escapeHTML() + "></span>"; | 460 var title = "<span class=\"webkit-html-tag close\"></" + this.rep
resentedObject.nodeName.toLowerCase().escapeHTML() + "></span>"; |
| 439 var item = new TreeElement(title, null, false); | 461 var item = new TreeElement(title, null, false); |
| 440 item.selectable = false; | 462 item.selectable = false; |
| 441 item.elementCloseTag = true; | 463 item.elementCloseTag = true; |
| 442 this.appendChild(item); | 464 this.appendChild(item); |
| 443 } | 465 } |
| 444 }, | 466 }, |
| 445 | 467 |
| 446 onexpand: function() | 468 onexpand: function() |
| 447 { | 469 { |
| 448 this.treeOutline.updateSelection(); | 470 this.treeOutline.updateSelection(); |
| 449 | |
| 450 if (this.treeOutline.panel && this.representedObject.contentDocument) | |
| 451 this.treeOutline.panel.registerMutationEventListeners(this.represent
edObject.contentDocument.defaultView); | |
| 452 }, | 471 }, |
| 453 | 472 |
| 454 oncollapse: function() | 473 oncollapse: function() |
| 455 { | 474 { |
| 456 this.treeOutline.updateSelection(); | 475 this.treeOutline.updateSelection(); |
| 457 }, | 476 }, |
| 458 | 477 |
| 459 onreveal: function() | 478 onreveal: function() |
| 460 { | 479 { |
| 461 if (this.listItemElement) | 480 if (this.listItemElement) |
| (...skipping 14 matching lines...) Expand all Loading... |
| 476 // Prevent selecting the nearest word on double click. | 495 // Prevent selecting the nearest word on double click. |
| 477 if (event.detail >= 2) | 496 if (event.detail >= 2) |
| 478 event.preventDefault(); | 497 event.preventDefault(); |
| 479 }, | 498 }, |
| 480 | 499 |
| 481 ondblclick: function(treeElement, event) | 500 ondblclick: function(treeElement, event) |
| 482 { | 501 { |
| 483 if (this._editing) | 502 if (this._editing) |
| 484 return; | 503 return; |
| 485 | 504 |
| 486 if (this._startEditing(event)) | 505 if (this._startEditing(event, treeElement)) |
| 487 return; | 506 return; |
| 488 | 507 |
| 489 if (this.treeOutline.panel) { | 508 if (this.treeOutline.panel) { |
| 490 this.treeOutline.rootDOMNode = this.parent.representedObject; | 509 this.treeOutline.rootDOMNode = this.representedObject.parentNode; |
| 491 this.treeOutline.focusedDOMNode = this.representedObject; | 510 this.treeOutline.focusedDOMNode = this.representedObject; |
| 492 } | 511 } |
| 493 | 512 |
| 494 if (this.hasChildren && !this.expanded) | 513 if (this.hasChildren && !this.expanded) |
| 495 this.expand(); | 514 this.expand(); |
| 496 }, | 515 }, |
| 497 | 516 |
| 498 _startEditing: function(event) | 517 _insertInLastAttributePosition: function(tag, node) |
| 518 { |
| 519 if (tag.getElementsByClassName("webkit-html-attribute").length > 0) |
| 520 tag.insertBefore(node, tag.lastChild); |
| 521 else { |
| 522 var nodeName = tag.textContent.match(/^<(.*?)>$/)[1]; |
| 523 tag.textContent = ''; |
| 524 tag.appendChild(document.createTextNode('<'+nodeName)); |
| 525 tag.appendChild(node); |
| 526 tag.appendChild(document.createTextNode('>')); |
| 527 } |
| 528 }, |
| 529 |
| 530 _startEditing: function(event, treeElement) |
| 499 { | 531 { |
| 500 if (this.treeOutline.focusedDOMNode != this.representedObject) | 532 if (this.treeOutline.focusedDOMNode != this.representedObject) |
| 501 return; | 533 return; |
| 502 | 534 |
| 503 if (this.representedObject.nodeType != Node.ELEMENT_NODE && this.represe
ntedObject.nodeType != Node.TEXT_NODE) | 535 if (this.representedObject.nodeType != Node.ELEMENT_NODE && this.represe
ntedObject.nodeType != Node.TEXT_NODE) |
| 504 return false; | 536 return false; |
| 505 | 537 |
| 506 var textNode = event.target.enclosingNodeOrSelfWithClass("webkit-html-te
xt-node"); | 538 var textNode = event.target.enclosingNodeOrSelfWithClass("webkit-html-te
xt-node"); |
| 507 if (textNode) | 539 if (textNode) |
| 508 return this._startEditingTextNode(textNode); | 540 return this._startEditingTextNode(textNode); |
| 509 | 541 |
| 510 var attribute = event.target.enclosingNodeOrSelfWithClass("webkit-html-a
ttribute"); | 542 var attribute = event.target.enclosingNodeOrSelfWithClass("webkit-html-a
ttribute"); |
| 511 if (attribute) | 543 if (attribute) |
| 512 return this._startEditingAttribute(attribute, event); | 544 return this._startEditingAttribute(attribute, event.target); |
| 545 |
| 546 var newAttribute = event.target.enclosingNodeOrSelfWithClass("add-attrib
ute"); |
| 547 if (newAttribute) |
| 548 return this._addNewAttribute(treeElement.listItemElement); |
| 513 | 549 |
| 514 return false; | 550 return false; |
| 515 }, | 551 }, |
| 516 | 552 |
| 517 _startEditingAttribute: function(attribute, event) | 553 _addNewAttribute: function(listItemElement) |
| 554 { |
| 555 var attr = document.createElement("span"); |
| 556 attr.className = "webkit-html-attribute"; |
| 557 attr.style.marginLeft = "2px"; // overrides the .editing margin rule |
| 558 attr.style.marginRight = "2px"; // overrides the .editing margin rule |
| 559 var name = document.createElement("span"); |
| 560 name.className = "webkit-html-attribute-name new-attribute"; |
| 561 name.textContent = " "; |
| 562 var value = document.createElement("span"); |
| 563 value.className = "webkit-html-attribute-value"; |
| 564 attr.appendChild(name); |
| 565 attr.appendChild(value); |
| 566 |
| 567 var tag = listItemElement.getElementsByClassName("webkit-html-tag")[0]; |
| 568 this._insertInLastAttributePosition(tag, attr); |
| 569 return this._startEditingAttribute(attr, attr); |
| 570 }, |
| 571 |
| 572 _triggerEditAttribute: function(attributeName) |
| 573 { |
| 574 var attributeElements = this.listItemElement.getElementsByClassName("web
kit-html-attribute-name"); |
| 575 for (var i = 0, len = attributeElements.length; i < len; ++i) { |
| 576 if (attributeElements[i].textContent === attributeName) { |
| 577 for (var elem = attributeElements[i].nextSibling; elem; elem = e
lem.nextSibling) { |
| 578 if (elem.nodeType !== Node.ELEMENT_NODE) |
| 579 continue; |
| 580 |
| 581 if (elem.hasStyleClass("webkit-html-attribute-value")) |
| 582 return this._startEditingAttribute(attributeElements[i].
parentNode, elem); |
| 583 } |
| 584 } |
| 585 } |
| 586 }, |
| 587 |
| 588 _startEditingAttribute: function(attribute, elementForSelection) |
| 518 { | 589 { |
| 519 if (WebInspector.isBeingEdited(attribute)) | 590 if (WebInspector.isBeingEdited(attribute)) |
| 520 return true; | 591 return true; |
| 521 | 592 |
| 522 var attributeNameElement = attribute.getElementsByClassName("webkit-html
-attribute-name")[0]; | 593 var attributeNameElement = attribute.getElementsByClassName("webkit-html
-attribute-name")[0]; |
| 523 if (!attributeNameElement) | 594 if (!attributeNameElement) |
| 524 return false; | 595 return false; |
| 525 | 596 |
| 526 var attributeName = attributeNameElement.innerText; | 597 var attributeName = attributeNameElement.innerText; |
| 527 | 598 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 538 for (var child = node.firstChild; child; child = child.nextSibling) | 609 for (var child = node.firstChild; child; child = child.nextSibling) |
| 539 removeZeroWidthSpaceRecursive(child); | 610 removeZeroWidthSpaceRecursive(child); |
| 540 } | 611 } |
| 541 | 612 |
| 542 // Remove zero-width spaces that were added by nodeTitleInfo. | 613 // Remove zero-width spaces that were added by nodeTitleInfo. |
| 543 removeZeroWidthSpaceRecursive(attribute); | 614 removeZeroWidthSpaceRecursive(attribute); |
| 544 | 615 |
| 545 this._editing = true; | 616 this._editing = true; |
| 546 | 617 |
| 547 WebInspector.startEditing(attribute, this._attributeEditingCommitted.bin
d(this), this._editingCancelled.bind(this), attributeName); | 618 WebInspector.startEditing(attribute, this._attributeEditingCommitted.bin
d(this), this._editingCancelled.bind(this), attributeName); |
| 548 window.getSelection().setBaseAndExtent(event.target, 0, event.target, 1)
; | 619 window.getSelection().setBaseAndExtent(elementForSelection, 0, elementFo
rSelection, 1); |
| 549 | 620 |
| 550 return true; | 621 return true; |
| 551 }, | 622 }, |
| 552 | 623 |
| 553 _startEditingTextNode: function(textNode) | 624 _startEditingTextNode: function(textNode) |
| 554 { | 625 { |
| 555 if (WebInspector.isBeingEdited(textNode)) | 626 if (WebInspector.isBeingEdited(textNode)) |
| 556 return true; | 627 return true; |
| 557 | 628 |
| 558 this._editing = true; | 629 this._editing = true; |
| 559 | 630 |
| 560 WebInspector.startEditing(textNode, this._textNodeEditingCommitted.bind(
this), this._editingCancelled.bind(this)); | 631 WebInspector.startEditing(textNode, this._textNodeEditingCommitted.bind(
this), this._editingCancelled.bind(this)); |
| 561 window.getSelection().setBaseAndExtent(textNode, 0, textNode, 1); | 632 window.getSelection().setBaseAndExtent(textNode, 0, textNode, 1); |
| 562 | 633 |
| 563 return true; | 634 return true; |
| 564 }, | 635 }, |
| 565 | 636 |
| 566 _attributeEditingCommitted: function(element, newText, oldText, attributeNam
e) | 637 _attributeEditingCommitted: function(element, newText, oldText, attributeNam
e, moveDirection) |
| 567 { | 638 { |
| 568 delete this._editing; | 639 delete this._editing; |
| 569 | 640 |
| 641 // Before we do anything, determine where we should move |
| 642 // next based on the current element's settings |
| 643 var moveToAttribute; |
| 644 var newAttribute; |
| 645 if (moveDirection) { |
| 646 var found = false; |
| 647 var attributes = this.representedObject.attributes; |
| 648 for (var i = 0, len = attributes.length; i < len; ++i) { |
| 649 if (attributes[i].name === attributeName) { |
| 650 found = true; |
| 651 if (moveDirection === "backward" && i > 0) |
| 652 moveToAttribute = attributes[i - 1].name; |
| 653 else if (moveDirection === "forward" && i < attributes.lengt
h - 1) |
| 654 moveToAttribute = attributes[i + 1].name; |
| 655 else if (moveDirection === "forward" && i === attributes.len
gth - 1) |
| 656 newAttribute = true; |
| 657 } |
| 658 } |
| 659 |
| 660 if (!found && moveDirection === "backward") |
| 661 moveToAttribute = attributes[attributes.length - 1].name; |
| 662 else if (!found && moveDirection === "forward" && !/^\s*$/.test(newT
ext)) |
| 663 newAttribute = true; |
| 664 } |
| 665 |
| 666 function moveToNextAttributeIfNeeded() { |
| 667 if (moveToAttribute) |
| 668 this._triggerEditAttribute(moveToAttribute); |
| 669 else if (newAttribute) |
| 670 this._addNewAttribute(this.listItemElement); |
| 671 } |
| 672 |
| 570 var parseContainerElement = document.createElement("span"); | 673 var parseContainerElement = document.createElement("span"); |
| 571 parseContainerElement.innerHTML = "<span " + newText + "></span>"; | 674 parseContainerElement.innerHTML = "<span " + newText + "></span>"; |
| 572 var parseElement = parseContainerElement.firstChild; | 675 var parseElement = parseContainerElement.firstChild; |
| 573 if (!parseElement || !parseElement.hasAttributes()) { | 676 |
| 574 this._editingCancelled(element, context); | 677 if (!parseElement) { |
| 678 this._editingCancelled(element, attributeName); |
| 679 moveToNextAttributeIfNeeded.call(this); |
| 575 return; | 680 return; |
| 576 } | 681 } |
| 577 | 682 |
| 683 if (!parseElement.hasAttributes()) { |
| 684 this.representedObject.removeAttribute(attributeName); |
| 685 this._updateTitle(); |
| 686 moveToNextAttributeIfNeeded.call(this); |
| 687 return; |
| 688 } |
| 689 |
| 578 var foundOriginalAttribute = false; | 690 var foundOriginalAttribute = false; |
| 579 for (var i = 0; i < parseElement.attributes.length; ++i) { | 691 for (var i = 0; i < parseElement.attributes.length; ++i) { |
| 580 var attr = parseElement.attributes[i]; | 692 var attr = parseElement.attributes[i]; |
| 581 foundOriginalAttribute = foundOriginalAttribute || attr.name === att
ributeName; | 693 foundOriginalAttribute = foundOriginalAttribute || attr.name === att
ributeName; |
| 582 InspectorController.inspectedWindow().Element.prototype.setAttribute
.call(this.representedObject, attr.name, attr.value); | 694 try { |
| 695 this.representedObject.setAttribute(attr.name, attr.value); |
| 696 } catch(e) {} // ignore invalid attribute (innerHTML doesn't throw e
rrors, but this can) |
| 583 } | 697 } |
| 584 | 698 |
| 585 if (!foundOriginalAttribute) | 699 if (!foundOriginalAttribute) |
| 586 InspectorController.inspectedWindow().Element.prototype.removeAttrib
ute.call(this.representedObject, attributeName); | 700 this.representedObject.removeAttribute(attributeName); |
| 587 | 701 |
| 588 this._updateTitle(); | 702 this._updateTitle(); |
| 589 | 703 |
| 590 this.treeOutline.focusedNodeChanged(true); | 704 this.treeOutline.focusedNodeChanged(true); |
| 705 |
| 706 moveToNextAttributeIfNeeded.call(this); |
| 591 }, | 707 }, |
| 592 | 708 |
| 593 _textNodeEditingCommitted: function(element, newText) | 709 _textNodeEditingCommitted: function(element, newText) |
| 594 { | 710 { |
| 595 delete this._editing; | 711 delete this._editing; |
| 596 | 712 |
| 597 var textNode; | 713 var textNode; |
| 598 if (this.representedObject.nodeType == Node.ELEMENT_NODE) { | 714 if (this.representedObject.nodeType == Node.ELEMENT_NODE) { |
| 599 // We only show text nodes inline in elements if the element only | 715 // We only show text nodes inline in elements if the element only |
| 600 // has a single child, and that child is a text node. | 716 // has a single child, and that child is a text node. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 617 { | 733 { |
| 618 var title = nodeTitleInfo.call(this.representedObject, this.hasChildren,
WebInspector.linkifyURL).title; | 734 var title = nodeTitleInfo.call(this.representedObject, this.hasChildren,
WebInspector.linkifyURL).title; |
| 619 this.title = "<span class=\"highlight\">" + title + "</span>"; | 735 this.title = "<span class=\"highlight\">" + title + "</span>"; |
| 620 delete this.selectionElement; | 736 delete this.selectionElement; |
| 621 this.updateSelection(); | 737 this.updateSelection(); |
| 622 this._preventFollowingLinksOnDoubleClick(); | 738 this._preventFollowingLinksOnDoubleClick(); |
| 623 }, | 739 }, |
| 624 } | 740 } |
| 625 | 741 |
| 626 WebInspector.ElementsTreeElement.prototype.__proto__ = TreeElement.prototype; | 742 WebInspector.ElementsTreeElement.prototype.__proto__ = TreeElement.prototype; |
| OLD | NEW |