| 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 22 matching lines...) Expand all Loading... |
| 33 WebInspector.TextPrompt = class extends WebInspector.Object { | 33 WebInspector.TextPrompt = class extends WebInspector.Object { |
| 34 constructor() { | 34 constructor() { |
| 35 super(); | 35 super(); |
| 36 /** | 36 /** |
| 37 * @type {!Element|undefined} | 37 * @type {!Element|undefined} |
| 38 */ | 38 */ |
| 39 this._proxyElement; | 39 this._proxyElement; |
| 40 this._proxyElementDisplay = 'inline-block'; | 40 this._proxyElementDisplay = 'inline-block'; |
| 41 this._autocompletionTimeout = WebInspector.TextPrompt.DefaultAutocompletionT
imeout; | 41 this._autocompletionTimeout = WebInspector.TextPrompt.DefaultAutocompletionT
imeout; |
| 42 this._title = ''; | 42 this._title = ''; |
| 43 this._prefixRange = null; | 43 this._queryRange = null; |
| 44 this._previousText = ''; | 44 this._previousText = ''; |
| 45 this._currentSuggestion = ''; | 45 this._currentSuggestion = ''; |
| 46 this._completionRequestId = 0; | 46 this._completionRequestId = 0; |
| 47 this._ghostTextElement = createElementWithClass('span', 'auto-complete-text'
); | 47 this._ghostTextElement = createElementWithClass('span', 'auto-complete-text'
); |
| 48 } | 48 } |
| 49 | 49 |
| 50 /** | 50 /** |
| 51 * @param {function(!Element, !Range, boolean, function(!Array.<string>, numbe
r=))} completions | 51 * @param {function(!Element, !Range, boolean, function(!Array.<string>, numbe
r=))} completions |
| 52 * @param {string=} stopCharacters | 52 * @param {string=} stopCharacters |
| 53 */ | 53 */ |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 if (handled) | 292 if (handled) |
| 293 event.consume(true); | 293 event.consume(true); |
| 294 } | 294 } |
| 295 | 295 |
| 296 /** | 296 /** |
| 297 * @param {!Event} event | 297 * @param {!Event} event |
| 298 */ | 298 */ |
| 299 onInput(event) { | 299 onInput(event) { |
| 300 var text = this.text(); | 300 var text = this.text(); |
| 301 var hasCommonPrefix = text.startsWith(this._previousText) || this._previousT
ext.startsWith(text); | 301 var hasCommonPrefix = text.startsWith(this._previousText) || this._previousT
ext.startsWith(text); |
| 302 if (this._prefixRange && hasCommonPrefix) | 302 if (this._queryRange && hasCommonPrefix) |
| 303 this._prefixRange.endColumn += text.length - this._previousText.length; | 303 this._queryRange.endColumn += text.length - this._previousText.length; |
| 304 this._refreshGhostText(); | 304 this._refreshGhostText(); |
| 305 this._previousText = text; | 305 this._previousText = text; |
| 306 | 306 |
| 307 this.autoCompleteSoon(); | 307 this.autoCompleteSoon(); |
| 308 } | 308 } |
| 309 | 309 |
| 310 /** | 310 /** |
| 311 * @return {boolean} | 311 * @return {boolean} |
| 312 */ | 312 */ |
| 313 acceptAutoComplete() { | 313 acceptAutoComplete() { |
| 314 var result = false; | 314 var result = false; |
| 315 if (this._isSuggestBoxVisible()) | 315 if (this._isSuggestBoxVisible()) |
| 316 result = this._suggestBox.acceptSuggestion(); | 316 result = this._suggestBox.acceptSuggestion(); |
| 317 if (!result) | 317 if (!result) |
| 318 result = this._acceptSuggestionInternal(); | 318 result = this._acceptSuggestionInternal(); |
| 319 | 319 |
| 320 return result; | 320 return result; |
| 321 } | 321 } |
| 322 | 322 |
| 323 clearAutocomplete() { | 323 clearAutocomplete() { |
| 324 if (this._isSuggestBoxVisible()) | 324 if (this._isSuggestBoxVisible()) |
| 325 this._suggestBox.hide(); | 325 this._suggestBox.hide(); |
| 326 this._clearAutocompleteTimeout(); | 326 this._clearAutocompleteTimeout(); |
| 327 this._prefixRange = null; | 327 this._queryRange = null; |
| 328 this._refreshGhostText(); | 328 this._refreshGhostText(); |
| 329 } | 329 } |
| 330 | 330 |
| 331 _refreshGhostText() { | 331 _refreshGhostText() { |
| 332 if (this._prefixRange && this._isCaretAtEndOfPrompt()) { | 332 if (this._queryRange && this._isCaretAtEndOfPrompt()) { |
| 333 this._ghostTextElement.textContent = | 333 this._ghostTextElement.textContent = |
| 334 this._currentSuggestion.substring(this._prefixRange.endColumn - this._
prefixRange.startColumn); | 334 this._currentSuggestion.substring(this._queryRange.endColumn - this._q
ueryRange.startColumn); |
| 335 this._element.appendChild(this._ghostTextElement); | 335 this._element.appendChild(this._ghostTextElement); |
| 336 } else { | 336 } else { |
| 337 this._ghostTextElement.remove(); | 337 this._ghostTextElement.remove(); |
| 338 } | 338 } |
| 339 } | 339 } |
| 340 | 340 |
| 341 _clearAutocompleteTimeout() { | 341 _clearAutocompleteTimeout() { |
| 342 if (this._completeTimeout) { | 342 if (this._completeTimeout) { |
| 343 clearTimeout(this._completeTimeout); | 343 clearTimeout(this._completeTimeout); |
| 344 delete this._completeTimeout; | 344 delete this._completeTimeout; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 selectionRange.endOffset, this._completionStopCharacters, this._elemen
t, 'forward'); | 379 selectionRange.endOffset, this._completionStopCharacters, this._elemen
t, 'forward'); |
| 380 var autocompleteTextLength = this._ghostTextElement.parentNode ? this._gho
stTextElement.textContent.length : 0; | 380 var autocompleteTextLength = this._ghostTextElement.parentNode ? this._gho
stTextElement.textContent.length : 0; |
| 381 if (wordSuffixRange.toString().length !== autocompleteTextLength) | 381 if (wordSuffixRange.toString().length !== autocompleteTextLength) |
| 382 shouldExit = true; | 382 shouldExit = true; |
| 383 } | 383 } |
| 384 if (shouldExit) { | 384 if (shouldExit) { |
| 385 this.clearAutocomplete(); | 385 this.clearAutocomplete(); |
| 386 return; | 386 return; |
| 387 } | 387 } |
| 388 | 388 |
| 389 var wordPrefixRange = selectionRange.startContainer.rangeOfWord( | 389 var wordQueryRange = selectionRange.startContainer.rangeOfWord( |
| 390 selectionRange.startOffset, this._completionStopCharacters, this._elemen
t, 'backward'); | 390 selectionRange.startOffset, this._completionStopCharacters, this._elemen
t, 'backward'); |
| 391 this._loadCompletions( | 391 this._loadCompletions( |
| 392 /** @type {!Element} */ (this._proxyElement), wordPrefixRange, force ||
false, | 392 /** @type {!Element} */ (this._proxyElement), wordQueryRange, force || f
alse, |
| 393 this._completionsReady.bind(this, ++this._completionRequestId, selection
, wordPrefixRange, !!reverse, !!force)); | 393 this._completionsReady.bind(this, ++this._completionRequestId, selection
, wordQueryRange, !!reverse, !!force)); |
| 394 } | 394 } |
| 395 | 395 |
| 396 disableDefaultSuggestionForEmptyInput() { | 396 disableDefaultSuggestionForEmptyInput() { |
| 397 this._disableDefaultSuggestionForEmptyInput = true; | 397 this._disableDefaultSuggestionForEmptyInput = true; |
| 398 } | 398 } |
| 399 | 399 |
| 400 /** | 400 /** |
| 401 * @param {!Selection} selection | 401 * @param {!Selection} selection |
| 402 * @param {!Range} textRange | 402 * @param {!Range} textRange |
| 403 */ | 403 */ |
| (...skipping 11 matching lines...) Expand all Loading... |
| 415 | 415 |
| 416 /** | 416 /** |
| 417 * @return {?Range} | 417 * @return {?Range} |
| 418 * @suppressGlobalPropertiesCheck | 418 * @suppressGlobalPropertiesCheck |
| 419 */ | 419 */ |
| 420 _createRange() { | 420 _createRange() { |
| 421 return document.createRange(); | 421 return document.createRange(); |
| 422 } | 422 } |
| 423 | 423 |
| 424 /** | 424 /** |
| 425 * @param {string} prefix | 425 * @param {string} query |
| 426 * @return {!WebInspector.SuggestBox.Suggestions} | 426 * @return {!WebInspector.SuggestBox.Suggestions} |
| 427 */ | 427 */ |
| 428 additionalCompletions(prefix) { | 428 additionalCompletions(query) { |
| 429 return []; | 429 return []; |
| 430 } | 430 } |
| 431 | 431 |
| 432 /** | 432 /** |
| 433 * @param {number} completionRequestId | 433 * @param {number} completionRequestId |
| 434 * @param {!Selection} selection | 434 * @param {!Selection} selection |
| 435 * @param {!Range} originalWordPrefixRange | 435 * @param {!Range} originalWordQueryRange |
| 436 * @param {boolean} reverse | 436 * @param {boolean} reverse |
| 437 * @param {boolean} force | 437 * @param {boolean} force |
| 438 * @param {!Array.<string>} completions | 438 * @param {!Array.<string>} completions |
| 439 * @param {number=} selectedIndex | 439 * @param {number=} selectedIndex |
| 440 */ | 440 */ |
| 441 _completionsReady( | 441 _completionsReady( |
| 442 completionRequestId, | 442 completionRequestId, |
| 443 selection, | 443 selection, |
| 444 originalWordPrefixRange, | 444 originalWordQueryRange, |
| 445 reverse, | 445 reverse, |
| 446 force, | 446 force, |
| 447 completions, | 447 completions, |
| 448 selectedIndex) { | 448 selectedIndex) { |
| 449 if (this._completionRequestId !== completionRequestId) | 449 if (this._completionRequestId !== completionRequestId) |
| 450 return; | 450 return; |
| 451 | 451 |
| 452 var prefix = originalWordPrefixRange.toString(); | 452 var query = originalWordQueryRange.toString(); |
| 453 | 453 |
| 454 // Filter out dupes. | 454 // Filter out dupes. |
| 455 var store = new Set(); | 455 var store = new Set(); |
| 456 completions = completions.filter(item => !store.has(item) && !!store.add(ite
m)); | 456 completions = completions.filter(item => !store.has(item) && !!store.add(ite
m)); |
| 457 var annotatedCompletions = completions.map(item => ({title: item})); | 457 var annotatedCompletions = completions.map(item => ({title: item})); |
| 458 | 458 |
| 459 if (prefix || force) { | 459 if (query || force) { |
| 460 if (prefix) | 460 if (query) |
| 461 annotatedCompletions = annotatedCompletions.concat(this.additionalComple
tions(prefix)); | 461 annotatedCompletions = annotatedCompletions.concat(this.additionalComple
tions(query)); |
| 462 else | 462 else |
| 463 annotatedCompletions = this.additionalCompletions(prefix).concat(annotat
edCompletions); | 463 annotatedCompletions = this.additionalCompletions(query).concat(annotate
dCompletions); |
| 464 } | 464 } |
| 465 | 465 |
| 466 if (!annotatedCompletions.length) { | 466 if (!annotatedCompletions.length) { |
| 467 this.clearAutocomplete(); | 467 this.clearAutocomplete(); |
| 468 return; | 468 return; |
| 469 } | 469 } |
| 470 | 470 |
| 471 var selectionRange = selection.getRangeAt(0); | 471 var selectionRange = selection.getRangeAt(0); |
| 472 | 472 |
| 473 var fullWordRange = this._createRange(); | 473 var fullWordRange = this._createRange(); |
| 474 fullWordRange.setStart(originalWordPrefixRange.startContainer, originalWordP
refixRange.startOffset); | 474 fullWordRange.setStart(originalWordQueryRange.startContainer, originalWordQu
eryRange.startOffset); |
| 475 fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffset); | 475 fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffset); |
| 476 | 476 |
| 477 if (prefix + selectionRange.toString() !== fullWordRange.toString()) | 477 if (query + selectionRange.toString() !== fullWordRange.toString()) |
| 478 return; | 478 return; |
| 479 | 479 |
| 480 selectedIndex = (this._disableDefaultSuggestionForEmptyInput && !this.text()
) ? -1 : (selectedIndex || 0); | 480 selectedIndex = (this._disableDefaultSuggestionForEmptyInput && !this.text()
) ? -1 : (selectedIndex || 0); |
| 481 | 481 |
| 482 if (this._suggestBox) | 482 if (this._suggestBox) |
| 483 this._suggestBox.updateSuggestions( | 483 this._suggestBox.updateSuggestions( |
| 484 this._boxForAnchorAtStart(selection, fullWordRange), annotatedCompleti
ons, selectedIndex, | 484 this._boxForAnchorAtStart(selection, fullWordRange), annotatedCompleti
ons, selectedIndex, |
| 485 !this._isCaretAtEndOfPrompt(), this.text()); | 485 !this._isCaretAtEndOfPrompt(), this.text()); |
| 486 | 486 |
| 487 var beforeRange = this._createRange(); | 487 var beforeRange = this._createRange(); |
| 488 beforeRange.setStart(this._element, 0); | 488 beforeRange.setStart(this._element, 0); |
| 489 beforeRange.setEnd(fullWordRange.startContainer, fullWordRange.startOffset); | 489 beforeRange.setEnd(fullWordRange.startContainer, fullWordRange.startOffset); |
| 490 this._prefixRange = new WebInspector.TextRange( | 490 this._queryRange = new WebInspector.TextRange( |
| 491 0, beforeRange.toString().length, 0, beforeRange.toString().length + ful
lWordRange.toString().length); | 491 0, beforeRange.toString().length, 0, beforeRange.toString().length + ful
lWordRange.toString().length); |
| 492 | 492 |
| 493 if (selectedIndex === -1) | 493 if (selectedIndex === -1) |
| 494 return; | 494 return; |
| 495 this.applySuggestion(annotatedCompletions[selectedIndex].title, true); | 495 this.applySuggestion(annotatedCompletions[selectedIndex].title, true); |
| 496 } | 496 } |
| 497 | 497 |
| 498 /** | 498 /** |
| 499 * @override | 499 * @override |
| 500 * @param {string} suggestion | 500 * @param {string} suggestion |
| 501 * @param {boolean=} isIntermediateSuggestion | 501 * @param {boolean=} isIntermediateSuggestion |
| 502 */ | 502 */ |
| 503 applySuggestion(suggestion, isIntermediateSuggestion) { | 503 applySuggestion(suggestion, isIntermediateSuggestion) { |
| 504 if (!this._prefixRange) | 504 if (!this._queryRange) |
| 505 return; | 505 return; |
| 506 this._currentSuggestion = suggestion; | 506 this._currentSuggestion = suggestion; |
| 507 this._refreshGhostText(); | 507 this._refreshGhostText(); |
| 508 if (isIntermediateSuggestion) | 508 if (isIntermediateSuggestion) |
| 509 this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemApplied); | 509 this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemApplied); |
| 510 } | 510 } |
| 511 | 511 |
| 512 /** | 512 /** |
| 513 * @override | 513 * @override |
| 514 */ | 514 */ |
| 515 acceptSuggestion() { | 515 acceptSuggestion() { |
| 516 this._acceptSuggestionInternal(); | 516 this._acceptSuggestionInternal(); |
| 517 } | 517 } |
| 518 | 518 |
| 519 /** | 519 /** |
| 520 * @return {boolean} | 520 * @return {boolean} |
| 521 */ | 521 */ |
| 522 _acceptSuggestionInternal() { | 522 _acceptSuggestionInternal() { |
| 523 if (!this._prefixRange) | 523 if (!this._queryRange) |
| 524 return false; | 524 return false; |
| 525 | 525 |
| 526 var text = this.text(); | 526 var text = this.text(); |
| 527 this._element.textContent = text.substring(0, this._prefixRange.startColumn)
+ this._currentSuggestion + | 527 this._element.textContent = text.substring(0, this._queryRange.startColumn)
+ this._currentSuggestion + |
| 528 text.substring(this._prefixRange.endColumn); | 528 text.substring(this._queryRange.endColumn); |
| 529 this.setDOMSelection( | 529 this.setDOMSelection( |
| 530 this._prefixRange.startColumn + this._currentSuggestion.length, | 530 this._queryRange.startColumn + this._currentSuggestion.length, |
| 531 this._prefixRange.startColumn + this._currentSuggestion.length); | 531 this._queryRange.startColumn + this._currentSuggestion.length); |
| 532 | 532 |
| 533 this.clearAutocomplete(); | 533 this.clearAutocomplete(); |
| 534 this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemAccepted); | 534 this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemAccepted); |
| 535 | 535 |
| 536 return true; | 536 return true; |
| 537 } | 537 } |
| 538 | 538 |
| 539 /** | 539 /** |
| 540 * @param {number} startColumn | 540 * @param {number} startColumn |
| 541 * @param {number} endColumn | 541 * @param {number} endColumn |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 636 } | 636 } |
| 637 }; | 637 }; |
| 638 | 638 |
| 639 WebInspector.TextPrompt.DefaultAutocompletionTimeout = 250; | 639 WebInspector.TextPrompt.DefaultAutocompletionTimeout = 250; |
| 640 | 640 |
| 641 /** @enum {symbol} */ | 641 /** @enum {symbol} */ |
| 642 WebInspector.TextPrompt.Events = { | 642 WebInspector.TextPrompt.Events = { |
| 643 ItemApplied: Symbol('text-prompt-item-applied'), | 643 ItemApplied: Symbol('text-prompt-item-applied'), |
| 644 ItemAccepted: Symbol('text-prompt-item-accepted') | 644 ItemAccepted: Symbol('text-prompt-item-accepted') |
| 645 }; | 645 }; |
| OLD | NEW |