Template handler update (#896)
* Rename TemplateHandler to HtmlTemplateCollection * Rename _templateHandler to _templates * Allow creation from both string and element * Simplify setup of templates, don't throw errors on invalid ID
This commit is contained in:
parent
2d765d2c4e
commit
cb1902eadd
@ -16,24 +16,24 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* global
|
/* global
|
||||||
* TemplateHandler
|
* HtmlTemplateCollection
|
||||||
* api
|
* api
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class QueryParserGenerator {
|
class QueryParserGenerator {
|
||||||
constructor() {
|
constructor() {
|
||||||
this._templateHandler = null;
|
this._templates = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async prepare() {
|
async prepare() {
|
||||||
const html = await api.getQueryParserTemplatesHtml();
|
const html = await api.getQueryParserTemplatesHtml();
|
||||||
this._templateHandler = new TemplateHandler(html);
|
this._templates = new HtmlTemplateCollection(html);
|
||||||
}
|
}
|
||||||
|
|
||||||
createParseResult(terms, preview=false) {
|
createParseResult(terms, preview=false) {
|
||||||
const fragment = document.createDocumentFragment();
|
const fragment = document.createDocumentFragment();
|
||||||
for (const term of terms) {
|
for (const term of terms) {
|
||||||
const termContainer = this._templateHandler.instantiate(preview ? 'term-preview' : 'term');
|
const termContainer = this._templates.instantiate(preview ? 'term-preview' : 'term');
|
||||||
for (const segment of term) {
|
for (const segment of term) {
|
||||||
if (!segment.text.trim()) { continue; }
|
if (!segment.text.trim()) { continue; }
|
||||||
if (!segment.reading.trim()) {
|
if (!segment.reading.trim()) {
|
||||||
@ -48,7 +48,7 @@ class QueryParserGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createSegment(segment) {
|
createSegment(segment) {
|
||||||
const segmentContainer = this._templateHandler.instantiate('segment');
|
const segmentContainer = this._templates.instantiate('segment');
|
||||||
const segmentTextContainer = segmentContainer.querySelector('.query-parser-segment-text');
|
const segmentTextContainer = segmentContainer.querySelector('.query-parser-segment-text');
|
||||||
const segmentReadingContainer = segmentContainer.querySelector('.query-parser-segment-reading');
|
const segmentReadingContainer = segmentContainer.querySelector('.query-parser-segment-reading');
|
||||||
segmentTextContainer.appendChild(this.createSegmentText(segment.text));
|
segmentTextContainer.appendChild(this.createSegmentText(segment.text));
|
||||||
@ -59,7 +59,7 @@ class QueryParserGenerator {
|
|||||||
createSegmentText(text) {
|
createSegmentText(text) {
|
||||||
const fragment = document.createDocumentFragment();
|
const fragment = document.createDocumentFragment();
|
||||||
for (const chr of text) {
|
for (const chr of text) {
|
||||||
const charContainer = this._templateHandler.instantiate('char');
|
const charContainer = this._templates.instantiate('char');
|
||||||
charContainer.textContent = chr;
|
charContainer.textContent = chr;
|
||||||
fragment.appendChild(charContainer);
|
fragment.appendChild(charContainer);
|
||||||
}
|
}
|
||||||
@ -67,9 +67,9 @@ class QueryParserGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createParserSelect(parseResults, selectedParser) {
|
createParserSelect(parseResults, selectedParser) {
|
||||||
const selectContainer = this._templateHandler.instantiate('select');
|
const selectContainer = this._templates.instantiate('select');
|
||||||
for (const parseResult of parseResults) {
|
for (const parseResult of parseResults) {
|
||||||
const optionContainer = this._templateHandler.instantiate('select-option');
|
const optionContainer = this._templates.instantiate('select-option');
|
||||||
optionContainer.value = parseResult.id;
|
optionContainer.value = parseResult.id;
|
||||||
switch (parseResult.source) {
|
switch (parseResult.source) {
|
||||||
case 'scanning-parser':
|
case 'scanning-parser':
|
||||||
|
@ -89,7 +89,7 @@
|
|||||||
<script src="/mixed/js/media-loader.js"></script>
|
<script src="/mixed/js/media-loader.js"></script>
|
||||||
<script src="/mixed/js/scroll.js"></script>
|
<script src="/mixed/js/scroll.js"></script>
|
||||||
<script src="/mixed/js/text-scanner.js"></script>
|
<script src="/mixed/js/text-scanner.js"></script>
|
||||||
<script src="/mixed/js/template-handler.js"></script>
|
<script src="/mixed/js/html-template-collection.js"></script>
|
||||||
<script src="/mixed/js/text-to-speech-audio.js"></script>
|
<script src="/mixed/js/text-to-speech-audio.js"></script>
|
||||||
|
|
||||||
<script src="/bg/js/anki-note-builder.js"></script>
|
<script src="/bg/js/anki-note-builder.js"></script>
|
||||||
|
@ -65,7 +65,7 @@
|
|||||||
<script src="/mixed/js/media-loader.js"></script>
|
<script src="/mixed/js/media-loader.js"></script>
|
||||||
<script src="/mixed/js/scroll.js"></script>
|
<script src="/mixed/js/scroll.js"></script>
|
||||||
<script src="/mixed/js/text-scanner.js"></script>
|
<script src="/mixed/js/text-scanner.js"></script>
|
||||||
<script src="/mixed/js/template-handler.js"></script>
|
<script src="/mixed/js/html-template-collection.js"></script>
|
||||||
<script src="/mixed/js/text-to-speech-audio.js"></script>
|
<script src="/mixed/js/text-to-speech-audio.js"></script>
|
||||||
|
|
||||||
<script src="/bg/js/anki-note-builder.js"></script>
|
<script src="/bg/js/anki-note-builder.js"></script>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
/* global
|
/* global
|
||||||
* DictionaryDataUtil
|
* DictionaryDataUtil
|
||||||
* TemplateHandler
|
* HtmlTemplateCollection
|
||||||
* api
|
* api
|
||||||
* jp
|
* jp
|
||||||
*/
|
*/
|
||||||
@ -25,17 +25,17 @@
|
|||||||
class DisplayGenerator {
|
class DisplayGenerator {
|
||||||
constructor({mediaLoader}) {
|
constructor({mediaLoader}) {
|
||||||
this._mediaLoader = mediaLoader;
|
this._mediaLoader = mediaLoader;
|
||||||
this._templateHandler = null;
|
this._templates = null;
|
||||||
this._termPitchAccentStaticTemplateIsSetup = false;
|
this._termPitchAccentStaticTemplateIsSetup = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async prepare() {
|
async prepare() {
|
||||||
const html = await api.getDisplayTemplatesHtml();
|
const html = await api.getDisplayTemplatesHtml();
|
||||||
this._templateHandler = new TemplateHandler(html);
|
this._templates = new HtmlTemplateCollection(html);
|
||||||
}
|
}
|
||||||
|
|
||||||
createTermEntry(details) {
|
createTermEntry(details) {
|
||||||
const node = this._templateHandler.instantiate('term-entry');
|
const node = this._templates.instantiate('term-entry');
|
||||||
|
|
||||||
const expressionsContainer = node.querySelector('.term-expression-list');
|
const expressionsContainer = node.querySelector('.term-expression-list');
|
||||||
const reasonsContainer = node.querySelector('.term-reasons');
|
const reasonsContainer = node.querySelector('.term-reasons');
|
||||||
@ -83,7 +83,7 @@ class DisplayGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createKanjiEntry(details) {
|
createKanjiEntry(details) {
|
||||||
const node = this._templateHandler.instantiate('kanji-entry');
|
const node = this._templates.instantiate('kanji-entry');
|
||||||
|
|
||||||
const glyphContainer = node.querySelector('.kanji-glyph');
|
const glyphContainer = node.querySelector('.kanji-glyph');
|
||||||
const frequenciesContainer = node.querySelector('.frequencies');
|
const frequenciesContainer = node.querySelector('.frequencies');
|
||||||
@ -130,7 +130,7 @@ class DisplayGenerator {
|
|||||||
// Private
|
// Private
|
||||||
|
|
||||||
_createTermExpression(details, termTags) {
|
_createTermExpression(details, termTags) {
|
||||||
const node = this._templateHandler.instantiate('term-expression');
|
const node = this._templates.instantiate('term-expression');
|
||||||
|
|
||||||
const expressionContainer = node.querySelector('.term-expression-text');
|
const expressionContainer = node.querySelector('.term-expression-text');
|
||||||
const tagContainer = node.querySelector('.tags');
|
const tagContainer = node.querySelector('.tags');
|
||||||
@ -164,7 +164,7 @@ class DisplayGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_createTermReason(reason) {
|
_createTermReason(reason) {
|
||||||
const fragment = this._templateHandler.instantiateFragment('term-reason');
|
const fragment = this._templates.instantiateFragment('term-reason');
|
||||||
const node = fragment.querySelector('.term-reason');
|
const node = fragment.querySelector('.term-reason');
|
||||||
node.textContent = reason;
|
node.textContent = reason;
|
||||||
node.dataset.reason = reason;
|
node.dataset.reason = reason;
|
||||||
@ -172,7 +172,7 @@ class DisplayGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_createTermDefinitionItem(details) {
|
_createTermDefinitionItem(details) {
|
||||||
const node = this._templateHandler.instantiate('term-definition-item');
|
const node = this._templates.instantiate('term-definition-item');
|
||||||
|
|
||||||
const tagListContainer = node.querySelector('.term-definition-tag-list');
|
const tagListContainer = node.querySelector('.term-definition-tag-list');
|
||||||
const onlyListContainer = node.querySelector('.term-definition-disambiguation-list');
|
const onlyListContainer = node.querySelector('.term-definition-disambiguation-list');
|
||||||
@ -202,7 +202,7 @@ class DisplayGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_createTermGlossaryItemText(glossary) {
|
_createTermGlossaryItemText(glossary) {
|
||||||
const node = this._templateHandler.instantiate('term-glossary-item');
|
const node = this._templates.instantiate('term-glossary-item');
|
||||||
const container = node.querySelector('.term-glossary');
|
const container = node.querySelector('.term-glossary');
|
||||||
if (container !== null) {
|
if (container !== null) {
|
||||||
this._appendMultilineText(container, glossary);
|
this._appendMultilineText(container, glossary);
|
||||||
@ -225,7 +225,7 @@ class DisplayGenerator {
|
|||||||
width / height
|
width / height
|
||||||
);
|
);
|
||||||
|
|
||||||
const node = this._templateHandler.instantiate('term-glossary-item-image');
|
const node = this._templates.instantiate('term-glossary-item-image');
|
||||||
node.dataset.path = path;
|
node.dataset.path = path;
|
||||||
node.dataset.dictionary = dictionary;
|
node.dataset.dictionary = dictionary;
|
||||||
node.dataset.imageLoadState = 'not-loaded';
|
node.dataset.imageLoadState = 'not-loaded';
|
||||||
@ -273,7 +273,7 @@ class DisplayGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_createTermDisambiguation(disambiguation) {
|
_createTermDisambiguation(disambiguation) {
|
||||||
const node = this._templateHandler.instantiate('term-definition-disambiguation');
|
const node = this._templates.instantiate('term-definition-disambiguation');
|
||||||
node.dataset.term = disambiguation;
|
node.dataset.term = disambiguation;
|
||||||
node.textContent = disambiguation;
|
node.textContent = disambiguation;
|
||||||
return node;
|
return node;
|
||||||
@ -287,7 +287,7 @@ class DisplayGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_createKanjiGlossaryItem(glossary) {
|
_createKanjiGlossaryItem(glossary) {
|
||||||
const node = this._templateHandler.instantiate('kanji-glossary-item');
|
const node = this._templates.instantiate('kanji-glossary-item');
|
||||||
const container = node.querySelector('.kanji-glossary');
|
const container = node.querySelector('.kanji-glossary');
|
||||||
if (container !== null) {
|
if (container !== null) {
|
||||||
this._appendMultilineText(container, glossary);
|
this._appendMultilineText(container, glossary);
|
||||||
@ -296,13 +296,13 @@ class DisplayGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_createKanjiReading(reading) {
|
_createKanjiReading(reading) {
|
||||||
const node = this._templateHandler.instantiate('kanji-reading');
|
const node = this._templates.instantiate('kanji-reading');
|
||||||
node.textContent = reading;
|
node.textContent = reading;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
_createKanjiInfoTable(details) {
|
_createKanjiInfoTable(details) {
|
||||||
const node = this._templateHandler.instantiate('kanji-info-table');
|
const node = this._templates.instantiate('kanji-info-table');
|
||||||
|
|
||||||
const container = node.querySelector('.kanji-info-table-body');
|
const container = node.querySelector('.kanji-info-table-body');
|
||||||
|
|
||||||
@ -318,7 +318,7 @@ class DisplayGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_createKanjiInfoTableItem(details) {
|
_createKanjiInfoTableItem(details) {
|
||||||
const node = this._templateHandler.instantiate('kanji-info-table-item');
|
const node = this._templates.instantiate('kanji-info-table-item');
|
||||||
const nameNode = node.querySelector('.kanji-info-table-item-header');
|
const nameNode = node.querySelector('.kanji-info-table-item-header');
|
||||||
const valueNode = node.querySelector('.kanji-info-table-item-value');
|
const valueNode = node.querySelector('.kanji-info-table-item-value');
|
||||||
if (nameNode !== null) {
|
if (nameNode !== null) {
|
||||||
@ -331,11 +331,11 @@ class DisplayGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_createKanjiInfoTableItemEmpty() {
|
_createKanjiInfoTableItemEmpty() {
|
||||||
return this._templateHandler.instantiate('kanji-info-table-empty');
|
return this._templates.instantiate('kanji-info-table-empty');
|
||||||
}
|
}
|
||||||
|
|
||||||
_createTag(details) {
|
_createTag(details) {
|
||||||
const node = this._templateHandler.instantiate('tag');
|
const node = this._templates.instantiate('tag');
|
||||||
|
|
||||||
const inner = node.querySelector('.tag-inner');
|
const inner = node.querySelector('.tag-inner');
|
||||||
|
|
||||||
@ -347,7 +347,7 @@ class DisplayGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_createSearchTag(details) {
|
_createSearchTag(details) {
|
||||||
const node = this._templateHandler.instantiate('tag-search');
|
const node = this._templates.instantiate('tag-search');
|
||||||
|
|
||||||
node.textContent = details.query;
|
node.textContent = details.query;
|
||||||
|
|
||||||
@ -359,13 +359,13 @@ class DisplayGenerator {
|
|||||||
_createPitches(details) {
|
_createPitches(details) {
|
||||||
if (!this._termPitchAccentStaticTemplateIsSetup) {
|
if (!this._termPitchAccentStaticTemplateIsSetup) {
|
||||||
this._termPitchAccentStaticTemplateIsSetup = true;
|
this._termPitchAccentStaticTemplateIsSetup = true;
|
||||||
const t = this._templateHandler.instantiate('term-pitch-accent-static');
|
const t = this._templates.instantiate('term-pitch-accent-static');
|
||||||
document.head.appendChild(t);
|
document.head.appendChild(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
const {dictionary, pitches} = details;
|
const {dictionary, pitches} = details;
|
||||||
|
|
||||||
const node = this._templateHandler.instantiate('term-pitch-accent-group');
|
const node = this._templates.instantiate('term-pitch-accent-group');
|
||||||
node.dataset.dictionary = dictionary;
|
node.dataset.dictionary = dictionary;
|
||||||
node.dataset.pitchesMulti = 'true';
|
node.dataset.pitchesMulti = 'true';
|
||||||
node.dataset.pitchesCount = `${pitches.length}`;
|
node.dataset.pitchesCount = `${pitches.length}`;
|
||||||
@ -383,7 +383,7 @@ class DisplayGenerator {
|
|||||||
const {reading, position, tags, exclusiveExpressions, exclusiveReadings} = details;
|
const {reading, position, tags, exclusiveExpressions, exclusiveReadings} = details;
|
||||||
const morae = jp.getKanaMorae(reading);
|
const morae = jp.getKanaMorae(reading);
|
||||||
|
|
||||||
const node = this._templateHandler.instantiate('term-pitch-accent');
|
const node = this._templates.instantiate('term-pitch-accent');
|
||||||
|
|
||||||
node.dataset.pitchAccentPosition = `${position}`;
|
node.dataset.pitchAccentPosition = `${position}`;
|
||||||
node.dataset.tagCount = `${tags.length}`;
|
node.dataset.tagCount = `${tags.length}`;
|
||||||
@ -403,7 +403,7 @@ class DisplayGenerator {
|
|||||||
const highPitch = jp.isMoraPitchHigh(i, position);
|
const highPitch = jp.isMoraPitchHigh(i, position);
|
||||||
const highPitchNext = jp.isMoraPitchHigh(i + 1, position);
|
const highPitchNext = jp.isMoraPitchHigh(i + 1, position);
|
||||||
|
|
||||||
const n1 = this._templateHandler.instantiate('term-pitch-accent-character');
|
const n1 = this._templates.instantiate('term-pitch-accent-character');
|
||||||
const n2 = n1.querySelector('.term-pitch-accent-character-inner');
|
const n2 = n1.querySelector('.term-pitch-accent-character-inner');
|
||||||
|
|
||||||
n1.dataset.position = `${i}`;
|
n1.dataset.position = `${i}`;
|
||||||
@ -424,14 +424,14 @@ class DisplayGenerator {
|
|||||||
_createPitchAccentDisambiguations(container, exclusiveExpressions, exclusiveReadings) {
|
_createPitchAccentDisambiguations(container, exclusiveExpressions, exclusiveReadings) {
|
||||||
const templateName = 'term-pitch-accent-disambiguation';
|
const templateName = 'term-pitch-accent-disambiguation';
|
||||||
for (const exclusiveExpression of exclusiveExpressions) {
|
for (const exclusiveExpression of exclusiveExpressions) {
|
||||||
const node = this._templateHandler.instantiate(templateName);
|
const node = this._templates.instantiate(templateName);
|
||||||
node.dataset.type = 'expression';
|
node.dataset.type = 'expression';
|
||||||
node.textContent = exclusiveExpression;
|
node.textContent = exclusiveExpression;
|
||||||
container.appendChild(node);
|
container.appendChild(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const exclusiveReading of exclusiveReadings) {
|
for (const exclusiveReading of exclusiveReadings) {
|
||||||
const node = this._templateHandler.instantiate(templateName);
|
const node = this._templates.instantiate(templateName);
|
||||||
node.dataset.type = 'reading';
|
node.dataset.type = 'reading';
|
||||||
node.textContent = exclusiveReading;
|
node.textContent = exclusiveReading;
|
||||||
container.appendChild(node);
|
container.appendChild(node);
|
||||||
@ -483,7 +483,7 @@ class DisplayGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_createFrequencyTag(details) {
|
_createFrequencyTag(details) {
|
||||||
const node = this._templateHandler.instantiate('tag-frequency');
|
const node = this._templates.instantiate('tag-frequency');
|
||||||
|
|
||||||
let n = node.querySelector('.term-frequency-dictionary-name');
|
let n = node.querySelector('.term-frequency-dictionary-name');
|
||||||
if (n !== null) {
|
if (n !== null) {
|
||||||
|
@ -15,23 +15,22 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
class HtmlTemplateCollection {
|
||||||
class TemplateHandler {
|
constructor(source) {
|
||||||
constructor(html) {
|
|
||||||
this._templates = new Map();
|
this._templates = new Map();
|
||||||
|
|
||||||
const doc = new DOMParser().parseFromString(html, 'text/html');
|
const sourceNode = (
|
||||||
for (const template of doc.querySelectorAll('template')) {
|
typeof source === 'string' ?
|
||||||
this._setTemplate(template);
|
new DOMParser().parseFromString(source, 'text/html') :
|
||||||
}
|
source
|
||||||
}
|
);
|
||||||
|
|
||||||
_setTemplate(template) {
|
const pattern = /^([\w\W]+)-template$/;
|
||||||
const idMatch = template.id.match(/^([a-z-]+)-template$/);
|
for (const template of sourceNode.querySelectorAll('template')) {
|
||||||
if (!idMatch) {
|
const match = pattern.exec(template.id);
|
||||||
throw new Error(`Invalid template ID: ${template.id}`);
|
if (match === null) { continue; }
|
||||||
|
this._templates.set(match[1], template);
|
||||||
}
|
}
|
||||||
this._templates.set(idMatch[1], template);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
instantiate(name) {
|
instantiate(name) {
|
Loading…
Reference in New Issue
Block a user