summaryrefslogtreecommitdiff
path: root/ext/mixed/js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/mixed/js')
-rw-r--r--ext/mixed/js/display.js344
1 files changed, 185 insertions, 159 deletions
diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js
index f408fb25..97dd7d5c 100644
--- a/ext/mixed/js/display.js
+++ b/ext/mixed/js/display.js
@@ -32,171 +32,57 @@ class Display {
$(document).keydown(this.onKeyDown.bind(this));
}
- handleError(error) {
+ onError(error) {
throw 'override me';
}
- clearSearch() {
+ onSearchClear() {
throw 'override me';
}
- showTermDefs(definitions, options, context) {
- window.focus();
-
- this.spinner.hide();
- this.definitions = definitions;
- this.options = options;
- this.context = context;
-
- const sequence = ++this.sequence;
- const params = {
- definitions,
- addable: options.anki.enable,
- grouped: options.general.groupResults,
- playback: options.general.audioSource !== 'disabled',
- debug: options.general.debugInfo
- };
-
- if (context) {
- for (const definition of definitions) {
- if (context.sentence) {
- definition.cloze = Display.clozeBuild(context.sentence, definition.source);
- }
-
- definition.url = context.url;
- }
- }
-
- apiTemplateRender('terms.html', params).then(content => {
- this.container.html(content);
- this.entryScroll(context && context.index || 0);
-
- $('.action-add-note').click(this.onAddNote.bind(this));
- $('.action-view-note').click(this.onViewNote.bind(this));
- $('.action-play-audio').click(this.onPlayAudio.bind(this));
- $('.kanji-link').click(this.onKanjiLookup.bind(this));
-
- return this.adderButtonsUpdate(['term-kanji', 'term-kana'], sequence);
- }).catch(this.handleError.bind(this));
- }
-
- showKanjiDefs(definitions, options, context) {
- window.focus();
-
- this.spinner.hide();
- this.definitions = definitions;
- this.options = options;
- this.context = context;
-
- const sequence = ++this.sequence;
- const params = {
- definitions,
- source: context && context.source,
- addable: options.anki.enable,
- debug: options.general.debugInfo
- };
-
- if (context) {
- for (const definition of definitions) {
- if (context.sentence) {
- definition.cloze = Display.clozeBuild(context.sentence);
- }
-
- definition.url = context.url;
- }
- }
-
- apiTemplateRender('kanji.html', params).then(content => {
- this.container.html(content);
- this.entryScroll(context && context.index || 0);
-
- $('.action-add-note').click(this.onAddNote.bind(this));
- $('.source-term').click(this.onSourceTerm.bind(this));
-
- return this.adderButtonsUpdate(['kanji'], sequence);
- }).catch(this.handleError.bind(this));
- }
-
- adderButtonsUpdate(modes, sequence) {
- return apiDefinitionsAddable(this.definitions, modes).then(states => {
- if (!states || sequence !== this.sequence) {
- return;
- }
-
- states.forEach((state, index) => {
- for (const mode in state) {
- const button = Display.adderButtonFind(index, mode);
- if (state[mode]) {
- button.removeClass('disabled');
- } else {
- button.addClass('disabled');
- }
-
- button.removeClass('pending');
- }
- });
- });
- }
-
- entryScroll(index, smooth) {
- index = Math.min(index, this.definitions.length - 1);
- index = Math.max(index, 0);
-
- $('.current').hide().eq(index).show();
-
- const container = $('html,body').stop();
- const entry = $('.entry').eq(index);
- const target = index === 0 ? 0 : entry.offset().top;
-
- if (smooth) {
- container.animate({scrollTop: target}, 200);
- } else {
- container.scrollTop(target);
- }
-
- this.index = index;
- }
-
- onSourceTerm(e) {
+ onSourceTermView(e) {
e.preventDefault();
this.sourceBack();
}
- onKanjiLookup(e) {
- e.preventDefault();
+ async onKanjiLookup(e) {
+ try {
+ e.preventDefault();
- const link = $(e.target);
- const context = {
- source: {
- definitions: this.definitions,
- index: Display.entryIndexFind(link)
+ const link = $(e.target);
+ const context = {
+ source: {
+ definitions: this.definitions,
+ index: Display.entryIndexFind(link)
+ }
+ };
+
+ if (this.context) {
+ context.sentence = this.context.sentence;
+ context.url = this.context.url;
}
- };
- if (this.context) {
- context.sentence = this.context.sentence;
- context.url = this.context.url;
+ const kanjiDefs = await apiKanjiFind(link.text());
+ this.kanjiShow(kanjiDefs, this.options, context);
+ } catch (e) {
+ this.onError(e);
}
-
- apiKanjiFind(link.text()).then(kanjiDefs => {
- this.showKanjiDefs(kanjiDefs, this.options, context);
- }).catch(this.handleError.bind(this));
}
- onPlayAudio(e) {
+ onAudioPlay(e) {
e.preventDefault();
const index = Display.entryIndexFind($(e.currentTarget));
this.audioPlay(this.definitions[index]);
}
- onAddNote(e) {
+ onNoteAdd(e) {
e.preventDefault();
const link = $(e.currentTarget);
const index = Display.entryIndexFind(link);
this.noteAdd(this.definitions[index], link.data('mode'));
}
- onViewNote(e) {
+ onNoteView(e) {
e.preventDefault();
const link = $(e.currentTarget);
const index = Display.entryIndexFind(link);
@@ -220,48 +106,48 @@ class Display {
const handlers = {
27: /* escape */ () => {
- this.clearSearch();
+ this.onSearchClear();
return true;
},
33: /* page up */ () => {
if (e.altKey) {
- this.entryScroll(this.index - 3, true);
+ this.entryScrollIntoView(this.index - 3, true);
return true;
}
},
34: /* page down */ () => {
if (e.altKey) {
- this.entryScroll(this.index + 3, true);
+ this.entryScrollIntoView(this.index + 3, true);
return true;
}
},
35: /* end */ () => {
if (e.altKey) {
- this.entryScroll(this.definitions.length - 1, true);
+ this.entryScrollIntoView(this.definitions.length - 1, true);
return true;
}
},
36: /* home */ () => {
if (e.altKey) {
- this.entryScroll(0, true);
+ this.entryScrollIntoView(0, true);
return true;
}
},
38: /* up */ () => {
if (e.altKey) {
- this.entryScroll(this.index - 1, true);
+ this.entryScrollIntoView(this.index - 1, true);
return true;
}
},
40: /* down */ () => {
if (e.altKey) {
- this.entryScroll(this.index + 1, true);
+ this.entryScrollIntoView(this.index + 1, true);
return true;
}
},
@@ -317,6 +203,135 @@ class Display {
}
}
+ async termsShow(definitions, options, context) {
+ try {
+ window.focus();
+
+ this.definitions = definitions;
+ this.options = options;
+ this.context = context;
+
+ const sequence = ++this.sequence;
+ const params = {
+ definitions,
+ addable: options.anki.enable,
+ grouped: options.general.groupResults,
+ playback: options.general.audioSource !== 'disabled',
+ debug: options.general.debugInfo
+ };
+
+ if (context) {
+ for (const definition of definitions) {
+ if (context.sentence) {
+ definition.cloze = Display.clozeBuild(context.sentence, definition.source);
+ }
+
+ definition.url = context.url;
+ }
+ }
+
+ const content = await apiTemplateRender('terms.html', params);
+ this.container.html(content);
+ this.entryScrollIntoView(context && context.index || 0);
+
+ $('.action-add-note').click(this.onNoteAdd.bind(this));
+ $('.action-view-note').click(this.onNoteView.bind(this));
+ $('.action-play-audio').click(this.onAudioPlay.bind(this));
+ $('.kanji-link').click(this.onKanjiLookup.bind(this));
+
+ await this.adderButtonUpdate(['term-kanji', 'term-kana'], sequence);
+ } catch (e) {
+ this.onError(e);
+ }
+ }
+
+ async kanjiShow(definitions, options, context) {
+ try {
+ window.focus();
+
+ this.definitions = definitions;
+ this.options = options;
+ this.context = context;
+
+ const sequence = ++this.sequence;
+ const params = {
+ definitions,
+ source: context && context.source,
+ addable: options.anki.enable,
+ debug: options.general.debugInfo
+ };
+
+ if (context) {
+ for (const definition of definitions) {
+ if (context.sentence) {
+ definition.cloze = Display.clozeBuild(context.sentence);
+ }
+
+ definition.url = context.url;
+ }
+ }
+
+ const content = await apiTemplateRender('kanji.html', params);
+ this.container.html(content);
+ this.entryScrollIntoView(context && context.index || 0);
+
+ $('.action-add-note').click(this.onNoteAdd.bind(this));
+ $('.source-term').click(this.onSourceTermView.bind(this));
+
+ await this.adderButtonUpdate(['kanji'], sequence);
+ } catch (e) {
+ this.onError(e);
+ }
+ }
+
+ async adderButtonUpdate(modes, sequence) {
+ try {
+ this.spinner.show();
+
+ const states = apiDefinitionsAddable(this.definitions, modes);
+ if (!states || sequence !== this.sequence) {
+ return;
+ }
+
+ for (let i = 0; i < states.length; ++i) {
+ const state = states[i];
+ for (const mode in state) {
+ const button = Display.adderButtonFind(i, mode);
+ if (state[mode]) {
+ button.removeClass('disabled');
+ } else {
+ button.addClass('disabled');
+ }
+
+ button.removeClass('pending');
+ }
+ }
+ } catch (e) {
+ this.onError(e);
+ } finally {
+ this.spinner.hide();
+ }
+ }
+
+ entryScrollIntoView(index, smooth) {
+ index = Math.min(index, this.definitions.length - 1);
+ index = Math.max(index, 0);
+
+ $('.current').hide().eq(index).show();
+
+ const container = $('html,body').stop();
+ const entry = $('.entry').eq(index);
+ const target = index === 0 ? 0 : entry.offset().top;
+
+ if (smooth) {
+ container.animate({scrollTop: target}, 200);
+ } else {
+ container.scrollTop(target);
+ }
+
+ this.index = index;
+ }
+
sourceBack() {
if (this.context && this.context.source) {
const context = {
@@ -325,35 +340,42 @@ class Display {
index: this.context.source.index
};
- this.showTermDefs(this.context.source.definitions, this.options, context);
+ this.termsShow(this.context.source.definitions, this.options, context);
}
}
- noteAdd(definition, mode) {
- this.spinner.show();
- return apiDefinitionAdd(definition, mode).then(noteId => {
+ async noteAdd(definition, mode) {
+ try {
+ this.spinner.show();
+
+ const noteId = await apiDefinitionAdd(definition, mode);
if (noteId) {
const index = this.definitions.indexOf(definition);
Display.adderButtonFind(index, mode).addClass('disabled');
Display.viewerButtonFind(index).removeClass('pending disabled').data('noteId', noteId);
} else {
- this.handleError('note could not be added');
+ throw 'note could note be added';
}
- }).catch(this.handleError.bind(this)).then(() => this.spinner.hide());
+ } catch (e) {
+ this.onError(e);
+ } finally {
+ this.spinner.hide();
+ }
}
- audioPlay(definition) {
- this.spinner.show();
-
- for (const key in this.audioCache) {
- this.audioCache[key].pause();
- }
+ async audioPlay(definition) {
+ try {
+ this.spinner.show();
- audioBuildUrl(definition, this.options.general.audioSource, this.responseCache).then(url => {
+ let url = await audioBuildUrl(definition, this.options.general.audioSource, this.responseCache);
if (!url) {
url = '/mixed/mp3/button.mp3';
}
+ for (const key in this.audioCache) {
+ this.audioCache[key].pause();
+ }
+
let audio = this.audioCache[url];
if (audio) {
audio.currentTime = 0;
@@ -371,7 +393,11 @@ class Display {
audio.play();
};
}
- }).catch(this.handleError.bind(this)).then(() => this.spinner.hide());
+ } catch (e) {
+ this.onError(e);
+ } finally {
+ this.spinner.hide();
+ }
}
static clozeBuild(sentence, source) {