diff options
Diffstat (limited to 'ext/bg/js/search.js')
-rw-r--r-- | ext/bg/js/search.js | 299 |
1 files changed, 148 insertions, 151 deletions
diff --git a/ext/bg/js/search.js b/ext/bg/js/search.js index e9ec2b85..90e9fce8 100644 --- a/ext/bg/js/search.js +++ b/ext/bg/js/search.js @@ -30,31 +30,22 @@ class DisplaySearch extends Display { constructor() { super(document.querySelector('#spinner'), document.querySelector('#content')); - this._isPrepared = false; - - this.setOptionsContext({ - depth: 0, - url: window.location.href + this._search = document.querySelector('#search'); + this._query = document.querySelector('#query'); + this._intro = document.querySelector('#intro'); + this._clipboardMonitorEnable = document.querySelector('#clipboard-monitor-enable'); + this._wanakanaEnable = document.querySelector('#wanakana-enable'); + this._introVisible = true; + this._introAnimationTimer = null; + this._clipboardMonitor = new ClipboardMonitor({ + getClipboard: api.clipboardGet.bind(api) }); - - this.queryParser = new QueryParser({ + this._queryParser = new QueryParser({ getOptionsContext: this.getOptionsContext.bind(this), setContent: this.setContent.bind(this), setSpinnerVisible: this.setSpinnerVisible.bind(this) }); - - this.search = document.querySelector('#search'); - this.query = document.querySelector('#query'); - this.intro = document.querySelector('#intro'); - this.clipboardMonitorEnable = document.querySelector('#clipboard-monitor-enable'); - this.wanakanaEnable = document.querySelector('#wanakana-enable'); - - this.introVisible = true; - this.introAnimationTimer = null; - - this.clipboardMonitor = new ClipboardMonitor({getClipboard: api.clipboardGet.bind(api)}); - this._onKeyDownIgnoreKeys = new Map([ ['ANY_MOD', new Set([ 'Tab', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'PageDown', 'PageUp', 'Home', 'End', @@ -69,17 +60,21 @@ class DisplaySearch extends Display { ['AltGraph', new Set()], ['Shift', new Set()] ]); - this._runtimeMessageHandlers = new Map([ - ['searchQueryUpdate', this.onExternalSearchUpdate.bind(this)] + ['searchQueryUpdate', this._onExternalSearchUpdate.bind(this)] ]); + + this.setOptionsContext({ + depth: 0, + url: window.location.href + }); } async prepare() { await super.prepare(); await this.updateOptions(); yomichan.on('optionsUpdated', () => this.updateOptions()); - await this.queryParser.prepare(); + await this._queryParser.prepare(); const options = this.getOptions(); const {queryParams: {query='', mode=''}} = parseUrl(window.location.href); @@ -87,35 +82,35 @@ class DisplaySearch extends Display { document.documentElement.dataset.searchMode = mode; if (options.general.enableWanakana === true) { - this.wanakanaEnable.checked = true; - wanakana.bind(this.query); + this._wanakanaEnable.checked = true; + wanakana.bind(this._query); } else { - this.wanakanaEnable.checked = false; + this._wanakanaEnable.checked = false; } - this.setQuery(query); - this.onSearchQueryUpdated(this.query.value, false); + this._setQuery(query); + this._onSearchQueryUpdated(this._query.value, false); if (mode !== 'popup') { if (options.general.enableClipboardMonitor === true) { - this.clipboardMonitorEnable.checked = true; - this.clipboardMonitor.start(); + this._clipboardMonitorEnable.checked = true; + this._clipboardMonitor.start(); } else { - this.clipboardMonitorEnable.checked = false; + this._clipboardMonitorEnable.checked = false; } - this.clipboardMonitorEnable.addEventListener('change', this.onClipboardMonitorEnableChange.bind(this)); + this._clipboardMonitorEnable.addEventListener('change', this._onClipboardMonitorEnableChange.bind(this)); } - chrome.runtime.onMessage.addListener(this.onRuntimeMessage.bind(this)); + chrome.runtime.onMessage.addListener(this._onRuntimeMessage.bind(this)); - this.search.addEventListener('click', this.onSearch.bind(this), false); - this.query.addEventListener('input', this.onSearchInput.bind(this), false); - this.wanakanaEnable.addEventListener('change', this.onWanakanaEnableChange.bind(this)); - window.addEventListener('popstate', this.onPopState.bind(this)); - window.addEventListener('copy', this.onCopy.bind(this)); - this.clipboardMonitor.on('change', this.onExternalSearchUpdate.bind(this)); + this._search.addEventListener('click', this._onSearch.bind(this), false); + this._query.addEventListener('input', this._onSearchInput.bind(this), false); + this._wanakanaEnable.addEventListener('change', this._onWanakanaEnableChange.bind(this)); + window.addEventListener('popstate', this._onPopState.bind(this)); + window.addEventListener('copy', this._onCopy.bind(this)); + this._clipboardMonitor.on('change', this._onExternalSearchUpdate.bind(this)); - this.updateSearchButton(); + this._updateSearchButton(); await this._prepareNestedPopups(); @@ -123,49 +118,94 @@ class DisplaySearch extends Display { } onEscape() { - if (this.query === null) { + if (this._query === null) { return; } - this.query.focus(); - this.query.select(); + this._query.focus(); + this._query.select(); } - onSearchInput() { - this.updateSearchButton(); + onKeyDown(e) { + const key = DOM.getKeyFromEvent(e); + const ignoreKeys = this._onKeyDownIgnoreKeys; - const queryElementRect = this.query.getBoundingClientRect(); + const activeModifierMap = new Map([ + ['Control', e.ctrlKey], + ['Meta', e.metaKey], + ['Shift', e.shiftKey], + ['Alt', e.altKey], + ['ANY_MOD', true] + ]); + + let preventFocus = false; + for (const [modifier, keys] of ignoreKeys.entries()) { + const modifierActive = activeModifierMap.get(modifier); + if (key === modifier || (modifierActive && keys.has(key))) { + preventFocus = true; + break; + } + } + + if (!super.onKeyDown(e) && !preventFocus && document.activeElement !== this._query) { + this._query.focus({preventScroll: true}); + } + } + + async updateOptions() { + await super.updateOptions(); + const options = this.getOptions(); + this._queryParser.setOptions(options); + if (!this._isPrepared) { return; } + const query = this._query.value; + if (query) { + this._setQuery(query); + this._onSearchQueryUpdated(query, false); + } + } + + async setContent(type, details) { + this._query.blur(); + await super.setContent(type, details); + } + + // Private + + _onSearchInput() { + this._updateSearchButton(); + + const queryElementRect = this._query.getBoundingClientRect(); if (queryElementRect.top < 0 || queryElementRect.bottom > window.innerHeight) { - this.query.scrollIntoView(); + this._query.scrollIntoView(); } } - onSearch(e) { - if (this.query === null) { + _onSearch(e) { + if (this._query === null) { return; } e.preventDefault(); - const query = this.query.value; + const query = this._query.value; - this.queryParser.setText(query); + this._queryParser.setText(query); const url = new URL(window.location.href); url.searchParams.set('query', query); window.history.pushState(null, '', url.toString()); - this.onSearchQueryUpdated(query, true); + this._onSearchQueryUpdated(query, true); } - onPopState() { + _onPopState() { const {queryParams: {query='', mode=''}} = parseUrl(window.location.href); document.documentElement.dataset.searchMode = mode; - this.setQuery(query); - this.onSearchQueryUpdated(this.query.value, false); + this._setQuery(query); + this._onSearchQueryUpdated(this._query.value, false); } - onRuntimeMessage({action, params}, sender, callback) { + _onRuntimeMessage({action, params}, sender, callback) { const handler = this._runtimeMessageHandlers.get(action); if (typeof handler !== 'function') { return false; } @@ -174,46 +214,20 @@ class DisplaySearch extends Display { return false; } - onKeyDown(e) { - const key = DOM.getKeyFromEvent(e); - const ignoreKeys = this._onKeyDownIgnoreKeys; - - const activeModifierMap = new Map([ - ['Control', e.ctrlKey], - ['Meta', e.metaKey], - ['Shift', e.shiftKey], - ['Alt', e.altKey], - ['ANY_MOD', true] - ]); - - let preventFocus = false; - for (const [modifier, keys] of ignoreKeys.entries()) { - const modifierActive = activeModifierMap.get(modifier); - if (key === modifier || (modifierActive && keys.has(key))) { - preventFocus = true; - break; - } - } - - if (!super.onKeyDown(e) && !preventFocus && document.activeElement !== this.query) { - this.query.focus({preventScroll: true}); - } - } - - onCopy() { + _onCopy() { // ignore copy from search page - this.clipboardMonitor.setPreviousText(window.getSelection().toString().trim()); + this._clipboardMonitor.setPreviousText(window.getSelection().toString().trim()); } - onExternalSearchUpdate({text}) { - this.setQuery(text); + _onExternalSearchUpdate({text}) { + this._setQuery(text); const url = new URL(window.location.href); url.searchParams.set('query', text); window.history.pushState(null, '', url.toString()); - this.onSearchQueryUpdated(this.query.value, true); + this._onSearchQueryUpdated(this._query.value, true); } - async onSearchQueryUpdated(query, animate) { + async _onSearchQueryUpdated(query, animate) { try { const details = {}; const match = /^([*\uff0a]*)([\w\W]*?)([*\uff0a]*)$/.exec(query); @@ -227,8 +241,8 @@ class DisplaySearch extends Display { } const valid = (query.length > 0); - this.setIntroVisible(!valid, animate); - this.updateSearchButton(); + this._setIntroVisible(!valid, animate); + this._updateSearchButton(); if (valid) { const {definitions} = await api.termsFind(query, details, this.getOptionsContext()); this.setContent('terms', {definitions, context: { @@ -240,19 +254,19 @@ class DisplaySearch extends Display { } else { this.clearContent(); } - this.setTitleText(query); + this._setTitleText(query); window.parent.postMessage('popupClose', '*'); } catch (e) { this.onError(e); } } - onWanakanaEnableChange(e) { + _onWanakanaEnableChange(e) { const value = e.target.checked; if (value) { - wanakana.bind(this.query); + wanakana.bind(this._query); } else { - wanakana.unbind(this.query); + wanakana.unbind(this._query); } api.modifySettings([{ action: 'set', @@ -263,13 +277,13 @@ class DisplaySearch extends Display { }], 'search'); } - onClipboardMonitorEnableChange(e) { + _onClipboardMonitorEnableChange(e) { if (e.target.checked) { chrome.permissions.request( {permissions: ['clipboardRead']}, (granted) => { if (granted) { - this.clipboardMonitor.start(); + this._clipboardMonitor.start(); api.modifySettings([{ action: 'set', path: 'general.enableClipboardMonitor', @@ -283,7 +297,7 @@ class DisplaySearch extends Display { } ); } else { - this.clipboardMonitor.stop(); + this._clipboardMonitor.stop(); api.modifySettings([{ action: 'set', path: 'general.enableClipboardMonitor', @@ -294,101 +308,84 @@ class DisplaySearch extends Display { } } - async updateOptions() { - await super.updateOptions(); - const options = this.getOptions(); - this.queryParser.setOptions(options); - if (!this._isPrepared) { return; } - const query = this.query.value; - if (query) { - this.setQuery(query); - this.onSearchQueryUpdated(query, false); - } - } - - isWanakanaEnabled() { - return this.wanakanaEnable !== null && this.wanakanaEnable.checked; + _isWanakanaEnabled() { + return this._wanakanaEnable !== null && this._wanakanaEnable.checked; } - setQuery(query) { + _setQuery(query) { let interpretedQuery = query; - if (this.isWanakanaEnabled()) { + if (this._isWanakanaEnabled()) { try { interpretedQuery = wanakana.toKana(query); } catch (e) { // NOP } } - this.query.value = interpretedQuery; - this.queryParser.setText(interpretedQuery); - } - - async setContent(type, details) { - this.query.blur(); - await super.setContent(type, details); + this._query.value = interpretedQuery; + this._queryParser.setText(interpretedQuery); } - setIntroVisible(visible, animate) { - if (this.introVisible === visible) { + _setIntroVisible(visible, animate) { + if (this._introVisible === visible) { return; } - this.introVisible = visible; + this._introVisible = visible; - if (this.intro === null) { + if (this._intro === null) { return; } - if (this.introAnimationTimer !== null) { - clearTimeout(this.introAnimationTimer); - this.introAnimationTimer = null; + if (this._introAnimationTimer !== null) { + clearTimeout(this._introAnimationTimer); + this._introAnimationTimer = null; } if (visible) { - this.showIntro(animate); + this._showIntro(animate); } else { - this.hideIntro(animate); + this._hideIntro(animate); } } - showIntro(animate) { + _showIntro(animate) { if (animate) { const duration = 0.4; - this.intro.style.transition = ''; - this.intro.style.height = ''; - const size = this.intro.getBoundingClientRect(); - this.intro.style.height = '0px'; - this.intro.style.transition = `height ${duration}s ease-in-out 0s`; - window.getComputedStyle(this.intro).getPropertyValue('height'); // Commits height so next line can start animation - this.intro.style.height = `${size.height}px`; - this.introAnimationTimer = setTimeout(() => { - this.intro.style.height = ''; - this.introAnimationTimer = null; + this._intro.style.transition = ''; + this._intro.style.height = ''; + const size = this._intro.getBoundingClientRect(); + this._intro.style.height = '0px'; + this._intro.style.transition = `height ${duration}s ease-in-out 0s`; + window.getComputedStyle(this._intro).getPropertyValue('height'); // Commits height so next line can start animation + this._intro.style.height = `${size.height}px`; + this._introAnimationTimer = setTimeout(() => { + this._intro.style.height = ''; + this._introAnimationTimer = null; }, duration * 1000); } else { - this.intro.style.transition = ''; - this.intro.style.height = ''; + this._intro.style.transition = ''; + this._intro.style.height = ''; } } - hideIntro(animate) { + _hideIntro(animate) { if (animate) { const duration = 0.4; - const size = this.intro.getBoundingClientRect(); - this.intro.style.height = `${size.height}px`; - this.intro.style.transition = `height ${duration}s ease-in-out 0s`; - window.getComputedStyle(this.intro).getPropertyValue('height'); // Commits height so next line can start animation + const size = this._intro.getBoundingClientRect(); + this._intro.style.height = `${size.height}px`; + this._intro.style.transition = `height ${duration}s ease-in-out 0s`; + window.getComputedStyle(this._intro).getPropertyValue('height'); // Commits height so next line can start animation } else { - this.intro.style.transition = ''; + this._intro.style.transition = ''; } - this.intro.style.height = '0'; + this._intro.style.height = '0'; } - updateSearchButton() { - this.search.disabled = this.introVisible && (this.query === null || this.query.value.length === 0); + _updateSearchButton() { + this._search.disabled = this._introVisible && (this._query === null || this._query.value.length === 0); } - setTitleText(text) { + _setTitleText(text) { // Chrome limits title to 1024 characters if (text.length > 1000) { text = text.substring(0, 1000) + '...'; |