diff --git a/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper.html b/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper.html new file mode 100644 index 0000000000..c495c948f3 --- /dev/null +++ b/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper.html @@ -0,0 +1,21 @@ + + + + + + + diff --git a/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper.js b/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper.js new file mode 100644 index 0000000000..301c12e48a --- /dev/null +++ b/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper.js @@ -0,0 +1,87 @@ +// 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]; + }; + + window.GrAttributeHelper = GrAttributeHelper; +})(window); diff --git a/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.html b/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.html new file mode 100644 index 0000000000..5dababead1 --- /dev/null +++ b/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.html @@ -0,0 +1,97 @@ + + + + +gr-attribute-helper + + + + + + + + + + + + + + + + + diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface.html index f73f731601..f6e2b64591 100644 --- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface.html +++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface.html @@ -17,6 +17,7 @@ limitations under the License. + diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html index 1236ca4065..ca0f3722aa 100644 --- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html +++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html @@ -318,6 +318,10 @@ limitations under the License. } }); + test('attributeHelper', () => { + assert.isOk(plugin.attributeHelper()); + }); + suite('test plugin with base url', () => { setup(() => { sandbox.stub(Gerrit.BaseUrlBehavior, 'getBaseUrl').returns('/r'); diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js index 97b67ae3c8..a631c2faa0 100644 --- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js +++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js @@ -158,6 +158,10 @@ return new GrThemeApi(this); }; + Plugin.prototype.attributeHelper = function(element) { + return new GrAttributeHelper(element); + }; + Plugin.prototype.getDomHook = function(endpointName, opt_options) { const hook = this._domHooks.getDomHook(endpointName); const moduleName = hook.getModuleName(); diff --git a/polygerrit-ui/app/test/index.html b/polygerrit-ui/app/test/index.html index e503812319..ed898f91d8 100644 --- a/polygerrit-ui/app/test/index.html +++ b/polygerrit-ui/app/test/index.html @@ -92,6 +92,7 @@ limitations under the License. 'diff/gr-selection-action-box/gr-selection-action-box_test.html', 'diff/gr-syntax-layer/gr-syntax-layer_test.html', 'diff/gr-syntax-lib-loader/gr-syntax-lib-loader_test.html', + 'plugins/gr-attribute-helper/gr-attribute-helper_test.html', 'plugins/gr-external-style/gr-external-style_test.html', 'plugins/gr-plugin-host/gr-plugin-host_test.html', 'settings/gr-account-info/gr-account-info_test.html',