2 YUI 3.13.0 (build 508226d)
3 Copyright 2013 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
8 YUI.add('app-transitions-native', function (Y, NAME) {
11 Provides the implementation of view transitions for `Y.App.Transitions` in
12 browsers which support native CSS3 transitions.
15 @submodule app-transitions-native
19 var AppTransitions = Y.App.Transitions;
22 Provides the implementation of view transitions for `Y.App.Transitions` in
23 browsers which support native CSS3 transitions.
25 When this module is used, `Y.App.TransitionsNative` will automatically mix
28 @class App.TransitionsNative
32 function AppTransitionsNative() {}
34 AppTransitionsNative.prototype = {
35 // -- Protected Properties -------------------------------------------------
38 Whether this app is currently transitioning its `activeView`.
40 @property _transitioning
48 A queue that holds pending calls to this app's `_uiTransitionActiveView()`
51 @property _viewTransitionQueue
58 // -- Lifecycle Methods ----------------------------------------------------
60 initializer: function () {
61 this._transitioning = false;
62 this._viewTransitionQueue = [];
64 // TODO: Consider the AOP approach that `Plugin.WidgetAnim` uses.
65 Y.Do.before(this._queueActiveView, this, '_uiSetActiveView');
68 // -- Protected Methods ----------------------------------------------------
71 Dequeues any pending calls to `_uiTransitionActiveView()`.
73 **Note:** When there is more than one queued transition, only the most
74 recent `activeView` change will be visually transitioned, while the others
75 will have their `transition` option overridden to `false`.
77 @method _dequeueActiveView
81 _dequeueActiveView: function () {
82 var queue = this._viewTransitionQueue,
83 transition = queue.shift(),
87 // When items are still left in the queue, override the transition
88 // so it does not run.
90 // Overrides `transition` option and splices in the new options.
91 options = Y.merge(transition[2], {transition: false});
92 transition.splice(2, 1, options);
95 this._uiTransitionActiveView.apply(this, transition);
100 Returns an object containing a named fx for both `viewIn` and `viewOut`
101 based on the relationship between the specified `newView` and `oldView`.
104 @param {View} newView The view being transitioned-in.
105 @param {View} oldView The view being transitioned-out.
106 @param {String} [transition] The preferred transition to use.
107 @return {Object} An object containing a named fx for both `viewIn` and
112 _getFx: function (newView, oldView, transition) {
113 var fx = AppTransitions.FX,
114 transitions = this.get('transitions');
116 if (transition === false || !transitions) {
121 return fx[transition];
124 if (this._isChildView(newView, oldView)) {
125 return fx[transitions.toChild];
128 if (this._isParentView(newView, oldView)) {
129 return fx[transitions.toParent];
132 return fx[transitions.navigate];
136 Queues calls to `_uiTransitionActiveView()` to make sure a currently running
137 transition isn't interrupted.
139 **Note:** This method prevents the default `_uiSetActiveView()` method from
142 @method _queueActiveView
146 _queueActiveView: function () {
147 var args = Y.Array(arguments, 0, true);
149 this._viewTransitionQueue.push(args);
151 if (!this._transitioning) {
152 this._dequeueActiveView();
155 return new Y.Do.Prevent();
159 Performs the actual change of this app's `activeView` by visually
160 transitioning between the `newView` and `oldView` using any specified
163 The `newView` is attached to the app by rendering it to the `viewContainer`,
164 and making this app a bubble target of its events.
166 The `oldView` is detached from the app by removing it from the
167 `viewContainer`, and removing this app as a bubble target for its events.
168 The `oldView` will either be preserved or properly destroyed.
170 **Note:** This method overrides `_uiSetActiveView()` and provides all of its
171 functionality plus supports visual transitions. Also, the `activeView`
172 attribute is read-only and can be changed by calling the `showView()`
175 @method _uiTransitionActiveView
176 @param {View} newView The View which is now this app's `activeView`.
177 @param {View} [oldView] The View which was this app's `activeView`.
178 @param {Object} [options] Optional object containing any of the following
180 @param {Function} [options.callback] Optional callback function to call
181 after new `activeView` is ready to use, the function will be passed:
182 @param {View} options.callback.view A reference to the new
184 @param {Boolean} [options.prepend=false] Whether the `view` should be
185 prepended instead of appended to the `viewContainer`.
186 @param {Boolean} [options.render] Whether the `view` should be rendered.
187 **Note:** If no value is specified, a view instance will only be
188 rendered if it's newly created by this method.
189 @param {Boolean|String} [options.transition] Optional transition override.
190 A transition can be specified which will override the default, or
191 `false` for no transition.
192 @param {Boolean} [options.update=false] Whether an existing view should
193 have its attributes updated by passing the `config` object to its
194 `setAttrs()` method. **Note:** This option does not have an effect if
195 the `view` instance is created as a result of calling this method.
199 _uiTransitionActiveView: function (newView, oldView, options) {
200 options || (options = {});
202 var callback = options.callback,
203 container, transitioning, isChild, isParent, prepend,
204 fx, fxConfig, transitions;
206 // Quits early when to new and old views are the same.
207 if (newView === oldView) {
208 callback && callback.call(this, newView);
210 this._transitioning = false;
211 return this._dequeueActiveView();
214 fx = this._getFx(newView, oldView, options.transition);
215 isChild = this._isChildView(newView, oldView);
216 isParent = !isChild && this._isParentView(newView, oldView);
217 prepend = !!options.prepend || isParent;
219 // Preforms simply attach/detach of the new and old view respectively
220 // when there's no transition to perform.
222 this._attachView(newView, prepend);
223 this._detachView(oldView);
224 callback && callback.call(this, newView);
226 this._transitioning = false;
227 return this._dequeueActiveView();
230 this._transitioning = true;
232 container = this.get('container');
233 transitioning = Y.App.CLASS_NAMES.transitioning;
235 container.addClass(transitioning);
237 this._attachView(newView, prepend);
239 // Called when view transitions completed, if none were added this will
241 function complete() {
242 this._detachView(oldView);
243 container.removeClass(transitioning);
244 callback && callback.call(this, newView);
246 this._transitioning = false;
247 return this._dequeueActiveView();
250 // Setup a new stack to run the view transitions in parallel.
251 transitions = new Y.Parallel({context: this});
253 crossView: !!oldView && !!newView,
257 // Transition the new view first to prevent a gap when sliding.
258 if (newView && fx.viewIn) {
259 newView.get('container')
260 .transition(fx.viewIn, fxConfig, transitions.add());
263 if (oldView && fx.viewOut) {
264 oldView.get('container')
265 .transition(fx.viewOut, fxConfig, transitions.add());
268 transitions.done(complete);
272 // -- Transition fx ------------------------------------------------------------
273 Y.mix(Y.Transition.fx, {
279 start: function (data) {
280 var styles = {opacity: 0},
281 config = data.config;
283 if (config.crossView && !config.prepended) {
284 styles.transform = 'translateX(-100%)';
287 this.setStyles(styles);
291 this.setStyle('transform', 'translateX(0)');
301 start: function (data) {
302 var styles = {opacity: 1},
303 config = data.config;
305 if (config.crossView && config.prepended) {
306 styles.transform = 'translateX(-100%)';
309 this.setStyles(styles);
313 this.setStyle('transform', 'translateX(0)');
320 transform: 'translateX(-100%)',
326 transform: 'translateX(0%)'
331 this.setStyle('transform', 'translateX(0)');
338 transform: 'translateX(0)',
344 transform: 'translateX(-100%)'
349 this.setStyle('transform', 'translateX(0)');
355 // -- Namespacae ---------------------------------------------------------------
356 Y.App.TransitionsNative = AppTransitionsNative;
357 Y.Base.mix(Y.App, [AppTransitionsNative]);
360 }, '3.13.0', {"requires": ["app-transitions", "app-transitions-css", "parallel", "transition"]});