Chromium Code Reviews| 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 clearHint = true; |
| 293 if (this.autoCompleteElement) { | |
|
lushnikov
2016/09/01 21:25:33
can we hide autoCompleteElement inside text prompt
einbinder
2016/09/01 23:28:46
Yes, I am planning a TextPrompt rewrite/refactor.
| |
| 294 var text = this.userEnteredText(); | |
| 295 if (this._previousText === text.substring(0, text.length - 1)) { | |
|
lushnikov
2016/09/01 21:25:33
can we generalize this to the "this.userEnteredTex
einbinder
2016/09/01 23:28:46
No, it's checking that exactly one character was d
| |
| 296 this._hintPrefix += this.autoCompleteElement.textContent.charAt( 0); | |
| 297 this.autoCompleteElement.textContent = this.autoCompleteElement. textContent.substring(1); | |
| 298 clearHint = false; | |
| 299 } | |
|
lushnikov
2016/09/01 21:25:33
nit: else on the same line as "}"
einbinder
2016/09/01 23:28:46
Done.
| |
| 300 else if (this._previousText.substring(0, this._previousText.length - 1) === text) { | |
| 301 this.autoCompleteElement.textContent = this._hintPrefix.charAt(t his._hintPrefix.length - 1) + this.autoCompleteElement.textContent; | |
| 302 this._hintPrefix = this._hintPrefix.substring(0, this._hintPrefi x.length - 1); | |
| 303 clearHint = false; | |
| 304 } | |
| 305 } | |
| 306 if (clearHint) | |
| 307 this.clearAutoComplete(false); | |
| 308 delete this._waitingForCompletions; | |
| 291 this.autoCompleteSoon(force); | 309 this.autoCompleteSoon(force); |
| 292 }, | 310 }, |
| 293 | 311 |
| 294 /** | 312 /** |
| 295 * @param {!Event} event | 313 * @param {!Event} event |
| 296 */ | 314 */ |
| 297 onMouseWheel: function(event) | 315 onMouseWheel: function(event) |
| 298 { | 316 { |
| 299 // Subclasses can implement. | 317 // Subclasses can implement. |
| 300 }, | 318 }, |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 354 event.consume(true); | 372 event.consume(true); |
| 355 }, | 373 }, |
| 356 | 374 |
| 357 /** | 375 /** |
| 358 * @param {!Event} event | 376 * @param {!Event} event |
| 359 */ | 377 */ |
| 360 onInput: function(event) | 378 onInput: function(event) |
| 361 { | 379 { |
| 362 if (this._needUpdateAutocomplete) | 380 if (this._needUpdateAutocomplete) |
| 363 this._updateAutoComplete(); | 381 this._updateAutoComplete(); |
| 382 this._previousText = this.userEnteredText(); | |
| 364 }, | 383 }, |
| 365 | 384 |
| 366 /** | 385 /** |
| 367 * @return {boolean} | 386 * @return {boolean} |
| 368 */ | 387 */ |
| 369 acceptAutoComplete: function() | 388 acceptAutoComplete: function() |
| 370 { | 389 { |
| 371 var result = false; | 390 var result = false; |
| 372 if (this.isSuggestBoxVisible()) | 391 if (this.isSuggestBoxVisible()) |
| 373 result = this._suggestBox.acceptSuggestion(); | 392 result = this._suggestBox.acceptSuggestion(); |
| 374 if (!result) | 393 if (!result) |
| 375 result = this._acceptSuggestionInternal(); | 394 result = this._acceptSuggestionInternal(); |
| 376 | 395 |
| 377 return result; | 396 return result; |
| 378 }, | 397 }, |
| 379 | 398 |
| 380 /** | 399 /** |
| 381 * @param {boolean=} includeTimeout | 400 * @param {boolean=} includeTimeout |
| 382 */ | 401 */ |
| 383 clearAutoComplete: function(includeTimeout) | 402 clearAutoComplete: function(includeTimeout) |
|
lushnikov
2016/09/01 21:25:33
I'm confused with TextPrompt API.
So there are th
einbinder
2016/09/01 23:28:46
I think we can get away with always hiding Suggest
| |
| 384 { | 403 { |
| 385 if (includeTimeout && this._completeTimeout) { | 404 if (includeTimeout) |
|
lushnikov
2016/09/01 21:25:33
why would anyone ever want to call this with inclu
einbinder
2016/09/01 23:28:46
I don't think there is a good reason.
| |
| 386 clearTimeout(this._completeTimeout); | 405 this._clearAutocompleteTimeout(); |
| 387 delete this._completeTimeout; | 406 |
| 388 } | |
| 389 delete this._waitingForCompletions; | 407 delete this._waitingForCompletions; |
| 390 | 408 |
| 391 if (!this.autoCompleteElement) | 409 if (!this.autoCompleteElement) |
| 392 return; | 410 return; |
| 393 | 411 |
| 394 this.autoCompleteElement.remove(); | 412 this.autoCompleteElement.remove(); |
| 395 delete this.autoCompleteElement; | 413 delete this.autoCompleteElement; |
| 396 delete this._userEnteredRange; | 414 delete this._userEnteredRange; |
| 397 delete this._userEnteredText; | 415 delete this._userEnteredText; |
| 398 }, | 416 }, |
| 399 | 417 |
| 418 _clearAutocompleteTimeout: function() | |
| 419 { | |
| 420 if (this._completeTimeout) { | |
| 421 clearTimeout(this._completeTimeout); | |
| 422 delete this._completeTimeout; | |
| 423 } | |
| 424 }, | |
| 425 | |
| 400 /** | 426 /** |
| 401 * @param {boolean=} force | 427 * @param {boolean=} force |
| 402 */ | 428 */ |
| 403 autoCompleteSoon: function(force) | 429 autoCompleteSoon: function(force) |
| 404 { | 430 { |
| 405 var immediately = this.isSuggestBoxVisible() || force; | 431 var immediately = this.isSuggestBoxVisible() || force; |
| 406 if (!this._completeTimeout) | 432 if (!this._completeTimeout) |
| 407 this._completeTimeout = setTimeout(this.complete.bind(this, force), immediately ? 0 : this._autocompletionTimeout); | 433 this._completeTimeout = setTimeout(this.complete.bind(this, force), immediately ? 0 : this._autocompletionTimeout); |
| 408 }, | 434 }, |
| 409 | 435 |
| 410 /** | 436 /** |
| 411 * @param {boolean=} force | 437 * @param {boolean=} force |
| 412 * @param {boolean=} reverse | 438 * @param {boolean=} reverse |
| 413 */ | 439 */ |
| 414 complete: function(force, reverse) | 440 complete: function(force, reverse) |
| 415 { | 441 { |
| 416 this.clearAutoComplete(true); | 442 this._clearAutocompleteTimeout(); |
| 417 var selection = this._element.getComponentSelection(); | 443 var selection = this._element.getComponentSelection(); |
| 418 var selectionRange = selection && selection.rangeCount ? selection.getRa ngeAt(0) : null; | 444 var selectionRange = selection && selection.rangeCount ? selection.getRa ngeAt(0) : null; |
| 419 if (!selectionRange) | 445 if (!selectionRange) |
| 420 return; | 446 return; |
| 421 | 447 |
| 422 var shouldExit; | 448 var shouldExit; |
| 423 | 449 |
| 424 if (!force && !this.isCaretAtEndOfPrompt() && !this.isSuggestBoxVisible( )) | 450 if (!force && !this.isCaretAtEndOfPrompt() && !this.isSuggestBoxVisible( )) |
| 425 shouldExit = true; | 451 shouldExit = true; |
| 426 else if (!selection.isCollapsed) | 452 else if (!selection.isCollapsed) |
| 427 shouldExit = true; | 453 shouldExit = true; |
| 428 else if (!force) { | 454 else if (!force) { |
| 429 // BUG72018: Do not show suggest box if caret is followed by a non-s top character. | 455 // 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"); | 456 var wordSuffixRange = selectionRange.startContainer.rangeOfWord(sele ctionRange.endOffset, this._completionStopCharacters, this._element, "forward"); |
| 431 if (wordSuffixRange.toString().length) | 457 if (wordSuffixRange.toString().length + this.userEnteredText().lengt h - this.text().length) |
| 432 shouldExit = true; | 458 shouldExit = true; |
| 433 } | 459 } |
| 434 if (shouldExit) { | 460 if (shouldExit) { |
| 435 this.hideSuggestBox(); | 461 this._removeSuggestionAids(); |
| 436 return; | 462 return; |
| 437 } | 463 } |
| 438 | 464 |
| 439 var wordPrefixRange = selectionRange.startContainer.rangeOfWord(selectio nRange.startOffset, this._completionStopCharacters, this._element, "backward"); | 465 var wordPrefixRange = selectionRange.startContainer.rangeOfWord(selectio nRange.startOffset, this._completionStopCharacters, this._element, "backward"); |
| 440 this._waitingForCompletions = true; | 466 this._waitingForCompletions = true; |
| 441 this._loadCompletions(/** @type {!Element} */ (this._proxyElement), word PrefixRange, force || false, this._completionsReady.bind(this, selection, wordPr efixRange, !!reverse, !!force)); | 467 this._loadCompletions(/** @type {!Element} */ (this._proxyElement), word PrefixRange, force || false, this._completionsReady.bind(this, selection, wordPr efixRange, !!reverse, !!force)); |
| 442 }, | 468 }, |
| 443 | 469 |
| 444 disableDefaultSuggestionForEmptyInput: function() | 470 disableDefaultSuggestionForEmptyInput: function() |
| 445 { | 471 { |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 519 var annotatedCompletions = completions.map(item => ({title: item})); | 545 var annotatedCompletions = completions.map(item => ({title: item})); |
| 520 | 546 |
| 521 if (prefix || force) { | 547 if (prefix || force) { |
| 522 if (prefix) | 548 if (prefix) |
| 523 annotatedCompletions = annotatedCompletions.concat(this.addition alCompletions(prefix)); | 549 annotatedCompletions = annotatedCompletions.concat(this.addition alCompletions(prefix)); |
| 524 else | 550 else |
| 525 annotatedCompletions = this.additionalCompletions(prefix).concat (annotatedCompletions); | 551 annotatedCompletions = this.additionalCompletions(prefix).concat (annotatedCompletions); |
| 526 } | 552 } |
| 527 | 553 |
| 528 if (!this._waitingForCompletions || !annotatedCompletions.length) { | 554 if (!this._waitingForCompletions || !annotatedCompletions.length) { |
| 529 this.hideSuggestBox(); | 555 this._removeSuggestionAids(); |
| 530 return; | 556 return; |
| 531 } | 557 } |
| 532 | 558 |
| 533 delete this._waitingForCompletions; | 559 delete this._waitingForCompletions; |
| 534 | 560 |
| 535 var selectionRange = selection.getRangeAt(0); | 561 var selectionRange = selection.getRangeAt(0); |
| 536 | 562 |
| 537 var fullWordRange = this._createRange(); | 563 var fullWordRange = this._createRange(); |
| 538 fullWordRange.setStart(originalWordPrefixRange.startContainer, originalW ordPrefixRange.startOffset); | 564 fullWordRange.setStart(originalWordPrefixRange.startContainer, originalW ordPrefixRange.startOffset); |
| 539 fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffs et); | 565 fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffs et); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 559 var completionText = annotatedCompletions[selectedIndex].title; | 585 var completionText = annotatedCompletions[selectedIndex].title; |
| 560 var prefixText = this._userEnteredRange.toString(); | 586 var prefixText = this._userEnteredRange.toString(); |
| 561 var suffixText = completionText.substring(wordPrefixLength); | 587 var suffixText = completionText.substring(wordPrefixLength); |
| 562 this._userEnteredRange.deleteContents(); | 588 this._userEnteredRange.deleteContents(); |
| 563 this._element.normalize(); | 589 this._element.normalize(); |
| 564 var finalSelectionRange = this._createRange(); | 590 var finalSelectionRange = this._createRange(); |
| 565 | 591 |
| 566 var prefixTextNode = createTextNode(prefixText); | 592 var prefixTextNode = createTextNode(prefixText); |
| 567 fullWordRange.insertNode(prefixTextNode); | 593 fullWordRange.insertNode(prefixTextNode); |
| 568 | 594 |
| 569 this.autoCompleteElement = createElementWithClass("span", "auto-comp lete-text"); | 595 if (!this.autoCompleteElement) |
| 596 this.autoCompleteElement = createElementWithClass("span", "auto- complete-text"); | |
| 570 this.autoCompleteElement.textContent = suffixText; | 597 this.autoCompleteElement.textContent = suffixText; |
| 598 this._hintPrefix = completionText.substring(0, wordPrefixLength); | |
| 571 | 599 |
| 572 prefixTextNode.parentNode.insertBefore(this.autoCompleteElement, pre fixTextNode.nextSibling); | 600 prefixTextNode.parentNode.insertBefore(this.autoCompleteElement, pre fixTextNode.nextSibling); |
| 573 | 601 |
| 574 finalSelectionRange.setStart(prefixTextNode, wordPrefixLength); | 602 finalSelectionRange.setStart(prefixTextNode, wordPrefixLength); |
| 575 finalSelectionRange.setEnd(prefixTextNode, wordPrefixLength); | 603 finalSelectionRange.setEnd(prefixTextNode, wordPrefixLength); |
| 576 selection.removeAllRanges(); | 604 selection.removeAllRanges(); |
| 577 selection.addRange(finalSelectionRange); | 605 selection.addRange(finalSelectionRange); |
| 578 this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemApp lied); | 606 this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemApp lied); |
| 579 } | 607 } |
| 580 }, | 608 }, |
| (...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1030 }, | 1058 }, |
| 1031 | 1059 |
| 1032 /** | 1060 /** |
| 1033 * @return {string|undefined} | 1061 * @return {string|undefined} |
| 1034 */ | 1062 */ |
| 1035 _currentHistoryItem: function() | 1063 _currentHistoryItem: function() |
| 1036 { | 1064 { |
| 1037 return this._data[this._data.length - this._historyOffset]; | 1065 return this._data[this._data.length - this._historyOffset]; |
| 1038 } | 1066 } |
| 1039 }; | 1067 }; |
| OLD | NEW |