1 // ==========================================================================
  2 // Project:   SproutCore
  3 // Copyright: @2013 7x7 Software, Inc.
  4 // License:   Licensed under MIT license (see license.js)
  5 // ==========================================================================
  6 
  7 
  8 SC.mixin(SC.View,
  9   /** @scope SC.View */ {
 10 
 11   /** @class
 12 
 13     @extends SC.ViewTransitionProtocol
 14     @since Version 1.10
 15   */
 16   SPRING_IN: {
 17 
 18     /** @private */
 19     setup: function (view, options, inPlace) {
 20       var parentView = view.get('parentView'),
 21         parentFrame,
 22         viewFrame = view.get('borderFrame'),
 23         left,
 24         top;
 25 
 26       if (inPlace) {
 27         // Move from the current position.
 28       } else {
 29         // If there is no parentView, use the window's frame.
 30         if (parentView) {
 31           parentFrame = parentView.get('borderFrame');
 32         } else {
 33           parentFrame = SC.RootResponder.responder.currentWindowSize;
 34         }
 35 
 36         switch (options.direction) {
 37         case 'left':
 38           left = parentFrame.width;
 39           break;
 40         case 'up':
 41           top = parentFrame.height;
 42           break;
 43         case 'down':
 44           top = -viewFrame.height;
 45           break;
 46         default:
 47           left = -viewFrame.width;
 48         }
 49       }
 50 
 51       view.adjust({ centerX: null, centerY: null, bottom: null, left: left || viewFrame.x, right: null, top: top || viewFrame.y, height: viewFrame.height, width: viewFrame.width });
 52     },
 53 
 54     /** @private */
 55     run: function (view, options, finalLayout, finalFrame) {
 56       var layout = view.get('layout'),
 57         springiness = options.springiness || 0.25,
 58         spring,
 59         duration,
 60         frames,
 61         finalValue,
 62         spring1, spring2, spring3,
 63         value;
 64 
 65       switch (options.direction) {
 66       case 'left':
 67         finalValue = finalFrame.x;
 68         value = { left: finalValue };
 69         spring = (layout.left - finalValue) * springiness;
 70         spring1 = { left: finalValue - spring };
 71         spring2 = { left: finalValue + (spring * 0.5) };
 72         spring3 = { left: finalValue - (spring * 0.25) };
 73         break;
 74       case 'up':
 75         finalValue = finalFrame.y;
 76         value = { top: finalValue };
 77         spring = (layout.top - finalValue) * springiness;
 78         spring1 = { top: finalValue - spring };
 79         spring2 = { top: finalValue + (spring * 0.5) };
 80         spring3 = { top: finalValue - (spring * 0.25) };
 81         break;
 82       case 'down':
 83         finalValue = finalFrame.y;
 84         value = { top: finalValue };
 85         spring = (finalValue - layout.top) * springiness;
 86         spring1 = { top: finalValue + spring };
 87         spring2 = { top: finalValue - (spring * 0.5) };
 88         spring3 = { top: finalValue + (spring * 0.25) };
 89         break;
 90       default:
 91         finalValue = finalFrame.x;
 92         value = { left: finalValue };
 93         spring = (finalValue - layout.left) * springiness;
 94         spring1 = { left: finalValue + spring };
 95         spring2 = { left: finalValue - (spring * 0.5) };
 96         spring3 = { left: finalValue + (spring * 0.25) };
 97       }
 98 
 99       // Split the duration evenly per frame.
100       duration = options.duration || 0.4;
101       duration = duration * 0.25;
102 
103       // Define the frames.
104       frames = [
105         { value: spring1, duration: duration, timing: 'ease-out' }, // Overshoot.
106         { value: spring2, duration: duration, timing: 'ease-in-out' }, // Overshoot back.
107         { value: spring3, duration: duration, timing: 'ease-in-out' }, // Overshoot.
108         { value: value, duration: duration, timing: 'ease-in-out' } // Hit target.
109       ];
110 
111       var callback = function (data) {
112         if (!data.isCancelled) {
113           view.didTransitionIn();
114         }
115       };
116 
117       // Animate through the frames.
118       view._animateFrames(frames, callback, options.delay || 0);
119     }
120   },
121 
122   /** @class
123 
124     @extends SC.ViewTransitionProtocol
125     @since Version 1.10
126   */
127   SPRING_OUT: {
128 
129     /** @private */
130     setup: function (view, options) {
131       var viewFrame = view.get('borderFrame'),
132         left = viewFrame.x,
133         top = viewFrame.y,
134         height = viewFrame.height,
135         width = viewFrame.width;
136 
137       view.adjust({ centerX: null, centerY: null, bottom: null, left: left, right: null, top: top, height: height, width: width });
138     },
139 
140     /** @private */
141     run: function (view, options, finalLayout, finalFrame) {
142       var springiness = options.springiness || 0.25,
143         duration,
144         finalValue,
145         frames,
146         layout = view.get('layout'),
147         viewFrame = view.get('borderFrame'),
148         parentView = view.get('parentView'),
149         parentFrame,
150         spring,
151         spring1, spring2;
152 
153       // If there is no parentView, use the window's frame.
154       if (parentView) {
155         parentFrame = parentView.get('borderFrame');
156       } else {
157         parentFrame = SC.RootResponder.responder.currentWindowSize;
158       }
159 
160       switch (options.direction) {
161       case 'left':
162         finalValue = { left: -viewFrame.width };
163         spring = (layout.left + viewFrame.width) * springiness;
164         spring1 = { left: layout.left - (spring * 0.5) };
165         spring2 = { left: layout.left + spring };
166         break;
167       case 'up':
168         finalValue = { top: -viewFrame.height };
169         spring = (layout.top + viewFrame.height) * springiness;
170         spring1 = { top: layout.top - (spring * 0.5) };
171         spring2 = { top: layout.top + spring };
172         break;
173       case 'down':
174         finalValue = { top: parentFrame.height };
175         spring = (parentFrame.height - layout.top) * springiness;
176         spring1 = { top: layout.top + (spring * 0.5) };
177         spring2 = { top: layout.top - spring };
178         break;
179       default:
180         finalValue = { left: parentFrame.width };
181         spring = (parentFrame.width - layout.left) * springiness;
182         spring1 = { left: layout.left + (spring * 0.5) };
183         spring2 = { left: layout.left - spring };
184       }
185 
186       // Split the duration evenly per frame.
187       duration = options.duration || 0.3;
188       duration = duration * 0.33;
189 
190       // Define the frames.
191       frames = [
192         { value: spring1, duration: duration, timing: 'ease-in-out' },
193         { value: spring2, duration: duration, timing: 'ease-in-out' },
194         { value: finalValue, duration: duration, timing: 'ease-in' }
195       ];
196 
197       var callback = function (data) {
198         if (!data.isCancelled) {
199           view.didTransitionOut();
200         }
201       };
202 
203       // Animate through the frames.
204       view._animateFrames(frames, callback, options.delay || 0);
205     }
206   }
207 });
208