javascript multiple rating svg star click

72
February 10, 2021, at 11:10 PM

I have a rating star animation, on click should make the parent(span) active with a class. I have multiple rating and I have the star 1 to 5 rating with also the half rating should work.

Currently I can increase. But I can't go from say 4 back to 1

Please have a look at my demo for a "fully" working example

This is a js css challenge:-)

JS

var ratingElemOne = $('.ratingOne input[name="starOne"]');
 
ratingElemOne.change(function (e) {
        if (this.checked) {
            $(this).parent().addClass("active");
        }
    });
 
var ratingElemTwo = $('.ratingTwo input[name="starTwo"]');
ratingElemTwo.change(function () {
    if (this.checked) {
        $(this).parent().addClass("active");
    }
});

HTML

<div class="col-8 md-col-8 pt2 relative">
  <svg style="position: absolute; width: 0; height: 0; overflow: hidden" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <symbol id="starOne" viewBox="0 0 28 28" preserveAspectRatio="xMaxYMax meet">
      <title>Star Rating</title>
      <path class="starOne" d="M13.996,22.501 L22.649,27.997 L20.352,17.637 L27.996,10.667 L17.930,9.768 L13.996,-0.003 L10.063,9.768 L-0.003,10.667 L7.641,17.637 L5.345,27.997 L13.996,22.501 Z" />
    </symbol>
  </svg>
  <p>Value for money?</p>
  <div class="rating ratingOne">
    <fieldset class="rating-fieldset">
      <span>
        <input type="checkbox" id="starOne5" class="rating-checkbox" value="5" name="starOne" /><label class="full" for="star5" title="Awesome - 5 stars">
          <svg role="img" aria-label="rating">
            <use xlink:href="#starOne"></use>
          </svg>
        </label>
        <input type="checkbox" id="star4half" class="rating-checkbox" value="4.5" name="starOne" /><label class="half" for="star4half" title="Pretty good - 4.5 stars" name="star">
          <svg role="img" aria-label="rating">
            <use xlink:href="#starOne"></use>
          </svg>
        </label>
      </span>
      <span>
        <input type="checkbox" id="star4" class="rating-checkbox" value="4" name="starOne" /><label class="full" for="star4" title="Pretty good - 4 stars">
          <svg role="img" aria-label="rating">
            <use xlink:href="#starOne"></use>
          </svg>
        </label>
        <input type="checkbox" id="star3half" class="rating-checkbox" value="3.5" name="starOne" /><label class="half" for="star3half" title="Meh - 3.5 stars">
          <svg role="img" aria-label="rating">
            <use xlink:href="#starOne"></use>
          </svg>
        </label>
      </span>
      <span>
        <input type="checkbox" id="star3" class="rating-checkbox" value="3" name="starOne" /><label class="full" for="star3" title="Meh - 3 stars" name="star">
          <svg role="img" aria-label="rating">
            <use xlink:href="#starOne"></use>
          </svg>
        </label>
        <input type="checkbox" id="star2half" class="rating-checkbox" value="2.5" name="starOne" /><label class="half" for="star2half" title="Kinda bad - 2.5 stars">
          <svg role="img" aria-label="rating">
            <use xlink:href="#starOne"></use>
          </svg>
        </label>
      </span>
      <span>
        <input type="checkbox" id="star2" class="rating-checkbox" value="2" name="starOne" /><label class="full" for="star2" title="Kinda bad - 2 stars">
          <svg role="img" aria-label="rating">
            <use xlink:href="#starOne"></use>
          </svg>
        </label>
        <input type="checkbox" id="star1half" class="rating-checkbox" value="1.5" name="starOne" /><label class="half" for="star1half" title="Meh - 1.5 stars">
          <svg role="img" aria-label="rating">
            <use xlink:href="#starOne"></use>
          </svg>
        </label>
      </span>
      <span>
        <input type="checkbox" id="star1" class="rating-checkbox" value="1" name="starOne" /><label class="full" for="star1" title="Sucks big time - 1 star">
          <svg role="img" aria-label="rating">
            <use xlink:href="#starOne"></use>
          </svg>
        </label>
        <input type="checkbox" id="starhalf" class="rating-checkbox" value="0.5" name="starOne" /><label class="half" for="starhalf" title="Sucks big time - 0.5 stars">
          <svg role="img" aria-label="rating">
            <use xlink:href="#starOne"></use>
          </svg>
        </label>
      </span>
      <small>Rate Now</small>
    </fieldset>
  </div>
