简体   繁体   中英

Javascript for-loops for calculations

is there a clean way to do multiple calculations with for-loops? My javascript program has a few tables (workouts) consisting of exercises and the amount of repetitions. The user can change the difficulty by clicking for example the button 25%. It then multiplies the number of repetitions by 0.25, dropping it to a quarter.

Now I have done this multiplication manually, but as there becomes more tables it becomes painful. Any ideas using for-loops? The ID:s are unique.

let difficulty = 1

// Initializing default values 100 %

document.querySelector("#edJumpingJacks").innerHTML = 200;
document.querySelector("#edSquat").innerHTML = 100;

// Eventlisteners for difficulty

document.querySelector("#dif25").addEventListener("click", dif25);
document.querySelector("#dif50").addEventListener("click", dif50);
document.querySelector("#dif75").addEventListener("click", dif75);
document.querySelector("#dif100").addEventListener("click", dif100);

function dif25(){
    difficulty = 0.25;
    document.querySelector("#edJumpingJacks").innerHTML = (200 * difficulty).toFixed(0);
    document.querySelector("#edSquat").innerHTML = (100 * difficulty).toFixed(0);
}
function dif50(){
    difficulty = 0.50;
    document.querySelector("#edJumpingJacks").innerHTML = (200 * difficulty).toFixed(0);
    document.querySelector("#edSquat").innerHTML = (100 * difficulty).toFixed(0);

It's always important to keep your code as simple and readable as possible. I would therefore simplify most of your code, except for the buttons itself (unless you plan to create a lot of them).


Create an array containing your element ids:

let ids = ['edJumpingJacks', 'edSquat'];

Change your click handlers to support just one function with a difficulty param:

document.querySelector("#dif25").addEventListener("click", diff(25));
document.querySelector("#dif50").addEventListener("click", diff(50));
document.querySelector("#dif75").addEventListener("click", diff(75));
document.querySelector("#dif100").addEventListener("click", diff(100));

In your function, loop over your ids array:

function diff (diff) {
    difficulty = diff;
    ids.forEach(function(id) {
        document.querySelector("#" + id).innerHTML = (200 * difficulty ).toFixed(0);
    })
}

Here is a more generic way. all your click elements have the difficulty in their id's and all they need to do is pass that id to the click handler.

var difficulties = [25, 50, 75, 100];
for (var i = 0; i< difficulties.length; i++) {
    document.querySelector("#dif" + difficulties[i]).addEventListener("click", calculateDifficulty(difficulties[i]));
}

function calculateDifficulty(difficulty) {
    return function(e) {
        document.querySelector("#edJumpingJacks").innerHTML = (200 * difficulty).toFixed(0);
        document.querySelector("#edSquat").innerHTML = (100 * difficulty).toFixed(0);
    };
}

You better use only one generic function to calculate the difficulty and append it to the elements, then use this generic function on the click event of your buttons.

This is how should be your code:

Array.from(document.querySelectorAll("#dif25, #dif50, #dif75, #dif100")).forEach(function(btn) {
  btn.onclick = function() {
    diff(parseInt(btn.id.match(/(\d+)$/)[0]));
  }
});

function diff(difficulty) {
  Array.from(document.querySelectorAll("#edJumpingJacks, #edSquat")).forEach(function(el) {
    el.textContent = (200 * difficulty).toFixed(0);
  });
}

Explanation:

Where document.querySelectorAll("#dif25, #dif50, #dif75, #dif100") will match all the buttons, and then attach the event to them dynamically.

And inside your diff function get all the elements that needs to be updated with document.querySelectorAll("#edJumpingJacks, #edSquat") .

Note that you better use el.textContent to change the content of the elements instead of using .innerHTML which is used to change the HTML content.

Demo:

 Array.from(document.querySelectorAll("#dif25, #dif50, #dif75, #dif100")).forEach(function(btn) { btn.onclick = function() { diff(parseInt(btn.id.match(/(\\d+)$/)[0])); } }); function diff(difficulty) { Array.from(document.querySelectorAll("#edJumpingJacks, #edSquat")).forEach(function(el) { el.textContent = (200 * difficulty).toFixed(0); }); } 
 <button id="dif25">dif25</button> <button id="dif50">dif50</button> <button id="dif75">dif75</button> <button id="dif100">dif100</button> <div id="edJumpingJacks">200</div> <div id="edSquat">100</div> 

Thanks for the super fast answers. This solution works perfectly for the multiplication.

One minor problem came around. At the end of the code I give the pressed difficulty-button a CSS-class and make the others grey. With this solution console log is always 25 for each button . Any advice on that?

Edit. I figured it out. Must use double equal signs in the if-statement. Now it works perfectly. And the code shrunk from 130 lines to 60 lines. Sweet!

// Initializing default values 100 %

document.querySelector("#edJumpingJacks").innerHTML = 200;
document.querySelector("#edSquat").innerHTML = 100;
document.querySelector("#edMountainClimber").innerHTML = 90;
document.querySelector("#edSitUp").innerHTML = 80;
document.querySelector("#edJumpOverPlank").innerHTML = 70;
document.querySelector("#edPushUp").innerHTML = 60;
document.querySelector("#edLunge").innerHTML = 50;
document.querySelector("#edPullUp").innerHTML = 40;

// Eventlisteners for difficulty

let difficulties = [25, 50, 75, 100];
for (let i = 0; i< difficulties.length; i++) {
    document.querySelector("#dif" +difficulties[i]).addEventListener("click", calculateDifficulty(difficulties[i]));
}

function calculateDifficulty(difficulty) {
    return function(e) {

    document.querySelector("#edJumpingJacks").innerHTML = (200 * (difficulty /100)).toFixed(0);
    document.querySelector("#edSquat").innerHTML = (100 * (difficulty /100)).toFixed(0);
    document.querySelector("#edMountainClimber").innerHTML = (90 * (difficulty / 100)).toFixed(0);
    document.querySelector("#edSitUp").innerHTML = (80 * (difficulty / 100)).toFixed(0);
    document.querySelector("#edJumpOverPlank").innerHTML = (70 * (difficulty / 100)).toFixed(0);
    document.querySelector("#edPushUp").innerHTML = (60 * (difficulty / 100)).toFixed(0);
    document.querySelector("#edLunge").innerHTML = (50 * (difficulty / 100)).toFixed(0);
    document.querySelector("#edPullUp").innerHTML = (40 * (difficulty / 100)).toFixed(0);

    // Change active difficulty button
    if (difficulty == 25){
        document.querySelector("#dif25").className = "ui green label";
        document.querySelector("#dif50").className = "ui grey label";
        document.querySelector("#dif75").className = "ui grey label";
        document.querySelector("#dif100").className = "ui grey label";
    } else if (difficulty == 50){
        document.querySelector("#dif25").className = "ui grey label";
        document.querySelector("#dif50").className = "ui yellow label";
        document.querySelector("#dif75").className = "ui grey label";
        document.querySelector("#dif100").className = "ui grey label";
    } else if (difficulty == 75){
        document.querySelector("#dif25").className = "ui grey label";
        document.querySelector("#dif50").className = "ui grey label";
        document.querySelector("#dif75").className = "ui orange label";
        document.querySelector("#dif100").className = "ui grey label";
    } else if (difficulty == 100){
        document.querySelector("#dif25").className = "ui grey label";
        document.querySelector("#dif50").className = "ui grey label";
        document.querySelector("#dif75").className = "ui grey label";
        document.querySelector("#dif100").className = "ui red label";
    }
};
}

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