diff options
Diffstat (limited to 'ext/mixed/js')
| -rw-r--r-- | ext/mixed/js/display-generator.js | 80 | ||||
| -rw-r--r-- | ext/mixed/js/display.js | 249 | ||||
| -rw-r--r-- | ext/mixed/js/scroll.js | 2 | 
3 files changed, 137 insertions, 194 deletions
| diff --git a/ext/mixed/js/display-generator.js b/ext/mixed/js/display-generator.js index 46f3d17e..d7e77cc0 100644 --- a/ext/mixed/js/display-generator.js +++ b/ext/mixed/js/display-generator.js @@ -16,36 +16,20 @@   * along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -/*global apiGetDisplayTemplatesHtml*/ +/*global apiGetDisplayTemplatesHtml, TemplateHandler*/  class DisplayGenerator {      constructor() { -        this._termEntryTemplate = null; -        this._termExpressionTemplate = null; -        this._termDefinitionItemTemplate = null; -        this._termDefinitionOnlyTemplate = null; -        this._termGlossaryItemTemplate = null; -        this._termReasonTemplate = null; - -        this._kanjiEntryTemplate = null; -        this._kanjiInfoTableTemplate = null; -        this._kanjiInfoTableItemTemplate = null; -        this._kanjiInfoTableEmptyTemplate = null; -        this._kanjiGlossaryItemTemplate = null; -        this._kanjiReadingTemplate = null; - -        this._tagTemplate = null; -        this._tagFrequencyTemplate = null; +        this._templateHandler = null;      }      async prepare() {          const html = await apiGetDisplayTemplatesHtml(); -        const doc = new DOMParser().parseFromString(html, 'text/html'); -        this._setTemplates(doc); +        this._templateHandler = new TemplateHandler(html);      }      createTermEntry(details) { -        const node = DisplayGenerator._instantiateTemplate(this._termEntryTemplate); +        const node = this._templateHandler.instantiate('term-entry');          const expressionsContainer = node.querySelector('.term-expression-list');          const reasonsContainer = node.querySelector('.term-reasons'); @@ -78,7 +62,7 @@ class DisplayGenerator {      }      createTermExpression([details, termTags]) { -        const node = DisplayGenerator._instantiateTemplate(this._termExpressionTemplate); +        const node = this._templateHandler.instantiate('term-expression');          const expressionContainer = node.querySelector('.term-expression-text');          const tagContainer = node.querySelector('.tags'); @@ -112,7 +96,7 @@ class DisplayGenerator {      }      createTermReason(reason) { -        const fragment = DisplayGenerator._instantiateTemplateFragment(this._termReasonTemplate); +        const fragment = this._templateHandler.instantiateFragment('term-reason');          const node = fragment.querySelector('.term-reason');          node.textContent = reason;          node.dataset.reason = reason; @@ -120,7 +104,7 @@ class DisplayGenerator {      }      createTermDefinitionItem(details) { -        const node = DisplayGenerator._instantiateTemplate(this._termDefinitionItemTemplate); +        const node = this._templateHandler.instantiate('term-definition-item');          const tagListContainer = node.querySelector('.term-definition-tag-list');          const onlyListContainer = node.querySelector('.term-definition-only-list'); @@ -136,7 +120,7 @@ class DisplayGenerator {      }      createTermGlossaryItem(glossary) { -        const node = DisplayGenerator._instantiateTemplate(this._termGlossaryItemTemplate); +        const node = this._templateHandler.instantiate('term-glossary-item');          const container = node.querySelector('.term-glossary');          if (container !== null) {              DisplayGenerator._appendMultilineText(container, glossary); @@ -145,7 +129,7 @@ class DisplayGenerator {      }      createTermOnly(only) { -        const node = DisplayGenerator._instantiateTemplate(this._termDefinitionOnlyTemplate); +        const node = this._templateHandler.instantiate('term-definition-only');          node.dataset.only = only;          node.textContent = only;          return node; @@ -160,7 +144,7 @@ class DisplayGenerator {      }      createKanjiEntry(details) { -        const node = DisplayGenerator._instantiateTemplate(this._kanjiEntryTemplate); +        const node = this._templateHandler.instantiate('kanji-entry');          const glyphContainer = node.querySelector('.kanji-glyph');          const frequenciesContainer = node.querySelector('.frequencies'); @@ -205,7 +189,7 @@ class DisplayGenerator {      }      createKanjiGlossaryItem(glossary) { -        const node = DisplayGenerator._instantiateTemplate(this._kanjiGlossaryItemTemplate); +        const node = this._templateHandler.instantiate('kanji-glossary-item');          const container = node.querySelector('.kanji-glossary');          if (container !== null) {              DisplayGenerator._appendMultilineText(container, glossary); @@ -214,13 +198,13 @@ class DisplayGenerator {      }      createKanjiReading(reading) { -        const node = DisplayGenerator._instantiateTemplate(this._kanjiReadingTemplate); +        const node = this._templateHandler.instantiate('kanji-reading');          node.textContent = reading;          return node;      }      createKanjiInfoTable(details) { -        const node = DisplayGenerator._instantiateTemplate(this._kanjiInfoTableTemplate); +        const node = this._templateHandler.instantiate('kanji-info-table');          const container = node.querySelector('.kanji-info-table-body'); @@ -236,7 +220,7 @@ class DisplayGenerator {      }      createKanjiInfoTableItem(details) { -        const node = DisplayGenerator._instantiateTemplate(this._kanjiInfoTableItemTemplate); +        const node = this._templateHandler.instantiate('kanji-info-table-item');          const nameNode = node.querySelector('.kanji-info-table-item-header');          const valueNode = node.querySelector('.kanji-info-table-item-value');          if (nameNode !== null) { @@ -249,11 +233,11 @@ class DisplayGenerator {      }      createKanjiInfoTableItemEmpty() { -        return DisplayGenerator._instantiateTemplate(this._kanjiInfoTableEmptyTemplate); +        return this._templateHandler.instantiate('kanji-info-table-empty');      }      createTag(details) { -        const node = DisplayGenerator._instantiateTemplate(this._tagTemplate); +        const node = this._templateHandler.instantiate('tag');          const inner = node.querySelector('.tag-inner'); @@ -265,7 +249,7 @@ class DisplayGenerator {      }      createSearchTag(details) { -        const node = DisplayGenerator._instantiateTemplate(this._tagSearchTemplate); +        const node = this._templateHandler.instantiate('tag-search');          node.textContent = details.query; @@ -275,7 +259,7 @@ class DisplayGenerator {      }      createFrequencyTag(details) { -        const node = DisplayGenerator._instantiateTemplate(this._tagFrequencyTemplate); +        const node = this._templateHandler.instantiate('tag-frequency');          let n = node.querySelector('.term-frequency-dictionary-name');          if (n !== null) { @@ -293,26 +277,6 @@ class DisplayGenerator {          return node;      } -    _setTemplates(doc) { -        this._termEntryTemplate = doc.querySelector('#term-entry-template'); -        this._termExpressionTemplate = doc.querySelector('#term-expression-template'); -        this._termDefinitionItemTemplate = doc.querySelector('#term-definition-item-template'); -        this._termDefinitionOnlyTemplate = doc.querySelector('#term-definition-only-template'); -        this._termGlossaryItemTemplate = doc.querySelector('#term-glossary-item-template'); -        this._termReasonTemplate = doc.querySelector('#term-reason-template'); - -        this._kanjiEntryTemplate = doc.querySelector('#kanji-entry-template'); -        this._kanjiInfoTableTemplate = doc.querySelector('#kanji-info-table-template'); -        this._kanjiInfoTableItemTemplate = doc.querySelector('#kanji-info-table-item-template'); -        this._kanjiInfoTableEmptyTemplate = doc.querySelector('#kanji-info-table-empty-template'); -        this._kanjiGlossaryItemTemplate = doc.querySelector('#kanji-glossary-item-template'); -        this._kanjiReadingTemplate = doc.querySelector('#kanji-reading-template'); - -        this._tagTemplate = doc.querySelector('#tag-template'); -        this._tagSearchTemplate = doc.querySelector('#tag-search-template'); -        this._tagFrequencyTemplate = doc.querySelector('#tag-frequency-template'); -    } -      _appendKanjiLinks(container, text) {          let part = '';          for (const c of text) { @@ -382,12 +346,4 @@ class DisplayGenerator {              container.appendChild(document.createTextNode(parts[i]));          }      } - -    static _instantiateTemplate(template) { -        return document.importNode(template.content.firstChild, true); -    } - -    static _instantiateTemplateFragment(template) { -        return document.importNode(template.content, true); -    }  } diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 8113260c..631f9e34 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -45,6 +45,110 @@ class Display {          this.displayGenerator = new DisplayGenerator();          this.windowScroll = new WindowScroll(); +        this._onKeyDownHandlers = new Map([ +            ['Escape', () => { +                this.onSearchClear(); +                return true; +            }], +            ['PageUp', (e) => { +                if (e.altKey) { +                    this.entryScrollIntoView(this.index - 3, null, true); +                    return true; +                } +                return false; +            }], +            ['PageDown', (e) => { +                if (e.altKey) { +                    this.entryScrollIntoView(this.index + 3, null, true); +                    return true; +                } +                return false; +            }], +            ['End', (e) => { +                if (e.altKey) { +                    this.entryScrollIntoView(this.definitions.length - 1, null, true); +                    return true; +                } +                return false; +            }], +            ['Home', (e) => { +                if (e.altKey) { +                    this.entryScrollIntoView(0, null, true); +                    return true; +                } +                return false; +            }], +            ['ArrowUp', (e) => { +                if (e.altKey) { +                    this.entryScrollIntoView(this.index - 1, null, true); +                    return true; +                } +                return false; +            }], +            ['ArrowDown', (e) => { +                if (e.altKey) { +                    this.entryScrollIntoView(this.index + 1, null, true); +                    return true; +                } +                return false; +            }], +            ['B', (e) => { +                if (e.altKey) { +                    this.sourceTermView(); +                    return true; +                } +                return false; +            }], +            ['F', (e) => { +                if (e.altKey) { +                    this.nextTermView(); +                    return true; +                } +                return false; +            }], +            ['E', (e) => { +                if (e.altKey) { +                    this.noteTryAdd('term-kanji'); +                    return true; +                } +                return false; +            }], +            ['K', (e) => { +                if (e.altKey) { +                    this.noteTryAdd('kanji'); +                    return true; +                } +                return false; +            }], +            ['R', (e) => { +                if (e.altKey) { +                    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 entry = this.getEntry(index); +                    if (entry !== null && entry.dataset.type === 'term') { +                        this.audioPlay(this.definitions[index], this.firstExpressionIndex, index); +                    } +                    return true; +                } +                return false; +            }], +            ['V', (e) => { +                if (e.altKey) { +                    this.noteTryView(); +                    return true; +                } +                return false; +            }] +        ]); +          this.setInteractive(true);      } @@ -215,9 +319,9 @@ class Display {      onKeyDown(e) {          const key = Display.getKeyFromEvent(e); -        const handler = Display._onKeyDownHandlers.get(key); +        const handler = this._onKeyDownHandlers.get(key);          if (typeof handler === 'function') { -            if (handler(this, e)) { +            if (handler(e)) {                  e.preventDefault();                  return true;              } @@ -303,7 +407,7 @@ class Display {          if (interactive) {              const actionPrevious = document.querySelector('.action-previous');              const actionNext = document.querySelector('.action-next'); -            const navigationHeader = document.querySelector('.navigation-header'); +            // 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}); @@ -313,9 +417,10 @@ class Display {              if (actionNext !== null) {                  this.persistentEventListeners.addEventListener(actionNext, 'click', this.onNextTermView.bind(this));              } -            if (navigationHeader !== null) { -                this.persistentEventListeners.addEventListener(navigationHeader, 'wheel', this.onHistoryWheel.bind(this), {passive: false}); -            } +            // temporarily disabled +            // if (navigationHeader !== null) { +            //     this.persistentEventListeners.addEventListener(navigationHeader, 'wheel', this.onHistoryWheel.bind(this), {passive: false}); +            // }          } else {              this.persistentEventListeners.removeAllEventListeners();          } @@ -519,15 +624,13 @@ class Display {      updateAdderButtons(states) {          for (let i = 0; i < states.length; ++i) { -            const state = states[i];              let noteId = null; -            for (const mode in state) { +            for (const [mode, info] of Object.entries(states[i])) {                  const button = this.adderButtonFind(i, mode);                  if (button === null) {                      continue;                  } -                const info = state[mode];                  if (!info.canAdd && noteId === null && info.noteId) {                      noteId = info.noteId;                  } @@ -634,7 +737,7 @@ class Display {              this.setSpinnerVisible(true);              const context = {}; -            if (this.noteUsesScreenshot()) { +            if (this.noteUsesScreenshot(mode)) {                  const screenshot = await this.getScreenshot();                  if (screenshot) {                      context.screenshot = screenshot; @@ -704,10 +807,11 @@ class Display {          }      } -    noteUsesScreenshot() { -        const fields = this.options.anki.terms.fields; -        for (const name in fields) { -            if (fields[name].includes('{screenshot}')) { +    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}')) {                  return true;              }          } @@ -814,120 +918,3 @@ class Display {          return (typeof key === 'string' ? (key.length === 1 ? key.toUpperCase() : key) : '');      }  } - -Display._onKeyDownHandlers = new Map([ -    ['Escape', (self) => { -        self.onSearchClear(); -        return true; -    }], - -    ['PageUp', (self, e) => { -        if (e.altKey) { -            self.entryScrollIntoView(self.index - 3, null, true); -            return true; -        } -        return false; -    }], - -    ['PageDown', (self, e) => { -        if (e.altKey) { -            self.entryScrollIntoView(self.index + 3, null, true); -            return true; -        } -        return false; -    }], - -    ['End', (self, e) => { -        if (e.altKey) { -            self.entryScrollIntoView(self.definitions.length - 1, null, true); -            return true; -        } -        return false; -    }], - -    ['Home', (self, e) => { -        if (e.altKey) { -            self.entryScrollIntoView(0, null, true); -            return true; -        } -        return false; -    }], - -    ['ArrowUp', (self, e) => { -        if (e.altKey) { -            self.entryScrollIntoView(self.index - 1, null, true); -            return true; -        } -        return false; -    }], - -    ['ArrowDown', (self, e) => { -        if (e.altKey) { -            self.entryScrollIntoView(self.index + 1, null, true); -            return true; -        } -        return false; -    }], - -    ['B', (self, e) => { -        if (e.altKey) { -            self.sourceTermView(); -            return true; -        } -        return false; -    }], - -    ['F', (self, e) => { -        if (e.altKey) { -            self.nextTermView(); -            return true; -        } -        return false; -    }], - -    ['E', (self, e) => { -        if (e.altKey) { -            self.noteTryAdd('term-kanji'); -            return true; -        } -        return false; -    }], - -    ['K', (self, e) => { -        if (e.altKey) { -            self.noteTryAdd('kanji'); -            return true; -        } -        return false; -    }], - -    ['R', (self, e) => { -        if (e.altKey) { -            self.noteTryAdd('term-kana'); -            return true; -        } -        return false; -    }], - -    ['P', (self, e) => { -        if (e.altKey) { -            const index = self.index; -            if (index < 0 || index >= self.definitions.length) { return; } - -            const entry = self.getEntry(index); -            if (entry !== null && entry.dataset.type === 'term') { -                self.audioPlay(self.definitions[index], self.firstExpressionIndex, index); -            } -            return true; -        } -        return false; -    }], - -    ['V', (self, e) => { -        if (e.altKey) { -            self.noteTryView(); -            return true; -        } -        return false; -    }] -]); diff --git a/ext/mixed/js/scroll.js b/ext/mixed/js/scroll.js index 5829d294..72da8b65 100644 --- a/ext/mixed/js/scroll.js +++ b/ext/mixed/js/scroll.js @@ -26,7 +26,7 @@ class WindowScroll {          this.animationEndTime = 0;          this.animationEndX = 0;          this.animationEndY = 0; -        this.requestAnimationFrameCallback = (t) => this.onAnimationFrame(t); +        this.requestAnimationFrameCallback = this.onAnimationFrame.bind(this);      }      toY(y) { |