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