/** * @license * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ (function(window) { 'use strict'; function GrAttributeHelper(element) { this.element = element; this._promises = {}; } GrAttributeHelper.prototype._getChangedEventName = function(name) { return name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase() + '-changed'; }; /** * Returns true if the property is defined on wrapped element. * @param {string} name * @return {boolean} */ GrAttributeHelper.prototype._elementHasProperty = function(name) { return this.element[name] !== undefined; }; GrAttributeHelper.prototype._reportValue = function(callback, value) { try { callback(value); } catch (e) { console.info(e); } }; /** * Binds callback to property updates. * * @param {string} name Property name. * @param {function(?)} callback * @return {function()} Unbind function. */ GrAttributeHelper.prototype.bind = function(name, callback) { const attributeChangedEventName = this._getChangedEventName(name); const changedHandler = e => this._reportValue(callback, e.detail.value); const unbind = () => this.element.removeEventListener( attributeChangedEventName, changedHandler); this.element.addEventListener( attributeChangedEventName, changedHandler); if (this._elementHasProperty(name)) { this._reportValue(callback, this.element[name]); } return unbind; }; /** * Get value of the property from wrapped object. Waits for the property * to be initialized if it isn't defined. * * @param {string} name Property name. * @return {!Promise<?>} */ GrAttributeHelper.prototype.get = function(name) { if (this._elementHasProperty(name)) { return Promise.resolve(this.element[name]); } if (!this._promises[name]) { let resolve; const promise = new Promise(r => resolve = r); const unbind = this.bind(name, value => { resolve(value); unbind(); }); this._promises[name] = promise; } return this._promises[name]; }; /** * Sets value and dispatches event to force notify. * * @param {string} name Property name. * @param {?} value */ GrAttributeHelper.prototype.set = function(name, value) { this.element[name] = value; this.element.dispatchEvent( new CustomEvent(this._getChangedEventName(name), {detail: {value}})); }; window.GrAttributeHelper = GrAttributeHelper; })(window);