diff options
Diffstat (limited to 'ext/fg/js')
| -rw-r--r-- | ext/fg/js/driver.js | 85 | ||||
| -rw-r--r-- | ext/fg/js/popup.js | 44 | 
2 files changed, 86 insertions, 43 deletions
| diff --git a/ext/fg/js/driver.js b/ext/fg/js/driver.js index d0907e7d..1e817c1c 100644 --- a/ext/fg/js/driver.js +++ b/ext/fg/js/driver.js @@ -20,6 +20,7 @@  class Driver {      constructor() {          this.popup = new Popup(); +        this.popupTimer = null;          this.audio = {};          this.lastMousePos = null;          this.lastTextSource = null; @@ -32,6 +33,7 @@ class Driver {          chrome.runtime.onMessage.addListener(this.onBgMessage.bind(this));          window.addEventListener('message', this.onFrameMessage.bind(this)); +        window.addEventListener('mouseover', this.onMouseOver.bind(this));          window.addEventListener('mousedown', this.onMouseDown.bind(this));          window.addEventListener('mousemove', this.onMouseMove.bind(this));          window.addEventListener('keydown', this.onKeyDown.bind(this)); @@ -46,25 +48,58 @@ class Driver {          });      } +    popupTimerSet(callback) { +        this.popupTimerClear(); +        this.popupTimer = window.setTimeout(callback, this.options.scanDelay); +    } + +    popupTimerClear() { +        if (this.popupTimer !== null) { +            window.clearTimeout(this.popupTimer); +            this.popupTimer = null; +        } +    } +      onKeyDown(e) { -        if (this.enabled && this.lastMousePos !== null && (e.keyCode === 16 || e.charCode === 16)) { -            this.searchAt(this.lastMousePos, e.ctrlKey ? 'kanji' : 'terms'); +        this.popupTimerClear(); + +        if (this.enabled && this.lastMousePos !== null && e.keyCode === 16 /* shift */) { +            this.searchAt(this.lastMousePos, true);          } else {              this.hidePopup();          }      } +    onMouseOver(e) { +        if (e.target === this.popup.container && this.popuptimer !== null) { +            this.popupTimerClear(); +        } +    } +      onMouseMove(e) { +        this.popupTimerClear(); +          this.lastMousePos = {x: e.clientX, y: e.clientY}; -        if (this.enabled && (e.shiftKey || e.which === 2)) { -            this.searchAt(this.lastMousePos, e.ctrlKey ? 'kanji' : 'terms'); +        if (!this.enabled) { +            return; +        } + +        if (this.options.holdShiftToScan && !e.shiftKey) { +            return; +        } + +        const searcher = () => this.searchAt(this.lastMousePos, false); +        if (!this.popup.visible() || e.shiftKey || e.which === 2 /* mmb */) { +            searcher(); +        } else { +            this.popupTimerSet(searcher);          }      }      onMouseDown(e) {          this.lastMousePos = {x: e.clientX, y: e.clientY}; -        if (this.enabled && (e.shiftKey || e.which === 2)) { -            this.searchAt(this.lastMousePos, e.ctrlKey ? 'kanji' : 'terms'); +        if (this.enabled && (e.shiftKey || !this.options.holdShiftToScan || e.which === 2 /* mmb */)) { +            this.searchAt(this.lastMousePos, true);          } else {              this.hidePopup();          } @@ -90,10 +125,10 @@ class Driver {          textSource.setEndOffset(this.options.scanLength);          this.pendingLookup = true; -        findTerm(textSource.text()).then(({definitions, length}) => { +        return findTerm(textSource.text()).then(({definitions, length}) => {              if (definitions.length === 0) {                  this.pendingLookup = false; -                this.hidePopup(); +                return false;              } else {                  textSource.setEndOffset(length); @@ -113,6 +148,8 @@ class Driver {                      if (states !== null) {                          states.forEach((state, index) => this.popup.invokeApi('setActionState', {index, state, sequence}));                      } + +                    return true;                  });              }          }); @@ -122,10 +159,10 @@ class Driver {          textSource.setEndOffset(1);          this.pendingLookup = true; -        findKanji(textSource.text()).then(definitions => { +        return findKanji(textSource.text()).then(definitions => {              if (definitions.length === 0) {                  this.pendingLookup = false; -                this.hidePopup(); +                return false;              } else {                  definitions.forEach(definition => definition.url = window.location.href); @@ -139,34 +176,40 @@ class Driver {                      if (states !== null) {                          states.forEach((state, index) => this.popup.invokeApi('setActionState', {index, state, sequence}));                      } + +                    return true;                  });              }          });      } -    searchAt(point, mode) { +    searchAt(point, hideNotFound) {          if (this.pendingLookup) {              return;          }          const textSource = textSourceFromPoint(point);          if (textSource === null || !textSource.containsPoint(point)) { -            this.hidePopup(); +            if (hideNotFound) { +                this.hidePopup(); +            } +              return;          }          if (this.lastTextSource !== null && this.lastTextSource.equals(textSource)) { -            return; +            return true;          } -        switch (mode) { -            case 'terms': -                this.searchTerms(textSource); -                break; -            case 'kanji': -                this.searchKanji(textSource); -                break; -        } +        this.searchTerms(textSource).then(found => { +            if (!found) { +                this.searchKanji(textSource).then(found => { +                    if (!found && hideNotFound) { +                        this.hidePopup(); +                    } +                }); +            } +        });      }      showPopup(textSource, content) { diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 31ff02d8..83da3fe1 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -19,16 +19,16 @@  class Popup {      constructor() { -        this.popup = null; +        this.container = null;          this.offset = 10;      }      showAt(pos, content) {          this.inject(); -        this.popup.style.left = pos.x + 'px'; -        this.popup.style.top = pos.y + 'px'; -        this.popup.style.visibility = 'visible'; +        this.container.style.left = pos.x + 'px'; +        this.container.style.top = pos.y + 'px'; +        this.container.style.visibility = 'visible';          this.setContent(content);      } @@ -36,58 +36,58 @@ class Popup {      showNextTo(elementRect, content) {          this.inject(); -        const popupRect = this.popup.getBoundingClientRect(); +        const containerRect = this.container.getBoundingClientRect();          let posX = elementRect.left; -        if (posX + popupRect.width >= window.innerWidth) { -            posX = window.innerWidth - popupRect.width; +        if (posX + containerRect.width >= window.innerWidth) { +            posX = window.innerWidth - containerRect.width;          }          let posY = elementRect.bottom + this.offset; -        if (posY + popupRect.height >= window.innerHeight) { -            posY = elementRect.top - popupRect.height - this.offset; +        if (posY + containerRect.height >= window.innerHeight) { +            posY = elementRect.top - containerRect.height - this.offset;          }          this.showAt({x: posX, y: posY}, content);      }      visible() { -        return this.popup !== null && this.popup.style.visibility !== 'hidden'; +        return this.container !== null && this.container.style.visibility !== 'hidden';      }      hide() { -        if (this.popup !== null) { -            this.popup.style.visibility = 'hidden'; +        if (this.container !== null) { +            this.container.style.visibility = 'hidden';          }      }      setContent(content) { -        if (this.popup === null) { +        if (this.container === null) {              return;          } -        const doc = this.popup.contentDocument; +        const doc = this.container.contentDocument;          doc.open();          doc.write(content);          doc.close();      }      invokeApi(action, params) { -        if (this.popup !== null) { -            this.popup.contentWindow.postMessage({action, params}, '*'); +        if (this.container !== null) { +            this.container.contentWindow.postMessage({action, params}, '*');          }      }      inject() { -        if (this.popup !== null) { +        if (this.container !== null) {              return;          } -        this.popup = document.createElement('iframe'); -        this.popup.id = 'yomichan-popup'; -        this.popup.addEventListener('mousedown', e => e.stopPropagation()); -        this.popup.addEventListener('scroll', e => e.stopPropagation()); +        this.container = document.createElement('iframe'); +        this.container.id = 'yomichan-popup'; +        this.container.addEventListener('mousedown', e => e.stopPropagation()); +        this.container.addEventListener('scroll', e => e.stopPropagation()); -        document.body.appendChild(this.popup); +        document.body.appendChild(this.container);      }  } |