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

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

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