-/**
- * 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