1

I'm using Odometer to animate some values https://github.hubspot.com/odometer/

I see that it states:

Any libraries you're using to update their value, provided they don't update by erasing and rerendering the odometer element, will work just fine.

But this is what I need to do. Is there a way to get this to work with dynamically created elements? I've tried calling the entire library function again on my AJAX success but no dice...

I have elements on page load that do work correctly (the initial value of 0 is set via JS)

<strong id="odometer-away" class="odometer" data-value="'. $value .'"></strong>

And my js uses jQuery's .text() to set the elements value once scrolled into view. (pulled from the data attribute)

var odo = $('#odometer-away');
odo.text(parseFloat(odo.data('value')));

BUT When I create more of the elements via AJAX and load them to the page, the animations no longer work on those elements and I see that the elements do not contain any of the generated HTML from the odometer script that the elements have on pageload... So clearly something is not registering.

I can't find any information on this and I have looked pretty hard. Here is a fiddle where newly created elements do not animate.

Fiddle demo

isherwood
  • 58,414
  • 16
  • 114
  • 157
Taylor A. Leach
  • 2,115
  • 4
  • 25
  • 43
  • Odometer shouldn't care when the element was created as long as it exists when you invoke the function on it. – isherwood Oct 19 '18 at 18:16
  • Well doesn't the fiddle prove otherwise? – Taylor A. Leach Oct 19 '18 at 18:23
  • You aren't calling Odometer on the new element, near as I can tell. Odometer probably looks for elements with the `odometer` class on document.ready, but you'd have to manually call it on new elements. – isherwood Oct 19 '18 at 18:25

2 Answers2

3

You need to reinitalize the newly created elements, by using new Odometer(). Use this in your fiddle demo.

/* elements already on the page will animate */
setTimeout(function(){
  var odo = $('#odometer-away');
  odo.text(parseFloat(odo.data('value')));
}, 1000);


/* create new element */
var div = document.createElement("DIV");    
div.classList.add("odometer");
div.classList.add("new-odometer");
var t = document.createTextNode(0);      
div.appendChild(t);                              
document.body.appendChild(div); 


/* try and animate newly created elements but it just updates the value... */
setTimeout(function(){
  var new_odo = document.querySelector('.new-odometer');  
   var odPhone = new Odometer({
    el: new_odo,
  });
  odPhone.update(200);
}, 3000);
karthick
  • 11,998
  • 6
  • 56
  • 88
2

Odometer probably looks for elements with the odometer class on document.ready, but you'd have to manually call it on new elements:

  var el = document.getElementById('new-odo');
  var new_odo = new Odometer({
    el: el
  });
  new_odo.update(999);

Demo

isherwood
  • 58,414
  • 16
  • 114
  • 157
  • I can't get it to work if the selector is jQuery. Only using JavaScript. Is this a limitation of Odometer? – Taylor A. Leach Oct 19 '18 at 19:42
  • It's not a jQuery plugin, so it's not expecting a jQuery object. You might get it to work by appending `[0]` to your jQuery selector to indicate the raw DOM element. – isherwood Oct 19 '18 at 19:46