Commit 1faa001a authored by apavlov@chromium.org's avatar apavlov@chromium.org

2010-12-08 Alexander Pavlov <apavlov@chromium.org>

        Reviewed by Joseph Pecoraro.

        Web Inspector: Enable CSS property editing name/value-wise (like Firebug does)
        https://bugs.webkit.org/show_bug.cgi?id=50565

        For CSS property editing, the property name and value have become two fields separated
        by a colon (rather than one field containing the full property text.) A user can tab
        between the name and value fields forward and backward. A colon typed in the name field
        and a semicolon in the value field (unless found inside a string) act as a Tab and focus
        the next editable field (while applying the entire property value.)

        Now a user can tab through all editable styles for an element, even across rule boundaries.

        WebCore:
        * inspector/front-end/BreakpointsSidebarPane.js:
        (WebInspector.XHRBreakpointsSidebarPane.prototype._startEditingBreakpoint):
        * inspector/front-end/DataGrid.js:
        (WebInspector.DataGrid.prototype._startEditingColumnOfDataGridNode):
        (WebInspector.DataGrid.prototype._startEditing):
        * inspector/front-end/ElementsTreeOutline.js:
        (WebInspector.ElementsTreeElement.prototype._startEditingAttribute):
        (WebInspector.ElementsTreeElement.prototype._startEditingTextNode):
        (WebInspector.ElementsTreeElement.prototype._startEditingTagName):
        (WebInspector.ElementsTreeElement.prototype._startEditingAsHTML):
        * inspector/front-end/MetricsSidebarPane.js:
        (WebInspector.MetricsSidebarPane.prototype.startEditing):
        * inspector/front-end/ObjectPropertiesSection.js:
        (WebInspector.ObjectPropertyTreeElement.prototype.startEditing):
        * inspector/front-end/Section.js:
        (WebInspector.Section):
        (WebInspector.Section.prototype.get subtitleAsTextForTest):
        (WebInspector.Section.prototype.get nextSibling):
        (WebInspector.Section.prototype.get previousSibling):
        * inspector/front-end/SourceFrame.js:
        (WebInspector.SourceFrame.prototype._editBreakpointCondition):
        * inspector/front-end/StylesSidebarPane.js:
        (WebInspector.StylePropertiesSection.prototype.nextEditableSibling):
        (WebInspector.StylePropertiesSection.prototype.previousEditableSibling):
        (WebInspector.StylePropertiesSection.prototype.addNewBlankProperty):
        (WebInspector.StylePropertiesSection.prototype.startEditingSelector):
        (WebInspector.StylePropertiesSection.prototype.editingSelectorCommitted):
        (WebInspector.StylePropertyTreeElement.prototype.):
        (WebInspector.StylePropertyTreeElement.prototype):
        * inspector/front-end/TextViewer.js:
        (WebInspector.TextViewer.prototype._handleDoubleClick):
        * inspector/front-end/WatchExpressionsSidebarPane.js:
        (WebInspector.WatchExpressionTreeElement.prototype.startEditing):
        * inspector/front-end/inspector.css:
        (.child-editing):
        * inspector/front-end/inspector.js:
        (WebInspector.startEditing.defaultFinishHandler):
        (WebInspector.startEditing):
        * inspector/front-end/treeoutline.js:
        (TreeElement.prototype.select):

        LayoutTests:
        * inspector/console-dir.html:
        * inspector/styles-add-blank-property.html:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@73913 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent b3e168d3
