aboutsummaryrefslogtreecommitdiff
path: root/ext/fg/js/frame.js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/fg/js/frame.js')
-rw-r--r--ext/fg/js/frame.js168
1 files changed, 124 insertions, 44 deletions
diff --git a/ext/fg/js/frame.js b/ext/fg/js/frame.js
index 8a99a405..4295dbb3 100644
--- a/ext/fg/js/frame.js
+++ b/ext/fg/js/frame.js
@@ -16,65 +16,145 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+class Frame {
+ constructor() {
+ this.definitions = [];
+ this.audioCache = {};
+ this.sequence = 0;
-function invokeApi(action, params, target) {
- target.postMessage({action, params}, '*');
-}
+ $(window).on('message', e => {
+ const {action, params} = e.originalEvent.data, method = this['api_' + action];
+ if (typeof(method) === 'function') {
+ method.call(this, params);
+ }
+ });
+ }
+
+ api_showTermDefs({definitions, options}) {
+ const sequence = ++this.sequence;
+ const context = {
+ definitions,
+ grouped: options.groupTermResults,
+ addable: options.ankiMethod !== 'disabled',
+ playback: options.enableAudioPlayback
+ };
+
+ this.definitions = definitions;
+ this.showSpinner(false);
+ window.scrollTo(0, 0);
+
+ renderText(context, 'term-list.html').then(content => {
+ $('.content').html(content);
+ $('.action-add-note').click(this.onAddNote.bind(this));
+
+ $('.kanji-link').click(e => {
+ e.preventDefault();
+ findKanji($(e.target).text()).then(kdefs => this.api_showKanjiDefs({options, definitions: kdefs}));
+ });
+
+ $('.action-play-audio').click(e => {
+ e.preventDefault();
+ const index = $(e.currentTarget).data('index');
+ this.playAudio(this.definitions[index]);
+ });
-function registerKanjiLinks() {
- for (const link of Array.from(document.getElementsByClassName('kanji-link'))) {
- link.addEventListener('click', e => {
- e.preventDefault();
- invokeApi('displayKanji', e.target.innerHTML, window.parent);
+ this.updateAddNoteButtons(['term_kanji', 'term_kana'], sequence);
});
}
-}
-function registerAddNoteLinks() {
- for (const link of Array.from(document.getElementsByClassName('action-add-note'))) {
- link.addEventListener('click', e => {
- e.preventDefault();
- const ds = e.currentTarget.dataset;
- invokeApi('addNote', {index: ds.index, mode: ds.mode}, window.parent);
+ api_showKanjiDefs({definitions, options}) {
+ const sequence = ++this.sequence;
+ const context = {
+ definitions,
+ addable: options.ankiMethod !== 'disabled'
+ };
+
+ this.definitions = definitions;
+ this.showSpinner(false);
+ window.scrollTo(0, 0);
+
+ renderText(context, 'kanji-list.html').then(content => {
+ $('.content').html(content);
+ $('.action-add-note').click(this.onAddNote.bind(this));
+
+ this.updateAddNoteButtons(['kanji'], sequence);
});
}
-}
-function registerAudioLinks() {
- for (const link of Array.from(document.getElementsByClassName('action-play-audio'))) {
- link.addEventListener('click', e => {
- e.preventDefault();
- const ds = e.currentTarget.dataset;
- invokeApi('playAudio', ds.index, window.parent);
+ findAddNoteButton(index, mode) {
+ return $(`.action-add-note[data-index="${index}"][data-mode="${mode}"]`);
+ }
+
+ onAddNote(e) {
+ e.preventDefault();
+ this.showSpinner(true);
+
+ const link = $(e.currentTarget);
+ const index = link.data('index');
+ const mode = link.data('mode');
+
+ addDefinition(this.definitions[index], mode).then(success => {
+ if (success) {
+ const button = this.findAddNoteButton(index, mode);
+ button.addClass('disabled');
+ } else {
+ window.alert('Note could not be added');
+ }
+ }).catch(error => {
+ window.alert('Error: ' + error);
+ }).then(() => {
+ this.showSpinner(false);
});
}
-}
-function api_setActionState({index, state, sequence}) {
- for (const mode in state) {
- const matches = document.querySelectorAll(`.action-bar[data-sequence="${sequence}"] .action-add-note[data-index="${index}"][data-mode="${mode}"]`);
- if (matches.length === 0) {
- return;
- }
+ updateAddNoteButtons(modes, sequence) {
+ canAddDefinitions(this.definitions, modes).then(states => {
+ if (states === null) {
+ return;
+ }
- const classes = matches[0].classList;
- if (state[mode]) {
- classes.remove('disabled');
+ if (sequence !== this.sequence) {
+ return;
+ }
+
+ states.forEach((state, index) => {
+ for (const mode in state) {
+ const button = this.findAddNoteButton(index, mode);
+ if (state[mode]) {
+ button.removeClass('disabled');
+ } else {
+ button.addClass('disabled');
+ }
+
+ button.removeClass('pending');
+ }
+ });
+ });
+ }
+
+ showSpinner(show) {
+ const spinner = $('.spinner');
+ if (show) {
+ spinner.show();
} else {
- classes.add('disabled');
+ spinner.hide();
}
}
-}
-document.addEventListener('DOMContentLoaded', () => {
- registerKanjiLinks();
- registerAddNoteLinks();
- registerAudioLinks();
-});
+ playAudio(definition) {
+ let url = `https://assets.languagepod101.com/dictionary/japanese/audiomp3.php?kanji=${encodeURIComponent(definition.expression)}`;
+ if (definition.reading) {
+ url += `&kana=${encodeURIComponent(definition.reading)}`;
+ }
-window.addEventListener('message', e => {
- const {action, params} = e.data, method = window['api_' + action];
- if (typeof(method) === 'function') {
- method(params);
+ for (const key in this.audioCache) {
+ this.audioCache[key].pause();
+ }
+
+ const audio = this.audioCache[url] || new Audio(url);
+ audio.currentTime = 0;
+ audio.play();
}
-});
+}
+
+window.frame = new Frame();