Add @polymerMixin and @memberof annotations. Misc doc cleanup.

* `TODOC` indicates docs that need further elaboration/review.
This commit is contained in:
Kevin Schaaf 2017-02-21 23:23:40 -08:00
parent 25f5a55346
commit b9f5b4c271
16 changed files with 486 additions and 259 deletions

View File

@ -8,60 +8,6 @@ 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
-->
<!--
Keeping structured data in sync requires that Polymer understand the path
associations of data being bound. The `array-selector` element ensures path
linkage when selecting specific items from an array (either single or multiple).
The `items` property accepts an array of user data, and via the `select(item)`
and `deselect(item)` API, updates the `selected` property which may be bound to
other parts of the application, and any changes to sub-fields of `selected`
item(s) will be kept in sync with items in the `items` array. When `multi`
is false, `selected` is a property representing the last selected item. When
`multi` is true, `selected` is an array of multiply selected items.
```html
<dom-module id="employee-list">
<template>
<div> Employee list: </div>
<template is="dom-repeat" id="employeeList" items="{{employees}}">
<div>First name: <span>{{item.first}}</span></div>
<div>Last name: <span>{{item.last}}</span></div>
<button on-click="toggleSelection">Select</button>
</template>
<array-selector id="selector" items="{{employees}}" selected="{{selected}}" multi toggle></array-selector>
<div> Selected employees: </div>
<template is="dom-repeat" items="{{selected}}">
<div>First name: <span>{{item.first}}</span></div>
<div>Last name: <span>{{item.last}}</span></div>
</template>
</template>
<script>
Polymer({
is: 'employee-list',
ready() {
this.employees = [
{first: 'Bob', last: 'Smith'},
{first: 'Sally', last: 'Johnson'},
...
];
},
toggleSelection(e) {
var item = this.$.employeeList.itemForElement(e.target);
this.$.selector.select(item);
}
});
</script>
</dom-module>
```
-->
<link rel="import" href="../../polymer-element.html">
<link rel="import" href="../utils/mixin.html">
<link rel="import" href="../utils/array-splice.html">
@ -69,6 +15,23 @@ is false, `selected` is a property representing the last selected item. When
<script>
(function() {
/**
* Element mixin for recording dynamic associations between item paths in a
* master `items` array and a `selected` array such that path changes to the
* master array (at the host) element or elsewhere via data-binding) are
* correctly propagated to items in the selected array and vice-versa.
*
* The `items` property accepts an array of user data, and via the
* `select(item)` and `deselect(item)` API, updates the `selected` property
* which may be bound to other parts of the application, and any changes to
* sub-fields of `selected` item(s) will be kept in sync with items in the
* `items` array. When `multi` is false, `selected` is a property
* representing the last selected item. When `multi` is true, `selected`
* is an array of multiply selected items.
*
* @polymerMixin
* @memberof Polymer
*/
let ArraySelectorMixin = Polymer.dedupingMixin(superClass => {
return class extends superClass {
@ -361,9 +324,76 @@ is false, `selected` is a property representing the last selected item. When
// export mixin
Polymer.ArraySelectorMixin = ArraySelectorMixin;
// define element class & export
const ArraySelector = ArraySelectorMixin(Polymer.Element);
customElements.define('array-selector', ArraySelector);
/**
* Element implementing the `Polymer.ArraySelector` mixin, which records
* dynamic associations between item paths in a master `items` array and a
* `selected` array such that path changes to the master array (at the host)
* element or elsewhere via data-binding) are correctly propagated to items
* in the selected array and vice-versa.
*
* The `items` property accepts an array of user data, and via the
* `select(item)` and `deselect(item)` API, updates the `selected` property
* which may be bound to other parts of the application, and any changes to
* sub-fields of `selected` item(s) will be kept in sync with items in the
* `items` array. When `multi` is false, `selected` is a property
* representing the last selected item. When `multi` is true, `selected`
* is an array of multiply selected items.
*
* Example:
*
* ```html
* <dom-module id="employee-list">
*
* <template>
*
* <div> Employee list: </div>
* <template is="dom-repeat" id="employeeList" items="{{employees}}">
* <div>First name: <span>{{item.first}}</span></div>
* <div>Last name: <span>{{item.last}}</span></div>
* <button on-click="toggleSelection">Select</button>
* </template>
*
* <array-selector id="selector" items="{{employees}}" selected="{{selected}}" multi toggle></array-selector>
*
* <div> Selected employees: </div>
* <template is="dom-repeat" items="{{selected}}">
* <div>First name: <span>{{item.first}}</span></div>
* <div>Last name: <span>{{item.last}}</span></div>
* </template>
*
* </template>
*
* </dom-module>
* ```
*
* ```js
* Polymer({
* is: 'employee-list',
* ready() {
* this.employees = [
* {first: 'Bob', last: 'Smith'},
* {first: 'Sally', last: 'Johnson'},
* ...
* ];
* },
* toggleSelection(e) {
* var item = this.$.employeeList.itemForElement(e.target);
* this.$.selector.select(item);
* }
* });
* ```
*
* @polymerElement
* @extends Polymer.Element
* @mixes Polymer.ArraySelectorMixin
* @memberof Polymer
*/
const ArraySelector = class extends ArraySelectorMixin(Polymer.Element) {
// Not needed to find template; can be removed once the analyzer
// can find the tag name from customElements.define call
static get is() { return 'array-selector' }
}
customElements.define(ArraySelector.is, ArraySelector);
Polymer.ArraySelector = ArraySelector;
})();

View File

@ -17,6 +17,23 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
const CustomStyleInterface = window.ShadyCSS.CustomStyleInterface;
/**
* Custom element for defining styles in the main document that can take
* advantage of several special features of Polymer's styling system:
*
* - Document styles defined in a custom-style are shimmed to ensure they
* do not leak into local DOM when running on browsers without native
* Shadow DOM.
* - Custom properties used by Polymer's shim for cross-scope styling may
* be defined in an custom-style. Use the :root selector to define custom
* properties that apply to all custom elements.
*
* To use, simply wrap an inline `<style>` tag in the main document whose
* CSS uses these features with a `<custom-style>` element.
*
* @extends HTMLElement
* @memberof Polymer
*/
class CustomStyle extends HTMLElement {
constructor() {
super();

View File

@ -15,9 +15,23 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
(function() {
const mixin = Polymer.PropertyEffects(HTMLElement);
const domBindBase = Polymer.PropertyEffects(HTMLElement);
class DomBind extends mixin {
/**
* Custom element to allow using Polymer's template features (data binding,
* declarative event listeners, etc.) in the main document without defining
* a new custom element.
*
* `<template>` tags utilizing bindings may be wrapped with the `<dom-bind>`
* element, which will immediately stamp the wrapped template into the main
* document and bind elements to the `dom-bind` element itself as the
* binding scope.
*
* @extends HTMLElement
* @mixes Polymer.PropertyEffects
* @memberof Polymer
*/
class DomBind extends domBindBase {
connectedCallback() {
this.render();

View File

@ -18,7 +18,10 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
(function() {
/**
* Stamps the template iff the `if` property is truthy.
* The `<dom-if>` element will stamp a light-dom `<template>` child when
* the `if` property becomes truthy, and the template can use Polymer
* data-binding and declarative event features when used in the context of
* a Polymer element's template.
*
* When `if` becomes falsey, the stamped content is hidden but not
* removed from dom. When `if` subsequently becomes truthy again, the content
@ -28,9 +31,17 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
*
* Set the `restamp` property to true to force the stamped content to be
* created / destroyed when the `if` condition changes.
*
* @polymerElement
* @extends Polymer.Element
* @memberof Polymer
*/
class DomIf extends Polymer.Element {
// Not needed to find template; can be removed once the analyzer
// can find the tag name from customElements.define call
static get is() { return 'dom-if'; }
static get template() { return null; }
static get properties() {
@ -237,7 +248,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}
customElements.define('dom-if', DomIf);
customElements.define(DomIf.is, DomIf);
Polymer.DomIf = DomIf;

View File

@ -30,6 +30,8 @@
*
* let img = document.createElement('dom-module').import('foo', 'img');
*
* @extends HTMLElement
* @memberof Polymer
*/
class DomModule extends HTMLElement {

View File

@ -8,96 +8,6 @@ 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
-->
<!--
The `dom-repeat` element is a custom `HTMLTemplateElement` type extension that
automatically stamps and binds one instance of template content to each object
in a user-provided array. `dom-repeat` accepts an `items` property, and one
instance of the template is stamped for each item into the DOM at the location
of the `dom-repeat` element. The `item` property will be set on each instance's
binding scope, thus templates should bind to sub-properties of `item`.
Example:
```html
<dom-module id="employee-list">
<template>
<div> Employee list: </div>
<template is="dom-repeat" items="{{employees}}">
<div>First name: <span>{{item.first}}</span></div>
<div>Last name: <span>{{item.last}}</span></div>
</template>
</template>
<script>
Polymer({
is: 'employee-list',
ready: function() {
this.employees = [
{first: 'Bob', last: 'Smith'},
{first: 'Sally', last: 'Johnson'},
...
];
}
});
</script>
</dom-module>
```
Notifications for changes to items sub-properties will be forwarded to template
instances, which will update via the normal structured data notification system.
Mutations to the `items` array itself should me made using the Array
mutation API's on `Polymer.Base` (`push`, `pop`, `splice`, `shift`,
`unshift`), and template instances will be kept in sync with the data in the
array.
Events caught by event handlers within the `dom-repeat` template will be
decorated with a `model` property, which represents the binding scope for
each template instance. The model is an instance of Polymer.Base, and should
be used to manipulate data on the instance, for example
`event.model.set('item.checked', true);`.
Alternatively, the model for a template instance for an element stamped by
a `dom-repeat` can be obtained using the `modelForElement` API on the
`dom-repeat` that stamped it, for example
`this.$.domRepeat.modelForElement(event.target).set('item.checked', true);`.
This may be useful for manipulating instance data of event targets obtained
by event handlers on parents of the `dom-repeat` (event delegation).
A view-specific filter/sort may be applied to each `dom-repeat` by supplying a
`filter` and/or `sort` property. This may be a string that names a function on
the host, or a function may be assigned to the property directly. The functions
should implemented following the standard `Array` filter/sort API.
In order to re-run the filter or sort functions based on changes to sub-fields
of `items`, the `observe` property may be set as a space-separated list of
`item` sub-fields that should cause a re-filter/sort when modified. If
the filter or sort function depends on properties not contained in `items`,
the user should observe changes to those properties and call `render` to update
the view based on the dependency change.
For example, for an `dom-repeat` with a filter of the following:
```js
isEngineer: function(item) {
return item.type == 'engineer' || item.manager.type == 'engineer';
}
```
Then the `observe` property should be configured as follows:
```html
<template is="dom-repeat" items="{{employees}}"
filter="isEngineer" observe="type manager.type">
```
-->
<link rel="import" href="../../polymer-element.html">
<link rel="import" href="../utils/templatize.html">
<link rel="import" href="../utils/debounce.html">
@ -107,8 +17,103 @@ Then the `observe` property should be configured as follows:
(function() {
'use strict';
/**
* The `<dom-repeat>` element will automatically stamp and binds one instance
* of template content to each object in a user-provided array.
* `dom-repeat` accepts an `items` property, and one instance of the template
* is stamped for each item into the DOM at the location of the `dom-repeat`
* element. The `item` property will be set on each instance's binding
* scope, thus templates should bind to sub-properties of `item`.
*
* Example:
*
* ```html
* <dom-module id="employee-list">
*
* <template>
*
* <div> Employee list: </div>
* <template is="dom-repeat" items="{{employees}}">
* <div>First name: <span>{{item.first}}</span></div>
* <div>Last name: <span>{{item.last}}</span></div>
* </template>
*
* </template>
*
* <script>
* Polymer({
* is: 'employee-list',
* ready: function() {
* this.employees = [
* {first: 'Bob', last: 'Smith'},
* {first: 'Sally', last: 'Johnson'},
* ...
* ];
* }
* });
* &lt;/script&gt;
*
* </dom-module>
* ```
*
* Notifications for changes to items sub-properties will be forwarded to template
* instances, which will update via the normal structured data notification system.
*
* Mutations to the `items` array itself should me made using the Array
* mutation API's on `Polymer.Base` (`push`, `pop`, `splice`, `shift`,
* `unshift`), and template instances will be kept in sync with the data in the
* array.
*
* Events caught by event handlers within the `dom-repeat` template will be
* decorated with a `model` property, which represents the binding scope for
* each template instance. The model is an instance of Polymer.Base, and should
* be used to manipulate data on the instance, for example
* `event.model.set('item.checked', true);`.
*
* Alternatively, the model for a template instance for an element stamped by
* a `dom-repeat` can be obtained using the `modelForElement` API on the
* `dom-repeat` that stamped it, for example
* `this.$.domRepeat.modelForElement(event.target).set('item.checked', true);`.
* This may be useful for manipulating instance data of event targets obtained
* by event handlers on parents of the `dom-repeat` (event delegation).
*
* A view-specific filter/sort may be applied to each `dom-repeat` by supplying a
* `filter` and/or `sort` property. This may be a string that names a function on
* the host, or a function may be assigned to the property directly. The functions
* should implemented following the standard `Array` filter/sort API.
*
* In order to re-run the filter or sort functions based on changes to sub-fields
* of `items`, the `observe` property may be set as a space-separated list of
* `item` sub-fields that should cause a re-filter/sort when modified. If
* the filter or sort function depends on properties not contained in `items`,
* the user should observe changes to those properties and call `render` to update
* the view based on the dependency change.
*
* For example, for an `dom-repeat` with a filter of the following:
*
* ```js
* isEngineer: function(item) {
* return item.type == 'engineer' || item.manager.type == 'engineer';
* }
* ```
*
* Then the `observe` property should be configured as follows:
*
* ```html
* <template is="dom-repeat" items="{{employees}}"
* filter="isEngineer" observe="type manager.type">
* ```
*
* @polymerElement
* @extends Polymer.Element
* @memberof Polymer
*/
class DomRepeat extends Polymer.Element {
// Not needed to find template; can be removed once the analyzer
// can find the tag name from customElements.define call
static get is() { return 'dom-repeat'; }
static get template() { return null; }
static get properties() {
@ -661,7 +666,7 @@ Then the `observe` property should be configured as follows:
}
customElements.define('dom-repeat', DomRepeat);
customElements.define(DomRepeat.is, DomRepeat);
Polymer.DomRepeat = DomRepeat;

View File

@ -32,6 +32,15 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
listeners: true
}
/**
* Applies a "legacy" behavior or array of behaviors to the provided class.
*
* TODOC
*
* @param {Object|Array} behaviors Behavior object or array of behaviors
* @param {HTMLElement} klass Element class
* @memberof Polymer
*/
function mixinBehaviors(behaviors, klass) {
if (!behaviors) {
return klass;
@ -231,6 +240,20 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
return PolymerGenerated;
}
/**
* Generates a class that extends `Polymer.LegacyElement` based on the
* provided info object. Metadata objects on the `info` object
* (`properties`, `observers`, `listeners`, `behaviors`, `is`) are used
* for Polymer's meta-programming systems, and any functions are copied
* to the generated class.
*
* TODOC
*
* @param {Object} info Object containing Polymer metadata and functions
* to become class methods.
* @return {Polymer.LegacyElement} Generated class
* @memberof Polymer
*/
Polymer.Class = function(info) {
if (!info) {
Polymer._warn('Polymer.Class requires `info` argument');

View File

@ -24,9 +24,22 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
let styleInterface = window.ShadyCSS;
/**
* Element class mixin that provides Polymer's "legacy" API intended to be
* backward-compatible to the greatest extent possible with the API
* found on the Polymer 1.x `Polymer.Base` prototype applied to all elements
* defined using the `Polymer({...})` function.
*
* TODOC
*
* @polymerMixin
* @mixes Polymer.ElementMixin
* @mixes Polymer.GestureEventListeners
* @memberof Polymer
*/
Polymer.LegacyElementMixin = Polymer.dedupingMixin(function(base) {
const mixin = Polymer.GestureEventListeners(Polymer.ElementMixin(base));
const legacyElementBase = Polymer.GestureEventListeners(Polymer.ElementMixin(base));
/**
* Map of simple names to touch action names
@ -39,7 +52,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
'all': 'auto'
};
return class LegacyElement extends mixin {
return class LegacyElement extends legacyElementBase {
constructor() {
super();

View File

@ -14,6 +14,18 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
(function() {
/**
* Legacy class factory and registration helper for defining Polymer
* elements.
*
* TODOC
*
* @namespace Polymer
* @function Polymer
* @param {Object} info Object containing Polymer metadata and functions
* to become class methods.
* @return {Polymer.LegacyElement} Generated class
*/
window.Polymer._polymerFn = function(info) {
// if input is a `class` (aka a function with a prototype), use the prototype
// remember that the `constructor` will never be called

View File

@ -13,16 +13,25 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
<script>
(function() {
let matchesSelector = (function() {
let p = Element.prototype;
let normalizedMatchesSelector = p.matches || p.matchesSelector ||
p.mozMatchesSelector || p.msMatchesSelector ||
p.oMatchesSelector || p.webkitMatchesSelector;
const p = Element.prototype;
const normalizedMatchesSelector = p.matches || p.matchesSelector ||
p.mozMatchesSelector || p.msMatchesSelector ||
p.oMatchesSelector || p.webkitMatchesSelector;
return function(node, selector) {
return normalizedMatchesSelector.call(node, selector);
}
})();
/**
* Cross-platform `element.matches` shim.
*
* TODOC
*
* @function matchesSelector
* @memberof Polymer
* @param {Node} node Node to check selector against
* @param {string} selector Selector to match
* @return {boolean} True if node matched selector
*/
const matchesSelector = function(node, selector) {
return normalizedMatchesSelector.call(node, selector);
}
class DomApi {
@ -174,6 +183,20 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}
}
/**
* Legacy DOM manipulation API used to abstract differences between native
* Shadow DOM and "Shady DOM" when polyfilling on older browsers.
*
* Note that in Polymer 2.x use of `Polymer.dom` is no longer required and
* in the majority of cases simply facades directly to the standard native
* API.
*
* TODOC
*
* @memberof Polymer
* @param {Node|Event} obj Node or event to operate on
* @return {DomApi|EventApi} Wrapper providing either node API or event API
*/
Polymer.dom = function(obj) {
obj = obj || document;
let ctor = obj instanceof Event ? EventApi : DomApi;

View File

@ -14,6 +14,68 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
(function() {
'use strict';
/**
* The `Polymer.Templatizer` behavior adds methods to generate instances of
* templates that are each managed by an anonymous `Polymer.PropertyEffects`
* instance where data-bindings in the stamped template content are bound to
* accessors on itself.
*
* This behavior is provided in Polymer 2.x as a hybrid-element convenience
* only. For non-legacy/hybrid usage, the `Polymer.Templatize` library
* should be used instead.
*
* Example:
*
* // Get a template from somewhere, e.g. light DOM
* var template = this.querySelector('template');
* // Prepare the template
* this.templatize(template);
* // Instance the template with an initial data model
* var instance = this.stamp({myProp: 'initial'});
* // Insert the instance's DOM somewhere, e.g. light DOM
* Polymer.dom(this).appendChild(instance.root);
* // Changing a property on the instance will propagate to bindings
* // in the template
* instance.myProp = 'new value';
*
* Users of `Templatizer` may need to implement the following abstract
* API's to determine how properties and paths from the host should be
* forwarded into to instances:
*
* _forwardHostPropV2: function(prop, value)
*
* Likewise, users may implement these additional abstract API's to determine
* how instance-specific properties that change on the instance should be
* forwarded out to the host, if necessary.
*
* _notifyInstancePropV2: function(inst, prop, value)
*
* In order to determine which properties are instance-specific and require
* custom forwarding via `_forwardInstanceProp`/`_forwardInstancePath`,
* define an `_instanceProps` map containing keys for each instance prop,
* for example:
*
* _instanceProps: {
* item: true,
* index: true
* }
*
* Any properties used in the template that are not defined in _instanceProp
* will be forwarded out to the host automatically.
*
* Users should also implement the following abstract function to show or
* hide any DOM generated using `stamp`:
*
* _showHideChildren: function(shouldHide)
*
* Note that some callbacks are suffixed with `V2` in the Polymer 2.x behavior
* as the implementations will need to differ from the callbacks required
* by the 1.x Templatizer API due to changes in the `TemplateInstance` API
* between versions 1.x and 2.x.
*
* @polymerBehavior
* @memberof Polymer
*/
let Templatizer = {
templatize(template) {
this._templatizerTemplate = template;

View File

@ -17,9 +17,20 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
<link rel="import" href="property-effects.html">
<script>
/**
* Element class mixin that provides the core API for Polymer's meta-programming
* features including template stamping, data-binding, attribute deserialization,
* and property change observation.
*
* TODOC
*
* @polymerMixin
* @mixes Polymer.PropertyEffects
* @memberof Polymer
*/
Polymer.ElementMixin = Polymer.dedupingMixin(function(base) {
const mixin = Polymer.PropertyEffects(base);
const polymerElementBase = Polymer.PropertyEffects(base);
let caseMap = Polymer.CaseMap;
@ -321,9 +332,10 @@ Polymer.ElementMixin = Polymer.dedupingMixin(function(base) {
}
/**
* @polymerMixinClass
* @unrestricted
*/
class PolymerElement extends mixin {
class PolymerElement extends polymerElementBase {
static get observedAttributes() {
if (!this.hasOwnProperty(goog.reflect.objectProperty('__observedAttributes', this))) {

View File

@ -17,6 +17,18 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
const gestures = Polymer.Gestures;
/**
* Element class mixin that provides API for adding Polymer's cross-platform
* gesture events to nodes.
*
* The API is designed to be compatible with override points implemented
* in `Polymer.TemplateStamp` such that declarative event listeners in
* templates will support gesture events when this mixin is applied along with
* `Polymer.TemplateStamp`.
*
* @polymerMixin
* @memberof Polymer
*/
Polymer.GestureEventListeners = Polymer.dedupingMixin(function(superClass) {
return class GestureEventListeners extends superClass {

View File

@ -70,6 +70,22 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}
}
/**
* Element class mixin that provides basic meta-programming for creating one
* or more property accessors (getter/setter pair) that enqueue an async
* (batched) `_propertiesChanged` callback.
*
* For basic usage of this mixin, simply declare attributes to observe via
* the standard `static get observedAttributes()`, implement `_propertiesChanged`
* on the class, and then call `MyClass.createPropertiesForAttributes()` once
* on the class to generate property accessors for each observed attribute
* prior to instancing.
*
* TODOC
*
* @polymerMixin
* @memberof Polymer
*/
Polymer.PropertyAccessors = Polymer.dedupingMixin(function(superClass) {
return class PropertyAccessors extends superClass {

View File

@ -1203,11 +1203,23 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}
}
/**
* Element class mixin that provides meta-programming for Polymer's template
* binding and data observation (collectively, "property effects") system.
*
* TODOC
*
* @polymerMixin
* @mixes Polymer.TemplateStamp
* @mixes Polymer.PropertyAccessors
* @memberof Polymer
*/
Polymer.PropertyEffects = Polymer.dedupingMixin(function(superClass) {
const mixin = Polymer.TemplateStamp(Polymer.PropertyAccessors(superClass));
/**
* @polymerMixinClass
* @unrestricted
*/
class PropertyEffects extends mixin {

View File

@ -16,99 +16,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
'use strict';
/**
* Scans a template to produce an annotation object that stores expression
* metadata along with information to associate the metadata with nodes in an
* instance.
*
* Elements with `id` in the template are noted and marshaled into an
* the `$` hash in an instance.
*
* Example
*
* &lt;template>
* &lt;div id="foo">&lt;/div>
* &lt;/template>
* &lt;script>
* Polymer({
* task: function() {
* this.$.foo.style.color = 'red';
* }
* });
* &lt;/script>
*
* Other expressions that are noted include:
*
* Double-mustache annotations in text content. The annotation must be the only
* content in the tag, compound expressions are not (currently) supported.
*
* <[tag]>{{path.to.host.property}}<[tag]>
*
* Double-mustache annotations in an attribute.
*
* <[tag] someAttribute="{{path.to.host.property}}"><[tag]>
*
* Only immediate host properties can automatically trigger side-effects.
* Setting `host.path` in the example above triggers the binding, setting
* `host.path.to.host.property` does not.
*
* `on-` style event declarations.
*
* <[tag] on-<event-name>="{{hostMethodName}}"><[tag]>
*
* Note: **the `annotations` feature does not actually implement the behaviors
* associated with these expressions, it only captures the data**.
*
* Other optional features contain actual data implementations.
*
* @class standard feature: annotations
*/
/*
Scans a template to produce an annotation map that stores expression metadata
and information that associates the metadata to nodes in a template instance.
Supported annotations are:
* id attributes
* binding annotations in text nodes
* double-mustache expressions: {{expression}}
* double-bracket expressions: [[expression]]
* binding annotations in attributes
* attribute-bind expressions: name="{{expression}} || [[expression]]"
* property-bind expressions: name*="{{expression}} || [[expression]]"
* property-bind expressions: name:="expression"
* event annotations
* event delegation directives: on-<eventName>="expression"
Generated data-structure:
[
{
id: '<id>',
events: [
{
mode: ['auto'|''],
name: '<name>'
value: '<expression>'
}, ...
],
bindings: [
{
kind: ['text'|'attribute'|'property'],
mode: ['auto'|''],
name: '<name>'
value: '<expression>'
}, ...
],
parent: <reference to parent annotation>,
index: <integer index in parent's childNodes collection>
},
...
]
*/
// null-array (shared empty array to avoid null-checks)
const emptyArray = [];
@ -134,6 +41,46 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
let insertionPointTag = 'slot';
/**
* Scans a template to produce an annotation map that stores expression metadata
* and information that associates the metadata to nodes in a template instance.
*
* Supported annotations are:
* * id attributes
* * binding annotations in text nodes
* * double-mustache expressions: {{expression}}
* * double-bracket expressions: [[expression]]
* * binding annotations in attributes
* * attribute-bind expressions: name="{{expression}} || [[expression]]"
* * property-bind expressions: name*="{{expression}} || [[expression]]"
* * property-bind expressions: name:="expression"
* * event annotations
* * event delegation directives: on-<eventName>="expression"
*
* Generated data-structure:
* [
* {
* id: '<id>',
* events: [
* {
* mode: ['auto'|''],
* name: '<name>'
* value: '<expression>'
* }, ...
* ],
* bindings: [
* {
* kind: ['text'|'attribute'|'property'],
* mode: ['auto'|''],
* name: '<name>'
* value: '<expression>'
* }, ...
* ],
* parent: <reference to parent annotation>,
* index: <integer index in parent's childNodes collection>
* },
* ...
* ]
*
* @param {HTMLTemplateElement} template
* @param {boolean=} stripWhiteSpace
* @return {Array<Object>}
@ -487,6 +434,22 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
return handler;
}
/**
* Element mixin that provides basic template parsing and stamping, including
* the following template-related features for stamped templates:
*
* - Declarative event listeners (`on-eventname="listener"`)
* - Map of node id's to stamped node instances (`this.$.id`)
* - Nested template content caching/removal and re-installation (performance
* optimization)
* - Relative URL's relative to original template location
* - Template binding annotation parsing (note that this library only parses
* template bindings and provides annotation metadata; see
* `Polymer.PropertyEffects` for a full implementation of data-binding)
*
* @polymerMixin
* @memberof Polymer
*/
Polymer.TemplateStamp = Polymer.dedupingMixin(function(superClass) {
return class TemplateStamp extends superClass {
@ -507,7 +470,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
* event listeners (`on-...``), `id`'s, `<template>`s, and bindings
* (`{{...}}` and `[[...]]`). This template metadata ("notes")
* are stored as `this._templateNotes`, and any nodes identified in
* with notes are collected for this instance into `_templateNodes` in
* notes are collected for this instance into `_templateNodes` in
* the same order as the notes array.
*
* Finally, this method generates an "id map" for all nodes with id's