remove debugging code
[roojs1] / ux / FlipCounter.js
index 58d4675..0296373 100644 (file)
-/**
- * Apple-Style Flip Counter
- * Version 0.5.3 - May 7, 2011
- *
- * Copyright (c) 2010 Chris Nanney
- * http://cnanney.com/journal/code/apple-style-counter-revisited/
- *
- * Licensed under MIT
- * http://www.opensource.org/licenses/mit-license.php
- */
 
-var flipCounter = function(d, options){
 
-       // Default values
-       var defaults = {
-               value: 0,
-               inc: 1,
-               pace: 1000,
-               auto: true,
-               tFH: 39,
-               bFH: 64,
-               fW: 53,
-               bOffset: 390
-       };
-
-       var     doc = window.document,
-       divId = typeof d !== 'undefined' && d !== '' ? d : 'flip-counter',
-       div = doc.getElementById(divId);
-
-    var o = {};
-    for (var opt in defaults) {
-        o[opt] = (opt in options) ? options[opt] : defaults[opt];
+Roo.ux.FlipCounter = function(options)
+{
+    Roo.ux.FlipCounter.superclass.constructor.call(this, options);
+    
+    //Roo.apply(this, options);
+    //this.el = $(element);
+    //this.options = $.extend({}, defaults, options);
+    this.addEvents({
+        // raw events
+        /**
+         * @event flip
+         * When a box is flipped
+         * @param {Roo.ux.FlipCounter} counter
+         */
+        "flip" : true,
+        /**
+         * @event resize
+         * When a box is resized
+         * @param {Roo.ux.FlipCounter} counter
+         */
+        "resize" : true
+        
+         
+    });
+    this.digits = new Array();
+       
+    //this.init();
+
+
+    
+}
+Roo.extend(Roo.ux.FlipCounter, Roo.bootstrap.Component, {
+    
+    speed : 0.2,
+    startnumber : 0,
+    currentNumber : 0,
+    decimal : 0,
+    
+    digits : false, // array...
+    ulWidth : 0,
+    cls : '',
+    
+    getAutoCreate : function(){
+        
+        return {
+            tag: 'ul',
+            cls: 'flipcounter ' + this.cls,
+            
+        };
+    },
+        
+    initEvents : function ()
+    { 
+        
+        
+        var startNum = (1.0*this.startnumber).toFixed(this.decimal);
+        //Roo.log("STARTNUmber:  " + startNum);
+        
+        for (i=startNum.length-1; i>=0; i=i-1)
+        {
+            if (startNum[i] == '.') {
+                this.addSeparator('.');
+                continue;
+            }
+            this.addDigit(startNum[i]);
+        }
+        this.currentNumber = this.startnumber;
+    },
+    
+    addDigit : function (num)
+    {
+        
+        //Roo.log("Add digit "+ num);
+        // Add separator after every 3rd digit
+        if (this.decimal == 0 && this.digits.length % 3 == 0 && this.digits.length != 0) {
+            this.addSeparator(',');
+        }
+        
+          
+        
+        var digit = new Roo.ux.FlipCounter.Digit({ manager : this, currentNumber : num });
+        digit.manager = this;
+        this.digits.push(digit);
+        digit.render(this.el, 0);
+         
+        // Update width
+        this.ulWidth = this.ulWidth + digit.el.getWidth(true);
+        this.el.set({
+            'min-width' : this.ulWidth,
+            'min-height' :digit.el.getHeight(true)
+        });
+        
+    },
+    
+    removeDigit : function ()
+    {
+        var digit = this.digits.splice(this.digits.length-1, 1)[0];
+        
+        this.ulWidth = this.ulWidth - digit.el.getWidth(true);
+        digit.el.remove();
+        
+        // Remove separators
+        if (this.decimal == 0 & this.digits.length % 3 == 0)
+        {
+            var comma = this.el.select('li.comma:first-child');
+            this.ulWidth = this.ulWidth - comma.getWidth(true);
+            comma.remove();
+        }
+        
+        // Update width to current
+        this.el.set( { 'min-width' : this.ulWidth});
+    },
+    
+    addSeparator : function (str)
+    {
+        var comma = this.el.insertHtml('afterBegin','<li class="comma">'+str+'</li>',true);
+        
+        // Update width
+        
+        this.ulWidth = this.ulWidth + comma.getWidth(true);
+        this.el.set({'min-width' : this.ulWidth});
+    },
+    
+    updateTo : function (num)
+    {
+        var numStr = (1.0*num).toFixed(this.decimal);
+        
+        this.currentNumber = num;
+        
+        var dl = this.digits.length + (this.decimal > 0 ? 1 : 0);
+        // Change the number of digits displayed if needed
+        if (numStr.length != dl)
+        {
+            var diff = numStr.length - dl;
+            //Roo.log("DIFF LEN=" +diff);
+            if (diff > 0)
+            {
+                for (i=0; i<diff; i=i+1) {
+                    this.addDigit(0);
+                }
+            }
+            else
+            {
+                for (i=diff; i<0; i=i+1) {
+                    this.removeDigit();
+                }
+            }
+            
+            this.fireEvent('onResize',this);
+        }
+        
+        // Change all digit values
+        
+        for (i=0, n=0; i<numStr.length; i=i+1)
+        {
+            if (numStr[numStr.length - 1 - i] == '.') {
+                continue;
+            }
+            //Roo.log("UPDATE DIGIT=" + i + " to " + numStr[numStr.length - 1 - i]);
+            this.digits[n++].flipTo(numStr[numStr.length - 1 - i]);
+        }
     }
-
-       var digitsOld = [], digitsNew = [], subStart, subEnd, x, y, nextCount = null, newDigit, newComma,
-       best = {
-               q: null,
-               pace: 0,
-               inc: 0
-       };
-
-       /**
-        * Sets the value of the counter and animates the digits to new value.
-        *
-        * Example: myCounter.setValue(500); would set the value of the counter to 500,
-        * no matter what value it was previously.
-        *
-        * @param {int} n
-        *   New counter value
-        */
-       this.setValue = function(n){
-               if (isNumber(n)){
-                       x = o.value;
-                       y = n;
-                       o.value = n;
-                       digitCheck(x,y);
-               }
-               return this;
-       };
-
-       /**
-        * Sets the increment for the counter. Does NOT animate digits.
-        */
-       this.setIncrement = function(n){
-               o.inc = isNumber(n) ? n : defaults.inc;
-               return this;
-       };
-
-       /**
-        * Sets the pace of the counter. Only affects counter when auto == true.
-        *
-        * @param {int} n
-        *   New pace for counter in milliseconds
-        */
-       this.setPace = function(n){
-               o.pace = isNumber(n) ? n : defaults.pace;
-               return this;
-       };
-
-       /**
-        * Sets counter to auto-incrememnt (true) or not (false).
-        *
-        * @param {bool} a
-        *   Should counter auto-increment, true or false
-        */
-       this.setAuto = function(a){
-               if (a && ! o.auto){
-                       o.auto = true;
-                       doCount();
-               }
-               if (! a && o.auto){
-                       if (nextCount) clearNext();
-                       o.auto = false;
-               }
-               return this;
-       };
-
-       /**
-        * Increments counter by one animation based on set 'inc' value.
-        */
-       this.step = function(){
-               if (! o.auto) doCount();
-               return this;
-       };
-
-       /**
-        * Adds a number to the counter value, not affecting the 'inc' or 'pace' of the counter.
-        *
-        * @param {int} n
-        *   Number to add to counter value
-        */
-       this.add = function(n){
-               if (isNumber(n)){
-                       x = o.value;
-                       o.value += n;
-                       y = o.value;
-                       digitCheck(x,y);
-               }
-               return this;
-       };
-
-       /**
-        * Subtracts a number from the counter value, not affecting the 'inc' or 'pace' of the counter.
-        *
-        * @param {int} n
-        *   Number to subtract from counter value
-        */
-       this.subtract = function(n){
-               if (isNumber(n)){
-                       x = o.value;
-                       o.value -= n;
-                       if (o.value >= 0){
-                               y = o.value;
-                       }
-                       else{
-                               y = "0";
-                               o.value = 0;
-                       }
-                       digitCheck(x,y);
-               }
-               return this;
-       };
-
-       /**
-        * Increments counter to given value, animating by current pace and increment.
-        *
-        * @param {int} n
-        *   Number to increment to
-        * @param {int} t (optional)
-        *   Time duration in seconds - makes increment a 'smart' increment
-        * @param {int} p (optional)
-        *   Desired pace for counter if 'smart' increment
-        */
-       this.incrementTo = function(n, t, p){
-               if (nextCount) clearNext();
-
-               // Smart increment
-               if (typeof t != 'undefined'){
-                       var time = isNumber(t) ? t * 1000 : 10000,
-                       pace = typeof p != 'undefined' && isNumber(p) ? p : o.pace,
-                       diff = typeof n != 'undefined' && isNumber(n) ? n - o.value : 0,
-                       cycles, inc, check, i = 0;
-                       best.q = null;
-
-                       // Initial best guess
-                       pace = (time / diff > pace) ? Math.round((time / diff) / 10) * 10 : pace;
-                       cycles = Math.floor(time / pace);
-                       inc = Math.floor(diff / cycles);
-
-                       check = checkSmartValues(diff, cycles, inc, pace, time);
-
-                       if (diff > 0){
-                               while (check.result === false && i < 100){
-                                       pace += 10;
-                                       cycles = Math.floor(time / pace);
-                                       inc = Math.floor(diff / cycles);
-
-                                       check = checkSmartValues(diff, cycles, inc, pace, time);
-                                       i++;
-                               }
-
-                               if (i == 100){
-                                       // Could not find optimal settings, use best found so far
-                                       o.inc = best.inc;
-                                       o.pace = best.pace;
-                               }
-                               else{
-                                       // Optimal settings found, use those
-                                       o.inc = inc;
-                                       o.pace = pace;
-                               }
-
-                               doIncrement(n, true, cycles);
-                       }
-
-               }
-               // Regular increment
-               else{
-                       doIncrement(n);
-               }
-
-       }
-
-       /**
-        * Gets current value of counter.
-        */
-       this.getValue = function(){
-               return o.value;
-       }
-
-       /**
-        * Stops all running increments.
-        */
-       this.stop = function(){
-               if (nextCount) clearNext();
-               return this;
-       }
-
-       //---------------------------------------------------------------------------//
-
-       function doCount(){
-               x = o.value;
-               o.value += o.inc;
-               y = o.value;
-               digitCheck(x,y);
-               if (o.auto === true) nextCount = setTimeout(doCount, o.pace);
-       }
-
-       function doIncrement(n, s, c){
-               var val = o.value,
-               smart = (typeof s == 'undefined') ? false : s,
-               cycles = (typeof c == 'undefined') ? 1 : c;
-
-               if (smart === true) cycles--;
-
-               if (val != n){
-                       x = o.value,
-                       o.auto = true;
-
-                       if (val + o.inc <= n && cycles != 0) val += o.inc
-                       else val = n;
-
-                       o.value = val;
-                       y = o.value;
-
-                       digitCheck(x,y);
-                       nextCount = setTimeout(function(){doIncrement(n, smart, cycles)}, o.pace);
-               }
-               else o.auto = false;
-       }
-
-       function digitCheck(x,y){
-               digitsOld = splitToArray(x);
-               digitsNew = splitToArray(y);
-               var diff,
-               xlen = digitsOld.length,
-               ylen = digitsNew.length;
-               if (ylen > xlen){
-                       diff = ylen - xlen;
-                       while (diff > 0){
-                               addDigit(ylen - diff + 1, digitsNew[ylen - diff]);
-                               diff--;
-                       }
-               }
-               if (ylen < xlen){
-                       diff = xlen - ylen;
-                       while (diff > 0){
-                               removeDigit(xlen - diff);
-                               diff--;
-                       }
-               }
-               for (var i = 0; i < xlen; i++){
-                       if (digitsNew[i] != digitsOld[i]){
-                               animateDigit(i, digitsOld[i], digitsNew[i]);
-                       }
-               }
-       }
-
-       function animateDigit(n, oldDigit, newDigit){
-               var speed, step = 0, w, a,
-               bp = [
-                       '-' + o.fW + 'px -' + (oldDigit * o.tFH) + 'px',
-                       (o.fW * -2) + 'px -' + (oldDigit * o.tFH) + 'px',
-                       '0 -' + (newDigit * o.tFH) + 'px',
-                       '-' + o.fW + 'px -' + (oldDigit * o.bFH + o.bOffset) + 'px',
-                       (o.fW * -2) + 'px -' + (newDigit * o.bFH + o.bOffset) + 'px',
-                       (o.fW * -3) + 'px -' + (newDigit * o.bFH + o.bOffset) + 'px',
-                       '0 -' + (newDigit * o.bFH + o.bOffset) + 'px'
-               ];
-
-               if (o.auto === true && o.pace <= 300){
-                       switch (n){
-                               case 0:
-                                       speed = o.pace/6;
-                                       break;
-                               case 1:
-                                       speed = o.pace/5;
-                                       break;
-                               case 2:
-                                       speed = o.pace/4;
-                                       break;
-                               case 3:
-                                       speed = o.pace/3;
-                                       break;
-                               default:
-                                       speed = o.pace/1.5;
-                                       break;
-                       }
-               }
-               else{
-                       speed = 80;
-               }
-               // Cap on slowest animation can go
-               speed = (speed > 80) ? 80 : speed;
-
-               function animate(){
-                       if (step < 7){
-                               w = step < 3 ? 't' : 'b';
-                               a = doc.getElementById(divId + "_" + w + "_d" + n);
-                               if (a) a.style.backgroundPosition = bp[step];
-                               step++;
-                               if (step != 3) setTimeout(animate, speed);
-                               else animate();
-                       }
-               }
-
-               animate();
-       }
-
-       // Creates array of digits for easier manipulation
-       function splitToArray(input){
-               return input.toString().split("").reverse();
-       }
-
-       // Adds new digit
-       function addDigit(len, digit){
-               var li = Number(len) - 1;
-               newDigit = doc.createElement("ul");
-               newDigit.className = 'cd';
-               newDigit.id = divId + '_d' + li;
-               newDigit.innerHTML = '<li class="t" id="' + divId + '_t_d' + li + '"></li><li class="b" id="' + divId + '_b_d' + li + '"></li>';
-
-               if (li % 3 == 0){
-                       newComma = doc.createElement("ul");
-                       newComma.className = 'cd';
-                       newComma.innerHTML = '<li class="s"></li>';
-                       div.insertBefore(newComma, div.firstChild);
-               }
-
-               div.insertBefore(newDigit, div.firstChild);
-               doc.getElementById(divId + "_t_d" + li).style.backgroundPosition = '0 -' + (digit * o.tFH) + 'px';
-               doc.getElementById(divId + "_b_d" + li).style.backgroundPosition = '0 -' + (digit * o.bFH + o.bOffset) + 'px';
-       }
-
-       // Removes digit
-       function removeDigit(id){
-               var remove = doc.getElementById(divId + "_d" + id);
-               div.removeChild(remove);
-
-               // Check for leading comma
-               var first = div.firstChild.firstChild;
-               if ((" " + first.className + " ").indexOf(" s ") > -1 ){
-                       remove = first.parentNode;
-                       div.removeChild(remove);
-               }
-       }
-
-       // Sets the correct digits on load
-       function initialDigitCheck(init){
-               // Creates the right number of digits
-               var initial = init.toString(),
-               count = initial.length,
-               bit = 1, i;
-               for (i = 0; i < count; i++){
-                       newDigit = doc.createElement("ul");
-                       newDigit.className = 'cd';
-                       newDigit.id = divId + '_d' + i;
-                       newDigit.innerHTML = newDigit.innerHTML = '<li class="t" id="' + divId + '_t_d' + i + '"></li><li class="b" id="' + divId + '_b_d' + i + '"></li>';
-                       div.insertBefore(newDigit, div.firstChild);
-                       if (bit != (count) && bit % 3 == 0){
-                               newComma = doc.createElement("ul");
-                               newComma.className = 'cd';
-                               newComma.innerHTML = '<li class="s"></li>';
-                               div.insertBefore(newComma, div.firstChild);
-                       }
-                       bit++;
-               }
-               // Sets them to the right number
-               var digits = splitToArray(initial);
-               for (i = 0; i < count; i++){
-                       doc.getElementById(divId + "_t_d" + i).style.backgroundPosition = '0 -' + (digits[i] * o.tFH) + 'px';
-                       doc.getElementById(divId + "_b_d" + i).style.backgroundPosition = '0 -' + (digits[i] * o.bFH + o.bOffset) + 'px';
-               }
-               // Do first animation
-               if (o.auto === true) nextCount = setTimeout(doCount, o.pace);
-       }
-
-       // Checks values for smart increment and creates debug text
-       function checkSmartValues(diff, cycles, inc, pace, time){
-               var r = {result: true}, q;
-               // Test conditions, all must pass to continue:
-               // 1: Unrounded inc value needs to be at least 1
-               r.cond1 = (diff / cycles >= 1) ? true : false;
-               // 2: Don't want to overshoot the target number
-               r.cond2 = (cycles * inc <= diff) ? true : false;
-               // 3: Want to be within 10 of the target number
-               r.cond3 = (Math.abs(cycles * inc - diff) <= 10) ? true : false;
-               // 4: Total time should be within 100ms of target time.
-               r.cond4 = (Math.abs(cycles * pace - time) <= 100) ? true : false;
-               // 5: Calculated time should not be over target time
-               r.cond5 = (cycles * pace <= time) ? true : false;
-
-               // Keep track of 'good enough' values in case can't find best one within 100 loops
-               if (r.cond1 && r.cond2 && r.cond4 && r.cond5){
-                       q = Math.abs(diff - (cycles * inc)) + Math.abs(cycles * pace - time);
-                       if (best.q === null) best.q = q;
-                       if (q <= best.q){
-                               best.pace = pace;
-                               best.inc = inc;
-                       }
-               }
-
-               for (var i = 1; i <= 5; i++){
-                       if (r['cond' + i] === false){
-                               r.result = false;
-                       }
-               }
-               return r;
-       }
-
-       // http://stackoverflow.com/questions/18082/validate-numbers-in-javascript-isnumeric/1830844
-       function isNumber(n) {
-               return !isNaN(parseFloat(n)) && isFinite(n);
-       }
-
-       function clearNext(){
-               clearTimeout(nextCount);
-               nextCount = null;
-       }
-
-       // Start it up
-       initialDigitCheck(o.value);
-};
\ No newline at end of file
+    
+});
+
+Roo.ux.FlipCounter.Digit = function(options)
+{
+    //Roo.apply(this, options);
+    Roo.ux.FlipCounter.Digit.superclass.constructor.call(this, options);
+
+    
+    this.currentNumber = parseInt(this.currentNumber);
+    
+    
+}
+
+Roo.extend(Roo.ux.FlipCounter.Digit, Roo.bootstrap.Component, {
+
+    manager : null, // the flipcounter... 
+    currentNumber : 0,
+    
+    
+    currentNum : 0,
+    nextNum : 0,
+    targetNum : 0,
+    
+    topFrontDiv  : null,
+    bottomFrontDiv : null,
+    topNumBack : null,
+    topNumFront : null,
+    bottomNumBack : null,
+    bottomNumFront : null,
+    
+    
+    
+    
+    getAutoCreate : function(){
+        
+        //Roo.log("render with cn=" + this.currentNumber);
+        return {
+                tag: 'li',
+                cn : [
+                    {
+                        cls: 'numberwrap',
+                        cn : [
+                            { cls : 'flipper_top flipper_top1' },
+                            {
+                                cls : 'flipper_top flipper_top2 flipper_top_back',
+                                cn : [
+                                    { tag: 'span', html: ""+this.currentNumber },
+                                    { cls : 'rings' }
+                                ]
+                        
+                            },
+                            {
+                                cls : 'flipper_top flipper_top_front',
+                                cn : [
+                                    { tag: 'span', html: ""+this.currentNumber },
+                                    { cls : 'rings' }
+                                ]
+                        
+                            },
+                            { cls : 'flipper_bottom flipper_bottom4' },
+                            { cls : 'flipper_bottom flipper_bottom3' },
+                            { cls : 'flipper_bottom flipper_bottom2' },
+                            {
+                                cls : 'flipper_bottom flipper_bottom1 flipper_bottom_back',
+                                cn : [
+                                    { tag: 'span', html: ""+this.currentNumber },
+                                    { cls : 'rings' }
+                                ]
+                            },
+                            {
+                                cls : 'flipper_bottom flipper_bottom_front',
+                                cn : [
+                                    { tag: 'span', html: ""+this.currentNumber },
+                                    { cls : 'rings' }
+                                ]
+                            },
+                        ]
+                    }
+                ]
+        };
+    },
+    
+    
+    initEvents : function()
+    {
+        
+         
+        
+        this.topFrontDiv = this.el.select('.flipper_top_front',true).first();
+        this.bottomFrontDiv = this.el.select('.flipper_bottom_front',true).first();
+        this.topNumBack = this.el.select('.flipper_top_back span',true).first();
+        this.topNumFront = this.el.select('.flipper_top_front span',true).first();
+        this.bottomNumBack = this.el.select('.flipper_bottom_back span',true).first();
+        this.bottomNumFront = this.el.select('.flipper_bottom_front span',true).first();
+        
+        this.targetNum = this.currentNumber;
+        this.currentNum = this.currentNumber;
+        this.nextNum = this.currentNumber;
+        
+        this.currentlyAnimating = false;
+    },
+    
+    flipTo : function (num)
+    {
+        if (this.currentNum === num)
+            return;
+        
+        this.targetNum = num;
+        if (this.currentlyAnimating) {
+            return;
+        }
+        
+        this.animNext();
+    },
+    
+    animNext : function ()
+    {
+        if (this.currentNum == this.targetNum)
+        {
+            this.currentlyAnimating = false;
+            return;
+        }
+        
+        var doRandomDelay = !this.currentlyAnimating;
+        this.currentlyAnimating = true;
+        this.nextNum = this.currentNum + 1;
+        if (this.nextNum > 9) {
+            this.nextNum = 0;
+        }
+        
+        var delay = Math.random()/5;
+        if (!doRandomDelay) {
+            delay = 0.01;
+        }
+        
+        // Animate top flipper
+        var digit = this;
+        digit.topNumBack.dom.innerHTML = digit.nextNum;
+        (function() {
+            digit.topFrontDiv.animate(
+                {
+                    scaleY: {from :1, to : 0}
+                },
+                this.manager.speed, //duration
+                function() {}, // oncomplate
+                'easeIn', //easing,
+                'motion' // desplay type.
+            );
+        }).defer(delay, this);
+        
+        (function() {
+            
+            digit.bottomNumFront.dom.innerHTML  = digit.nextNum;
+            
+            digit.bottomFrontDiv.animate(
+                {
+                    scaleY: {from: 0, to : 1},
+                    
+                },
+                this.manager.speed * 0.5, //duration
+                function() {
+                    digit.currentNum = digit.nextNum;
+                    digit.topNumFront.dom.innerHTML = digit.currentNum;
+                    digit.topFrontDiv.attr('style', '');
+                    digit.bottomNumBack.dom.innerHTML = digit.currentNum;
+                    
+                    digit.animNext();
+                    digit.manager.fireEvent('onFlip', digit.manager);
+                    
+                 }, // oncomplate
+                'easeOut', //easing,
+                'motion' // desplay type.
+            )
+            
+        }).defer(delay + this.manager.speed, this);
+                
+                
+       //??? digit.bottomFrontDiv. digit.bottomNumFront.html(digit.nextNum);
+        
+       
+    }
+});
\ No newline at end of file