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