diff options
Diffstat (limited to 'browser/components/payments/res/mixins/ObservedPropertiesMixin.js')
-rw-r--r-- | browser/components/payments/res/mixins/ObservedPropertiesMixin.js | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/browser/components/payments/res/mixins/ObservedPropertiesMixin.js b/browser/components/payments/res/mixins/ObservedPropertiesMixin.js new file mode 100644 index 0000000000..5fe71af90c --- /dev/null +++ b/browser/components/payments/res/mixins/ObservedPropertiesMixin.js @@ -0,0 +1,71 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Define getters and setters for observedAttributes converted to camelCase and + * trigger a batched aynchronous call to `render` upon observed + * attribute/property changes. + */ + +export default function ObservedPropertiesMixin(superClass) { + return class ObservedProperties extends superClass { + static kebabToCamelCase(name) { + return name.replace(/-([a-z])/g, ($0, $1) => $1.toUpperCase()); + } + + constructor() { + super(); + + this._observedPropertiesMixin = { + pendingRender: false, + }; + + // Reflect property changes for `observedAttributes` to attributes. + for (let name of this.constructor.observedAttributes || []) { + if (name in this) { + // Don't overwrite existing properties. + continue; + } + // Convert attribute names from kebab-case to camelCase properties + Object.defineProperty(this, ObservedProperties.kebabToCamelCase(name), { + configurable: true, + get() { + return this.getAttribute(name); + }, + set(value) { + if (value === null || value === undefined || value === false) { + this.removeAttribute(name); + } else { + this.setAttribute(name, value); + } + }, + }); + } + } + + async _invalidateFromObservedPropertiesMixin() { + if (this._observedPropertiesMixin.pendingRender) { + return; + } + + this._observedPropertiesMixin.pendingRender = true; + await Promise.resolve(); + try { + this.render(); + } finally { + this._observedPropertiesMixin.pendingRender = false; + } + } + + attributeChangedCallback(attr, oldValue, newValue) { + if (super.attributeChangedCallback) { + super.attributeChangedCallback(attr, oldValue, newValue); + } + if (oldValue === newValue) { + return; + } + this._invalidateFromObservedPropertiesMixin(); + } + }; +} |