- Revision
- 188429
- Author
- drou...@apple.com
- Date
- 2015-08-13 19:20:02 -0700 (Thu, 13 Aug 2015)
Log Message
Web Inspector: Flash DOM node attribute on change
https://bugs.webkit.org/show_bug.cgi?id=147973
Reviewed by Timothy Hatcher.
Whenever an attribute on a DOM node changes, flash the attribute value.
If that value doesn't exist, flash the attribute name instead.
* UserInterface/Views/DOMTreeElement.js:
(WebInspector.DOMTreeElement):
(WebInspector.DOMTreeElement.prototype.nodeChanged):
(WebInspector.DOMTreeElement.prototype._buildAttributeDOM):
If the node has been marked with a general change, mark the attribute element for animation.
(WebInspector.DOMTreeElement.prototype._markNodeChanged.animationEnd):
(WebInspector.DOMTreeElement.prototype._markNodeChanged):
Adds a class to the given element that applies a simple background flash animation.
(WebInspector.DOMTreeElement.prototype._fireDidChange):
Add the animation class once all building of the represented DOM object for that node is done.
* UserInterface/Views/DOMTreeOutline.css:
(@keyframes node-state-changed):
Applies a semi-transparent background that fades to default.
(.node-state-changed):
* UserInterface/Views/DOMTreeUpdater.js:
(WebInspector.DOMTreeUpdater.prototype._attributesUpdated):
Now passes along the name of the modified attribute.
(WebInspector.DOMTreeUpdater.prototype._updateModifiedNodes):
If the modified node object has an attribute member, mark the node as being generally changed.
Modified Paths
Diff
Modified: trunk/Source/WebInspectorUI/ChangeLog (188428 => 188429)
--- trunk/Source/WebInspectorUI/ChangeLog 2015-08-14 02:14:09 UTC (rev 188428)
+++ trunk/Source/WebInspectorUI/ChangeLog 2015-08-14 02:20:02 UTC (rev 188429)
@@ -1,5 +1,37 @@
2015-08-13 Devin Rousso <drou...@apple.com>
+ Web Inspector: Flash DOM node attribute on change
+ https://bugs.webkit.org/show_bug.cgi?id=147973
+
+ Reviewed by Timothy Hatcher.
+
+ Whenever an attribute on a DOM node changes, flash the attribute value.
+ If that value doesn't exist, flash the attribute name instead.
+
+ * UserInterface/Views/DOMTreeElement.js:
+ (WebInspector.DOMTreeElement):
+ (WebInspector.DOMTreeElement.prototype.nodeChanged):
+ (WebInspector.DOMTreeElement.prototype._buildAttributeDOM):
+ If the node has been marked with a general change, mark the attribute element for animation.
+ (WebInspector.DOMTreeElement.prototype._markNodeChanged.animationEnd):
+ (WebInspector.DOMTreeElement.prototype._markNodeChanged):
+ Adds a class to the given element that applies a simple background flash animation.
+ (WebInspector.DOMTreeElement.prototype._fireDidChange):
+ Add the animation class once all building of the represented DOM object for that node is done.
+
+ * UserInterface/Views/DOMTreeOutline.css:
+ (@keyframes node-state-changed):
+ Applies a semi-transparent background that fades to default.
+ (.node-state-changed):
+
+ * UserInterface/Views/DOMTreeUpdater.js:
+ (WebInspector.DOMTreeUpdater.prototype._attributesUpdated):
+ Now passes along the name of the modified attribute.
+ (WebInspector.DOMTreeUpdater.prototype._updateModifiedNodes):
+ If the modified node object has an attribute member, mark the node as being generally changed.
+
+2015-08-13 Devin Rousso <drou...@apple.com>
+
REGRESSION (r184000): Web Inspector: Stripped whitespace after editing CSS in Styles sidebar
https://bugs.webkit.org/show_bug.cgi?id=145679
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeElement.js (188428 => 188429)
--- trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeElement.js 2015-08-14 02:14:09 UTC (rev 188428)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeElement.js 2015-08-14 02:20:02 UTC (rev 188429)
@@ -41,6 +41,7 @@
this._canAddAttributes = true;
this._searchQuery = null;
this._expandedChildrenLimit = WebInspector.DOMTreeElement.InitialChildrenLimit;
+ this._nodeStateChanges = [];
}
isCloseTag()
@@ -192,6 +193,14 @@
return count;
}
+ nodeStateChanged(change)
+ {
+ if (!change)
+ return;
+
+ this._nodeStateChanges.push(change);
+ }
+
showChildNode(node)
{
console.assert(!this._elementCloseTag);
@@ -1070,41 +1079,43 @@
_buildAttributeDOM(parentElement, name, value, node)
{
- var hasText = (value.length > 0);
- var attrSpanElement = parentElement.createChild("span", "html-attribute");
- var attrNameElement = attrSpanElement.createChild("span", "html-attribute-name");
+ let hasText = (value.length > 0);
+ let attrSpanElement = parentElement.createChild("span", "html-attribute");
+ let attrNameElement = attrSpanElement.createChild("span", "html-attribute-name");
attrNameElement.textContent = name;
-
+ let attrValueElement = null;
if (hasText)
attrSpanElement.append("=\u200B\"");
if (name === "src" || name === "href") {
- var baseURL = node.ownerDocument ? node.ownerDocument.documentURL : null;
- var rewrittenURL = absoluteURL(value, baseURL);
-
+ let baseURL = node.ownerDocument ? node.ownerDocument.documentURL : null;
+ let rewrittenURL = absoluteURL(value, baseURL);
value = value.insertWordBreakCharacters();
-
if (!rewrittenURL) {
- var attrValueElement = attrSpanElement.createChild("span", "html-attribute-value");
+ attrValueElement = attrSpanElement.createChild("span", "html-attribute-value");
attrValueElement.textContent = value;
} else {
if (value.startsWith("data:"))
value = value.trimMiddle(60);
- var linkElement = document.createElement("a");
- linkElement.href = ""
- linkElement.textContent = value;
-
- attrSpanElement.appendChild(linkElement);
+ attrValueElement = document.createElement("a");
+ attrValueElement.href = ""
+ attrValueElement.textContent = value;
+ attrSpanElement.appendChild(attrValueElement);
}
} else {
value = value.insertWordBreakCharacters();
- var attrValueElement = attrSpanElement.createChild("span", "html-attribute-value");
+ attrValueElement = attrSpanElement.createChild("span", "html-attribute-value");
attrValueElement.textContent = value;
}
if (hasText)
attrSpanElement.append("\"");
+
+ for (let change of this._nodeStateChanges) {
+ if (change.type === WebInspector.DOMTreeElement.ChangeType.Attribute && change.attribute === name)
+ change.element = hasText ? attrValueElement : attrNameElement;
+ }
}
_buildTagDOM(parentElement, tagName, isClosingTag, isDistinctTreeElement)
@@ -1449,6 +1460,34 @@
WebInspector.highlightRangesWithStyleClass(this.title, matchRanges, WebInspector.DOMTreeElement.SearchHighlightStyleClassName, this._highlightResult);
}
+ _markNodeChanged()
+ {
+ function animationEnd() {
+ this.classList.remove("node-state-changed");
+ this.removeEventListener("animationEnd", animationEnd);
+ }
+
+ for (let change of this._nodeStateChanges) {
+ let element = change.element;
+ if (!element)
+ continue;
+
+ element.classList.remove("node-state-changed");
+ element.addEventListener("animationEnd", animationEnd);
+ element.classList.add("node-state-changed");
+ }
+
+ this._nodeStateChanges = [];
+ }
+
+ _fireDidChange()
+ {
+ super._fireDidChange();
+
+ if (this._nodeStateChanges)
+ this._markNodeChanged();
+ }
+
handleEvent(event)
{
if (event.type === "dragstart" && this._editing)
@@ -1472,5 +1511,9 @@
"html", "head", "body"
].keySet();
+WebInspector.DOMTreeElement.ChangeType = {
+ Attribute: "dom-tree-element-change-type-attribute"
+};
+
WebInspector.DOMTreeElement.SearchHighlightStyleClassName = "search-highlight";
WebInspector.DOMTreeElement.BouncyHighlightStyleClassName = "bouncy-highlight";
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.css (188428 => 188429)
--- trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.css 2015-08-14 02:14:09 UTC (rev 188428)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.css 2015-08-14 02:20:02 UTC (rev 188429)
@@ -165,3 +165,12 @@
background-color: hsla(53, 83%, 53%, 0.2);
border-bottom: 1px solid hsl(47, 82%, 60%);
}
+
+@keyframes node-state-changed {
+ from { background-color: hsla(212, 92%, 54%, 0.5); }
+}
+
+.node-state-changed {
+ animation: node-state-changed 1s cubic-bezier(0, 0, 0.25, 1);
+ border-radius: 3px;
+}
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeUpdater.js (188428 => 188429)
--- trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeUpdater.js 2015-08-14 02:14:09 UTC (rev 188428)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeUpdater.js 2015-08-14 02:20:02 UTC (rev 188429)
@@ -55,7 +55,7 @@
_attributesUpdated: function(event)
{
- this._recentlyModifiedNodes.push({node: event.data.node, updated: true});
+ this._recentlyModifiedNodes.push({node: event.data.node, updated: true, attribute: event.data.name});
if (this._treeOutline._visible)
this._updateModifiedNodesSoon();
},
@@ -99,26 +99,32 @@
{
if (this._updateModifiedNodesTimeout) {
clearTimeout(this._updateModifiedNodesTimeout);
- delete this._updateModifiedNodesTimeout;
+ this._updateModifiedNodesTimeout = null;
}
- var updatedParentTreeElements = [];
+ let updatedParentTreeElements = [];
+ for (let recentlyModifiedNode of this._recentlyModifiedNodes) {
+ let parent = recentlyModifiedNode.parent;
+ let node = recentlyModifiedNode.node;
+ let changeInfo = null;
+ if (recentlyModifiedNode.attribute)
+ changeInfo = {type: WebInspector.DOMTreeElement.ChangeType.Attribute, attribute: recentlyModifiedNode.attribute};
- for (var i = 0; i < this._recentlyModifiedNodes.length; ++i) {
- var parent = this._recentlyModifiedNodes[i].parent;
- var node = this._recentlyModifiedNodes[i].node;
+ if (recentlyModifiedNode.updated) {
+ let nodeTreeElement = this._treeOutline.findTreeElement(node);
+ if (!nodeTreeElement)
+ continue;
- if (this._recentlyModifiedNodes[i].updated) {
- var nodeItem = this._treeOutline.findTreeElement(node);
- if (nodeItem)
- nodeItem.updateTitle();
- continue;
+ if (changeInfo)
+ nodeTreeElement.nodeStateChanged(changeInfo);
+
+ nodeTreeElement.updateTitle();
}
if (!parent)
continue;
- var parentNodeItem = this._treeOutline.findTreeElement(parent);
+ let parentNodeItem = this._treeOutline.findTreeElement(parent);
if (parentNodeItem && !parentNodeItem.alreadyUpdatedChildren) {
parentNodeItem.updateTitle();
parentNodeItem.updateChildren();
@@ -127,8 +133,8 @@
}
}
- for (var i = 0; i < updatedParentTreeElements.length; ++i)
- delete updatedParentTreeElements[i].alreadyUpdatedChildren;
+ for (let i = 0; i < updatedParentTreeElements.length; ++i)
+ updatedParentTreeElements[i].alreadyUpdatedChildren = null;
this._recentlyModifiedNodes = [];
},