aboutsummaryrefslogtreecommitdiff
path: root/ext/bg/js/settings/generic-setting-controller.js
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2020-10-10 23:17:51 -0400
committerGitHub <noreply@github.com>2020-10-10 23:17:51 -0400
commit9da08c7fe662c40394fb30f6f43b589c1fa72523 (patch)
tree0b32141ae9279829ab5a206c992a14928032ec86 /ext/bg/js/settings/generic-setting-controller.js
parent25c590e54b3086558c10765a4df6f1ddea00fc54 (diff)
Generic settings improvements (#909)
* Add helper function _getElementRelativeToAncestor * Move helper functions * Add setVisibility transform * Add support for data-transform attribute shorthand * Add support for using the document element as the ancestor
Diffstat (limited to 'ext/bg/js/settings/generic-setting-controller.js')
-rw-r--r--ext/bg/js/settings/generic-setting-controller.js96
1 files changed, 73 insertions, 23 deletions
diff --git a/ext/bg/js/settings/generic-setting-controller.js b/ext/bg/js/settings/generic-setting-controller.js
index aa20dbbc..cb49845a 100644
--- a/ext/bg/js/settings/generic-setting-controller.js
+++ b/ext/bg/js/settings/generic-setting-controller.js
@@ -33,6 +33,7 @@ class GenericSettingController {
this._transforms = new Map([
['setDocumentAttribute', this._setDocumentAttribute.bind(this)],
['setRelativeAttribute', this._setRelativeAttribute.bind(this)],
+ ['setVisibility', this._setVisibility.bind(this)],
['splitTags', this._splitTags.bind(this)],
['joinTags', this._joinTags.bind(this)],
['toNumber', this._toNumber.bind(this)],
@@ -52,11 +53,12 @@ class GenericSettingController {
}
_createElementMetadata(element) {
+ const {dataset: {setting: path, scope, transform, transformPre, transformPost}} = element;
return {
- path: element.dataset.setting,
- scope: element.dataset.scope,
- transformPre: element.dataset.transformPre,
- transformPost: element.dataset.transformPost
+ path,
+ scope,
+ transformPre: typeof transformPre === 'string' ? transformPre : transform,
+ transformPost: typeof transformPost === 'string' ? transformPost : transform
};
}
@@ -118,6 +120,62 @@ class GenericSettingController {
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;
+ }
+ }
+ }
+ }
+ return node;
+ }
+
+ _getElementRelativeToAncestor(node, ancestorDistance, relativeSelector) {
+ const relativeElement = this._getAncestor(node, ancestorDistance);
+ if (relativeElement === null) { return null; }
+
+ return (
+ typeof relativeSelector === 'string' ?
+ relativeElement.querySelector(relativeSelector) :
+ relativeElement
+ );
+ }
+
+ _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;
+ case '!!': return !!lhs;
+ case '===': return lhs === rhs;
+ case '!==': return lhs !== rhs;
+ case '>=': return lhs >= rhs;
+ case '<=': return lhs <= rhs;
+ case '>': return lhs > rhs;
+ case '<': return lhs < rhs;
+ default: return false;
+ }
+ }
+
// Transforms
_setDocumentAttribute(value, metadata, element) {
@@ -127,14 +185,18 @@ class GenericSettingController {
_setRelativeAttribute(value, metadata, element) {
const {ancestorDistance, relativeSelector, relativeAttribute} = element.dataset;
- let relativeElement = this._getAncestor(element, ancestorDistance);
+ const relativeElement = this._getElementRelativeToAncestor(element, ancestorDistance, relativeSelector);
if (relativeElement !== null) {
- if (typeof relativeSelector === 'string') {
- relativeElement = relativeElement.querySelector(relativeSelector);
- }
- if (relativeElement !== null) {
- relativeElement.setAttribute(relativeAttribute, `${value}`);
- }
+ relativeElement.setAttribute(relativeAttribute, `${value}`);
+ }
+ return value;
+ }
+
+ _setVisibility(value, metadata, element) {
+ const {ancestorDistance, relativeSelector, visbilityCondition} = element.dataset;
+ const relativeElement = this._getElementRelativeToAncestor(element, ancestorDistance, relativeSelector);
+ if (relativeElement !== null) {
+ relativeElement.hidden = !this._getConditionalResult(value, visbilityCondition);
}
return value;
}
@@ -147,18 +209,6 @@ class GenericSettingController {
return value.join(' ');
}
- _getAncestor(node, ancestorDistance) {
- if (typeof ancestorDistance === 'string') {
- const ii = Number.parseInt(ancestorDistance, 10);
- if (Number.isFinite(ii)) {
- for (let i = 0; i < ii && node !== null; ++i) {
- node = node.parentNode;
- }
- }
- }
- return node;
- }
-
_toNumber(value, metadata, element) {
return DOMDataBinder.convertToNumber(value, element.dataset);
}