Commits

Chris Nanney committed 98ff545

Made some optimizations to smart increment function.

Comments (0)

Files changed (3)

 
 	<div class="explain">
 		<p>This counter was initialized with the following code:</p>
-		<code>var myCounter = new flipCounter('counter', {value:10000, inc:123, pace:800, auto:true});</code>
+		<code>var myCounter = new flipCounter('counter', {value:10000, inc:123, pace:600, auto:true});</code>
 		<p>Use the controls below to make changes to the counter using built-in methods.</p>
 		<p><a class="back" href="http://cnanney.com/journal/code/apple-style-counter-revisited/">http://cnanney.com/journal/code/apple-style-counter-revisited/</a></p>
 	</div>
 			</div>
 		</li>
 		<li class="auto_on_controls">Pace: 
-			<span id="pace_value">800</span>ms <a href="#" class="expand">[?]</a><div id="pace_slider" class="demo_widget"></div>
+			<span id="pace_value">600</span>ms <a href="#" class="expand">[?]</a><div id="pace_slider" class="demo_widget"></div>
 			<div class="explain toggle">
 				<p>This slider controls the counter pace by using the <b>setPace</b> method:</p>
 				<code>myCounter.setPace(value);</code>
 	//<![CDATA[
 
 	// Initialize a new counter
