summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2020-07-03 12:02:21 -0400
committerGitHub <noreply@github.com>2020-07-03 12:02:21 -0400
commite36bc8771fd0b79a43cd809041002879f862487d (patch)
treef817984be2b95c71975892cc1c58a5c9c3b9d0fd /ext
parent6ede83f2934195cb1dc5f261834b7c1bca8bfa90 (diff)
Display refactor (#643)
* Remove statics * Move orphan detection and error handling to Display * Add clearContent function * Add/use public get/set functions for optionsContext * Add public getOptions * Move interactive assignment * Mark fields as private * Mark functions as private * Change stray getter into a function
Diffstat (limited to 'ext')
-rw-r--r--ext/bg/js/search.js18
-rw-r--r--ext/fg/js/float.js20
-rw-r--r--ext/mixed/js/display.js531
3 files changed, 287 insertions, 282 deletions
diff --git a/ext/bg/js/search.js b/ext/bg/js/search.js
index e968e8cf..e9ec2b85 100644
--- a/ext/bg/js/search.js
+++ b/ext/bg/js/search.js
@@ -33,10 +33,10 @@ class DisplaySearch extends Display {
this._isPrepared = false;
- this.optionsContext = {
+ this.setOptionsContext({
depth: 0,
url: window.location.href
- };
+ });
this.queryParser = new QueryParser({
getOptionsContext: this.getOptionsContext.bind(this),
@@ -80,12 +80,13 @@ class DisplaySearch extends Display {
await this.updateOptions();
yomichan.on('optionsUpdated', () => this.updateOptions());
await this.queryParser.prepare();
+ const options = this.getOptions();
const {queryParams: {query='', mode=''}} = parseUrl(window.location.href);
document.documentElement.dataset.searchMode = mode;
- if (this.options.general.enableWanakana === true) {
+ if (options.general.enableWanakana === true) {
this.wanakanaEnable.checked = true;
wanakana.bind(this.query);
} else {
@@ -96,7 +97,7 @@ class DisplaySearch extends Display {
this.onSearchQueryUpdated(this.query.value, false);
if (mode !== 'popup') {
- if (this.options.general.enableClipboardMonitor === true) {
+ if (options.general.enableClipboardMonitor === true) {
this.clipboardMonitorEnable.checked = true;
this.clipboardMonitor.start();
} else {
@@ -121,10 +122,6 @@ class DisplaySearch extends Display {
this._isPrepared = true;
}
- onError(error) {
- yomichan.logError(error);
- }
-
onEscape() {
if (this.query === null) {
return;
@@ -241,7 +238,7 @@ class DisplaySearch extends Display {
url: window.location.href
}});
} else {
- this.container.textContent = '';
+ this.clearContent();
}
this.setTitleText(query);
window.parent.postMessage('popupClose', '*');
@@ -299,7 +296,8 @@ class DisplaySearch extends Display {
async updateOptions() {
await super.updateOptions();
- this.queryParser.setOptions(this.options);
+ const options = this.getOptions();
+ this.queryParser.setOptions(options);
if (!this._isPrepared) { return; }
const query = this.query.value;
if (query) {
diff --git a/ext/fg/js/float.js b/ext/fg/js/float.js
index d7beb675..d86f16c3 100644
--- a/ext/fg/js/float.js
+++ b/ext/fg/js/float.js
@@ -31,7 +31,6 @@ class DisplayFloat extends Display {
this._secret = yomichan.generateId(16);
this._token = null;
- this._orphaned = false;
this._nestedPopupsPrepared = false;
this._onKeyDownHandlers = new Map([
@@ -59,24 +58,11 @@ class DisplayFloat extends Display {
async prepare() {
await super.prepare();
- yomichan.on('orphaned', this.onOrphaned.bind(this));
window.addEventListener('message', this.onMessage.bind(this), false);
api.broadcastTab('popupPrepared', {secret: this._secret});
}
- onError(error) {
- if (this._orphaned) {
- this.setContent('orphaned');
- } else {
- yomichan.logError(error);
- }
- }
-
- onOrphaned() {
- this._orphaned = true;
- }
-
onEscape() {
window.parent.postMessage('popupClose', '*');
}
@@ -126,7 +112,7 @@ class DisplayFloat extends Display {
}
async setOptionsContext(optionsContext) {
- this.optionsContext = optionsContext;
+ super.setOptionsContext(optionsContext);
await this.updateOptions();
}
@@ -181,7 +167,7 @@ class DisplayFloat extends Display {
}
async _configure({messageId, frameId, popupId, optionsContext, childrenSupported, scale}) {
- this.optionsContext = optionsContext;
+ this.setOptionsContext(optionsContext);
await this.updateOptions();
@@ -208,7 +194,7 @@ class DisplayFloat extends Display {
let complete = false;
const onOptionsUpdated = async () => {
- const optionsContext = this.optionsContext;
+ const optionsContext = this.getOptionsContext();
const options = await api.optionsGet(optionsContext);
const maxPopupDepthExceeded = !(typeof depth === 'number' && depth < options.scanning.popupNestingMaxDepth);
if (maxPopupDepthExceeded || complete) { return; }
diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js
index e7439796..c8c574f4 100644
--- a/ext/mixed/js/display.js
+++ b/ext/mixed/js/display.js
@@ -29,16 +29,16 @@
class Display {
constructor(spinner, container) {
- this.spinner = spinner;
- this.container = container;
- this.definitions = [];
- this.optionsContext = null;
- this.options = null;
- this.context = null;
- this.index = 0;
- this.audioPlaying = null;
- this.audioFallback = null;
- this.audioSystem = new AudioSystem({
+ this._spinner = spinner;
+ this._container = container;
+ this._definitions = [];
+ this._optionsContext = null;
+ this._options = null;
+ this._context = null;
+ this._index = 0;
+ this._audioPlaying = null;
+ this._audioFallback = null;
+ this._audioSystem = new AudioSystem({
audioUriBuilder: {
getUri: async (definition, source, details) => {
return await api.audioGetUri(definition, source, details);
@@ -46,18 +46,19 @@ class Display {
},
useCache: true
});
- this.styleNode = null;
+ this._styleNode = null;
+ this._orphaned = false;
- this.eventListeners = new EventListenerCollection();
- this.persistentEventListeners = new EventListenerCollection();
- this.interactive = false;
- this.eventListenersActive = false;
- this.clickScanPrevent = false;
- this.setContentToken = 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._mediaLoader = new MediaLoader();
+ this._displayGenerator = new DisplayGenerator({mediaLoader: this._mediaLoader});
+ this._windowScroll = new WindowScroll();
this._onKeyDownHandlers = new Map([
['Escape', () => {
@@ -66,89 +67,89 @@ class Display {
}],
['PageUp', (e) => {
if (e.altKey) {
- this.entryScrollIntoView(this.index - 3, null, true);
+ this._entryScrollIntoView(this._index - 3, null, true);
return true;
}
return false;
}],
['PageDown', (e) => {
if (e.altKey) {
- this.entryScrollIntoView(this.index + 3, null, true);
+ this._entryScrollIntoView(this._index + 3, null, true);
return true;
}
return false;
}],
['End', (e) => {
if (e.altKey) {
- this.entryScrollIntoView(this.definitions.length - 1, null, true);
+ this._entryScrollIntoView(this._definitions.length - 1, null, true);
return true;
}
return false;
}],
['Home', (e) => {
if (e.altKey) {
- this.entryScrollIntoView(0, null, true);
+ this._entryScrollIntoView(0, null, true);
return true;
}
return false;
}],
['ArrowUp', (e) => {
if (e.altKey) {
- this.entryScrollIntoView(this.index - 1, null, true);
+ this._entryScrollIntoView(this._index - 1, null, true);
return true;
}
return false;
}],
['ArrowDown', (e) => {
if (e.altKey) {
- this.entryScrollIntoView(this.index + 1, null, true);
+ this._entryScrollIntoView(this._index + 1, null, true);
return true;
}
return false;
}],
['B', (e) => {
if (e.altKey) {
- this.sourceTermView();
+ this._sourceTermView();
return true;
}
return false;
}],
['F', (e) => {
if (e.altKey) {
- this.nextTermView();
+ this._nextTermView();
return true;
}
return false;
}],
['E', (e) => {
if (e.altKey) {
- this.noteTryAdd('term-kanji');
+ this._noteTryAdd('term-kanji');
return true;
}
return false;
}],
['K', (e) => {
if (e.altKey) {
- this.noteTryAdd('kanji');
+ this._noteTryAdd('kanji');
return true;
}
return false;
}],
['R', (e) => {
if (e.altKey) {
- this.noteTryAdd('term-kana');
+ this._noteTryAdd('term-kana');
return true;
}
return false;
}],
['P', (e) => {
if (e.altKey) {
- const index = this.index;
- if (index < 0 || index >= this.definitions.length) { return; }
+ const index = this._index;
+ if (index < 0 || index >= this._definitions.length) { return; }
- const entry = this.getEntry(index);
+ const entry = this._getEntry(index);
if (entry !== null && entry.dataset.type === 'term') {
- this.audioPlay(this.definitions[index], this.firstExpressionIndex, index);
+ this._audioPlay(this._definitions[index], this._getFirstExpressionIndex(), index);
}
return true;
}
@@ -156,52 +157,60 @@ class Display {
}],
['V', (e) => {
if (e.altKey) {
- this.noteTryView();
+ this._noteTryView();
return true;
}
return false;
}]
]);
-
- this.setInteractive(true);
}
async prepare() {
+ this._setInteractive(true);
await yomichan.ready();
- await this.displayGenerator.prepare();
+ await this._displayGenerator.prepare();
+ yomichan.on('orphaned', this._onOrphaned.bind(this));
}
- onError(_error) {
- throw new Error('Override me');
+ _onOrphaned() {
+ this._orphaned = true;
+ }
+
+ onError(error) {
+ if (this._orphaned) {
+ this.setContent('orphaned');
+ } else {
+ yomichan.logError(error);
+ }
}
onEscape() {
throw new Error('Override me');
}
- onSourceTermView(e) {
+ _onSourceTermView(e) {
e.preventDefault();
- this.sourceTermView();
+ this._sourceTermView();
}
- onNextTermView(e) {
+ _onNextTermView(e) {
e.preventDefault();
- this.nextTermView();
+ this._nextTermView();
}
- async onKanjiLookup(e) {
+ async _onKanjiLookup(e) {
try {
e.preventDefault();
- if (!this.context) { return; }
+ if (!this._context) { return; }
const link = e.target;
- this.context.update({
- index: this.entryIndexFind(link),
- scroll: this.windowScroll.y
+ this._context.update({
+ index: this._entryIndexFind(link),
+ scroll: this._windowScroll.y
});
const context = {
- sentence: this.context.get('sentence'),
- url: this.context.get('url')
+ sentence: this._context.get('sentence'),
+ url: this._context.get('url')
};
const definitions = await api.kanjiFind(link.textContent, this.getOptionsContext());
@@ -211,53 +220,53 @@ class Display {
}
}
- onGlossaryMouseDown(e) {
+ _onGlossaryMouseDown(e) {
if (DOM.isMouseButtonPressed(e, 'primary')) {
- this.clickScanPrevent = false;
+ this._clickScanPrevent = false;
}
}
- onGlossaryMouseMove() {
- this.clickScanPrevent = true;
+ _onGlossaryMouseMove() {
+ this._clickScanPrevent = true;
}
- onGlossaryMouseUp(e) {
- if (!this.clickScanPrevent && DOM.isMouseButtonPressed(e, 'primary')) {
- this.onTermLookup(e);
+ _onGlossaryMouseUp(e) {
+ if (!this._clickScanPrevent && DOM.isMouseButtonPressed(e, 'primary')) {
+ this._onTermLookup(e);
}
}
- async onTermLookup(e, {disableScroll, selectText, disableHistory}={}) {
+ async _onTermLookup(e, {disableScroll, selectText, disableHistory}={}) {
try {
- if (!this.context) { return; }
+ if (!this._context) { return; }
- const termLookupResults = await this.termLookup(e);
+ const termLookupResults = await this._termLookup(e);
if (!termLookupResults) { return; }
const {textSource, definitions} = termLookupResults;
const scannedElement = e.target;
- const sentenceExtent = this.options.anki.sentenceExt;
- const layoutAwareScan = this.options.scanning.layoutAwareScan;
+ const sentenceExtent = this._options.anki.sentenceExt;
+ const layoutAwareScan = this._options.scanning.layoutAwareScan;
const sentence = docSentenceExtract(textSource, sentenceExtent, layoutAwareScan);
- this.context.update({
- index: this.entryIndexFind(scannedElement),
- scroll: this.windowScroll.y
+ this._context.update({
+ index: this._entryIndexFind(scannedElement),
+ scroll: this._windowScroll.y
});
const context = {
disableScroll,
disableHistory,
sentence,
- url: this.context.get('url')
+ url: this._context.get('url')
};
if (disableHistory) {
Object.assign(context, {
- previous: this.context.previous,
- next: this.context.next
+ previous: this._context.previous,
+ next: this._context.next
});
} else {
Object.assign(context, {
- previous: this.context
+ previous: this._context
});
}
@@ -271,11 +280,11 @@ class Display {
}
}
- async termLookup(e) {
+ async _termLookup(e) {
try {
e.preventDefault();
- const {length: scanLength, deepDomScan: deepScan, layoutAwareScan} = this.options.scanning;
+ const {length: scanLength, deepDomScan: deepScan, layoutAwareScan} = this._options.scanning;
const textSource = docRangeFromPoint(e.clientX, e.clientY, deepScan);
if (textSource === null) {
return false;
@@ -301,32 +310,32 @@ class Display {
}
}
- onAudioPlay(e) {
+ _onAudioPlay(e) {
e.preventDefault();
const link = e.currentTarget;
const entry = link.closest('.entry');
- const index = this.entryIndexFind(entry);
- if (index < 0 || index >= this.definitions.length) { return; }
+ const index = this._entryIndexFind(entry);
+ if (index < 0 || index >= this._definitions.length) { return; }
- const expressionIndex = Display.indexOf(entry.querySelectorAll('.term-expression .action-play-audio'), link);
- this.audioPlay(
- this.definitions[index],
+ const expressionIndex = this._indexOf(entry.querySelectorAll('.term-expression .action-play-audio'), link);
+ this._audioPlay(
+ this._definitions[index],
// expressionIndex is used in audioPlay to detect result output mode
- Math.max(expressionIndex, this.options.general.resultOutputMode === 'merge' ? 0 : -1),
+ Math.max(expressionIndex, this._options.general.resultOutputMode === 'merge' ? 0 : -1),
index
);
}
- onNoteAdd(e) {
+ _onNoteAdd(e) {
e.preventDefault();
const link = e.currentTarget;
- const index = this.entryIndexFind(link);
- if (index < 0 || index >= this.definitions.length) { return; }
+ const index = this._entryIndexFind(link);
+ if (index < 0 || index >= this._definitions.length) { return; }
- this.noteAdd(this.definitions[index], link.dataset.mode);
+ this._noteAdd(this._definitions[index], link.dataset.mode);
}
- onNoteView(e) {
+ _onNoteView(e) {
e.preventDefault();
const link = e.currentTarget;
api.noteView(link.dataset.noteId);
@@ -344,43 +353,51 @@ class Display {
return false;
}
- onWheel(e) {
+ _onWheel(e) {
if (e.altKey) {
if (e.deltaY !== 0) {
- this.entryScrollIntoView(this.index + (e.deltaY > 0 ? 1 : -1), null, true);
+ this._entryScrollIntoView(this._index + (e.deltaY > 0 ? 1 : -1), null, true);
e.preventDefault();
}
} else if (e.shiftKey) {
- this.onHistoryWheel(e);
+ this._onHistoryWheel(e);
}
}
- onHistoryWheel(e) {
+ _onHistoryWheel(e) {
if (e.altKey) { return; }
const delta = -e.deltaX || e.deltaY;
if (delta > 0) {
- this.sourceTermView();
+ this._sourceTermView();
e.preventDefault();
e.stopPropagation();
} else if (delta < 0) {
- this.nextTermView();
+ this._nextTermView();
e.preventDefault();
e.stopPropagation();
}
}
+ getOptions() {
+ return this._options;
+ }
+
getOptionsContext() {
- return this.optionsContext;
+ 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);
+ 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) {
+ _updateDocumentOptions(options) {
const data = document.documentElement.dataset;
data.ankiEnabled = `${options.anki.enable}`;
data.audioEnabled = `${options.audio.enabled}`;
@@ -392,227 +409,227 @@ class Display {
data.debug = `${options.general.debugInfo}`;
}
- updateTheme(themeName) {
+ _updateTheme(themeName) {
document.documentElement.dataset.yomichanTheme = themeName;
}
setCustomCss(css) {
- if (this.styleNode === null) {
+ if (this._styleNode === null) {
if (css.length === 0) { return; }
- this.styleNode = document.createElement('style');
+ this._styleNode = document.createElement('style');
}
- this.styleNode.textContent = css;
+ this._styleNode.textContent = css;
const parent = document.head;
- if (this.styleNode.parentNode !== parent) {
- parent.appendChild(this.styleNode);
+ if (this._styleNode.parentNode !== parent) {
+ parent.appendChild(this._styleNode);
}
}
- setInteractive(interactive) {
+ _setInteractive(interactive) {
interactive = !!interactive;
- if (this.interactive === interactive) { return; }
- this.interactive = interactive;
+ if (this._interactive === interactive) { return; }
+ this._interactive = interactive;
if (interactive) {
const actionPrevious = document.querySelector('.action-previous');
const actionNext = document.querySelector('.action-next');
// const navigationHeader = document.querySelector('.navigation-header');
- this.persistentEventListeners.addEventListener(document, 'keydown', this.onKeyDown.bind(this), false);
- this.persistentEventListeners.addEventListener(document, 'wheel', this.onWheel.bind(this), {passive: false});
+ this._persistentEventListeners.addEventListener(document, 'keydown', this.onKeyDown.bind(this), false);
+ this._persistentEventListeners.addEventListener(document, 'wheel', this._onWheel.bind(this), {passive: false});
if (actionPrevious !== null) {
- this.persistentEventListeners.addEventListener(actionPrevious, 'click', this.onSourceTermView.bind(this));
+ this._persistentEventListeners.addEventListener(actionPrevious, 'click', this._onSourceTermView.bind(this));
}
if (actionNext !== null) {
- this.persistentEventListeners.addEventListener(actionNext, 'click', this.onNextTermView.bind(this));
+ this._persistentEventListeners.addEventListener(actionNext, 'click', this._onNextTermView.bind(this));
}
// temporarily disabled
// if (navigationHeader !== null) {
// this.persistentEventListeners.addEventListener(navigationHeader, 'wheel', this.onHistoryWheel.bind(this), {passive: false});
// }
} else {
- this.persistentEventListeners.removeAllEventListeners();
+ this._persistentEventListeners.removeAllEventListeners();
}
- this.setEventListenersActive(this.eventListenersActive);
+ this._setEventListenersActive(this._eventListenersActive);
}
- setEventListenersActive(active) {
- active = !!active && this.interactive;
- if (this.eventListenersActive === active) { return; }
- this.eventListenersActive = active;
+ _setEventListenersActive(active) {
+ active = !!active && this._interactive;
+ if (this._eventListenersActive === active) { return; }
+ this._eventListenersActive = active;
if (active) {
- this.addMultipleEventListeners('.action-add-note', 'click', this.onNoteAdd.bind(this));
- this.addMultipleEventListeners('.action-view-note', 'click', this.onNoteView.bind(this));
- this.addMultipleEventListeners('.action-play-audio', 'click', this.onAudioPlay.bind(this));
- this.addMultipleEventListeners('.kanji-link', 'click', this.onKanjiLookup.bind(this));
- if (this.options.scanning.enablePopupSearch) {
- this.addMultipleEventListeners('.term-glossary-item, .tag', 'mouseup', this.onGlossaryMouseUp.bind(this));
- this.addMultipleEventListeners('.term-glossary-item, .tag', 'mousedown', this.onGlossaryMouseDown.bind(this));
- this.addMultipleEventListeners('.term-glossary-item, .tag', 'mousemove', this.onGlossaryMouseMove.bind(this));
+ this.addMultipleEventListeners('.action-add-note', 'click', this._onNoteAdd.bind(this));
+ this.addMultipleEventListeners('.action-view-note', 'click', this._onNoteView.bind(this));
+ this.addMultipleEventListeners('.action-play-audio', 'click', this._onAudioPlay.bind(this));
+ this.addMultipleEventListeners('.kanji-link', 'click', this._onKanjiLookup.bind(this));
+ if (this._options.scanning.enablePopupSearch) {
+ this.addMultipleEventListeners('.term-glossary-item, .tag', 'mouseup', this._onGlossaryMouseUp.bind(this));
+ this.addMultipleEventListeners('.term-glossary-item, .tag', 'mousedown', this._onGlossaryMouseDown.bind(this));
+ this.addMultipleEventListeners('.term-glossary-item, .tag', 'mousemove', this._onGlossaryMouseMove.bind(this));
}
} else {
- this.eventListeners.removeAllEventListeners();
+ this._eventListeners.removeAllEventListeners();
}
}
addMultipleEventListeners(selector, type, listener, options) {
- for (const node of this.container.querySelectorAll(selector)) {
- this.eventListeners.addEventListener(node, 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;
+ this._setContentToken = token;
try {
- this.mediaLoader.unloadAll();
+ this._mediaLoader.unloadAll();
switch (type) {
case 'terms':
- await this.setContentTerms(details.definitions, details.context, token);
+ await this._setContentTerms(details.definitions, details.context, token);
break;
case 'kanji':
- await this.setContentKanji(details.definitions, details.context, token);
+ await this._setContentKanji(details.definitions, details.context, token);
break;
case 'orphaned':
- this.setContentOrphaned();
+ this._setContentOrphaned();
break;
}
} catch (e) {
this.onError(e);
} finally {
- if (this.setContentToken === token) {
- this.setContentToken = null;
+ if (this._setContentToken === token) {
+ this._setContentToken = null;
}
}
}
- async setContentTerms(definitions, context, token) {
+ async _setContentTerms(definitions, context, token) {
if (!context) { throw new Error('Context expected'); }
- this.setEventListenersActive(false);
+ this._setEventListenersActive(false);
if (context.focus !== false) {
window.focus();
}
- this.definitions = definitions;
+ this._definitions = definitions;
if (context.disableHistory) {
delete context.disableHistory;
- this.context = new DisplayContext('terms', definitions, context);
+ this._context = new DisplayContext('terms', definitions, context);
} else {
- this.context = DisplayContext.push(this.context, 'terms', definitions, context);
+ this._context = DisplayContext.push(this._context, 'terms', definitions, context);
}
for (const definition of definitions) {
- definition.cloze = Display.clozeBuild(context.sentence, definition.source);
+ definition.cloze = this._clozeBuild(context.sentence, definition.source);
definition.url = context.url;
}
- this.updateNavigation(this.context.previous, this.context.next);
- this.setNoContentVisible(definitions.length === 0);
+ this._updateNavigation(this._context.previous, this._context.next);
+ this._setNoContentVisible(definitions.length === 0);
- const container = this.container;
+ const container = this._container;
container.textContent = '';
for (let i = 0, ii = definitions.length; i < ii; ++i) {
if (i > 0) {
await promiseTimeout(1);
- if (this.setContentToken !== token) { return; }
+ if (this._setContentToken !== token) { return; }
}
- const entry = this.displayGenerator.createTermEntry(definitions[i]);
+ const entry = this._displayGenerator.createTermEntry(definitions[i]);
container.appendChild(entry);
}
const {index, scroll, disableScroll} = context;
if (!disableScroll) {
- this.entryScrollIntoView(index || 0, scroll);
+ this._entryScrollIntoView(index || 0, scroll);
} else {
delete context.disableScroll;
- this.entrySetCurrent(index || 0);
+ this._entrySetCurrent(index || 0);
}
- if (this.options.audio.enabled && this.options.audio.autoPlay) {
+ if (this._options.audio.enabled && this._options.audio.autoPlay) {
this.autoPlayAudio();
}
- this.setEventListenersActive(true);
+ this._setEventListenersActive(true);
- const states = await this.getDefinitionsAddable(definitions, ['term-kanji', 'term-kana']);
- if (this.setContentToken !== token) { return; }
+ const states = await this._getDefinitionsAddable(definitions, ['term-kanji', 'term-kana']);
+ if (this._setContentToken !== token) { return; }
- this.updateAdderButtons(states);
+ this._updateAdderButtons(states);
}
- async setContentKanji(definitions, context, token) {
+ async _setContentKanji(definitions, context, token) {
if (!context) { throw new Error('Context expected'); }
- this.setEventListenersActive(false);
+ this._setEventListenersActive(false);
if (context.focus !== false) {
window.focus();
}
- this.definitions = definitions;
+ this._definitions = definitions;
if (context.disableHistory) {
delete context.disableHistory;
- this.context = new DisplayContext('kanji', definitions, context);
+ this._context = new DisplayContext('kanji', definitions, context);
} else {
- this.context = DisplayContext.push(this.context, 'kanji', definitions, context);
+ this._context = DisplayContext.push(this._context, 'kanji', definitions, context);
}
for (const definition of definitions) {
- definition.cloze = Display.clozeBuild(context.sentence, definition.character);
+ definition.cloze = this._clozeBuild(context.sentence, definition.character);
definition.url = context.url;
}
- this.updateNavigation(this.context.previous, this.context.next);
- this.setNoContentVisible(definitions.length === 0);
+ this._updateNavigation(this._context.previous, this._context.next);
+ this._setNoContentVisible(definitions.length === 0);
- const container = this.container;
+ const container = this._container;
container.textContent = '';
for (let i = 0, ii = definitions.length; i < ii; ++i) {
if (i > 0) {
await promiseTimeout(1);
- if (this.setContentToken !== token) { return; }
+ if (this._setContentToken !== token) { return; }
}
- const entry = this.displayGenerator.createKanjiEntry(definitions[i]);
+ const entry = this._displayGenerator.createKanjiEntry(definitions[i]);
container.appendChild(entry);
}
const {index, scroll} = context;
- this.entryScrollIntoView(index || 0, scroll);
+ this._entryScrollIntoView(index || 0, scroll);
- this.setEventListenersActive(true);
+ this._setEventListenersActive(true);
- const states = await this.getDefinitionsAddable(definitions, ['kanji']);
- if (this.setContentToken !== token) { return; }
+ const states = await this._getDefinitionsAddable(definitions, ['kanji']);
+ if (this._setContentToken !== token) { return; }
- this.updateAdderButtons(states);
+ this._updateAdderButtons(states);
}
- setContentOrphaned() {
+ _setContentOrphaned() {
const errorOrphaned = document.querySelector('#error-orphaned');
- if (this.container !== null) {
- this.container.hidden = true;
+ if (this._container !== null) {
+ this._container.hidden = true;
}
if (errorOrphaned !== null) {
errorOrphaned.hidden = false;
}
- this.updateNavigation(null, null);
- this.setNoContentVisible(false);
+ this._updateNavigation(null, null);
+ this._setNoContentVisible(false);
}
- setNoContentVisible(visible) {
+ _setNoContentVisible(visible) {
const noResults = document.querySelector('#no-results');
if (noResults !== null) {
@@ -620,7 +637,11 @@ class Display {
}
}
- updateNavigation(previous, next) {
+ clearContent() {
+ this._container.textContent = '';
+ }
+
+ _updateNavigation(previous, next) {
const navigation = document.querySelector('#navigation-header');
if (navigation !== null) {
navigation.hidden = !(previous || next);
@@ -630,16 +651,16 @@ class Display {
}
autoPlayAudio() {
- if (this.definitions.length === 0) { return; }
+ if (this._definitions.length === 0) { return; }
- this.audioPlay(this.definitions[0], this.firstExpressionIndex, 0);
+ this._audioPlay(this._definitions[0], this._getFirstExpressionIndex(), 0);
}
- updateAdderButtons(states) {
+ _updateAdderButtons(states) {
for (let i = 0; i < states.length; ++i) {
let noteId = null;
for (const [mode, info] of Object.entries(states[i])) {
- const button = this.adderButtonFind(i, mode);
+ const button = this._adderButtonFind(i, mode);
if (button === null) {
continue;
}
@@ -651,39 +672,39 @@ class Display {
button.classList.remove('pending');
}
if (noteId !== null) {
- this.viewerButtonShow(i, noteId);
+ this._viewerButtonShow(i, noteId);
}
}
}
- entrySetCurrent(index) {
- index = Math.min(index, this.definitions.length - 1);
+ _entrySetCurrent(index) {
+ index = Math.min(index, this._definitions.length - 1);
index = Math.max(index, 0);
- const entryPre = this.getEntry(this.index);
+ const entryPre = this._getEntry(this._index);
if (entryPre !== null) {
entryPre.classList.remove('entry-current');
}
- const entry = this.getEntry(index);
+ const entry = this._getEntry(index);
if (entry !== null) {
entry.classList.add('entry-current');
}
- this.index = index;
+ this._index = index;
return entry;
}
- entryScrollIntoView(index, scroll, smooth) {
- this.windowScroll.stop();
+ _entryScrollIntoView(index, scroll, smooth) {
+ this._windowScroll.stop();
- const entry = this.entrySetCurrent(index);
+ const entry = this._entrySetCurrent(index);
let target;
if (scroll !== null) {
target = scroll;
} else {
- target = this.index === 0 || entry === null ? 0 : Display.getElementTop(entry);
+ target = this._index === 0 || entry === null ? 0 : this._getElementTop(entry);
const header = document.querySelector('#navigation-header');
if (header !== null) {
@@ -692,19 +713,19 @@ class Display {
}
if (smooth) {
- this.windowScroll.animate(this.windowScroll.x, target, 200);
+ this._windowScroll.animate(this._windowScroll.x, target, 200);
} else {
- this.windowScroll.toY(target);
+ this._windowScroll.toY(target);
}
}
- sourceTermView() {
- if (!this.context || !this.context.previous) { return; }
- this.context.update({
- index: this.index,
- scroll: this.windowScroll.y
+ _sourceTermView() {
+ if (!this._context || !this._context.previous) { return; }
+ this._context.update({
+ index: this._index,
+ scroll: this._windowScroll.y
});
- const previousContext = this.context.previous;
+ const previousContext = this._context.previous;
previousContext.set('disableHistory', true);
const details = {
definitions: previousContext.definitions,
@@ -713,13 +734,13 @@ class Display {
this.setContent(previousContext.type, details);
}
- nextTermView() {
- if (!this.context || !this.context.next) { return; }
- this.context.update({
- index: this.index,
- scroll: this.windowScroll.y
+ _nextTermView() {
+ if (!this._context || !this._context.next) { return; }
+ this._context.update({
+ index: this._index,
+ scroll: this._windowScroll.y
});
- const nextContext = this.context.next;
+ const nextContext = this._context.next;
nextContext.set('disableHistory', true);
const details = {
definitions: nextContext.definitions,
@@ -728,30 +749,30 @@ class Display {
this.setContent(nextContext.type, details);
}
- noteTryAdd(mode) {
- const index = this.index;
- if (index < 0 || index >= this.definitions.length) { return; }
+ _noteTryAdd(mode) {
+ const index = this._index;
+ if (index < 0 || index >= this._definitions.length) { return; }
- const button = this.adderButtonFind(index, mode);
+ const button = this._adderButtonFind(index, mode);
if (button !== null && !button.classList.contains('disabled')) {
- this.noteAdd(this.definitions[index], mode);
+ this._noteAdd(this._definitions[index], mode);
}
}
- noteTryView() {
- const button = this.viewerButtonFind(this.index);
+ _noteTryView() {
+ const button = this._viewerButtonFind(this._index);
if (button !== null && !button.classList.contains('disabled')) {
api.noteView(button.dataset.noteId);
}
}
- async noteAdd(definition, mode) {
+ async _noteAdd(definition, mode) {
try {
this.setSpinnerVisible(true);
const details = {};
- if (this.noteUsesScreenshot(mode)) {
- const screenshot = await this.getScreenshot();
+ if (this._noteUsesScreenshot(mode)) {
+ const screenshot = await this._getScreenshot();
if (screenshot) {
details.screenshot = screenshot;
}
@@ -760,12 +781,12 @@ class Display {
const context = await this._getNoteContext();
const noteId = await api.definitionAdd(definition, mode, context, details, this.getOptionsContext());
if (noteId) {
- const index = this.definitions.indexOf(definition);
- const adderButton = this.adderButtonFind(index, mode);
+ const index = this._definitions.indexOf(definition);
+ const adderButton = this._adderButtonFind(index, mode);
if (adderButton !== null) {
adderButton.classList.add('disabled');
}
- this.viewerButtonShow(index, noteId);
+ this._viewerButtonShow(index, noteId);
} else {
throw new Error('Note could not be added');
}
@@ -776,7 +797,7 @@ class Display {
}
}
- async audioPlay(definition, expressionIndex, entryIndex) {
+ async _audioPlay(definition, expressionIndex, entryIndex) {
try {
this.setSpinnerVisible(true);
@@ -786,19 +807,19 @@ class Display {
let audio, info;
try {
- const {sources, textToSpeechVoice, customSourceUrl} = this.options.audio;
+ const {sources, textToSpeechVoice, customSourceUrl} = this._options.audio;
let index;
- ({audio, index} = await this.audioSystem.getDefinitionAudio(expression, sources, {textToSpeechVoice, customSourceUrl}));
+ ({audio, index} = await this._audioSystem.getDefinitionAudio(expression, sources, {textToSpeechVoice, customSourceUrl}));
info = `From source ${1 + index}: ${sources[index]}`;
} catch (e) {
- if (this.audioFallback === null) {
- this.audioFallback = new Audio('/mixed/mp3/button.mp3');
+ if (this._audioFallback === null) {
+ this._audioFallback = new Audio('/mixed/mp3/button.mp3');
}
- audio = this.audioFallback;
+ audio = this._audioFallback;
info = 'Could not find audio';
}
- const button = this.audioButtonFindImage(entryIndex, expressionIndex);
+ const button = this._audioButtonFindImage(entryIndex, expressionIndex);
if (button !== null) {
let titleDefault = button.dataset.titleDefault;
if (!titleDefault) {
@@ -810,8 +831,8 @@ class Display {
this._stopPlayingAudio();
- const volume = Math.max(0.0, Math.min(1.0, this.options.audio.volume / 100.0));
- this.audioPlaying = audio;
+ const volume = Math.max(0.0, Math.min(1.0, this._options.audio.volume / 100.0));
+ this._audioPlaying = audio;
audio.currentTime = 0;
audio.volume = Number.isFinite(volume) ? volume : 1.0;
const playPromise = audio.play();
@@ -830,14 +851,14 @@ class Display {
}
_stopPlayingAudio() {
- if (this.audioPlaying !== null) {
- this.audioPlaying.pause();
- this.audioPlaying = null;
+ if (this._audioPlaying !== null) {
+ this._audioPlaying.pause();
+ this._audioPlaying = null;
}
}
- noteUsesScreenshot(mode) {
- const optionsAnki = this.options.anki;
+ _noteUsesScreenshot(mode) {
+ const optionsAnki = this._options.anki;
const fields = (mode === 'kanji' ? optionsAnki.kanji : optionsAnki.terms).fields;
for (const fieldValue of Object.values(fields)) {
if (fieldValue.includes('{screenshot}')) {
@@ -847,41 +868,41 @@ class Display {
return false;
}
- async getScreenshot() {
+ async _getScreenshot() {
try {
- await this.setPopupVisibleOverride(false);
+ await this._setPopupVisibleOverride(false);
await promiseTimeout(1); // Wait for popup to be hidden.
- const {format, quality} = this.options.anki.screenshot;
+ const {format, quality} = this._options.anki.screenshot;
const dataUrl = await api.screenshotGet({format, quality});
if (!dataUrl || dataUrl.error) { return; }
return {dataUrl, format};
} finally {
- await this.setPopupVisibleOverride(null);
+ await this._setPopupVisibleOverride(null);
}
}
- get firstExpressionIndex() {
- return this.options.general.resultOutputMode === 'merge' ? 0 : -1;
+ _getFirstExpressionIndex() {
+ return this._options.general.resultOutputMode === 'merge' ? 0 : -1;
}
- setPopupVisibleOverride(visible) {
+ _setPopupVisibleOverride(visible) {
return api.broadcastTab('popupSetVisibleOverride', {visible});
}
setSpinnerVisible(visible) {
- if (this.spinner !== null) {
- this.spinner.hidden = !visible;
+ if (this._spinner !== null) {
+ this._spinner.hidden = !visible;
}
}
- getEntry(index) {
- const entries = this.container.querySelectorAll('.entry');
+ _getEntry(index) {
+ const entries = this._container.querySelectorAll('.entry');
return index >= 0 && index < entries.length ? entries[index] : null;
}
- static clozeBuild({text, offset}, source) {
+ _clozeBuild({text, offset}, source) {
return {
sentence: text.trim(),
prefix: text.substring(0, offset).trim(),
@@ -890,23 +911,23 @@ class Display {
};
}
- entryIndexFind(element) {
+ _entryIndexFind(element) {
const entry = element.closest('.entry');
- return entry !== null ? Display.indexOf(this.container.querySelectorAll('.entry'), entry) : -1;
+ return entry !== null ? this._indexOf(this._container.querySelectorAll('.entry'), entry) : -1;
}
- adderButtonFind(index, mode) {
- const entry = this.getEntry(index);
+ _adderButtonFind(index, mode) {
+ const entry = this._getEntry(index);
return entry !== null ? entry.querySelector(`.action-add-note[data-mode="${mode}"]`) : null;
}
- viewerButtonFind(index) {
- const entry = this.getEntry(index);
+ _viewerButtonFind(index) {
+ const entry = this._getEntry(index);
return entry !== null ? entry.querySelector('.action-view-note') : null;
}
- viewerButtonShow(index, noteId) {
- const viewerButton = this.viewerButtonFind(index);
+ _viewerButtonShow(index, noteId) {
+ const viewerButton = this._viewerButtonFind(index);
if (viewerButton === null) {
return;
}
@@ -914,8 +935,8 @@ class Display {
viewerButton.dataset.noteId = noteId;
}
- audioButtonFindImage(index, expressionIndex) {
- const entry = this.getEntry(index);
+ _audioButtonFindImage(index, expressionIndex) {
+ const entry = this._getEntry(index);
if (entry === null) { return null; }
const container = (
@@ -926,7 +947,7 @@ class Display {
return container !== null ? container.querySelector('.action-play-audio>img') : null;
}
- async getDefinitionsAddable(definitions, modes) {
+ async _getDefinitionsAddable(definitions, modes) {
try {
const context = await this._getNoteContext();
return await api.definitionsAddable(definitions, modes, context, this.getOptionsContext());
@@ -939,7 +960,7 @@ class Display {
return document.title;
}
- static indexOf(nodeList, node) {
+ _indexOf(nodeList, node) {
for (let i = 0, ii = nodeList.length; i < ii; ++i) {
if (nodeList[i] === node) {
return i;
@@ -948,7 +969,7 @@ class Display {
return -1;
}
- static getElementTop(element) {
+ _getElementTop(element) {
const elementRect = element.getBoundingClientRect();
const documentRect = document.documentElement.getBoundingClientRect();
return elementRect.top - documentRect.top;