diff options
Diffstat (limited to 'ext/fg/js/frame.js')
-rw-r--r-- | ext/fg/js/frame.js | 168 |
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(); |