简体   繁体   中英

How to run same function on multiple elements?

I created a web page with 3 counters that can be triggered separately, but I have a problem with the count function I can't use it on the 3 counters.

I manage to retrieve the index of each button but I don't know how to use it to trigger each counter separately.

can you help me to solve this problem please?

Here is my code.

 "use strict"; /* ___________________________Déclarer les variables et les fonctions______________________________ */ /* Déclaration des variables */ var item = document.querySelectorAll('.slider-item'); var str = document.querySelectorAll('.buttons--start'); var stp = document.querySelectorAll('.button--stop'); var start = 0; var end = 0; var diff = 0; var timer = 0; /* Fonction chrono */ function chrono(){ end = new Date(); diff = end - start; diff = new Date(diff); var sec = diff.getSeconds(); item.innerHTML = sec; timer = setTimeout("chrono()", 10); } /* Fonction pour déclancher le chrono */ function chronoStart(i){ start = new Date(); chrono(); console.log('start '+i); } /* Fonction pour arrêter et rénitialiser le chrono */ function chronoStop(i){ clearTimeout(timer) item[i].innerHTML = "0"; start = new Date(); console.log('stop '+i); } /* Fonction qui change la couleur du background */ function changeColor(i){ let bgColor = '#' + Math.random().toString(16).substr(-6); item[i].style.backgroundColor = bgColor; } /* ___________________________Écouter les événements__________________________________ */ /* Appeler la fonction qui déclanche le chrono lorsqu'on clique sur start*/ for (let i=0; i<item.length; i++) { str[i].addEventListener('click',(e)=>{ chronoStart(i); }); //currentPos = i; } /* Appeler la fonction qui arrête le chrono lorsqu'on clique sur stop*/ for (let i=0; i<item.length; i++) { stp[i].addEventListener('click',(e)=>{ chronoStop(i); }); } /* Appeler la fonction qui change la couleur du background lorsque l'évenement est déclancher*/ for (let i=0; i<item.length; i++) { item[i].addEventListener("click",(e)=>{ changeColor(i); }); }
 body { font-family: Arial, sans-serif; }.wrapper { /* display: flex; flex-flow: column wrap; position: fixed; left: 0; right: 0; top: 0; bottom: 0; padding: 50px; */ }.slider { display: flex; align-items: center; justify-content: center; flex-grow: 1; }.slider-item { font-size: 120px; font-weight: bold; padding: 15px; background-color: yellow; user-select: none; }.buttons { margin-top: 15px; text-align: center; }.buttons button { display: inline-block; padding: 15px; font-size: 16px; color: #fff; border: none; outline: none; background-color: #000; cursor: pointer; }
 <div class="wrapper "> <div class="slider"> <div class="slider-item">0</div> </div> <div class="buttons"> <button class="buttons--start" type="button">Start</button> <button class="button--stop" type="button">Stop</button> </div> </div> <div class="wrapper"> <div class="slider"> <div class="slider-item">0</div> </div> <div class="buttons"> <button class="buttons--start" type="button">Start</button> <button class="button--stop" type="button">Stop</button> </div> </div> <div class="wrapper"> <div class="slider"> <div class="slider-item">0</div> </div> <div class="buttons"> <button class="buttons--start" type="button">Start</button> <button class="button--stop" type="button">Stop</button> </div> </div>

The issue is because you have multiple instances of the same repeated HTML content yet within your logic you do not keep the relevant references to the correct elements when an event occurs.

A simpler way to achieve this would be to loop through the containing elements and find the relevant child elements to bind event handlers to, or to update the content of.

The simple version of this logic would be something like this:

 "use strict"; document.querySelectorAll('.chrono-wrapper').forEach(el => { const container = el; const item = el.querySelector('.slider-item'); const str = el.querySelector('.buttons--start'); const stp = el.querySelector('.button--stop'); var start = 0; var end = 0; var diff = 0; var timer = 0; function chrono() { end = new Date(); diff = end - start; diff = new Date(diff); var sec = diff.getSeconds(); item.innerHTML = sec; timer = setTimeout(chrono, 10); } function chronoStart() { start = new Date(); chrono(); } function chronoStop() { clearTimeout(timer) item.innerHTML = "0"; start = new Date(); } function changeColor(i) { let bgColor = '#' + Math.random().toString(16).substr(-6); item.style.backgroundColor = bgColor; } str.addEventListener('click', chronoStart); stp.addEventListener('click', chronoStop); });
 body { font-family: Arial, sans-serif; }.chrono-wrapper { /* display: flex; flex-flow: column wrap; position: fixed; left: 0; right: 0; top: 0; bottom: 0; padding: 50px; */ }.slider { display: flex; align-items: center; justify-content: center; flex-grow: 1; }.slider-item { font-size: 120px; font-weight: bold; padding: 15px; background-color: yellow; user-select: none; }.buttons { margin-top: 15px; text-align: center; }.buttons button { display: inline-block; padding: 15px; font-size: 16px; color: #fff; border: none; outline: none; background-color: #000; cursor: pointer; }
 <div class="chrono-wrapper"> <div class="slider"> <div class="slider-item">0</div> </div> <div class="buttons"> <button class="buttons--start" type="button">Start</button> <button class="button--stop" type="button">Stop</button> </div> </div> <div class="chrono-wrapper"> <div class="slider"> <div class="slider-item">0</div> </div> <div class="buttons"> <button class="buttons--start" type="button">Start</button> <button class="button--stop" type="button">Stop</button> </div> </div> <div class="chrono-wrapper"> <div class="slider"> <div class="slider-item">0</div> </div> <div class="buttons"> <button class="buttons--start" type="button">Start</button> <button class="button--stop" type="button">Stop</button> </div> </div>

As Rory pointed out while I was doodling this up, you have repeated markup but a single set of variables tracking the timers.

You could remedy this by iterating over the occurrences in the HTML and setting up distinct handlers for each. Here's one way you could do that:

 "use strict"; function init() { // get elements whose id begins with "slider-" const sliders = document.querySelectorAll('[id^=slider-]'); // set up event listeners for each occurrence: sliders.forEach(s => { // the setInterval/timeout identifier for this instance let timerId; // get references to the child elements we need const startButton = s.querySelector('.buttons--start'); const stopButton = s.querySelector('.button--stop'); const display = s.querySelector('.slider-item'); // add a start button click listener startButton.addEventListener('click', () => { // clear existing timer if already running clearTimeout(timerId); // capture the start time const start = new Date(); // function to update the display const update = () => { display.innerHTML = ((Date.now() - start) / 1000).toFixed(1); } // start a timer, update the timerId variable timerId = setInterval(update, 100) // add a listener for the stop button to kill this timer const stopHandler = () => clearInterval(timerId); stopButton.addEventListener('click', () => { stopHandler(); // only needs to run once; remove the listener stopButton.removeEventListener('click', stopHandler); }); }); }); } // kick it off init();
 body { font-family: Arial, sans-serif; }.wrapper { /* display: flex; flex-flow: column wrap; position: fixed; left: 0; right: 0; top: 0; bottom: 0; padding: 50px; */ }.slider { display: flex; align-items: center; justify-content: center; flex-grow: 1; }.slider-item { font-size: 120px; font-weight: bold; padding: 15px; background-color: yellow; user-select: none; }.buttons { margin-top: 15px; text-align: center; }.buttons button { display: inline-block; padding: 15px; font-size: 16px; color: #fff; border: none; outline: none; background-color: #000; cursor: pointer; }
 <div class="wrapper" id="slider-1"> <div class="slider"> <div class="slider-item">0</div> </div> <div class="buttons"> <button class="buttons--start" type="button">Start</button> <button class="button--stop" type="button">Stop</button> </div> </div> <div class="wrapper" id="slider-2"> <div class="slider"> <div class="slider-item">0</div> </div> <div class="buttons"> <button class="buttons--start" type="button">Start</button> <button class="button--stop" type="button">Stop</button> </div> </div> <div class="wrapper" id="slider-3"> <div class="slider"> <div class="slider-item">0</div> </div> <div class="buttons"> <button class="buttons--start" type="button">Start</button> <button class="button--stop" type="button">Stop</button> </div> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM