| Index: chrome/tools/test/reference_build/chrome_linux/resources/inspector/ElementsTreeOutline.js
|
| diff --git a/chrome/tools/test/reference_build/chrome_linux/resources/inspector/ElementsTreeOutline.js b/chrome/tools/test/reference_build/chrome_linux/resources/inspector/ElementsTreeOutline.js
|
| index 822bf35f738f7bca680592e659b0903b2aef7fac..a55547f87ee945f8a0a3aa0fbef17571aa43cbc9 100644
|
| --- a/chrome/tools/test/reference_build/chrome_linux/resources/inspector/ElementsTreeOutline.js
|
| +++ b/chrome/tools/test/reference_build/chrome_linux/resources/inspector/ElementsTreeOutline.js
|
| @@ -1,6 +1,7 @@
|
| /*
|
| * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
|
| * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
|
| + * Copyright (C) 2009 Joseph Pecoraro
|
| *
|
| * Redistribution and use in source and binary forms, with or without
|
| * modification, are permitted provided that the following conditions
|
| @@ -50,7 +51,7 @@ WebInspector.ElementsTreeOutline.prototype = {
|
|
|
| set rootDOMNode(x)
|
| {
|
| - if (objectsAreSame(this._rootDOMNode, x))
|
| + if (this._rootDOMNode === x)
|
| return;
|
|
|
| this._rootDOMNode = x;
|
| @@ -65,7 +66,7 @@ WebInspector.ElementsTreeOutline.prototype = {
|
|
|
| set focusedDOMNode(x)
|
| {
|
| - if (objectsAreSame(this._focusedDOMNode, x)) {
|
| + if (this._focusedDOMNode === x) {
|
| this.revealAndSelectNode(x);
|
| return;
|
| }
|
| @@ -78,11 +79,11 @@ WebInspector.ElementsTreeOutline.prototype = {
|
| // and the select() call would change the focusedDOMNode and reenter this setter. So to
|
| // avoid calling focusedNodeChanged() twice, first check if _focusedDOMNode is the same
|
| // node as the one passed in.
|
| - if (objectsAreSame(this._focusedDOMNode, x)) {
|
| + if (this._focusedDOMNode === x) {
|
| this.focusedNodeChanged();
|
|
|
| if (x && !this.suppressSelectHighlight) {
|
| - InspectorController.highlightDOMNode(x);
|
| + InspectorController.highlightDOMNode(x.id);
|
|
|
| if ("_restorePreviousHighlightNodeTimeout" in this)
|
| clearTimeout(this._restorePreviousHighlightNodeTimeout);
|
| @@ -91,7 +92,7 @@ WebInspector.ElementsTreeOutline.prototype = {
|
| {
|
| var hoveredNode = WebInspector.hoveredDOMNode;
|
| if (hoveredNode)
|
| - InspectorController.highlightDOMNode(hoveredNode);
|
| + InspectorController.highlightDOMNode(hoveredNode.id);
|
| else
|
| InspectorController.hideDOMNodeHighlight();
|
| }
|
| @@ -137,19 +138,12 @@ WebInspector.ElementsTreeOutline.prototype = {
|
|
|
| focusedNodeChanged: function(forceUpdate) {},
|
|
|
| - findTreeElement: function(node, isAncestor, getParent, equal)
|
| + findTreeElement: function(node)
|
| {
|
| - if (typeof isAncestor === "undefined")
|
| - isAncestor = isAncestorIncludingParentFrames;
|
| - if (typeof getParent === "undefined")
|
| - getParent = parentNodeOrFrameElement;
|
| - if (typeof equal === "undefined")
|
| - equal = objectsAreSame;
|
| -
|
| - var treeElement = TreeOutline.prototype.findTreeElement.call(this, node, isAncestor, getParent, equal);
|
| + var treeElement = TreeOutline.prototype.findTreeElement.call(this, node, isAncestorNode, parentNode);
|
| if (!treeElement && node.nodeType === Node.TEXT_NODE) {
|
| // The text node might have been inlined if it was short, so try to find the parent element.
|
| - treeElement = TreeOutline.prototype.findTreeElement.call(this, node.parentNode, isAncestor, getParent, equal);
|
| + treeElement = TreeOutline.prototype.findTreeElement.call(this, node.parentNode, isAncestorNode, parentNode);
|
| }
|
|
|
| return treeElement;
|
| @@ -247,7 +241,7 @@ WebInspector.ElementsTreeOutline.prototype.__proto__ = TreeOutline.prototype;
|
|
|
| WebInspector.ElementsTreeElement = function(node)
|
| {
|
| - var hasChildren = node.contentDocument || (Preferences.ignoreWhitespace ? (firstChildSkippingWhitespace.call(node) ? true : false) : node.hasChildNodes());
|
| + var hasChildren = Preferences.ignoreWhitespace ? (firstChildSkippingWhitespace.call(node) ? true : false) : node.hasChildNodes();
|
| var titleInfo = nodeTitleInfo.call(node, hasChildren, WebInspector.linkifyURL);
|
|
|
| if (titleInfo.hasChildren)
|
| @@ -255,6 +249,9 @@ WebInspector.ElementsTreeElement = function(node)
|
|
|
| // The title will be updated in onattach.
|
| TreeElement.call(this, "", node, titleInfo.hasChildren);
|
| +
|
| + if (this.representedObject.nodeType == Node.ELEMENT_NODE)
|
| + this._canAddAttributes = true;
|
| }
|
|
|
| WebInspector.ElementsTreeElement.prototype = {
|
| @@ -296,9 +293,36 @@ WebInspector.ElementsTreeElement.prototype = {
|
| this.listItemElement.addStyleClass("hovered");
|
| } else
|
| this.listItemElement.removeStyleClass("hovered");
|
| + if (this._canAddAttributes)
|
| + this.toggleNewAttributeButton();
|
| }
|
| },
|
|
|
| + toggleNewAttributeButton: function()
|
| + {
|
| + function removeWhenEditing(event)
|
| + {
|
| + if (this._addAttributeElement && this._addAttributeElement.parentNode)
|
| + this._addAttributeElement.parentNode.removeChild(this._addAttributeElement);
|
| + delete this._addAttributeElement;
|
| + }
|
| +
|
| + if (!this._addAttributeElement && this._hovered && !this._editing) {
|
| + var span = document.createElement("span");
|
| + span.className = "add-attribute";
|
| + span.textContent = "\u2026";
|
| + span.addEventListener("dblclick", removeWhenEditing.bind(this), false);
|
| + this._addAttributeElement = span;
|
| +
|
| + var tag = this.listItemElement.getElementsByClassName("webkit-html-tag")[0];
|
| + this._insertInLastAttributePosition(tag, span);
|
| + } else if (!this._hovered && this._addAttributeElement) {
|
| + if (this._addAttributeElement.parentNode)
|
| + this._addAttributeElement.parentNode.removeChild(this._addAttributeElement);
|
| + delete this._addAttributeElement;
|
| + }
|
| + },
|
| +
|
| updateSelection: function()
|
| {
|
| var listItemElement = this.listItemElement;
|
| @@ -356,9 +380,14 @@ WebInspector.ElementsTreeElement.prototype = {
|
|
|
| this.updateChildren();
|
| },
|
| -
|
| +
|
| updateChildren: function(fullRefresh)
|
| {
|
| + WebInspector.domAgent.getChildNodesAsync(this.representedObject, this._updateChildren.bind(this, fullRefresh));
|
| + },
|
| +
|
| + _updateChildren: function(fullRefresh)
|
| + {
|
| if (fullRefresh) {
|
| var selectedTreeElement = this.treeOutline.selectedTreeElement;
|
| if (selectedTreeElement && selectedTreeElement.hasAncestor(this))
|
| @@ -375,11 +404,11 @@ WebInspector.ElementsTreeElement.prototype = {
|
| var child = (Preferences.ignoreWhitespace ? firstChildSkippingWhitespace.call(node) : node.firstChild);
|
| while (child) {
|
| var currentTreeElement = treeElement.children[treeChildIndex];
|
| - if (!currentTreeElement || !objectsAreSame(currentTreeElement.representedObject, child)) {
|
| + if (!currentTreeElement || currentTreeElement.representedObject !== child) {
|
| // Find any existing element that is later in the children list.
|
| var existingTreeElement = null;
|
| for (var i = (treeChildIndex + 1); i < treeElement.children.length; ++i) {
|
| - if (objectsAreSame(treeElement.children[i].representedObject, child)) {
|
| + if (treeElement.children[i].representedObject === child) {
|
| existingTreeElement = treeElement.children[i];
|
| break;
|
| }
|
| @@ -414,9 +443,7 @@ WebInspector.ElementsTreeElement.prototype = {
|
| var currentNode = currentChild.representedObject;
|
| var currentParentNode = currentNode.parentNode;
|
|
|
| - if (objectsAreSame(currentParentNode, this.representedObject))
|
| - continue;
|
| - if (this.representedObject.contentDocument && objectsAreSame(currentParentNode, this.representedObject.contentDocument))
|
| + if (currentParentNode === this.representedObject)
|
| continue;
|
|
|
| var selectedTreeElement = this.treeOutline.selectedTreeElement;
|
| @@ -424,13 +451,8 @@ WebInspector.ElementsTreeElement.prototype = {
|
| this.select();
|
|
|
| this.removeChildAtIndex(i);
|
| -
|
| - if (this.treeOutline.panel && currentNode.contentDocument)
|
| - this.treeOutline.panel.unregisterMutationEventListeners(currentNode.contentDocument.defaultView);
|
| }
|
|
|
| - if (this.representedObject.contentDocument)
|
| - updateChildrenOfNode(this.representedObject.contentDocument);
|
| updateChildrenOfNode(this.representedObject);
|
|
|
| var lastChild = this.children[this.children.length - 1];
|
| @@ -446,9 +468,6 @@ WebInspector.ElementsTreeElement.prototype = {
|
| onexpand: function()
|
| {
|
| this.treeOutline.updateSelection();
|
| -
|
| - if (this.treeOutline.panel && this.representedObject.contentDocument)
|
| - this.treeOutline.panel.registerMutationEventListeners(this.representedObject.contentDocument.defaultView);
|
| },
|
|
|
| oncollapse: function()
|
| @@ -483,11 +502,11 @@ WebInspector.ElementsTreeElement.prototype = {
|
| if (this._editing)
|
| return;
|
|
|
| - if (this._startEditing(event))
|
| + if (this._startEditing(event, treeElement))
|
| return;
|
|
|
| if (this.treeOutline.panel) {
|
| - this.treeOutline.rootDOMNode = this.parent.representedObject;
|
| + this.treeOutline.rootDOMNode = this.representedObject.parentNode;
|
| this.treeOutline.focusedDOMNode = this.representedObject;
|
| }
|
|
|
| @@ -495,7 +514,20 @@ WebInspector.ElementsTreeElement.prototype = {
|
| this.expand();
|
| },
|
|
|
| - _startEditing: function(event)
|
| + _insertInLastAttributePosition: function(tag, node)
|
| + {
|
| + if (tag.getElementsByClassName("webkit-html-attribute").length > 0)
|
| + tag.insertBefore(node, tag.lastChild);
|
| + else {
|
| + var nodeName = tag.textContent.match(/^<(.*?)>$/)[1];
|
| + tag.textContent = '';
|
| + tag.appendChild(document.createTextNode('<'+nodeName));
|
| + tag.appendChild(node);
|
| + tag.appendChild(document.createTextNode('>'));
|
| + }
|
| + },
|
| +
|
| + _startEditing: function(event, treeElement)
|
| {
|
| if (this.treeOutline.focusedDOMNode != this.representedObject)
|
| return;
|
| @@ -509,12 +541,51 @@ WebInspector.ElementsTreeElement.prototype = {
|
|
|
| var attribute = event.target.enclosingNodeOrSelfWithClass("webkit-html-attribute");
|
| if (attribute)
|
| - return this._startEditingAttribute(attribute, event);
|
| + return this._startEditingAttribute(attribute, event.target);
|
| +
|
| + var newAttribute = event.target.enclosingNodeOrSelfWithClass("add-attribute");
|
| + if (newAttribute)
|
| + return this._addNewAttribute(treeElement.listItemElement);
|
|
|
| return false;
|
| },
|
|
|
| - _startEditingAttribute: function(attribute, event)
|
| + _addNewAttribute: function(listItemElement)
|
| + {
|
| + var attr = document.createElement("span");
|
| + attr.className = "webkit-html-attribute";
|
| + attr.style.marginLeft = "2px"; // overrides the .editing margin rule
|
| + attr.style.marginRight = "2px"; // overrides the .editing margin rule
|
| + var name = document.createElement("span");
|
| + name.className = "webkit-html-attribute-name new-attribute";
|
| + name.textContent = " ";
|
| + var value = document.createElement("span");
|
| + value.className = "webkit-html-attribute-value";
|
| + attr.appendChild(name);
|
| + attr.appendChild(value);
|
| +
|
| + var tag = listItemElement.getElementsByClassName("webkit-html-tag")[0];
|
| + this._insertInLastAttributePosition(tag, attr);
|
| + return this._startEditingAttribute(attr, attr);
|
| + },
|
| +
|
| + _triggerEditAttribute: function(attributeName)
|
| + {
|
| + var attributeElements = this.listItemElement.getElementsByClassName("webkit-html-attribute-name");
|
| + for (var i = 0, len = attributeElements.length; i < len; ++i) {
|
| + if (attributeElements[i].textContent === attributeName) {
|
| + for (var elem = attributeElements[i].nextSibling; elem; elem = elem.nextSibling) {
|
| + if (elem.nodeType !== Node.ELEMENT_NODE)
|
| + continue;
|
| +
|
| + if (elem.hasStyleClass("webkit-html-attribute-value"))
|
| + return this._startEditingAttribute(attributeElements[i].parentNode, elem);
|
| + }
|
| + }
|
| + }
|
| + },
|
| +
|
| + _startEditingAttribute: function(attribute, elementForSelection)
|
| {
|
| if (WebInspector.isBeingEdited(attribute))
|
| return true;
|
| @@ -545,7 +616,7 @@ WebInspector.ElementsTreeElement.prototype = {
|
| this._editing = true;
|
|
|
| WebInspector.startEditing(attribute, this._attributeEditingCommitted.bind(this), this._editingCancelled.bind(this), attributeName);
|
| - window.getSelection().setBaseAndExtent(event.target, 0, event.target, 1);
|
| + window.getSelection().setBaseAndExtent(elementForSelection, 0, elementForSelection, 1);
|
|
|
| return true;
|
| },
|
| @@ -563,15 +634,56 @@ WebInspector.ElementsTreeElement.prototype = {
|
| return true;
|
| },
|
|
|
| - _attributeEditingCommitted: function(element, newText, oldText, attributeName)
|
| + _attributeEditingCommitted: function(element, newText, oldText, attributeName, moveDirection)
|
| {
|
| delete this._editing;
|
|
|
| + // Before we do anything, determine where we should move
|
| + // next based on the current element's settings
|
| + var moveToAttribute;
|
| + var newAttribute;
|
| + if (moveDirection) {
|
| + var found = false;
|
| + var attributes = this.representedObject.attributes;
|
| + for (var i = 0, len = attributes.length; i < len; ++i) {
|
| + if (attributes[i].name === attributeName) {
|
| + found = true;
|
| + if (moveDirection === "backward" && i > 0)
|
| + moveToAttribute = attributes[i - 1].name;
|
| + else if (moveDirection === "forward" && i < attributes.length - 1)
|
| + moveToAttribute = attributes[i + 1].name;
|
| + else if (moveDirection === "forward" && i === attributes.length - 1)
|
| + newAttribute = true;
|
| + }
|
| + }
|
| +
|
| + if (!found && moveDirection === "backward")
|
| + moveToAttribute = attributes[attributes.length - 1].name;
|
| + else if (!found && moveDirection === "forward" && !/^\s*$/.test(newText))
|
| + newAttribute = true;
|
| + }
|
| +
|
| + function moveToNextAttributeIfNeeded() {
|
| + if (moveToAttribute)
|
| + this._triggerEditAttribute(moveToAttribute);
|
| + else if (newAttribute)
|
| + this._addNewAttribute(this.listItemElement);
|
| + }
|
| +
|
| var parseContainerElement = document.createElement("span");
|
| parseContainerElement.innerHTML = "<span " + newText + "></span>";
|
| var parseElement = parseContainerElement.firstChild;
|
| - if (!parseElement || !parseElement.hasAttributes()) {
|
| - this._editingCancelled(element, context);
|
| +
|
| + if (!parseElement) {
|
| + this._editingCancelled(element, attributeName);
|
| + moveToNextAttributeIfNeeded.call(this);
|
| + return;
|
| + }
|
| +
|
| + if (!parseElement.hasAttributes()) {
|
| + this.representedObject.removeAttribute(attributeName);
|
| + this._updateTitle();
|
| + moveToNextAttributeIfNeeded.call(this);
|
| return;
|
| }
|
|
|
| @@ -579,15 +691,19 @@ WebInspector.ElementsTreeElement.prototype = {
|
| for (var i = 0; i < parseElement.attributes.length; ++i) {
|
| var attr = parseElement.attributes[i];
|
| foundOriginalAttribute = foundOriginalAttribute || attr.name === attributeName;
|
| - InspectorController.inspectedWindow().Element.prototype.setAttribute.call(this.representedObject, attr.name, attr.value);
|
| + try {
|
| + this.representedObject.setAttribute(attr.name, attr.value);
|
| + } catch(e) {} // ignore invalid attribute (innerHTML doesn't throw errors, but this can)
|
| }
|
|
|
| if (!foundOriginalAttribute)
|
| - InspectorController.inspectedWindow().Element.prototype.removeAttribute.call(this.representedObject, attributeName);
|
| + this.representedObject.removeAttribute(attributeName);
|
|
|
| this._updateTitle();
|
|
|
| this.treeOutline.focusedNodeChanged(true);
|
| +
|
| + moveToNextAttributeIfNeeded.call(this);
|
| },
|
|
|
| _textNodeEditingCommitted: function(element, newText)
|
|
|