diff options
author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2020-10-30 17:41:52 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-30 17:41:52 -0400 |
commit | 327d7b1f26d8553809292e159b97d44bc77b7b8e (patch) | |
tree | 175d18d86fc09e97cef6dba68ed62331467ca934 | |
parent | cb76848df980b4245e9f5c0dee4eec4280ed645d (diff) |
Anki templates refactor (#970)
* Support menus with multiple sources
* Update anki templates controller
-rw-r--r-- | ext/bg/css/settings.css | 6 | ||||
-rw-r--r-- | ext/bg/js/settings/anki-controller.js | 14 | ||||
-rw-r--r-- | ext/bg/js/settings/anki-templates-controller.js | 73 | ||||
-rw-r--r-- | ext/bg/settings.html | 26 |
4 files changed, 76 insertions, 43 deletions
diff --git a/ext/bg/css/settings.css b/ext/bg/css/settings.css index 231df1b3..5416371f 100644 --- a/ext/bg/css/settings.css +++ b/ext/bg/css/settings.css @@ -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; } diff --git a/ext/bg/js/settings/anki-controller.js b/ext/bg/js/settings/anki-controller.js index 6988e4b8..c205c160 100644 --- a/ext/bg/js/settings/anki-controller.js +++ b/ext/bg/js/settings/anki-controller.js @@ -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; } diff --git a/ext/bg/js/settings/anki-templates-controller.js b/ext/bg/js/settings/anki-templates-controller.js index 65900336..e6bab256 100644 --- a/ext/bg/js/settings/anki-templates-controller.js +++ b/ext/bg/js/settings/anki-templates-controller.js @@ -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); } } diff --git a/ext/bg/settings.html b/ext/bg/settings.html index 066662e5..1b1e9124 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -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> |