</div>

https://jsfiddle.net/davidesitua/mq2xfp9L/

Answer 1

It is way easier if you create all SVG client-side, using a Custom Element (supported in all modern Browsers):

  • copied only the d-path from a star icon
  • Edited the d-path in https://yqnn.github.io/svg-path-editor/ to a 100x100 viewBox/grid
  • made it an inverse star by prepending M0 0h100v100h-100v-100 to the path
  • Created a new SVG file in a 0 0 N 100 viewBox to fit all stars.. see below
  • Added a background rectangle setting gold color rating
  • Used inverse stars, each at an x-offset
  • added rectangles covering all half-stars
  • set inline events onclick and onmouseover on every "half-star"

<star-rating stars=5 rating="3.5"
             bgcolor="green" nocolor="grey" color="gold"></star-rating>
<star-rating stars=7 rating="50%"
             bgcolor="rebeccapurple" nocolor="beige" color="goldenrod"></star-rating>
<script>
  document.addEventListener("click", (evt) => console.log(evt.target.getAttribute("n")))
  customElements.define("star-rating", class extends HTMLElement {
    set rating( rate ) {
      if (!String(rate).includes("%")) rate = Number(rate) / this.stars * 100 + "%";
      this.querySelector("#rating").setAttribute("width", rate);
    }
    connectedCallback() {
      let { bgcolor, stars, nocolor, color, rating } = this.attributes;
      this.stars = ~~stars.value || 5;
      this.innerHTML = 
        `<svg viewBox="0 0 ${this.stars*100} 100" style="cursor:pointer;width:300px">`
      + `<rect width="100%" height="100" fill="${nocolor.value}"/>`
      + `<rect id="rating"  height="100" fill="${color.value}"  />`
        + Array(  this.stars     ).fill()
               .map((i, n) => `<path fill="${bgcolor.value}" d="M${ n*100 } 0h102v100h-102v-100m91 42a6 6 90 00-4-10l-22-1a1 1 90 01-1 0l-8-21a6 6 90 00-11 0l-8 21a1 1 90 01-1 1l-22 1a6 6 90 00-4 10l18 14a1 1 90 010 1l-6 22a6 6 90 008 6l19-13a1 1 90 011 0l19 13a6 6 90 006 0a6 6 90 002-6l-6-22a1 1 90 010-1z"/>`)
               .join("")
        + Array(  this.stars * 2 ).fill()
               .map((i, n) => `<rect x="${ n*50 }" n="${n}" opacity="0" width="50" height="100"`
                  + ` onclick="dispatchEvent(new Event('click'))" `
                  + ` onmouseover="this.closest('star-rating').rating = ${(n+1)/2}"/>`)
              .join("") 
      + "</svg>";
      this.rating = rating.value;
    }
  });
</script>

READ ALSO
The xlabels and xtick labels overlap between subplots in matplotlib. How to solve it?

The xlabels and xtick labels overlap between subplots in matplotlib. How to solve it?

The xlabels and xtick labels overlap between subplots as shown in the figureI am trying to use tight_layout() and plt

78
ANDROID REPLAY TOUCH EVENTS [closed]

ANDROID REPLAY TOUCH EVENTS [closed]

Want to improve this question? Update the question so it's on-topic for Stack Overflow

93
GitBash installed but not able to find any node module

GitBash installed but not able to find any node module

I have installed git-bash in windows 10After that, I installed http-server and lerna globally using -g

86
How to implement HTML/JS with Github API to save changes in file to Repository

How to implement HTML/JS with Github API to save changes in file to Repository

In numerous software/web programs, including TiddlyWiki5, I have seen advanced "Save to Github" featuresThese features generally need use of username, repository, and password/PAT, and save changes to the actual file to the Github Repository

54