diff options
| -rw-r--r-- | ext/mixed/css/display.css | 24 | ||||
| -rw-r--r-- | ext/mixed/display-templates.html | 4 | ||||
| -rw-r--r-- | ext/mixed/js/display-generator.js | 237 | 
3 files changed, 132 insertions, 133 deletions
| diff --git a/ext/mixed/css/display.css b/ext/mixed/css/display.css index 92ba52c6..d1a54064 100644 --- a/ext/mixed/css/display.css +++ b/ext/mixed/css/display.css @@ -297,13 +297,13 @@ button.action-button {      content: "\3001";  } -.term-expression-list[data-multi=true]>.term-expression:last-of-type:after { +.entry[data-expression-multi=true] .term-expression-list>.term-expression:last-of-type:after {      font-size: 2em;      content: "\3000";      visibility: hidden;  } -.term-expression-list[data-multi=true] .term-expression-details { +.entry[data-expression-multi=true] .term-expression-list .term-expression-details {      display: inline-block;      position: relative;      width: 0; @@ -312,21 +312,21 @@ button.action-button {      z-index: 1;  } -.term-expression-list[data-multi=true] .term-expression:hover .term-expression-details { +.entry[data-expression-multi=true] .term-expression:hover .term-expression-details {      visibility: visible;  } -.term-expression-list[data-multi=true] .term-expression-details>.action-play-audio { +.entry[data-expression-multi=true] .term-expression-list .term-expression-details>.action-play-audio {      position: absolute;      left: 0;      bottom: 0.5em;  } -.term-expression-list:not([data-multi=true]) .term-expression-details>.action-play-audio { +.entry:not([data-expression-multi=true]) .term-expression-list .term-expression-details>.action-play-audio {      display: none;  } -.term-expression-list[data-multi=true] .term-expression-details>.tags { +.entry[data-expression-multi=true] .term-expression-list .term-expression-details>.tags {      display: block;      position: absolute;      left: 0; @@ -334,7 +334,7 @@ button.action-button {      white-space: nowrap;  } -.term-expression-list[data-multi=true] .term-expression-details>.frequencies { +.entry[data-expression-multi=true] .term-expression-list .term-expression-details>.frequencies {      display: block;      position: absolute;      left: 0; @@ -364,19 +364,19 @@ button.action-button {      list-style-type: circle;  } -.term-definition-only-list[data-count="0"] { +.term-definition-disambiguation-list[data-count="0"] {      display: none;  } -.term-definition-only-list:before { +.term-definition-disambiguation-list:before {      content: "(";  } -.term-definition-only-list:after { +.term-definition-disambiguation-list:after {      content: " only)";  } -.term-definition-only+.term-definition-only:before { +.term-definition-disambiguation+.term-definition-disambiguation:before {      content: ", ";  } @@ -398,7 +398,7 @@ button.action-button {  }  :root[data-compact-glossaries=true] .term-definition-tag-list, -:root[data-compact-glossaries=true] .term-definition-only-list:not([data-count="0"]) { +:root[data-compact-glossaries=true] .term-definition-disambiguation-list:not([data-count="0"]) {      display: inline;  } diff --git a/ext/mixed/display-templates.html b/ext/mixed/display-templates.html index b8d52d15..3baa8293 100644 --- a/ext/mixed/display-templates.html +++ b/ext/mixed/display-templates.html @@ -30,10 +30,10 @@  </div></div></template>  <template id="term-definition-item-template"><li class="term-definition-item">      <div class="term-definition-tag-list tag-list"></div> -    <div class="term-definition-only-list"></div> +    <div class="term-definition-disambiguation-list"></div>      <ul class="term-glossary-list"></ul>  </li></template> -<template id="term-definition-only-template"><span class="term-definition-only"></span></template> +<template id="term-definition-disambiguation-template"><span class="term-definition-disambiguation"></span></template>  <template id="term-glossary-item-template"><li class="term-glossary-item"><span class="term-glossary-separator"> </span><span class="term-glossary"></span></li></template>  <template id="term-reason-template"><span class="term-reason"></span><span class="term-reason-separator"> </span></template> diff --git a/ext/mixed/js/display-generator.js b/ext/mixed/js/display-generator.js index b0cc2478..0f991362 100644 --- a/ext/mixed/js/display-generator.js +++ b/ext/mixed/js/display-generator.js @@ -43,13 +43,15 @@ class DisplayGenerator {          const debugInfoContainer = node.querySelector('.debug-info');          const bodyContainer = node.querySelector('.term-entry-body'); -        const pitches = DisplayGenerator._getPitchInfos(details); +        const {termTags, expressions, definitions} = details; + +        const pitches = this._getPitchInfos(details);          const pitchCount = pitches.reduce((i, v) => i + v[1].length, 0); -        const expressionMulti = Array.isArray(details.expressions); -        const definitionMulti = Array.isArray(details.definitions); -        const expressionCount = expressionMulti ? details.expressions.length : 1; -        const definitionCount = definitionMulti ? details.definitions.length : 1; +        const expressionMulti = Array.isArray(expressions); +        const definitionMulti = Array.isArray(definitions); +        const expressionCount = expressionMulti ? expressions.length : 1; +        const definitionCount = definitionMulti ? definitions.length : 1;          const uniqueExpressionCount = Array.isArray(details.expression) ? new Set(details.expression).size : 1;          node.dataset.expressionMulti = `${expressionMulti}`; @@ -65,15 +67,56 @@ class DisplayGenerator {              (pitches.length > 0 ? 1 : 0)          }`; -        const termTags = details.termTags; -        let expressions = details.expressions; -        expressions = Array.isArray(expressions) ? expressions.map((e) => [e, termTags]) : null; +        this._appendMultiple(expressionsContainer, this._createTermExpression.bind(this), expressionMulti ? expressions : [details], termTags); +        this._appendMultiple(reasonsContainer, this._createTermReason.bind(this), details.reasons); +        this._appendMultiple(frequenciesContainer, this._createFrequencyTag.bind(this), details.frequencies); +        this._appendMultiple(pitchesContainer, this._createPitches.bind(this), pitches); +        this._appendMultiple(definitionsContainer, this._createTermDefinitionItem.bind(this), definitionMulti ? definitions : [details]); + +        if (debugInfoContainer !== null) { +            debugInfoContainer.textContent = JSON.stringify(details, null, 4); +        } + +        return node; +    } + +    createKanjiEntry(details) { +        const node = this._templateHandler.instantiate('kanji-entry'); + +        const glyphContainer = node.querySelector('.kanji-glyph'); +        const frequenciesContainer = node.querySelector('.frequencies'); +        const tagContainer = node.querySelector('.tags'); +        const glossaryContainer = node.querySelector('.kanji-glossary-list'); +        const chineseReadingsContainer = node.querySelector('.kanji-readings-chinese'); +        const japaneseReadingsContainer = node.querySelector('.kanji-readings-japanese'); +        const statisticsContainer = node.querySelector('.kanji-statistics'); +        const classificationsContainer = node.querySelector('.kanji-classifications'); +        const codepointsContainer = node.querySelector('.kanji-codepoints'); +        const dictionaryIndicesContainer = node.querySelector('.kanji-dictionary-indices'); +        const debugInfoContainer = node.querySelector('.debug-info'); + +        if (glyphContainer !== null) { +            glyphContainer.textContent = details.character; +        } -        DisplayGenerator._appendMultiple(expressionsContainer, this.createTermExpression.bind(this), expressions, [[details, termTags]]); -        DisplayGenerator._appendMultiple(reasonsContainer, this.createTermReason.bind(this), details.reasons); -        DisplayGenerator._appendMultiple(frequenciesContainer, this.createFrequencyTag.bind(this), details.frequencies); -        DisplayGenerator._appendMultiple(pitchesContainer, this.createPitches.bind(this), pitches); -        DisplayGenerator._appendMultiple(definitionsContainer, this.createTermDefinitionItem.bind(this), details.definitions, [details]); +        this._appendMultiple(frequenciesContainer, this._createFrequencyTag.bind(this), details.frequencies); +        this._appendMultiple(tagContainer, this._createTag.bind(this), details.tags); +        this._appendMultiple(glossaryContainer, this._createKanjiGlossaryItem.bind(this), details.glossary); +        this._appendMultiple(chineseReadingsContainer, this._createKanjiReading.bind(this), details.onyomi); +        this._appendMultiple(japaneseReadingsContainer, this._createKanjiReading.bind(this), details.kunyomi); + +        if (statisticsContainer !== null) { +            statisticsContainer.appendChild(this._createKanjiInfoTable(details.stats.misc)); +        } +        if (classificationsContainer !== null) { +            classificationsContainer.appendChild(this._createKanjiInfoTable(details.stats.class)); +        } +        if (codepointsContainer !== null) { +            codepointsContainer.appendChild(this._createKanjiInfoTable(details.stats.code)); +        } +        if (dictionaryIndicesContainer !== null) { +            dictionaryIndicesContainer.appendChild(this._createKanjiInfoTable(details.stats.index)); +        }          if (debugInfoContainer !== null) {              debugInfoContainer.textContent = JSON.stringify(details, null, 4); @@ -82,7 +125,9 @@ class DisplayGenerator {          return node;      } -    createTermExpression([details, termTags]) { +    // Private + +    _createTermExpression(details, termTags) {          const node = this._templateHandler.instantiate('term-expression');          const expressionContainer = node.querySelector('.term-expression-text'); @@ -99,7 +144,7 @@ class DisplayGenerator {                  // This case should not occur                  furiganaSegments = [{text: details.expression, furigana: details.reading}];              } -            DisplayGenerator._appendFurigana(expressionContainer, furiganaSegments, this._appendKanjiLinks.bind(this)); +            this._appendFurigana(expressionContainer, furiganaSegments, this._appendKanjiLinks.bind(this));          }          if (!Array.isArray(termTags)) { @@ -109,14 +154,14 @@ class DisplayGenerator {          const searchQueries = [details.expression, details.reading]              .filter((x) => !!x)              .map((x) => ({query: x})); -        DisplayGenerator._appendMultiple(tagContainer, this.createTag.bind(this), termTags); -        DisplayGenerator._appendMultiple(tagContainer, this.createSearchTag.bind(this), searchQueries); -        DisplayGenerator._appendMultiple(frequencyContainer, this.createFrequencyTag.bind(this), details.frequencies); +        this._appendMultiple(tagContainer, this._createTag.bind(this), termTags); +        this._appendMultiple(tagContainer, this._createSearchTag.bind(this), searchQueries); +        this._appendMultiple(frequencyContainer, this._createFrequencyTag.bind(this), details.frequencies);          return node;      } -    createTermReason(reason) { +    _createTermReason(reason) {          const fragment = this._templateHandler.instantiateFragment('term-reason');          const node = fragment.querySelector('.term-reason');          node.textContent = reason; @@ -124,39 +169,39 @@ class DisplayGenerator {          return fragment;      } -    createTermDefinitionItem(details) { +    _createTermDefinitionItem(details) {          const node = this._templateHandler.instantiate('term-definition-item');          const tagListContainer = node.querySelector('.term-definition-tag-list'); -        const onlyListContainer = node.querySelector('.term-definition-only-list'); +        const onlyListContainer = node.querySelector('.term-definition-disambiguation-list');          const glossaryContainer = node.querySelector('.term-glossary-list');          node.dataset.dictionary = details.dictionary; -        DisplayGenerator._appendMultiple(tagListContainer, this.createTag.bind(this), details.definitionTags); -        DisplayGenerator._appendMultiple(onlyListContainer, this.createTermOnly.bind(this), details.only); -        DisplayGenerator._appendMultiple(glossaryContainer, this.createTermGlossaryItem.bind(this), details.glossary); +        this._appendMultiple(tagListContainer, this._createTag.bind(this), details.definitionTags); +        this._appendMultiple(onlyListContainer, this._createTermDisambiguation.bind(this), details.only); +        this._appendMultiple(glossaryContainer, this._createTermGlossaryItem.bind(this), details.glossary);          return node;      } -    createTermGlossaryItem(glossary) { +    _createTermGlossaryItem(glossary) {          const node = this._templateHandler.instantiate('term-glossary-item');          const container = node.querySelector('.term-glossary');          if (container !== null) { -            DisplayGenerator._appendMultilineText(container, glossary); +            this._appendMultilineText(container, glossary);          }          return node;      } -    createTermOnly(only) { -        const node = this._templateHandler.instantiate('term-definition-only'); -        node.dataset.only = only; -        node.textContent = only; +    _createTermDisambiguation(disambiguation) { +        const node = this._templateHandler.instantiate('term-definition-disambiguation'); +        node.dataset.term = disambiguation; +        node.textContent = disambiguation;          return node;      } -    createKanjiLink(character) { +    _createKanjiLink(character) {          const node = document.createElement('a');          node.href = '#';          node.className = 'kanji-link'; @@ -164,75 +209,30 @@ class DisplayGenerator {          return node;      } -    createKanjiEntry(details) { -        const node = this._templateHandler.instantiate('kanji-entry'); - -        const glyphContainer = node.querySelector('.kanji-glyph'); -        const frequenciesContainer = node.querySelector('.frequencies'); -        const tagContainer = node.querySelector('.tags'); -        const glossaryContainer = node.querySelector('.kanji-glossary-list'); -        const chineseReadingsContainer = node.querySelector('.kanji-readings-chinese'); -        const japaneseReadingsContainer = node.querySelector('.kanji-readings-japanese'); -        const statisticsContainer = node.querySelector('.kanji-statistics'); -        const classificationsContainer = node.querySelector('.kanji-classifications'); -        const codepointsContainer = node.querySelector('.kanji-codepoints'); -        const dictionaryIndicesContainer = node.querySelector('.kanji-dictionary-indices'); -        const debugInfoContainer = node.querySelector('.debug-info'); - -        if (glyphContainer !== null) { -            glyphContainer.textContent = details.character; -        } - -        DisplayGenerator._appendMultiple(frequenciesContainer, this.createFrequencyTag.bind(this), details.frequencies); -        DisplayGenerator._appendMultiple(tagContainer, this.createTag.bind(this), details.tags); -        DisplayGenerator._appendMultiple(glossaryContainer, this.createKanjiGlossaryItem.bind(this), details.glossary); -        DisplayGenerator._appendMultiple(chineseReadingsContainer, this.createKanjiReading.bind(this), details.onyomi); -        DisplayGenerator._appendMultiple(japaneseReadingsContainer, this.createKanjiReading.bind(this), details.kunyomi); - -        if (statisticsContainer !== null) { -            statisticsContainer.appendChild(this.createKanjiInfoTable(details.stats.misc)); -        } -        if (classificationsContainer !== null) { -            classificationsContainer.appendChild(this.createKanjiInfoTable(details.stats.class)); -        } -        if (codepointsContainer !== null) { -            codepointsContainer.appendChild(this.createKanjiInfoTable(details.stats.code)); -        } -        if (dictionaryIndicesContainer !== null) { -            dictionaryIndicesContainer.appendChild(this.createKanjiInfoTable(details.stats.index)); -        } - -        if (debugInfoContainer !== null) { -            debugInfoContainer.textContent = JSON.stringify(details, null, 4); -        } - -        return node; -    } - -    createKanjiGlossaryItem(glossary) { +    _createKanjiGlossaryItem(glossary) {          const node = this._templateHandler.instantiate('kanji-glossary-item');          const container = node.querySelector('.kanji-glossary');          if (container !== null) { -            DisplayGenerator._appendMultilineText(container, glossary); +            this._appendMultilineText(container, glossary);          }          return node;      } -    createKanjiReading(reading) { +    _createKanjiReading(reading) {          const node = this._templateHandler.instantiate('kanji-reading');          node.textContent = reading;          return node;      } -    createKanjiInfoTable(details) { +    _createKanjiInfoTable(details) {          const node = this._templateHandler.instantiate('kanji-info-table');          const container = node.querySelector('.kanji-info-table-body');          if (container !== null) { -            const count = DisplayGenerator._appendMultiple(container, this.createKanjiInfoTableItem.bind(this), details); +            const count = this._appendMultiple(container, this._createKanjiInfoTableItem.bind(this), details);              if (count === 0) { -                const n = this.createKanjiInfoTableItemEmpty(); +                const n = this._createKanjiInfoTableItemEmpty();                  container.appendChild(n);              }          } @@ -240,7 +240,7 @@ class DisplayGenerator {          return node;      } -    createKanjiInfoTableItem(details) { +    _createKanjiInfoTableItem(details) {          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'); @@ -253,11 +253,11 @@ class DisplayGenerator {          return node;      } -    createKanjiInfoTableItemEmpty() { +    _createKanjiInfoTableItemEmpty() {          return this._templateHandler.instantiate('kanji-info-table-empty');      } -    createTag(details) { +    _createTag(details) {          const node = this._templateHandler.instantiate('tag');          const inner = node.querySelector('.tag-inner'); @@ -269,7 +269,7 @@ class DisplayGenerator {          return node;      } -    createSearchTag(details) { +    _createSearchTag(details) {          const node = this._templateHandler.instantiate('tag-search');          node.textContent = details.query; @@ -279,7 +279,7 @@ class DisplayGenerator {          return node;      } -    createPitches(details) { +    _createPitches(details) {          if (!this._termPitchAccentStaticTemplateIsSetup) {              this._termPitchAccentStaticTemplateIsSetup = true;              const t = this._templateHandler.instantiate('term-pitch-accent-static'); @@ -293,16 +293,16 @@ class DisplayGenerator {          node.dataset.pitchesMulti = 'true';          node.dataset.pitchesCount = `${dictionaryPitches.length}`; -        const tag = this.createTag({notes: '', name: dictionary, category: 'pitch-accent-dictionary'}); +        const tag = this._createTag({notes: '', name: dictionary, category: 'pitch-accent-dictionary'});          node.querySelector('.term-pitch-accent-group-tag-list').appendChild(tag);          const n = node.querySelector('.term-pitch-accent-list'); -        DisplayGenerator._appendMultiple(n, this.createPitch.bind(this), dictionaryPitches); +        this._appendMultiple(n, this._createPitch.bind(this), dictionaryPitches);          return node;      } -    createPitch(details) { +    _createPitch(details) {          const {reading, position, tags, exclusiveExpressions, exclusiveReadings} = details;          const morae = jp.getKanaMorae(reading); @@ -315,10 +315,10 @@ class DisplayGenerator {          n.textContent = `${position}`;          n = node.querySelector('.term-pitch-accent-tag-list'); -        DisplayGenerator._appendMultiple(n, this.createTag.bind(this), tags); +        this._appendMultiple(n, this._createTag.bind(this), tags);          n = node.querySelector('.term-pitch-accent-disambiguation-list'); -        this.createPitchAccentDisambiguations(n, exclusiveExpressions, exclusiveReadings); +        this._createPitchAccentDisambiguations(n, exclusiveExpressions, exclusiveReadings);          n = node.querySelector('.term-pitch-accent-characters');          for (let i = 0, ii = morae.length; i < ii; ++i) { @@ -338,13 +338,13 @@ class DisplayGenerator {          }          if (morae.length > 0) { -            this.populatePitchGraph(node.querySelector('.term-pitch-accent-graph'), position, morae); +            this._populatePitchGraph(node.querySelector('.term-pitch-accent-graph'), position, morae);          }          return node;      } -    createPitchAccentDisambiguations(container, exclusiveExpressions, exclusiveReadings) { +    _createPitchAccentDisambiguations(container, exclusiveExpressions, exclusiveReadings) {          const templateName = 'term-pitch-accent-disambiguation';          for (const exclusiveExpression of exclusiveExpressions) {              const node = this._templateHandler.instantiate(templateName); @@ -360,13 +360,12 @@ class DisplayGenerator {              container.appendChild(node);          } -        container.dataset.multi = 'true';          container.dataset.count = `${exclusiveExpressions.length + exclusiveReadings.length}`;          container.dataset.expressionCount = `${exclusiveExpressions.length}`;          container.dataset.readingCount = `${exclusiveReadings.length}`;      } -    populatePitchGraph(svg, position, morae) { +    _populatePitchGraph(svg, position, morae) {          const svgns = svg.getAttribute('xmlns');          const ii = morae.length;          svg.setAttribute('viewBox', `0 0 ${50 * (ii + 1)} 100`); @@ -406,7 +405,7 @@ class DisplayGenerator {          path.setAttribute('d', `M${pathPoints.join(' L')}`);      } -    createFrequencyTag(details) { +    _createFrequencyTag(details) {          const node = this._templateHandler.instantiate('tag-frequency');          let n = node.querySelector('.term-frequency-dictionary-name'); @@ -434,7 +433,7 @@ class DisplayGenerator {                      part = '';                  } -                const link = this.createKanjiLink(c); +                const link = this._createKanjiLink(c);                  container.appendChild(link);              } else {                  part += c; @@ -445,31 +444,31 @@ class DisplayGenerator {          }      } -    static _appendMultiple(container, createItem, detailsIterable, fallback=[]) { -        if (container === null) { return 0; } - -        const multi = ( -            detailsIterable !== null && -            typeof detailsIterable === 'object' && -            typeof detailsIterable[Symbol.iterator] !== 'undefined' +    _isIterable(value) { +        return ( +            value !== null && +            typeof value === 'object' && +            typeof value[Symbol.iterator] !== 'undefined'          ); -        if (!multi) { detailsIterable = fallback; } +    } +    _appendMultiple(container, createItem, detailsIterable, ...args) {          let count = 0; -        for (const details of detailsIterable) { -            const item = createItem(details); -            if (item === null) { continue; } -            container.appendChild(item); -            ++count; +        if (container !== null && this._isIterable(detailsIterable)) { +            for (const details of detailsIterable) { +                const item = createItem(details, ...args); +                if (item === null) { continue; } +                container.appendChild(item); +                ++count; +            }          } -        container.dataset.multi = `${multi}`;          container.dataset.count = `${count}`;          return count;      } -    static _appendFurigana(container, segments, addText) { +    _appendFurigana(container, segments, addText) {          for (const {text, furigana} of segments) {              if (furigana) {                  const ruby = document.createElement('ruby'); @@ -484,7 +483,7 @@ class DisplayGenerator {          }      } -    static _appendMultilineText(container, text) { +    _appendMultilineText(container, text) {          const parts = text.split('\n');          container.appendChild(document.createTextNode(parts[0]));          for (let i = 1, ii = parts.length; i < ii; ++i) { @@ -493,7 +492,7 @@ class DisplayGenerator {          }      } -    static _getPitchInfos(definition) { +    _getPitchInfos(definition) {          const results = new Map();          const allExpressions = new Set(); @@ -511,7 +510,7 @@ class DisplayGenerator {                  }                  for (const {position, tags} of pitches) { -                    let pitchInfo = DisplayGenerator._findExistingPitchInfo(reading, position, tags, dictionaryResults); +                    let pitchInfo = this._findExistingPitchInfo(reading, position, tags, dictionaryResults);                      if (pitchInfo === null) {                          pitchInfo = {expressions: new Set(), reading, position, tags};                          dictionaryResults.push(pitchInfo); @@ -540,12 +539,12 @@ class DisplayGenerator {          return [...results.entries()];      } -    static _findExistingPitchInfo(reading, position, tags, pitchInfoList) { +    _findExistingPitchInfo(reading, position, tags, pitchInfoList) {          for (const pitchInfo of pitchInfoList) {              if (                  pitchInfo.reading === reading &&                  pitchInfo.position === position && -                DisplayGenerator._areTagListsEqual(pitchInfo.tags, tags) +                this._areTagListsEqual(pitchInfo.tags, tags)              ) {                  return pitchInfo;              } @@ -553,7 +552,7 @@ class DisplayGenerator {          return null;      } -    static _areTagListsEqual(tagList1, tagList2) { +    _areTagListsEqual(tagList1, tagList2) {          const ii = tagList1.length;          if (tagList2.length !== ii) { return false; } |