Case (shopping cart and carousel javaScript)

1. Shopping cart

style:
     * {<!-- -->
            margin: 0;
            padding: 0;
        }

        table {<!-- -->
            border: 1px solid gray;
            border-collapse: collapse;
            width: 500px;
            height: 200px;
            margin: 20px auto;
            text-align: center;
        }
        td,
        th {<!-- -->
            border: 1px solid white;
            background-color: lightblue;
        }

        th {<!-- -->
            background-color: darkseagreen;
        }

        button {<!-- -->
            width: 35px;
        }
html:

    <table>
        <tr>
            <th>Product name</th>
            <th>Quantity</th>
            <th>Unit price</th>
            <th>Subtotal</th>
            <th>Operation</th>
        </tr>
        <tr>
            <td>Fried noodles</td>
            <td>
                <button> - </button>
                <span class="SingleGoodNum">1</span>
                <button> + </button>
            </td>
            <td>
                Unit price: <span>10</span>
            </td>
            <td>
                Subtotal: <span class="SingleGood-TotalPrice">0</span>
            </td>
            <td>
                Operation: <input type="submit" value="Delete">
            </td>
        </tr>
        <tr>
            <td>Hairy crab</td>
            <td>
                <button> - </button>
                <span class="SingleGoodNum">10</span>
                <button> + </button>
            </td>
            <td>
                Unit price: <span>298</span>
            </td>
            <td>
                Subtotal: <span class="SingleGood-TotalPrice">0</span>
            </td>
            <td>
                Operation: <input type="submit" value="Delete">
            </td>
        </tr>
        <tr>
            <td colspan="5">A total of <span id="AllGoods-TotalNums">0</span> items, with a total cost of <span id="AllGoods-TotalPrices">0</span> yuan.
            </td>
        </tr>
    </table>
