0

I am new to jquery, with some basic understanding.

I am trying to use the jOdometer.js https://github.com/jesucarr/jodometer . I can get the odometer well and good, and the default setInterval method makes the odometer tick.

There is a section of the code

function advanceCounter() {
            setNumbers(counter);
            counter = counter + settings.increment; // increment the number 
            // if we reach the end clear the interval and use the ending number
            if(settings.counterEnd != false && counter >= settings.counterEnd){
                clearInterval(counterInterval);
                setNumbers(settings.counterEnd);
            }
        }
        // to move the colums from one number position to another
        function setNumbers(counter){
            digits = String(counter).split('.'); // check decimals
            // if we where using decimals
            if (decimalsArray.length > 0){
                // for each decimal digit, update the old digit position to the new
                for (i=0;i<decimalsArray.length;i++){
                    oldDigit = decimalsArray[i];
                    // the new numer could have not decimal part, but we need it anyway
                    if (digits[1]){
                        decimalsArray[i] = digits[1].charAt(i);
                    }
                    if (decimalsArray[i] == ''){
                        decimalsArray[i] = '0';
                    }
                    updatePosition($('.jodometer_decimal_'+i, scope), parseInt(decimalsArray[i]), parseInt(oldDigit));
                }
            }

            integers = digits[0];
            j=integers.length-1;
            // for each integer digit, update the old digit position to the new
            for (i=0;i<integersArray.length;i++){
                oldDigit = integersArray[i];
                integersArray[i] = integers.charAt(j);
                if (integersArray[i] == ''){
                    integersArray[i] = '0';
                }
                //alert($(this));
                updatePosition($('.jodometer_integer_'+i, scope), parseInt(integersArray[i]), parseInt(oldDigit));
                j--;
            }
        }
        // changes the column position from one number to another
        function updatePosition(col, newDigit, oldDigit){
            if(newDigit != oldDigit){
                col.stop();
                // if the number is 0 use the bottom 0 in the image, and change intantly to the top 0
                if (newDigit == 0){
                    col.animate({top: (10*settings.heightNumber*-1)+zeroSet}, settings.speed, settings.easing).animate({top: zeroSet},1, 'linear');
                }else{
                    // if the new number is lower than the old, we have to go to the bottom 0 and start from the top 0, with the apropiate speed, to don't note the jump
                    if (newDigit < oldDigit){
                        col.animate({top: (10*settings.heightNumber*-1)+zeroSet}, settings.speed*((10-oldDigit)/10), 'linear').animate({top: zeroSet},1, 'linear').animate({top: (newDigit*settings.heightNumber*-1)+zeroSet}, settings.speed*oldDigit/10, settings.easing);
                    }else{
                        col.animate({top: (newDigit*settings.heightNumber*-1)+zeroSet}, settings.speed, settings.easing);
                    }
                }
            }
        }

which updates the odometer. I am using ajax to get new data, and I want to update the odometer readings. How can I call advanceCounter() or setNumbers() from my webpage, to update the odometer?

Help.

Here is a demo of the actual plugin (from the author himself). http://www.frontendmatters.com/demos/jodometer/

2 Answers 2

1

It looks like you could just set it when you get new data like this:

function updateTimer(newVal)
{
    $(".myCounter").jOdometer({ counterStart: newVal, counterEnd:newVal, numbersImage: 'images/jodometer-numbers.png'});
}

I'm not sure what you would want the increment to be, if any, but this should do the trick.

Update:

Here it is with the built-in animation.

Open up your jquery.jodometer.js file. Look at line 100 (right below the function 'advanceCounter()') and add this:

$.fn.Advance = function(newVal)
{
    setNumbers(newVal);
}

Now you can increment the counter by doing:

$("#MyCounterDiv").Advance(150); //150  whatever new value you want.

Update 2:

I was only testing with one counter. aVC pointed out that only the last counter initialized will be affected. Here's how I worked around that:

Replace the setNumbers function with this:

function setNumbers(counter, elem){
    digits = String(counter).split('.'); // check decimals
    // if we where using decimals
    if (decimalsArray.length > 0){
        // for each decimal digit, update the old digit position to the new
        for (i=0;i<decimalsArray.length;i++){
            oldDigit = decimalsArray[i];
            // the new numer could have not decimal part, but we need it anyway
            if (digits[1]){
                decimalsArray[i] = digits[1].charAt(i);
            }
            if (decimalsArray[i] == ''){
                decimalsArray[i] = '0';
            }
            var theScope = (elem) ? elem : scope;
            console.log(theScope);
            updatePosition($('.jodometer_decimal_'+i, theScope), parseInt(decimalsArray[i]), parseInt(oldDigit));
        }
    }

    integers = digits[0];
    j=integers.length-1;
    // for each integer digit, update the old digit position to the new
    for (i=0;i<integersArray.length;i++){
        oldDigit = integersArray[i];
        integersArray[i] = integers.charAt(j);
        if (integersArray[i] == ''){
            integersArray[i] = '0';
        }
        var theScope = (elem) ? elem : scope;
        console.log(theScope);
        updatePosition($('.jodometer_integer_'+i, theScope), parseInt(integersArray[i]), parseInt(oldDigit));
        j--;
    }
}

