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