Search code examples
javascriptjqueryruby-on-railshaml

How to get id from tag name in JavaScript HAML


I built Web App with photos. I want to hide each photo onmouseover but it hides all the photos when my mouse is over one of them. I am trying to get id from tag name in HAML using JavaScript jQuery to hide one photo at a time but it returns nothing. This is what I tried so far:

HAML:

.centered
  %table.table
    %tbody
      - @sorted_photos_array.each do |user_following_photos|
        - user_following_photos.each do |photo|
          %tr
            %td
              .p-3.border
                .email #{@users.find(photo.user_id).email}
                %img{:id => "image", :src => photo.image(:medium)}
                %h3= photo.title
          - break

JavaScript:

$(function() {
    var id = document.getElementsByTagName("img")[0].id;

    $(id).on("mouseover", function() {
        $("img").hide();
    });
});

Solution

  • You're thinking about this completely wrong. Missusing the ID attribute is a common jQuery beginner hangup that just hobbles you. And this approach won't even work since IDs must be unique on the page.

    Instead use attributes like css classes or data attributes to target the elements you want to augment the behavior of and use this or event.target to get the element where the event was fired and DOM traversal to get children, siblings or any other element relative to it.

    .centered
      %table.table
        %tbody
          - @sorted_photos_array.each do |user_following_photos|
            - user_following_photos.each do |photo|
              %tr
                %td
                  .p-3.border
                    .email #{@users.find(photo.user_id).email}
                    %img.my-special-photo-thingy{ src: photo.image(:medium) }
                    %h3= photo.title`
    
    $(function() {
      $('.my-special-photo-thingy').on("mouseover", function(event) {
        // this is bound to event.target in jQuery callbacks 
        $(this).fade();
      });
    });
    

    One gotcha here is that both Turbo and Turbolinks do page replacement with AJAX so dynamically insterted elements will not have the event handler attached to them. You can solve that by using event delegation:

    $(document, "mouseover", ".my-special-photo-thingy", function(event) {
      // this is bound to event.target in jQuery callbacks 
      $(this).fade();
    });
    

    The other gotchas are that the mouseover event happens repeatidly while the users mouse is over the element that you can do the exact same thing in a much more performant way with just CSS Animations .