Thinking analysis of js case -- five-star scoring effect

Keywords: html5 html css

Thinking analysis of js case -- five-star scoring effect

The purpose of putting the structure and style in front is to make the idea clearer. You can also look at the next steps first, and then come back and look at the two parts to assist in understanding.

1, Structure

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>

    <div id="star">
        <span>You can score by clicking on the stars</span>
        <ul>
            <li><a href="javascript:;">1</a></li>
            <li><a href="javascript:;">2</a></li>
            <li><a href="javascript:;">3</a></li>
            <li><a href="javascript:;">4</a></li>
            <li><a href="javascript:;">5</a></li>
        </ul>
        <!-- When selected, the explanation statement is displayed -->
        <span></span>
        <!-- Show explanatory statements in selection -->
        <p>Select interpretation</p>
    </div>
</body>
</html>

2, Style

<style>
    body {
        color: #666;
        font: 12px/2 Arial;
    }

    #star {
        margin: 10px auto;
        /* border: 1px solid red; */
        width: 800px;
        position: relative;
        /*Set positioning to p label reference*/
    }

    ul {
        list-style-type: none;
        /* border: 1px solid green; */
        margin: 0px 10px;
        /*The outer margin must be set to go up*/

    }

    ul,
    span {
        float: left;
    }

    ul li {
        float: left;

        background: url('./images/star.png') no-repeat;
        text-indent: -9999px;
        /* Hide text in a label */
        width: 24px;
        margin: 0px;

    }
    #star li.on {
        /* The state after the stars are lit */
        background-position: 0 -28px;
    }
    
    p {
        /*Later, you need to change p according to the change of the mouse, so you need to set the positioning*/
        /* border: 1px solid blue;  */
        position: absolute;
        top: 20px;
        width: 200px;
        display: none;
    }

    p em {
        color: #f60;
        display: block;
        font-style: normal;
    }

    strong {
        color: #f60;
        padding-left: 20px;
    }
</style>

3, Steps

  1. Get the node and define a variable, save the index value setScore of the last selected star, set the default value to 0, and bind mouse move in, move out and click events to each star;
  2. Prepare a star state change function sel and pass in a parameter index (a position subscript). The stars before this subscript add the class name "on" and the stars after this subscript remove the class name "on";
  3. Move in event: display the explanatory text, calculate the position of the explanatory text (i.e. the value of left), get the content of the explanatory text, call the star state change function sel, and the incoming parameter is the index value of the current star + 1;
  4. Move out event: hide the explanatory text, call the star state change function sel, and the incoming parameter is setScore;
  5. Click event: get the score corresponding to the last selected star, put it in the span label behind all stars (reserved text display area), call the function sel of stars to change state, and the incoming parameter is setScore;

4, Step implementation

The method adopted is the class method of es6, so the following codes are in the class. It should be noted that the class must be instantiated outside, otherwise the code will not be executed.

  1. Get the node and define a variable, save the index value setScore of the last selected star, set the default value to 0, and bind mouse move in, move out and click events to each star;
        constructor() {
            // Explanatory text
            this.msg = [
                "Very dissatisfied|It's too bad. It's seriously inconsistent with the seller's description. I'm very dissatisfied",
                "dissatisfied|Some parts are damaged, inconsistent with the seller's description, dissatisfied",
                "commonly|The quality is average, not as good as described by the seller",
                "satisfied|Good quality, basically consistent with the seller's description, very satisfied",
                "Very satisfied|Very good quality, completely consistent with the seller's description, very satisfied"
            ];
            // Save last clicked index
            this.setScore = 0;

            // Get node
            this.ulObj = this.$("ul");
            this.lisObj = this.ulObj.children;
            this.spanObj = this.ulObj.nextElementSibling;
            this.pObj = this.$("p");


            // Bind li to move in and move out events and click events
            Array.from(this.lisObj).forEach((li, k) => {
                // console.log(this);
                li.addEventListener("mouseover", this.overFn.bind(this, k));
                li.addEventListener("mouseout", this.outFn.bind(this, k));
                li.addEventListener("click", this.clickFn.bind(this, k));
            });
        }

        /* 
         * Get node object
         * @param tag Gets the selector for the node
        */
        $(tag) {
            return document.querySelector(tag);
        }
  1. Prepare a star state change function sel and pass in a parameter index (a position subscript). The stars before this subscript add the class name "on" and the stars after this subscript remove the class name "on";
        /* 
         * Change of stars 
         * @param index Location index
        */
        sel(index) {
            for (let i = 0; i < this.lisObj.length; i++) {
                i < index ? this.lisObj[i].classList.add("on") : this.lisObj[i].classList.remove("on");
            }
        }
  1. Move in event: display the explanatory text, calculate the position of the explanatory text (i.e. the value of left), get the content of the explanatory text, call the star state change function sel, and the incoming parameter is the index value of the current star + 1;
        /* 
         * Move in 
         * @param index Index of the current star
         * @param event Mouse events, no value transfer
        */
        overFn(index, event) {
            // Calculate the position of explanatory text, display p and change its position
            let left = event.target.offsetWidth * (index + 1) + this.ulObj.offsetLeft;
            this.pObj.style.display = "block";
            this.pObj.style.left = left + "px";

            // Sets the content of explanatory text
            let tmpMsg = this.msg[index].split("|");
            this.pObj.innerHTML = '<em><strong>' + tmpMsg[0] + '</strong></em>' + tmpMsg[1];

            // Select all stars before selection
            this.sel(index + 1);

        }
  1. Move out event: hide the explanatory text, call the star state change function sel, and the incoming parameter is setScore;
        /* 
         * Remove 
         * @param index Index of the current star
         * @param event Mouse events, no value transfer
        */
        outFn(index, event) {
            this.pObj.style.display = "none";
            this.sel(this.setScore);
        }
  1. Click event: get the score corresponding to the last selected star, put it in the span label behind all stars (reserved text display area), call the function sel of stars to change state, and the incoming parameter is setScore;
        /* 
         * click 
         * @param index Index of the current star
         * @param event Mouse events, no value transfer
        */
        clickFn(index, event) {
            // Set the contents of span
            let tmpMsg = this.msg[index].split("|");
            this.spanObj.innerHTML = '<strong>' + tmpMsg[0] + '</strong>' + tmpMsg[1];
            // Change the state of the stars
            this.setScore = index + 1;
            this.sel(this.setScore);
        }

5, Complete source code

In order to avoid being too cumbersome, I put the source code on gitee. The link is as follows:
https://gitee.com/lyxdgitee/js

Posted by ErikTheViking on Thu, 09 Sep 2021 18:34:19 -0700