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