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