ux/FlipCounter.js
[roojs1] / ux / FlipCounter.js
1
2
3 Roo.ux.FlipCounter = function(options)
4 {
5     Roo.apply(this, options);
6     //this.el = $(element);
7     //this.options = $.extend({}, defaults, options);
8      this.addEvents({
9         // raw events
10         /**
11          * @event flip
12          * When a box is flipped
13          * @param {Roo.ux.FlipCounter} counter
14          */
15         "flip" : true,
16         /**
17          * @event resize
18          * When a box is resized
19          * @param {Roo.ux.FlipCounter} counter
20          */
21         "resize" : true
22         
23          
24     });
25      
26     //this.init();
27
28
29     
30 }
31 Roo.extend(Roo.ux.FlipCounter, Roo.bootstrap.Component, {
32     
33     speed : 0.2,
34     startnumber : 0,
35     
36     getAutoCreate : function(){
37         
38         return {
39             tag: 'ul',
40             cls: 'flipcounter',
41             
42         };
43         
44     init : function ()
45     { 
46         var startNum = ""+ this.startnumber;
47         this.ulWidth = 0;
48         this.digits = new Array();
49         
50         for (i=startNum.length-1; i>=0; i=i-1)
51         {
52             this.addDigit(startNum[i]);
53         }
54     };
55     
56     FlipCounter.prototype.addDigit = function (num) {
57         // Add separator after every 3rd digit
58         if (this.digits.length % 3 == 0 && this.digits.length != 0)
59         {
60             this.addSeparator();
61         }
62         
63         this.ul.prepend('<li>\
64             <div class="numberwrap">\
65                 <div class="flipper_top flipper_top1"></div>\
66                 <div class="flipper_top flipper_top2 flipper_top_back">\
67                     <span>'+num+'</span>\
68                     <div class="rings"></div>\
69                 </div>\
70                 <div class="flipper_top flipper_top_front">\
71                     <span>'+num+'</span>\
72                     <div class="rings"></div>\
73                 </div>\
74                 <div class="flipper_bottom flipper_bottom4"></div>\
75                 <div class="flipper_bottom flipper_bottom3"></div>\
76                 <div class="flipper_bottom flipper_bottom2"></div>\
77                 <div class="flipper_bottom flipper_bottom1 flipper_bottom_back">\
78                     <span>'+num+'</span>\
79                     <div class="rings"></div>\
80                 </div>\
81                 <div class="flipper_bottom flipper_bottom_front">\
82                     <span>'+num+'</span>\
83                     <div class="rings"></div>\
84                 </div>\
85             </div>\
86         </li>');
87         
88         var li = this.ul.find('li:first-child');
89         var digit = new Digit(li, num);
90         digit.manager = this;
91         this.digits.push(digit);
92         
93         // Update width
94         this.ulWidth = this.ulWidth + digit.li.outerWidth(true);
95         this.ul.css('min-width', this.ulWidth);
96         this.ul.css('min-height', digit.li.outerHeight(true));
97     };
98     
99     FlipCounter.prototype.removeDigit = function () {
100         var digit = this.digits.splice(this.digits.length-1, 1)[0];
101         this.ulWidth = this.ulWidth - digit.li.outerWidth(true);
102         digit.li.remove();
103         
104         // Remove separators
105         if (this.digits.length % 3 == 0)
106         {
107             var comma = this.ul.find('li.comma:first-child');
108             this.ulWidth = this.ulWidth - comma.outerWidth(true);
109             comma.remove();
110         }
111         
112         // Update width to current
113         this.ul.css('min-width', this.ulWidth);
114     }
115     
116     FlipCounter.prototype.addSeparator = function (num) {
117         this.ul.prepend('<li class="comma">,</li>');
118         
119         // Update width
120         var comma = this.ul.find('li.comma:first-child');
121         this.ulWidth = this.ulWidth + comma.outerWidth(true);
122         this.ul.css('min-width', this.ulWidth);
123     };
124     
125     FlipCounter.prototype.updateTo = function (num) {
126         var numStr = parseInt(num).toString();
127         
128         // Change the number of digits displayed if needed
129         if (numStr.length != this.digits.length)
130         {
131             var diff = numStr.length - this.digits.length;
132             if (diff > 0)
133             {
134                 for (i=0; i<diff; i=i+1) {
135                     this.addDigit(0);
136                 }
137             }
138             else
139             {
140                 for (i=diff; i<0; i=i+1) {
141                     this.removeDigit();
142                 }
143             }
144             
145             this.options['onResize']();
146         }
147         
148         // Change all digit values
149         for (i=0; i<numStr.length; i=i+1)
150         {
151             this.digits[i].flipTo(numStr[numStr.length - 1 - i]);
152         }
153     };
154     
155     function Digit( element, currentNumber ) {
156         currentNumber = parseInt(currentNumber);
157         
158         this.li = $(element);
159         this.topFrontDiv = this.li.find('.flipper_top_front');
160         this.bottomFrontDiv = this.li.find('.flipper_bottom_front');
161         this.topNumBack = this.li.find('.flipper_top_back span');
162         this.topNumFront = this.li.find('.flipper_top_front span');
163         this.bottomNumBack = this.li.find('.flipper_bottom_back span');
164         this.bottomNumFront = this.li.find('.flipper_bottom_front span');
165         
166         this.targetNum = currentNumber;
167         this.currentNum = currentNumber;
168         this.nextNum = currentNumber;
169         
170         this.currentlyAnimating = false;
171     }
172     
173     Digit.prototype.flipTo = function (num) {
174         if (this.currentNum === num)
175             return;
176         
177         this.targetNum = num;
178         if (this.currentlyAnimating)
179             return;
180         
181         this.animNext();
182     };
183     
184     Digit.prototype.animNext = function () {
185         if (this.currentNum == this.targetNum)
186         {
187             this.currentlyAnimating = false;
188             return;
189         }
190         
191         var doRandomDelay = !this.currentlyAnimating;
192         this.currentlyAnimating = true;
193         this.nextNum = this.currentNum + 1;
194         if (this.nextNum > 9)
195             this.nextNum = 0;
196         
197         var delay = Math.random()/5;
198         if (!doRandomDelay) delay = 0.01;
199         
200         // Animate top flipper
201         var digit = this;
202         digit.topNumBack.html(digit.nextNum);
203         digit.topFrontDiv.tween({
204             transform: {
205                 start: 'scaleY(1)',
206                 stop: 'scaleY(0)',
207                 time: delay,
208                 duration: this.manager.options.speed,
209                 units: '',
210                 effect: 'easeIn'
211             }
212         }).play();
213         
214         // Animate bottom flipper with delay
215         digit.bottomFrontDiv.tween({
216             transform: {
217                 start: 'scaleY(0)',
218                 stop: 'scaleY(1)',
219                 time: delay + this.manager.options.speed,
220                 duration: this.manager.options.speed * 0.5,
221                 units: '',
222                 effect: 'easeOut',
223                 onStart: function() {
224                     digit.bottomNumFront.html(digit.nextNum);
225                 },
226                 onStop: function() {
227                     digit.currentNum = digit.nextNum;
228                     digit.topNumFront.html(digit.currentNum);
229                     digit.topFrontDiv.removeAttr('style', '');
230                     digit.bottomNumBack.html(digit.currentNum);
231                     digit.animNext();
232                     digit.manager.options['onFlip']();
233                 }
234             }
235         }).play();
236     }
237
238     // A really lightweight plugin wrapper around the constructor, 
239     // preventing against multiple instantiations
240     $.fn[pluginName+'Init'] = function ( options ) {
241         return this.each(function () {
242             if (!$.data(this, 'plugin_' + pluginName)) {
243                 $.data(this, 'plugin_' + pluginName, 
244                 new FlipCounter( this, options ));
245             }
246         });
247     }
248         
249     $.fn[pluginName+'Update'] = function ( num ) {
250         return this.each(function () {
251             var obj = $.data(this, 'plugin_' + pluginName);
252             if (obj) {
253                 obj.updateTo(num);
254             }
255         });
256     }
257
258 })( jQuery, window, document );