Be careful when reading data with jQuery!

The set up

On a form of one of our apps we had several buttons with class change-mentor that toggled the visibility of a link delete-mentor related to that object via jQuery, based on the id of said object.

- #...
%tr{id: allocated_mentor.id.to_s}
  = link_to "Change allocation", '#', class: "change-mentor", data: { allocated_mentor: allocated_mentor.id.to_s }

  .change-mentor-form
    - # the form
- #...
$(".change-mentor").click (e) ->
  e.preventDefault()
  allocatedMentor = $(this).data('allocated-mentor')
  $("#" + allocatedMentor + " .change-mentor-form").toggle()
  if $("#" + allocatedMentor + " .public-holiday select").is(':visible')
    $("#" + allocatedMentor + " .public-holiday-link").click()

This would work well, but our Mongo database works with 24 characters ids for objects, being a mixture of digits and letters, for example 56860807896fd140cd000056.

Big numbers

We were told that the toggle functionality wasn’t working for some objects, so we investigated. The problem was when an id of an object would be all-digits, like 568645794449975722000009. But, why?

When doing allocatedMentor = $(this).data('allocated-mentor'), the data that is being read is casted into an appropriate type. In this case, a number. And being 24 digits long, it got into fixed point notation. So if we had the aforementioned id on the data-allocated-mentor attribute, we would have:

> allocatedMentor
5.686457944499757e+23

This would not be usable by the rest of our javascript code, this is, the jQuery selectors would not be well formed and the toggle function wouldn’t work.

A solution

By doing some research, I found out that, reading data using attr instead of data forces the data to be casted into a string, so:

allocatedMentor = $(this).attr('data-allocated-mentor')

Would result in:

> allocatedMentor
"568645794449975722000009"

Allowing the rest of the jQuery code to work as intended.

Conclusion

I wrote about this because I found this to be an interesting bug. I guess the chance of you running into it is fairly low, but in any case, be careful with how you read your data in Javascript!

Picture ‘Cups and Balls’ by Joakim Wahlander, used under CC BY-NC 2.0 license.