Search code examples
jquerycoffeescriptthisunobtrusive-javascript

Why doesn't javascript "this" work with "each"?


I'm trying to assign a class to an element upon detecting that it has a data-voted attribute of "true", but the simple addClass line is not working.

I was using $(this) until I read jQuery's documentation for each(), and then switched to the following:

windowReady = ->
  jQuery -> 
    $voteLinks = $('.vote-button a')

    $voteLinks.each (i, current) ->
      if $(current).data('voted') == "true" 
        $(current).addClass('voted')

$(window).load(windowReady);
$(window).on('page:load', windowReady);

$(this)

windowReady = ->
  jQuery -> 
    $voteLinks = $('.vote-button a')

    $voteLinks.each ->
      if $(this).data('voted') == "true" 
        $(this).addClass('voted')

$(window).load(windowReady);
$(window).on('page:load', windowReady);

But even that is still not assigning a class, even though I've confirmed that it does have the data-voted attribute of "true"

CoffeesSript can be converted to Javascript at js2coffee.


Solution

  • As a complement to the answer by @gwho, this implicit type conversion is in fact a documented feature of JQuery:

    HTML5 data-* Attributes

    Every attempt is made to convert the string to a JavaScript value (this includes booleans, numbers, objects, arrays, and null). A value is only converted to a number if doing so doesn't change the value's representation. For example, "1E02" and "100.000" are equivalent as numbers (numeric value 100) but converting them would alter their representation so they are left as strings. The string value "100" is converted to the number 100.

    [...]

    To retrieve the value's attribute as a string without any attempt to convert it, use the attr() method.

    As explained in the above quote, if you "don't like" implicit conversion, you might prefer using attr() (using the full attribute name) instead of data():

    windowReady = ->
      jQuery -> 
        $voteLinks = $('.vote-button a')
    
        $voteLinks.each (i, current) ->
          if $(current).attr('data-voted') == "true" 
            $(current).addClass('voted')
    

    And if you can live with that implicit conversion:

    windowReady = ->
      jQuery -> 
        $voteLinks = $('.vote-button a')
    
        $voteLinks.each (i, current) ->
          if $(current).data('voted') == true 
            $(current).addClass('voted')