Danny
Danny

Reputation: 25

How do I print a repeated piece of javascript to a HTML document using a for loop?

Self-teaching amateur here trying to create a worksheet to help students practice simultaneous equations. I am struggling with how to run the code below repeatedly to generate multiple questions.

I think the issue is with the [i] here

document.getElementsByClassName("question")[i].getElementsByClassName("part")[n].innerHTML

Could someone please explain to me why using the for loop variable to repeatedly write to HTML like this does not work and how I can fix it?

Thanks very much for your help.

<div class="question">
  <ul>
    <li class="part"></li>
    <li class="part"></li>
    <li class="part"></li>
  </ul>
</div>

<div class="question">
  <ul>
    <li class="part"></li>
    <li class="part"></li>
    <li class="part"></li>
  </ul>
</div>



for (i = 0; i < 5; i++){
    var n = 12

    x = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*n))
    y = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*n))
    z = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*n))

    m = 20
    a = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*m))
    b = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*m))
    c = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*m))

    d = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*m))
    e = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*m))
    f = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*m))

    g = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*m))
    h = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*m))
    i = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*m))

    rhs1 = a*x + b*y + c*z
    rhs2=  d*x + e*y + f*z
    rhs3 = g*x + h*y + i*z

    document.getElementsByClassName("question")[i].getElementsByClassName("part")[0].innerHTML= a + " x + " + b + " y + " + z + " z = " + rhs1;
    document.getElementsByClassName("question")[i].getElementsByClassName("part")[1].innerHTML= d + " x + " + e + " y + " + f + " z = " + rhs2;
    document.getElementsByClassName("question")[i].getElementsByClassName("part")[2].innerHTML= g + " x + " + h + " y + " + i + " z = " + rhs3;

  }

Upvotes: 2

Views: 237

Answers (4)

StackSlave
StackSlave

Reputation: 10627

Maybe you should study the following structures:

//<![CDATA[
/* js/external.js */
let doc, htm, bod, nav, M, I, mobile, S, Q, rand, signedRand; // for use on other loads
addEventListener('load', ()=>{
doc = document; htm = doc.documentElement; bod = doc.body; nav = navigator; M = tag=>doc.createElement(tag); I = id=>doc.getElementById(id);
mobile = nav.userAgent.match(/Mobi/i) ? true : false;
S = (selector, within)=>{
  var w = within || doc;
  return w.querySelector(selector);
}
Q = (selector, within)=>{
  var w = within || doc;
  return w.querySelectorAll(selector);
}
rand = (min, max)=>{
  let mn = min, mx = max;
  if(mx === undefined){
    mx = mn; mn = 0;
  }
  return mn+Math.floor(Math.random()*(mx-mn+1));
}
signedRand = (min, max)=>{
  return (Math.random() < 0.5 ? 1 : -1)*rand(min, max);
}
// magic under here - you could put below on a separate page using a load event - execept the end load
const question = Q('.question');
let n, x, y, z, a, b, c, d, e, f, g, h, i, xyz, p;
for(let q of question){
  n = 13; x = signedRand(n); y = signedRand(n); z = signedRand(n);
  n = 21; a = signedRand(n); b = signedRand(n); c = signedRand(n);
  d = signedRand(n); e = signedRand(n); f = signedRand(n);
  g = signedRand(n); h = signedRand(n); i = signedRand(n);
  xyz = S('.xyz', q); p = Q('.part', q);
  xyz.textContent = 'x = '+x+'; y = '+y+'; z = '+z+';';
  p[0].textContent = a+'x + '+b+'y + '+c+'z = '+(a*x+b*y+c*z);
  p[1].textContent = d+'x + '+e+'y + '+f+'z = '+(d*x+e*y+f*z);
  p[2].textContent = g+'x + '+h+'y + '+i+'z = '+(g*x+h*y+i*z);
}
}); // end load
//]]>
/* css/external.css */
*{
  box-sizing:border-box; font-size:0; color:#000; padding:0; margin:0; overflow:hidden;
}
html,body,.main{
  width:100%; height:100%;
}
.main{
  background:#333; overflow-y:auto; padding:7px 10px;
}
.question>div{
  color:#fff; font:bold 22px Tahoma, Geneva, sans-serif;
}
.question>.xyz{
  background:#ccc; color:#000; padding:3px 5px; margin-bottom:2px; border-radius:1px;
}
.question{
  padding:7px; border:1px solid #fff; border-radius:2px; margin-bottom:7px;
}
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
  <head>
    <meta charset='UTF-8' /><meta name='viewport' content='width=device-width, height=device-height, initial-scale:1, user-scalable=no' />
    <title>Title Here</title>
    <link type='text/css' rel='stylesheet' href='css/external.css' />
    <script src='js/external.js'></script>
  </head>