-	var myCounter = new flipCounter('counter', {value:10000, inc:123, pace:800, auto:true});
+	var myCounter = new flipCounter('counter', {value:10000, inc:123, pace:600, auto:true});
 
 	$(function(){
 
 		// Pace
 		$("#pace_slider").slider({
 			range: "max",
-			value: 800,
+			value: 600,
 			min: 100,
 			max: 1000,
 			step: 100,
 			
 			function runTest(){
 				var newVal = myCounter.getValue() + steps[smartInc];
-				myCounter.incrementTo(newVal, 10, 400);
+				myCounter.incrementTo(newVal, 10, 600);
 				smartInc++;
 				if (smartInc < 4) setTimeout(runTest, 10000);
 			}

js/flipcounter.js

 	var tFrameHeight = 39,
 	bFrameHeight = 64,
 	frameWidth = 53,
-	digitsOld = [], digitsNew = [], subStart, subEnd, x, y, nextCount = null;
+	digitsOld = [], digitsNew = [], subStart, subEnd, x, y, nextCount = null,
+	best = {
+		q: null,
+		pace: 0,
+		inc: 0
+	};
 	
 	/**
 	 * Sets the value of the counter and animates the digits to new value.
 			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, q, nq, check,
-			i = 0,
-			best = {
-				pace: 0,
-				inc: 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.round(diff / cycles);
-			q = Math.abs(diff - (cycles * inc)) + Math.abs(cycles * pace - time);
+			inc = Math.floor(diff / cycles);
 			
 			check = checkSmartValues(diff, cycles, inc, pace, time);
 			
 			// DEBUGGING
-			/*
-			if (o.debug){
-				console.log(
-					'***************************************************************\n' + 
-					'START: ' + o.value + '\nEND: ' + n + '\n' + check.str
-				);
-			}
-			*/
+			
+//			if (o.debug){
+//				console.log(
+//					'***************************************************************\n' +
+//					'START: ' + o.value + '\nEND: ' + n + '\n' + check.str
+//				);
+//			}
 			
 			if (diff > 0){
 				while (check.result === false && i < 100){				
 					pace += 10;
 					cycles = Math.floor(time / pace);
-					inc = Math.round(diff / cycles);
-					nq = Math.abs(diff - (cycles * inc)) + Math.abs(cycles * pace - time);
+					inc = Math.floor(diff / cycles);
 					
 					check = checkSmartValues(diff, cycles, inc, pace, time);
 					
-					if (nq < q){
-						q = nq;
-						best.pace = pace;
-						best.inc = inc;
-					}
+					// DEBUGGING
 					
-					// DEBUGGING
-					/*
-					if (o.debug){
-						console.log('ADJUSTMENT: ' + (i + 1) + '\n' + check.str);
-					}
-					*/
+//					if (o.debug){
+//						console.log('ADJUSTMENT: ' + (i + 1) + '\n' + check.str);
+//					}
 					
 					i++;
 				}
 			doIncrement(n);
 		}
 		
-		
 	}
 	
 	/**
 	}
 	
 	function digitCheck(x,y){
+		var diff, adder;
 		digitsOld = splitToArray(x);
 		digitsNew = splitToArray(y);
 		if (y.length > x.length){
-			var diff = y.length - x.length;
+			diff = y.length - x.length;
 			while (diff > 0){
-				var adder = 1;
+				adder = 1;
 				addDigit(y.length - diff + 1, digitsNew[y.length - diff]);
 				adder++;
 				diff--;
 			}
 		}
 		if (y.length < x.length){
-			var diff = x.length - y.length;
+			diff = x.length - y.length;
 			while (diff > 0){
-				var adder = 1;
+				adder = 1;
 				removeDigit(x.length - diff);
 				diff--;
 			}
 					speed = o.pace/3;
 					break;
 				default:
-					speed = o.pace/2;
+					speed = o.pace/1.5;
 					break;
 			}
 		}
 	// Sets the correct digits on load
 	function initialDigitCheck(initial){
 		// Creates the right number of digits
-		var count = initial.toString().length;
-		var bit = 1;
-		for (var i = 0; i < count; i++){
+		var count = initial.toString().length,
+		bit = 1, i;
+		for (i = 0; i < count; i++){
 			jQuery(div).prepend('<ul class="cd" id="d' + i + '"><li class="t"></li><li class="b"></li></ul>');
 			if (bit != (count) && bit % 3 == 0) jQuery(div).prepend('<ul class="cd"><li class="s"></li></ul>');
 			bit++;
 		}
 		// Sets them to the right number
 		var digits = splitToArray(initial.toString());
-		for (var i = 0; i < count; i++){
+		for (i = 0; i < count; i++){
 			jQuery(div + " #d" + i + " li.t").css({'background-position': '0 -' + (digits[i] * tFrameHeight) + 'px'});
 			jQuery(div + " #d" + i + " li.b").css({'background-position': '0 -' + (digits[i] * bFrameHeight) + 'px'});
 		}
 	
 	// Checks values for smart increment and creates debug text
 	function checkSmartValues(diff, cycles, inc, pace, time){
-		var r = {result: true};
+		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 5 of the target number
-		r.cond3 = (Math.abs(cycles * inc - diff) <= 5) ? 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;
+			}
+		}
+		
 		// DEBUGGING
 		//r.str = 'Condition Checks:\n';
 		for (var i = 1; i <= 5; i++){
 				//r.str += 'FAIL';
 				r.result = false;
 			}
-			/*
-			else{
-				r.str += 'PASS';
-			}
-			r.str += i < 5 ? ', ' : '';
-			*/
+			
+//			else{
+//				r.str += 'PASS';
+//			}
+//			r.str += i < 5 ? ', ' : '';
+			
 		}
 		
 		// DEBUGGING
-		/*
-		r.str += '\n----\n   Pace: ' + pace +
-			'\n   Cycles: ' + cycles +
-			'\n   Calculated Inc: ' + (diff / cycles) +
-			'\n   Rounded Inc: ' + inc +
-			'\n   Calculated time: ' + Math.abs(cycles * pace) +
-			'\n   Target time: ' + time +
-			'\n   ACTUAL END VALUE: ' + (cycles*inc+o.value);
-		*/
+		
+//		r.str += '\n----\n   Pace: ' + pace +
+//			'\n   Diff: ' + diff +
+//			'\n   Cycles: ' + cycles +
+//			'\n   Calculated Inc: ' + (diff / cycles) +
+//			'\n   Rounded Inc: ' + inc +
+//			'\n   Calculated time: ' + Math.abs(cycles * pace) +
+//			'\n   Target time: ' + time +
+//			'\n   ACTUAL END VALUE: ' + (cycles*inc+o.value);
+		
 		return r;
 	}
 	

js/flipcounter.min.js

  * Licensed under MIT
  * http://www.opensource.org/licenses/mit-license.php
  */
-var flipCounter=function(y,H){function t(){j=c.value.toString();c.value+=c.inc;h=c.value.toString();o(j,h);if(c.auto===true)k=setTimeout(t,c.pace)}function z(a,d,b){var e=c.value,f=typeof d=="undefined"?false:d,g=typeof b=="undefined"?1:b;f===true&&g--;if(e!=a){j=c.value.toString();c.auto=true;if(e+c.inc<=a&&g!=0)e+=c.inc;else e=a;c.value=e;h=c.value.toString();o(j,h);k=setTimeout(function(){z(a,f,g)},c.pace)}else c.auto=false}function o(a,d){u=A(a);v=A(d);if(d.length>a.length)for(var b=d.length-
-a.length;b>0;){var e=v[d.length-b],f=Number(d.length-b+1)-1;f%3==0&&jQuery(i).prepend('<ul class="cd"><li class="s"></li></ul>');jQuery(i).prepend('<ul class="cd" id="d'+f+'"><li class="t"></li><li class="b"></li></ul>');jQuery(i+" #d"+f+" li.t").css({"background-position":"0 -"+e*p+"px"});jQuery(i+" #d"+f+" li.b").css({"background-position":"0 -"+e*m+"px"});b--}if(d.length<a.length)for(b=a.length-d.length;b>0;){jQuery(i+" #d"+(a.length-b)).remove();e=jQuery(i+" li").first();e.hasClass("s")&&e.parent("ul").remove();
-b--}for(b=0;b<u.length;b++)v[b]!=u[b]&&I(b,u[b],v[b])}function I(a,d,b){function e(){if(g<7){n=g<3?"t":"b";jQuery(i+" #d"+a+" li."+n).css("background-position",q[g]);g++;g!=3?setTimeout(e,f):e()}}var f,g=0,n,q=["-"+r+"px -"+d*p+"px",r*-2+"px -"+d*p+"px","0 -"+b*p+"px","-"+r+"px -"+d*m+"px",r*-2+"px -"+b*m+"px",r*-3+"px -"+b*m+"px","0 -"+b*m+"px"];if(c.auto===true&&c.pace<=300)switch(a){case 0:f=c.pace/6;break;case 1:f=c.pace/5;break;case 2:f=c.pace/4;break;case 3:f=c.pace/3;break;default:f=c.pace/
-2}else f=80;f=f>80?80:f;e()}function A(a){for(var d=[],b=0;b<a.length;b++){E=a.length-(b+1);F=a.length-b;d[b]=a.substring(E,F)}return d}function G(a,d,b,e,f){var g={result:true};g.cond1=a/d>=1?true:false;g.cond2=d*b<=a?true:false;g.cond3=Math.abs(d*b-a)<=5?true:false;g.cond4=Math.abs(d*e-f)<=100?true:false;g.cond5=d*e<=f?true:false;for(a=1;a<=5;a++)if(g["cond"+a]===false)g.result=false;return g}function l(a){return!isNaN(parseFloat(a))&&isFinite(a)}function B(){clearTimeout(k);k=null}var w={value:0,
-inc:1,pace:1E3,auto:true,debug:false},c=H||{},i=y&&y!=""?"#"+y:"#counter",s;for(s in w)c[s]=s in c?c[s]:w[s];var p=39,m=64,r=53,u=[],v=[],E,F,j,h,k=null;this.setValue=function(a){if(l(a)){j=c.value.toString();h=a.toString();c.value=a;o(j,h)}return this};this.setIncrement=function(a){c.inc=l(a)?a:w.inc;return this};this.setPace=function(a){c.pace=l(a)?a:w.pace;return this};this.setAuto=function(a){if(a&&!c.atuo){c.auto=true;t()}if(!a&&c.auto){k&&B();c.auto=false}return this};this.step=function(){c.auto||
-t();return this};this.add=function(a){if(l(a)){j=c.value.toString();c.value+=a;h=c.value.toString();o(j,h)}return this};this.subtract=function(a){if(l(a)){j=c.value.toString();c.value-=a;if(c.value>=0)h=c.value.toString();else{h="0";c.value=0}o(j,h)}return this};this.incrementTo=function(a,d,b){k&&B();if(typeof d!="undefined"){d=l(d)?d*1E3:1E4;b=typeof b!="undefined"&&l(b)?b:c.pace;var e=typeof a!="undefined"&&l(a)?a-c.value:0,f,g,n,q,C,D=0,x={pace:0,inc:0};b=d/e>b?Math.round(d/e/10)*10:b;f=Math.floor(d/
-b);g=Math.round(e/f);n=Math.abs(e-f*g)+Math.abs(f*b-d);C=G(e,f,g,b,d);if(e>0){for(;C.result===false&&D<100;){b+=10;f=Math.floor(d/b);g=Math.round(e/f);q=Math.abs(e-f*g)+Math.abs(f*b-d);C=G(e,f,g,b,d);if(q<n){n=q;x.pace=b;x.inc=g}D++}if(D==100){c.inc=x.inc;c.pace=x.pace}else{c.inc=g;c.pace=b}z(a,true,f)}}else z(a)};this.getValue=function(){return c.value};this.stop=function(){k&&B();return this};(function(a){for(var d=a.toString().length,b=1,e=0;e<d;e++){jQuery(i).prepend('<ul class="cd" id="d'+e+
-'"><li class="t"></li><li class="b"></li></ul>');b!=d&&b%3==0&&jQuery(i).prepend('<ul class="cd"><li class="s"></li></ul>');b++}a=A(a.toString());for(e=0;e<d;e++){jQuery(i+" #d"+e+" li.t").css({"background-position":"0 -"+a[e]*p+"px"});jQuery(i+" #d"+e+" li.b").css({"background-position":"0 -"+a[e]*m+"px"})}if(c.auto===true)k=setTimeout(t,c.pace)})(c.value)};
+var flipCounter=function(w,D){function s(){i=a.value.toString();a.value+=a.inc;h=a.value.toString();o(i,h);a.auto===!0&&(k=setTimeout(s,a.pace))}function x(c,f,b){var d=a.value,e=typeof f=="undefined"?!1:f,g=typeof b=="undefined"?1:b;e===!0&&g--;d!=c?(i=a.value.toString(),a.auto=!0,d+a.inc<=c&&g!=0?d+=a.inc:d=c,a.value=d,h=a.value.toString(),o(i,h),k=setTimeout(function(){x(c,e,g)},a.pace)):a.auto=!1}function o(c,a){var b;t=y(c);u=y(a);if(a.length>c.length)for(b=a.length-c.length;b>0;){var d=u[a.length-
+b],e=Number(a.length-b+1)-1;e%3==0&&jQuery(j).prepend('<ul class="cd"><li class="s"></li></ul>');jQuery(j).prepend('<ul class="cd" id="d'+e+'"><li class="t"></li><li class="b"></li></ul>');jQuery(j+" #d"+e+" li.t").css({"background-position":"0 -"+d*p+"px"});jQuery(j+" #d"+e+" li.b").css({"background-position":"0 -"+d*n+"px"});b--}if(a.length<c.length)for(b=c.length-a.length;b>0;)jQuery(j+" #d"+(c.length-b)).remove(),d=jQuery(j+" li").first(),d.hasClass("s")&&d.parent("ul").remove(),b--;for(b=0;b<
+t.length;b++)u[b]!=t[b]&&E(b,t[b],u[b])}function E(c,f,b){function d(){g<7&&(h=g<3?"t":"b",jQuery(j+" #d"+c+" li."+h).css("background-position",i[g]),g++,g!=3?setTimeout(d,e):d())}var e,g=0,h,i=["-"+q+"px -"+f*p+"px",q*-2+"px -"+f*p+"px","0 -"+b*p+"px","-"+q+"px -"+f*n+"px",q*-2+"px -"+b*n+"px",q*-3+"px -"+b*n+"px","0 -"+b*n+"px"];if(a.auto===!0&&a.pace<=300)switch(c){case 0:e=a.pace/6;break;case 1:e=a.pace/5;break;case 2:e=a.pace/4;break;case 3:e=a.pace/3;break;default:e=a.pace/1.5}else e=80;e=e>
+80?80:e;d()}function y(c){for(var a=[],b=0;b<c.length;b++)A=c.length-(b+1),B=c.length-b,a[b]=c.substring(A,B);return a}function C(a,f,b,d,e){var g={result:!0};g.cond1=a/f>=1?!0:!1;g.cond2=f*b<=a?!0:!1;g.cond3=Math.abs(f*b-a)<=10?!0:!1;g.cond4=Math.abs(f*d-e)<=100?!0:!1;g.cond5=f*d<=e?!0:!1;if(g.cond1&&g.cond2&&g.cond4&&g.cond5){a=Math.abs(a-f*b)+Math.abs(f*d-e);if(l.q===null)l.q=a;if(a<=l.q)l.pace=d,l.inc=b}for(b=1;b<=5;b++)if(g["cond"+b]===!1)g.result=!1;return g}function m(a){return!isNaN(parseFloat(a))&&
+isFinite(a)}function z(){clearTimeout(k);k=null}var v={value:0,inc:1,pace:1E3,auto:!0,debug:!1},a=D||{},j=w&&w!=""?"#"+w:"#counter",r;for(r in v)a[r]=r in a?a[r]:v[r];var p=39,n=64,q=53,t=[],u=[],A,B,i,h,k=null,l={q:null,pace:0,inc:0};this.setValue=function(c){if(m(c))i=a.value.toString(),h=c.toString(),a.value=c,o(i,h);return this};this.setIncrement=function(c){a.inc=m(c)?c:v.inc;return this};this.setPace=function(c){a.pace=m(c)?c:v.pace;return this};this.setAuto=function(c){if(c&&!a.atuo)a.auto=
+!0,s();if(!c&&a.auto)k&&z(),a.auto=!1;return this};this.step=function(){a.auto||s();return this};this.add=function(c){m(c)&&(i=a.value.toString(),a.value+=c,h=a.value.toString(),o(i,h));return this};this.subtract=function(c){if(m(c))i=a.value.toString(),a.value-=c,a.value>=0?h=a.value.toString():(h="0",a.value=0),o(i,h);return this};this.incrementTo=function(c,f,b){k&&z();if(typeof f!="undefined"){var f=m(f)?f*1E3:1E4,b=typeof b!="undefined"&&m(b)?b:a.pace,d=typeof c!="undefined"&&m(c)?c-a.value:
+0,e,g,h,i=0;l.q=null;b=f/d>b?Math.round(f/d/10)*10:b;e=Math.floor(f/b);g=Math.floor(d/e);h=C(d,e,g,b,f);if(d>0){for(;h.result===!1&&i<100;)b+=10,e=Math.floor(f/b),g=Math.floor(d/e),h=C(d,e,g,b,f),i++;i==100?(a.inc=l.inc,a.pace=l.pace):(a.inc=g,a.pace=b);x(c,!0,e)}}else x(c)};this.getValue=function(){return a.value};this.stop=function(){k&&z();return this};(function(c){var f=c.toString().length,b=1,d;for(d=0;d<f;d++)jQuery(j).prepend('<ul class="cd" id="d'+d+'"><li class="t"></li><li class="b"></li></ul>'),
+b!=f&&b%3==0&&jQuery(j).prepend('<ul class="cd"><li class="s"></li></ul>'),b++;c=y(c.toString());for(d=0;d<f;d++)jQuery(j+" #d"+d+" li.t").css({"background-position":"0 -"+c[d]*p+"px"}),jQuery(j+" #d"+d+" li.b").css({"background-position":"0 -"+c[d]*n+"px"});a.auto===!0&&(k=setTimeout(s,a.pace))})(a.value)};