2010-12-08 Alexander Pavlov <apavlov@chromium.org>
Reviewed by Joseph Pecoraro.
Web Inspector: Enable CSS property editing name/value-wise (like Firebug does)
https://bugs.webkit.org/show_bug.cgi?id=50565
* inspector/console-dir.html:
* inspector/styles-add-blank-property.html:
2010-12-13 W. James MacLean <wjmaclean@chromium.org>
Reviewed by Csaba Osztrogonác.
......
......@@ -37,9 +37,9 @@ function frontend_expandAndDumpConsoleMessages(testController)
var element = messages[i].toMessageElement();
var node = element.traverseNextNode(element);
while (node) {
if (node.sectionForTest) {
messages[i].section = node.sectionForTest;
node.sectionForTest.expanded = true;
if (node._section) {
messages[i].section = node._section;
node._section.expanded = true;
break;
}
node = node.traverseNextNode(element);
......
......@@ -39,8 +39,9 @@ function frontend_dumpInspectedStyle(testController)
var evt = document.createEvent("KeyboardEvent");
evt.initKeyboardEvent("keydown", true /* can bubble */, true /* can cancel */, null /* view */, "Enter", "");
treeElement.listItemElement.textContent = "text-decoration: none";
treeElement.listItemElement.dispatchEvent(evt);
treeElement.nameElement.textContent = "text-decoration";
treeElement.valueElement.textContent = "none";
treeElement.nameElement.dispatchEvent(evt);
testController.runAfterPendingDispatches(frontend_dumpResults.bind(this, testController));
}
......
2010-12-08 Alexander Pavlov <apavlov@chromium.org>
Reviewed by Joseph Pecoraro.
Web Inspector: Enable CSS property editing name/value-wise (like Firebug does)
https://bugs.webkit.org/show_bug.cgi?id=50565
For CSS property editing, the property name and value have become two fields separated
by a colon (rather than one field containing the full property text.) A user can tab
between the name and value fields forward and backward. A colon typed in the name field
and a semicolon in the value field (unless found inside a string) act as a Tab and focus
the next editable field (while applying the entire property value.)
Now a user can tab through all editable styles for an element, even across rule boundaries.
* inspector/front-end/BreakpointsSidebarPane.js:
(WebInspector.XHRBreakpointsSidebarPane.prototype._startEditingBreakpoint):
* inspector/front-end/DataGrid.js:
(WebInspector.DataGrid.prototype._startEditingColumnOfDataGridNode):
(WebInspector.DataGrid.prototype._startEditing):
* inspector/front-end/ElementsTreeOutline.js:
(WebInspector.ElementsTreeElement.prototype._startEditingAttribute):
(WebInspector.ElementsTreeElement.prototype._startEditingTextNode):
(WebInspector.ElementsTreeElement.prototype._startEditingTagName):
(WebInspector.ElementsTreeElement.prototype._startEditingAsHTML):
* inspector/front-end/MetricsSidebarPane.js:
(WebInspector.MetricsSidebarPane.prototype.startEditing):
* inspector/front-end/ObjectPropertiesSection.js:
(WebInspector.ObjectPropertyTreeElement.prototype.startEditing):
* inspector/front-end/Section.js:
(WebInspector.Section):
(WebInspector.Section.prototype.get subtitleAsTextForTest):
(WebInspector.Section.prototype.get nextSibling):
(WebInspector.Section.prototype.get previousSibling):
* inspector/front-end/SourceFrame.js:
(WebInspector.SourceFrame.prototype._editBreakpointCondition):
* inspector/front-end/StylesSidebarPane.js:
(WebInspector.StylePropertiesSection.prototype.nextEditableSibling):
(WebInspector.StylePropertiesSection.prototype.previousEditableSibling):
(WebInspector.StylePropertiesSection.prototype.addNewBlankProperty):
(WebInspector.StylePropertiesSection.prototype.startEditingSelector):
(WebInspector.StylePropertiesSection.prototype.editingSelectorCommitted):
(WebInspector.StylePropertyTreeElement.prototype.):
(WebInspector.StylePropertyTreeElement.prototype):
* inspector/front-end/TextViewer.js:
(WebInspector.TextViewer.prototype._handleDoubleClick):
* inspector/front-end/WatchExpressionsSidebarPane.js:
(WebInspector.WatchExpressionTreeElement.prototype.startEditing):
* inspector/front-end/inspector.css:
(.child-editing):
* inspector/front-end/inspector.js:
(WebInspector.startEditing.defaultFinishHandler):
(WebInspector.startEditing):
* inspector/front-end/treeoutline.js:
(TreeElement.prototype.select):
2010-12-13 Yael Aharon <yael.aharon@nokia.com>
Unreviewed.
......
......@@ -145,7 +145,10 @@ WebInspector.XHRBreakpointsSidebarPane.prototype = {
var commitHandler = this._hideEditBreakpointDialog.bind(this, inputElement, true, breakpointItem);
var cancelHandler = this._hideEditBreakpointDialog.bind(this, inputElement, false, breakpointItem);
WebInspector.startEditing(inputElement, commitHandler, cancelHandler);
WebInspector.startEditing(inputElement, {
commitHandler: commitHandler,
cancelHandler: cancelHandler
});
},
_hideEditBreakpointDialog: function(inputElement, accept, breakpointItem)
......
......@@ -169,7 +169,11 @@ WebInspector.DataGrid.prototype = {
this._editingNode.select();
var element = this._editingNode._element.children[column];
WebInspector.startEditing(element, this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent);
WebInspector.startEditing(element, {
context: element.textContent,
commitHandler: this._editingCommitted.bind(this),
cancelHandler: this._editingCancelled.bind(this)
});
window.getSelection().setBaseAndExtent(element, 0, element, 1);
},
......@@ -191,7 +195,11 @@ WebInspector.DataGrid.prototype = {
return this._startEditingColumnOfDataGridNode(this._editingNode, 0);
this._editing = true;
WebInspector.startEditing(element, this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent);
WebInspector.startEditing(element, {
context: element.textContent,
commitHandler: this._editingCommitted.bind(this),
cancelHandler: this._editingCancelled.bind(this)
});
window.getSelection().setBaseAndExtent(element, 0, element, 1);
},
......
......@@ -872,7 +872,11 @@ WebInspector.ElementsTreeElement.prototype = {
// Remove zero-width spaces that were added by nodeTitleInfo.
removeZeroWidthSpaceRecursive(attribute);
this._editing = WebInspector.startEditing(attribute, this._attributeEditingCommitted.bind(this), this._editingCancelled.bind(this), attributeName);
this._editing = WebInspector.startEditing(attribute, {
context: attributeName,
commitHandler: this._attributeEditingCommitted.bind(this),
cancelHandler: this._editingCancelled.bind(this)
});
window.getSelection().setBaseAndExtent(elementForSelection, 0, elementForSelection, 1);
return true;
......@@ -883,7 +887,11 @@ WebInspector.ElementsTreeElement.prototype = {
if (WebInspector.isBeingEdited(textNode))
return true;
this._editing = WebInspector.startEditing(textNode, this._textNodeEditingCommitted.bind(this), this._editingCancelled.bind(this));
this._editing = WebInspector.startEditing(textNode, {
context: null,
commitHandler: this._textNodeEditingCommitted.bind(this),
cancelHandler: this._editingCancelled.bind(this)
});
window.getSelection().setBaseAndExtent(textNode, 0, textNode, 1);
return true;
......@@ -926,7 +934,11 @@ WebInspector.ElementsTreeElement.prototype = {
tagNameElement.addEventListener('keyup', keyupListener, false);
this._editing = WebInspector.startEditing(tagNameElement, editingComitted.bind(this), editingCancelled.bind(this), tagName);
this._editing = WebInspector.startEditing(tagNameElement, {
context: tagName,
commitHandler: editingComitted.bind(this),
cancelHandler: editingCancelled.bind(this)
});
window.getSelection().setBaseAndExtent(tagNameElement, 0, tagNameElement, 1);
return true;
},
......@@ -980,7 +992,12 @@ WebInspector.ElementsTreeElement.prototype = {
this.updateSelection();
}
this._editing = WebInspector.startEditing(this._htmlEditElement, commit.bind(this), dispose.bind(this), null, true);
this._editing = WebInspector.startEditing(this._htmlEditElement, {
context: null,
commitHandler: commit.bind(this),
cancelHandler: dispose.bind(this),
multiline: true
});
},
_attributeEditingCommitted: function(element, newText, oldText, attributeName, moveDirection)
......
......@@ -175,7 +175,11 @@ WebInspector.MetricsSidebarPane.prototype = {
var context = { box: box, styleProperty: styleProperty };
WebInspector.startEditing(targetElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);
WebInspector.startEditing(targetElement, {
context: context,
commitHandler: this.editingCommitted.bind(this),
cancelHandler: this.editingCancelled.bind(this)
});
},
editingCancelled: function(element, context)
......
......@@ -238,7 +238,11 @@ WebInspector.ObjectPropertyTreeElement.prototype = {
this.listItemElement.addStyleClass("editing-sub-part");
WebInspector.startEditing(this.valueElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);
WebInspector.startEditing(this.valueElement, {
context: context,
commitHandler: this.editingCommitted.bind(this),
cancelHandler: this.editingCancelled.bind(this)
});
},
editingEnded: function(context)
......
......@@ -31,7 +31,7 @@ WebInspector.Section = function(title, subtitle)
{
this.element = document.createElement("div");
this.element.className = "section";
this.element.sectionForTest = this;
this.element._section = this;
this.headerElement = document.createElement("div");
this.headerElement.className = "header";
......@@ -85,15 +85,15 @@ WebInspector.Section.prototype = {
this.subtitleElement.textContent = x;
},
get subtitleAsTextForTest()
{
var result = this.subtitleElement.textContent;
var child = this.subtitleElement.querySelector("[data-uncopyable]");
if (child) {
var linkData = child.getAttribute("data-uncopyable");
if (linkData)
result += linkData;
}
get subtitleAsTextForTest()
{
var result = this.subtitleElement.textContent;
var child = this.subtitleElement.querySelector("[data-uncopyable]");
if (child) {
var linkData = child.getAttribute("data-uncopyable");
if (linkData)
result += linkData;
}
return result;
},
......@@ -124,6 +124,26 @@ WebInspector.Section.prototype = {
}
},
get nextSibling()
{
var curElement = this.element;
do {
curElement = curElement.nextSibling;
} while (curElement && !curElement._section);
return curElement ? curElement._section : null;
},
get previousSibling()
{
var curElement = this.element;
do {
curElement = curElement.previousSibling;
} while (curElement && !curElement._section);
return curElement ? curElement._section : null;
},
expand: function()
{
if (this._expanded)
......
......@@ -705,7 +705,11 @@ WebInspector.SourceFrame.prototype = {
var dismissedHandler = dismissed.bind(this);
this._conditionEditorElement.addEventListener("blur", dismissedHandler, false);
WebInspector.startEditing(this._conditionEditorElement, committed.bind(this), dismissedHandler);
WebInspector.startEditing(this._conditionEditorElement, {
context: null,
commitHandler: committed.bind(this),
cancelHandler: dismissedHandler
});
this._conditionEditorElement.value = breakpoint.condition;
this._conditionEditorElement.select();
},
......
......@@ -268,7 +268,12 @@ WebInspector.TextViewer.prototype = {
var oldContent = lineRow.lastChild.innerHTML;
var cancelEditingCallback = this._cancelEditingLine.bind(this, lineRow.lastChild, oldContent);
var commitEditingCallback = this._commitEditingLine.bind(this, lineRow.lineNumber, lineRow.lastChild, cancelEditingCallback);
this._editingLine = WebInspector.startEditing(lineRow.lastChild, commitEditingCallback, cancelEditingCallback, null, true);
this._editingLine = WebInspector.startEditing(lineRow.lastChild, {
context: null,
commitHandler: commitEditingCallback,
cancelHandler: cancelEditingCallback,
multiline: true
});
},
_commitEditingLine: function(lineNumber, element, cancelEditingCallback)
......
......@@ -240,7 +240,11 @@ WebInspector.WatchExpressionTreeElement.prototype = {
this.listItemElement.addStyleClass("editing-sub-part");
WebInspector.startEditing(this.nameElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);
WebInspector.startEditing(this.nameElement, {
context: context,
commitHandler: this.editingCommitted.bind(this),
cancelHandler: this.editingCancelled.bind(this)
});
},
editingCancelled: function(element, context)
......
......@@ -1424,6 +1424,12 @@ body.inactive .placard.selected {
text-decoration: none !important;
}
.child-editing {
color: black !important;
text-decoration: none !important;
overflow: visible !important;
}
.editing br {
display: none;
}
......
......@@ -1915,13 +1915,23 @@ WebInspector.isEditingAnyField = function()
return this.__editing;
}
WebInspector.startEditing = function(element, committedCallback, cancelledCallback, context, multiline)
// Available config fields (all optional):
// context: Object - an arbitrary context object to be passed to the commit and cancel handlers
// commitHandler: Function - handles editing "commit" outcome
// cancelHandler: Function - handles editing "cancel" outcome
// customFinishHandler: Function - custom finish handler for the editing session (invoked on keydown)
// multiline: Boolean - whether the edited element is multiline
WebInspector.startEditing = function(element, config)
{
if (element.__editing)
return;
element.__editing = true;
WebInspector.__editing = true;
config = config || {};
var committedCallback = config.commitHandler;
var cancelledCallback = config.cancelHandler;
var context = config.context;
var oldText = getContent(element);
var moveDirection = "";
......@@ -1977,20 +1987,36 @@ WebInspector.startEditing = function(element, committedCallback, cancelledCallba
committedCallback(this, getContent(this), oldText, context, moveDirection);
}
function keyDownEventListener(event) {
function defaultFinishHandler(event)
{
var isMetaOrCtrl = WebInspector.isMac() ?
event.metaKey && !event.shiftKey && !event.ctrlKey && !event.altKey :
event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey;
if (isEnterKey(event) && (!multiline || isMetaOrCtrl)) {
if (isEnterKey(event) && (!config.multiline || isMetaOrCtrl))
return "commit";
else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code)
return "cancel";
else if (event.keyIdentifier === "U+0009") // Tab key
return "move-" + (event.shiftKey ? "backward" : "forward");
}
function keyDownEventListener(event)
{
var handler = config.customFinishHandler || defaultFinishHandler;
var result = handler(event);
if (result === "commit") {
editingCommitted.call(element);
event.preventDefault();
event.stopPropagation();
} else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) {
} else if (result === "cancel") {
editingCancelled.call(element);
event.preventDefault();
event.stopPropagation();
} else if (event.keyIdentifier === "U+0009") // Tab key
moveDirection = (event.shiftKey ? "backward" : "forward");
} else if (result && result.indexOf("move-") === 0) {
moveDirection = result.substring(5);
if (event.keyIdentifier !== "U+0009")
blurEventListener();
}
}
element.addEventListener("blur", blurEventListener, false);
......
......@@ -821,6 +821,10 @@ TreeElement.prototype.select = function(supressOnSelect, selectedByUser)
this.selected = true;
this.treeOutline._childrenListNode.focus();
// Focusing on another node may detach "this" from tree.
if (!this.treeOutline)
return;
this.treeOutline.selectedTreeElement = this;
if (this._listItemNode)
this._listItemNode.addStyleClass("selected");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment