Title: [105252] branches/chromium/963/Source/WebCore/inspector/front-end
Revision
105252
Author
apav...@chromium.org
Date
2012-01-18 02:15:26 -0800 (Wed, 18 Jan 2012)

Log Message

Merge 105140 - Web Inspector: [TextPrompt] Autocomplete adds unwanted text that's hard to remove
https://bugs.webkit.org/show_bug.cgi?id=76058

Reviewed by Pavel Feldman.

As per the results of a war room:
- Auto-suggest only after user typing (avoid showing suggestions when navigating through the user input.)
- Do not select the first item if the suggest box is shown at the end of prompt (to allow Enter to commit the input.)
- Only show grayed autocompletion at the end of prompt (otherwise show a suggest box with the first item selected.)
- Grayed autocompletion can only be accepted with the End or Right keys.
- Enter can accept a selected suggestion item from the list, without committing the input.
- Retain the CSS model editing behavior as close to the existing one as possible.
- Enable PageUp/PageDown to navigate the suggest box items.

* inspector/front-end/StylesSidebarPane.js:
(WebInspector.StylePropertyTreeElement.prototype):
():
* inspector/front-end/TextPrompt.js:
(WebInspector.TextPrompt.prototype.set text):
(WebInspector.TextPrompt.prototype._removeSuggestionAids):
(WebInspector.TextPrompt.prototype._selectStart.moveBackIfOutside):
(WebInspector.TextPrompt.prototype._selectStart):
(WebInspector.TextPrompt.prototype.onKeyDown):
(WebInspector.TextPrompt.prototype.acceptAutoComplete):
(WebInspector.TextPrompt.prototype.complete):
(WebInspector.TextPrompt.prototype._completionsReady):
(WebInspector.TextPrompt.prototype.isCaretAtEndOfPrompt):
(WebInspector.TextPrompt.prototype.tabKeyPressed):
(WebInspector.TextPrompt.prototype.downKeyPressed):
(WebInspector.TextPrompt.prototype.pageUpKeyPressed):
(WebInspector.TextPrompt.prototype.pageDownKeyPressed):
(WebInspector.TextPrompt.SuggestBox.prototype._onNextItem):
(WebInspector.TextPrompt.SuggestBox.prototype._onPreviousItem):
(WebInspector.TextPrompt.SuggestBox.prototype.updateSuggestions):
(WebInspector.TextPrompt.SuggestBox.prototype._updateItems):
(WebInspector.TextPrompt.SuggestBox.prototype._canShowBox):
(WebInspector.TextPrompt.SuggestBox.prototype._rememberRowCountPerViewport):
(WebInspector.TextPrompt.SuggestBox.prototype._completionsReady):
(WebInspector.TextPrompt.SuggestBox.prototype.pageUpKeyPressed):
(WebInspector.TextPrompt.SuggestBox.prototype.pageDownKeyPressed):
(WebInspector.TextPrompt.SuggestBox.prototype.enterKeyPressed):

TBR=apav...@chromium.org
Review URL: https://chromiumcodereview.appspot.com/9252006

Modified Paths

Diff

Modified: branches/chromium/963/Source/WebCore/inspector/front-end/StylesSidebarPane.js (105251 => 105252)


--- branches/chromium/963/Source/WebCore/inspector/front-end/StylesSidebarPane.js	2012-01-18 10:08:22 UTC (rev 105251)
+++ branches/chromium/963/Source/WebCore/inspector/front-end/StylesSidebarPane.js	2012-01-18 10:15:26 UTC (rev 105252)
@@ -2150,9 +2150,9 @@
 
     _hasBeenModifiedIncrementally: function()
     {
-        // New properties applied via up/down have an originalPropertyText and will be deleted later
+        // New properties applied via up/down or live editing have an originalPropertyText and will be deleted later
         // on, if cancelled, when the empty string gets applied as their style text.
-        return typeof this.originalPropertyText === "string";
+        return typeof this.originalPropertyText === "string" || (!!this.property.propertyText && this._newProperty);
     },
 
     applyStyleText: function(styleText, updateInterface, majorChange, isRevert)
@@ -2178,7 +2178,7 @@
         styleText = styleText.replace(/\s/g, " ").trim(); // Replace   with whitespace.
         var styleTextLength = styleText.length;
         if (!styleTextLength && updateInterface && !isRevert && this._newProperty && !this._hasBeenModifiedIncrementally()) {
-            // The user deleted everything and never applied a new property value via Up/Down scrolling, so remove the tree element and update.
+            // The user deleted everything and never applied a new property value via Up/Down scrolling/live editing, so remove the tree element and update.
             this.parent.removeChild(this);
             section.afterUpdate();
             return;
@@ -2252,17 +2252,19 @@
                 return;
             }
             break;
