bfintal / Counter-Up

Counter-Up is a lightweight jQuery plugin that counts up to a targeted number when the number becomes visible.
http://bfintal.github.io/Counter-Up/demo/demo.html
GNU General Public License v2.0
746 stars 719 forks source link

How can the count start again if I scroll back up to the number? #57

Open klausabio opened 6 years ago

klausabio commented 6 years ago

Lets say I have a counting number. I scroll to it, it works great, then I do some more scrolling down the page, then I go up again back to it. I would like to see the count again from zero, is that possible?

tranlehaiquan commented 6 years ago

@klausabio it because waypoints remove option once. Temporary fix: Use this.desktop, and set handler for waypoints

/*!
* jquery.counterup.js 1.0
*
* Copyright 2013, Benjamin Intal http://gambit.ph @bfintal
* Released under the GPL v2 License
*
* Date: Nov 26, 2013
*/
(function( $ ){
  "use strict";

  $.fn.counterUp = function( options ) {

    // Defaults
    var settings = $.extend({
        'time': 400,
        'delay': 10
    }, options);

    return this.each(function(){

        // Store the object
        var $this = $(this);
        var $settings = settings;

        var counterUpper = function() {
            var nums = [];
            var divisions = $settings.time / $settings.delay;
            var num = $this.text();
            var isComma = /[0-9]+,[0-9]+/.test(num);
            num = num.replace(/,/g, '');
            var isInt = /^[0-9]+$/.test(num);
            var isFloat = /^[0-9]+\.[0-9]+$/.test(num);
            var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0;

            // Generate list of incremental numbers to display
            for (var i = divisions; i >= 1; i--) {

                // Preserve as int if input was int
                var newNum = parseInt(num / divisions * i);

                // Preserve float if input was float
                if (isFloat) {
                    newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces);
                }

                // Preserve commas if input had commas
                if (isComma) {
                    while (/(\d+)(\d{3})/.test(newNum.toString())) {
                        newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1'+','+'$2');
                    }
                }

                nums.unshift(newNum);
            }

            $this.data('counterup-nums', nums);
            $this.text('0');

            // Updates the number until we're done
            var f = function() {
                $this.text($this.data('counterup-nums').shift());
                if ($this.data('counterup-nums').length) {
                    setTimeout($this.data('counterup-func'), $settings.delay);
                } else {
                    delete $this.data('counterup-nums');
                    $this.data('counterup-nums', null);
                    $this.data('counterup-func', null);
                }
            };
            $this.data('counterup-func', f);

            // Start the count up
            setTimeout($this.data('counterup-func'), $settings.delay);
            // Destroy waypoint
            this.destroy();
        };

        // Perform counts when the element gets into view
        $this.waypoint({ offset: '100%', handler: counterUpper});
    });

  };

})( jQuery );
dnunes commented 6 years ago

A very simple fix is to use a variable rather than getting the data directly from the DOM Node. The code stores the DOM Reference but not the starting number. So the fix would be...

