1 // ==========================================================================
  2 // Project:   SproutCore
  3 // Copyright: @2013 7x7 Software, Inc.
  4 // License:   Licensed under MIT license (see license.js)
  5 // ==========================================================================
  6 sc_require('views/container');
  7 
  8 
  9 SC.mixin(SC.ContainerView,
 10 /** @scope SC.ContainerView */ {
 11   /** @class
 12     Provides push transitions to SC.ContainerView.  The new content will push
 13     the old content out of the view.
 14 
 15     To modify the push animation, you can set the following transition options:
 16 
 17       - direction {String} the direction to push new content in.  Default: 'left'
 18         ** 'left' - pushes new content from the right to the left
 19         ** 'right' - pushes new content from the left to the right
 20         ** 'up' - pushes new content from the bottom to the top
 21         ** 'down' - pushes new content from the top to the bottom
 22       - duration {Number} the number of seconds for the animation.  Default: 0.4
 23       - timing {String} the animation timing function.  Default: 'ease'
 24 
 25     @extends SC.ViewTransitionProtocol
 26     @see SC.View#animate for other timing functions.
 27     @since Version 1.10
 28   */
 29   PUSH: {
 30 
 31     /** @private */
 32     willBuildInToView: function (container, content, previousStatechart, options) {
 33       var adjustLeft = 0,
 34         adjustTop = 0,
 35         frame = container.get('frame'),
 36         left = 0,
 37         top = 0,
 38         height,
 39         width;
 40 
 41       height = frame.height;
 42       width = frame.width;
 43 
 44       // Push on to the edge of whatever the current position of previous content is.
 45       if (previousStatechart && previousStatechart.get('content')) {
 46         var adjustments = previousStatechart.getPath('content.liveAdjustments');
 47 
 48         adjustLeft = adjustments.left || 0;
 49         adjustTop = adjustments.top || 0;
 50       }
 51 
 52       switch (options.direction) {
 53       case 'right':
 54         left = -width + adjustLeft;
 55         break;
 56       case 'up':
 57         top = height + adjustTop;
 58         break;
 59       case 'down':
 60         top = -height + adjustTop;
 61         break;
 62       default:
 63         left = width + adjustLeft;
 64       }
 65 
 66       // Convert to an animatable layout.
 67       content.adjust({ bottom: null, right: null, left: left, top: top, height: height, width: width });
 68     },
 69 
 70     /** @private */
 71     buildInToView: function (statechart, container, content, previousStatechart, options) {
 72       var key;
 73 
 74       switch (options.direction) {
 75       case 'up':
 76         key = 'top';
 77         break;
 78       case 'down':
 79         key = 'top';
 80         break;
 81       default:
 82         key = 'left';
 83       }
 84 
 85       content.animate(key, 0, {
 86         duration: options.duration || 0.4,
 87         timing: options.timing || 'ease'
 88       }, function (data) {
 89         // We may already be in exiting state by the time we transition in.
 90         if (statechart.get('state') === 'entering') {
 91           statechart.entered();
 92         }
 93       });
 94     },
 95 
 96     /** @private */
 97     didBuildInToView: function (container, content, options) {
 98       // Convert to a flexible layout.
 99       content.adjust({ bottom: 0, right: 0, height: null, width: null });
100     },
101 
102     /** @private */
103     willBuildOutFromView: function (container, content, options) {
104       var frame = container.get('frame'),
105         height,
106         width;
107 
108       height = frame.height;
109       width = frame.width;
110 
111       // Convert to an animatable layout.
112       content.adjust({ bottom: null, right: null, height: height, width: width });
113     },
114 
115     /** @private */
116     buildOutFromView: function (statechart, container, content, options, exitCount) {
117       var frame = container.get('frame'),
118         key,
119         value;
120 
121       switch (options.direction) {
122       case 'right':
123         key = 'left';
124         value = frame.width;
125         break;
126       case 'up':
127         key = 'top';
128         value = -frame.height;
129         break;
130       case 'down':
131         key = 'top';
132         value = frame.height;
133         break;
134       default:
135         key = 'left';
136         value = -frame.width;
137       }
138 
139       content.animate(key, value * exitCount, {
140         duration: options.duration || 0.4,
141         timing: options.timing || 'ease'
142       }, function (data) {
143         if (!data.isCancelled) {
144           statechart.exited();
145         }
146       });
147     },
148 
149     /** @private */
150     didBuildOutFromView: function (container, content, options) {
151       // Convert to a flexible layout.
152       content.adjust({ bottom: 0, right: 0, height: null, width: null });
153     },
154 
155     /** @private */
156     transitionClippingFrame: function (container, clippingFrame, options) {
157       var frame = container.get('frame');
158 
159       switch (options.direction) {
160       case 'right':
161         clippingFrame.width = frame.width * 2;
162         clippingFrame.x = -frame.width;
163         break;
164       case 'up':
165         clippingFrame.height = frame.height * 2;
166         clippingFrame.y = -frame.height;
167         break;
168       case 'down':
169         clippingFrame.height = frame.height * 2;
170         clippingFrame.y = 0;
171         break;
172       default:
173         clippingFrame.width = frame.width * 2;
174         clippingFrame.x = 0;
175       }
176 
177       return clippingFrame;
178     }
179   }
180 
181 });
182