diff options
| author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2020-09-08 19:40:15 -0400 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-09-08 19:40:15 -0400 | 
| commit | b687870a55eae43a71ea3adc41be0ab341a8721f (patch) | |
| tree | 55b5046b6c2f9513edf09307c05cc50d3468ae67 /ext/fg/js | |
| parent | ab4dbacc4c36d6373e22f758eefdb7514dc7cdb9 (diff) | |
Delay hide option (#774)
* Add hideDelay option
* Add _clearSelection
* Use hideDelay
* Prevent repeated delayed selection clears
* Fix popup hide timer being cleared when the cursor is moved into the frame
Diffstat (limited to 'ext/fg/js')
| -rw-r--r-- | ext/fg/js/frontend.js | 64 | ||||
| -rw-r--r-- | ext/fg/js/popup.js | 10 | 
2 files changed, 65 insertions, 9 deletions
| diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 9177f985..e92feaf9 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -61,7 +61,10 @@ class Frontend {          this._popupFactory = popupFactory;          this._allowRootFramePopupProxy = allowRootFramePopupProxy;          this._popupCache = new Map(); +        this._popupEventListeners = new EventListenerCollection();          this._updatePopupToken = null; +        this._clearSelectionTimer = null; +        this._isPointerOverPopup = false;          this._runtimeMessageHandlers = new Map([              ['requestFrontendReadyBroadcast',        {async: false, handler: this._onMessageRequestFrontendReadyBroadcast.bind(this)}] @@ -175,7 +178,7 @@ class Frontend {      }      _onApiClosePopup() { -        this._textScanner.clearSelection(false); +        this._clearSelection(false);      }      _onApiCopySelection() { @@ -232,9 +235,11 @@ class Frontend {      }      _onClearSelection({passive}) { +        this._stopClearSelectionDelayed();          if (this._popup !== null) {              this._popup.hide(!passive);              this._popup.clearAutoPlayTimer(); +            this._isPointerOverPopup = false;          }          this._updatePendingOptions();      } @@ -249,24 +254,61 @@ class Frontend {          await this.updateOptions();      } -    _onSearched({textScanner, type, definitions, sentence, input: {cause}, textSource, optionsContext, error}) { +    _onSearched({type, definitions, sentence, input: {cause}, textSource, optionsContext, error}) { +        const scanningOptions = this._options.scanning; +          if (error !== null) {              if (yomichan.isExtensionUnloaded) { -                if (textSource !== null && this._options.scanning.modifier !== 'none') { +                if (textSource !== null && scanningOptions.modifier !== 'none') {                      this._showExtensionUnloaded(textSource);                  }              } else {                  yomichan.logError(error);              } +        } if (type !== null) { +            this._stopClearSelectionDelayed(); +            const focus = (cause === 'mouse'); +            this._showContent(textSource, focus, definitions, type, sentence, optionsContext);          } else { -            if (type !== null) { -                const focus = (cause === 'mouse'); -                this._showContent(textSource, focus, definitions, type, sentence, optionsContext); +            if (scanningOptions.autoHideResults) { +                this._clearSelectionDelayed(scanningOptions.hideDelay, false);              }          } +    } + +    _onPopupFramePointerOver() { +        this._isPointerOverPopup = true; +        this._stopClearSelectionDelayed(); +    } + +    _onPopupFramePointerOut() { +        this._isPointerOverPopup = false; +    } + +    _clearSelection(passive) { +        this._stopClearSelectionDelayed(); +        this._textScanner.clearSelection(passive); +    } + +    _clearSelectionDelayed(delay, restart, passive) { +        if (!this._textScanner.hasSelection()) { return; } +        if (delay > 0) { +            if (this._clearSelectionTimer !== null && !restart) { return; } // Already running +            this._stopClearSelectionDelayed(); +            this._clearSelectionTimer = setTimeout(() => { +                this._clearSelectionTimer = null; +                if (this._isPointerOverPopup) { return; } +                this._clearSelection(passive); +            }, delay); +        } else { +            this._clearSelection(passive); +        } +    } -        if (type === null && this._options.scanning.autoHideResults) { -            textScanner.clearSelection(false); +    _stopClearSelectionDelayed() { +        if (this._clearSelectionTimer !== null) { +            clearTimeout(this._clearSelectionTimer); +            this._clearSelectionTimer = null;          }      } @@ -354,8 +396,12 @@ class Frontend {              this.setDisabledOverride(!this._options.scanning.enableOnSearchPage);          } -        this._textScanner.clearSelection(true); +        this._clearSelection(true); +        this._popupEventListeners.removeAllEventListeners();          this._popup = popup; +        this._popupEventListeners.on(popup, 'framePointerOver', this._onPopupFramePointerOver.bind(this)); +        this._popupEventListeners.on(popup, 'framePointerOut', this._onPopupFramePointerOut.bind(this)); +        this._isPointerOverPopup = false;      }      async _getDefaultPopup() { diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index f644ee98..ee3bf646 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -95,6 +95,8 @@ class Popup extends EventDispatcher {      // Public functions      prepare() { +        this._frame.addEventListener('mouseover', this._onFrameMouseOver.bind(this)); +        this._frame.addEventListener('mouseout', this._onFrameMouseOut.bind(this));          this._frame.addEventListener('mousedown', (e) => e.stopPropagation());          this._frame.addEventListener('scroll', (e) => e.stopPropagation());          this._frame.addEventListener('load', this._onFrameLoad.bind(this)); @@ -207,6 +209,14 @@ class Popup extends EventDispatcher {      // Private functions +    _onFrameMouseOver() { +        this.trigger('framePointerOver', {}); +    } + +    _onFrameMouseOut() { +        this.trigger('framePointerOut', {}); +    } +      _inject() {          let injectPromise = this._injectPromise;          if (injectPromise === null) { |