Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(595)

Side by Side Diff: Source/WebCore/inspector/front-end/TextPrompt.js

Issue 9252006: Merge 105140 - Web Inspector: [TextPrompt] Autocomplete adds unwanted text that's hard to remove (Closed) Base URL: http://svn.webkit.org/repository/webkit/branches/chromium/963/
Patch Set: Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/WebCore/inspector/front-end/StylesSidebarPane.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2011 Google Inc. All rights reserved. 3 * Copyright (C) 2011 Google Inc. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 8 *
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 WebInspector.setCurrentFocusElement(WebInspector.previousFocusElemen t()); 130 WebInspector.setCurrentFocusElement(WebInspector.previousFocusElemen t());
131 }, 131 },
132 132
133 get text() 133 get text()
134 { 134 {
135 return this._element.textContent; 135 return this._element.textContent;
136 }, 136 },
137 137
138 set text(x) 138 set text(x)
139 { 139 {
140 this.clearAutoComplete(true); 140 this._removeSuggestionAids();
141 if (!x) { 141 if (!x) {
142 // Append a break element instead of setting textContent to make sur e the selection is inside the prompt. 142 // Append a break element instead of setting textContent to make sur e the selection is inside the prompt.
143 this._element.removeChildren(); 143 this._element.removeChildren();
144 this._element.appendChild(document.createElement("br")); 144 this._element.appendChild(document.createElement("br"));
145 } else 145 } else
146 this._element.textContent = x; 146 this._element.textContent = x;
147 147
148 this.moveCaretToEndOfPrompt(); 148 this.moveCaretToEndOfPrompt();
149 this._element.scrollIntoView(); 149 this._element.scrollIntoView();
150 }, 150 },
(...skipping 28 matching lines...) Expand all
179 _stopEditing: function() 179 _stopEditing: function()
180 { 180 {
181 this._element.tabIndex = this._oldTabIndex; 181 this._element.tabIndex = this._oldTabIndex;
182 if (this._blurListener) 182 if (this._blurListener)
183 this._element.removeEventListener("blur", this._blurListener, false) ; 183 this._element.removeEventListener("blur", this._blurListener, false) ;
184 this._element.removeStyleClass("editing"); 184 this._element.removeStyleClass("editing");
185 delete this._isEditing; 185 delete this._isEditing;
186 WebInspector.markBeingEdited(this._element, false); 186 WebInspector.markBeingEdited(this._element, false);
187 }, 187 },
188 188
189 _removeSuggestionAids: function()
190 {
191 this.clearAutoComplete();
192 this.hideSuggestBox();
193 },
194
189 _selectStart: function(event) 195 _selectStart: function(event)
190 { 196 {
191 if (this._selectionTimeout) 197 if (this._selectionTimeout)
192 clearTimeout(this._selectionTimeout); 198 clearTimeout(this._selectionTimeout);
193 199
194 this.clearAutoComplete(); 200 this._removeSuggestionAids();
195 201
196 function moveBackIfOutside() 202 function moveBackIfOutside()
197 { 203 {
198 delete this._selectionTimeout; 204 delete this._selectionTimeout;
199 if (!this.isCaretInsidePrompt() && window.getSelection().isCollapsed ) 205 if (!this.isCaretInsidePrompt() && window.getSelection().isCollapsed ) {
200 this.moveCaretToEndOfPrompt(); 206 this.moveCaretToEndOfPrompt();
201 this.autoCompleteSoon(); 207 this.autoCompleteSoon();
208 }
202 } 209 }
203 210
204 this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100); 211 this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100);
205 }, 212 },
206 213
207 /** 214 /**
208 * @param {boolean=} force 215 * @param {boolean=} force
209 */ 216 */
210 defaultKeyHandler: function(event, force) 217 defaultKeyHandler: function(event, force)
211 { 218 {
212 this.clearAutoComplete(); 219 this.clearAutoComplete();
213 this.autoCompleteSoon(force); 220 this.autoCompleteSoon(force);
214 return false; 221 return false;
215 }, 222 },
216 223
217 onKeyDown: function(event) 224 onKeyDown: function(event)
218 { 225 {
219 var handled = false; 226 var handled = false;
220 var invokeDefault = true; 227 var invokeDefault = true;
221 228
222 switch (event.keyIdentifier) { 229 switch (event.keyIdentifier) {
223 case "Up": 230 case "Up":
224 handled = this.upKeyPressed(event); 231 handled = this.upKeyPressed(event);
225 break; 232 break;
226 case "Down": 233 case "Down":
227 handled = this.downKeyPressed(event); 234 handled = this.downKeyPressed(event);
228 break; 235 break;
236 case "PageUp":
237 handled = this.pageUpKeyPressed(event);
238 break;
239 case "PageDown":
240 handled = this.pageDownKeyPressed(event);
241 break;
229 case "U+0009": // Tab 242 case "U+0009": // Tab
230 handled = this.tabKeyPressed(event); 243 handled = this.tabKeyPressed(event);
231 break; 244 break;
232 case "Enter": 245 case "Enter":
233 handled = this.enterKeyPressed(event); 246 handled = this.enterKeyPressed(event);
234 break; 247 break;
248 case "Left":
249 case "Home":
250 this._removeSuggestionAids();
251 invokeDefault = false;
252 break;
235 case "Right": 253 case "Right":
236 case "End": 254 case "End":
237 if (this.isSuggestBoxVisible() && this.isCaretAtEndOfPrompt()) 255 if (this.isCaretAtEndOfPrompt())
238 handled = this._suggestBox.tabKeyPressed(event);
239 else {
240 handled = this.acceptAutoComplete(); 256 handled = this.acceptAutoComplete();
241 if (!handled) 257 else
242 this.autoCompleteSoon(); 258 this._removeSuggestionAids();
243 } 259 invokeDefault = false;
244 break; 260 break;
245 case "U+001B": // Esc 261 case "U+001B": // Esc
246 if (this.isSuggestBoxVisible()) { 262 if (this.isSuggestBoxVisible()) {
247 this._suggestBox.hide(); 263 this._suggestBox.hide();
248 handled = true; 264 handled = true;
249 break;
250 } 265 }
266 break;
251 case "U+0020": // Space 267 case "U+0020": // Space
252 if (this._suggestForceable && event.ctrlKey && !event.metaKey && !ev ent.altKey && !event.shiftKey) { 268 if (this._suggestForceable && event.ctrlKey && !event.metaKey && !ev ent.altKey && !event.shiftKey) {
253 this.defaultKeyHandler(event, true); 269 this.defaultKeyHandler(event, true);
254 handled = true; 270 handled = true;
255 } 271 }
256 break; 272 break;
257 case "Alt": 273 case "Alt":
258 case "Meta": 274 case "Meta":
259 case "Shift": 275 case "Shift":
260 case "Control": 276 case "Control":
261 invokeDefault = false; 277 invokeDefault = false;
262 break; 278 break;
263 } 279 }
264 280
265 if (!handled && invokeDefault) 281 if (!handled && invokeDefault)
266 handled = this.defaultKeyHandler(event); 282 handled = this.defaultKeyHandler(event);
267 283
268 if (handled) { 284 if (handled) {
269 event.preventDefault(); 285 event.preventDefault();
270 event.stopPropagation(); 286 event.stopPropagation();
271 } 287 }
272 288
273 return handled; 289 return handled;
274 }, 290 },
275 291
276 acceptAutoComplete: function() 292 acceptAutoComplete: function()
277 { 293 {
294 var result = false;
278 if (this.isSuggestBoxVisible()) 295 if (this.isSuggestBoxVisible())
279 return this._suggestBox.acceptSuggestion(); 296 result = this._suggestBox.acceptSuggestion();
280 return this.acceptSuggestion(); 297 if (!result)
298 result = this.acceptSuggestion();
299
300 return result;
281 }, 301 },
282 302
283 /** 303 /**
284 * @param {boolean=} includeTimeout 304 * @param {boolean=} includeTimeout
285 */ 305 */
286 clearAutoComplete: function(includeTimeout) 306 clearAutoComplete: function(includeTimeout)
287 { 307 {
288 if (includeTimeout && this._completeTimeout) { 308 if (includeTimeout && this._completeTimeout) {
289 clearTimeout(this._completeTimeout); 309 clearTimeout(this._completeTimeout);
290 delete this._completeTimeout; 310 delete this._completeTimeout;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 var selectionRange = selection.getRangeAt(0); 361 var selectionRange = selection.getRangeAt(0);
342 var isEmptyInput = selectionRange.commonAncestorContainer === this._elem ent; // this._element has no child Text nodes. 362 var isEmptyInput = selectionRange.commonAncestorContainer === this._elem ent; // this._element has no child Text nodes.
343 363
344 var shouldExit; 364 var shouldExit;
345 365
346 // Do not attempt to auto-complete an empty input in the auto mode (only on demand). 366 // Do not attempt to auto-complete an empty input in the auto mode (only on demand).
347 if (auto && isEmptyInput && !force) 367 if (auto && isEmptyInput && !force)
348 shouldExit = true; 368 shouldExit = true;
349 else if (!auto && !isEmptyInput && !selectionRange.commonAncestorContain er.isDescendant(this._element)) 369 else if (!auto && !isEmptyInput && !selectionRange.commonAncestorContain er.isDescendant(this._element))
350 shouldExit = true; 370 shouldExit = true;
351 else if (auto && !this._suggestBox && !force && !this.isCaretAtEndOfProm pt()) 371 else if (auto && !force && !this.isCaretAtEndOfPrompt() && !this.isSugge stBoxVisible())
352 shouldExit = true; 372 shouldExit = true;
353 else if (!selection.isCollapsed) 373 else if (!selection.isCollapsed)
354 shouldExit = true; 374 shouldExit = true;
355 else if (!force) { 375 else if (!force) {
356 // BUG72018: Do not show suggest box if caret is followed by a non-s top character. 376 // BUG72018: Do not show suggest box if caret is followed by a non-s top character.
357 var wordSuffixRange = selectionRange.startContainer.rangeOfWord(sele ctionRange.endOffset, this._completionStopCharacters, this._element, "forward"); 377 var wordSuffixRange = selectionRange.startContainer.rangeOfWord(sele ctionRange.endOffset, this._completionStopCharacters, this._element, "forward");
358 if (wordSuffixRange.toString().length) 378 if (wordSuffixRange.toString().length)
359 shouldExit = true; 379 shouldExit = true;
360 } 380 }
361 if (shouldExit) { 381 if (shouldExit) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 fullWordRange.setStart(originalWordPrefixRange.startContainer, originalW ordPrefixRange.startOffset); 418 fullWordRange.setStart(originalWordPrefixRange.startContainer, originalW ordPrefixRange.startOffset);
399 fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffs et); 419 fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffs et);
400 420
401 if (originalWordPrefixRange.toString() + selectionRange.toString() != fu llWordRange.toString()) 421 if (originalWordPrefixRange.toString() + selectionRange.toString() != fu llWordRange.toString())
402 return; 422 return;
403 423
404 this._userEnteredRange = fullWordRange; 424 this._userEnteredRange = fullWordRange;
405 this._userEnteredText = fullWordRange.toString(); 425 this._userEnteredText = fullWordRange.toString();
406 426
407 if (this._suggestBox) 427 if (this._suggestBox)
408 this._suggestBox.updateSuggestions(this._boxForAnchorAtStart(selecti on, fullWordRange), completions); 428 this._suggestBox.updateSuggestions(this._boxForAnchorAtStart(selecti on, fullWordRange), completions, !this.isCaretAtEndOfPrompt());
409 429
410 var wordPrefixLength = originalWordPrefixRange.toString().length; 430 var wordPrefixLength = originalWordPrefixRange.toString().length;
411 431
412 if (auto) 432 if (auto)
413 var completionText = completions[0]; 433 var completionText = completions[0];
414 else { 434 else {
415 if (completions.length === 1) { 435 if (completions.length === 1) {
416 var completionText = completions[0]; 436 var completionText = completions[0];
417 wordPrefixLength = completionText.length; 437 wordPrefixLength = completionText.length;
418 } else { 438 } else {
(...skipping 26 matching lines...) Expand all
445 var completionText = completions[0]; 465 var completionText = completions[0];
446 else if (nextIndex < 0) 466 else if (nextIndex < 0)
447 var completionText = completions[completions.length - 1] ; 467 var completionText = completions[completions.length - 1] ;
448 else 468 else
449 var completionText = completions[nextIndex]; 469 var completionText = completions[nextIndex];
450 } 470 }
451 } 471 }
452 } 472 }
453 473
454 if (auto) { 474 if (auto) {
455 this._userEnteredRange.deleteContents(); 475 if (this.isCaretAtEndOfPrompt()) {
456 this._element.pruneEmptyTextNodes(); 476 this._userEnteredRange.deleteContents();
457 var finalSelectionRange = document.createRange(); 477 this._element.pruneEmptyTextNodes();
458 var prefixText = completionText.substring(0, wordPrefixLength); 478 var finalSelectionRange = document.createRange();
459 var suffixText = completionText.substring(wordPrefixLength); 479 var prefixText = completionText.substring(0, wordPrefixLength);
480 var suffixText = completionText.substring(wordPrefixLength);
460 481
461 var prefixTextNode = document.createTextNode(prefixText); 482 var prefixTextNode = document.createTextNode(prefixText);
462 fullWordRange.insertNode(prefixTextNode); 483 fullWordRange.insertNode(prefixTextNode);
463 484
464 this.autoCompleteElement = document.createElement("span"); 485 this.autoCompleteElement = document.createElement("span");
465 this.autoCompleteElement.className = "auto-complete-text"; 486 this.autoCompleteElement.className = "auto-complete-text";
466 this.autoCompleteElement.textContent = suffixText; 487 this.autoCompleteElement.textContent = suffixText;
467 488
468 prefixTextNode.parentNode.insertBefore(this.autoCompleteElement, pre fixTextNode.nextSibling); 489 prefixTextNode.parentNode.insertBefore(this.autoCompleteElement, prefixTextNode.nextSibling);
469 490
470 finalSelectionRange.setStart(prefixTextNode, wordPrefixLength); 491 finalSelectionRange.setStart(prefixTextNode, wordPrefixLength);
471 finalSelectionRange.setEnd(prefixTextNode, wordPrefixLength); 492 finalSelectionRange.setEnd(prefixTextNode, wordPrefixLength);
472 selection.removeAllRanges(); 493 selection.removeAllRanges();
473 selection.addRange(finalSelectionRange); 494 selection.addRange(finalSelectionRange);
495 }
474 } else 496 } else
475 this.applySuggestion(completionText, completions.length > 1, origina lWordPrefixRange); 497 this.applySuggestion(completionText, completions.length > 1, origina lWordPrefixRange);
476 }, 498 },
477 499
478 /** 500 /**
479 * @param {Range=} originalPrefixRange 501 * @param {Range=} originalPrefixRange
480 */ 502 */
481 applySuggestion: function(completionText, isIntermediateSuggestion, original PrefixRange) 503 applySuggestion: function(completionText, isIntermediateSuggestion, original PrefixRange)
482 { 504 {
483 var wordPrefixLength; 505 var wordPrefixLength;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 var node = selectionRange.startContainer; 580 var node = selectionRange.startContainer;
559 if (node !== this._element && !node.isDescendant(this._element)) 581 if (node !== this._element && !node.isDescendant(this._element))
560 return false; 582 return false;
561 583
562 if (node.nodeType === Node.TEXT_NODE && selectionRange.startOffset < nod e.nodeValue.length) 584 if (node.nodeType === Node.TEXT_NODE && selectionRange.startOffset < nod e.nodeValue.length)
563 return false; 585 return false;
564 586
565 var foundNextText = false; 587 var foundNextText = false;
566 while (node) { 588 while (node) {
567 if (node.nodeType === Node.TEXT_NODE && node.nodeValue.length) { 589 if (node.nodeType === Node.TEXT_NODE && node.nodeValue.length) {
568 if (foundNextText) 590 if (foundNextText && (!this.autoCompleteElement || !this.autoCom pleteElement.isAncestor(node)))
569 return false; 591 return false;
570 foundNextText = true; 592 foundNextText = true;
571 } 593 }
572 594
573 node = node.traverseNextNode(this._element); 595 node = node.traverseNextNode(this._element);
574 } 596 }
575 597
576 return true; 598 return true;
577 }, 599 },
578 600
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 var offset = this._element.childNodes.length; 650 var offset = this._element.childNodes.length;
629 selectionRange.setStart(this._element, offset); 651 selectionRange.setStart(this._element, offset);
630 selectionRange.setEnd(this._element, offset); 652 selectionRange.setEnd(this._element, offset);
631 653
632 selection.removeAllRanges(); 654 selection.removeAllRanges();
633 selection.addRange(selectionRange); 655 selection.addRange(selectionRange);
634 }, 656 },
635 657
636 tabKeyPressed: function(event) 658 tabKeyPressed: function(event)
637 { 659 {
638 if (this.isSuggestBoxVisible()) 660 // Just consume the key.
639 return this._suggestBox.tabKeyPressed(event);
640
641 this.complete(false, false, event.shiftKey);
642 return true; 661 return true;
643 }, 662 },
644 663
645 enterKeyPressed: function(event) 664 enterKeyPressed: function(event)
646 { 665 {
647 if (this.isSuggestBoxVisible()) 666 if (this.isSuggestBoxVisible())
648 return this._suggestBox.enterKeyPressed(event); 667 return this._suggestBox.enterKeyPressed(event);
649 668
650 return false; 669 return false;
651 }, 670 },
652 671
653 upKeyPressed: function(event) 672 upKeyPressed: function(event)
654 { 673 {
655 if (this.isSuggestBoxVisible()) 674 if (this.isSuggestBoxVisible())
656 return this._suggestBox.upKeyPressed(event); 675 return this._suggestBox.upKeyPressed(event);
657 676
658 return false; 677 return false;
659 }, 678 },
660 679
661 downKeyPressed: function(event) 680 downKeyPressed: function(event)
662 { 681 {
663 if (this.isSuggestBoxVisible()) 682 if (this.isSuggestBoxVisible())
664 return this._suggestBox.downKeyPressed(event); 683 return this._suggestBox.downKeyPressed(event);
665 684
666 return false; 685 return false;
667 } 686 },
687
688 pageUpKeyPressed: function(event)
689 {
690 if (this.isSuggestBoxVisible())
691 return this._suggestBox.pageUpKeyPressed(event);
692
693 return false;
694 },
695
696 pageDownKeyPressed: function(event)
697 {
698 if (this.isSuggestBoxVisible())
699 return this._suggestBox.pageDownKeyPressed(event);
700
701 return false;
702 },
668 } 703 }
669 704
670 WebInspector.TextPrompt.prototype.__proto__ = WebInspector.Object.prototype; 705 WebInspector.TextPrompt.prototype.__proto__ = WebInspector.Object.prototype;
671 706
672 /** 707 /**
673 * @constructor 708 * @constructor
674 * @extends {WebInspector.TextPrompt} 709 * @extends {WebInspector.TextPrompt}
675 * @param {function(Range, boolean, function(*))} completions 710 * @param {function(Range, boolean, function(*))} completions
676 * @param {string} stopCharacters 711 * @param {string} stopCharacters
677 */ 712 */
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
980 var result = this._applySuggestion(text, false); 1015 var result = this._applySuggestion(text, false);
981 this.hide(); 1016 this.hide();
982 if (!result) 1017 if (!result)
983 return false; 1018 return false;
984 1019
985 this._textPrompt.acceptSuggestion(); 1020 this._textPrompt.acceptSuggestion();
986 1021
987 return true; 1022 return true;
988 }, 1023 },
989 1024
990 _onNextItem: function(event) 1025 _onNextItem: function(event, isPageScroll)
991 { 1026 {
992 var children = this.contentElement.childNodes; 1027 var children = this.contentElement.childNodes;
993 if (!children.length) 1028 if (!children.length)
994 return false; 1029 return false;
995 1030
996 if (this._selectedElement) 1031 if (!this._selectedElement)
997 this._selectedElement = this._selectedElement.nextSibling || this.co ntentElement.firstChild;
998 else
999 this._selectedElement = this.contentElement.firstChild; 1032 this._selectedElement = this.contentElement.firstChild;
1033 else {
1034 if (!isPageScroll)
1035 this._selectedElement = this._selectedElement.nextSibling || thi s.contentElement.firstChild;
1036 else {
1037 var candidate = this._selectedElement;
1038
1039 for (var itemsLeft = this._rowCountPerViewport; itemsLeft; --ite msLeft) {
1040 if (candidate.nextSibling)
1041 candidate = candidate.nextSibling;
1042 else
1043 break;
1044 }
1045
1046 this._selectedElement = candidate;
1047 }
1048 }
1000 this._updateSelection(); 1049 this._updateSelection();
1001 this._applySuggestion(undefined, true); 1050 this._applySuggestion(undefined, true);
1002 return true; 1051 return true;
1003 }, 1052 },
1004 1053
1005 _onPreviousItem: function(event) 1054 _onPreviousItem: function(event, isPageScroll)
1006 { 1055 {
1007 var children = this.contentElement.childNodes; 1056 var children = this.contentElement.childNodes;
1008 if (!children.length) 1057 if (!children.length)
1009 return false; 1058 return false;
1010 1059
1011 if (this._selectedElement) 1060 if (!this._selectedElement)
1012 this._selectedElement = this._selectedElement.previousSibling || thi s.contentElement.lastChild;
1013 else
1014 this._selectedElement = this.contentElement.lastChild; 1061 this._selectedElement = this.contentElement.lastChild;
1062 else {
1063 if (!isPageScroll)
1064 this._selectedElement = this._selectedElement.previousSibling || this.contentElement.lastChild;
1065 else {
1066 var candidate = this._selectedElement;
1067
1068 for (var itemsLeft = this._rowCountPerViewport; itemsLeft; --ite msLeft) {
1069 if (candidate.previousSibling)
1070 candidate = candidate.previousSibling;
1071 else
1072 break;
1073 }
1074
1075 this._selectedElement = candidate;
1076 }
1077 }
1015 this._updateSelection(); 1078 this._updateSelection();
1016 this._applySuggestion(undefined, true); 1079 this._applySuggestion(undefined, true);
1017 return true; 1080 return true;
1018 }, 1081 },
1019 1082
1020 /** 1083 /**
1021 * @param {AnchorBox} anchorBox 1084 * @param {AnchorBox} anchorBox
1022 * @param {Array.<string>=} completions 1085 * @param {Array.<string>=} completions
1086 * @param {boolean=} canShowForSingleItem
1023 */ 1087 */
1024 updateSuggestions: function(anchorBox, completions) 1088 updateSuggestions: function(anchorBox, completions, canShowForSingleItem)
1025 { 1089 {
1026 if (this._suggestTimeout) { 1090 if (this._suggestTimeout) {
1027 clearTimeout(this._suggestTimeout); 1091 clearTimeout(this._suggestTimeout);
1028 delete this._suggestTimeout; 1092 delete this._suggestTimeout;
1029 } 1093 }
1030 this._completionsReady(anchorBox, completions); 1094 this._completionsReady(anchorBox, completions, canShowForSingleItem);
1031 }, 1095 },
1032 1096
1033 _onItemMouseDown: function(text, event) 1097 _onItemMouseDown: function(text, event)
1034 { 1098 {
1035 this.acceptSuggestion(text); 1099 this.acceptSuggestion(text);
1036 event.stopPropagation(); 1100 event.stopPropagation();
1037 event.preventDefault(); 1101 event.preventDefault();
1038 }, 1102 },
1039 1103
1040 _createItemElement: function(prefix, text) 1104 _createItemElement: function(prefix, text)
1041 { 1105 {
1042 var element = document.createElement("div"); 1106 var element = document.createElement("div");
1043 element.className = "suggest-box-content-item source-code"; 1107 element.className = "suggest-box-content-item source-code";
1044 element.tabIndex = -1; 1108 element.tabIndex = -1;
1045 if (prefix && prefix.length && !text.indexOf(prefix)) { 1109 if (prefix && prefix.length && !text.indexOf(prefix)) {
1046 var prefixElement = element.createChild("span", "prefix"); 1110 var prefixElement = element.createChild("span", "prefix");
1047 prefixElement.textContent = prefix; 1111 prefixElement.textContent = prefix;
1048 var suffixElement = element.createChild("span", "suffix"); 1112 var suffixElement = element.createChild("span", "suffix");
1049 suffixElement.textContent = text.substring(prefix.length); 1113 suffixElement.textContent = text.substring(prefix.length);
1050 } else { 1114 } else {
1051 var suffixElement = element.createChild("span", "suffix"); 1115 var suffixElement = element.createChild("span", "suffix");
1052 suffixElement.textContent = text; 1116 suffixElement.textContent = text;
1053 } 1117 }
1054 element.addEventListener("mousedown", this._onItemMouseDown.bind(this, t ext), false); 1118 element.addEventListener("mousedown", this._onItemMouseDown.bind(this, t ext), false);
1055 return element; 1119 return element;
1056 }, 1120 },
1057 1121
1058 _updateItems: function(items) 1122 /**
1123 * @param {boolean=} canShowForSingleItem
1124 */
1125 _updateItems: function(items, canShowForSingleItem)
1059 { 1126 {
1060 var children = this.contentElement.children;
1061 this._selectedIndex = Math.min(children.length - 1, this._selectedIndex) ;
1062 var selectedItemText = this._selectedIndex >= 0 ? children[this._selecte dIndex].textContent : null;
1063 var itemIndex = 0;
1064 var child = this.contentElement.firstChild;
1065 var childText = child ? child.textContent : null;
1066 this.contentElement.removeChildren(); 1127 this.contentElement.removeChildren();
1067 1128
1068 var userEnteredText = this._textPrompt._userEnteredText; 1129 var userEnteredText = this._textPrompt._userEnteredText;
1069 for (var i = 0; i < items.length; ++i) { 1130 for (var i = 0; i < items.length; ++i) {
1070 var item = items[i]; 1131 var item = items[i];
1071 var currentItemElement = this._createItemElement(userEnteredText, it em); 1132 var currentItemElement = this._createItemElement(userEnteredText, it em);
1072 this.contentElement.appendChild(currentItemElement); 1133 this.contentElement.appendChild(currentItemElement);
1073 } 1134 }
1074 1135
1075 this._selectedElement = this.contentElement.firstChild; 1136 this._selectedElement = canShowForSingleItem ? this.contentElement.first Child : null;
1076 this._updateSelection(); 1137 this._updateSelection();
1077 }, 1138 },
1078 1139
1079 _updateSelection: function() 1140 _updateSelection: function()
1080 { 1141 {
1081 // FIXME: might want some optimization if becomes a bottleneck. 1142 // FIXME: might want some optimization if becomes a bottleneck.
1082 for (var child = this.contentElement.firstChild; child; child = child.ne xtSibling) { 1143 for (var child = this.contentElement.firstChild; child; child = child.ne xtSibling) {
1083 if (child !== this._selectedElement) 1144 if (child !== this._selectedElement)
1084 child.removeStyleClass("selected"); 1145 child.removeStyleClass("selected");
1085 } 1146 }
1086 if (this._selectedElement) { 1147 if (this._selectedElement) {
1087 this._selectedElement.addStyleClass("selected"); 1148 this._selectedElement.addStyleClass("selected");
1088 this._selectedElement.scrollIntoViewIfNeeded(false); 1149 this._selectedElement.scrollIntoViewIfNeeded(false);
1089 } 1150 }
1090 }, 1151 },
1091 1152
1092 /** 1153 /**
1154 * @param {Array.<string>=} completions
1155 * @param {boolean=} canShowForSingleItem
1156 */
1157 _canShowBox: function(completions, canShowForSingleItem)
1158 {
1159 if (!completions || !completions.length)
1160 return false;
1161
1162 if (completions.length > 1)
1163 return true;
1164
1165 // Do not show a single suggestion if it is the same as user-entered pre fix, even if allowed to show single-item suggest boxes.
1166 return canShowForSingleItem && completions[0] !== this._textPrompt._user EnteredText;
1167 },
1168
1169 _rememberRowCountPerViewport: function()
1170 {
1171 if (!this.contentElement.firstChild)
1172 return;
1173
1174 this._rowCountPerViewport = Math.floor(this.containerElement.offsetHeigh t / this.contentElement.firstChild.offsetHeight);
1175 },
1176
1177 /**
1093 * @param {AnchorBox} anchorBox 1178 * @param {AnchorBox} anchorBox
1094 * @param {Array.<string>=} completions 1179 * @param {Array.<string>=} completions
1180 * @param {boolean=} canShowForSingleItem
1095 */ 1181 */
1096 _completionsReady: function(anchorBox, completions) 1182 _completionsReady: function(anchorBox, completions, canShowForSingleItem)
1097 { 1183 {
1098 if (!completions || !completions.length) { 1184 if (this._canShowBox(completions, canShowForSingleItem)) {
1099 this.hide() 1185 this._updateItems(completions, canShowForSingleItem);
1100 return; 1186 this._updateBoxPosition(anchorBox);
1101 }
1102
1103 this._updateItems(completions);
1104 this._updateBoxPosition(anchorBox);
1105 if (this.contentElement.children.length && this.contentElement.children. length > 1) {
1106 // Will not be shown if a sole suggestion is equal to the user input .
1107 this._element.addStyleClass("visible"); 1187 this._element.addStyleClass("visible");
1188 this._rememberRowCountPerViewport();
1108 } else 1189 } else
1109 this.hide(); 1190 this.hide();
1110 }, 1191 },
1111 1192
1112 upKeyPressed: function(event) 1193 upKeyPressed: function(event)
1113 { 1194 {
1114 return this._onPreviousItem(event); 1195 return this._onPreviousItem(event);
1115 }, 1196 },
1116 1197
1117 downKeyPressed: function(event) 1198 downKeyPressed: function(event)
1118 { 1199 {
1119 return this._onNextItem(event); 1200 return this._onNextItem(event);
1120 }, 1201 },
1121 1202
1203 pageUpKeyPressed: function(event)
1204 {
1205 return this._onPreviousItem(event, true);
1206 },
1207
1208 pageDownKeyPressed: function(event)
1209 {
1210 return this._onNextItem(event, true);
1211 },
1212
1122 enterKeyPressed: function(event) 1213 enterKeyPressed: function(event)
1123 { 1214 {
1215 var hasSelectedItem = !!this._selectedElement;
1124 this.acceptSuggestion(); 1216 this.acceptSuggestion();
1125 return true; 1217
1218 // Report the event as non-handled if there is no selected item,
1219 // to commit the input or handle it otherwise.
1220 return hasSelectedItem;
1126 }, 1221 },
1127 1222
1128 tabKeyPressed: function(event) 1223 tabKeyPressed: function(event)
1129 { 1224 {
1130 return this.enterKeyPressed(event); 1225 return this.enterKeyPressed(event);
1131 } 1226 }
1132 } 1227 }
OLDNEW
« no previous file with comments | « Source/WebCore/inspector/front-end/StylesSidebarPane.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698