script:

    let hBtns = document.getElementsByTagName("button")
    let hFnums = document.getElementsByClassName("SingleGoodNum");
    let hFPrices = document.getElementsByClassName("SingleGood-TotalPrice");
    let hANums = document.querySelector("#AllGoods-TotalNums");
    let hAPrices = document.querySelector("#AllGoods-TotalPrices");
    let hDBtns = document.getElementsByTagName("input");
    
    class Cart{<!-- -->
        constructor(hBtns,hFnums,hFPrices,hANums,hAPrices,hDBtns){<!-- -->
            this.hBtns = hBtns; increase and decrease keys
            this.hFPrices = hFPrices; total price of single meal
            this.hFnums = hFnums; number of single meal portions
            this.hANums = hANums; total number of meals
            this.hAPrices = hAPrices;Total total price
            this.hDBtns = hDBtns; delete key
        }
        Total and total price updates
        updatehANumsAndhAPrices(){<!-- -->
            Declare a variable to collect the number of dishes in each row in the loop
            let nums = 0;
            Use a loop structure to add the number of dishes in each row to the declared variables. The addition requires implicit conversion of the innerhtml string.
            for(var i = 0;i<this.hFnums.length;i + + ){<!-- -->
                nums + =this.hFnums[i].innerHTML/1;
            }
            Total number, here assign the number of collected dishes to the total number
            this.hANums.innerHTML = nums;
            Declare a variable to collect the price subtotal of each row of dishes in a loop
            let prices = 0;
            Use a loop structure to add the subtotal of dish prices in each row to the declared variables. The addition requires implicit conversion of the innerhtml string.
            for(var i = 0;i<this.hFPrices.length;i + + ){<!-- -->
                prices + =this.hFPrices[i].innerHTML/1;
            }
            Total price, here the subtotal of the collected dish prices is assigned to the total price
            this.hAPrices.innerHTML = prices;
        }
        Extra meal
        addFoods(btn){<!-- -->
            Traverse the element positions of the number of dishes according to the passed parameter btn (the increase button that was clicked when the event was triggered)
            let hFnums = btn.previousElementSibling;
            Traverse the element positions of the unit price of the dishes according to the passed parameter btn (the price increase button that was clicked when the event was triggered)
            let Price = btn.parentNode.nextElementSibling.firstElementChild;
            Traverse the element positions of the dish price subtotal according to the passed parameter btn (the price increase button that was clicked when the event was triggered)
            let hFPrices = btn.parentNode.nextElementSibling.nextElementSibling.firstElementChild;
            hFnums.innerHTML = hFnums.innerHTML/1 + 1;
            Calculate the total price of a single meal, the formula is: subtotal = unit price × quantity, no implicit conversion is required here
            hFPrices.innerHTML = hFnums.innerHTML*Price.innerHTML;
             Total number and total price update: The total price and total number of dishes need to be updated each time after adding the number of meals.
            this.updatehANumsAndhAPrices();
        }
        Reduce meals
        reduceFoods(btn){<!-- -->
            Traverse the element positions of the number of dishes according to the passed parameter btn (the decrement button that was clicked when the event was triggered)
            let hFnums = btn.nextElementSibling;
            Traverse the element positions of the dish unit prices according to the passed parameter btn (the decrement button that was clicked when the event was triggered)
            let Price = btn.parentNode.nextElementSibling.firstElementChild;
            Traverse the element positions of the dish price subtotal according to the passed parameter btn (the decrement button that was clicked when the event was triggered)
            let hFPrices = btn.parentNode.nextElementSibling.nextElementSibling.firstElementChild;
            The reduction of dishes requires adding prerequisites and cannot be reduced to a negative number.
            if(hFnums.innerHTML>0){<!-- -->
                hFnums.innerHTML -=1;
            }
            
            Calculate the total price of a single meal
            hFPrices.innerHTML = hFnums.innerHTML*Price.innerHTML;
            Last updated total number of dishes and total price
            this.updatehANumsAndhAPrices();
        }
        delete
        delBtn(btn){<!-- -->
            According to the passed parameter btn (the delete button that was clicked when the event was triggered), traverse the position of the element that needs to be deleted, that is, the tr row. The element tr that needs to be deleted here is the parent element tr of the click event element btn's parent element td.
            let hTr = btn.parentNode.parentNode;
            Parent element removed
            hTr.remove();
            Last updated total number of dishes and total price
            this.updatehANumsAndhAPrices();
        }
        Collection binds all events to facilitate unified calling
        eventBind(){<!-- -->
            The variable that is declared here to save a this pointing to the new object of the constructor. Use that to bring this into the event body.
            let that = this;
            The loop structure traverses the array composed of plus and minus buttons
            for(let i = 0;i<this.hBtns.length;i + + ){<!-- -->
                Set the conditions. When the button key is the even number, it is the decrement button, and the odd number is the increase button. Then bind the click event respectively according to the if selection condition, and then call the increase and decrement functions.
                if(i%2){<!-- -->
                    When calling the sibling attribute of the method in the class, you need to add this, which refers to the attribute or element in the class object created by new. Bind the click event to the corresponding element. If you select the odd-numbered button here, call add Quantity function event body
                    this.hBtns[i].onclick = function(){<!-- -->
                        Because in the event body, if you directly use this to call the function addFoods, the this in the event body represents the element that triggered the event and cannot point to the class object created by new. Therefore, the variable that is used to store this pointing to the class object. , using the variable that here is equivalent to using this pointing to the class object
                        that.addFoods(this);
                    }
                }else{<!-- -->
                    The button under the even number condition is also bound to the click event. The decrement function is called here. The usage is the same as above.
                    this.hBtns[i].onclick = function(){<!-- -->
                        that.reduceFoods(this);
                    }
                }
            }
            The delete key also uses a loop structure to bind click events.
            for(let i = 0;i<this.hDBtns.length;i + + ){<!-- -->
                this.hDBtns[i].onclick = function(){<!-- -->
                    that.delBtn(btn);
                }
            }
        }
    }
    let a = new Cart(hBtns,hFnums,hFPrices,hANums,hAPrices,hDBtns);
    a.eventBind();

2. Carousel chart case

style:
    *{<!-- -->
            margin: 0;
            padding: 0;
        }
        div{<!-- -->
            width: 500px;
            height: 300px;
            margin: 100px auto;
            border: 1px solid;
            position: relative;
            transition: 1s linear;
            background-size: 500px 300px;
        }
        ul{<!-- -->
            width: 80%;
            display: flex;
            position: absolute;
            bottom:15px;
            left: 70px;
            justify-content: space-evenly;
        }
        li{<!-- -->
            list-style: none;
            width: 20px;
            height: 20px;
            border-radius: 50%;
            background-color: black;
        }
        #right{<!-- -->
            width: 30px;
            height: 30px;
            position: absolute;
            right: 10px;
            top: 45%;
        }
        #left{<!-- -->
            width: 30px;
            height: 30px;
            position: absolute;
            left: 10px;
            top: 45%;
        }
html:
    <div>
        <button id="right">></button>
        <button id="left"><</button>
        <ul>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
        </ul>
    </div>
