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

Side by Side Diff: appengine/config_service/ui/bower_components/polymer/lib/elements/dom-if.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="../../polymer-element.html">
12 <link rel="import" href="../utils/templatize.html">
13 <link rel="import" href="../utils/debounce.html">
14 <link rel="import" href="../utils/flush.html">
15
16 <script>
17
18 (function() {
19 'use strict';
20
21 /**
22 * The `<dom-if>` element will stamp a light-dom `<template>` child when
23 * the `if` property becomes truthy, and the template can use Polymer
24 * data-binding and declarative event features when used in the context of
25 * a Polymer element's template.
26 *
27 * When `if` becomes falsey, the stamped content is hidden but not
28 * removed from dom. When `if` subsequently becomes truthy again, the content
29 * is simply re-shown. This approach is used due to its favorable performance
30 * characteristics: the expense of creating template content is paid only
31 * once and lazily.
32 *
33 * Set the `restamp` property to true to force the stamped content to be
34 * created / destroyed when the `if` condition changes.
35 *
36 * @polymerElement
37 * @extends Polymer.Element
38 * @memberof Polymer
39 * @summary Custom element that conditionally stamps and hides or removes
40 * template content based on a boolean flag.
41 */
42 class DomIf extends Polymer.Element {
43
44 // Not needed to find template; can be removed once the analyzer
45 // can find the tag name from customElements.define call
46 static get is() { return 'dom-if'; }
47
48 static get template() { return null; }
49
50 static get properties() {
51
52 return {
53
54 /**
55 * Fired whenever DOM is added or removed/hidden by this template (by
56 * default, rendering occurs lazily). To force immediate rendering, cal l
57 * `render`.
58 *
59 * @event dom-change
60 */
61
62 /**
63 * A boolean indicating whether this template should stamp.
64 */
65 if: {
66 type: Boolean,
67 observer: '__debounceRender'
68 },
69
70 /**
71 * When true, elements will be removed from DOM and discarded when `if`
72 * becomes false and re-created and added back to the DOM when `if`
73 * becomes true. By default, stamped elements will be hidden but left
74 * in the DOM when `if` becomes false, which is generally results
75 * in better performance.
76 */
77 restamp: {
78 type: Boolean,
79 observer: '__debounceRender'
80 }
81
82 }
83
84 }
85
86 constructor() {
87 super();
88 this.__renderDebouncer = null;
89 this.__invalidProps = null;
90 this.__instance = null;
91 }
92
93 __debounceRender() {
94 // Render is async for 2 reasons:
95 // 1. To eliminate dom creation trashing if user code thrashes `if` in the
96 // same turn. This was more common in 1.x where a compound computed
97 // property could result in the result changing multiple times, but is
98 // mitigated to a large extent by batched property processing in 2.x.
99 // 2. To avoid double object propagation when a bag including values bound
100 // to the `if` property as well as one or more hostProps could enqueue
101 // the <dom-if> to flush before the <template>'s host property
102 // forwarding. In that scenario creating an instance would result in
103 // the host props being set once, and then the enqueued changes on the
104 // template would set properties a second time, potentially causing an
105 // object to be set to an instance more than once. Creating the
106 // instance async from flushing data ensures this doesn't happen. If
107 // we wanted a sync option in the future, simply having <dom-if> flush
108 // (or clear) its template's pending host properties before creating
109 // the instance would also avoid the problem.
110 this.__renderDebouncer = Polymer.Debouncer.debounce(
111 this.__renderDebouncer
112 , Polymer.Async.microTask
113 , () => this.__render());
114 Polymer.enqueueDebouncer(this.__renderDebouncer);
115 }
116
117 disconnectedCallback() {
118 super.disconnectedCallback();
119 if (!this.parentNode ||
120 (this.parentNode.nodeType == Node.DOCUMENT_FRAGMENT_NODE &&
121 !this.parentNode.host)) {
122 this.__teardownInstance();
123 }
124 }
125
126 connectedCallback() {
127 super.connectedCallback();
128 if (this.if) {
129 this.__debounceRender();
130 }
131 }
132
133 /**
134 * Forces the element to render its content. Normally rendering is
135 * asynchronous to a provoking change. This is done for efficiency so
136 * that multiple changes trigger only a single render. The render method
137 * should be called if, for example, template rendering is required to
138 * validate application state.
139 */
140 render() {
141 Polymer.flush();
142 }
143
144 __render() {
145 if (this.if) {
146 if (!this.__ensureInstance()) {
147 // No template found yet
148 return;
149 }
150 this._showHideChildren();
151 } else if (this.restamp) {
152 this.__teardownInstance();
153 }
154 if (!this.restamp && this.__instance) {
155 this._showHideChildren();
156 }
157 if (this.if != this._lastIf) {
158 this.dispatchEvent(new CustomEvent('dom-change', {
159 bubbles: true,
160 composed: true
161 }));
162 this._lastIf = this.if;
163 }
164 }
165
166 __ensureInstance() {
167 let parentNode = this.parentNode;
168 // Guard against element being detached while render was queued
169 if (parentNode) {
170 if (!this.__ctor) {
171 let template = this.querySelector('template');
172 if (!template) {
173 // Wait until childList changes and template should be there by then
174 let observer = new MutationObserver(() => {
175 if (this.querySelector('template')) {
176 observer.disconnect();
177 this.__render();
178 } else {
179 throw new Error('dom-if requires a <template> child');
180 }
181 })
182 observer.observe(this, {childList: true});
183 return false;
184 }
185 this.__ctor = Polymer.Templatize.templatize(template, this, {
186 // dom-if templatizer instances require `mutable: true`, as
187 // `__syncHostProperties` relies on that behavior to sync objects
188 mutableData: true,
189 forwardHostProp: function(prop, value) {
190 if (this.__instance) {
191 if (this.if) {
192 this.__instance.forwardHostProp(prop, value);
193 } else {
194 // If we have an instance but are squelching host property
195 // forwarding due to if being false, note the invalidated
196 // properties so `__syncHostProperties` can sync them the next
197 // time `if` becomes true
198 this.__invalidProps = this.__invalidProps || Object.create(nul l);
199 this.__invalidProps[Polymer.Path.root(prop)] = true;
200 }
201 }
202 }
203 });
204 }
205 if (!this.__instance) {
206 this.__instance = new this.__ctor();
207 parentNode.insertBefore(this.__instance.root, this);
208 } else {
209 this.__syncHostProperties();
210 let c$ = this.__instance.children;
211 if (c$ && c$.length) {
212 // Detect case where dom-if was re-attached in new position
213 let lastChild = this.previousSibling;
214 if (lastChild !== c$[c$.length-1]) {
215 for (let i=0, n; (i<c$.length) && (n=c$[i]); i++) {
216 parentNode.insertBefore(n, this);
217 }
218 }
219 }
220 }
221 }
222 return true;
223 }
224
225 __syncHostProperties() {
226 let props = this.__invalidProps;
227 if (props) {
228 for (let prop in props) {
229 this.__instance._setPendingProperty(prop, this.__dataHost[prop]);
230 }
231 this.__invalidProps = null;
232 this.__instance._flushProperties();
233 }
234 }
235
236 __teardownInstance() {
237 if (this.__instance) {
238 let c$ = this.__instance.children;
239 if (c$ && c$.length) {
240 // use first child parent, for case when dom-if may have been detached
241 let parent = c$[0].parentNode;
242 for (let i=0, n; (i<c$.length) && (n=c$[i]); i++) {
243 parent.removeChild(n);
244 }
245 }
246 this.__instance = null;
247 this.__invalidProps = null;
248 }
249 }
250
251 _showHideChildren() {
252 let hidden = this.__hideTemplateChildren__ || !this.if;
253 if (this.__instance) {
254 this.__instance._showHideChildren(hidden);
255 }
256 }
257
258 }
259
260 customElements.define(DomIf.is, DomIf);
261
262 Polymer.DomIf = DomIf;
263
264 })();
265 </script>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698