Search in the code for this part:

        // Store the object
        var $this = $(this);
        var $settings = settings;

        var counterUpper = function() {
            var nums = [];
            var divisions = $settings.time / $settings.delay;
            var num = $this.text();

and add a var origValue = $this.text(); before the counterUpper function, to save the original dom node value. Also, the code uses num = $this.text() to get the dom node value, and you should replace it with num = origValue;, so that it will be like this:

        // Store the object
        var $this = $(this);
        var $settings = settings;
        var origValue = $this.text();

        var counterUpper = function() {
            var nums = [];
            var divisions = $settings.time / $settings.delay;
            var num = origValue;

Done :)

firestar300 commented 6 years ago

Thanks @dnunes it's working.

marcelomgerais commented 6 years ago

hi @dnunes. im from brazil too. can u help me? i posted this:

"Hi, is possible to have the counter in a loop, in time interval. an e.g: when scroll target to numbers, counter starts, from "0" to " 13.423"; and then, in five seconds (an eg), the counter resumes the count, from 0 to 13.423 again. its possible? like a 'loop' with interval. 2) i want to use 1.300.000, but returns "NAn" for me. how can i use this format of numbers??" Tks a lot!

dnunes commented 6 years ago

Hey, @marcelomgerais. Sorry for the delay, I missed the notification.

First, re-running the counter is kind of a hard question because it requires us to "stop" the looping once the screen scrolls off, so it can restart when it becomes visible again. AFAIK there is no such funcionality on library (Waypoints) Counter Up uses. You could simply run it in a loop forever every 5-secs after it finishes (it would start when the user scrolls and then will keep looping). This is subideal because if the user scrolls again it could be mid-counting and would not start from 0, but is the best you can right now. This change would require a somehow bigger modification to the code (some 6 or 7 lines, maybe). You would need to store the array with the numbers and run the current "shifting" process in a copy of this array, so you can reset the array later to re-run. You would enqueue the restart using the "else" that detects the end of the counting at line 65.

For the second question, currently Counter Up runs a "parseInt" in the data you input and it cannot really understand any complex masks (it accepts commas as thousands separator). But as the code store the pre-calculated data in an array, you can easily pass the number through a masking function before storing it at line 54 with

nums.unshift(MASKING_FUNCTION(newNum, PARAMS_IF_NEEDED));

veselinminchev commented 6 years ago

A very simple fix is to use a variable rather than getting the data directly from the DOM Node. The code stores the DOM Reference but not the starting number. So the fix would be...

Search in the code for this part:

        // Store the object
        var $this = $(this);
        var $settings = settings;

        var counterUpper = function() {
            var nums = [];
            var divisions = $settings.time / $settings.delay;
            var num = $this.text();

and add a var origValue = $this.text(); before the counterUpper function, to save the original dom node value. Also, the code uses num = $this.text() to get the dom node value, and you should replace it with num = origValue;, so that it will be like this:

        // Store the object
        var $this = $(this);
        var $settings = settings;
        var origValue = $this.text();

        var counterUpper = function() {
            var nums = [];
            var divisions = $settings.time / $settings.delay;
            var num = origValue;

Done :)

It is working! Thanks a lot! Save my day!

KyawSoeAung116 commented 4 years ago

A very simple fix is to use a variable rather than getting the data directly from the DOM Node. The code stores the DOM Reference but not the starting number. So the fix would be...

Search in the code for this part:

        // Store the object
        var $this = $(this);
        var $settings = settings;

        var counterUpper = function() {
            var nums = [];
            var divisions = $settings.time / $settings.delay;
            var num = $this.text();

and add a var origValue = $this.text(); before the counterUpper function, to save the original dom node value. Also, the code uses num = $this.text() to get the dom node value, and you should replace it with num = origValue;, so that it will be like this:

        // Store the object
        var $this = $(this);
        var $settings = settings;
        var origValue = $this.text();

        var counterUpper = function() {
            var nums = [];
            var divisions = $settings.time / $settings.delay;
            var num = origValue;

Done :)

Not worked for me !!

kyaw-soe-aung commented 4 years ago

A very simple fix is to use a variable rather than getting the data directly from the DOM Node. The code stores the DOM Reference but not the starting number. So the fix would be... Search in the code for this part:

        // Store the object
        var $this = $(this);
        var $settings = settings;

        var counterUpper = function() {
            var nums = [];
            var divisions = $settings.time / $settings.delay;
            var num = $this.text();

and add a var origValue = $this.text(); before the counterUpper function, to save the original dom node value. Also, the code uses num = $this.text() to get the dom node value, and you should replace it with num = origValue;, so that it will be like this:

        // Store the object
        var $this = $(this);
        var $settings = settings;
        var origValue = $this.text();

        var counterUpper = function() {
            var nums = [];
            var divisions = $settings.time / $settings.delay;
            var num = origValue;

Done :)

It is working! Thanks a lot! Save my da

A very simple fix is to use a variable rather than getting the data directly from the DOM Node. The code stores the DOM Reference but not the starting number. So the fix would be... Search in the code for this part:

        // Store the object
        var $this = $(this);
        var $settings = settings;

        var counterUpper = function() {
            var nums = [];
            var divisions = $settings.time / $settings.delay;
            var num = $this.text();

and add a var origValue = $this.text(); before the counterUpper function, to save the original dom node value. Also, the code uses num = $this.text() to get the dom node value, and you should replace it with num = origValue;, so that it will be like this:

        // Store the object
        var $this = $(this);
        var $settings = settings;
        var origValue = $this.text();

        var counterUpper = function() {
            var nums = [];
            var divisions = $settings.time / $settings.delay;
            var num = origValue;

Done :)

It is working! Thanks a lot! Save my day!

Really? which version of waypoint do you use. I stuck for that animation. help plz.

esjdev commented 4 years ago

A very simple fix is to use a variable rather than getting the data directly from the DOM Node. The code stores the DOM Reference but not the starting number. So the fix would be...

Search in the code for this part:

        // Store the object
        var $this = $(this);
        var $settings = settings;

        var counterUpper = function() {
            var nums = [];
            var divisions = $settings.time / $settings.delay;
            var num = $this.text();

and add a var origValue = $this.text(); before the counterUpper function, to save the original dom node value. Also, the code uses num = $this.text() to get the dom node value, and you should replace it with num = origValue;, so that it will be like this:

        // Store the object
        var $this = $(this);
        var $settings = settings;
        var origValue = $this.text();

        var counterUpper = function() {
            var nums = [];
            var divisions = $settings.time / $settings.delay;
            var num = origValue;

Done :)

Thanks, it worked for me.