-        case "U+0009":
-            if (this.isSuggestBoxVisible()) {
-                this._suggestBox.acceptSuggestion();
-                return !this._isEditingName;
-            }
-            return this.acceptAutoComplete();
         }
 
         WebInspector.TextPrompt.prototype.onKeyDown.call(this, event);
     },
 
+    tabKeyPressed: function()
+    {
+        this.acceptAutoComplete();
+
+        // Always tab to the next field.
+        return false;
+    },
+
     _handleNameOrValueUpDown: function(event)
     {
         // Handle numeric value increment/decrement only at this point.

Modified: branches/chromium/963/Source/WebCore/inspector/front-end/TextPrompt.js (105251 => 105252)


--- branches/chromium/963/Source/WebCore/inspector/front-end/TextPrompt.js	2012-01-18 10:08:22 UTC (rev 105251)
+++ branches/chromium/963/Source/WebCore/inspector/front-end/TextPrompt.js	2012-01-18 10:15:26 UTC (rev 105252)
@@ -137,7 +137,7 @@
 
     set text(x)
     {
-        this.clearAutoComplete(true);
+        this._removeSuggestionAids();
         if (!x) {
             // Append a break element instead of setting textContent to make sure the selection is inside the prompt.
             this._element.removeChildren();
@@ -186,19 +186,26 @@
         WebInspector.markBeingEdited(this._element, false);
     },
 
+    _removeSuggestionAids: function()
+    {
+        this.clearAutoComplete();
+        this.hideSuggestBox();
+    },
+
     _selectStart: function(event)
     {
         if (this._selectionTimeout)
             clearTimeout(this._selectionTimeout);
 
-        this.clearAutoComplete();
+        this._removeSuggestionAids();
 
         function moveBackIfOutside()
         {
             delete this._selectionTimeout;
-            if (!this.isCaretInsidePrompt() && window.getSelection().isCollapsed)
+            if (!this.isCaretInsidePrompt() && window.getSelection().isCollapsed) {
                 this.moveCaretToEndOfPrompt();
-            this.autoCompleteSoon();
+                this.autoCompleteSoon();
+            }
         }
 
         this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100);
@@ -226,28 +233,37 @@
         case "Down":
             handled = this.downKeyPressed(event);
             break;
+        case "PageUp":
+            handled = this.pageUpKeyPressed(event);
+            break;
+        case "PageDown":
+            handled = this.pageDownKeyPressed(event);
+            break;
         case "U+0009": // Tab
             handled = this.tabKeyPressed(event);
             break;
         case "Enter":
             handled = this.enterKeyPressed(event);
             break;
+        case "Left":
+        case "Home":
+            this._removeSuggestionAids();
+            invokeDefault = false;
+            break;
         case "Right":
         case "End":
-            if (this.isSuggestBoxVisible() && this.isCaretAtEndOfPrompt())
-                handled = this._suggestBox.tabKeyPressed(event);
-            else {
+            if (this.isCaretAtEndOfPrompt())
                 handled = this.acceptAutoComplete();
-                if (!handled)
-                    this.autoCompleteSoon();
-            }
+            else
+                this._removeSuggestionAids();
+            invokeDefault = false;
             break;
         case "U+001B": // Esc
             if (this.isSuggestBoxVisible()) {
                 this._suggestBox.hide();
                 handled = true;
-                break;
             }
+            break;
         case "U+0020": // Space
             if (this._suggestForceable && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) {
                 this.defaultKeyHandler(event, true);
@@ -275,9 +291,13 @@
 
     acceptAutoComplete: function()
     {
+        var result = false;
         if (this.isSuggestBoxVisible())
-            return this._suggestBox.acceptSuggestion();
-        return this.acceptSuggestion();
+            result = this._suggestBox.acceptSuggestion();
+        if (!result)
+            result = this.acceptSuggestion();
+
+        return result;
     },
 
     /**
@@ -348,7 +368,7 @@
             shouldExit = true;
         else if (!auto && !isEmptyInput && !selectionRange.commonAncestorContainer.isDescendant(this._element))
             shouldExit = true;
-        else if (auto && !this._suggestBox && !force && !this.isCaretAtEndOfPrompt())
+        else if (auto && !force && !this.isCaretAtEndOfPrompt() && !this.isSuggestBoxVisible())
             shouldExit = true;
         else if (!selection.isCollapsed)
             shouldExit = true;
@@ -405,7 +425,7 @@
         this._userEnteredText = fullWordRange.toString();
 
         if (this._suggestBox)
-            this._suggestBox.updateSuggestions(this._boxForAnchorAtStart(selection, fullWordRange), completions);
+            this._suggestBox.updateSuggestions(this._boxForAnchorAtStart(selection, fullWordRange), completions, !this.isCaretAtEndOfPrompt());
 
         var wordPrefixLength = originalWordPrefixRange.toString().length;
 
@@ -452,25 +472,27 @@
         }
 
         if (auto) {
-            this._userEnteredRange.deleteContents();
-            this._element.pruneEmptyTextNodes();
-            var finalSelectionRange = document.createRange();
-            var prefixText = completionText.substring(0, wordPrefixLength);
-            var suffixText = completionText.substring(wordPrefixLength);
+            if (this.isCaretAtEndOfPrompt()) {
+                this._userEnteredRange.deleteContents();
+                this._element.pruneEmptyTextNodes();
+                var finalSelectionRange = document.createRange();
+                var prefixText = completionText.substring(0, wordPrefixLength);
+                var suffixText = completionText.substring(wordPrefixLength);
 
-            var prefixTextNode = document.createTextNode(prefixText);
-            fullWordRange.insertNode(prefixTextNode);
+                var prefixTextNode = document.createTextNode(prefixText);
+                fullWordRange.insertNode(prefixTextNode);
 
-            this.autoCompleteElement = document.createElement("span");
-            this.autoCompleteElement.className = "auto-complete-text";
-            this.autoCompleteElement.textContent = suffixText;
+                this.autoCompleteElement = document.createElement("span");
+                this.autoCompleteElement.className = "auto-complete-text";
+                this.autoCompleteElement.textContent = suffixText;
 
-            prefixTextNode.parentNode.insertBefore(this.autoCompleteElement, prefixTextNode.nextSibling);
+                prefixTextNode.parentNode.insertBefore(this.autoCompleteElement, prefixTextNode.nextSibling);
 
-            finalSelectionRange.setStart(prefixTextNode, wordPrefixLength);
-            finalSelectionRange.setEnd(prefixTextNode, wordPrefixLength);
-            selection.removeAllRanges();
-            selection.addRange(finalSelectionRange);
+                finalSelectionRange.setStart(prefixTextNode, wordPrefixLength);
+                finalSelectionRange.setEnd(prefixTextNode, wordPrefixLength);
+                selection.removeAllRanges();
+                selection.addRange(finalSelectionRange);
+            }
         } else
             this.applySuggestion(completionText, completions.length > 1, originalWordPrefixRange);
     },
@@ -565,7 +587,7 @@
         var foundNextText = false;
         while (node) {
             if (node.nodeType === Node.TEXT_NODE && node.nodeValue.length) {
-                if (foundNextText)
+                if (foundNextText && (!this.autoCompleteElement || !this.autoCompleteElement.isAncestor(node)))
                     return false;
                 foundNextText = true;
             }
@@ -635,10 +657,7 @@
 
     tabKeyPressed: function(event)
     {
-        if (this.isSuggestBoxVisible())
-            return this._suggestBox.tabKeyPressed(event);
-
-        this.complete(false, false, event.shiftKey);
+        // Just consume the key.
         return true;
     },
 
@@ -664,7 +683,23 @@
             return this._suggestBox.downKeyPressed(event);
 
         return false;
-    }
+    },
+
+    pageUpKeyPressed: function(event)
+    {
+        if (this.isSuggestBoxVisible())
+            return this._suggestBox.pageUpKeyPressed(event);
+
+        return false;
+    },
+
+    pageDownKeyPressed: function(event)
+    {
+        if (this.isSuggestBoxVisible())
+            return this._suggestBox.pageDownKeyPressed(event);
+
+        return false;
+    },
 }
 
 WebInspector.TextPrompt.prototype.__proto__ = WebInspector.Object.prototype;
@@ -987,31 +1022,59 @@
         return true;
     },
 
-    _onNextItem: function(event)
+    _onNextItem: function(event, isPageScroll)
     {
         var children = this.contentElement.childNodes;
         if (!children.length)
             return false;
 
-        if (this._selectedElement)
-            this._selectedElement = this._selectedElement.nextSibling || this.contentElement.firstChild;
-        else
+        if (!this._selectedElement)
             this._selectedElement = this.contentElement.firstChild;
+        else {
+            if (!isPageScroll)
+                this._selectedElement = this._selectedElement.nextSibling || this.contentElement.firstChild;
+            else {
+                var candidate = this._selectedElement;
+
+                for (var itemsLeft = this._rowCountPerViewport; itemsLeft; --itemsLeft) {
+                    if (candidate.nextSibling)
+                        candidate = candidate.nextSibling;
+                    else
+                        break;
+                }
+
+                this._selectedElement = candidate;
+            }
+        }
         this._updateSelection();
         this._applySuggestion(undefined, true);
         return true;
     },
 
-    _onPreviousItem: function(event)
+    _onPreviousItem: function(event, isPageScroll)
     {
         var children = this.contentElement.childNodes;
         if (!children.length)
             return false;
 
-        if (this._selectedElement)
-            this._selectedElement = this._selectedElement.previousSibling || this.contentElement.lastChild;
-        else
+        if (!this._selectedElement)
             this._selectedElement = this.contentElement.lastChild;
+        else {
+            if (!isPageScroll)
+                this._selectedElement = this._selectedElement.previousSibling || this.contentElement.lastChild;
+            else {
+                var candidate = this._selectedElement;
+
+                for (var itemsLeft = this._rowCountPerViewport; itemsLeft; --itemsLeft) {
+                    if (candidate.previousSibling)
+                        candidate = candidate.previousSibling;
+                    else
+                        break;
+                }
+
+                this._selectedElement = candidate;
+            }
+        }
         this._updateSelection();
         this._applySuggestion(undefined, true);
         return true;
@@ -1020,14 +1083,15 @@
     /**
      * @param {AnchorBox} anchorBox
      * @param {Array.<string>=} completions
+     * @param {boolean=} canShowForSingleItem
      */
-    updateSuggestions: function(anchorBox, completions)
+    updateSuggestions: function(anchorBox, completions, canShowForSingleItem)
     {
         if (this._suggestTimeout) {
             clearTimeout(this._suggestTimeout);
             delete this._suggestTimeout;
         }
-        this._completionsReady(anchorBox, completions);
+        this._completionsReady(anchorBox, completions, canShowForSingleItem);
     },
 
     _onItemMouseDown: function(text, event)
@@ -1055,14 +1119,11 @@
         return element;
     },
 
-    _updateItems: function(items)
+    /**
+     * @param {boolean=} canShowForSingleItem
+     */
+    _updateItems: function(items, canShowForSingleItem)
     {
-        var children = this.contentElement.children;
-        this._selectedIndex = Math.min(children.length - 1, this._selectedIndex);
-        var selectedItemText = this._selectedIndex >= 0 ? children[this._selectedIndex].textContent : null;
-        var itemIndex = 0;
-        var child = this.contentElement.firstChild;
-        var childText = child ? child.textContent : null;
         this.contentElement.removeChildren();
 
         var userEnteredText = this._textPrompt._userEnteredText;
@@ -1072,7 +1133,7 @@
             this.contentElement.appendChild(currentItemElement);
         }
 
-        this._selectedElement = this.contentElement.firstChild;
+        this._selectedElement = canShowForSingleItem ? this.contentElement.firstChild : null;
         this._updateSelection();
     },
 
@@ -1090,21 +1151,41 @@
     },
 
     /**
-     * @param {AnchorBox} anchorBox
      * @param {Array.<string>=} completions
+     * @param {boolean=} canShowForSingleItem
      */
