summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/catapult/third_party/polymer2/bower_components/polymer/lib/elements/dom-if.html
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/catapult/third_party/polymer2/bower_components/polymer/lib/elements/dom-if.html')
-rw-r--r--chromium/third_party/catapult/third_party/polymer2/bower_components/polymer/lib/elements/dom-if.html288
1 files changed, 288 insertions, 0 deletions
diff --git a/chromium/third_party/catapult/third_party/polymer2/bower_components/polymer/lib/elements/dom-if.html b/chromium/third_party/catapult/third_party/polymer2/bower_components/polymer/lib/elements/dom-if.html
new file mode 100644
index 00000000000..527ede86ae0
--- /dev/null
+++ b/chromium/third_party/catapult/third_party/polymer2/bower_components/polymer/lib/elements/dom-if.html
@@ -0,0 +1,288 @@
+<!--
+@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="../../polymer-element.html">
+<link rel="import" href="../utils/templatize.html">
+<link rel="import" href="../utils/debounce.html">
+<link rel="import" href="../utils/flush.html">
+
+<script>
+
+(function() {
+ 'use strict';
+
+ /**
+ * 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 falsy, the stamped content is hidden but not
+ * removed from dom. When `if` subsequently becomes truthy again, the content
+ * is simply re-shown. This approach is used due to its favorable performance
+ * characteristics: the expense of creating template content is paid only
+ * once and lazily.
+ *
+ * Set the `restamp` property to true to force the stamped content to be
+ * created / destroyed when the `if` condition changes.
+ *
+ * @customElement
+ * @polymer
+ * @extends Polymer.Element
+ * @memberof Polymer
+ * @summary Custom element that conditionally stamps and hides or removes
+ * template content based on a boolean flag.
+ */
+ 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() {
+
+ return {
+
+ /**
+ * Fired whenever DOM is added or removed/hidden by this template (by
+ * default, rendering occurs lazily). To force immediate rendering, call
+ * `render`.
+ *
+ * @event dom-change
+ */
+
+ /**
+ * A boolean indicating whether this template should stamp.
+ */
+ if: {
+ type: Boolean,
+ observer: '__debounceRender'
+ },
+
+ /**
+ * When true, elements will be removed from DOM and discarded when `if`
+ * becomes false and re-created and added back to the DOM when `if`
+ * becomes true. By default, stamped elements will be hidden but left
+ * in the DOM when `if` becomes false, which is generally results
+ * in better performance.
+ */
+ restamp: {
+ type: Boolean,
+ observer: '__debounceRender'
+ }
+
+ };
+
+ }
+
+ constructor() {
+ super();
+ this.__renderDebouncer = null;
+ this.__invalidProps = null;
+ this.__instance = null;
+ this._lastIf = false;
+ this.__ctor = null;
+ }
+
+ __debounceRender() {
+ // Render is async for 2 reasons:
+ // 1. To eliminate dom creation trashing if user code thrashes `if` in the
+ // same turn. This was more common in 1.x where a compound computed
+ // property could result in the result changing multiple times, but is
+ // mitigated to a large extent by batched property processing in 2.x.
+ // 2. To avoid double object propagation when a bag including values bound
+ // to the `if` property as well as one or more hostProps could enqueue
+ // the <dom-if> to flush before the <template>'s host property
+ // forwarding. In that scenario creating an instance would result in
+ // the host props being set once, and then the enqueued changes on the
+ // template would set properties a second time, potentially causing an
+ // object to be set to an instance more than once. Creating the
+ // instance async from flushing data ensures this doesn't happen. If
+ // we wanted a sync option in the future, simply having <dom-if> flush
+ // (or clear) its template's pending host properties before creating
+ // the instance would also avoid the problem.
+ this.__renderDebouncer = Polymer.Debouncer.debounce(
+ this.__renderDebouncer
+ , Polymer.Async.microTask
+ , () => this.__render());
+ Polymer.enqueueDebouncer(this.__renderDebouncer);
+ }
+
+ /**
+ * @return {void}
+ */
+ disconnectedCallback() {
+ super.disconnectedCallback();
+ if (!this.parentNode ||
+ (this.parentNode.nodeType == Node.DOCUMENT_FRAGMENT_NODE &&
+ !this.parentNode.host)) {
+ this.__teardownInstance();
+ }
+ }
+
+ /**
+ * @return {void}
+ */
+ connectedCallback() {
+ super.connectedCallback();
+ this.style.display = 'none';
+ if (this.if) {
+ this.__debounceRender();
+ }
+ }
+
+ /**
+ * Forces the element to render its content. Normally rendering is
+ * asynchronous to a provoking change. This is done for efficiency so
+ * that multiple changes trigger only a single render. The render method
+ * should be called if, for example, template rendering is required to
+ * validate application state.
+ * @return {void}
+ */
+ render() {
+ Polymer.flush();
+ }
+
+ __render() {
+ if (this.if) {
+ if (!this.__ensureInstance()) {
+ // No template found yet
+ return;
+ }
+ this._showHideChildren();
+ } else if (this.restamp) {
+ this.__teardownInstance();
+ }
+ if (!this.restamp && this.__instance) {
+ this._showHideChildren();
+ }
+ if (this.if != this._lastIf) {
+ this.dispatchEvent(new CustomEvent('dom-change', {
+ bubbles: true,
+ composed: true
+ }));
+ this._lastIf = this.if;
+ }
+ }
+
+ __ensureInstance() {
+ let parentNode = this.parentNode;
+ // Guard against element being detached while render was queued
+ if (parentNode) {
+ if (!this.__ctor) {
+ let template = /** @type {HTMLTemplateElement} */(this.querySelector('template'));
+ if (!template) {
+ // Wait until childList changes and template should be there by then
+ let observer = new MutationObserver(() => {
+ if (this.querySelector('template')) {
+ observer.disconnect();
+ this.__render();
+ } else {
+ throw new Error('dom-if requires a <template> child');
+ }
+ });
+ observer.observe(this, {childList: true});
+ return false;
+ }
+ this.__ctor = Polymer.Templatize.templatize(template, this, {
+ // dom-if templatizer instances require `mutable: true`, as
+ // `__syncHostProperties` relies on that behavior to sync objects
+ mutableData: true,
+ /**
+ * @param {string} prop Property to forward
+ * @param {*} value Value of property
+ * @this {this}
+ */
+ forwardHostProp: function(prop, value) {
+ if (this.__instance) {
+ if (this.if) {
+ this.__instance.forwardHostProp(prop, value);
+ } else {
+ // If we have an instance but are squelching host property
+ // forwarding due to if being false, note the invalidated
+ // properties so `__syncHostProperties` can sync them the next
+ // time `if` becomes true
+ this.__invalidProps = this.__invalidProps || Object.create(null);
+ this.__invalidProps[Polymer.Path.root(prop)] = true;
+ }
+ }
+ }
+ });
+ }
+ if (!this.__instance) {
+ this.__instance = new this.__ctor();
+ parentNode.insertBefore(this.__instance.root, this);
+ } else {
+ this.__syncHostProperties();
+ let c$ = this.__instance.children;
+ if (c$ && c$.length) {
+ // Detect case where dom-if was re-attached in new position
+ let lastChild = this.previousSibling;
+ if (lastChild !== c$[c$.length-1]) {
+ for (let i=0, n; (i<c$.length) && (n=c$[i]); i++) {
+ parentNode.insertBefore(n, this);
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ __syncHostProperties() {
+ let props = this.__invalidProps;
+ if (props) {
+ for (let prop in props) {
+ this.__instance._setPendingProperty(prop, this.__dataHost[prop]);
+ }
+ this.__invalidProps = null;
+ this.__instance._flushProperties();
+ }
+ }
+
+ __teardownInstance() {
+ if (this.__instance) {
+ let c$ = this.__instance.children;
+ if (c$ && c$.length) {
+ // use first child parent, for case when dom-if may have been detached
+ let parent = c$[0].parentNode;
+ for (let i=0, n; (i<c$.length) && (n=c$[i]); i++) {
+ parent.removeChild(n);
+ }
+ }
+ this.__instance = null;
+ this.__invalidProps = null;
+ }
+ }
+
+ /**
+ * Shows or hides the template instance top level child elements. For
+ * text nodes, `textContent` is removed while "hidden" and replaced when
+ * "shown."
+ * @return {void}
+ * @protected
+ */
+ _showHideChildren() {
+ let hidden = this.__hideTemplateChildren__ || !this.if;
+ if (this.__instance) {
+ this.__instance._showHideChildren(hidden);
+ }
+ }
+
+ }
+
+ customElements.define(DomIf.is, DomIf);
+
+ Polymer.DomIf = DomIf;
+
+})();
+</script>