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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js

Issue 2285993002: DevTools: Fix flickering hint when typing in TextPrompt (Closed)
Patch Set: Merge Created 4 years, 3 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 | « third_party/WebKit/LayoutTests/inspector/text-prompt-hint-expected.txt ('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 27 matching lines...) Expand all
38 { 38 {
39 /** 39 /**
40 * @type {!Element|undefined} 40 * @type {!Element|undefined}
41 */ 41 */
42 this._proxyElement; 42 this._proxyElement;
43 this._proxyElementDisplay = "inline-block"; 43 this._proxyElementDisplay = "inline-block";
44 this._loadCompletions = completions; 44 this._loadCompletions = completions;
45 this._completionStopCharacters = stopCharacters || " =:[({;,!+-*/&|^<>."; 45 this._completionStopCharacters = stopCharacters || " =:[({;,!+-*/&|^<>.";
46 this._autocompletionTimeout = WebInspector.TextPrompt.DefaultAutocompletionT imeout; 46 this._autocompletionTimeout = WebInspector.TextPrompt.DefaultAutocompletionT imeout;
47 this._title = ""; 47 this._title = "";
48 this._previousText = "";
48 } 49 }
49 50
50 WebInspector.TextPrompt.DefaultAutocompletionTimeout = 250; 51 WebInspector.TextPrompt.DefaultAutocompletionTimeout = 250;
51 52
52 /** @enum {symbol} */ 53 /** @enum {symbol} */
53 WebInspector.TextPrompt.Events = { 54 WebInspector.TextPrompt.Events = {
54 ItemApplied: Symbol("text-prompt-item-applied"), 55 ItemApplied: Symbol("text-prompt-item-applied"),
55 ItemAccepted: Symbol("text-prompt-item-accepted") 56 ItemAccepted: Symbol("text-prompt-item-accepted")
56 }; 57 };
57 58
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 setText: function(x) 183 setText: function(x)
183 { 184 {
184 this.clearAutoComplete(); 185 this.clearAutoComplete();
185 if (!x) { 186 if (!x) {
186 // Append a break element instead of setting textContent to make sur e the selection is inside the prompt. 187 // Append a break element instead of setting textContent to make sur e the selection is inside the prompt.
187 this._element.removeChildren(); 188 this._element.removeChildren();
188 this._element.createChild("br"); 189 this._element.createChild("br");
189 } else { 190 } else {
190 this._element.textContent = x; 191 this._element.textContent = x;
191 } 192 }
193 this._previousText = this.userEnteredText();
192 194
193 this.moveCaretToEndOfPrompt(); 195 this.moveCaretToEndOfPrompt();
194 this._element.scrollIntoView(); 196 this._element.scrollIntoView();
195 }, 197 },
196 198
197 /** 199 /**
198 * @return {string} 200 * @return {string}
199 */ 201 */
200 title: function() 202 title: function()
201 { 203 {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 } 276 }
275 277
276 this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100); 278 this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100);
277 }, 279 },
278 280
279 /** 281 /**
280 * @param {boolean=} force 282 * @param {boolean=} force
281 */ 283 */
282 _updateAutoComplete: function(force) 284 _updateAutoComplete: function(force)
283 { 285 {
284 this.clearAutoComplete(); 286 var clearHint = true;
287 if (this.autoCompleteElement) {
288 var text = this.userEnteredText();
289 if (this._previousText === text.substring(0, text.length - 1)) {
290 this._hintPrefix += this.autoCompleteElement.textContent.charAt( 0);
291 this.autoCompleteElement.textContent = this.autoCompleteElement. textContent.substring(1);
292 clearHint = false;
293 } else if (this._previousText.substring(0, this._previousText.length - 1) === text) {
lushnikov 2016/09/07 22:11:01 let's use .startsWith?
einbinder 2016/10/18 00:57:33 Done.
294 this.autoCompleteElement.textContent = this._hintPrefix.charAt(t his._hintPrefix.length - 1) + this.autoCompleteElement.textContent;
295 this._hintPrefix = this._hintPrefix.substring(0, this._hintPrefi x.length - 1);
296 clearHint = false;
297 }
298 }
299 if (clearHint)
300 this.clearAutoComplete();
301 delete this._waitingForCompletions;
lushnikov 2016/09/07 22:11:01 why would you need to delete this? The _waitingFo
einbinder 2016/10/18 00:57:33 Done.
285 this.autoCompleteSoon(force); 302 this.autoCompleteSoon(force);
286 }, 303 },
287 304
288 /** 305 /**
289 * @param {!Event} event 306 * @param {!Event} event
290 */ 307 */
291 onMouseWheel: function(event) 308 onMouseWheel: function(event)
292 { 309 {
293 // Subclasses can implement. 310 // Subclasses can implement.
294 }, 311 },
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 event.consume(true); 365 event.consume(true);
349 }, 366 },
350 367
351 /** 368 /**
352 * @param {!Event} event 369 * @param {!Event} event
353 */ 370 */
354 onInput: function(event) 371 onInput: function(event)
355 { 372 {
356 if (this._needUpdateAutocomplete) 373 if (this._needUpdateAutocomplete)
357 this._updateAutoComplete(); 374 this._updateAutoComplete();
375 this._previousText = this.userEnteredText();
358 }, 376 },
359 377
360 /** 378 /**
361 * @return {boolean} 379 * @return {boolean}
362 */ 380 */
363 acceptAutoComplete: function() 381 acceptAutoComplete: function()
364 { 382 {
365 var result = false; 383 var result = false;
366 if (this.isSuggestBoxVisible()) 384 if (this.isSuggestBoxVisible())
367 result = this._suggestBox.acceptSuggestion(); 385 result = this._suggestBox.acceptSuggestion();
368 if (!result) 386 if (!result)
369 result = this._acceptSuggestionInternal(); 387 result = this._acceptSuggestionInternal();
370 388
371 return result; 389 return result;
372 }, 390 },
373 391
374 clearAutoComplete: function() 392 clearAutoComplete: function()
375 { 393 {
376 if (this.isSuggestBoxVisible()) 394 if (this.isSuggestBoxVisible())
377 this._suggestBox.hide(); 395 this._suggestBox.hide();
378 396
379 if (this._completeTimeout) { 397 this._clearAutocompleteTimeout();
380 clearTimeout(this._completeTimeout); 398
381 delete this._completeTimeout;
382 }
383 delete this._waitingForCompletions; 399 delete this._waitingForCompletions;
384 400
385 if (!this.autoCompleteElement) 401 if (!this.autoCompleteElement)
386 return; 402 return;
387 403
388 this.autoCompleteElement.remove(); 404 this.autoCompleteElement.remove();
389 delete this.autoCompleteElement; 405 delete this.autoCompleteElement;
390 delete this._userEnteredRange; 406 delete this._userEnteredRange;
391 delete this._userEnteredText; 407 delete this._userEnteredText;
392 }, 408 },
393 409
410 _clearAutocompleteTimeout: function()
411 {
412 if (this._completeTimeout) {
413 clearTimeout(this._completeTimeout);
414 delete this._completeTimeout;
415 }
416 },
417
394 /** 418 /**
395 * @param {boolean=} force 419 * @param {boolean=} force
396 */ 420 */
397 autoCompleteSoon: function(force) 421 autoCompleteSoon: function(force)
398 { 422 {
399 var immediately = this.isSuggestBoxVisible() || force; 423 var immediately = this.isSuggestBoxVisible() || force;
400 if (!this._completeTimeout) 424 if (!this._completeTimeout)
401 this._completeTimeout = setTimeout(this.complete.bind(this, force), immediately ? 0 : this._autocompletionTimeout); 425 this._completeTimeout = setTimeout(this.complete.bind(this, force), immediately ? 0 : this._autocompletionTimeout);
402 }, 426 },
403 427
404 /** 428 /**
405 * @param {boolean=} force 429 * @param {boolean=} force
406 * @param {boolean=} reverse 430 * @param {boolean=} reverse
407 */ 431 */
408 complete: function(force, reverse) 432 complete: function(force, reverse)
409 { 433 {
410 this.clearAutoComplete(); 434 this._clearAutocompleteTimeout();
411 var selection = this._element.getComponentSelection(); 435 var selection = this._element.getComponentSelection();
412 var selectionRange = selection && selection.rangeCount ? selection.getRa ngeAt(0) : null; 436 var selectionRange = selection && selection.rangeCount ? selection.getRa ngeAt(0) : null;
413 if (!selectionRange) 437 if (!selectionRange)
414 return; 438 return;
415 439
416 var shouldExit; 440 var shouldExit;
417 441
418 if (!force && !this.isCaretAtEndOfPrompt() && !this.isSuggestBoxVisible( )) 442 if (!force && !this.isCaretAtEndOfPrompt() && !this.isSuggestBoxVisible( ))
419 shouldExit = true; 443 shouldExit = true;
420 else if (!selection.isCollapsed) 444 else if (!selection.isCollapsed)
421 shouldExit = true; 445 shouldExit = true;
422 else if (!force) { 446 else if (!force) {
423 // BUG72018: Do not show suggest box if caret is followed by a non-s top character. 447 // BUG72018: Do not show suggest box if caret is followed by a non-s top character.
424 var wordSuffixRange = selectionRange.startContainer.rangeOfWord(sele ctionRange.endOffset, this._completionStopCharacters, this._element, "forward"); 448 var wordSuffixRange = selectionRange.startContainer.rangeOfWord(sele ctionRange.endOffset, this._completionStopCharacters, this._element, "forward");
425 if (wordSuffixRange.toString().length) 449 if (wordSuffixRange.toString().length + this.userEnteredText().lengt h - this.text().length)
426 shouldExit = true; 450 shouldExit = true;
427 } 451 }
428 if (shouldExit) { 452 if (shouldExit) {
429 this.clearAutoComplete(); 453 this.clearAutoComplete();
430 return; 454 return;
431 } 455 }
432 456
433 var wordPrefixRange = selectionRange.startContainer.rangeOfWord(selectio nRange.startOffset, this._completionStopCharacters, this._element, "backward"); 457 var wordPrefixRange = selectionRange.startContainer.rangeOfWord(selectio nRange.startOffset, this._completionStopCharacters, this._element, "backward");
434 this._waitingForCompletions = true; 458 this._waitingForCompletions = true;
435 this._loadCompletions(/** @type {!Element} */ (this._proxyElement), word PrefixRange, force || false, this._completionsReady.bind(this, selection, wordPr efixRange, !!reverse, !!force)); 459 this._loadCompletions(/** @type {!Element} */ (this._proxyElement), word PrefixRange, force || false, this._completionsReady.bind(this, selection, wordPr efixRange, !!reverse, !!force));
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 var completionText = annotatedCompletions[selectedIndex].title; 577 var completionText = annotatedCompletions[selectedIndex].title;
554 var prefixText = this._userEnteredRange.toString(); 578 var prefixText = this._userEnteredRange.toString();
555 var suffixText = completionText.substring(wordPrefixLength); 579 var suffixText = completionText.substring(wordPrefixLength);
556 this._userEnteredRange.deleteContents(); 580 this._userEnteredRange.deleteContents();
557 this._element.normalize(); 581 this._element.normalize();
558 var finalSelectionRange = this._createRange(); 582 var finalSelectionRange = this._createRange();
559 583
560 var prefixTextNode = createTextNode(prefixText); 584 var prefixTextNode = createTextNode(prefixText);
561 fullWordRange.insertNode(prefixTextNode); 585 fullWordRange.insertNode(prefixTextNode);
562 586
563 this.autoCompleteElement = createElementWithClass("span", "auto-comp lete-text"); 587 if (!this.autoCompleteElement)
588 this.autoCompleteElement = createElementWithClass("span", "auto- complete-text");
564 this.autoCompleteElement.textContent = suffixText; 589 this.autoCompleteElement.textContent = suffixText;
590 this._hintPrefix = completionText.substring(0, wordPrefixLength);
565 591
566 prefixTextNode.parentNode.insertBefore(this.autoCompleteElement, pre fixTextNode.nextSibling); 592 prefixTextNode.parentNode.insertBefore(this.autoCompleteElement, pre fixTextNode.nextSibling);
567 593
568 finalSelectionRange.setStart(prefixTextNode, wordPrefixLength); 594 finalSelectionRange.setStart(prefixTextNode, wordPrefixLength);
569 finalSelectionRange.setEnd(prefixTextNode, wordPrefixLength); 595 finalSelectionRange.setEnd(prefixTextNode, wordPrefixLength);
570 selection.removeAllRanges(); 596 selection.removeAllRanges();
571 selection.addRange(finalSelectionRange); 597 selection.addRange(finalSelectionRange);
572 this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemApp lied); 598 this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemApp lied);
573 } 599 }
574 }, 600 },
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after
1018 }, 1044 },
1019 1045
1020 /** 1046 /**
1021 * @return {string|undefined} 1047 * @return {string|undefined}
1022 */ 1048 */
1023 _currentHistoryItem: function() 1049 _currentHistoryItem: function()
1024 { 1050 {
1025 return this._data[this._data.length - this._historyOffset]; 1051 return this._data[this._data.length - this._historyOffset];
1026 } 1052 }
1027 }; 1053 };
OLDNEW
« no previous file with comments | « third_party/WebKit/LayoutTests/inspector/text-prompt-hint-expected.txt ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698