2015-06-19 09:36:51 -07:00
|
|
|
<!--
|
|
|
|
Copyright (c) 2015 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/polymer.html">
|
|
|
|
<link rel="import" href="../iron-resizable-behavior/iron-resizable-behavior.html">
|
|
|
|
<link rel="import" href="../iron-selector/iron-selectable.html">
|
|
|
|
<link rel="import" href="neon-animation-runner-behavior.html">
|
|
|
|
<link rel="import" href="animations/opaque-animation.html">
|
|
|
|
|
|
|
|
<!--
|
2015-12-14 08:43:03 -07:00
|
|
|
Material design: [Meaningful transitions](https://www.google.com/design/spec/animation/meaningful-transitions.html)
|
|
|
|
|
2015-06-19 09:36:51 -07:00
|
|
|
`neon-animated-pages` manages a set of pages and runs an animation when switching between them. Its
|
|
|
|
children pages should implement `Polymer.NeonAnimatableBehavior` and define `entry` and `exit`
|
|
|
|
animations to be run when switching to or switching out of the page.
|
|
|
|
|
|
|
|
@group Neon Elements
|
|
|
|
@element neon-animated-pages
|
|
|
|
@demo demo/index.html
|
|
|
|
-->
|
|
|
|
|
|
|
|
<dom-module id="neon-animated-pages">
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
|
|
|
:host {
|
|
|
|
display: block;
|
|
|
|
position: relative;
|
|
|
|
}
|
|
|
|
|
|
|
|
:host > ::content > * {
|
2015-07-08 17:20:01 -07:00
|
|
|
position: absolute;
|
|
|
|
top: 0;
|
|
|
|
left: 0;
|
|
|
|
bottom: 0;
|
|
|
|
right: 0;
|
2015-06-19 09:36:51 -07:00
|
|
|
height: 100%;
|
|
|
|
}
|
|
|
|
|
|
|
|
:host > ::content > :not(.iron-selected):not(.neon-animating) {
|
|
|
|
display: none !important;
|
|
|
|
}
|
|
|
|
|
|
|
|
:host > ::content > .neon-animating {
|
|
|
|
pointer-events: none;
|
|
|
|
}
|
|
|
|
|
|
|
|
</style>
|
|
|
|
|
|
|
|
<template>
|
|
|
|
<content id="content"></content>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</dom-module>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
(function() {
|
|
|
|
|
|
|
|
Polymer({
|
|
|
|
|
|
|
|
is: 'neon-animated-pages',
|
|
|
|
|
|
|
|
behaviors: [
|
|
|
|
Polymer.IronResizableBehavior,
|
|
|
|
Polymer.IronSelectableBehavior,
|
|
|
|
Polymer.NeonAnimationRunnerBehavior
|
|
|
|
],
|
|
|
|
|
|
|
|
properties: {
|
|
|
|
|
|
|
|
activateEvent: {
|
|
|
|
type: String,
|
|
|
|
value: ''
|
|
|
|
},
|
|
|
|
|
|
|
|
// if true, the initial page selection will also be animated according to its animation config.
|
|
|
|
animateInitialSelection: {
|
|
|
|
type: Boolean,
|
|
|
|
value: false
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
observers: [
|
|
|
|
'_selectedChanged(selected)'
|
|
|
|
],
|
|
|
|
|
|
|
|
listeners: {
|
|
|
|
'neon-animation-finish': '_onNeonAnimationFinish'
|
|
|
|
},
|
|
|
|
|
|
|
|
_selectedChanged: function(selected) {
|
|
|
|
|
|
|
|
var selectedPage = this.selectedItem;
|
2015-07-10 19:23:28 -07:00
|
|
|
var oldPage = this._valueToItem(this._prevSelected) || false;
|
|
|
|
this._prevSelected = selected;
|
2015-06-19 09:36:51 -07:00
|
|
|
|
|
|
|
// on initial load and if animateInitialSelection is negated, simply display selectedPage.
|
|
|
|
if (!oldPage && !this.animateInitialSelection) {
|
|
|
|
this._completeSelectedChanged();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// insert safari fix.
|
|
|
|
this.animationConfig = [{
|
|
|
|
name: 'opaque-animation',
|
|
|
|
node: selectedPage
|
|
|
|
}];
|
|
|
|
|
|
|
|
// configure selectedPage animations.
|
|
|
|
if (this.entryAnimation) {
|
|
|
|
this.animationConfig.push({
|
|
|
|
name: this.entryAnimation,
|
|
|
|
node: selectedPage
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
if (selectedPage.getAnimationConfig) {
|
|
|
|
this.animationConfig.push({
|
|
|
|
animatable: selectedPage,
|
|
|
|
type: 'entry'
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// configure oldPage animations iff exists.
|
|
|
|
if (oldPage) {
|
|
|
|
|
|
|
|
// cancel the currently running animation if one is ongoing.
|
|
|
|
if (oldPage.classList.contains('neon-animating')) {
|
|
|
|
this._squelchNextFinishEvent = true;
|
|
|
|
this.cancelAnimation();
|
|
|
|
this._completeSelectedChanged();
|
2015-12-14 08:43:03 -07:00
|
|
|
this._squelchNextFinishEvent = false;
|
2015-06-19 09:36:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// configure the animation.
|
|
|
|
if (this.exitAnimation) {
|
|
|
|
this.animationConfig.push({
|
|
|
|
name: this.exitAnimation,
|
|
|
|
node: oldPage
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
if (oldPage.getAnimationConfig) {
|
|
|
|
this.animationConfig.push({
|
|
|
|
animatable: oldPage,
|
|
|
|
type: 'exit'
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// display the oldPage during the transition.
|
|
|
|
oldPage.classList.add('neon-animating');
|
|
|
|
}
|
|
|
|
|
|
|
|
// display the selectedPage during the transition.
|
|
|
|
selectedPage.classList.add('neon-animating');
|
|
|
|
|
|
|
|
// actually run the animations.
|
|
|
|
if (this.animationConfig.length > 1) {
|
|
|
|
|
|
|
|
// on first load, ensure we run animations only after element is attached.
|
|
|
|
if (!this.isAttached) {
|
|
|
|
this.async(function () {
|
2015-06-25 18:13:51 -07:00
|
|
|
this.playAnimation(undefined, {
|
2015-06-19 09:36:51 -07:00
|
|
|
fromPage: null,
|
|
|
|
toPage: selectedPage
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
} else {
|
2015-06-25 18:13:51 -07:00
|
|
|
this.playAnimation(undefined, {
|
2015-06-19 09:36:51 -07:00
|
|
|
fromPage: oldPage,
|
|
|
|
toPage: selectedPage
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
this._completeSelectedChanged(oldPage, selectedPage);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2015-06-25 18:13:51 -07:00
|
|
|
/**
|
|
|
|
* @param {Object=} oldPage
|
|
|
|
* @param {Object=} selectedPage
|
|
|
|
*/
|
2015-06-19 09:36:51 -07:00
|
|
|
_completeSelectedChanged: function(oldPage, selectedPage) {
|
|
|
|
if (selectedPage) {
|
|
|
|
selectedPage.classList.remove('neon-animating');
|
|
|
|
}
|
|
|
|
if (oldPage) {
|
|
|
|
oldPage.classList.remove('neon-animating');
|
|
|
|
}
|
|
|
|
if (!selectedPage || !oldPage) {
|
|
|
|
var nodes = Polymer.dom(this.$.content).getDistributedNodes();
|
|
|
|
for (var node, index = 0; node = nodes[index]; index++) {
|
|
|
|
node.classList && node.classList.remove('neon-animating');
|
|
|
|
}
|
|
|
|
}
|
2015-06-25 18:13:51 -07:00
|
|
|
this.async(this._notifyPageResize);
|
2015-06-19 09:36:51 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
_onNeonAnimationFinish: function(event) {
|
|
|
|
if (this._squelchNextFinishEvent) {
|
|
|
|
this._squelchNextFinishEvent = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this._completeSelectedChanged(event.detail.fromPage, event.detail.toPage);
|
2015-06-25 18:13:51 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
_notifyPageResize: function() {
|
|
|
|
var selectedPage = this.selectedItem;
|
|
|
|
this.resizerShouldNotify = function(element) {
|
|
|
|
return element == selectedPage;
|
|
|
|
}
|
|
|
|
this.notifyResize();
|
2015-06-19 09:36:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
})();
|
|
|
|
</script>
|