Chromium Code Reviews| Index: Source/devtools/front_end/elements/ElementsTreeOutline.js |
| diff --git a/Source/devtools/front_end/elements/ElementsTreeOutline.js b/Source/devtools/front_end/elements/ElementsTreeOutline.js |
| index c5e2d6f8f3eff068f09bcb413942338cdb083757..1ad9d011bcb06da51ffef765b0237b8812a7a16f 100644 |
| --- a/Source/devtools/front_end/elements/ElementsTreeOutline.js |
| +++ b/Source/devtools/front_end/elements/ElementsTreeOutline.js |
| @@ -1018,8 +1018,9 @@ WebInspector.ElementsTreeOutline.PseudoStateDecorator.prototype = { |
| * @extends {TreeElement} |
| * @param {!WebInspector.DOMNode} node |
| * @param {boolean=} elementCloseTag |
| + * @param {boolean=} isUpdated |
| */ |
| -WebInspector.ElementsTreeElement = function(node, elementCloseTag) |
| +WebInspector.ElementsTreeElement = function(node, elementCloseTag, isUpdated) |
| { |
| // The title will be updated in onattach. |
| TreeElement.call(this, "", node); |
| @@ -1030,6 +1031,7 @@ WebInspector.ElementsTreeElement = function(node, elementCloseTag) |
| if (this._node.nodeType() == Node.ELEMENT_NODE && !elementCloseTag) |
| this._canAddAttributes = true; |
| + this._isUpdated = isUpdated; |
| this._searchQuery = null; |
| this._expandedChildrenLimit = WebInspector.ElementsTreeElement.InitialChildrenLimit; |
| } |
| @@ -1151,7 +1153,7 @@ WebInspector.ElementsTreeElement.prototype = { |
| this._expandedChildrenLimit = x; |
| if (this.treeOutline && !this._updateChildrenInProgress) |
| - this._updateChildren(true, this.children); |
| + this._updateChildren(true, undefined, this.children); |
| }, |
| get expandedChildCount() |
| @@ -1179,7 +1181,7 @@ WebInspector.ElementsTreeElement.prototype = { |
| if (index >= this.expandedChildrenLimit) { |
| this._expandedChildrenLimit = index + 1; |
| - this._updateChildren(true, this.children); |
| + this._updateChildren(true, undefined, this.children); |
| } |
| // Whether index-th child is visible in the children tree |
| @@ -1244,24 +1246,26 @@ WebInspector.ElementsTreeElement.prototype = { |
| /** |
| * @param {boolean=} fullRefresh |
| + * @param {!WebInspector.ElementsTreeUpdater.Record=} updates |
| */ |
| - updateChildren: function(fullRefresh) |
| + updateChildren: function(fullRefresh, updates) |
| { |
| if (!this.hasChildren) |
| return; |
| console.assert(!this._elementCloseTag); |
| - this._node.getChildNodes(this._updateChildren.bind(this, fullRefresh || false)); |
| + this._node.getChildNodes(this._updateChildren.bind(this, fullRefresh || false, updates)); |
| }, |
| /** |
| * @param {!WebInspector.DOMNode} child |
| * @param {number} index |
| * @param {boolean=} closingTag |
| + * @param {boolean=} isUpdated |
| * @return {!WebInspector.ElementsTreeElement} |
| */ |
| - insertChildElement: function(child, index, closingTag) |
| + insertChildElement: function(child, index, closingTag, isUpdated) |
| { |
| - var newElement = new WebInspector.ElementsTreeElement(child, closingTag); |
| + var newElement = new WebInspector.ElementsTreeElement(child, closingTag, isUpdated); |
| newElement.selectable = this.treeOutline._selectEnabled; |
| this.insertChild(newElement, index); |
| return newElement; |
| @@ -1278,9 +1282,10 @@ WebInspector.ElementsTreeElement.prototype = { |
| /** |
| * @param {boolean} fullRefresh |
| + * @param {!WebInspector.ElementsTreeUpdater.Record|undefined} childUpdates |
| * @param {?Array.<!WebInspector.DOMNode>} children |
| */ |
| - _updateChildren: function(fullRefresh, children) |
| + _updateChildren: function(fullRefresh, childUpdates, children) |
| { |
| if (!children || this._updateChildrenInProgress || !this.treeOutline._visible) |
| return; |
| @@ -1327,7 +1332,7 @@ WebInspector.ElementsTreeElement.prototype = { |
| } else { |
| // No existing element found, insert a new element. |
| if (treeChildIndex < this.expandedChildrenLimit) { |
| - var newElement = this.insertChildElement(child, treeChildIndex); |
| + var newElement = this.insertChildElement(child, treeChildIndex, false, !!childUpdates && childUpdates.isNodeInserted(child)); |
|
pfeldman
2014/11/07 12:54:15
Can you do something like:
if (childUpdates.isNod
apavlov
2014/11/10 09:52:56
Done something along these lines with mыrging...
|
| if (child === selectedNode) |
| elementToSelect = newElement; |
| if (this.expandedChildCount > this.expandedChildrenLimit) |
| @@ -1360,7 +1365,7 @@ WebInspector.ElementsTreeElement.prototype = { |
| } |
| var elementToSelect = updateChildrenOfNode.call(this); |
| - this.updateTitle(); |
| + this.updateTitle(false, childUpdates); |
| this._adjustCollapsedRange(); |
| var lastChild = this.children[this.children.length - 1]; |
| @@ -2162,14 +2167,16 @@ WebInspector.ElementsTreeElement.prototype = { |
| /** |
| * @param {boolean=} onlySearchQueryChanged |
| + * @param {!WebInspector.ElementsTreeUpdater.Record=} updates |
| */ |
| - updateTitle: function(onlySearchQueryChanged) |
| + updateTitle: function(onlySearchQueryChanged, updates) |
| { |
| // If we are editing, return early to prevent canceling the edit. |
| // After editing is committed updateTitle will be called. |
| if (this._editing) |
| return; |
| + this._updates = updates; |
| if (onlySearchQueryChanged) { |
| if (this._highlightResult) |
| this._updateSearchHighlight(false); |
| @@ -2185,6 +2192,7 @@ WebInspector.ElementsTreeElement.prototype = { |
| delete this._highlightResult; |
| } |
| + delete this._isUpdated; |
| delete this.selectionElement; |
| if (this.selected) |
| this.updateSelection(); |
| @@ -2293,6 +2301,9 @@ WebInspector.ElementsTreeElement.prototype = { |
| var attrValueElement = attrSpanElement.createChild("span", "webkit-html-attribute-value"); |
| + if (this._updates && this._updates.isAttributeModified(name)) |
| + WebInspector.runCSSAnimationOnce(hasText ? attrValueElement : attrNameElement, "dom-update-highlight"); |
| + |
| /** |
| * @this {WebInspector.ElementsTreeElement} |
| * @param {string} value |
| @@ -2364,14 +2375,19 @@ WebInspector.ElementsTreeElement.prototype = { |
| tagElement.createTextChild("<"); |
| var tagNameElement = tagElement.createChild("span", isClosingTag ? "" : "webkit-html-tag-name"); |
| tagNameElement.textContent = (isClosingTag ? "/" : "") + tagName; |
| - if (!isClosingTag && node.hasAttributes()) { |
| - var attributes = node.attributes(); |
| - for (var i = 0; i < attributes.length; ++i) { |
| - var attr = attributes[i]; |
| - tagElement.createTextChild(" "); |
| - this._buildAttributeDOM(tagElement, attr.name, attr.value, false, node, linkify); |
| + if (!isClosingTag) { |
| + if (node.hasAttributes()) { |
| + var attributes = node.attributes(); |
| + for (var i = 0; i < attributes.length; ++i) { |
| + var attr = attributes[i]; |
| + tagElement.createTextChild(" "); |
| + this._buildAttributeDOM(tagElement, attr.name, attr.value, false, node, linkify); |
| + } |
| } |
| + if (this._isUpdated || (this._updates && (this._updates.hasRemovedAttributes() || this._updates.hasChangedChildren()))) |
| + WebInspector.runCSSAnimationOnce(tagNameElement, "dom-update-highlight"); |
| } |
| + |
| tagElement.createTextChild(">"); |
| parentElement.createTextChild("\u200B"); |
| }, |
| @@ -2454,6 +2470,8 @@ WebInspector.ElementsTreeElement.prototype = { |
| info.titleDOM.createTextChild("\u200B"); |
| this._buildTagDOM(info.titleDOM, tagName, true, false); |
| info.hasChildren = false; |
| + if (this._updates && (this._updates.isCharDataModified() || this._updates.hasInsertedNodes())) |
| + WebInspector.runCSSAnimationOnce(textNodeElement, "dom-update-highlight"); |
| } |
| break; |
| @@ -2477,6 +2495,8 @@ WebInspector.ElementsTreeElement.prototype = { |
| textNodeElement.textContent = result.text; |
| WebInspector.highlightRangesWithStyleClass(textNodeElement, result.entityRanges, "webkit-html-entity-value"); |
| info.titleDOM.createTextChild("\""); |
| + if (this._isUpdated || (this._updates && this._updates.isCharDataModified())) |
| + WebInspector.runCSSAnimationOnce(textNodeElement, "dom-update-highlight"); |
| } |
| break; |
| @@ -2505,6 +2525,7 @@ WebInspector.ElementsTreeElement.prototype = { |
| var cdataElement = info.titleDOM.createChild("span", "webkit-html-text-node"); |
| cdataElement.createTextChild("<![CDATA[" + node.nodeValue() + "]]>"); |
| break; |
| + |
| case Node.DOCUMENT_FRAGMENT_NODE: |
| var fragmentElement = info.titleDOM.createChild("span", "webkit-html-fragment"); |
| if (node.isInShadowTree()) { |
| @@ -2735,18 +2756,18 @@ WebInspector.ElementsTreeUpdater = function(domModel, treeOutline) |
| { |
| domModel.addEventListener(WebInspector.DOMModel.Events.NodeInserted, this._nodeInserted, this); |
| domModel.addEventListener(WebInspector.DOMModel.Events.NodeRemoved, this._nodeRemoved, this); |
| - domModel.addEventListener(WebInspector.DOMModel.Events.AttrModified, this._attributesUpdated, this); |
| - domModel.addEventListener(WebInspector.DOMModel.Events.AttrRemoved, this._attributesUpdated, this); |
| + domModel.addEventListener(WebInspector.DOMModel.Events.AttrModified, this._attributeModified, this); |
| + domModel.addEventListener(WebInspector.DOMModel.Events.AttrRemoved, this._attributeRemoved, this); |
| domModel.addEventListener(WebInspector.DOMModel.Events.CharacterDataModified, this._characterDataModified, this); |
| domModel.addEventListener(WebInspector.DOMModel.Events.DocumentUpdated, this._documentUpdated, this); |
| domModel.addEventListener(WebInspector.DOMModel.Events.ChildNodeCountUpdated, this._childNodeCountUpdated, this); |
| this._domModel = domModel; |
| this._treeOutline = treeOutline; |
| - /** @type {!Set.<!WebInspector.DOMNode>} */ |
| - this._recentlyModifiedNodes = new Set(); |
| - /** @type {!Set.<!WebInspector.DOMNode>} */ |
| - this._recentlyModifiedParentNodes = new Set(); |
| + /** @type {!Map.<!WebInspector.DOMNode, !WebInspector.ElementsTreeUpdater.Record>} */ |
| + this._recentlyModifiedNodes = new Map(); |
| + /** @type {!Map.<!WebInspector.DOMNode, !WebInspector.ElementsTreeUpdater.Record>} */ |
| + this._recentlyModifiedParentNodes = new Map(); |
| } |
| WebInspector.ElementsTreeUpdater.prototype = { |
| @@ -2754,8 +2775,8 @@ WebInspector.ElementsTreeUpdater.prototype = { |
| { |
| this._domModel.removeEventListener(WebInspector.DOMModel.Events.NodeInserted, this._nodeInserted, this); |
| this._domModel.removeEventListener(WebInspector.DOMModel.Events.NodeRemoved, this._nodeRemoved, this); |
| - this._domModel.removeEventListener(WebInspector.DOMModel.Events.AttrModified, this._attributesUpdated, this); |
| - this._domModel.removeEventListener(WebInspector.DOMModel.Events.AttrRemoved, this._attributesUpdated, this); |
| + this._domModel.removeEventListener(WebInspector.DOMModel.Events.AttrModified, this._attributeModified, this); |
| + this._domModel.removeEventListener(WebInspector.DOMModel.Events.AttrRemoved, this._attributeRemoved, this); |
| this._domModel.removeEventListener(WebInspector.DOMModel.Events.CharacterDataModified, this._characterDataModified, this); |
| this._domModel.removeEventListener(WebInspector.DOMModel.Events.DocumentUpdated, this._documentUpdated, this); |
| this._domModel.removeEventListener(WebInspector.DOMModel.Events.ChildNodeCountUpdated, this._childNodeCountUpdated, this); |
| @@ -2763,12 +2784,19 @@ WebInspector.ElementsTreeUpdater.prototype = { |
| /** |
| * @param {?WebInspector.DOMNode} parentNode |
| + * @param {!WebInspector.ElementsTreeUpdater.Record.ChangeType} changeType |
| + * @param {string|!WebInspector.DOMNode=} relatedTarget |
| */ |
| - _parentNodeModified: function(parentNode) |
| + _parentNodeModified: function(parentNode, changeType, relatedTarget) |
| { |
| if (!parentNode) |
| return; |
| - this._recentlyModifiedParentNodes.add(parentNode); |
| + var record = this._recentlyModifiedParentNodes.get(parentNode); |
| + if (!record) { |
| + record = new WebInspector.ElementsTreeUpdater.Record(); |
| + this._recentlyModifiedParentNodes.set(parentNode, record); |
| + } |
| + record.merge(parentNode, changeType, relatedTarget); |
| var treeElement = this._treeOutline.findTreeElement(parentNode); |
| if (treeElement) { |
| @@ -2776,7 +2804,7 @@ WebInspector.ElementsTreeUpdater.prototype = { |
| var oldShowInlineText = treeElement._showInlineText(); |
| treeElement._updateHasChildren(); |
| if (treeElement.hasChildren !== oldHasChildren || oldShowInlineText || treeElement._showInlineText()) |
| - this._nodeModified(parentNode); |
| + this._nodeModified(parentNode, changeType, relatedTarget); |
| } |
| if (this._treeOutline._visible) |
| @@ -2785,10 +2813,17 @@ WebInspector.ElementsTreeUpdater.prototype = { |
| /** |
| * @param {!WebInspector.DOMNode} node |
| + * @param {!WebInspector.ElementsTreeUpdater.Record.ChangeType} changeType |
| + * @param {string|!WebInspector.DOMNode=} relatedTarget |
| */ |
| - _nodeModified: function(node) |
| + _nodeModified: function(node, changeType, relatedTarget) |
| { |
| - this._recentlyModifiedNodes.add(node); |
| + var record = this._recentlyModifiedNodes.get(node); |
| + if (!record) { |
| + record = new WebInspector.ElementsTreeUpdater.Record(); |
| + this._recentlyModifiedNodes.set(node, record); |
| + } |
| + record.merge(node, changeType, relatedTarget); |
| if (this._treeOutline._visible) |
| this._updateModifiedNodesSoon(); |
| }, |
| @@ -2811,10 +2846,19 @@ WebInspector.ElementsTreeUpdater.prototype = { |
| /** |
| * @param {!WebInspector.Event} event |
| */ |
| - _attributesUpdated: function(event) |
| + _attributeModified: function(event) |
| { |
| var node = /** @type {!WebInspector.DOMNode} */ (event.data.node); |
| - this._nodeModified(node); |
| + this._nodeModified(node, WebInspector.ElementsTreeUpdater.Record.ChangeType.AttrModified, event.data.name); |
|
pfeldman
2014/11/07 12:54:15
Lets inline record creation here.
apavlov
2014/11/10 09:52:56
This will result in one record per single DOM upda
|
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.Event} event |
| + */ |
| + _attributeRemoved: function(event) |
| + { |
| + var node = /** @type {!WebInspector.DOMNode} */ (event.data.node); |
| + this._nodeModified(node, WebInspector.ElementsTreeUpdater.Record.ChangeType.AttrRemoved, event.data.name); |
| }, |
| /** |
| @@ -2823,8 +2867,8 @@ WebInspector.ElementsTreeUpdater.prototype = { |
| _characterDataModified: function(event) |
| { |
| var node = /** @type {!WebInspector.DOMNode} */ (event.data); |
| - this._parentNodeModified(node.parentNode); |
| - this._nodeModified(node); |
| + this._parentNodeModified(node.parentNode, WebInspector.ElementsTreeUpdater.Record.ChangeType.CharDataModified, node); |
| + this._nodeModified(node, WebInspector.ElementsTreeUpdater.Record.ChangeType.CharDataModified); |
| }, |
| /** |
| @@ -2833,7 +2877,7 @@ WebInspector.ElementsTreeUpdater.prototype = { |
| _nodeInserted: function(event) |
| { |
| var node = /** @type {!WebInspector.DOMNode} */ (event.data); |
| - this._parentNodeModified(node.parentNode); |
| + this._parentNodeModified(node.parentNode, WebInspector.ElementsTreeUpdater.Record.ChangeType.NodeInserted, node); |
| }, |
| /** |
| @@ -2844,7 +2888,7 @@ WebInspector.ElementsTreeUpdater.prototype = { |
| var node = /** @type {!WebInspector.DOMNode} */ (event.data.node); |
| var parentNode = /** @type {!WebInspector.DOMNode} */ (event.data.parent); |
| this._treeOutline._resetClipboardIfNeeded(node); |
| - this._parentNodeModified(parentNode); |
| + this._parentNodeModified(parentNode, WebInspector.ElementsTreeUpdater.Record.ChangeType.ChildNodeRemoved); |
| }, |
| /** |
| @@ -2853,7 +2897,7 @@ WebInspector.ElementsTreeUpdater.prototype = { |
| _childNodeCountUpdated: function(event) |
| { |
| var node = /** @type {!WebInspector.DOMNode} */ (event.data); |
| - this._parentNodeModified(node); |
| + this._parentNodeModified(node, WebInspector.ElementsTreeUpdater.Record.ChangeType.ChildNodeCountUpdated); |
|
pfeldman
2014/11/07 12:54:15
Lets not use this signal.
apavlov
2014/11/10 09:52:56
Done.
|
| }, |
| _updateModifiedNodesSoon: function() |
| @@ -2870,7 +2914,7 @@ WebInspector.ElementsTreeUpdater.prototype = { |
| delete this._updateModifiedNodesTimeout; |
| } |
| - var updatedNodes = this._recentlyModifiedNodes.valuesArray().concat(this._recentlyModifiedParentNodes.valuesArray()); |
| + var updatedNodes = this._recentlyModifiedNodes.keysArray().concat(this._recentlyModifiedParentNodes.keysArray()); |
| var hidePanelWhileUpdating = updatedNodes.length > 10; |
| if (hidePanelWhileUpdating) { |
| var treeOutlineContainerElement = this._treeOutline.element.parentNode; |
| @@ -2882,18 +2926,19 @@ WebInspector.ElementsTreeUpdater.prototype = { |
| // Document's children have changed, perform total update. |
| this._treeOutline.update(); |
| } else { |
| - var nodes = this._recentlyModifiedNodes.valuesArray(); |
| + var highlightDOMUpdates = WebInspector.settings.highlightDOMUpdates.get(); |
| + var nodes = this._recentlyModifiedNodes.keysArray(); |
| for (var i = 0, size = nodes.length; i < size; ++i) { |
| var nodeItem = this._treeOutline.findTreeElement(nodes[i]); |
| if (nodeItem) |
| - nodeItem.updateTitle(); |
| + nodeItem.updateTitle(false, highlightDOMUpdates ? this._recentlyModifiedNodes.get(nodes[i]) : undefined); |
|
pfeldman
2014/11/07 12:54:15
updateTitle can reach out for it on its own
apavlov
2014/11/10 09:52:56
Done.
|
| } |
| - var parentNodes = this._recentlyModifiedParentNodes.valuesArray(); |
| + var parentNodes = this._recentlyModifiedParentNodes.keysArray(); |
| for (var i = 0, size = parentNodes.length; i < size; ++i) { |
| var parentNodeItem = this._treeOutline.findTreeElement(parentNodes[i]); |
| if (parentNodeItem && parentNodeItem.populated) |
| - parentNodeItem.updateChildren(); |
| + parentNodeItem.updateChildren(false, highlightDOMUpdates ? this._recentlyModifiedParentNodes.get(parentNodes[i]) : undefined); |
|
pfeldman
2014/11/07 12:54:16
ditto
apavlov
2014/11/10 09:52:56
Done.
|
| } |
| } |
| @@ -2921,6 +2966,122 @@ WebInspector.ElementsTreeUpdater.prototype = { |
| /** |
| * @constructor |
| + */ |
| +WebInspector.ElementsTreeUpdater.Record = function() |
| +{ |
| + this._removedAttributeCount = 0; |
| +} |
| + |
| +WebInspector.ElementsTreeUpdater.Record.prototype = { |
|
pfeldman
2014/11/07 12:54:15
Since you merge those, I'd call it UpdateInfo
apavlov
2014/11/10 09:52:56
Done.
|
| + /** |
| + * @param {!WebInspector.DOMNode} node |
| + * @param {!WebInspector.ElementsTreeUpdater.Record.ChangeType} changeType |
| + * @param {!WebInspector.DOMNode|string|undefined} relatedTarget |
| + */ |
| + merge: function(node, changeType, relatedTarget) |
| + { |
| + var attrName; |
| + switch (changeType) { |
| + case WebInspector.ElementsTreeUpdater.Record.ChangeType.AttrModified: |
| + attrName = /** @type {string} */ (relatedTarget); |
| + if (this.removedAttributes && this.removedAttributes.has(attrName)) { |
| + this.removedAttributes.delete(attrName); |
| + --this._removedAttributeCount; |
| + } |
| + if (!this.modifiedAttributes) |
|
pfeldman
2014/11/07 12:54:15
make them all private.
apavlov
2014/11/10 09:52:56
Done.
|
| + this.modifiedAttributes = /** @type {!Set.<string>} */ (new Set()); |
| + this.modifiedAttributes.add(attrName); |
| + break; |
| + case WebInspector.ElementsTreeUpdater.Record.ChangeType.AttrRemoved: |
| + attrName = /** @type {string} */ (relatedTarget); |
| + if (this.modifiedAttributes && this.modifiedAttributes.has(attrName)) |
| + this.modifiedAttributes.delete(attrName); |
| + if (!this.removedAttributes) |
| + this.removedAttributes = /** @type {!Set.<string>} */ (new Set()); |
| + this.removedAttributes.add(attrName); |
| + ++this._removedAttributeCount; |
| + break; |
| + case WebInspector.ElementsTreeUpdater.Record.ChangeType.NodeInserted: |
| + if (!this.insertedNodes) |
| + this.insertedNodes = /** @type {!Set.<!WebInspector.DOMNode>} */ (new Set()); |
| + this.insertedNodes.add(/** @type {!WebInspector.DOMNode} */ (relatedTarget)); |
| + break; |
| + case WebInspector.ElementsTreeUpdater.Record.ChangeType.CharDataModified: |
| + this._charDataModified = true; |
| + break; |
| + case WebInspector.ElementsTreeUpdater.Record.ChangeType.ChildNodeRemoved: |
| + case WebInspector.ElementsTreeUpdater.Record.ChangeType.ChildNodeCountUpdated: |
| + this._hasChangedChildren = true; |
| + break; |
| + default: |
| + console.error("Invalid change type: " + changeType); |
| + } |
| + }, |
| + |
| + /** |
| + * @param {string} attributeName |
| + * @return {boolean} |
| + */ |
| + isAttributeModified: function(attributeName) |
| + { |
| + return this.modifiedAttributes && this.modifiedAttributes.has(attributeName); |
| + }, |
| + |
| + /** |
| + * @return {boolean} |
| + */ |
| + hasRemovedAttributes: function() |
| + { |
| + return !!this._removedAttributeCount; |
| + }, |
| + |
| + /** |
| + * @return {boolean} |
| + */ |
| + hasInsertedNodes: function() |
| + { |
| + return !!this.insertedNodes && !!this.insertedNodes.size; |
| + }, |
| + |
| + /** |
| + * @return {boolean} |
| + */ |
| + isCharDataModified: function() |
| + { |
| + return !!this._charDataModified; |
| + }, |
| + |
| + /** |
| + * @return {boolean} |
| + */ |
| + isNodeInserted: function(node) |
| + { |
| + return !!this.insertedNodes && this.insertedNodes.has(node); |
| + }, |
| + |
| + /** |
| + * @return {boolean} |
| + */ |
| + hasChangedChildren: function() |
| + { |
| + return !!this._hasChangedChildren; |
| + } |
| +} |
| + |
| +/** |
| + * @enum {number} |
| + */ |
| +WebInspector.ElementsTreeUpdater.Record.ChangeType = { |
| + AttrModified: 1, |
| + AttrRemoved: 2, |
| + CharDataModified: 3, |
| + NodeInserted: 4, |
| + ChildNodeRemoved: 5, |
| + ChildNodeCountUpdated: 6 |
| +} |
| + |
| +/** |
| + * @constructor |
| * @implements {WebInspector.Renderer} |
| */ |
| WebInspector.ElementsTreeOutline.Renderer = function() |