Display decimals with the Counter Element

I’m looking for having the functionality to display numbers with decimals using the Counter Element. There are a couple workarounds that I know of, but I’m hoping for a better way.

One way to get around it is to use the prefix to contain the whole number digits, and “count” up the digits past the decimal. But that’s obviously not ideal.

The other solution I found was using some Javascript code that alters the final counter value to include a comma every 3 digits. I modified this to do a decimal every 2 digits because I won’t have numbers higher than “99.99”. However, this is not ideal either because it uses a timeout value that waits for the count to finish, then tosses in the decimal. I’m wanting to use it on a page with about 18 counters, so I had to do this code 18 different times to make sure it all works properly. Page: http://okumf.org/okumf_v2/resources/investment-funds/.

Code sample:
jQuery(document).ready(function() { setTimeout(function() { var selector1 = jQuery('#dvf-ytd .number'); var theNumber1 = selector1.text(); theNumber1 = theNumber1.toString().replace(/\B(?=(\d{2})+(?!\d))/g, "."); selector1.text(theNumber1); }, 600); })

But this also has a problem when some of the counters are below the fold, and don’t start counting until you scroll, which means I can’t use the timeout function in the javascript properly.

ANYWAY, help?

Hi there,

Thanks for posting in.

The idea is correct, but you should use setInterval() instead of setTimeout(). With setInterval(), it will repeat over and over until you stop it based on certain condition.

Example,


var previous_number = ""; //this holds the previous number, we'll use this to compare and stop interval to prevent it from looping after the counter is finished


var the_interval = setInterval ( function() { //let's store the interval instance here

var current_number = selector1.text(); //The number!!!

if ( current_number !== previous_number ) { //if the current number is not the same as previous_number, then continue

theNumber1 = current_number.toString().replace(/\B(?=(\d{2})+(?!\d))/g, ".");

} else { //Else, let's stop the loop, when the current and previous number are the same, that means the counter is already finished

clearInterval( the_interval );

}

} , 800 );

This is not a complete code, I just like to show you the idea but it may not work. Then, since there are multiple instances of counter, you’ll need multiple instances of intervals too. Example,

var the_intervals = new Array();

$('.x-counter').each( function( index ) {

the_intervals [ index ] = setInterval ( function() {

....
....
....
clearInterval( the_intervals [ index ] );
....
....

} );

} );

And so on, you may want to contact a developer as this could be more complex and needs further testing.

Thanks!

Thank you very much. We have a developer here at my office and I might be able to borrow him for help on this code.

You’re welcome.

So, I think an issue with the interval script, is it’s basically checking for when the number stops changing to stop the interval loop.

But, because the counter number isn’t changing when it’s below the fold, that immediately ends the loop anyway. Only when we refresh the page that’s already scrolled to the counter will that work properly.

Is there a way to check for when the number matches the “numEnd” or Ending Number value in the counter settings? —and THAT ends the loop?

Hi there,

You may try some combination with this https://api.jquery.com/animated-selector/ and setTimeout, example,

var counter_counts = 0; //For comparison purposes

var counter_total = $('.x-counter').length; //So the script knows when to stop

var main_Interval = setInterval ( function() { // Our main interval that process each column

//Let's only pickup all animating columns

$('.x-column:animated').each( function() {

if ( this.recorded_interval !== true ) { //Aye, this column is not yet processed, let's continue

setTimeout ( function() { 

//We need this setTimeout() to make sure the Interval is only triggered after the animation is done, usually animation is about 750ms, let's make it 800 or anything you like, just make sure it's greater than the animation time itelf

var the_intervals = new Array();

$(this).find('.x-counter').each( function( index ) {

counter_counts = counter_counts + 1;

the_intervals [ index ] = setInterval ( function() { //Our local interval that process counters on current column

....
....
....
clearInterval( the_intervals [ index ] );
....
....

}, 300 );

}, 800 );
}

this.recorded_interval = true; //Mark this column as processed

if ( counter_counts == counter_total ) { 

//What if the total counter in the whole page is equal to the total of already processed counters? Then let's end the main interval :)

clearIntervals ( main_Interval );

}


} );

}, 300 );


Again, you may enhance it as well :slight_smile:, that’s all I could recommend for now as there is no available events and filters for already animating elements, else, you’ll need to do hard coding of the core javascript files.

Thanks!

Okay! Thanks again.

Do you know where the core script is for this counter in the Pro theme?

Hi there,

It’s under \cornerstone\assets\dist\js\site\cs-body.js, a bit of obscured so I can’t really point out which. But it’s all related to x-elements. The core files are compiled so it’s a bit hard to manually edit them, I’ll just add this as feature request.

Thanks!

1 Like