Anki templates refactor (#970)
* Support menus with multiple sources * Update anki templates controller
This commit is contained in:
parent
cb76848df9
commit
327d7b1f26
@ -272,7 +272,7 @@ html:root:not([data-options-general-result-output-mode=merge]) #dictionary-main-
|
||||
|
||||
#custom-popup-css,
|
||||
#custom-popup-outer-css,
|
||||
#field-templates {
|
||||
#anki-card-templates-textarea {
|
||||
width: 100%;
|
||||
min-height: 34px;
|
||||
line-height: 18px;
|
||||
@ -280,12 +280,10 @@ html:root:not([data-options-general-result-output-mode=merge]) #dictionary-main-
|
||||
resize: vertical;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
white-space: pre;
|
||||
}
|
||||
#field-templates {
|
||||
height: 240px;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
#field-templates-reset {
|
||||
#anki-card-templates-reset-button {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
@ -214,14 +214,20 @@ class AnkiController {
|
||||
|
||||
_setupFieldMenus() {
|
||||
const fieldMenuTargets = [
|
||||
['terms', '#anki-card-terms-field-menu-template'],
|
||||
['kanji', '#anki-card-kanji-field-menu-template']
|
||||
[['terms'], '#anki-card-terms-field-menu-template'],
|
||||
[['kanji'], '#anki-card-kanji-field-menu-template'],
|
||||
[['terms', 'kanji'], '#anki-card-all-field-menu-template']
|
||||
];
|
||||
for (const [type, selector] of fieldMenuTargets) {
|
||||
for (const [types, selector] of fieldMenuTargets) {
|
||||
const element = document.querySelector(selector);
|
||||
if (element === null) { continue; }
|
||||
|
||||
const markers = this.getFieldMarkers(type);
|
||||
let markers = [];
|
||||
for (const type of types) {
|
||||
markers.push(...this.getFieldMarkers(type));
|
||||
}
|
||||
markers = [...new Set(markers)];
|
||||
|
||||
const container = element.content.querySelector('.popup-menu');
|
||||
if (container === null) { return; }
|
||||
|
||||
|
@ -30,6 +30,10 @@ class AnkiTemplatesController {
|
||||
this._cachedDefinitionValue = null;
|
||||
this._cachedDefinitionText = null;
|
||||
this._defaultFieldTemplates = null;
|
||||
this._fieldTemplatesTextarea = null;
|
||||
this._compileResultInfo = null;
|
||||
this._renderFieldInput = null;
|
||||
this._renderResult = null;
|
||||
this._fieldTemplateResetModal = null;
|
||||
this._templateRenderer = new TemplateRendererProxy();
|
||||
}
|
||||
@ -37,24 +41,38 @@ class AnkiTemplatesController {
|
||||
async prepare() {
|
||||
this._defaultFieldTemplates = await api.getDefaultAnkiFieldTemplates();
|
||||
|
||||
this._fieldTemplateResetModal = this._modalController.getModal('field-template-reset-modal');
|
||||
this._fieldTemplatesTextarea = document.querySelector('#anki-card-templates-textarea');
|
||||
this._compileResultInfo = document.querySelector('#anki-card-templates-compile-result');
|
||||
this._renderFieldInput = document.querySelector('#anki-card-templates-test-field-input');
|
||||
this._renderTextInput = document.querySelector('#anki-card-templates-test-text-input');
|
||||
this._renderResult = document.querySelector('#anki-card-templates-render-result');
|
||||
const menuButton = document.querySelector('#anki-card-templates-test-field-menu-button');
|
||||
const testRenderButton = document.querySelector('#anki-card-templates-test-render-button');
|
||||
const resetButton = document.querySelector('#anki-card-templates-reset-button');
|
||||
const resetConfirmButton = document.querySelector('#anki-card-templates-reset-button-confirm');
|
||||
const fieldList = document.querySelector('#anki-card-templates-field-list');
|
||||
this._fieldTemplateResetModal = this._modalController.getModal('anki-card-templates-reset');
|
||||
|
||||
const markers = new Set([
|
||||
...this._ankiController.getFieldMarkers('terms'),
|
||||
...this._ankiController.getFieldMarkers('kanji')
|
||||
]);
|
||||
const fragment = this._ankiController.getFieldMarkersHtml(markers);
|
||||
|
||||
const list = document.querySelector('#field-templates-list');
|
||||
list.appendChild(fragment);
|
||||
for (const node of list.querySelectorAll('.marker-link')) {
|
||||
node.addEventListener('click', this._onMarkerClicked.bind(this), false);
|
||||
if (fieldList !== null) {
|
||||
const fragment = this._ankiController.getFieldMarkersHtml(markers);
|
||||
fieldList.appendChild(fragment);
|
||||
for (const node of fieldList.querySelectorAll('.marker-link')) {
|
||||
node.addEventListener('click', this._onMarkerClicked.bind(this), false);
|
||||
}
|
||||
}
|
||||
|
||||
document.querySelector('#field-templates').addEventListener('change', this._onChanged.bind(this), false);
|
||||
document.querySelector('#field-template-render').addEventListener('click', this._onRender.bind(this), false);
|
||||
document.querySelector('#field-templates-reset').addEventListener('click', this._onReset.bind(this), false);
|
||||
document.querySelector('#field-templates-reset-confirm').addEventListener('click', this._onResetConfirm.bind(this), false);
|
||||
this._fieldTemplatesTextarea.addEventListener('change', this._onChanged.bind(this), false);
|
||||
testRenderButton.addEventListener('click', this._onRender.bind(this), false);
|
||||
resetButton.addEventListener('click', this._onReset.bind(this), false);
|
||||
resetConfirmButton.addEventListener('click', this._onResetConfirm.bind(this), false);
|
||||
if (menuButton !== null) {
|
||||
menuButton.addEventListener('menuClosed', this._onFieldMenuClosed.bind(this), false);
|
||||
}
|
||||
|
||||
this._settingsController.on('optionsChanged', this._onOptionsChanged.bind(this));
|
||||
|
||||
@ -67,7 +85,7 @@ class AnkiTemplatesController {
|
||||
_onOptionsChanged({options}) {
|
||||
let templates = options.anki.fieldTemplates;
|
||||
if (typeof templates !== 'string') { templates = this._defaultFieldTemplates; }
|
||||
document.querySelector('#field-templates').value = templates;
|
||||
this._fieldTemplatesTextarea.value = templates;
|
||||
|
||||
this._onValidateCompile();
|
||||
}
|
||||
@ -84,9 +102,8 @@ class AnkiTemplatesController {
|
||||
|
||||
const value = this._defaultFieldTemplates;
|
||||
|
||||
const element = document.querySelector('#field-templates');
|
||||
element.value = value;
|
||||
element.dispatchEvent(new Event('change'));
|
||||
this._fieldTemplatesTextarea.value = value;
|
||||
this._fieldTemplatesTextarea.dispatchEvent(new Event('change'));
|
||||
}
|
||||
|
||||
async _onChanged(e) {
|
||||
@ -105,24 +122,37 @@ class AnkiTemplatesController {
|
||||
}
|
||||
|
||||
_onValidateCompile() {
|
||||
const infoNode = document.querySelector('#field-template-compile-result');
|
||||
this._validate(infoNode, '{expression}', 'term-kanji', false, true);
|
||||
this._validate(this._compileResultInfo, '{expression}', 'term-kanji', false, true);
|
||||
}
|
||||
|
||||
_onMarkerClicked(e) {
|
||||
e.preventDefault();
|
||||
document.querySelector('#field-template-render-text').value = `{${e.target.textContent}}`;
|
||||
this._renderFieldInput.value = `{${e.target.textContent}}`;
|
||||
}
|
||||
|
||||
_onRender(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const field = document.querySelector('#field-template-render-text').value;
|
||||
const infoNode = document.querySelector('#field-template-render-result');
|
||||
const field = this._renderFieldInput.value;
|
||||
const infoNode = this._renderResult;
|
||||
infoNode.hidden = true;
|
||||
this._validate(infoNode, field, 'term-kanji', true, false);
|
||||
}
|
||||
|
||||
_onFieldMenuClosed({currentTarget: node, detail: {action, item}}) {
|
||||
switch (action) {
|
||||
case 'setFieldMarker':
|
||||
this._setFieldMarker(node, item.dataset.marker);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_setFieldMarker(element, marker) {
|
||||
const input = this._renderFieldInput;
|
||||
input.value = `{${marker}}`;
|
||||
input.dispatchEvent(new Event('change'));
|
||||
}
|
||||
|
||||
async _getDefinition(text, optionsContext) {
|
||||
if (this._cachedDefinitionText !== text) {
|
||||
const {definitions} = await api.termsFind(text, {}, optionsContext);
|
||||
@ -135,7 +165,7 @@ class AnkiTemplatesController {
|
||||
}
|
||||
|
||||
async _validate(infoNode, field, mode, showSuccessResult, invalidateInput) {
|
||||
const text = document.querySelector('#field-templates-preview-text').value || '';
|
||||
const text = this._renderTextInput.value || '';
|
||||
const exceptions = [];
|
||||
let result = `No definition found for ${text}`;
|
||||
try {
|
||||
@ -179,8 +209,7 @@ class AnkiTemplatesController {
|
||||
infoNode.textContent = hasException ? exceptions.map((e) => `${e}`).join('\n') : (showSuccessResult ? result : '');
|
||||
infoNode.classList.toggle('text-danger', hasException);
|
||||
if (invalidateInput) {
|
||||
const input = document.querySelector('#field-templates');
|
||||
input.classList.toggle('is-invalid', hasException);
|
||||
this._fieldTemplatesTextarea.classList.toggle('is-invalid', hasException);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1004,32 +1004,32 @@
|
||||
their Anki cards. If you encounter problems with your changes, you can always reset to the default template settings.
|
||||
</p>
|
||||
<div class="ignore-form-changes">
|
||||
<textarea autocomplete="off" spellcheck="false" wrap="soft" class="form-control" rows="10" id="field-templates"></textarea>
|
||||
<textarea autocomplete="off" spellcheck="false" wrap="soft" class="form-control" rows="10" id="anki-card-templates-textarea"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<button class="btn btn-danger" id="field-templates-reset">Reset Templates</button>
|
||||
<button class="btn btn-danger" id="anki-card-templates-reset-button">Reset Templates</button>
|
||||
</div>
|
||||
<p></p>
|
||||
<pre id="field-template-compile-result" hidden></pre>
|
||||
<pre id="anki-card-templates-compile-result" hidden></pre>
|
||||
|
||||
<p>Templates can be tested using the inputs below.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<label for="field-templates-preview-text">Preview text</label>
|
||||
<input type="text" id="field-templates-preview-text" class="form-control" value="読め" placeholder="Preview text">
|
||||
<label for="anki-card-templates-test-text-input">Preview text</label>
|
||||
<input type="text" id="anki-card-templates-test-text-input" class="form-control" value="読め" placeholder="Preview text">
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<label for="field-template-render-text">Test field</label>
|
||||
<label for="anki-card-templates-test-field-input">Test field</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-btn">
|
||||
<button class="btn btn-default" id="field-template-render" title="Test"><span class="glyphicon glyphicon-play"></span></button>
|
||||
<button class="btn btn-default" id="anki-card-templates-test-render-button" title="Test"><span class="glyphicon glyphicon-play"></span></button>
|
||||
</div>
|
||||
<input type="text" class="form-control" id="field-template-render-text" value="{expression}" placeholder="{marker}">
|
||||
<input type="text" class="form-control" id="anki-card-templates-test-field-input" value="{expression}" placeholder="{marker}">
|
||||
<div class="input-group-btn">
|
||||
<button class="btn btn-default dropdown-toggle" id="field-templates-dropdown" data-toggle="dropdown"><span class="caret"></span></button>
|
||||
<ul class="dropdown-menu dropdown-menu-right" id="field-templates-list"></ul>
|
||||
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></button>
|
||||
<ul class="dropdown-menu dropdown-menu-right" id="anki-card-templates-field-list"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1037,10 +1037,10 @@
|
||||
</div>
|
||||
|
||||
<p></p>
|
||||
<pre id="field-template-render-result" hidden></pre>
|
||||
<pre id="anki-card-templates-render-result" hidden></pre>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" tabindex="-1" role="dialog" id="field-template-reset-modal">
|
||||
<div class="modal fade" tabindex="-1" role="dialog" id="anki-card-templates-reset">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
@ -1053,7 +1053,7 @@
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-danger" id="field-templates-reset-confirm">Reset Templates</button>
|
||||
<button type="button" class="btn btn-danger" id="anki-card-templates-reset-button-confirm">Reset Templates</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user