OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
182 setText: function(x) | 183 setText: function(x) |
183 { | 184 { |
184 this._removeSuggestionAids(); | 185 this._removeSuggestionAids(); |
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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
280 } | 282 } |
281 | 283 |
282 this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100); | 284 this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100); |
283 }, | 285 }, |
284 | 286 |
285 /** | 287 /** |
286 * @param {boolean=} force | 288 * @param {boolean=} force |
287 */ | 289 */ |
288 _updateAutoComplete: function(force) | 290 _updateAutoComplete: function(force) |
289 { | 291 { |
290 this.clearAutoComplete(); | 292 var singleCharInput = false; |
293 var singleCharDelete = false; | |
294 var text = this.userEnteredText(); | |
295 if (this._previousText === text.substring(0, text.length - 1)) | |
296 singleCharInput = true; | |
297 else if (this._previousText.substring(0, this._previousText.length - 1) === text) | |
298 singleCharDelete = true; | |
299 this.clearAutoComplete(false, singleCharInput, singleCharDelete); | |
291 this.autoCompleteSoon(force); | 300 this.autoCompleteSoon(force); |
292 }, | 301 }, |
293 | 302 |
294 /** | 303 /** |
295 * @param {!Event} event | 304 * @param {!Event} event |
296 */ | 305 */ |
297 onMouseWheel: function(event) | 306 onMouseWheel: function(event) |
298 { | 307 { |
299 // Subclasses can implement. | 308 // Subclasses can implement. |
300 }, | 309 }, |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
354 event.consume(true); | 363 event.consume(true); |
355 }, | 364 }, |
356 | 365 |
357 /** | 366 /** |
358 * @param {!Event} event | 367 * @param {!Event} event |
359 */ | 368 */ |
360 onInput: function(event) | 369 onInput: function(event) |
361 { | 370 { |
362 if (this._needUpdateAutocomplete) | 371 if (this._needUpdateAutocomplete) |
363 this._updateAutoComplete(); | 372 this._updateAutoComplete(); |
373 this._previousText = this.userEnteredText(); | |
364 }, | 374 }, |
365 | 375 |
366 /** | 376 /** |
367 * @return {boolean} | 377 * @return {boolean} |
368 */ | 378 */ |
369 acceptAutoComplete: function() | 379 acceptAutoComplete: function() |
370 { | 380 { |
371 var result = false; | 381 var result = false; |
372 if (this.isSuggestBoxVisible()) | 382 if (this.isSuggestBoxVisible()) |
373 result = this._suggestBox.acceptSuggestion(); | 383 result = this._suggestBox.acceptSuggestion(); |
374 if (!result) | 384 if (!result) |
375 result = this._acceptSuggestionInternal(); | 385 result = this._acceptSuggestionInternal(); |
376 | 386 |
377 return result; | 387 return result; |
378 }, | 388 }, |
379 | 389 |
380 /** | 390 /** |
381 * @param {boolean=} includeTimeout | 391 * @param {boolean=} includeTimeout |
392 * @param {boolean=} singleCharInput | |
393 * @param {boolean=} singleDeleteChar | |
382 */ | 394 */ |
383 clearAutoComplete: function(includeTimeout) | 395 clearAutoComplete: function(includeTimeout, singleCharInput, singleDeleteCha r) |
lushnikov
2016/08/29 22:10:41
why are these arguments a part of public interface
einbinder
2016/08/30 22:22:35
Done.
| |
384 { | 396 { |
385 if (includeTimeout && this._completeTimeout) { | 397 |
386 clearTimeout(this._completeTimeout); | 398 if (includeTimeout) |
387 delete this._completeTimeout; | 399 this._clearAutocompleteTimeout(); |
388 } | 400 |
389 delete this._waitingForCompletions; | 401 delete this._waitingForCompletions; |
390 | 402 |
391 if (!this.autoCompleteElement) | 403 if (!this.autoCompleteElement) |
392 return; | 404 return; |
393 | 405 if (singleCharInput) { |
394 this.autoCompleteElement.remove(); | 406 this._hintPrefix += this.autoCompleteElement.textContent.charAt(0); |
395 delete this.autoCompleteElement; | 407 this.autoCompleteElement.textContent = this.autoCompleteElement.text Content.substring(1); |
408 } else if (singleDeleteChar && this._hintPrefix) { | |
409 this.autoCompleteElement.textContent = this._hintPrefix.charAt(this. _hintPrefix.length - 1) + this.autoCompleteElement.textContent; | |
410 this._hintPrefix = this._hintPrefix.substring(0, this._hintPrefix.le ngth - 1); | |
411 } else { | |
412 this.autoCompleteElement.remove(); | |
413 delete this.autoCompleteElement; | |
414 } | |
396 delete this._userEnteredRange; | 415 delete this._userEnteredRange; |
397 delete this._userEnteredText; | 416 delete this._userEnteredText; |
398 }, | 417 }, |
399 | 418 |
419 _clearAutocompleteTimeout: function() | |
420 { | |
421 if (this._completeTimeout) { | |
422 clearTimeout(this._completeTimeout); | |
423 delete this._completeTimeout; | |
424 } | |
425 }, | |
426 | |
400 /** | 427 /** |
401 * @param {boolean=} force | 428 * @param {boolean=} force |
402 */ | 429 */ |
403 autoCompleteSoon: function(force) | 430 autoCompleteSoon: function(force) |
404 { | 431 { |
405 var immediately = this.isSuggestBoxVisible() || force; | 432 var immediately = this.isSuggestBoxVisible() || force; |
406 if (!this._completeTimeout) | 433 if (!this._completeTimeout) |
407 this._completeTimeout = setTimeout(this.complete.bind(this, force), immediately ? 0 : this._autocompletionTimeout); | 434 this._completeTimeout = setTimeout(this.complete.bind(this, force), immediately ? 0 : this._autocompletionTimeout); |
408 }, | 435 }, |
409 | 436 |
410 /** | 437 /** |
411 * @param {boolean=} force | 438 * @param {boolean=} force |
412 * @param {boolean=} reverse | 439 * @param {boolean=} reverse |
413 */ | 440 */ |
414 complete: function(force, reverse) | 441 complete: function(force, reverse) |
415 { | 442 { |
416 this.clearAutoComplete(true); | 443 this._clearAutocompleteTimeout(); |
417 var selection = this._element.getComponentSelection(); | 444 var selection = this._element.getComponentSelection(); |
418 var selectionRange = selection && selection.rangeCount ? selection.getRa ngeAt(0) : null; | 445 var selectionRange = selection && selection.rangeCount ? selection.getRa ngeAt(0) : null; |
419 if (!selectionRange) | 446 if (!selectionRange) |
420 return; | 447 return; |
421 | 448 |
422 var shouldExit; | 449 var shouldExit; |
423 | 450 |
424 if (!force && !this.isCaretAtEndOfPrompt() && !this.isSuggestBoxVisible( )) | 451 if (!force && !this.isCaretAtEndOfPrompt() && !this.isSuggestBoxVisible( )) |
425 shouldExit = true; | 452 shouldExit = true; |
426 else if (!selection.isCollapsed) | 453 else if (!selection.isCollapsed) |
427 shouldExit = true; | 454 shouldExit = true; |
428 else if (!force) { | 455 else if (!force) { |
429 // BUG72018: Do not show suggest box if caret is followed by a non-s top character. | 456 // BUG72018: Do not show suggest box if caret is followed by a non-s top character. |
430 var wordSuffixRange = selectionRange.startContainer.rangeOfWord(sele ctionRange.endOffset, this._completionStopCharacters, this._element, "forward"); | 457 var wordSuffixRange = selectionRange.startContainer.rangeOfWord(sele ctionRange.endOffset, this._completionStopCharacters, this._element, "forward"); |
431 if (wordSuffixRange.toString().length) | 458 if (wordSuffixRange.toString().length + this.userEnteredText().lengt h - this.text().length) |
432 shouldExit = true; | 459 shouldExit = true; |
433 } | 460 } |
434 if (shouldExit) { | 461 if (shouldExit) { |
435 this.hideSuggestBox(); | 462 this._removeSuggestionAids(); |
436 return; | 463 return; |
437 } | 464 } |
438 | 465 |
439 var wordPrefixRange = selectionRange.startContainer.rangeOfWord(selectio nRange.startOffset, this._completionStopCharacters, this._element, "backward"); | 466 var wordPrefixRange = selectionRange.startContainer.rangeOfWord(selectio nRange.startOffset, this._completionStopCharacters, this._element, "backward"); |
440 this._waitingForCompletions = true; | 467 this._waitingForCompletions = true; |
441 this._loadCompletions(/** @type {!Element} */ (this._proxyElement), word PrefixRange, force || false, this._completionsReady.bind(this, selection, wordPr efixRange, !!reverse, !!force)); | 468 this._loadCompletions(/** @type {!Element} */ (this._proxyElement), word PrefixRange, force || false, this._completionsReady.bind(this, selection, wordPr efixRange, !!reverse, !!force)); |
442 }, | 469 }, |
443 | 470 |
444 disableDefaultSuggestionForEmptyInput: function() | 471 disableDefaultSuggestionForEmptyInput: function() |
445 { | 472 { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
519 var annotatedCompletions = completions.map(item => ({title: item})); | 546 var annotatedCompletions = completions.map(item => ({title: item})); |
520 | 547 |
521 if (prefix || force) { | 548 if (prefix || force) { |
522 if (prefix) | 549 if (prefix) |
523 annotatedCompletions = annotatedCompletions.concat(this.addition alCompletions(prefix)); | 550 annotatedCompletions = annotatedCompletions.concat(this.addition alCompletions(prefix)); |
524 else | 551 else |
525 annotatedCompletions = this.additionalCompletions(prefix).concat (annotatedCompletions); | 552 annotatedCompletions = this.additionalCompletions(prefix).concat (annotatedCompletions); |
526 } | 553 } |
527 | 554 |
528 if (!this._waitingForCompletions || !annotatedCompletions.length) { | 555 if (!this._waitingForCompletions || !annotatedCompletions.length) { |
529 this.hideSuggestBox(); | 556 this._removeSuggestionAids(); |
530 return; | 557 return; |
531 } | 558 } |
532 | 559 |
533 delete this._waitingForCompletions; | 560 delete this._waitingForCompletions; |
534 | 561 |
535 var selectionRange = selection.getRangeAt(0); | 562 var selectionRange = selection.getRangeAt(0); |
536 | 563 |
537 var fullWordRange = this._createRange(); | 564 var fullWordRange = this._createRange(); |
538 fullWordRange.setStart(originalWordPrefixRange.startContainer, originalW ordPrefixRange.startOffset); | 565 fullWordRange.setStart(originalWordPrefixRange.startContainer, originalW ordPrefixRange.startOffset); |
539 fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffs et); | 566 fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffs et); |
(...skipping 19 matching lines...) Expand all Loading... | |
559 var completionText = annotatedCompletions[selectedIndex].title; | 586 var completionText = annotatedCompletions[selectedIndex].title; |
560 var prefixText = this._userEnteredRange.toString(); | 587 var prefixText = this._userEnteredRange.toString(); |
561 var suffixText = completionText.substring(wordPrefixLength); | 588 var suffixText = completionText.substring(wordPrefixLength); |
562 this._userEnteredRange.deleteContents(); | 589 this._userEnteredRange.deleteContents(); |
563 this._element.normalize(); | 590 this._element.normalize(); |
564 var finalSelectionRange = this._createRange(); | 591 var finalSelectionRange = this._createRange(); |
565 | 592 |
566 var prefixTextNode = createTextNode(prefixText); | 593 var prefixTextNode = createTextNode(prefixText); |
567 fullWordRange.insertNode(prefixTextNode); | 594 fullWordRange.insertNode(prefixTextNode); |
568 | 595 |
596 if (this.autoCompleteElement) | |
597 this.autoCompleteElement.remove(); | |
569 this.autoCompleteElement = createElementWithClass("span", "auto-comp lete-text"); | 598 this.autoCompleteElement = createElementWithClass("span", "auto-comp lete-text"); |
570 this.autoCompleteElement.textContent = suffixText; | 599 this.autoCompleteElement.textContent = suffixText; |
600 this._hintPrefix = completionText.substring(0, wordPrefixLength); | |
571 | 601 |
572 prefixTextNode.parentNode.insertBefore(this.autoCompleteElement, pre fixTextNode.nextSibling); | 602 prefixTextNode.parentNode.insertBefore(this.autoCompleteElement, pre fixTextNode.nextSibling); |
573 | 603 |
574 finalSelectionRange.setStart(prefixTextNode, wordPrefixLength); | 604 finalSelectionRange.setStart(prefixTextNode, wordPrefixLength); |
575 finalSelectionRange.setEnd(prefixTextNode, wordPrefixLength); | 605 finalSelectionRange.setEnd(prefixTextNode, wordPrefixLength); |
576 selection.removeAllRanges(); | 606 selection.removeAllRanges(); |
577 selection.addRange(finalSelectionRange); | 607 selection.addRange(finalSelectionRange); |
578 this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemApp lied); | 608 this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemApp lied); |
579 } | 609 } |
580 }, | 610 }, |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1030 }, | 1060 }, |
1031 | 1061 |
1032 /** | 1062 /** |
1033 * @return {string|undefined} | 1063 * @return {string|undefined} |
1034 */ | 1064 */ |
1035 _currentHistoryItem: function() | 1065 _currentHistoryItem: function() |
1036 { | 1066 { |
1037 return this._data[this._data.length - this._historyOffset]; | 1067 return this._data[this._data.length - this._historyOffset]; |
1038 } | 1068 } |
1039 }; | 1069 }; |
OLD | NEW |