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