Remove LOAD_SUB_FRAME load flag.
[chromium-blink-merge.git] / third_party / polymer / components / core-animated-pages / core-animated-pages.html
blobaea4b43f3c421d54f5d85f9ee156829c343d91a8
1 <!--
2 @license
3 Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
4 This code may only be used under the BSD style license found at http://polymer.github.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/CONTRIBUTORS.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/PATENTS.txt
9 -->
10 <link href="../core-selector/core-selector.html" rel="import">
11 <link href="../core-resizable/core-resizable.html" rel="import">
13 <link href="transitions/hero-transition.html" rel="import">
14 <link href="transitions/cross-fade.html" rel="import">
16 <!--
18 `core-animated-pages` selects one of its children "pages" to show and runs a transition
19 when switching between them. The transitions are designed to be pluggable, and can
20 accept any object that is an instance of a `core-transition-pages`. Transitions to run
21 are specified in the `transitions` attribute as a space-delimited string of `id`s of
22 transition elements. Several transitions are available with `core-animated-pages` by
23 default, including `hero-transition`, `cross-fade`, and `tile-cascade`.
25 Example:
27 <style>
28 #hero1 {
29 position: absolute;
30 top: 0;
31 left: 0;
32 width: 300px;
33 height: 300px;
34 background-color: orange;
36 #hero2 {
37 position: absolute;
38 top: 200px;
39 left: 300px;
40 width: 300px;
41 height: 300px;
42 background-color: orange;
44 #bottom1, #bottom2 {
45 position: absolute;
46 bottom: 0;
47 top: 0;
48 left: 0;
49 height: 50px;
51 #bottom1 {
52 background-color: blue;
54 #bottom2 {
55 background-color: green;
57 </style>
58 // hero-transition and cross-fade are declared elsewhere
59 <core-animated-pages transitions="hero-transition cross-fade">
60 <section id="page1">
61 <div id="hero1" hero-id="hero" hero></div>
62 <div id="bottom1" cross-fade></div>
63 </section>
64 <section id="page2">
65 <div id="hero2" hero-id="hero" hero></div>
66 <div id="bottom2" cross-fade></div>
67 </section>
68 </core-animated-pages>
70 In the above example, two transitions (`hero-transition` and `cross-fade`) are run when switching
71 between `page1` and `page2`. `hero-transition` transforms elements with the same `hero-id` such
72 that they appear to be shared across different pages. `cross-fade` fades out the elements marked
73 `cross-fade` in the outgoing page, and fades in those in the incoming page. See the individual
74 transition's documentation for specific details.
76 Finding elements to transition
77 ------------------------------
79 In general, a transition is applied to elements marked with a certain attribute. For example,
80 `hero-transition` applies the transition on elements with the `hero` and `hero-id` attribute.
81 Among the transitions included with `core-animated-pages`, script-based transitions such as
82 `hero-transition` generally look for elements up to one level of shadowRoot from the
83 `core-animated-pages` element, and CSS-based transitions such as `cross-fade` look for elements
84 within any shadowRoot within the `core-animated-pages` element. This means you can use
85 custom elements as pages and mark elements in their shadowRoots as heroes, or mark
86 elements in deeper shadowRoots with other transitions.
88 Example:
90 <polymer-element name="x-el" noscript>
91 <template>
92 <style>
93 #hero {
94 position: absolute;
95 top: 0;
96 right: 0;
97 width: 50px;
98 height: 300px;
99 background-color: blue;
101 </style>
102 <div id="hero" hero-id="bar" hero></div>
103 </template>
104 </polymer-element>
106 <polymer-element name="x-page-1" noscript>
107 <template>
108 <style>
109 #hero1 {
110 position: absolute;
111 top: 0;
112 left: 0;
113 width: 300px;
114 height: 300px;
115 background-color: orange;
117 </style>
118 <div id="hero1" hero-id="foo" hero></div>
119 <div id="hero2" hero-id="bar" hero></div>
120 </template>
121 </polymer-element>
123 <polymer-element name="x-page-2" noscript>
124 <template>
125 <style>
126 #hero1 {
127 position: absolute;
128 top: 200px;
129 left: 300px;
130 width: 300px;
131 height: 300px;
132 background-color: orange;
134 #hero2 {
135 background-color: blue;
136 height: 150px;
137 width: 400px;
139 </style>
140 // The below element is one level of shadow from the core-animated-pages and will
141 // be transitioned.
142 <div id="hero1" hero-id="foo" hero></div>
143 // The below element contains a hero inside its shadowRoot making it two levels away
144 // from the core-animated-pages, and will not be transitioned.
145 <x-el></x-el>
146 </template>
147 </polymer-element>
149 <core-animated-pages transitions="hero-transition">
150 <x-page-1></x-page-1>
151 <x-page-2></x-page-2>
152 </core-animated-pages>
154 Note that the container element of the page does not participate in the transition.
156 // This does not work
157 <core-animated-pages transitions="cross-fade">
158 <section cross-fade></section>
159 <section cross-fade></section>
160 </core-animated-pages>
162 // This works
163 <core-animated-pages transitions="cross-fade">
164 <section>
165 <div cross-fade></div>
166 </section>
167 <section>
168 <div cross-fade></div>
169 </section>
170 </core-animated-pages>
172 Dynamically setting up transitions
173 ----------------------------------
175 An easy way to set up transitions dynamically is to use property binding on
176 the transition attributes.
178 Example:
180 <core-animated-pages selected="{{selected}}">
181 <section id="page1">
182 <div hero-id="hero" hero></div>
183 </section>
184 <section id="page2">
185 <div id="foo" hero-id="hero" hero?="{{selected === 1 || selected === 0}}" cross-fade="{{selected === 2}}"></div>
186 </section>
187 <section id="page3">
188 </section>
189 </core-animated-pages>
191 In the above example, the "foo" element only behaves as a hero element if transitioning between
192 `#page1` and `#page2`. It gets cross-faded when transition to or from `#page3`.
194 Nesting pages
195 -------------
197 It is possible to nest core-animated-pages elements for organization. Excessive nesting is
198 not encouraged, however, since it makes setting up the transition more complex.
200 To nest core-animated-pages, the page containing the nested core-animated-pages element should
201 have a `selectedItem` property bound to the `selectedItem` property of the nested element. This
202 will allow the outer core-animated-pages to know which nested page it is actually transitioning
205 Example:
207 <polymer-element name="nested-page" attributes="selectedItem">
208 <template>
209 <core-animated-pages selectedItem="{{selectedItem}}">
211 </core-animated-pages>
212 </template>
213 </polymer-element>
215 <core-animated-pages>
216 <section id="page1"></section>
217 <nested-page id="page2"></nested-page>
218 </core-animated-pages>
220 @element core-animated-pages
221 @extends core-selector
222 @status beta
223 @homepage github.io
225 <!--
226 Fired before a page transition occurs. Both pages involved in the transition are visible when
227 this event fires. This is useful if there is something the client needs to do when a page becomes
228 visible.
230 @event core-animated-pages-transition-prepare
232 <!--
233 Fired when a page transition completes.
235 @event core-animated-pages-transition-end
237 <polymer-element name="core-animated-pages" extends="core-selector" notap attributes="transitions">
239 <template>
241 <link href="core-animated-pages.css" rel="stylesheet">
243 <shadow></shadow>
245 </template>
247 <script>
249 Polymer(Polymer.mixin({
251 eventDelegates: {
252 'core-transitionend': 'transitionEnd'
256 * A space-delimited string of transitions to use when switching between pages in this element.
257 * The strings are `id`s of `core-transition-pages` elements included elsewhere. See the
258 * individual transition's document for specific details.
260 * @attribute transitions
261 * @type string
262 * @default ''
264 transitions: '',
266 selected: 0,
269 * The last page selected. This property is useful to dynamically set transitions based
270 * on incoming and outgoing pages.
272 * @attribute lastSelected
273 * @type Object
274 * @default null
276 lastSelected: null,
278 registerCallback: function() {
279 this.tmeta = document.createElement('core-transition');
282 created: function() {
283 this._transitions = [];
284 this.transitioning = [];
287 attached: function() {
288 this.resizerAttachedHandler();
291 detached: function() {
292 this.resizerDetachedHandler();
295 transitionsChanged: function() {
296 this._transitions = this.transitions.split(' ');
299 _transitionsChanged: function(old) {
300 if (this._transitionElements) {
301 this._transitionElements.forEach(function(t) {
302 t.teardown(this);
303 }, this);
305 this._transitionElements = [];
306 this._transitions.forEach(function(transitionId) {
307 var t = this.getTransition(transitionId);
308 if (t) {
309 this._transitionElements.push(t);
310 t.setup(this);
312 }, this);
315 getTransition: function(transitionId) {
316 return this.tmeta.byId(transitionId);
319 selectionSelect: function(e, detail) {
320 this.updateSelectedItem();
321 // Wait to call applySelection when we run the transition
324 applyTransition: function(src, dst) {
325 if (this.animating) {
326 this.cancelAsync(this.animating);
327 this.animating = null;
330 Polymer.flush();
332 if (this.transitioning.indexOf(src) === -1) {
333 this.transitioning.push(src);
335 if (this.transitioning.indexOf(dst) === -1) {
336 this.transitioning.push(dst);
338 // force src, dst to display
339 src.setAttribute('animate', '');
340 dst.setAttribute('animate', '');
342 var options = {
343 src: src,
344 dst: dst,
345 easing: 'cubic-bezier(0.4, 0, 0.2, 1)'
348 // fire an event so clients have a chance to do something when the
349 // new page becomes visible but before it draws.
350 this.fire('core-animated-pages-transition-prepare');
353 // prepare transition
354 this._transitionElements.forEach(function(transition) {
355 transition.prepare(this, options);
356 }, this);
358 // force layout!
359 src.offsetTop;
362 // apply selection
363 this.applySelection(dst, true);
364 this.applySelection(src, false);
366 // start transition
367 this._transitionElements.forEach(function(transition) {
368 transition.go(this, options);
369 }, this);
371 if (!this._transitionElements.length) {
372 this.complete();
373 } else {
374 this.animating = this.async(this.complete.bind(this), null, 5000);
378 complete: function() {
379 if (this.animating) {
380 this.cancelAsync(this.animating);
381 this.animating = null;
384 this.transitioning.forEach(function(t) {
385 t.removeAttribute('animate');
387 this.transitioning = [];
389 this._transitionElements.forEach(function(transition) {
390 transition.ensureComplete(this);
391 }, this);
393 this.fire('core-animated-pages-transition-end');
396 transitionEnd: function(e) {
397 if (this.transitioning.length) {
398 var completed = true;
399 this._transitionElements.forEach(function(transition) {
400 if (!transition.completed) {
401 completed = false;
404 if (completed) {
405 this.job('transitionWatch', function() {
406 this.complete();
407 }, 100);
412 selectedChanged: function(old) {
413 this.lastSelected = old;
414 this.super(arguments);
417 selectedItemChanged: function(oldItem) {
418 this.super(arguments);
420 if (!oldItem) {
421 this.applySelection(this.selectedItem, true);
422 return;
425 if (this.hasAttribute('no-transition') || !this._transitionElements || !this._transitionElements.length) {
426 this.applySelection(oldItem, false);
427 this.applySelection(this.selectedItem, true);
428 this.notifyResize();
429 return;
432 if (oldItem && this.selectedItem) {
433 // TODO(sorvell): allow bindings to update first?
434 var self = this;
435 Polymer.flush();
436 Polymer.endOfMicrotask(function() {
437 self.applyTransition(oldItem, self.selectedItem);
438 self.notifyResize();
443 resizerShouldNotify: function(el) {
444 // Only notify descendents of selected item
445 while (el && (el != this)) {
446 if (el == this.selectedItem) {
447 return true;
449 el = el.parentElement || (el.parentNode && el.parentNode.host);
453 }, Polymer.CoreResizer));
455 </script>
457 </polymer-element>