Implement Star Rating Widget using HTML, CSS and JavaScript | The DOM Challenge

Implement Star Rating Widget using HTML, CSS and JavaScript | The DOM Challenge

In order to become a successful FrontEnd developer, it is very important to have a very strong understanding of HTML, CSS, and Javascript, and various topics like DOM and Critical rendering path. And this understanding and skill can be only built by solving various challenges and problems. Challenges can be of any type, it can be as easy as making a small calculator or creating a star rating widget from scratch but the only thing requires that you keep on bettering yourself each day.

This is a 7 series blog based on The DOM Challenge created and formulated by Sunny Puri (SDE2 at Swiggy) and Sadanand Pai (SDE2 at CoinDCX) in order to inspire and push the upcoming or already established developer to brush up their skills and deep-dive more to learn concepts lik̋e Asynchronous nature of JS or DOM manipulation.

Challenge 1: Star Rating

This is the first challenge from The DOM Challenge, creating a star rating utility using HTML, CSS, and JavaScript. For this challenge you would be provided with a simple template and using it you have to solve the challenge.

Note:- You can modify the code according to your style and convenience but make sure you follow all the rules.

Templates

For HTML,

<body>
    <div id="star"></div>
    <div id="display-star"></div>
    <script src="script.js"></script>
</body>

To display the star we need to import the star icon from font awesome using CDN,

<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css">

Star Icons,

<i class="fa fa-star"></i>
<i class="fa fa-star-o"></i>

Also read, What is a Callback Functions in JavaScript

CSS,

.fa-star-o:before {
    content: "\f006";
    color: #5f6368;
}

.fa-star:before {
    content: "\f005";
    color: #d56e0c;
}

Rules

There are a few rules by which your star rating system should abide,

  • When you hover your mouse pointer over the stars, it should turn yellow.
  • If the user enters their mouse at the middle or end, for example, If the user hovers his mouse at the number 4th star, all the stars from 1 to 4 should change their colors to yellow.
  • If users remove the pointer from the stars without clicking over it all the stars should go back to their original state.
  • Lastly, If the user clicks on a star, for example, If the user clicks on the 3rd star then, first all the stars till the 3rd should turn yellow and the rating number should be displayed below it.

Demo

star rating widget

Also read, Easy tutorial to build React Autosuggest from scratch

My Solution

My approach to this problem is very simple, first I have populated the body with a star icon to display 5 stars in a row. The container div brings the icons to the middle of the webpage for aesthetic looks. And Inside the input-container, I added a total 5 star-icons with class fa fa-star-o elements to display empty 5-star icons.

Then, at last, I added an h2 tag with the rating class to display the rating when the user clicks on the star, by default it displays 0.

HTML

<body>
    <h1>Star Rating!!</h1>
    <div class="container">
      <div class="input-container">
      <i class="fa fa-star-o"></i>
      <i class="fa fa-star-o"></i>
      <i class="fa fa-star-o"></i>
      <i class="fa fa-star-o"></i>
      <i class="fa fa-star-o"></i>
      </div>
      <h2 class="rating">0</h2>
    </div>
    <script src="script.js"></script>
</body>

CSS

Then I have added some CSS to make it look more attractive,

body {
  text-align: center;
}

.container{
  width: 100%;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.input-container{
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}

.fa-star-o:before {
  content: "\f006";
  color: #5f6368;
  font-size: 40px;
}

.fa-star:hover {
  cursor: pointer;
}

.fa-star:before {
  content: "\f005";
  color: #d56e0c;
  font-size: 40px;
}

.rating{
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  margin-top: 60px;
}

Also read, JavaScript Functions | How does Function works in Js {Detail Explanation}

JS

In JS we will now add some functions and events which get triggered when the mouse hovers on the stars and when the user clicks on them.

let ratDisplay = document.querySelector('.rating');
let stars = document.querySelectorAll('.fa-star-o');
let totalStar = 0;

At first, we are using a document.querySelector('.rating')method to get the reference of the rating div and save it in the ratDisplay variable and document.querySelectorAll('.fa-star-o') method is used to return the array of all the star-icons div having class fa-star-o and a variable totalStar is used to convert it to the default state of the star icon.

stars.forEach((star, index) => {
  star.dataset.rating = index + 1;
  star.addEventListener('mouseover', onMouseOver);
  star.addEventListener('click', onClick);
  star.addEventListener('mouseleave', onMouseLeave);
});

Now we will iterate through each star-icon div and attach the unique dataset id containing the value which later we can use it to find and differentiate the exact star-icon div on which the mouse is hovering. Also, we will attach three different events of the mouse, like mouseover, click and mouseleave and pass onMouseOver, onClick, and onMouseLeave callbacks which get called when the specific events get triggered.

function onMouseOver(e) {
  const ratingVal = e.target.dataset.rating;
  if (!ratingVal) {
    return;
  } else {
    fill(ratingVal);
  }
}

In mouseover event we pass onMouseOver callback which first checks and gets the id of the current star-icon div through e.target.dataset.rating method on which the mouse is hovering and then pass the id to the fill function.

function fill(ratingVal) {
  for (let i = 0; i < 5; i++) {
    if (i < ratingVal) {
      stars[i].classList.replace('fa-star-o', 'fa-star');
    } else {
      stars[i].classList.replace('fa-star', 'fa-star-o');
    }
  }
}

Fill function is the most important function here, In this function, we run a loop till 5, and check if the passed argument ratingVal is greater than i then we replace star-icon div containing fa-star-o with fa-star else we keep the star-icon div containing class fa-star-o same or if it has class fa-star then replace it with fa-star-o.

function onMouseLeave(e) {
  fill(totalStar);
}

In case of mouseleave event, onMouseLeave callback get triggers which simply call fill function and pass an argument totalStar which has a current value of 0. And in the fill function, as i is not greater than the passed argument ratingVal, thus we keep the star-icon div containing class fa-star-o same or if it has class fa-star then replace it with fa-star-o.

function onClick(e) {
  const ratingVal = e.target.dataset.rating;
  totalStar = ratingVal;
  fill(totalStar);
  ratDisplay.innerHTML = ratingVal;
}

Lastly when the user clicks on any star-icon div, first we store totalStar with the current id of star-icon div on which mouse is hovering and the pass it to fill function. In fill function as the passed argument ratingVal is greater than i, it replaces star-icon div containing fa-star-o with fa-star till the condition is true. And finally, we update the rating with the help of ratDisplay.innerHTML method.

Demo

Also read, How JavaScript works with HTML you might not know

Final Words

I hope you like the article and if did then do comment and let me know about it. I will also be solving the rest of the challenges soon and will be posting a blog on each challenge with the solutions, bookmark this website to get more awesome article like these.

Also, you can check out more articles on JavaScript, Data Strictures and algorithms, and React, and if you are also interested in software or technology we also publish articles in these categories too.