0

I’m having trouble fixing a JavaScript issue. I’ll share my HTML and JavaScript code. Here’s what I’m trying to achieve:

Before clicking any star, star-value.textContent should be ‘-��.

When a star is clicked, it should change to that star’s value (e.g., poor, average, good…).

But if the same star is clicked again, it should reset star-value.textContent back to ‘-’.

The problem is: clicking the same star again doesn’t reset it to ‘-’. It just stays at the same value.

Code:

const stars = document.querySelectorAll(".stars");
let selectedStars = 0;

stars.forEach(star => {
  star.addEventListener("mouseover", () => {
    const nthStar = parseInt(star.id.split("-")[1]);

    stars.forEach((s, index) => {
      s.textContent = (index < nthStar) ? "★" : "☆";
    });
  });

  star.addEventListener("mouseleave", () => {
    stars.forEach((s, index) => {
      s.textContent = (index < selectedStars) ? "★" : "☆";
    });
  });

  star.addEventListener("click", () => {
    const nthStar = parseInt(star.id.split("-")[1]);
    if (nthStar === selectedStars) {
      selectedStars = 0;
      return;
    } else {
      selectedStars = nthStar;
    }

    stars.forEach((s, index) => {
      s.textContent = (index < selectedStars) ? "★" : "☆";
    });

    valueDetectOfReview(selectedStars);
  });
});


const review = document.querySelector('.star-value');


function valueDetectOfReview(starNumber) {
  switch (starNumber) {
    case 0:
      review.textContent = '-';
      break;
    case 1:
      review.textContent = 'Very Poor';
      break;
    case 2:
      review.textContent = 'Poor';
      break;
    case 3:
      review.textContent = 'Average';
      break;
    case 4:
      review.textContent = 'Good';
      break;
    case 5:
      review.textContent = 'Excellent';
      break;
    default:
      break;
  }
}
<div class="rating">
  <div class="section-header">
    <p>Rating</p>
  </div>
  <div class="section-main">
    <span class="stars" id="star-1">&#9734;</span>
    <span class="stars" id="star-2">&#9734;</span>
    <span class="stars" id="star-3">&#9734;</span>
    <span class="stars" id="star-4">&#9734;</span>
    <span class="stars" id="star-5">&#9734;</span>
  </div>
  <div class="star-value">-</div>
</div>

1
  • 1
    Remove the return after the selectedStars = 0; Commented May 9 at 16:53

1 Answer 1

2

When you click the selected star, you do selectedStars = 0; return;. That prevents the rest of the event listener from running, so you never reset the text content.

Get rid of the return statement and it does what you want.

const stars = document.querySelectorAll(".stars");
let selectedStars = 0;

stars.forEach(star => {
  star.addEventListener("mouseover", () => {
    const nthStar = parseInt(star.id.split("-")[1]);

    stars.forEach((s, index) => {
      s.textContent = (index < nthStar) ? "★" : "☆";
    });
  });

  star.addEventListener("mouseleave", () => {
    stars.forEach((s, index) => {
      s.textContent = (index < selectedStars) ? "★" : "☆";
    });
  });

  star.addEventListener("click", () => {
    const nthStar = parseInt(star.id.split("-")[1]);
    if (nthStar === selectedStars) {
      selectedStars = 0;
    } else {
      selectedStars = nthStar;
    }

    stars.forEach((s, index) => {
      s.textContent = (index < selectedStars) ? "★" : "☆";
    });

    valueDetectOfReview(selectedStars);
  });
});


const review = document.querySelector('.star-value');


function valueDetectOfReview(starNumber) {
  switch (starNumber) {
    case 0:
      review.textContent = '-';
      break;
    case 1:
      review.textContent = 'Very Poor';
      break;
    case 2:
      review.textContent = 'Poor';
      break;
    case 3:
      review.textContent = 'Average';
      break;
    case 4:
      review.textContent = 'Good';
      break;
    case 5:
      review.textContent = 'Excellent';
      break;
    default:
      break;
  }
}
<div class="rating">
  <div class="section-header">
    <p>Rating</p>
  </div>
  <div class="section-main">
    <span class="stars" id="star-1">&#9734;</span>
    <span class="stars" id="star-2">&#9734;</span>
    <span class="stars" id="star-3">&#9734;</span>
    <span class="stars" id="star-4">&#9734;</span>
    <span class="stars" id="star-5">&#9734;</span>
  </div>
  <div class="star-value">-</div>
</div>

Sign up to request clarification or add additional context in comments.

2 Comments

"remove a return" is hardly worth an answer is it?
I was on the fence, erred on this side.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.