script:
    let hB = document.querySelector("div");Picture box
    let hNext = document.querySelector("#right");right button
    let hLeft = document.querySelector("#left");Left button
    let hLis = document.getElementsByTagName("li");Bottom switch button

    class Pic{<!-- -->
        constructor(hB,hNext,hLeft,hLis){<!-- -->
            this.hB = hB;
            this.hLeft = hLeft;
            this.hNext = hNext;
            this.hLis = hLis;
            this.eventBind(); Integrate binding event calls
            this.index = 0; core logic, change the order of background images and list icon buttons by changing the index value
            this.hB.style.backgroundImage = `url(img/${<!-- -->this.index}.jpg)`; Template string nested variable index
        }
        High-frequency events are written first to facilitate later calls. The method here describes that the background image changes with the change of the index value. The list icon button cycles through each index change to confirm that the corresponding icon turns red, and other icons remain black.
        Lis(){<!-- -->
            Change the background image based on the index value
            this.hB.style.backgroundImage = `url(img/${<!-- -->this.index}.jpg)`;
            The loop structure confirms the list icon corresponding to the subscript corresponding to the index value.
            for(let i = 0;i<this.hLis.length;i + + ){<!-- -->
                if(i == this.index){<!-- -->
                    The list icon corresponding to the new value of index turns red
                    this.hLis[i].style.backgroundColor = `red`;
                }else{<!-- -->
                    Except for the corresponding icon, other icons remain black
                    this.hLis[i].style.backgroundColor = `black`;
                }
            }
        }
        List icon click event, switch different background images by clicking on the list icon.
        onLis(){<!-- -->
            Because there is a function that binds the click event body later, a this needs to be stored here.
            let that = this;
            The loop structure confirms the clicked li and binds the click event to it
            for(let i = 0;i<this.hLis.length;i + + ){<!-- -->
                this.hLis[i].onclick = function(){<!-- -->
                    Assign the value of the list subscript to index
                    that.index = i;
                    Use this value to change the background image
                    that.Lis();
                }
            }
        }
        Here is the next event method of the right arrow button
        Next(){<!-- -->
            The index value increases each time an event is triggered.
            this.index + + ;
            Set restrictions to prevent the index from increasing beyond the bounds. It cannot exceed the number of pictures and the number of list subscripts. When the index reaches the last digit of the li subscript, assign a value of 0 to the index and let it cycle again from the first digit.
            if(this.index == this.hLis.length){<!-- -->
                this.index = 0;
            }
            After the index value changes, call the background image and list icon events to change the position where the background image and icon turn red.
            this.Lis();
        }
        Here is the previous event method of the right arrow button
        Left(){<!-- -->
            Each time an event is triggered, the index value decreases.
            this.index--;
            Set restrictions to prevent the index from increasing beyond the bounds. It cannot exceed the number of pictures and the number of list subscripts. When the index reaches the first position before the first li subscript and crosses the boundary, assign the index to the end of li and let it start from the last position. Cycle forward again
            if(this.index == -1){<!-- -->
                this.index = this.hLis.length-1;
            }
            After the index value changes, call the background image and list icon events to change the position where the background image and icon turn red.
            this.Lis();
        }
        Automatic carousel event body
        Auto(){<!-- -->
            Because there is event body binding for mouse movement in and out later, a this needs to be stored here;
            let that = this;
            let s; This variable is preparing to turn on and off the timer
            this.hB.onmouseout= function(){<!-- -->Start the timer by binding the mouse move-out event to the banner box, because if you only bind the move-in stop, then the timer will completely stop when the mouse moves in and out, and the automatic rotation The playback effect will be gone, so a restart must be added here to ensure that the automatic carousel effect can continue after the mouse is moved out.
                s = setInterval(function(){<!-- -->
                that.onLis(); There can only be one carousel direction in the timer, either left or right. If both directions are written, it will not work.
                that.Next();
            },2000)
            }
            A timer is added here to stop when the mouse moves in; the variable s declared earlier is used here
            this.hB.onmouseover = function(){<!-- -->
                clearInterval(s);
            }
        }
        Integrate event binding to facilitate unified calling
        eventBind(){<!-- -->
            let that = this;
            Call the automatic carousel effect
            this.Auto();
            Left arrow button binding left switching effect
            this.hLeft.onclick = function(){<!-- -->
                that.Left();
            }
            Right arrow button binding right switching effect
            this.hNext.onclick = function(){<!-- -->
                that.Next();
            }
            Call li click to switch background image event
            this.onLis();
            
        }
        
    }

    let a = new Pic(hB,hNext,hLeft,hLis);
    The order of passing parameters cannot be messed up, and must be consistent with the internal constructor of the class. There must be no fewer calling functions, this must be complete, and a this must be saved when encountering an event body;