I added another parameter "elem" which will be passed in the Advance function we added earlier. Just need to change the $.fn.Advance function to this:

$.fn.Advance = function(newVal)
{
    setNumbers(newVal, $(this));
}

Finally, I found that for some reason I needed to remove an if statement from the updatePosition function. This if statement figures out if you're trying to tell it to 'change' to the same number. It breaks because it checks the wrong counter's settings. We could work around this if it's important, but I just decided to comment it out :P

function updatePosition(col, newDigit, oldDigit){
    //if(newDigit != oldDigit){
        col.stop();
        // if the number is 0 use the bottom 0 in the image, and change intantly to the top 0
        if (newDigit == 0){
            col.animate({top: (10*settings.heightNumber*-1)+zeroSet}, settings.speed, settings.easing).animate({top: zeroSet},1, 'linear');
        }else{
            // if the new number is lower than the old, we have to go to the bottom 0 and start from the top 0, with the apropiate speed, to don't note the jump
            if (newDigit < oldDigit){
                col.animate({top: (10*settings.heightNumber*-1)+zeroSet}, settings.speed*((10-oldDigit)/10), 'linear').animate({top: zeroSet},1, 'linear').animate({top: (newDigit*settings.heightNumber*-1)+zeroSet}, settings.speed*oldDigit/10, settings.easing);
            }else{
                col.animate({top: (newDigit*settings.heightNumber*-1)+zeroSet}, settings.speed, settings.easing);
            }
        }
    //}
}
Sign up to request clarification or add additional context in comments.

5 Comments

The quotes in the options object of your example are a bit wacky.
I am looking for the syntax, which will enable me to access the function advanceCounter() which is inside the jquery plugin from the webpage.
@IanW, Thanks. while waiting for your response, I put my trial and error mask on, and got it working with $.fn.Advance = function(newVal) { scope=$.this; setNumbers(newVal); } //scope = $(this),this, etc, plus some other attempts dint work. I dont know if this is the correct way. It works so far. If you got a minute, please check it out. If I find errors, I will stick to your method. Salute! to your mastery
@IanW, Some results. When the update values for the two counters are different, issues pop up. The digits on the second counter seem to flywheel even when the new update value is the same as the old. :P Just a passing thought. Is it possible to have the advancecounter() function through something like $('.Counter').jOdometer.Advance ??? Because, the .jOdometer({}) part works without errors, during the initialization and I think it will clean up the 'scope' error or whatever is causing the issue? .
@aVC, Yeah, but the whole plugin needs to be restructured a bit to do that. I poked around with it a little bit to try and get all the variables to be specific to the jQuery object that's returned when it's initialized, but didn't get too far. The only plugins I've created/worked with have been the kind of 'set it and forget it' ones like this was written as. I'll try and take another look to get the scope working as it should.
0

Remove the old counter and replace it with a new element on which you can call the jodometer plugin:

$.ajax({
    success : function (serverResponse) {

        //create a new element to add to the DOM
        var $counter = $('<div id="counter" />');

        //replace the old `#counter` element with the new one (which has nothing bound to it)
        $('#counter').replaceWith($counter);

        //now initialize the plugin on the new DOM element
        $counter.jodometer({ ... });
    }
});

Update

To animate the change of content you can do something like this:

$.ajax({
    success : function (serverResponse) {

        //create a new element to add to the DOM
        var $counter = $('<div id="counter" style="display:none;" />');

        //replace the old `#counter` element with the new one (which has nothing bound to it)
        $('#counter').fadeOut(500).replaceWith($counter);

        //now initialize the plugin on the new DOM element
        $counter.fadeIn(500).jodometer({ ... });
    }
});

Note that I added style="display:none;" to the new element before adding it to the DOM, this way you can fadeIn() the element.

5 Comments

I was prefering to use teh function because the advanceCounter() makes the change in an animated way. By replacing the old counter, Would nt it simply redraw?
Yes it would just redraw it without an animation. It's not hard to add an animation however. See the update to my answer for an example.
Also, you have removed all of the code from the advanceCounter function. Having done this I cannot give any advice regarding the function since I have no idea what it does. If you want more detailed advise then you will need to post the actual code for the function.
Sorry. The code is big, thats why I had posted a link. github.com/jesucarr/jOdometer/blob/master/jquery.jodometer.js
I have posted the code. Thanks for the fadeIn code. I was hoping to implement the digit slide animation shown in the original demo frontendmatters.com/demos/jodometer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.