From 8f48a23a458d5d72c9e8d0b5c79bd1eaa8e16925 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Fri, 3 Jul 2020 15:58:29 -0400 Subject: Display class refactoring (#650) * Organize by public/private * Don't access super class's private members * Make _autoPlayAudioTimer private * Refactor constructors * Make functions private * Organize by public/private * Organize window message handlers * Make fields private * Refactor DisplaySearch constructor * Make functions private * Organize by public/private --- ext/bg/js/search.js | 299 ++++++++++++++++++++++++------------------------ ext/fg/js/float.js | 170 +++++++++++++++------------ ext/mixed/js/display.js | 205 +++++++++++++++++---------------- 3 files changed, 350 insertions(+), 324 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) + '...'; diff --git a/ext/fg/js/float.js b/ext/fg/js/float.js index d86f16c3..83355c5c 100644 --- a/ext/fg/js/float.js +++ b/ext/fg/js/float.js @@ -26,39 +26,35 @@ class DisplayFloat extends Display { constructor() { super(document.querySelector('#spinner'), document.querySelector('#definitions')); - this.autoPlayAudioTimer = null; - + this._autoPlayAudioTimer = null; this._secret = yomichan.generateId(16); this._token = null; - this._nestedPopupsPrepared = false; + this._windowMessageHandlers = new Map([ + ['initialize', {handler: this._onMessageInitialize.bind(this), authenticate: false}], + ['configure', {handler: this._onMessageConfigure.bind(this)}], + ['setOptionsContext', {handler: this._onMessageSetOptionsContext.bind(this)}], + ['setContent', {handler: this._onMessageSetContent.bind(this)}], + ['clearAutoPlayTimer', {handler: this._onMessageClearAutoPlayTimer.bind(this)}], + ['setCustomCss', {handler: this._onMessageSetCustomCss.bind(this)}], + ['setContentScale', {handler: this._onMessageSetContentScale.bind(this)}] + ]); - this._onKeyDownHandlers = new Map([ + this.setOnKeyDownHandlers([ ['C', (e) => { if (e.ctrlKey && !window.getSelection().toString()) { - this.onSelectionCopy(); + this._copySelection(); return true; } return false; - }], - ...this._onKeyDownHandlers - ]); - - this._windowMessageHandlers = new Map([ - ['initialize', {handler: this._initialize.bind(this), authenticate: false}], - ['configure', {handler: this._configure.bind(this)}], - ['setOptionsContext', {handler: ({optionsContext}) => this.setOptionsContext(optionsContext)}], - ['setContent', {handler: ({type, details}) => this.setContent(type, details)}], - ['clearAutoPlayTimer', {handler: () => this.clearAutoPlayTimer()}], - ['setCustomCss', {handler: ({css}) => this.setCustomCss(css)}], - ['setContentScale', {handler: ({scale}) => this.setContentScale(scale)}] + }] ]); } async prepare() { await super.prepare(); - window.addEventListener('message', this.onMessage.bind(this), false); + window.addEventListener('message', this._onMessage.bind(this), false); api.broadcastTab('popupPrepared', {secret: this._secret}); } @@ -67,11 +63,46 @@ class DisplayFloat extends Display { window.parent.postMessage('popupClose', '*'); } - onSelectionCopy() { - window.parent.postMessage('selectionCopy', '*'); + async setOptionsContext(optionsContext) { + super.setOptionsContext(optionsContext); + await this.updateOptions(); } - onMessage(e) { + async getDocumentTitle() { + try { + const uniqueId = yomichan.generateId(16); + + const promise = yomichan.getTemporaryListenerResult( + chrome.runtime.onMessage, + ({action, params}, {resolve}) => { + if ( + action === 'documentInformationBroadcast' && + isObject(params) && + params.uniqueId === uniqueId && + params.frameId === 0 + ) { + resolve(params); + } + }, + 2000 + ); + api.broadcastTab('requestDocumentInformationBroadcast', {uniqueId}); + + const {title} = await promise; + return title; + } catch (e) { + return ''; + } + } + + autoPlayAudio() { + this._clearAutoPlayTimer(); + this._autoPlayAudioTimer = window.setTimeout(() => super.autoPlayAudio(), 400); + } + + // Message handling + + _onMessage(e) { const data = e.data; if (typeof data !== 'object' || data === null) { this._logMessageError(e, 'Invalid data'); @@ -99,56 +130,65 @@ class DisplayFloat extends Display { handler(data.params); } - autoPlayAudio() { - this.clearAutoPlayTimer(); - this.autoPlayAudioTimer = window.setTimeout(() => super.autoPlayAudio(), 400); + _onMessageInitialize(params) { + this._initialize(params); } - clearAutoPlayTimer() { - if (this.autoPlayAudioTimer) { - window.clearTimeout(this.autoPlayAudioTimer); - this.autoPlayAudioTimer = null; + async _onMessageConfigure({messageId, frameId, popupId, optionsContext, childrenSupported, scale}) { + this.setOptionsContext(optionsContext); + + await this.updateOptions(); + + if (childrenSupported && !this._nestedPopupsPrepared) { + const {depth, url} = optionsContext; + this._prepareNestedPopups(popupId, depth, frameId, url); + this._nestedPopupsPrepared = true; } + + this._setContentScale(scale); + + api.sendMessageToFrame(frameId, 'popupConfigured', {messageId}); } - async setOptionsContext(optionsContext) { - super.setOptionsContext(optionsContext); - await this.updateOptions(); + _onMessageSetOptionsContext({optionsContext}) { + this.setOptionsContext(optionsContext); } - setContentScale(scale) { - const body = document.body; - if (body === null) { return; } - body.style.fontSize = `${scale}em`; + _onMessageSetContent({type, details}) { + this.setContent(type, details); } - async getDocumentTitle() { - try { - const uniqueId = yomichan.generateId(16); + _onMessageClearAutoPlayTimer() { + this._clearAutoPlayTimer.bind(this); + } - const promise = yomichan.getTemporaryListenerResult( - chrome.runtime.onMessage, - ({action, params}, {resolve}) => { - if ( - action === 'documentInformationBroadcast' && - isObject(params) && - params.uniqueId === uniqueId && - params.frameId === 0 - ) { - resolve(params); - } - }, - 2000 - ); - api.broadcastTab('requestDocumentInformationBroadcast', {uniqueId}); + _onMessageSetCustomCss({css}) { + this.setCustomCss(css); + } - const {title} = await promise; - return title; - } catch (e) { - return ''; + _onMessageSetContentScale({scale}) { + this._setContentScale(scale); + } + + // Private + + _copySelection() { + window.parent.postMessage('selectionCopy', '*'); + } + + _clearAutoPlayTimer() { + if (this._autoPlayAudioTimer) { + window.clearTimeout(this._autoPlayAudioTimer); + this._autoPlayAudioTimer = null; } } + _setContentScale(scale) { + const body = document.body; + if (body === null) { return; } + body.style.fontSize = `${scale}em`; + } + _logMessageError(event, type) { yomichan.logWarning(new Error(`Popup received invalid message from origin ${JSON.stringify(event.origin)}: ${type}`)); } @@ -166,22 +206,6 @@ class DisplayFloat extends Display { api.sendMessageToFrame(frameId, 'popupInitialized', {secret, token}); } - async _configure({messageId, frameId, popupId, optionsContext, childrenSupported, scale}) { - this.setOptionsContext(optionsContext); - - await this.updateOptions(); - - if (childrenSupported && !this._nestedPopupsPrepared) { - const {depth, url} = optionsContext; - this._prepareNestedPopups(popupId, depth, frameId, url); - this._nestedPopupsPrepared = true; - } - - this.setContentScale(scale); - - api.sendMessageToFrame(frameId, 'popupConfigured', {messageId}); - } - _isMessageAuthenticated(message) { return ( this._token !== null && diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index f02a6e5c..2ab1b871 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -47,18 +47,15 @@ class Display { useCache: true }); this._styleNode = null; - this._eventListeners = new EventListenerCollection(); this._persistentEventListeners = new EventListenerCollection(); this._interactive = false; this._eventListenersActive = false; this._clickScanPrevent = false; this._setContentToken = null; - this._mediaLoader = new MediaLoader(); this._displayGenerator = new DisplayGenerator({mediaLoader: this._mediaLoader}); this._windowScroll = new WindowScroll(); - this._onKeyDownHandlers = new Map([ ['Escape', () => { this.onEscape(); @@ -182,6 +179,111 @@ class Display { throw new Error('Override me'); } + onKeyDown(e) { + const key = DOM.getKeyFromEvent(e); + const handler = this._onKeyDownHandlers.get(key); + if (typeof handler === 'function') { + if (handler(e)) { + e.preventDefault(); + return true; + } + } + return false; + } + + getOptions() { + return this._options; + } + + getOptionsContext() { + return this._optionsContext; + } + + setOptionsContext(optionsContext) { + this._optionsContext = optionsContext; + } + + async updateOptions() { + this._options = await api.optionsGet(this.getOptionsContext()); + this._updateDocumentOptions(this._options); + this._updateTheme(this._options.general.popupTheme); + this.setCustomCss(this._options.general.customPopupCss); + } + + addMultipleEventListeners(selector, type, listener, options) { + for (const node of this._container.querySelectorAll(selector)) { + this._eventListeners.addEventListener(node, type, listener, options); + } + } + + autoPlayAudio() { + if (this._definitions.length === 0) { return; } + + this._audioPlay(this._definitions[0], this._getFirstExpressionIndex(), 0); + } + + async setContent(type, details) { + const token = {}; // Unique identifier token + this._setContentToken = token; + try { + this._mediaLoader.unloadAll(); + + switch (type) { + case 'terms': + await this._setContentTerms(details.definitions, details.context, token); + break; + case 'kanji': + await this._setContentKanji(details.definitions, details.context, token); + break; + case 'extensionUnloaded': + this._setContentExtensionUnloaded(); + break; + } + } catch (e) { + this.onError(e); + } finally { + if (this._setContentToken === token) { + this._setContentToken = null; + } + } + } + + clearContent() { + this._container.textContent = ''; + } + + setCustomCss(css) { + if (this._styleNode === null) { + if (css.length === 0) { return; } + this._styleNode = document.createElement('style'); + } + + this._styleNode.textContent = css; + + const parent = document.head; + if (this._styleNode.parentNode !== parent) { + parent.appendChild(this._styleNode); + } + } + + async getDocumentTitle() { + return document.title; + } + + setSpinnerVisible(visible) { + if (this._spinner !== null) { + this._spinner.hidden = !visible; + } + } + + setOnKeyDownHandlers(handlers) { + for (const [key, handler] of handlers) { + this._onKeyDownHandlers.set(key, handler); + } + } + + // Private + _onSourceTermView(e) { e.preventDefault(); this._sourceTermView(); @@ -335,18 +437,6 @@ class Display { api.noteView(link.dataset.noteId); } - onKeyDown(e) { - const key = DOM.getKeyFromEvent(e); - const handler = this._onKeyDownHandlers.get(key); - if (typeof handler === 'function') { - if (handler(e)) { - e.preventDefault(); - return true; - } - } - return false; - } - _onWheel(e) { if (e.altKey) { if (e.deltaY !== 0) { @@ -372,25 +462,6 @@ class Display { } } - getOptions() { - return this._options; - } - - getOptionsContext() { - return this._optionsContext; - } - - setOptionsContext(optionsContext) { - this._optionsContext = optionsContext; - } - - async updateOptions() { - this._options = await api.optionsGet(this.getOptionsContext()); - this._updateDocumentOptions(this._options); - this._updateTheme(this._options.general.popupTheme); - this.setCustomCss(this._options.general.customPopupCss); - } - _updateDocumentOptions(options) { const data = document.documentElement.dataset; data.ankiEnabled = `${options.anki.enable}`; @@ -407,20 +478,6 @@ class Display { document.documentElement.dataset.yomichanTheme = themeName; } - setCustomCss(css) { - if (this._styleNode === null) { - if (css.length === 0) { return; } - this._styleNode = document.createElement('style'); - } - - this._styleNode.textContent = css; - - const parent = document.head; - if (this._styleNode.parentNode !== parent) { - parent.appendChild(this._styleNode); - } - } - _setInteractive(interactive) { interactive = !!interactive; if (this._interactive === interactive) { return; } @@ -469,38 +526,6 @@ class Display { } } - addMultipleEventListeners(selector, type, listener, options) { - for (const node of this._container.querySelectorAll(selector)) { - this._eventListeners.addEventListener(node, type, listener, options); - } - } - - async setContent(type, details) { - const token = {}; // Unique identifier token - this._setContentToken = token; - try { - this._mediaLoader.unloadAll(); - - switch (type) { - case 'terms': - await this._setContentTerms(details.definitions, details.context, token); - break; - case 'kanji': - await this._setContentKanji(details.definitions, details.context, token); - break; - case 'extensionUnloaded': - this._setContentExtensionUnloaded(); - break; - } - } catch (e) { - this.onError(e); - } finally { - if (this._setContentToken === token) { - this._setContentToken = null; - } - } - } - async _setContentTerms(definitions, context, token) { if (!context) { throw new Error('Context expected'); } @@ -631,10 +656,6 @@ class Display { } } - clearContent() { - this._container.textContent = ''; - } - _updateNavigation(previous, next) { const navigation = document.querySelector('#navigation-header'); if (navigation !== null) { @@ -644,12 +665,6 @@ class Display { } } - autoPlayAudio() { - if (this._definitions.length === 0) { return; } - - this._audioPlay(this._definitions[0], this._getFirstExpressionIndex(), 0); - } - _updateAdderButtons(states) { for (let i = 0; i < states.length; ++i) { let noteId = null; @@ -885,12 +900,6 @@ class Display { return api.broadcastTab('popupSetVisibleOverride', {visible}); } - setSpinnerVisible(visible) { - if (this._spinner !== null) { - this._spinner.hidden = !visible; - } - } - _getEntry(index) { const entries = this._container.querySelectorAll('.entry'); return index >= 0 && index < entries.length ? entries[index] : null; @@ -950,10 +959,6 @@ class Display { } } - async getDocumentTitle() { - return document.title; - } - _indexOf(nodeList, node) { for (let i = 0, ii = nodeList.length; i < ii; ++i) { if (nodeList[i] === node) { -- cgit v1.2.3