-    _completionsReady: function(anchorBox, completions)
+    _canShowBox: function(completions, canShowForSingleItem)
     {
-        if (!completions || !completions.length) {
-            this.hide()
+        if (!completions || !completions.length)
+            return false;
+
+        if (completions.length > 1)
+            return true;
+
+        // Do not show a single suggestion if it is the same as user-entered prefix, even if allowed to show single-item suggest boxes.
+        return canShowForSingleItem && completions[0] !== this._textPrompt._userEnteredText;
+    },
+
+    _rememberRowCountPerViewport: function()
+    {
+        if (!this.contentElement.firstChild)
             return;
-        }
 
-        this._updateItems(completions);
-        this._updateBoxPosition(anchorBox);
-        if (this.contentElement.children.length && this.contentElement.children.length > 1) {
-            // Will not be shown if a sole suggestion is equal to the user input.
+        this._rowCountPerViewport = Math.floor(this.containerElement.offsetHeight / this.contentElement.firstChild.offsetHeight);
+    },
+
+    /**
+     * @param {AnchorBox} anchorBox
+     * @param {Array.<string>=} completions
+     * @param {boolean=} canShowForSingleItem
+     */
+    _completionsReady: function(anchorBox, completions, canShowForSingleItem)
+    {
+        if (this._canShowBox(completions, canShowForSingleItem)) {
+            this._updateItems(completions, canShowForSingleItem);
+            this._updateBoxPosition(anchorBox);
             this._element.addStyleClass("visible");
+            this._rememberRowCountPerViewport();
         } else
             this.hide();
     },
@@ -1119,10 +1200,24 @@
         return this._onNextItem(event);
     },
 
+    pageUpKeyPressed: function(event)
+    {
+        return this._onPreviousItem(event, true);
+    },
+
+    pageDownKeyPressed: function(event)
+    {
+        return this._onNextItem(event, true);
+    },
+
     enterKeyPressed: function(event)
     {
+        var hasSelectedItem = !!this._selectedElement;
         this.acceptSuggestion();
-        return true;
+
+        // Report the event as non-handled if there is no selected item,
+        // to commit the input or handle it otherwise.
+        return hasSelectedItem;
     },
 
     tabKeyPressed: function(event)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to