(function ($){
var CountTo=function (element, options){
this.$element=$(element);
this.options=$.extend({}, CountTo.DEFAULTS, this.dataOptions(), options);
this.init();
};
CountTo.DEFAULTS={
from: 0,
to: 0,
speed: 1000,
refreshInterval: 100,
decimals: 0,
formatter: formatter,
onUpdate: null,
onComplete: null
};
CountTo.prototype.init=function (){
this.value=this.options.from;
this.loops=Math.ceil(this.options.speed / this.options.refreshInterval);
this.loopCount=0;
this.increment=(this.options.to - this.options.from) / this.loops;
};
CountTo.prototype.dataOptions=function (){
var options={
from:            this.$element.data('from'),
to:              this.$element.data('to'),
speed:           this.$element.data('speed'),
refreshInterval: this.$element.data('refresh-interval'),
decimals:        this.$element.data('decimals')
};
var keys=Object.keys(options);
for (var i in keys){
var key=keys[i];
if(typeof(options[key])==='undefined'){
delete options[key];
}}
return options;
};
CountTo.prototype.update=function (){
this.value +=this.increment;
this.loopCount++;
this.render();
if(typeof(this.options.onUpdate)=='function'){
this.options.onUpdate.call(this.$element, this.value);
}
if(this.loopCount >=this.loops){
clearInterval(this.interval);
this.value=this.options.to;
if(typeof(this.options.onComplete)=='function'){
this.options.onComplete.call(this.$element, this.value);
}}
};
CountTo.prototype.render=function (){
var formattedValue=this.options.formatter.call(this.$element, this.value, this.options);
this.$element.text(formattedValue);
};
CountTo.prototype.restart=function (){
this.stop();
this.init();
this.start();
};
CountTo.prototype.start=function (){
this.stop();
this.render();
this.interval=setInterval(this.update.bind(this), this.options.refreshInterval);
};
CountTo.prototype.stop=function (){
if(this.interval){
clearInterval(this.interval);
}};
CountTo.prototype.toggle=function (){
if(this.interval){
this.stop();
}else{
this.start();
}};
function formatter(value, options){
return value.toFixed(options.decimals);
}
$.fn.countTo=function (option){
return this.each(function (){
var $this=$(this);
var data=$this.data('countTo');
var init    = !data||typeof(option)==='object';
var options=typeof(option)==='object' ? option:{};
var method=typeof(option)==='string' ? option:'start';
if(init){
if(data) data.stop();
$this.data('countTo', data=new CountTo(this, options));
}
data[method].call(data);
});
};}(jQuery));