diff options
-rw-r--r-- | ext/bg/js/settings/generic-setting-controller.js | 118 | ||||
-rw-r--r-- | ext/bg/settings.html | 48 | ||||
-rw-r--r-- | ext/bg/settings2.html | 55 | ||||
-rw-r--r-- | ext/bg/welcome.html | 8 |
4 files changed, 144 insertions, 85 deletions
diff --git a/ext/bg/js/settings/generic-setting-controller.js b/ext/bg/js/settings/generic-setting-controller.js index 132dc042..04cad67d 100644 --- a/ext/bg/js/settings/generic-setting-controller.js +++ b/ext/bg/js/settings/generic-setting-controller.js @@ -31,8 +31,7 @@ class GenericSettingController { setValues: this._setValues.bind(this) }); this._transforms = new Map([ - ['setDocumentAttribute', this._setDocumentAttribute.bind(this)], - ['setRelativeAttribute', this._setRelativeAttribute.bind(this)], + ['setAttribute', this._setAttribute.bind(this)], ['setVisibility', this._setVisibility.bind(this)], ['splitTags', this._splitTags.bind(this)], ['joinTags', this._joinTags.bind(this)], @@ -57,12 +56,19 @@ class GenericSettingController { } _createElementMetadata(element) { - const {dataset: {setting: path, scope, transform, transformPre, transformPost}} = element; + const {dataset: {setting: path, scope, transform: transformRaw}} = element; + let transforms; + if (typeof transformRaw === 'string') { + transforms = JSON.parse(transformRaw); + if (!Array.isArray(transforms)) { transforms = [transforms]; } + } else { + transforms = []; + } return { path, scope, - transformPre: typeof transformPre === 'string' ? transformPre : transform, - transformPost: typeof transformPost === 'string' ? transformPost : transform + transforms, + transformRaw }; } @@ -70,8 +76,7 @@ class GenericSettingController { return ( metadata1.path === metadata2.path && metadata1.scope === metadata2.scope && - metadata1.transformPre === metadata2.transformPre && - metadata1.transformPost === metadata2.transformPost + metadata1.transformRaw === metadata2.transformRaw ); } @@ -91,13 +96,13 @@ class GenericSettingController { async _setValues(targets) { const defaultScope = this._defaultScope; const settingsTargets = []; - for (const {metadata, value, element} of targets) { - const {path, scope, transformPre} = metadata; + for (const {metadata: {path, scope, transforms}, value, element} of targets) { + const transformedValue = this._applyTransforms(value, transforms, 'pre', element); const target = { path, scope: scope || defaultScope, action: 'set', - value: this._transform(value, transformPre, metadata, element) + value: transformedValue }; settingsTargets.push(target); } @@ -108,64 +113,50 @@ class GenericSettingController { return values.map((value, i) => { const error = value.error; if (error) { return jsonToError(error); } - const {metadata, element} = targets[i]; - const result = this._transform(value.result, metadata.transformPost, metadata, element); + const {metadata: {transforms}, element} = targets[i]; + const result = this._applyTransforms(value.result, transforms, 'post', element); return {result}; }); } - _transform(value, transform, metadata, element) { - if (typeof transform === 'string') { - const transformFunction = this._transforms.get(transform); - if (typeof transformFunction !== 'undefined') { - value = transformFunction(value, metadata, element); - } + _applyTransforms(value, transforms, step, element) { + for (const transform of transforms) { + const transformStep = transform.step; + if (typeof transformStep !== 'undefined' && transformStep !== step) { continue; } + + const transformFunction = this._transforms.get(transform.type); + if (typeof transformFunction === 'undefined') { continue; } + + value = transformFunction(value, transform, element); } return value; } _getAncestor(node, ancestorDistance) { - if (typeof ancestorDistance === 'string') { - const ii = Number.parseInt(ancestorDistance, 10); - if (Number.isFinite(ii)) { - if (ii < 0) { - node = document.documentElement; - } else { - for (let i = 0; i < ii && node !== null; ++i) { - node = node.parentNode; - } - } - } + if (ancestorDistance < 0) { + return document.documentElement; + } + for (let i = 0; i < ancestorDistance && node !== null; ++i) { + node = node.parentNode; } return node; } - _getElementRelativeToAncestor(node, ancestorDistance, relativeSelector) { - const relativeElement = this._getAncestor(node, ancestorDistance); - if (relativeElement === null) { return null; } + _getRelativeElement(node, ancestorDistance, selector) { + const selectorRoot = ( + typeof ancestorDistance === 'number' ? + this._getAncestor(node, ancestorDistance) : + document + ); + if (selectorRoot === null) { return null; } return ( - typeof relativeSelector === 'string' ? - relativeElement.querySelector(relativeSelector) : - relativeElement + typeof selector === 'string' ? + selectorRoot.querySelector(selector) : + (selectorRoot === document ? document.documentElement : selectorRoot) ); } - _getConditionalResult(value, conditionString) { - let op = '!!'; - let rhsOperand = null; - try { - if (typeof conditionString === 'string') { - const {op: op2, value: value2} = JSON.parse(conditionString); - op = (typeof op2 === 'string' ? op2 : '==='); - rhsOperand = value2; - } - } catch (e) { - // NOP - } - return this._evaluateSimpleOperation(op, value, rhsOperand); - } - _evaluateSimpleOperation(operation, lhs, rhs) { switch (operation) { case '!': return !lhs; @@ -182,25 +173,20 @@ class GenericSettingController { // Transforms - _setDocumentAttribute(value, metadata, element) { - document.documentElement.setAttribute(element.dataset.documentAttribute, `${value}`); - return value; - } - - _setRelativeAttribute(value, metadata, element) { - const {ancestorDistance, relativeSelector, relativeAttribute} = element.dataset; - const relativeElement = this._getElementRelativeToAncestor(element, ancestorDistance, relativeSelector); + _setAttribute(value, data, element) { + const {ancestorDistance, selector, attribute} = data; + const relativeElement = this._getRelativeElement(element, ancestorDistance, selector); if (relativeElement !== null) { - relativeElement.setAttribute(relativeAttribute, `${value}`); + relativeElement.setAttribute(attribute, `${value}`); } return value; } - _setVisibility(value, metadata, element) { - const {ancestorDistance, relativeSelector, visbilityCondition} = element.dataset; - const relativeElement = this._getElementRelativeToAncestor(element, ancestorDistance, relativeSelector); + _setVisibility(value, data, element) { + const {ancestorDistance, selector, condition} = data; + const relativeElement = this._getRelativeElement(element, ancestorDistance, selector); if (relativeElement !== null) { - relativeElement.hidden = !this._getConditionalResult(value, visbilityCondition); + relativeElement.hidden = !this._evaluateSimpleOperation(condition.op, value, condition.value); } return value; } @@ -213,8 +199,10 @@ class GenericSettingController { return value.join(' '); } - _toNumber(value, metadata, element) { - return DOMDataBinder.convertToNumber(value, element.dataset); + _toNumber(value, data) { + let {constraints} = data; + if (!isObject(constraints)) { constraints = {}; } + return DOMDataBinder.convertToNumber(value, constraints); } _toString(value) { diff --git a/ext/bg/settings.html b/ext/bg/settings.html index c6070baf..ec048a3b 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -151,7 +151,13 @@ </div> <div class="checkbox"> - <label><input type="checkbox" id="show-advanced-options" data-setting="general.showAdvanced" data-transform-pre="setDocumentAttribute" data-transform-post="setDocumentAttribute" data-document-attribute="data-options-general-show-advanced"> Show advanced options</label> + <label><input type="checkbox" id="show-advanced-options" data-setting="general.showAdvanced" + data-transform='{ + "type": "setAttribute", + "selector": ":root", + "attribute": "data-options-general-show-advanced" + }' + > Show advanced options</label> </div> <div class="checkbox options-advanced ignore-form-changes" data-hide-for-browser="firefox-mobile"> @@ -195,7 +201,13 @@ </div> <div class="checkbox options-advanced"> - <label><input type="checkbox" id="show-debug-info" data-setting="general.debugInfo" data-transform-pre="setDocumentAttribute" data-transform-post="setDocumentAttribute" data-document-attribute="data-options-general-debug-info"> Show debug information</label> + <label><input type="checkbox" id="show-debug-info" data-setting="general.debugInfo" + data-transform='{ + "type": "setAttribute", + "selector": ":root", + "attribute": "data-options-general-debug-info" + }' + > Show debug information</label> </div> <div class="checkbox options-advanced"> @@ -204,7 +216,13 @@ <div class="form-group"> <label for="result-output-mode">Result grouping</label> - <select class="form-control" id="result-output-mode" data-setting="general.resultOutputMode" data-transform-pre="setDocumentAttribute" data-transform-post="setDocumentAttribute" data-document-attribute="data-options-general-result-output-mode"> + <select class="form-control" id="result-output-mode" data-setting="general.resultOutputMode" + data-transform='{ + "type": "setAttribute", + "selector": ":root", + "attribute": "data-options-general-result-output-mode" + }' + > <option value="group">Group results by term-reading pairs</option> <option value="merge">Group results by main dictionary entry</option> <option value="split">Split definitions to their own results</option> @@ -498,10 +516,11 @@ <label class="scan-input-toggle scan-input-type"><input type="checkbox" class="scan-input-settings-checkbox" data-property="types.touch"><span>Touch</span></label> <label class="scan-input-toggle scan-input-type"><input type="checkbox" class="scan-input-settings-checkbox" data-property="types.pen"><span>Pen</span></label> <label class="scan-input-toggle scan-input-type"><input type="checkbox" class="scan-input-settings-checkbox" data-property="options.showAdvanced" - data-transform-pre="setRelativeAttribute" - data-transform-post="setRelativeAttribute" - data-ancestor-distance="7" - data-relative-attribute="data-show-advanced" + data-transform='{ + "type": "setAttribute", + "ancestorDistance": 7, + "attribute": "data-show-advanced" + }' ><span>Advanced</span></label> </div></div> </div></div> @@ -899,7 +918,13 @@ </p> <div class="checkbox"> - <label><input type="checkbox" id="anki-enable" data-setting="anki.enable" data-transform="setDocumentAttribute" data-document-attribute="data-options-anki-enable"> Enable Anki integration</label> + <label><input type="checkbox" id="anki-enable" data-setting="anki.enable" + data-transform='{ + "type": "setAttribute", + "selector": ":root", + "attribute": "data-options-anki-enable" + }' + > Enable Anki integration</label> </div> <div id="anki-general"> @@ -925,7 +950,12 @@ <div class="form-group"> <label for="card-tags">Card tags <span class="label-light">(comma or space separated)</span></label> - <input type="text" id="card-tags" class="form-control" data-setting="anki.tags" data-transform-pre="splitTags" data-transform-post="joinTags"> + <input type="text" id="card-tags" class="form-control" data-setting="anki.tags" + data-transform='[ + {"type": "splitTags", "step": "pre"}, + {"type": "joinTags", "step": "post"} + ]' + > </div> <div class="form-group options-advanced"> diff --git a/ext/bg/settings2.html b/ext/bg/settings2.html index 41cd3946..be6e01e1 100644 --- a/ext/bg/settings2.html +++ b/ext/bg/settings2.html @@ -39,7 +39,13 @@ </div> <div class="sidebar-bottom"> <label class="outline-item"><span class="outline-item-left"> - <label class="toggle"><input id="advanced-checkbox" type="checkbox" data-setting="general.showAdvanced" data-transform="setDocumentAttribute" data-document-attribute="data-advanced"><span class="toggle-body"><span class="toggle-track"></span><span class="toggle-knob"></span></span></label> + <label class="toggle"><input id="advanced-checkbox" type="checkbox" data-setting="general.showAdvanced" + data-transform='{ + "type": "setAttribute", + "selector": ":root", + "attribute": "data-advanced" + }' + ><span class="toggle-body"><span class="toggle-track"></span><span class="toggle-knob"></span></span></label> </span><span class="outline-item-label">Advanced</span></label> <a href="/bg/info.html" class="outline-item"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="question-mark"></span></span><span class="outline-item-label">About Yomichan</span></a> </div> @@ -216,7 +222,13 @@ </div> </div> <div class="settings-item-right"> - <select data-setting="general.resultOutputMode" data-transform="setVisibility" data-ancestor-distance="-1" data-relative-selector="#main-dictionary-container" data-visbility-condition='{"op":"===","value":"merge"}'> + <select data-setting="general.resultOutputMode" + data-transform='{ + "type": "setVisibility", + "selector": "#main-dictionary-container", + "condition": {"op": "===", "value": "merge"} + }' + > <option value="split">No grouping</option> <option value="group">Group term-reading pairs</option> <option value="merge">Group related terms</option> @@ -375,7 +387,13 @@ <div class="settings-item-description">When no text or definitions are found, the popup will automatically hide.</div> </div> <div class="settings-item-right"> - <label class="toggle"><input type="checkbox" data-setting="scanning.autoHideResults" data-transform="setVisibility" data-ancestor-distance="-1" data-relative-selector="#auto-hide-search-popup-options" data-visbility-condition='{"op":"===","value":true}'><span class="toggle-body"><span class="toggle-track"></span><span class="toggle-knob"></span></span></label> + <label class="toggle"><input type="checkbox" data-setting="scanning.autoHideResults" + data-transform='{ + "type": "setVisibility", + "selector": "#auto-hide-search-popup-options", + "condition": {"op": "===", "value": true} + }' + ><span class="toggle-body"><span class="toggle-track"></span><span class="toggle-knob"></span></span></label> </div> </div> <div class="settings-item-children settings-item-children-group" id="auto-hide-search-popup-options" hidden> @@ -737,7 +755,12 @@ <div class="settings-item-description">Control the scaling factor of the popup.</div> </div> <div class="settings-item-right"> - <select data-setting="general.popupScalingFactor" data-transform-pre="toNumber" data-transform-post="toString" data-min="0.25"> + <select data-setting="general.popupScalingFactor" + data-transform='[ + {"type": "toNumber", "step": "pre", "constraints": {"min": 0.25}}, + {"type": "toString", "step": "post"} + ]' + > <option value="0.25">25%</option> <option value="0.33">33%</option> <option value="0.5">50%</option> @@ -1253,7 +1276,12 @@ <div class="settings-item-description">List of space or comma separated tags to add to the card.</div> </div> <div class="settings-item-right"> - <input type="text" spellcheck="false" autocomplete="off" data-setting="anki.tags" data-transform-pre="splitTags" data-transform-post="joinTags"> + <input type="text" spellcheck="false" autocomplete="off" data-setting="anki.tags" + data-transform='[ + {"type": "splitTags", "step": "pre"}, + {"type": "joinTags", "step": "post"} + ]' + > </div> </div></div> <div class="settings-item advanced-only"> @@ -1263,7 +1291,13 @@ <div class="settings-item-description">When a card is detected as a duplicate, the add buttons will be disabled.</div> </div> <div class="settings-item-right"> - <label class="toggle"><input type="checkbox" data-setting="anki.checkForDuplicates" data-transform="setVisibility" data-ancestor-distance="-1" data-relative-selector="#anki-card-duplicate-options" data-visbility-condition='{"op":"===","value":true}'><span class="toggle-body"><span class="toggle-track"></span><span class="toggle-knob"></span></span></label> + <label class="toggle"><input type="checkbox" data-setting="anki.checkForDuplicates" + data-transform='{ + "type": "setVisibility", + "selector": "#anki-card-duplicate-options", + "condition": {"op": "===", "value": true} + }' + ><span class="toggle-body"><span class="toggle-track"></span><span class="toggle-knob"></span></span></label> </div> </div> <div class="settings-item-children settings-item-children-group" id="anki-card-duplicate-options" hidden> @@ -1316,10 +1350,11 @@ <div class="settings-item-group-item"> <div class="settings-item-group-item-label">Format</div> <select class="short-width short-height" data-setting="anki.screenshot.format" - data-transform="setVisibility" - data-ancestor-distance="-1" - data-relative-selector="#anki-screenshot-quality" - data-visbility-condition='{"op":"===","value":"jpeg"}' + data-transform='{ + "type": "setVisibility", + "selector": "#anki-screenshot-quality", + "condition": {"op": "===", "value": "jpeg"} + }' > <option value="png">PNG</option> <option value="jpeg">JPEG</option> diff --git a/ext/bg/welcome.html b/ext/bg/welcome.html index 86c8ee83..2c769e2b 100644 --- a/ext/bg/welcome.html +++ b/ext/bg/welcome.html @@ -132,7 +132,13 @@ <div class="settings-item-description">When no text or definitions are found, the popup will automatically hide.</div> </div> <div class="settings-item-right"> - <label class="toggle"><input type="checkbox" data-setting="scanning.autoHideResults" data-transform="setVisibility" data-ancestor-distance="-1" data-relative-selector="#auto-hide-search-popup-options" data-visbility-condition='{"op":"===","value":true}'><span class="toggle-body"><span class="toggle-track"></span><span class="toggle-knob"></span></span></label> + <label class="toggle"><input type="checkbox" data-setting="scanning.autoHideResults" + data-transform='{ + "type": "setVisibility", + "selector": "#auto-hide-search-popup-options", + "condition": {"op": "===", "value": true} + }' + ><span class="toggle-body"><span class="toggle-track"></span><span class="toggle-knob"></span></span></label> </div> </div> <div class="settings-item-children settings-item-children-group" id="auto-hide-search-popup-options" hidden> |