<body>
  <div class='main'>
    <div class='question'>
      <div class='xyz'></div>
      <div class='part'></div>
      <div class='part'></div>
      <div class='part'></div>
    </div>
    <div class='question'>
      <div class='xyz'></div>
      <div class='part'></div>
      <div class='part'></div>
      <div class='part'></div>
    </div>
    <div class='question'>
      <div class='xyz'></div>
      <div class='part'></div>
      <div class='part'></div>
      <div class='part'></div>
    </div>
    <div class='question'>
      <div class='xyz'></div>
      <div class='part'></div>
      <div class='part'></div>
      <div class='part'></div>
    </div>
    <div class='question'>
      <div class='xyz'></div>
      <div class='part'></div>
      <div class='part'></div>
      <div class='part'></div>
    </div>
    <div class='question'>
      <div class='xyz'></div>
      <div class='part'></div>
      <div class='part'></div>
      <div class='part'></div>
    </div>
    <div class='question'>
      <div class='xyz'></div>
      <div class='part'></div>
      <div class='part'></div>
      <div class='part'></div>
    </div>
  </div>
</body>
</html>

Upvotes: 0

vp_arth
vp_arth

Reputation: 14982

Extract the function:

function getTriplet(n) {
  return [0, 1, 2].map(_ => (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*n)));
}

const [x, y, z] = getTriplet(12);

console.log(x, y, z);

Generate the DOM dynamically:

function getQuestion(parts) {
  const q = document.createElement('div');
  q.classList.add('question');

  const list = document.createElement('ul');
  for (const part of parts) {
    const item = document.createElement('li');
    item.classList.add('part');
    item.innerText = part;
    list.appendChild(item);
  }
  q.appendChild(list);
  return q;
}

document.body.appendChild(getQuestion(['A', 'B', 'C']));
document.body.appendChild(getQuestion(['1', '2', '3']));

Use string template interpolation for more clarity:

const a = 6;
const b = 7;

document.querySelector('sample').innerText = `${a} * ${b} = ${a * b}`;
<sample></sample>

Don't use global vars. You are reuse global i for loop and calculation, for example.

Upvotes: 1

imvain2
imvain2

Reputation: 15847

The problem that you are having is you are referring to i as an incremental value in your for loop, but you then change it's value to the value of a calculation.

I changed it to cntr.

for (cntr=0; cntr<5; cntr++){
var n = 12

    x = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*n))
    y = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*n))
    z = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*n))

    m = 20
    a = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*m))
    b = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*m))
    c = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*m))

    d = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*m))
    e = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*m))
    f = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*m))

    g = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*m))
    h = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*m))
    i = (Math.random()<0.5? 1:-1)*(Math.ceil(Math.random()*m))

    rhs1 = a*x + b*y + c*z
    rhs2=  d*x + e*y + f*z
    rhs3 = g*x + h*y + i*z

    document.getElementsByClassName("question")[cntr].getElementsByClassName("part")[0].innerHTML= a + " x + " + b + " y + " + z + " z = " + rhs1;
    document.getElementsByClassName("question")[cntr].getElementsByClassName("part")[1].innerHTML= d + " x + " + e + " y + " + f + " z = " + rhs2;
    document.getElementsByClassName("question")[cntr].getElementsByClassName("part")[2].innerHTML= g + " x + " + h + " y + " + i + " z = " + rhs3;

  }

Upvotes: 2

Coupe
Coupe

Reputation: 372

Try this, the first children[0] accesses the ul element and the second children[0 or 1 or 2] access the part, also slight change you can just set a variable equal to the document.getElementsByClassName("question") so you don't need to request it each time

questions = document.getElementsByClassName("question")
questions[i].children[0].children[0].innerHTML = a + " x + " + b + " y + " + z + " z = " + rhs1;
questions[i].children[0].children[1].innerHTML = d + " x + " + e + " y + " + f + " z = " + rhs2;
questions[i].children[0].children[2].innerHTML = g + " x + " + h + " y + " + i + " z = " + rhs3;

Upvotes: 1

Related Questions