UNPKG

@polymer/polymer

Version:

The Polymer library makes it easy to create your own web components. Give your element some markup and properties, and then use it on a site. Polymer provides features like dynamic templates and data binding to reduce the amount of boilerplate you need to

242 lines (216 loc) 8.39 kB
<!-- @license Copyright (c) 2017 The Polymer Project Authors. All rights reserved. This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as part of the polymer project is also subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt --> <link rel="import" href="../utils/boot.html"> <link rel="import" href="../utils/telemetry.html"> <link rel="import" href="../utils/mixin.html"> <link rel="import" href="../mixins/properties-changed.html"> <script> (function() { 'use strict'; /** * Creates a copy of `props` with each property normalized such that * upgraded it is an object with at least a type property { type: Type}. * * @param {Object} props Properties to normalize * @return {Object} Copy of input `props` with normalized properties that * are in the form {type: Type} * @private */ function normalizeProperties(props) { const output = {}; for (let p in props) { const o = props[p]; output[p] = (typeof o === 'function') ? {type: o} : o; } return output; } /** * Mixin that provides a minimal starting point to using the PropertiesChanged * mixin by providing a mechanism to declare properties in a static * getter (e.g. static get properties() { return { foo: String } }). Changes * are reported via the `_propertiesChanged` method. * * This mixin provides no specific support for rendering. Users are expected * to create a ShadowRoot and put content into it and update it in whatever * way makes sense. This can be done in reaction to properties changing by * implementing `_propertiesChanged`. * * @mixinFunction * @polymer * @appliesMixin Polymer.PropertiesChanged * @memberof Polymer * @summary Mixin that provides a minimal starting point for using * the PropertiesChanged mixin by providing a declarative `properties` object. */ Polymer.PropertiesMixin = Polymer.dedupingMixin(superClass => { /** * @constructor * @extends {superClass} * @implements {Polymer_PropertiesChanged} * @private */ const base = Polymer.PropertiesChanged(superClass); /** * Returns the super class constructor for the given class, if it is an * instance of the PropertiesMixin. * * @param {!PropertiesMixinConstructor} constructor PropertiesMixin constructor * @return {PropertiesMixinConstructor} Super class constructor */ function superPropertiesClass(constructor) { const superCtor = Object.getPrototypeOf(constructor); // Note, the `PropertiesMixin` class below only refers to the class // generated by this call to the mixin; the instanceof test only works // because the mixin is deduped and guaranteed only to apply once, hence // all constructors in a proto chain will see the same `PropertiesMixin` return (superCtor.prototype instanceof PropertiesMixin) ? /** @type {PropertiesMixinConstructor} */ (superCtor) : null; } /** * Returns a memoized version of the `properties` object for the * given class. Properties not in object format are converted to at * least {type}. * * @param {PropertiesMixinConstructor} constructor PropertiesMixin constructor * @return {Object} Memoized properties object */ function ownProperties(constructor) { if (!constructor.hasOwnProperty(JSCompiler_renameProperty('__ownProperties', constructor))) { let props = null; if (constructor.hasOwnProperty(JSCompiler_renameProperty('properties', constructor))) { const properties = constructor.properties; if (properties) { props = normalizeProperties(properties); } } constructor.__ownProperties = props; } return constructor.__ownProperties; } /** * @polymer * @mixinClass * @extends {base} * @implements {Polymer_PropertiesMixin} * @unrestricted */ class PropertiesMixin extends base { /** * Implements standard custom elements getter to observes the attributes * listed in `properties`. * @suppress {missingProperties} Interfaces in closure do not inherit statics, but classes do */ static get observedAttributes() { if (!this.hasOwnProperty('__observedAttributes')) { Polymer.telemetry.register(this.prototype); const props = this._properties; this.__observedAttributes = props ? Object.keys(props).map(p => this.attributeNameForProperty(p)) : []; } return this.__observedAttributes; } /** * Finalizes an element definition, including ensuring any super classes * are also finalized. This includes ensuring property * accessors exist on the element prototype. This method calls * `_finalizeClass` to finalize each constructor in the prototype chain. * @return {void} */ static finalize() { if (!this.hasOwnProperty(JSCompiler_renameProperty('__finalized', this))) { const superCtor = superPropertiesClass(/** @type {PropertiesMixinConstructor} */(this)); if (superCtor) { superCtor.finalize(); } this.__finalized = true; this._finalizeClass(); } } /** * Finalize an element class. This includes ensuring property * accessors exist on the element prototype. This method is called by * `finalize` and finalizes the class constructor. * * @protected */ static _finalizeClass() { const props = ownProperties(/** @type {PropertiesMixinConstructor} */(this)); if (props) { this.createProperties(props); } } /** * Returns a memoized version of all properties, including those inherited * from super classes. Properties not in object format are converted to * at least {type}. * * @return {Object} Object containing properties for this class * @protected */ static get _properties() { if (!this.hasOwnProperty( JSCompiler_renameProperty('__properties', this))) { const superCtor = superPropertiesClass(/** @type {PropertiesMixinConstructor} */(this)); this.__properties = Object.assign({}, superCtor && superCtor._properties, ownProperties(/** @type {PropertiesMixinConstructor} */(this))); } return this.__properties; } /** * Overrides `PropertiesChanged` method to return type specified in the * static `properties` object for the given property. * @param {string} name Name of property * @return {*} Type to which to deserialize attribute * * @protected */ static typeForProperty(name) { const info = this._properties[name]; return info && info.type; } /** * Overrides `PropertiesChanged` method and adds a call to * `finalize` which lazily configures the element's property accessors. * @override * @return {void} */ _initializeProperties() { Polymer.telemetry.instanceCount++; this.constructor.finalize(); super._initializeProperties(); } /** * Called when the element is added to a document. * Calls `_enableProperties` to turn on property system from * `PropertiesChanged`. * @suppress {missingProperties} Super may or may not implement the callback * @return {void} */ connectedCallback() { if (super.connectedCallback) { super.connectedCallback(); } this._enableProperties(); } /** * Called when the element is removed from a document * @suppress {missingProperties} Super may or may not implement the callback * @return {void} */ disconnectedCallback() { if (super.disconnectedCallback) { super.disconnectedCallback(); } } } return PropertiesMixin; }); })(); </script>