DEV Community

Cover image for Designing a Stars Rating program in vanilla JS
Uriel Bitton
Uriel Bitton

Posted on • Edited on

Designing a Stars Rating program in vanilla JS

Designing a stars rating program can seem rather cumbersome and you might think it requires a lot of code.
Here is our train of thought: Each star must be responsible for turning itself on but as well turning stars below it on and stars above it off. So we may have a click event on all 5 stars and each star's click event turns off some and turns on some. This idea requires a ton of code and makes it long and unreadable.

For efficency, its terrible, it means order of: O(n) - meaning if we have 10 stars we need 10 click events with many lines of code inside it.

Instead let's discover a method that will let us use only a few lines of code to achieve this using unlimited number of stars! - Making our code O(c) where c is a small constant (around 5 lines of code)

The idea is instead of treating each star's onclick functions, we need to find a way to abstract the clicking. But how? The most efficient method is by giving each star a number to compare. Based on that comparision we can decide whether to turn on or off stars that are lower or higher than the current selected star.

Let's see some code.

In this example we'll be working with 5 stars for common product/movie rating features.
We'll also be using the Font Awesome icon pack so make sure to use their cdn link in your html file.

First we'll assign each star a data-attribute number:

<i class="far fa-star" data-num="1"></i>
<i class="far fa-star" data-num="2"></i>
<i class="far fa-star" data-num="3"></i>
<i class="far fa-star" data-num="4"></i>
<i class="far fa-star" data-num="5"></i>
Enter fullscreen mode Exit fullscreen mode

We could have used JS to iterate an array of these elements and produce 5 tags but let's keep it simpel for this example.

Now we can run a forEach function to loop through all the stars

const allstars = document.querySelectorAll('.fa-star')
allstars.forEach(star => {
    star.onclick = () => {

    }
})
Enter fullscreen mode Exit fullscreen mode

We set up this code and detect which star has been clicked.
Next we will retrieve the data attribute value and use it to make our comparision

allstars.forEach(star => {
    star.onclick = () => {
        let starlevel = star.getAttribute('data-num')
        allstars.forEach(el => { //loop through stars again to compare the clicked star to all other stars
           if(starlevel < el.getAttribute('data-num')) {
                el.classList.remove('fas')
                el.classList.add('far')
           }
           else {
              el.classList.remove('far')
              el.classList.add('fas')
           }
        }
    }
})
Enter fullscreen mode Exit fullscreen mode

In this part of the code we retreive the data attribute vaue and assign it to a var called starlevel and we then compare that number to all other star attributes.
Now the real magic happens here. If that starlevel is higher than any starlevel of another star, we will change its class to 'fas' meaning the star is turned on.
But if the star level of the clicked star is lower than any other star levels, it will turn those stars off!

There you have it, in just a few lines of code we created a system of rating that would intuitively taken up possibly over 50 lines of code!

I hope you enjoyed this!
Let me know your thoughts.

Top comments (2)

Collapse
 
piclez profile image
Peter WD

Great article Uriel! I think your 3rd line should be:

star.getAttribute('data-num')

Thanks!

Collapse
 
urielbitton profile image
Uriel Bitton

Yes just corrected it thanks for pointing that out!