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
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">
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`.
34 background-color: orange;
42 background-color: orange;
52 background-color: blue;
55 background-color: green;
58 // hero-transition and cross-fade are declared elsewhere
59 <core-animated-pages transitions="hero-transition cross-fade">
61 <div id="hero1" hero-id="hero" hero></div>
62 <div id="bottom1" cross-fade></div>
65 <div id="hero2" hero-id="hero" hero></div>
66 <div id="bottom2" cross-fade></div>
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.
90 <polymer-element name="x-el" noscript>
99 background-color: blue;
102 <div id="hero" hero-id="bar" hero></div>
106 <polymer-element name="x-page-1" noscript>
115 background-color: orange;
118 <div id="hero1" hero-id="foo" hero></div>
119 <div id="hero2" hero-id="bar" hero></div>
123 <polymer-element name="x-page-2" noscript>
132 background-color: orange;
135 background-color: blue;
140 // The below element is one level of shadow from the core-animated-pages and will
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.
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>
163 <core-animated-pages transitions="cross-fade">
165 <div cross-fade></div>
168 <div cross-fade></div>
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.
180 <core-animated-pages selected="{{selected}}">
182 <div hero-id="hero" hero></div>
185 <div id="foo" hero-id="hero" hero?="{{selected === 1 || selected === 0}}" cross-fade="{{selected === 2}}"></div>
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`.
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
207 <polymer-element name="nested-page" attributes="selectedItem">
209 <core-animated-pages selectedItem="{{selectedItem}}">
211 </core-animated-pages>
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
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
230 @event core-animated-pages-transition-prepare
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">
241 <link href=
"core-animated-pages.css" rel=
"stylesheet">
249 Polymer(Polymer
.mixin({
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
269 * The last page selected. This property is useful to dynamically set transitions based
270 * on incoming and outgoing pages.
272 * @attribute lastSelected
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
) {
305 this._transitionElements
= [];
306 this._transitions
.forEach(function(transitionId
) {
307 var t
= this.getTransition(transitionId
);
309 this._transitionElements
.push(t
);
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;
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', '');
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
);
363 this.applySelection(dst
, true);
364 this.applySelection(src
, false);
367 this._transitionElements
.forEach(function(transition
) {
368 transition
.go(this, options
);
371 if (!this._transitionElements
.length
) {
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);
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
) {
405 this.job('transitionWatch', function() {
412 selectedChanged: function(old
) {
413 this.lastSelected
= old
;
414 this.super(arguments
);
417 selectedItemChanged: function(oldItem
) {
418 this.super(arguments
);
421 this.applySelection(this.selectedItem
, true);
425 if (this.hasAttribute('no-transition') || !this._transitionElements
|| !this._transitionElements
.length
) {
426 this.applySelection(oldItem
, false);
427 this.applySelection(this.selectedItem
, true);
432 if (oldItem
&& this.selectedItem
) {
433 // TODO(sorvell): allow bindings to update first?
436 Polymer
.endOfMicrotask(function() {
437 self
.applyTransition(oldItem
, self
.selectedItem
);
443 resizerShouldNotify: function(el
) {
444 // Only notify descendents of selected item
445 while (el
&& (el
!= this)) {
446 if (el
== this.selectedItem
) {
449 el
= el
.parentElement
|| (el
.parentNode
&& el
.parentNode
.host
);
453 }, Polymer
.CoreResizer
));