Changeset 73913 in webkit
- Timestamp:
- Dec 13, 2010 7:06:26 AM (13 years ago)
- Location:
- trunk
- Files:
-
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r73911 r73913 1 2010-12-08 Alexander Pavlov <apavlov@chromium.org> 2 3 Reviewed by Joseph Pecoraro. 4 5 Web Inspector: Enable CSS property editing name/value-wise (like Firebug does) 6 https://bugs.webkit.org/show_bug.cgi?id=50565 7 8 * inspector/console-dir.html: 9 * inspector/styles-add-blank-property.html: 10 1 11 2010-12-13 W. James MacLean <wjmaclean@chromium.org> 2 12 -
trunk/LayoutTests/inspector/console-dir.html
r65248 r73913 38 38 var node = element.traverseNextNode(element); 39 39 while (node) { 40 if (node. sectionForTest) {41 messages[i].section = node. sectionForTest;42 node. sectionForTest.expanded = true;40 if (node._section) { 41 messages[i].section = node._section; 42 node._section.expanded = true; 43 43 break; 44 44 } -
trunk/LayoutTests/inspector/styles-add-blank-property.html
r70880 r73913 40 40 var evt = document.createEvent("KeyboardEvent"); 41 41 evt.initKeyboardEvent("keydown", true /* can bubble */, true /* can cancel */, null /* view */, "Enter", ""); 42 treeElement.listItemElement.textContent = "text-decoration: none"; 43 treeElement.listItemElement.dispatchEvent(evt); 42 treeElement.nameElement.textContent = "text-decoration"; 43 treeElement.valueElement.textContent = "none"; 44 treeElement.nameElement.dispatchEvent(evt); 44 45 45 46 testController.runAfterPendingDispatches(frontend_dumpResults.bind(this, testController)); -
trunk/WebCore/ChangeLog
r73912 r73913 1 2010-12-08 Alexander Pavlov <apavlov@chromium.org> 2 3 Reviewed by Joseph Pecoraro. 4 5 Web Inspector: Enable CSS property editing name/value-wise (like Firebug does) 6 https://bugs.webkit.org/show_bug.cgi?id=50565 7 8 For CSS property editing, the property name and value have become two fields separated 9 by a colon (rather than one field containing the full property text.) A user can tab 10 between the name and value fields forward and backward. A colon typed in the name field 11 and a semicolon in the value field (unless found inside a string) act as a Tab and focus 12 the next editable field (while applying the entire property value.) 13 14 Now a user can tab through all editable styles for an element, even across rule boundaries. 15 16 * inspector/front-end/BreakpointsSidebarPane.js: 17 (WebInspector.XHRBreakpointsSidebarPane.prototype._startEditingBreakpoint): 18 * inspector/front-end/DataGrid.js: 19 (WebInspector.DataGrid.prototype._startEditingColumnOfDataGridNode): 20 (WebInspector.DataGrid.prototype._startEditing): 21 * inspector/front-end/ElementsTreeOutline.js: 22 (WebInspector.ElementsTreeElement.prototype._startEditingAttribute): 23 (WebInspector.ElementsTreeElement.prototype._startEditingTextNode): 24 (WebInspector.ElementsTreeElement.prototype._startEditingTagName): 25 (WebInspector.ElementsTreeElement.prototype._startEditingAsHTML): 26 * inspector/front-end/MetricsSidebarPane.js: 27 (WebInspector.MetricsSidebarPane.prototype.startEditing): 28 * inspector/front-end/ObjectPropertiesSection.js: 29 (WebInspector.ObjectPropertyTreeElement.prototype.startEditing): 30 * inspector/front-end/Section.js: 31 (WebInspector.Section): 32 (WebInspector.Section.prototype.get subtitleAsTextForTest): 33 (WebInspector.Section.prototype.get nextSibling): 34 (WebInspector.Section.prototype.get previousSibling): 35 * inspector/front-end/SourceFrame.js: 36 (WebInspector.SourceFrame.prototype._editBreakpointCondition): 37 * inspector/front-end/StylesSidebarPane.js: 38 (WebInspector.StylePropertiesSection.prototype.nextEditableSibling): 39 (WebInspector.StylePropertiesSection.prototype.previousEditableSibling): 40 (WebInspector.StylePropertiesSection.prototype.addNewBlankProperty): 41 (WebInspector.StylePropertiesSection.prototype.startEditingSelector): 42 (WebInspector.StylePropertiesSection.prototype.editingSelectorCommitted): 43 (WebInspector.StylePropertyTreeElement.prototype.): 44 (WebInspector.StylePropertyTreeElement.prototype): 45 * inspector/front-end/TextViewer.js: 46 (WebInspector.TextViewer.prototype._handleDoubleClick): 47 * inspector/front-end/WatchExpressionsSidebarPane.js: 48 (WebInspector.WatchExpressionTreeElement.prototype.startEditing): 49 * inspector/front-end/inspector.css: 50 (.child-editing): 51 * inspector/front-end/inspector.js: 52 (WebInspector.startEditing.defaultFinishHandler): 53 (WebInspector.startEditing): 54 * inspector/front-end/treeoutline.js: 55 (TreeElement.prototype.select): 56 1 57 2010-12-13 Yael Aharon <yael.aharon@nokia.com> 2 58 -
trunk/WebCore/inspector/front-end/BreakpointsSidebarPane.js
r72733 r73913 146 146 var commitHandler = this._hideEditBreakpointDialog.bind(this, inputElement, true, breakpointItem); 147 147 var cancelHandler = this._hideEditBreakpointDialog.bind(this, inputElement, false, breakpointItem); 148 WebInspector.startEditing(inputElement, commitHandler, cancelHandler); 148 WebInspector.startEditing(inputElement, { 149 commitHandler: commitHandler, 150 cancelHandler: cancelHandler 151 }); 149 152 }, 150 153 -
trunk/WebCore/inspector/front-end/DataGrid.js
r71351 r73913 170 170 171 171 var element = this._editingNode._element.children[column]; 172 WebInspector.startEditing(element, this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent); 172 WebInspector.startEditing(element, { 173 context: element.textContent, 174 commitHandler: this._editingCommitted.bind(this), 175 cancelHandler: this._editingCancelled.bind(this) 176 }); 173 177 window.getSelection().setBaseAndExtent(element, 0, element, 1); 174 178 }, … … 192 196 193 197 this._editing = true; 194 WebInspector.startEditing(element, this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent); 198 WebInspector.startEditing(element, { 199 context: element.textContent, 200 commitHandler: this._editingCommitted.bind(this), 201 cancelHandler: this._editingCancelled.bind(this) 202 }); 195 203 window.getSelection().setBaseAndExtent(element, 0, element, 1); 196 204 }, -
trunk/WebCore/inspector/front-end/ElementsTreeOutline.js
r73285 r73913 873 873 removeZeroWidthSpaceRecursive(attribute); 874 874 875 this._editing = WebInspector.startEditing(attribute, this._attributeEditingCommitted.bind(this), this._editingCancelled.bind(this), attributeName); 875 this._editing = WebInspector.startEditing(attribute, { 876 context: attributeName, 877 commitHandler: this._attributeEditingCommitted.bind(this), 878 cancelHandler: this._editingCancelled.bind(this) 879 }); 876 880 window.getSelection().setBaseAndExtent(elementForSelection, 0, elementForSelection, 1); 877 881 … … 884 888 return true; 885 889 886 this._editing = WebInspector.startEditing(textNode, this._textNodeEditingCommitted.bind(this), this._editingCancelled.bind(this)); 890 this._editing = WebInspector.startEditing(textNode, { 891 context: null, 892 commitHandler: this._textNodeEditingCommitted.bind(this), 893 cancelHandler: this._editingCancelled.bind(this) 894 }); 887 895 window.getSelection().setBaseAndExtent(textNode, 0, textNode, 1); 888 896 … … 927 935 tagNameElement.addEventListener('keyup', keyupListener, false); 928 936 929 this._editing = WebInspector.startEditing(tagNameElement, editingComitted.bind(this), editingCancelled.bind(this), tagName); 937 this._editing = WebInspector.startEditing(tagNameElement, { 938 context: tagName, 939 commitHandler: editingComitted.bind(this), 940 cancelHandler: editingCancelled.bind(this) 941 }); 930 942 window.getSelection().setBaseAndExtent(tagNameElement, 0, tagNameElement, 1); 931 943 return true; … … 981 993 } 982 994 983 this._editing = WebInspector.startEditing(this._htmlEditElement, commit.bind(this), dispose.bind(this), null, true); 995 this._editing = WebInspector.startEditing(this._htmlEditElement, { 996 context: null, 997 commitHandler: commit.bind(this), 998 cancelHandler: dispose.bind(this), 999 multiline: true 1000 }); 984 1001 }, 985 1002 -
trunk/WebCore/inspector/front-end/MetricsSidebarPane.js
r70772 r73913 176 176 var context = { box: box, styleProperty: styleProperty }; 177 177 178 WebInspector.startEditing(targetElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context); 178 WebInspector.startEditing(targetElement, { 179 context: context, 180 commitHandler: this.editingCommitted.bind(this), 181 cancelHandler: this.editingCancelled.bind(this) 182 }); 179 183 }, 180 184 -
trunk/WebCore/inspector/front-end/ObjectPropertiesSection.js
r73285 r73913 239 239 this.listItemElement.addStyleClass("editing-sub-part"); 240 240 241 WebInspector.startEditing(this.valueElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context); 241 WebInspector.startEditing(this.valueElement, { 242 context: context, 243 commitHandler: this.editingCommitted.bind(this), 244 cancelHandler: this.editingCancelled.bind(this) 245 }); 242 246 }, 243 247 -
trunk/WebCore/inspector/front-end/Section.js
r65905 r73913 32 32 this.element = document.createElement("div"); 33 33 this.element.className = "section"; 34 this.element. sectionForTest= this;34 this.element._section = this; 35 35 36 36 this.headerElement = document.createElement("div"); … … 125 125 }, 126 126 127 get nextSibling() 128 { 129 var curElement = this.element; 130 do { 131 curElement = curElement.nextSibling; 132 } while (curElement && !curElement._section); 133 134 return curElement ? curElement._section : null; 135 }, 136 137 get previousSibling() 138 { 139 var curElement = this.element; 140 do { 141 curElement = curElement.previousSibling; 142 } while (curElement && !curElement._section); 143 144 return curElement ? curElement._section : null; 145 }, 146 127 147 expand: function() 128 148 { -
trunk/WebCore/inspector/front-end/SourceFrame.js
r73730 r73913 706 706 this._conditionEditorElement.addEventListener("blur", dismissedHandler, false); 707 707 708 WebInspector.startEditing(this._conditionEditorElement, committed.bind(this), dismissedHandler); 708 WebInspector.startEditing(this._conditionEditorElement, { 709 context: null, 710 commitHandler: committed.bind(this), 711 cancelHandler: dismissedHandler 712 }); 709 713 this._conditionEditorElement.value = breakpoint.condition; 710 714 this._conditionEditorElement.select(); -
trunk/WebCore/inspector/front-end/StylesSidebarPane.js
r73311 r73913 705 705 }, 706 706 707 nextEditableSibling: function() 708 { 709 var curSection = this; 710 do { 711 curSection = curSection.nextSibling; 712 } while (curSection && !curSection.editable); 713 714 return curSection; 715 }, 716 717 previousEditableSibling: function() 718 { 719 var curSection = this; 720 do { 721 curSection = curSection.previousSibling; 722 } while (curSection && !curSection.editable); 723 724 return curSection; 725 }, 726 707 727 update: function(full) 708 728 { … … 796 816 item.listItemElement.textContent = ""; 797 817 item._newProperty = true; 818 item.updateTitle(); 798 819 return item; 799 820 }, … … 876 897 return; 877 898 878 WebInspector.startEditing(this._selectorElement, this.editingSelectorCommitted.bind(this), this.editingSelectorCancelled.bind(this), null); 899 WebInspector.startEditing(this._selectorElement, { 900 context: null, 901 commitHandler: this.editingSelectorCommitted.bind(this), 902 cancelHandler: this.editingSelectorCancelled.bind(this) 903 }); 879 904 window.getSelection().setBaseAndExtent(element, 0, element, 1); 880 905 }, … … 883 908 { 884 909 function moveToNextIfNeeded() { 885 if (!moveDirection || moveDirection !== "forward")910 if (!moveDirection) 886 911 return; 887 912 888 this.expand(); 889 if (this.propertiesTreeOutline.children.length === 0) 890 this.addNewBlankProperty().startEditing(); 891 else { 892 var item = this.propertiesTreeOutline.children[0] 893 item.startEditing(item.valueElement); 913 if (moveDirection === "forward") { 914 this.expand(); 915 if (this.propertiesTreeOutline.children.length === 0) 916 this.addNewBlankProperty().startEditing(); 917 else { 918 var item = this.propertiesTreeOutline.children[0] 919 item.startEditing(item.nameElement); 920 } 921 } else { 922 var previousSection = this.previousEditableSibling(); 923 if (!previousSection) 924 return; 925 926 previousSection.expand(); 927 previousSection.addNewBlankProperty().startEditing(); 894 928 } 895 929 } … … 1347 1381 this.listItemElement.appendChild(document.createTextNode(";")); 1348 1382 1349 if (!this.parsedOk) 1383 if (!this.parsedOk) { 1384 // Avoid having longhands under an invalid shorthand. 1385 this.hasChildren = false; 1350 1386 this.listItemElement.addStyleClass("not-parsed-ok"); 1387 } 1351 1388 if (this.property.inactive) 1352 1389 this.listItemElement.addStyleClass("inactive"); … … 1461 1498 return; 1462 1499 1463 if (WebInspector.isBeingEdited(this.listItemElement) || (this.treeOutline.section && !this.treeOutline.section.editable)) 1500 if (this.treeOutline.section && !this.treeOutline.section.editable) 1501 return; 1502 1503 if (!selectElement) 1504 selectElement = this.nameElement; // No arguments passed in - edit the name element by default. 1505 else 1506 selectElement = selectElement.enclosingNodeOrSelfWithClass("webkit-css-property") || selectElement.enclosingNodeOrSelfWithClass("value"); 1507 1508 var isEditingName = selectElement === this.nameElement; 1509 if (!isEditingName && selectElement !== this.valueElement) { 1510 // Double-click in the LI - start editing value. 1511 isEditingName = false; 1512 selectElement = this.valueElement; 1513 } 1514 1515 if (WebInspector.isBeingEdited(selectElement)) 1464 1516 return; 1465 1517 … … 1467 1519 expanded: this.expanded, 1468 1520 hasChildren: this.hasChildren, 1469 keyDownListener: this.editingKeyDown.bind(this), 1470 keyPressListener: this.editingKeyPress.bind(this) 1521 keyDownListener: isEditingName ? this.editingNameKeyDown.bind(this) : this.editingValueKeyDown.bind(this), 1522 keyPressListener: isEditingName ? this.editingNameKeyPress.bind(this) : this.editingValueKeyPress.bind(this), 1523 isEditingName: isEditingName, 1471 1524 }; 1472 1525 … … 1474 1527 this.hasChildren = false; 1475 1528 1476 if (!selectElement) 1477 selectElement = this.listItemElement; 1478 1479 this.listItemElement.addEventListener("keydown", context.keyDownListener, false); 1480 this.listItemElement.addEventListener("keypress", context.keyPressListener, false); 1481 1482 WebInspector.startEditing(this.listItemElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context); 1529 selectElement.addEventListener("keydown", context.keyDownListener, false); 1530 selectElement.addEventListener("keypress", context.keyPressListener, false); 1531 if (selectElement.parentElement) 1532 selectElement.parentElement.addStyleClass("child-editing"); 1533 selectElement.textContent = selectElement.textContent; // remove color swatch and the like 1534 1535 function shouldCommitValueSemicolon(text, cursorPosition) 1536 { 1537 // FIXME: should this account for semicolons inside comments? 1538 var openQuote = ""; 1539 for (var i = 0; i < cursorPosition; ++i) { 1540 var ch = text[i]; 1541 if (ch === "\\" && openQuote !== "") 1542 ++i; // skip next character inside string 1543 else if (!openQuote && (ch === "\"" || ch === "'")) 1544 openQuote = ch; 1545 else if (openQuote === ch) 1546 openQuote = ""; 1547 } 1548 return !openQuote; 1549 } 1550 1551 function nameValueFinishHandler(context, isEditingName, event) 1552 { 1553 // FIXME: the ":"/";" detection does not work for non-US layouts due to the event being keydown rather than keypress. 1554 var isFieldInputTerminated = (event.keyCode === WebInspector.KeyboardShortcut.Keys.Semicolon.code) && 1555 (isEditingName ? event.shiftKey : (!event.shiftKey && shouldCommitValueSemicolon(event.target.textContent, event.target.selectionLeftOffset))); 1556 if (isEnterKey(event) || isFieldInputTerminated) { 1557 // Enter or colon (for name)/semicolon outside of string (for value). 1558 event.preventDefault(); 1559 return "move-forward"; 1560 } else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) 1561 return "cancel"; 1562 else if (event.keyIdentifier === "U+0009") // Tab key. 1563 return "move-" + (event.shiftKey ? "backward" : "forward"); 1564 } 1565 1566 WebInspector.startEditing(selectElement, { 1567 context: context, 1568 commitHandler: this.editingCommitted.bind(this), 1569 cancelHandler: this.editingCancelled.bind(this), 1570 customFinishHandler: nameValueFinishHandler.bind(this, context, isEditingName) 1571 }); 1483 1572 window.getSelection().setBaseAndExtent(selectElement, 0, selectElement, 1); 1484 1573 }, 1485 1574 1486 editingKeyPress: function(event) 1487 { 1575 editingNameKeyPress: function(event) 1576 { 1577 // Complete property names. 1578 var character = event.data.toLowerCase(); 1579 if (character && /[a-z-]/.test(character)) { 1580 var selection = window.getSelection(); 1581 var prefix = selection.anchorNode.textContent.substring(0, selection.anchorOffset); 1582 var property = WebInspector.CSSCompletions.firstStartsWith(prefix + character); 1583 1584 if (!selection.isCollapsed) 1585 selection.deleteFromDocument(); 1586 1587 this.restoreNameElement(); 1588 1589 if (property) { 1590 if (property !== this.nameElement.textContent) 1591 this.nameElement.textContent = property; 1592 this.nameElement.firstChild.select(prefix.length + 1); 1593 event.preventDefault(); 1594 } 1595 } 1596 }, 1597 1598 editingValueKeyPress: function(event) 1599 { 1600 // FIXME: This should complete property values. 1601 }, 1602 1603 editingNameKeyDown: function(event) 1604 { 1605 var showNext; 1606 if (event.keyIdentifier === "Up") 1607 showNext = false; 1608 else if (event.keyIdentifier === "Down") 1609 showNext = true; 1610 else 1611 return; 1612 1488 1613 var selection = window.getSelection(); 1489 var colonIndex = this.listItemElement.textContent.indexOf(":"); 1490 var selectionLeftOffset = event.target.selectionLeftOffset; 1491 1492 if (colonIndex < 0 || selectionLeftOffset <= colonIndex) { 1493 // Complete property names. 1494 var character = event.data.toLowerCase(); 1495 if (character && /[a-z-]/.test(character)) { 1496 var prefix = selection.anchorNode.textContent.substring(0, selection.anchorOffset); 1497 var property = WebInspector.CSSCompletions.firstStartsWith(prefix + character); 1498 1499 if (!selection.isCollapsed) 1500 selection.deleteFromDocument(); 1501 1502 this.restoreNameElement(); 1503 1504 if (property) { 1505 if (property !== this.nameElement.textContent) 1506 this.nameElement.textContent = property; 1507 this.nameElement.firstChild.select(prefix.length + 1); 1508 event.preventDefault(); 1509 } 1510 } 1511 } else { 1512 // FIXME: This should complete property values. 1513 } 1514 }, 1515 1516 editingKeyDown: function(event) 1614 if (!selection.rangeCount) 1615 return; 1616 1617 var selectionRange = selection.getRangeAt(0); 1618 if (selectionRange.commonAncestorContainer !== this.nameElement && !selectionRange.commonAncestorContainer.isDescendant(this.nameElement)) 1619 return; 1620 1621 const styleValueDelimeters = " \t\n\"':;,/()"; 1622 var wordRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, styleValueDelimeters, this.nameElement); 1623 var wordString = wordRange.toString(); 1624 var prefix = selectionRange.startContainer.textContent.substring(0, selectionRange.startOffset); 1625 var property; 1626 1627 if (showNext) 1628 property = WebInspector.CSSCompletions.next(wordString, prefix); 1629 else 1630 property = WebInspector.CSSCompletions.previous(wordString, prefix); 1631 1632 if (property) { 1633 this.nameElement.textContent = property; 1634 this.nameElement.firstChild.select(selectionRange.startOffset); 1635 } 1636 event.preventDefault(); 1637 }, 1638 1639 editingValueKeyDown: function(event) 1517 1640 { 1518 1641 var arrowKeyPressed = (event.keyIdentifier === "Up" || event.keyIdentifier === "Down"); … … 1526 1649 1527 1650 var selectionRange = selection.getRangeAt(0); 1528 if (selectionRange.commonAncestorContainer !== this.listItemElement && !selectionRange.commonAncestorContainer.isDescendant(this.listItemElement)) 1529 return; 1530 1531 // If there are several properties in the text, do not handle increments/decrements. 1532 var text = event.target.textContent.trim(); 1533 var openQuote; 1534 var wasEscape = false; 1535 // Exclude the last character from the check since it is allowed to be ";". 1536 for (var i = 0; i < text.length - 1; ++i) { 1537 var ch = text.charAt(i); 1538 if (ch === "\\") { 1539 wasEscape = true; 1540 continue; 1541 } 1542 if (ch === ";" && !openQuote) 1543 return; // Do not handle name/value shifts if the property is compound. 1544 if ((ch === "'" || ch === "\"") && !wasEscape) { 1545 if (!openQuote) 1546 openQuote = ch; 1547 else if (ch === openQuote) 1548 openQuote = null; 1549 } 1550 wasEscape = false; 1551 } 1651 if (selectionRange.commonAncestorContainer !== this.valueElement && !selectionRange.commonAncestorContainer.isDescendant(this.valueElement)) 1652 return; 1552 1653 1553 1654 const styleValueDelimeters = " \t\n\"':;,/()"; 1554 var wordRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, styleValueDelimeters, this. listItemElement);1655 var wordRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, styleValueDelimeters, this.valueElement); 1555 1656 var wordString = wordRange.toString(); 1556 1657 var replacementString = wordString; … … 1594 1695 1595 1696 replacementString = prefix + number + suffix; 1596 } else if (selection.containsNode(this.nameElement, true)) {1597 var prefix = selectionRange.startContainer.textContent.substring(0, selectionRange.startOffset);1598 var property;1599 1600 if (event.keyIdentifier === "Up")1601 property = WebInspector.CSSCompletions.previous(wordString, prefix);1602 else if (event.keyIdentifier === "Down")1603 property = WebInspector.CSSCompletions.next(wordString, prefix);1604 1605 var startOffset = selectionRange.startOffset;1606 if (property) {1607 this.nameElement.textContent = property;1608 this.nameElement.firstChild.select(startOffset);1609 }1610 event.preventDefault();1611 return;1612 1697 } else { 1613 1698 // FIXME: this should cycle through known keywords for the current property value. … … 1633 1718 this.originalPropertyText = this.property.propertyText; 1634 1719 } 1635 this.applyStyleText(this.listItemElement.textContent); 1720 1721 // Synthesize property text disregarding any comments, custom whitespace etc. 1722 this.applyStyleText(this.nameElement.textContent + ": " + this.valueElement.textContent); 1636 1723 }, 1637 1724 … … 1641 1728 if (context.expanded) 1642 1729 this.expand(); 1643 this.listItemElement.removeEventListener("keydown", context.keyDownListener, false); 1644 this.listItemElement.removeEventListener("keypress", context.keyPressListener, false); 1730 var editedElement = context.isEditingName ? this.nameElement : this.valueElement; 1731 editedElement.removeEventListener("keydown", context.keyDownListener, false); 1732 editedElement.removeEventListener("keypress", context.keyPressListener, false); 1733 if (editedElement.parentElement) 1734 editedElement.parentElement.removeStyleClass("child-editing"); 1735 1645 1736 delete this.originalPropertyText; 1646 1737 }, … … 1662 1753 { 1663 1754 this.editingEnded(context); 1755 var isEditingName = context.isEditingName; 1664 1756 1665 1757 // Determine where to move to before making changes 1666 var newProperty, moveToPropertyName, moveToSelector;1758 var createNewProperty, moveToPropertyName, moveToSelector; 1667 1759 var moveTo = this; 1668 do { 1669 moveTo = (moveDirection === "forward" ? moveTo.nextSibling : moveTo.previousSibling); 1670 } while(moveTo && !moveTo.selectable); 1671 1672 if (moveTo) 1673 moveToPropertyName = moveTo.name; 1674 else if (moveDirection === "forward") 1675 newProperty = true; 1676 else if (moveDirection === "backward" && this.treeOutline.section.rule) 1677 moveToSelector = true; 1678 1679 // Make the Changes and trigger the moveToNextCallback after updating 1760 var moveToOther = (isEditingName ^ (moveDirection === "forward")); 1761 var abandonNewProperty = this._newProperty && !userInput && (moveToOther || isEditingName); 1762 if (moveDirection === "forward" && !isEditingName || moveDirection === "backward" && isEditingName) { 1763 do { 1764 moveTo = (moveDirection === "forward" ? moveTo.nextSibling : moveTo.previousSibling); 1765 } while(moveTo && !moveTo.selectable); 1766 1767 if (moveTo) 1768 moveToPropertyName = moveTo.name; 1769 else if (moveDirection === "forward" && (!this._newProperty || userInput)) 1770 createNewProperty = true; 1771 else if (moveDirection === "backward" && this.treeOutline.section.rule) 1772 moveToSelector = true; 1773 } 1774 1775 // Make the Changes and trigger the moveToNextCallback after updating. 1680 1776 var blankInput = /^\s*$/.test(userInput); 1681 if (userInput !== previousContent || (this._newProperty && blankInput)) { // only if something changed, or adding a new style and it was blank 1682 this.treeOutline.section._afterUpdate = moveToNextCallback.bind(this, this._newProperty, !blankInput); 1683 this.applyStyleText(userInput, true); 1684 } else 1685 moveToNextCallback(this._newProperty, false, this.treeOutline.section, false); 1686 1687 // The Callback to start editing the next property 1777 var shouldCommitNewProperty = this._newProperty && (moveToOther || (!moveDirection && !isEditingName) || (isEditingName && blankInput)); 1778 1779 if ((userInput !== previousContent && !this._newProperty) || shouldCommitNewProperty) { 1780 this.treeOutline.section._afterUpdate = moveToNextCallback.bind(this, this._newProperty, !blankInput, this.treeOutline.section); 1781 var propertyText; 1782 if (blankInput || (this._newProperty && /^\s*$/.test(this.valueElement.textContent))) 1783 propertyText = ""; 1784 else { 1785 if (isEditingName) 1786 propertyText = userInput + ": " + this.valueElement.textContent; 1787 else 1788 propertyText = this.nameElement.textContent + ": " + userInput; 1789 } 1790 this.applyStyleText(propertyText, true); 1791 } else { 1792 if (!this._newProperty) 1793 this.updateTitle(); 1794 moveToNextCallback(this._newProperty, false, this.treeOutline.section); 1795 } 1796 1797 var moveToIndex = moveTo && this.treeOutline ? this.treeOutline.children.indexOf(moveTo) : -1; 1798 1799 // The Callback to start editing the next/previous property/selector. 1688 1800 function moveToNextCallback(alreadyNew, valueChanged, section) 1689 1801 { … … 1691 1803 return; 1692 1804 1693 // User just tabbed through without changes 1805 // User just tabbed through without changes. 1694 1806 if (moveTo && moveTo.parent) { 1695 moveTo.startEditing( moveTo.valueElement);1807 moveTo.startEditing(!isEditingName ? moveTo.nameElement : moveTo.valueElement); 1696 1808 return; 1697 1809 } 1698 1810 1699 // User has made a change then tabbed, wiping all the original treeElements, 1700 // recalculate the new treeElement for the same property we were going to edit next 1701 // FIXME(apavlov): this will not work for multiple same-named properties in a style 1702 // (the first one will always be returned). 1811 // User has made a change then tabbed, wiping all the original treeElements. 1812 // Recalculate the new treeElement for the same property we were going to edit next. 1703 1813 if (moveTo && !moveTo.parent) { 1704 var treeElement = section.findTreeElementWithName(moveToPropertyName); 1705 if (treeElement) 1706 treeElement.startEditing(treeElement.valueElement); 1707 return; 1708 } 1709 1710 // Create a new attribute in this section 1711 if (newProperty) { 1712 if (alreadyNew && !valueChanged) 1814 var propertyElements = section.propertiesTreeOutline.children; 1815 if (moveDirection === "forward" && blankInput && !isEditingName) 1816 --moveToIndex; 1817 if (moveToIndex >= propertyElements.length && !this._newProperty) 1818 createNewProperty = true; 1819 else { 1820 var treeElement = moveToIndex >= 0 ? propertyElements[moveToIndex] : null; 1821 if (treeElement) { 1822 treeElement.startEditing(!isEditingName ? treeElement.nameElement : treeElement.valueElement); 1823 return; 1824 } else if (!alreadyNew) 1825 moveToSelector = true; 1826 } 1827 } 1828 1829 // Create a new attribute in this section (or move to next editable selector if possible). 1830 if (createNewProperty) { 1831 if (alreadyNew && !valueChanged && (isEditingName ^ (moveDirection === "backward"))) 1713 1832 return; 1714 1833 … … 1717 1836 } 1718 1837 1838 if (abandonNewProperty) { 1839 var sectionToEdit = moveDirection === "backward" ? section : section.nextEditableSibling(); 1840 if (sectionToEdit && sectionToEdit.rule) 1841 sectionToEdit.startEditingSelector(); 1842 return; 1843 } 1844 1719 1845 if (moveToSelector) 1720 1846 section.startEditingSelector(); … … 1726 1852 var section = this.treeOutline.section; 1727 1853 var elementsPanel = WebInspector.panels.elements; 1728 styleText = styleText.replace(/\s/g, " ").trim(); // replace with whitespace.1854 styleText = styleText.replace(/\s/g, " ").trim(); // Replace with whitespace. 1729 1855 var styleTextLength = styleText.length; 1730 if (!styleTextLength && updateInterface) { 1731 if (this._newProperty) { 1732 // The user deleted everything, so remove the tree element and update. 1733 this.parent.removeChild(this); 1734 section.afterUpdate(); 1735 return; 1736 } else 1737 delete section._afterUpdate; 1856 if (!styleTextLength && updateInterface && this._newProperty) { 1857 // The user deleted everything, so remove the tree element and update. 1858 this.parent.removeChild(this); 1859 section.afterUpdate(); 1860 return; 1738 1861 } 1739 1862 -
trunk/WebCore/inspector/front-end/TextViewer.js
r69276 r73913 269 269 var cancelEditingCallback = this._cancelEditingLine.bind(this, lineRow.lastChild, oldContent); 270 270 var commitEditingCallback = this._commitEditingLine.bind(this, lineRow.lineNumber, lineRow.lastChild, cancelEditingCallback); 271 this._editingLine = WebInspector.startEditing(lineRow.lastChild, commitEditingCallback, cancelEditingCallback, null, true); 271 this._editingLine = WebInspector.startEditing(lineRow.lastChild, { 272 context: null, 273 commitHandler: commitEditingCallback, 274 cancelHandler: cancelEditingCallback, 275 multiline: true 276 }); 272 277 }, 273 278 -
trunk/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js
r71109 r73913 241 241 this.listItemElement.addStyleClass("editing-sub-part"); 242 242 243 WebInspector.startEditing(this.nameElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context); 243 WebInspector.startEditing(this.nameElement, { 244 context: context, 245 commitHandler: this.editingCommitted.bind(this), 246 cancelHandler: this.editingCancelled.bind(this) 247 }); 244 248 }, 245 249 -
trunk/WebCore/inspector/front-end/inspector.css
r73311 r73913 1425 1425 } 1426 1426 1427 .child-editing { 1428 color: black !important; 1429 text-decoration: none !important; 1430 overflow: visible !important; 1431 } 1432 1427 1433 .editing br { 1428 1434 display: none; -
trunk/WebCore/inspector/front-end/inspector.js
r73909 r73913 1916 1916 } 1917 1917 1918 WebInspector.startEditing = function(element, committedCallback, cancelledCallback, context, multiline) 1918 // Available config fields (all optional): 1919 // context: Object - an arbitrary context object to be passed to the commit and cancel handlers 1920 // commitHandler: Function - handles editing "commit" outcome 1921 // cancelHandler: Function - handles editing "cancel" outcome 1922 // customFinishHandler: Function - custom finish handler for the editing session (invoked on keydown) 1923 // multiline: Boolean - whether the edited element is multiline 1924 WebInspector.startEditing = function(element, config) 1919 1925 { 1920 1926 if (element.__editing) … … 1923 1929 WebInspector.__editing = true; 1924 1930 1931 config = config || {}; 1932 var committedCallback = config.commitHandler; 1933 var cancelledCallback = config.cancelHandler; 1934 var context = config.context; 1925 1935 var oldText = getContent(element); 1926 1936 var moveDirection = ""; … … 1978 1988 } 1979 1989 1980 function keyDownEventListener(event) { 1990 function defaultFinishHandler(event) 1991 { 1981 1992 var isMetaOrCtrl = WebInspector.isMac() ? 1982 1993 event.metaKey && !event.shiftKey && !event.ctrlKey && !event.altKey : 1983 1994 event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey; 1984 if (isEnterKey(event) && (!multiline || isMetaOrCtrl)) { 1995 if (isEnterKey(event) && (!config.multiline || isMetaOrCtrl)) 1996 return "commit"; 1997 else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) 1998 return "cancel"; 1999 else if (event.keyIdentifier === "U+0009") // Tab key 2000 return "move-" + (event.shiftKey ? "backward" : "forward"); 2001 } 2002 2003 function keyDownEventListener(event) 2004 { 2005 var handler = config.customFinishHandler || defaultFinishHandler; 2006 var result = handler(event); 2007 if (result === "commit") { 1985 2008 editingCommitted.call(element); 1986 2009 event.preventDefault(); 1987 2010 event.stopPropagation(); 1988 } else if ( event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) {2011 } else if (result === "cancel") { 1989 2012 editingCancelled.call(element); 1990 2013 event.preventDefault(); 1991 2014 event.stopPropagation(); 1992 } else if (event.keyIdentifier === "U+0009") // Tab key 1993 moveDirection = (event.shiftKey ? "backward" : "forward"); 2015 } else if (result && result.indexOf("move-") === 0) { 2016 moveDirection = result.substring(5); 2017 if (event.keyIdentifier !== "U+0009") 2018 blurEventListener(); 2019 } 1994 2020 } 1995 2021 -
trunk/WebCore/inspector/front-end/treeoutline.js
r72072 r73913 822 822 this.selected = true; 823 823 this.treeOutline._childrenListNode.focus(); 824 825 // Focusing on another node may detach "this" from tree. 826 if (!this.treeOutline) 827 return; 824 828 this.treeOutline.selectedTreeElement = this; 825 829 if (this._listItemNode)
Note: See TracChangeset
for help on using the changeset viewer.