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();  |