bergJ
bergJ

Reputation: 477

Need some tips on jQuery code optimization

Iam trying to reduce the code of my rating component which is made with html, css and jquery. I've managed to reduce it alot already but there is one piece I cant make generic.

Here do you see the HTML which I want to be able to use multiple times

<div class="col-control description">
 <fieldset class="rating-fieldset">
  <legend class="sr-only">Rating</legend>
   <div class="rating-container">
    <div class="rating">
     <span class="hover-score-label hide" dir="ltr"></span>
     <span class="click-score hide" dir="ltr"></span>
     <div>
      <input type="checkbox" id="star5" name="rating" value="5"><label for="star5" class="star5" title="5"><span>★</span></label>
      <input type="checkbox" id="star4" name="rating" value="4"><label for="star4" class="star4" title="4"><span>★</span></label>
      <input type="checkbox" id="star3" name="rating" value="3"><label for="star3" class="star3" title="3"><span>★</span></label>
      <input type="checkbox" id="star2" name="rating" value="2"><label for="star2" class="star2" title="2"><span>★</span></label>
      <input type="checkbox" id="star1" name="rating" value="1"><label for="star1" class="star1" title="1"><span>★</span></label>
     </div>
    </div>
   </div>
  </fieldset>
 </div>

Here do you see the jQuery which I want to optimize.

$('.rating label').hover(function () {
    $(this).parents('div.rating').find('.hover-score-label').removeClass("hide");

    if (!$(this).parents('div.rating').find('.hover-score-label').hasClass("hide")) {
        $(".click-score").addClass("hide");
    }
    else {
        $(".click-score").removeClass("hide");
    }

}, function () {
    $(".click-score.scored").removeClass("hide")
    $(".hover-score-label").addClass("hide");
});

$(".rating label").eq(0).hover(function () {
    $(this).parents('div.rating').find('.hover-score-label').text("5")
});


$(".rating label").eq(1).hover(function () {
    $(this).parents('div.rating').find('.hover-score-label').text("4")
});

$(".rating label").eq(2).hover(function () {
    $(this).parents('div.rating').find('.hover-score-label').text("3")
});


$(".rating label").eq(3).hover(function () {
    $(this).parents('div.rating').find('.hover-score-label').text("2")
});

$(".rating label").eq(4).hover(function () {
    $(this).parents('div.rating').find('.hover-score-label').text("1")
});

I hoped that it would work with the eq() but it doesnt... When I use the exact same html for the rating (See HTML part) twice on a page, the ".rating label" are not eq(0) till eq(4) but eq(5) till eq(9).

I notice i'm having a hard time to explain exactly what I want. I hope it is clear enough for you to understand.

Thanks in advance

Upvotes: 1

Views: 38

Answers (1)

Rory McCrossan
Rory McCrossan

Reputation: 337560

The first part of your hover logic is a little odd, you first remove the hide class, then check that it's not on the element before adding it back on again...? I presume this is an attempt to toggle the class, so you can just use toggleClass() with no if condition at all. All that said, using a hide class is a little redundant. Just use hide() or show() as needed.

Secondly, closest() is preferred over the use of parents() in this case as it stops traversing up the DOM when the first match is found.

You can also merge the two hover events in to one as they are on the same element. You don't need a handler per-element. I did have to move the hover-score-label element underneath the stars, otherwise the showing/hiding of the element interfered with the hover events.

As you want the label to show a description of the checkbox value you can put that in the title attribute and read it back out. Try this:

$('.rating label').hover(function() {
  $(this).closest('div.rating').find('.hover-score-label').show().text($(this).prop('title'));
}, function() {
  $(".click-score.scored").show();
  $(".hover-score-label").hide();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="col-control description">
  <fieldset class="rating-fieldset">
    <legend class="sr-only">Rating</legend>
    <div class="rating-container">
      <div class="rating">
        <span class="click-score hide" dir="ltr"></span>
        <div>
          <label title="Worst">
            <input type="checkbox" id="star1" name="rating" value="1">
            <span>★</span>
          </label>
          <label title="Bad">
            <input type="checkbox" id="star2" name="rating" value="2">
            <span>★</span>
          </label>
          <label title="Average">
            <input type="checkbox" id="star3" name="rating" value="3">
            <span>★</span>
          </label>
          <label title="Good">
            <input type="checkbox" id="star4" name="rating" value="4">
            <span>★</span>
          </label>
          <label title="Best">
            <input type="checkbox" id="star5" name="rating" value="5">
            <span>★</span>
          </label>
        </div>
        <span class="hover-score-label hide" dir="ltr"></span>
      </div>
    </div>
  </fieldset>
</div>

Upvotes: 1

Related Questions