Favorite button/image on HTML table activating when clicking anywhere in the row

Viewed 68

I was able to copy Jquery code from this previous question (adding favourite button to html table) to create a favorites functionality in my html table.

Unfortunately the script activates the favorite/unfavorite script whenever the row is clicked on rather than just when the star image is clicked. It is simple enough to trigger the 'click' function just for the button by pointing to the 'div' rather than 'tr' but when i do so the script breaks in some way as refreshing the page doesn't store the favorite/unfavorite image elements.

HTML code can be found in the above linked question.

The original question/reply has the working code sample here: https://plungjan.name/SO/bookrating/allbooks.html . Note that if you click anywhere in the row it will activate code rather than just the star.

TLDR: how do i change above Jquery script to work when i only want to click on the star rather than the whole row?

Relevant code below:

const showFavs = function(key, favs) {
  if (!favs) return;
  key = key.replace("favs", ""); // this could be cleaner
  favs = JSON.parse(favs);
  $.each(favs, function(i, fav) {
    const selector = "#" + key + " tr td[data-id='" + fav + "']";
        $(selector).closest("tr").trigger("click"); // click the TR
  });
};

$(function() {
  $('tr').click(function(e) {
    const $parentTable = $(this).closest("tbody");
    $(this).find('img.white-star').toggle();
    $(this).find('img.yellow-star').toggle();
    const $favs = $("tr", $parentTable).has('img.yellow-star:visible');
    const favs = $favs.find("td:first").map((i, fav) => $(fav).data("id")).get();
    localStorage.setItem($parentTable.attr("id") + "favs", JSON.stringify(favs));
  })
  // read all favs and trigger them
  Object.keys(localStorage).forEach(key => {
    if (key.endsWith("favs")) showFavs(key, localStorage.getItem(key));
  });

  const $onlyRated = $("#onlyrated");
  if ($onlyRated.length>0) {
    $onlyRated.on("click",function() {  
      if (this.checked) {
        $("tr").find('img.white-star:visible').each(function() {
          $(this).closest("tr").hide();
        });
      }    
      else {
        $("tr").find('img.white-star').each(function() {
          $(this).closest("tr").show();
        });
      }    
    });  
  }
});
1 Answers

When the tr is clicked, you can check if the actual element that was clicked is a "star". If it is, then you run the code, otherwise ignore it. Try this

$(function() {
  $('tr').click(function(e) {
    if ($(e.target).is('.fav img')) {
      $(this).find('img.white-star').toggle();
      $(this).find('img.yellow-star').toggle();
      const $favs = $("tr").has('img.yellow-star:visible');
      $("table").prepend($favs)
      const favs = $favs.find("td:first").map((i, fav) => $(fav).data("id")).get();
      localStorage.setItem("favs", JSON.stringify(favs));
    }
  });

  let favs = localStorage.getItem("favs");
  favs = favs ? JSON.parse(favs) : [];
  $.each(favs, function(i, fav) {
    $("table tr td[data-id='" + fav + "']").each(function() {
      $(this).parent().find('.white-star').trigger('click')
    });
  });
});
img {
  height: 25px;
  cursor: pointer;
}

.hide {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
  <tr>
    <td data-id="Book A">ല്ലെങ്കിൽ (Eg For Book name in another lang )</td>
    <td style="display:none" class="serial-code">book-dais</td>
    <td>
      <div class="fav">
        <img class="white-star" src="https://i.postimg.cc/g0b9JG0w/unfav.png" />
        <img class="yellow-star hide" src="https://i.postimg.cc/QN1T9bSH/fav.png" />
      </div>
    </td>
  </tr>
  <tr>
    <td data-id="Book B">The chair by Jhon</td>
    <td style="display:none" class="serial-code">book-jhon</td>
    <td>
      <div class="fav">
        <img class="white-star" src="https://i.postimg.cc/g0b9JG0w/unfav.png" />
        <img class="yellow-star hide" src="https://i.postimg.cc/QN1T9bSH/fav.png" />
      </div>
    </td>
  </tr>
  <tr>
    <td data-id="Book C"> ലോഡ് </td>
    <td style="display:none" class="serial-code">book-lady</td>
    <td>
      <div class="fav">
        <img class="white-star" src="https://i.postimg.cc/g0b9JG0w/unfav.png" />
        <img class="yellow-star hide" src="https://i.postimg.cc/QN1T9bSH/fav.png" />
      </div>
    </td>
  </tr>
</table>

Credit: https://stackoverflow.com/a/59828700/6214210
Note: localStorage does not work in the snippet so you have to test it locally.

Related