Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: appengine/config_service/ui/bower_components/polymer/lib/mixins/element-mixin.html

Issue 2923973003: Added base template for config ui. (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 <!--
2 @license
3 Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
4 This code may only be used under the BSD style license found at http://polymer.g ithub.io/LICENSE.txt
5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6 The complete set of contributors may be found at http://polymer.github.io/CONTRI BUTORS.txt
7 Code distributed by Google as part of the polymer project is also
8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN TS.txt
9 -->
10
11 <link rel="import" href="../utils/boot.html">
12 <link rel="import" href="../utils/mixin.html">
13 <link rel="import" href="../utils/case-map.html">
14 <link rel="import" href="../utils/style-gather.html">
15 <link rel="import" href="../utils/resolve-url.html">
16 <link rel="import" href="../elements/dom-module.html">
17 <link rel="import" href="property-effects.html">
18
19 <script>
20 (function() {
21 'use strict';
22 /**
23 * @typedef Object<string, {
24 * value: *,
25 * type: (Function | undefined),
26 * readOnly: (boolean | undefined),
27 * computed: (string | undefined),
28 * reflectToAttribute: (boolean | undefined),
29 * notify: (boolean | undefined),
30 * observer: (string | undefined)
31 * }>)
32 */
33 let PolymerElementProperties; // eslint-disable-line no-unused-vars
34
35 /** @record */
36 let PolymerElementConstructor = function(){}; // eslint-disable-line no-unused -vars
37 /** @type {(string | undefined)} */
38 PolymerElementConstructor.is;
39 /** @type {(string | undefined)} */
40 PolymerElementConstructor.extends;
41 /** @type {(!PolymerElementProperties | undefined)} */
42 PolymerElementConstructor.properties;
43 /** @type {(!Array<string> | undefined)} */
44 PolymerElementConstructor.observers;
45 /** @type {(!HTMLTemplateElement | string | undefined)} */
46 PolymerElementConstructor.template;
47
48 /**
49 * Element class mixin that provides the core API for Polymer's meta-programmi ng
50 * features including template stamping, data-binding, attribute deserializati on,
51 * and property change observation.
52 *
53 * Subclassers may provide the following static getters to return metadata
54 * used to configure Polymer's features for the class:
55 *
56 * - `static get is()`: When the template is provided via a `dom-module`,
57 * users should return the `dom-module` id from a static `is` getter. If
58 * no template is needed or the template is provided directly via the
59 * `template` getter, there is no need to define `is` for the element.
60 *
61 * - `static get template()`: Users may provide the template directly (as
62 * opposed to via `dom-module`) by implementing a static `template` getter.
63 * The getter may return an `HTMLTemplateElement` or a string, which will
64 * automatically be parsed into a template.
65 *
66 * - `static get properties()`: Should return an object describing
67 * property-related metadata used by Polymer features (key: property name
68 * value: object containing property metadata). Valid keys in per-property
69 * metadata include:
70 * - `type` (String|Number|Object|Array|...): Used by
71 * `attributeChangedCallback` to determine how string-based attributes
72 * are deserialized to JavaScript property values.
73 * - `notify` (boolean): Causes a change in the property to fire a
74 * non-bubbling event called `<property>-changed`. Elements that have
75 * enabled two-way binding to the property use this event to observe chang es.
76 * - `readOnly` (boolean): Creates a getter for the property, but no setter.
77 * To set a read-only property, use the private setter method
78 * `_setProperty(property, value)`.
79 * - `observer` (string): Observer method name that will be called when
80 * the property changes. The arguments of the method are
81 * `(value, previousValue)`.
82 * - `computed` (string): String describing method and dependent properties
83 * for computing the value of this property (e.g. `'computeFoo(bar, zot)'` ).
84 * Computed properties are read-only by default and can only be changed
85 * via the return value of the computing method.
86 *
87 * - `static get observers()`: Array of strings describing multi-property
88 * observer methods and their dependent properties (e.g.
89 * `'observeABC(a, b, c)'`).
90 *
91 * The base class provides default implementations for the following standard
92 * custom element lifecycle callbacks; users may override these, but should
93 * call the super method to ensure
94 * - `constructor`: Run when the element is created or upgraded
95 * - `connectedCallback`: Run each time the element is connected to the
96 * document
97 * - `disconnectedCallback`: Run each time the element is disconnected from
98 * the document
99 * - `attributeChangedCallback`: Run each time an attribute in
100 * `observedAttributes` is set or removed (note: this element's default
101 * `observedAttributes` implementation will automatically return an array
102 * of dash-cased attributes based on `properties`)
103 *
104 * @polymerMixin
105 * @mixes Polymer.PropertyEffects
106 * @memberof Polymer
107 * @property rootPath {string} Set to the value of `Polymer.rootPath`,
108 * which defaults to the main document path
109 * @property importPath {string} Set to the value of the class's static
110 * `importPath` property, which defaults to the path of this element's
111 * `dom-module` (when `is` is used), but can be overridden for other
112 * import strategies.
113 * @summary Element class mixin that provides the core API for Polymer's
114 * meta-programming features.
115 */
116 Polymer.ElementMixin = Polymer.dedupingMixin(base => {
117
118 /**
119 * @constructor
120 * @extends {base}
121 * @implements {Polymer_PropertyEffects}
122 */
123 const polymerElementBase = Polymer.PropertyEffects(base);
124
125 let caseMap = Polymer.CaseMap;
126
127 /**
128 * Returns the `properties` object specifically on `klass`. Use for:
129 * (1) super chain mixes togther to make `propertiesForClass` which is
130 * then used to make `observedAttributes`.
131 * (2) properties effects and observers are created from it at `finalize` ti me.
132 *
133 * @param {HTMLElement} klass Element class
134 * @return {Object} Object containing own properties for this class
135 * @private
136 */
137 function ownPropertiesForClass(klass) {
138 if (!klass.hasOwnProperty(
139 JSCompiler_renameProperty('__ownProperties', klass))) {
140 klass.__ownProperties =
141 klass.hasOwnProperty(JSCompiler_renameProperty('properties', klass)) ?
142 klass.properties : {};
143 }
144 return klass.__ownProperties;
145 }
146
147 /**
148 * Returns the `observers` array specifically on `klass`. Use for
149 * setting up observers.
150 *
151 * @param {HTMLElement} klass Element class
152 * @return {Array} Array containing own observers for this class
153 * @private
154 */
155 function ownObserversForClass(klass) {
156 if (!klass.hasOwnProperty(
157 JSCompiler_renameProperty('__ownObservers', klass))) {
158 klass.__ownObservers =
159 klass.hasOwnProperty(JSCompiler_renameProperty('observers', klass)) ?
160 klass.observers : [];
161 }
162 return klass.__ownObservers;
163 }
164
165 /**
166 * Mixes `props` into `flattenedProps` but upgrades shorthand type
167 * syntax to { type: Type}.
168 *
169 * @param {Object} flattenedProps Bag to collect flattened properties into
170 * @param {Object} props Bag of properties to add to `flattenedProps`
171 * @return {Objecg} The input `flattenedProps` bag
172 * @private
173 */
174 function flattenProperties(flattenedProps, props) {
175 for (let p in props) {
176 let o = props[p];
177 if (typeof o == 'function') {
178 o = { type: o };
179 }
180 flattenedProps[p] = o;
181 }
182 return flattenedProps;
183 }
184
185 /**
186 * Returns a flattened list of properties mixed together from the chain of a ll
187 * constructor's `config.properties`. This list is used to create
188 * (1) observedAttributes,
189 * (2) class property default values
190 *
191 * @param {HTMLElement} klass Element class
192 * @return {PolymerElementProperties} Flattened properties for this class
193 * @private
194 */
195 function propertiesForClass(klass) {
196 if (!klass.hasOwnProperty(
197 JSCompiler_renameProperty('__classProperties', klass))) {
198 klass.__classProperties =
199 flattenProperties({}, ownPropertiesForClass(klass));
200 let superCtor = Object.getPrototypeOf(klass.prototype).constructor;
201 if (superCtor.prototype instanceof PolymerElement) {
202 klass.__classProperties = Object.assign(
203 Object.create(propertiesForClass(superCtor)),
204 klass.__classProperties);
205 }
206 }
207 return klass.__classProperties;
208 }
209
210 /**
211 * Returns a list of properties with default values.
212 * This list is created as an optimization since it is a subset of
213 * the list returned from `propertiesForClass`.
214 * This list is used in `_initializeProperties` to set property defaults.
215 *
216 * @param {HTMLElement} klass Element class
217 * @return {PolymerElementProperties} Flattened properties for this class
218 * that have default values
219 * @private
220 */
221 function propertyDefaultsForClass(klass) {
222 if (!klass.hasOwnProperty(
223 JSCompiler_renameProperty('__classPropertyDefaults', klass))) {
224 klass.__classPropertyDefaults = null;
225 let props = propertiesForClass(klass);
226 for (let p in props) {
227 let info = props[p];
228 if ('value' in info) {
229 klass.__classPropertyDefaults = klass.__classPropertyDefaults || {};
230 klass.__classPropertyDefaults[p] = info;
231 }
232 }
233 }
234 return klass.__classPropertyDefaults;
235 }
236
237 /**
238 * Returns true if a `klass` has finalized. Called in `ElementClass.finalize ()`
239 * @param {HTMLElement} klass Element class
240 * @return {boolean} True if all metaprogramming for this class has been
241 * completed
242 * @private
243 */
244 function hasClassFinalized(klass) {
245 return klass.hasOwnProperty(JSCompiler_renameProperty('__finalized', klass ));
246 }
247
248 /**
249 * Called by `ElementClass.finalize()`. Ensures this `klass` and
250 * *all superclasses* are finalized by traversing the prototype chain
251 * and calling `klass.finalize()`.
252 *
253 * @param {HTMLElement} klass Element class
254 * @private
255 */
256 function finalizeClassAndSuper(klass) {
257 let proto = klass.prototype;
258 let superCtor = Object.getPrototypeOf(proto).constructor;
259 if (superCtor.prototype instanceof PolymerElement) {
260 superCtor.finalize();
261 }
262 finalizeClass(klass);
263 }
264
265 /**
266 * Configures a `klass` based on a staic `klass.config` object and
267 * a `template`. This includes creating accessors and effects
268 * for properties in `config` and the `template` as well as preparing the
269 * `template` for stamping.
270 *
271 * @param {HTMLElement} klass Element class
272 * @private
273 */
274 function finalizeClass(klass) {
275 klass.__finalized = true;
276 let proto = klass.prototype;
277 if (klass.hasOwnProperty(
278 JSCompiler_renameProperty('is', klass)) && klass.is) {
279 Polymer.telemetry.register(proto);
280 }
281 let props = ownPropertiesForClass(klass);
282 if (props) {
283 finalizeProperties(proto, props);
284 }
285 let observers = ownObserversForClass(klass);
286 if (observers) {
287 finalizeObservers(proto, observers, props);
288 }
289 // note: create "working" template that is finalized at instance time
290 let template = klass.template;
291 if (template) {
292 if (typeof template === 'string') {
293 let t = document.createElement('template');
294 t.innerHTML = template;
295 template = t;
296 } else {
297 template = template.cloneNode(true);
298 }
299 proto._template = template;
300 }
301 }
302
303 /**
304 * Configures a `proto` based on a `properties` object.
305 * Leverages `PropertyEffects` to create property accessors and effects
306 * supporting, observers, reflecting to attributes, change notification,
307 * computed properties, and read only properties.
308 * @param {HTMLElement} proto Element class prototype to add accessors
309 * and effects to
310 * @param {Object} properties Flattened bag of property descriptors for
311 * this class
312 * @private
313 */
314 function finalizeProperties(proto, properties) {
315 for (let p in properties) {
316 createPropertyFromConfig(proto, p, properties[p], properties);
317 }
318 }
319
320 /**
321 * Configures a `proto` based on a `observers` array.
322 * Leverages `PropertyEffects` to create observers.
323 * @param {HTMLElement} proto Element class prototype to add accessors
324 * and effects to
325 * @param {Object} observers Flattened array of observer descriptors for
326 * this class
327 * @param {Object} dynamicFns Object containing keys for any properties
328 * that are functions and should trigger the effect when the function
329 * reference is changed
330 * @private
331 */
332 function finalizeObservers(proto, observers, dynamicFns) {
333 for (let i=0; i < observers.length; i++) {
334 proto._createMethodObserver(observers[i], dynamicFns);
335 }
336 }
337
338 /**
339 * Creates effects for a property.
340 *
341 * Note, once a property has been set to
342 * `readOnly`, `computed`, `reflectToAttribute`, or `notify`
343 * these values may not be changed. For example, a subclass cannot
344 * alter these settings. However, additional `observers` may be added
345 * by subclasses.
346 *
347 * The info object should may contain property metadata as follows:
348 *
349 * * `type`: {function} type to which an attribute matching the property
350 * is deserialized. Note the property is camel-cased from a dash-cased
351 * attribute. For example, 'foo-bar' attribute is dersialized to a
352 * property named 'fooBar'.
353 *
354 * * `readOnly`: {boolean} creates a readOnly property and
355 * makes a private setter for the private of the form '_setFoo' for a
356 * property 'foo',
357 *
358 * * `computed`: {string} creates a computed property. A computed property
359 * also automatically is set to `readOnly: true`. The value is calculated
360 * by running a method and arguments parsed from the given string. For
361 * example 'compute(foo)' will compute a given property when the
362 * 'foo' property changes by executing the 'compute' method. This method
363 * must return the computed value.
364 *
365 * * `reflectToAttriute`: {boolean} If true, the property value is reflected
366 * to an attribute of the same name. Note, the attribute is dash-cased
367 * so a property named 'fooBar' is reflected as 'foo-bar'.
368 *
369 * * `notify`: {boolean} sends a non-bubbling notification event when
370 * the property changes. For example, a property named 'foo' sends an
371 * event named 'foo-changed' with `event.detail` set to the value of
372 * the property.
373 *
374 * * observer: {string} name of a method that runs when the property
375 * changes. The arguments of the method are (value, previousValue).
376 *
377 * Note: Users may want control over modifying property
378 * effects via subclassing. For example, a user might want to make a
379 * reflectToAttribute property not do so in a subclass. We've chosen to
380 * disable this because it leads to additional complication.
381 * For example, a readOnly effect generates a special setter. If a subclass
382 * disables the effect, the setter would fail unexpectedly.
383 * Based on feedback, we may want to try to make effects more malleable
384 * and/or provide an advanced api for manipulating them.
385 * Also consider adding warnings when an effect cannot be changed.
386 *
387 * @param {HTMLElement} proto Element class prototype to add accessors
388 * and effects to
389 * @param {string} name Name of the property.
390 * @param {Object} info Info object from which to create property effects.
391 * Supported keys:
392 * @param {Object} allProps Flattened map of all properties defined in this
393 * element (including inherited properties)
394 * @private
395 */
396 function createPropertyFromConfig(proto, name, info, allProps) {
397 // computed forces readOnly...
398 if (info.computed) {
399 info.readOnly = true;
400 }
401 // Note, since all computed properties are readOnly, this prevents
402 // adding additional computed property effects (which leads to a confusing
403 // setup where multiple triggers for setting a property)
404 // While we do have `hasComputedEffect` this is set on the property's
405 // dependencies rather than itself.
406 if (info.computed && !proto._hasReadOnlyEffect(name)) {
407 proto._createComputedProperty(name, info.computed, allProps);
408 }
409 if (info.readOnly && !proto._hasReadOnlyEffect(name)) {
410 proto._createReadOnlyProperty(name, !info.computed);
411 }
412 if (info.reflectToAttribute && !proto._hasReflectEffect(name)) {
413 proto._createReflectedProperty(name);
414 }
415 if (info.notify && !proto._hasNotifyEffect(name)) {
416 proto._createNotifyingProperty(name);
417 }
418 // always add observer
419 if (info.observer) {
420 proto._createPropertyObserver(name, info.observer, allProps[info.observe r]);
421 }
422 }
423
424 /**
425 * Configures an element `proto` to function with a given `template`.
426 * The element name `is` and extends `ext` must be specified for ShadyCSS
427 * style scoping.
428 *
429 * @param {HTMLElement} proto Element class prototype to add accessors
430 * and effects to
431 * @param {HTMLTemplateElement} template Template to process and bind
432 * @param {string} baseURI URL against which to resolve urls in
433 * style element cssText
434 * @param {string} is Tag name (or type extension name) for this element
435 * @param {string=} ext For type extensions, the tag name that was extended
436 * @private
437 */
438 function finalizeTemplate(proto, template, baseURI, is, ext) {
439 // support `include="module-name"`
440 let cssText =
441 Polymer.StyleGather.cssFromTemplate(template, baseURI) +
442 Polymer.StyleGather.cssFromModuleImports(is);
443 if (cssText) {
444 let style = document.createElement('style');
445 style.textContent = cssText;
446 template.content.insertBefore(style, template.content.firstChild);
447 }
448 if (window.ShadyCSS) {
449 window.ShadyCSS.prepareTemplate(template, is, ext);
450 }
451 proto._bindTemplate(template);
452 }
453
454 /**
455 * @polymerMixinClass
456 * @unrestricted
457 * @implements {Polymer_ElementMixin}
458 */
459 class PolymerElement extends polymerElementBase {
460
461 /**
462 * Standard Custom Elements V1 API. The default implementation returns
463 * a list of dash-cased attributes based on a flattening of all properties
464 * declared in `static get properties()` for this element and any
465 * superclasses.
466 *
467 * @return {Array} Observed attribute list
468 */
469 static get observedAttributes() {
470 if (!this.hasOwnProperty(JSCompiler_renameProperty('__observedAttributes ', this))) {
471 let list = [];
472 let properties = propertiesForClass(this);
473 for (let prop in properties) {
474 list.push(Polymer.CaseMap.camelToDashCase(prop));
475 }
476 this.__observedAttributes = list;
477 }
478 return this.__observedAttributes;
479 }
480
481 /**
482 * Called automatically when the first element instance is created to
483 * ensure that class finalization work has been completed.
484 * May be called by users to eagerly perform class finalization work
485 * prior to the creation of the first element instance.
486 *
487 * Class finalization work generally includes meta-programming such as
488 * creating property accessors and any property effect metadata needed for
489 * the features used.
490 *
491 * @public
492 */
493 static finalize() {
494 if (!hasClassFinalized(this)) {
495 finalizeClassAndSuper(this);
496 }
497 }
498
499 /**
500 * Returns the template that will be stamped into this element's shadow ro ot.
501 *
502 * If a `static get is()` getter is defined, the default implementation
503 * will return the first `<template>` in a `dom-module` whose `id`
504 * matches this element's `is`.
505 *
506 * Users may override this getter to return an arbitrary template
507 * (in which case the `is` getter is unnecessary). The template returned
508 * may be either an `HTMLTemplateElement` or a string that will be
509 * automatically parsed into a template.
510 *
511 * Note that when subclassing, if the super class overrode the default
512 * implementation and the subclass would like to provide an alternate
513 * template via a `dom-module`, it should override this getter and
514 * return `Polymer.DomModule.import(this.is, 'template')`.
515 *
516 * If a subclass would like to modify the super class template, it should
517 * clone it rather than modify it in place. If the getter does expensive
518 * work such as cloning/modifying a template, it should memoize the
519 * template for maximum performance:
520 *
521 * let memoizedTemplate;
522 * class MySubClass extends MySuperClass {
523 * static get template() {
524 * if (!memoizedTemplate) {
525 * memoizedTemplate = super.template.cloneNode(true);
526 * let subContent = document.createElement('div');
527 * subContent.textContent = 'This came from MySubClass';
528 * memoizedTemplate.content.appendChild(subContent);
529 * }
530 * return memoizedTemplate;
531 * }
532 * }
533 *
534 * @return {HTMLTemplateElement|string} Template to be stamped
535 */
536 static get template() {
537 if (!this.hasOwnProperty(JSCompiler_renameProperty('_template', this))) {
538 this._template = Polymer.DomModule.import(this.is, 'template') ||
539 // note: implemented so a subclass can retrieve the super
540 // template; call the super impl this way so that `this` points
541 // to the superclass.
542 Object.getPrototypeOf(this.prototype).constructor.template;
543 }
544 return this._template;
545 }
546
547 /**
548 * Path matching the url from which the element was imported.
549 * This path is used to resolve url's in template style cssText.
550 * The `importPath` property is also set on element instances and can be
551 * used to create bindings relative to the import path.
552 * Defaults to the path matching the url containing a `dom-module` element
553 * matching this element's static `is` property.
554 * Note, this path should contain a trailing `/`.
555 *
556 * @return {string} The import path for this element class
557 */
558 static get importPath() {
559 if (!this.hasOwnProperty(JSCompiler_renameProperty('_importPath', this)) ) {
560 const module = Polymer.DomModule.import(this.is);
561 this._importPath = module ? module.assetpath : '' ||
562 Object.getPrototypeOf(this.prototype).constructor.importPath;
563 }
564 return this._importPath;
565 }
566
567 /**
568 * Overrides the default `Polymer.PropertyAccessors` to ensure class
569 * metaprogramming related to property accessors and effects has
570 * completed (calls `finalize`).
571 *
572 * It also initializes any property defaults provided via `value` in
573 * `properties` metadata.
574 *
575 * @override
576 */
577 _initializeProperties() {
578 Polymer.telemetry.instanceCount++;
579 this.constructor.finalize();
580 const importPath = this.constructor.importPath;
581 // note: finalize template when we have access to `localName` to
582 // avoid dependence on `is` for polyfilling styling.
583 if (this._template && !this._template.__polymerFinalized) {
584 this._template.__polymerFinalized = true;
585 const baseURI =
586 importPath ? Polymer.ResolveUrl.resolveUrl(importPath) : '';
587 finalizeTemplate(this.__proto__, this._template, baseURI,
588 this.localName);
589 }
590 super._initializeProperties();
591 // set path defaults
592 this.rootPath = Polymer.rootPath;
593 this.importPath = importPath;
594 // apply property defaults...
595 let p$ = propertyDefaultsForClass(this.constructor);
596 if (!p$) {
597 return;
598 }
599 for (let p in p$) {
600 let info = p$[p];
601 // Don't set default value if there is already an own property, which
602 // happens when a `properties` property with default but no effects ha d
603 // a property set (e.g. bound) by its host before upgrade
604 if (!this.hasOwnProperty(p)) {
605 let value = typeof info.value == 'function' ?
606 info.value.call(this) :
607 info.value;
608 // Set via `_setProperty` if there is an accessor, to enable
609 // initializing readOnly property defaults
610 if (this._hasAccessor(p)) {
611 this._setPendingProperty(p, value, true);
612 } else {
613 this[p] = value;
614 }
615 }
616 }
617 }
618
619 /**
620 * Provides a default implementation of the standard Custom Elements
621 * `connectedCallback`.
622 *
623 * The default implementation enables the property effects system and
624 * flushes any pending properties, and updates shimmed CSS properties
625 * when using the ShadyCSS scoping/custom properties polyfill.
626 *
627 * @override
628 */
629 connectedCallback() {
630 if (window.ShadyCSS && this._template) {
631 window.ShadyCSS.styleElement(this);
632 }
633 this._enableProperties();
634 }
635
636 /**
637 * Provides a default implementation of the standard Custom Elements
638 * `disconnectedCallback`.
639 *
640 * @override
641 */
642 disconnectedCallback() {}
643
644 /**
645 * Stamps the element template.
646 *
647 * @override
648 */
649 ready() {
650 if (this._template) {
651 this.root = this._stampTemplate(this._template);
652 this.$ = this.root.$;
653 }
654 super.ready();
655 }
656
657 /**
658 * Implements `PropertyEffects`'s `_readyClients` call. Attaches
659 * element dom by calling `_attachDom` with the dom stamped from the
660 * element's template via `_stampTemplate`. Note that this allows
661 * client dom to be attached to the element prior to any observers
662 * running.
663 *
664 * @override
665 */
666 _readyClients() {
667 if (this._template) {
668 this.root = this._attachDom(this.root);
669 }
670 // The super._readyClients here sets the clients initialized flag.
671 // We must wait to do this until after client dom is created/attached
672 // so that this flag can be checked to prevent notifications fired
673 // during this process from being handled before clients are ready.
674 super._readyClients();
675 }
676
677
678 /**
679 * Attaches an element's stamped dom to itself. By default,
680 * this method creates a `shadowRoot` and adds the dom to it.
681 * However, this method may be overridden to allow an element
682 * to put its dom in another location.
683 *
684 * @throws {Error}
685 * @suppress {missingReturn}
686 * @param {NodeList} dom to attach to the element.
687 * @return {Node} node to which the dom has been attached.
688 */
689 _attachDom(dom) {
690 if (this.attachShadow) {
691 if (dom) {
692 if (!this.shadowRoot) {
693 this.attachShadow({mode: 'open'});
694 }
695 this.shadowRoot.appendChild(dom);
696 return this.shadowRoot;
697 }
698 } else {
699 throw new Error('ShadowDOM not available. ' +
700 // TODO(sorvell): move to compile-time conditional when supported
701 'Polymer.Element can create dom as children instead of in ' +
702 'ShadowDOM by setting `this.root = this;\` before \`ready\`.');
703 }
704 }
705
706 /**
707 * Provides a default implementation of the standard Custom Elements
708 * `attributeChangedCallback`.
709 *
710 * By default, attributes declared in `properties` metadata are
711 * deserialized using their `type` information to properties of the
712 * same name. "Dash-cased" attributes are deserialzed to "camelCase"
713 * properties.
714 *
715 * @override
716 */
717 attributeChangedCallback(name, old, value) {
718 if (old !== value) {
719 let property = caseMap.dashToCamelCase(name);
720 let type = propertiesForClass(this.constructor)[property].type;
721 if (!this._hasReadOnlyEffect(property)) {
722 this._attributeToProperty(name, value, type);
723 }
724 }
725 }
726
727 /**
728 * When using the ShadyCSS scoping and custom property shim, causes all
729 * shimmed styles in this element (and its subtree) to be updated
730 * based on current custom property values.
731 *
732 * The optional parameter overrides inline custom property styles with an
733 * object of properties where the keys are CSS properties, and the values
734 * are strings.
735 *
736 * Example: `this.updateStyles({'--color': 'blue'})`
737 *
738 * These properties are retained unless a value of `null` is set.
739 *
740 * @param {Object=} properties Bag of custom property key/values to
741 * apply to this element.
742 */
743 updateStyles(properties) {
744 if (window.ShadyCSS) {
745 window.ShadyCSS.styleSubtree(this, properties);
746 }
747 }
748
749 /**
750 * Rewrites a given URL relative to a base URL. The base URL defaults to
751 * the original location of the document containing the `dom-module` for
752 * this element. This method will return the same URL before and after
753 * bundling.
754 *
755 * @param {string} url URL to resolve.
756 * @param {string=} base Optional base URL to resolve against, defaults
757 * to the element's `importPath`
758 * @return {string} Rewritten URL relative to base
759 */
760 resolveUrl(url, base) {
761 if (!base && this.importPath) {
762 base = Polymer.ResolveUrl.resolveUrl(this.importPath);
763 }
764 return Polymer.ResolveUrl.resolveUrl(url, base);
765 }
766
767 /**
768 * Overrides `PropertyAccessors` to add map of dynamic functions on
769 * template info, for consumption by `PropertyEffects` template binding
770 * code. This map determines which method templates should have accessors
771 * created for them.
772 *
773 * @override
774 */
775 static _parseTemplateContent(template, templateInfo, nodeInfo) {
776 templateInfo.dynamicFns = templateInfo.dynamicFns || propertiesForClass( this);
777 return super._parseTemplateContent(template, templateInfo, nodeInfo);
778 }
779
780 }
781
782 return PolymerElement;
783 });
784
785 /**
786 * Provides basic tracking of element definitions (registrations) and
787 * instance counts.
788 *
789 * @namespace
790 * @summary Provides basic tracking of element definitions (registrations) and
791 * instance counts.
792 */
793 Polymer.telemetry = {
794 /**
795 * Total number of Polymer element instances created.
796 * @type {number}
797 */
798 instanceCount: 0,
799 /**
800 * Array of Polymer element classes that have been finalized.
801 * @type {Array<Polymer.Element>}
802 */
803 registrations: [],
804 /**
805 * @param {HTMLElement} prototype Element prototype to log
806 * @private
807 */
808 _regLog: function(prototype) {
809 console.log('[' + prototype.is + ']: registered')
810 },
811 /**
812 * Registers a class prototype for telemetry purposes.
813 * @param {HTMLElement} prototype Element prototype to register
814 * @protected
815 */
816 register: function(prototype) {
817 this.registrations.push(prototype);
818 Polymer.log && this._regLog(prototype);
819 },
820 /**
821 * Logs all elements registered with an `is` to the console.
822 * @public
823 */
824 dumpRegistrations: function() {
825 this.registrations.forEach(this._regLog);
826 }
827 };
828
829 /**
830 * When using the ShadyCSS scoping and custom property shim, causes all
831 * shimmed `styles` (via `custom-style`) in the document (and its subtree)
832 * to be updated based on current custom property values.
833 *
834 * The optional parameter overrides inline custom property styles with an
835 * object of properties where the keys are CSS properties, and the values
836 * are strings.
837 *
838 * Example: `Polymer.updateStyles({'--color': 'blue'})`
839 *
840 * These properties are retained unless a value of `null` is set.
841 *
842 * @param {Object=} props Bag of custom property key/values to
843 * apply to the document.
844 */
845 Polymer.updateStyles = function(props) {
846 if (window.ShadyCSS) {
847 window.ShadyCSS.styleDocument(props);
848 }
849 };
850
851 /**
852 * Globally settable property that is automatically assigned to
853 * `Polymer.ElementMixin` instances, useful for binding in templates to
854 * make URL's relative to an application's root. Defaults to the main
855 * document URL, but can be overridden by users. It may be useful to set
856 * `Polymer.rootPath` to provide a stable application mount path when
857 * using client side routing.
858 *
859 * @memberof Polymer
860 */
861 Polymer.rootPath = Polymer.rootPath ||
862 Polymer.ResolveUrl.pathFromUrl(document.baseURI || window.location.href);
863
864 })();
865 </script>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698