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

Unified Diff: appengine/config_service/ui/bower_components/polymer/lib/utils/templatize.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 side-by-side diff with in-line comments
Download patch
Index: appengine/config_service/ui/bower_components/polymer/lib/utils/templatize.html
diff --git a/appengine/config_service/ui/bower_components/polymer/lib/utils/templatize.html b/appengine/config_service/ui/bower_components/polymer/lib/utils/templatize.html
new file mode 100644
index 0000000000000000000000000000000000000000..31f792ec55dfb8010199f03c755980a52922b163
--- /dev/null
+++ b/appengine/config_service/ui/bower_components/polymer/lib/utils/templatize.html
@@ -0,0 +1,473 @@
+<!--
+@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="boot.html">
+<link rel="import" href="../mixins/property-effects.html">
+<link rel="import" href="../mixins/mutable-data.html">
+
+<script>
+ (function() {
+ 'use strict';
+
+ // Base class for HTMLTemplateElement extension that has property effects
+ // machinery for propagating host properties to children. This is an ES5
+ // class only because Babel (incorrectly) requires super() in the class
+ // constructor even though no `this` is used and it returns an instance.
+ let newInstance = null;
+ function HTMLTemplateElementExtension() { return newInstance; }
+ HTMLTemplateElementExtension.prototype = Object.create(HTMLTemplateElement.prototype, {
+ constructor: {
+ value: HTMLTemplateElementExtension,
+ writable: true
+ }
+ });
+ const DataTemplate = Polymer.PropertyEffects(HTMLTemplateElementExtension);
+ const MutableDataTemplate = Polymer.MutableData(DataTemplate);
+
+ // Applies a DataTemplate subclass to a <template> instance
+ function upgradeTemplate(template, constructor) {
+ newInstance = template;
+ Object.setPrototypeOf(template, constructor.prototype);
+ new constructor();
+ newInstance = null;
+ }
+
+ // Base class for TemplateInstance's
+ /**
+ * @constructor
+ * @implements {Polymer_PropertyEffects}
+ */
+ const base = Polymer.PropertyEffects(class {});
+ class TemplateInstanceBase extends base {
+ constructor(props) {
+ super();
+ this._configureProperties(props);
+ this.root = this._stampTemplate(this.__dataHost);
+ // Save list of stamped children
+ let children = this.children = [];
+ for (let n = this.root.firstChild; n; n=n.nextSibling) {
+ children.push(n);
+ n.__templatizeInstance = this;
+ }
+ if (this.__templatizeOwner.__hideTemplateChildren__) {
+ this._showHideChildren(true);
+ }
+ // Flush props only when props are passed if instance props exist
+ // or when there isn't instance props.
+ let options = this.__templatizeOptions;
+ if ((props && options.instanceProps) || !options.instanceProps) {
+ this._enableProperties();
+ }
+ }
+ /**
+ * Configure the given `props` by calling `_setPendingProperty`. Also
+ * sets any properties stored in `__hostProps`.
+ * @private
+ * @param {Object} props Object of property name-value pairs to set.
+ */
+ _configureProperties(props) {
+ let options = this.__templatizeOptions;
+ if (props) {
+ for (let iprop in options.instanceProps) {
+ if (iprop in props) {
+ this._setPendingProperty(iprop, props[iprop]);
+ }
+ }
+ }
+ for (let hprop in this.__hostProps) {
+ this._setPendingProperty(hprop, this.__dataHost['_host_' + hprop]);
+ }
+ }
+ /**
+ * Forwards a host property to this instance. This method should be
+ * called on instances from the `options.forwardHostProp` callback
+ * to propagate changes of host properties to each instance.
+ *
+ * Note this method enqueues the change, which are flushed as a batch.
+ *
+ * @param {string} prop Property or path name
+ * @param {*} value Value of the property to forward
+ */
+ forwardHostProp(prop, value) {
+ if (this._setPendingPropertyOrPath(prop, value, false, true)) {
+ this.__dataHost._enqueueClient(this);
+ }
+ }
+ /**
+ * @override
+ */
+ _addEventListenerToNode(node, eventName, handler) {
+ if (this._methodHost && this.__templatizeOptions.parentModel) {
+ // If this instance should be considered a parent model, decorate
+ // events this template instance as `model`
+ this._methodHost._addEventListenerToNode(node, eventName, (e) => {
+ e.model = this;
+ handler(e);
+ });
+ } else {
+ // Otherwise delegate to the template's host (which could be)
+ // another template instance
+ let templateHost = this.__dataHost.__dataHost;
+ if (templateHost) {
+ templateHost._addEventListenerToNode(node, eventName, handler);
+ }
+ }
+ }
+ /**
+ * Shows or hides the template instance top level child elements. For
+ * text nodes, `textContent` is removed while "hidden" and replaced when
+ * "shown."
+ * @param {boolean} hide Set to true to hide the children;
+ * set to false to show them.
+ * @protected
+ */
+ _showHideChildren(hide) {
+ let c = this.children;
+ for (let i=0; i<c.length; i++) {
+ let n = c[i];
+ // Ignore non-changes
+ if (Boolean(hide) != Boolean(n.__hideTemplateChildren__)) {
+ if (n.nodeType === Node.TEXT_NODE) {
+ if (hide) {
+ n.__polymerTextContent__ = n.textContent;
+ n.textContent = '';
+ } else {
+ n.textContent = n.__polymerTextContent__;
+ }
+ } else if (n.style) {
+ if (hide) {
+ n.__polymerDisplay__ = n.style.display;
+ n.style.display = 'none';
+ } else {
+ n.style.display = n.__polymerDisplay__;
+ }
+ }
+ }
+ n.__hideTemplateChildren__ = hide;
+ if (n._showHideChildren) {
+ n._showHideChildren(hide);
+ }
+ }
+ }
+ /**
+ * Overrides default property-effects implementation to intercept
+ * textContent bindings while children are "hidden" and cache in
+ * private storage for later retrieval.
+ *
+ * @override
+ */
+ _setUnmanagedPropertyToNode(node, prop, value) {
+ if (node.__hideTemplateChildren__ &&
+ node.nodeType == Node.TEXT_NODE && prop == 'textContent') {
+ node.__polymerTextContent__ = value;
+ } else {
+ super._setUnmanagedPropertyToNode(node, prop, value);
+ }
+ }
+ /**
+ * Find the parent model of this template instance. The parent model
+ * is either another templatize instance that had option `parentModel: true`,
+ * or else the host element.
+ *
+ * @return {Polymer.PropertyEffectsInterface} The parent model of this instance
+ */
+ get parentModel() {
+ let model = this.__parentModel;
+ if (!model) {
+ let options;
+ model = this
+ do {
+ // A template instance's `__dataHost` is a <template>
+ // `model.__dataHost.__dataHost` is the template's host
+ model = model.__dataHost.__dataHost;
+ } while ((options = model.__templatizeOptions) && !options.parentModel)
+ this.__parentModel = model;
+ }
+ return model;
+ }
+ }
+
+ const MutableTemplateInstanceBase = Polymer.MutableData(TemplateInstanceBase);
+
+ function findMethodHost(template) {
+ // Technically this should be the owner of the outermost template.
+ // In shadow dom, this is always getRootNode().host, but we can
+ // approximate this via cooperation with our dataHost always setting
+ // `_methodHost` as long as there were bindings (or id's) on this
+ // instance causing it to get a dataHost.
+ let templateHost = template.__dataHost;
+ return templateHost && templateHost._methodHost || templateHost;
+ }
+
+ function createTemplatizerClass(template, templateInfo, options) {
+ // Anonymous class created by the templatize
+ /**
+ * @unrestricted
+ */
+ let base = options.mutableData ?
+ MutableTemplateInstanceBase : TemplateInstanceBase;
+ let klass = class extends base { }
+ klass.prototype.__templatizeOptions = options;
+ klass.prototype._bindTemplate(template);
+ addNotifyEffects(klass, template, templateInfo, options);
+ return klass;
+ }
+
+ function addPropagateEffects(template, templateInfo, options) {
+ let userForwardHostProp = options.forwardHostProp;
+ if (userForwardHostProp) {
+ // Provide data API and property effects on memoized template class
+ let klass = templateInfo.templatizeTemplateClass;
+ if (!klass) {
+ let base = options.mutableData ? MutableDataTemplate : DataTemplate;
+ klass = templateInfo.templatizeTemplateClass =
+ class TemplatizedTemplate extends base {}
+ // Add template - >instances effects
+ // and host <- template effects
+ let hostProps = templateInfo.hostProps;
+ for (let prop in hostProps) {
+ klass.prototype._addPropertyEffect('_host_' + prop,
+ klass.prototype.PROPERTY_EFFECT_TYPES.PROPAGATE,
+ {fn: createForwardHostPropEffect(prop, userForwardHostProp)});
+ klass.prototype._createNotifyingProperty('_host_' + prop);
+ }
+ }
+ upgradeTemplate(template, klass);
+ // Mix any pre-bound data into __data; no need to flush this to
+ // instances since they pull from the template at instance-time
+ if (template.__dataProto) {
+ // Note, generally `__dataProto` could be chained, but it's guaranteed
+ // to not be since this is a vanilla template we just added effects to
+ Object.assign(template.__data, template.__dataProto);
+ }
+ // Clear any pending data for performance
+ template.__dataTemp = {};
+ template.__dataPending = null;
+ template.__dataOld = null;
+ template._enableProperties();
+ }
+ }
+
+ function createForwardHostPropEffect(hostProp, userForwardHostProp) {
+ return function forwardHostProp(template, prop, props) {
+ userForwardHostProp.call(template.__templatizeOwner,
+ prop.substring('_host_'.length), props[prop]);
+ }
+ }
+
+ function addNotifyEffects(klass, template, templateInfo, options) {
+ let hostProps = templateInfo.hostProps || {};
+ for (let iprop in options.instanceProps) {
+ delete hostProps[iprop];
+ let userNotifyInstanceProp = options.notifyInstanceProp;
+ if (userNotifyInstanceProp) {
+ klass.prototype._addPropertyEffect(iprop,
+ klass.prototype.PROPERTY_EFFECT_TYPES.NOTIFY,
+ {fn: createNotifyInstancePropEffect(iprop, userNotifyInstanceProp)});
+ }
+ }
+ if (options.forwardHostProp && template.__dataHost) {
+ for (let hprop in hostProps) {
+ klass.prototype._addPropertyEffect(hprop,
+ klass.prototype.PROPERTY_EFFECT_TYPES.NOTIFY,
+ {fn: createNotifyHostPropEffect()})
+ }
+ }
+ }
+
+ function createNotifyInstancePropEffect(instProp, userNotifyInstanceProp) {
+ return function notifyInstanceProp(inst, prop, props) {
+ userNotifyInstanceProp.call(inst.__templatizeOwner,
+ inst, prop, props[prop]);
+ }
+ }
+
+ function createNotifyHostPropEffect() {
+ return function notifyHostProp(inst, prop, props) {
+ inst.__dataHost._setPendingPropertyOrPath('_host_' + prop, props[prop], true, true);
+ }
+ }
+
+ /**
+ * Module for preparing and stamping instances of templates that utilize
+ * Polymer's data-binding and declarative event listener features.
+ *
+ * Example:
+ *
+ * // Get a template from somewhere, e.g. light DOM
+ * let template = this.querySelector('template');
+ * // Prepare the template
+ * let TemplateClass = Polymer.Templatize.templatize(template);
+ * // Instance the template with an initial data model
+ * let instance = new TemplateClass({myProp: 'initial'});
+ * // Insert the instance's DOM somewhere, e.g. element's shadow DOM
+ * this.shadowRoot.appendChild(instance.root);
+ * // Changing a property on the instance will propagate to bindings
+ * // in the template
+ * instance.myProp = 'new value';
+ *
+ * The `options` dictionary passed to `templatize` allows for customizing
+ * features of the generated template class, including how outer-scope host
+ * properties should be forwarded into template instances, how any instance
+ * properties added into the template's scope should be notified out to
+ * the host, and whether the instance should be decorated as a "parent model"
+ * of any event handlers.
+ *
+ * // Customze property forwarding and event model decoration
+ * let TemplateClass = Polymer.Tempaltize.templatize(template, this, {
+ * parentModel: true,
+ * instanceProps: {...},
+ * forwardHostProp(property, value) {...},
+ * notifyInstanceProp(instance, property, value) {...},
+ * });
+ *
+ *
+ * @namespace
+ * @memberof Polymer
+ * @summary Module for preparing and stamping instances of templates
+ * utilizing Polymer templating features.
+ */
+ const Templatize = {
+
+ /**
+ * Returns an anonymous `Polymer.PropertyEffects` class bound to the
+ * `<template>` provided. Instancing the class will result in the
+ * template being stamped into document fragment stored as the instance's
+ * `root` property, after which it can be appended to the DOM.
+ *
+ * Templates may utilize all Polymer data-binding features as well as
+ * declarative event listeners. Event listeners and inline computing
+ * functions in the template will be called on the host of the template.
+ *
+ * The constructor returned takes a single argument dictionary of initial
+ * property values to propagate into template bindings. Additionally
+ * host properties can be forwarded in, and instance properties can be
+ * notified out by providing optional callbacks in the `options` dictionary.
+ *
+ * Valid configuration in `options` are as follows:
+ *
+ * - `forwardHostProp(property, value)`: Called when a property referenced
+ * in the template changed on the template's host. As this library does
+ * not retain references to templates instanced by the user, it is the
+ * templatize owner's responsibility to forward host property changes into
+ * user-stamped instances. The `instance.forwardHostProp(property, value)`
+ * method on the generated class should be called to forward host
+ * properties into the template to prevent unnecessary property-changed
+ * notifications. Any properties referenced in the template that are not
+ * defined in `instanceProps` will be notified up to the template's host
+ * automatically.
+ * - `instanceProps`: Dictionary of property names that will be added
+ * to the instance by the templatize owner. These properties shadow any
+ * host properties, and changes within the template to these properties
+ * will result in `notifyInstanceProp` being called.
+ * - `mutableData`: When `true`, the generated class will skip strict
+ * dirty-checking for objects and arrays (always consider them to be
+ * "dirty").
+ * - `notifyInstanceProp(instance, property, value)`: Called when
+ * an instance property changes. Users may choose to call `notifyPath`
+ * on e.g. the owner to notify the change.
+ * - `parentModel`: When `true`, events handled by declarative event listeners
+ * (`on-event="handler"`) will be decorated with a `model` property pointing
+ * to the template instance that stamped it. It will also be returned
+ * from `instance.parentModel` in cases where template instance nesting
+ * causes an inner model to shadow an outer model.
+ *
+ * Note that the class returned from `templatize` is generated only once
+ * for a given `<template>` using `options` from the first call for that
+ * template, and the cached class is returned for all subsequent calls to
+ * `templatize` for that template. As such, `options` callbacks should not
+ * close over owner-specific properties since only the first `options` is
+ * used; rather, callbacks are called bound to the `owner`, and so context
+ * needed from the callbacks (such as references to `instances` stamped)
+ * should be stored on the `owner` such that they can be retrieved via `this`.
+ *
+ * @memberof Polymer.Templatize
+ * @param {HTMLTemplateElement} template Template to templatize
+ * @param {*} owner Owner of the template instances; any optional callbacks
+ * will be bound to this owner.
+ * @param {*=} options Options dictionary (see summary for details)
+ * @return {TemplateInstanceBase} Generated class bound to the template
+ * provided
+ */
+ templatize(template, owner, options) {
+ options = options || {};
+ if (template.__templatizeOwner) {
+ throw new Error('A <template> can only be templatized once');
+ }
+ template.__templatizeOwner = owner;
+ let templateInfo = owner.constructor._parseTemplate(template);
+ // Get memoized base class for the prototypical template, which
+ // includes property effects for binding template & forwarding
+ let baseClass = templateInfo.templatizeInstanceClass;
+ if (!baseClass) {
+ baseClass = createTemplatizerClass(template, templateInfo, options);
+ templateInfo.templatizeInstanceClass = baseClass;
+ }
+ // Host property forwarding must be installed onto template instance
+ addPropagateEffects(template, templateInfo, options);
+ // Subclass base class and add reference for this specific template
+ let klass = class TemplateInstance extends baseClass {};
+ klass.prototype._methodHost = findMethodHost(template);
+ klass.prototype.__dataHost = template;
+ klass.prototype.__templatizeOwner = owner;
+ klass.prototype.__hostProps = templateInfo.hostProps;
+ return klass;
+ },
+
+ /**
+ * Returns the template "model" associated with a given element, which
+ * serves as the binding scope for the template instance the element is
+ * contained in. A template model is an instance of
+ * `TemplateInstanceBase`, and should be used to manipulate data
+ * associated with this template instance.
+ *
+ * Example:
+ *
+ * let model = modelForElement(el);
+ * if (model.index < 10) {
+ * model.set('item.checked', true);
+ * }
+ *
+ * @memberof Polymer.Templatize
+ * @param {HTMLTemplateElement} template The model will be returned for
+ * elements stamped from this template
+ * @param {HTMLElement} el Element for which to return a template model.
+ * @return {TemplateInstanceBase} Template instance representing the
+ * binding scope for the element
+ */
+ modelForElement(template, el) {
+ let model;
+ while (el) {
+ // An element with a __templatizeInstance marks the top boundary
+ // of a scope; walk up until we find one, and then ensure that
+ // its __dataHost matches `this`, meaning this dom-repeat stamped it
+ if ((model = el.__templatizeInstance)) {
+ // Found an element stamped by another template; keep walking up
+ // from its __dataHost
+ if (model.__dataHost != template) {
+ el = model.__dataHost;
+ } else {
+ return model;
+ }
+ } else {
+ // Still in a template scope, keep going up until
+ // a __templatizeInstance is found
+ el = el.parentNode;
+ }
+ }
+ return null;
+ }
+ }
+
+ Polymer.Templatize = Templatize;
+
+ })();
+
+</script>

Powered by Google App Engine
This is Rietveld 408576698