1 2 3 Polymer('core-animated-pages',{ 4 5 eventDelegates: { 6 'core-transitionend': 'transitionEnd' 7 }, 8 9 /** 10 * A space-delimited string of transitions to use when switching between pages in this element. 11 * The strings are `id`s of `core-transition-pages` elements included elsewhere. See the 12 * individual transition's document for specific details. 13 * 14 * @attribute transitions 15 * @type string 16 * @default '' 17 */ 18 transitions: '', 19 20 selected: 0, 21 22 /** 23 * The last page selected. This property is useful to dynamically set transitions based 24 * on incoming and outgoing pages. 25 * 26 * @attribute lastSelected 27 * @type Object 28 * @default null 29 */ 30 lastSelected: null, 31 32 registerCallback: function() { 33 this.tmeta = document.createElement('core-transition'); 34 }, 35 36 created: function() { 37 this._transitions = []; 38 this.transitioning = []; 39 }, 40 41 transitionsChanged: function() { 42 this._transitions = this.transitions.split(' '); 43 }, 44 45 _transitionsChanged: function(old) { 46 if (this._transitionElements) { 47 this._transitionElements.forEach(function(t) { 48 t.teardown(this); 49 }, this); 50 } 51 this._transitionElements = []; 52 this._transitions.forEach(function(transitionId) { 53 var t = this.getTransition(transitionId); 54 if (t) { 55 this._transitionElements.push(t); 56 t.setup(this); 57 } 58 }, this); 59 }, 60 61 getTransition: function(transitionId) { 62 return this.tmeta.byId(transitionId); 63 }, 64 65 selectionSelect: function(e, detail) { 66 this.updateSelectedItem(); 67 // Wait to call applySelection when we run the transition 68 }, 69 70 applyTransition: function(src, dst) { 71 if (this.animating) { 72 this.cancelAsync(this.animating); 73 this.animating = null; 74 } 75 76 Platform.flush(); 77 78 if (this.transitioning.indexOf(src) === -1) { 79 this.transitioning.push(src); 80 } 81 if (this.transitioning.indexOf(dst) === -1) { 82 this.transitioning.push(dst); 83 } 84 // force src, dst to display 85 src.setAttribute('animate', ''); 86 dst.setAttribute('animate', ''); 87 // 88 var options = { 89 src: src, 90 dst: dst, 91 easing: 'cubic-bezier(0.4, 0, 0.2, 1)' 92 } 93 94 // fire an event so clients have a chance to do something when the 95 // new page becomes visible but before it draws. 96 this.fire('core-animated-pages-transition-prepare'); 97 98 // 99 // prepare transition 100 this._transitionElements.forEach(function(transition) { 101 transition.prepare(this, options); 102 }, this); 103 // 104 // force layout! 105 src.offsetTop; 106 107 // 108 // apply selection 109 this.applySelection(dst, true); 110 this.applySelection(src, false); 111 // 112 // start transition 113 this._transitionElements.forEach(function(transition) { 114 transition.go(this, options); 115 }, this); 116 117 if (!this._transitionElements.length) { 118 this.complete(); 119 } else { 120 this.animating = this.async(this.complete.bind(this), null, 5000); 121 } 122 }, 123 124 complete: function() { 125 if (this.animating) { 126 this.cancelAsync(this.animating); 127 this.animating = null; 128 } 129 130 this.transitioning.forEach(function(t) { 131 t.removeAttribute('animate'); 132 }); 133 this.transitioning = []; 134 135 this._transitionElements.forEach(function(transition) { 136 transition.ensureComplete(this); 137 }, this); 138 139 this.fire('core-animated-pages-transition-end'); 140 }, 141 142 transitionEnd: function(e) { 143 if (this.transitioning.length) { 144 var completed = true; 145 this._transitionElements.forEach(function(transition) { 146 if (!transition.completed) { 147 completed = false; 148 } 149 }); 150 if (completed) { 151 this.job('transitionWatch', function() { 152 this.complete(); 153 }, 100); 154 } 155 } 156 }, 157 158 selectedChanged: function(old) { 159 this.lastSelected = old; 160 this.super(arguments); 161 }, 162 163 selectedItemChanged: function(oldItem) { 164 this.super(arguments); 165 166 if (!oldItem) { 167 this.applySelection(this.selectedItem, true); 168 return; 169 } 170 171 if (this.hasAttribute('no-transition') || !this._transitionElements || !this._transitionElements.length) { 172 this.applySelection(oldItem, false); 173 this.applySelection(this.selectedItem, true); 174 return; 175 } 176 177 if (oldItem && this.selectedItem) { 178 // TODO(sorvell): allow bindings to update first? 179 var self = this; 180 Platform.flush(); 181 Platform.endOfMicrotask(function() { 182 self.applyTransition(oldItem, self.selectedItem); 183 }); 184 } 185 } 186 187 }); 188 189