1
\$\begingroup\$

I'm an EFL teacher, and I built this web app to present a random group of questions for quizzes and tests. The page opens with random questions. Clicking anywhere brings up the spinner. Clicking anywhere again brings up new questions. The app uses viewport units to scale to any device.

The app works well in recent browsers, and on both large screens and tablets. I'd like to share it with other teachers, but I'm concerned the JS and CSS don't follow best practices.

There's one thing that's really bugging me: I've tried to remove the inline event handlers, using this in the script section:

document.getElementById('click').onclick = location.reload();

This hasn't worked for me. Any ideas why not?

https://jsfiddle.net/Nic47/37oeye04/

<!DOCTYPE html>

<html>

<head>
    <meta charset="utf-8">
    <title>Random Test Questions</title>

    <!-- Mobile viewport-->
    <meta name="viewport" content="width=device-width, height=device-height,initial-scale=1.0, user-scalable=no">

<script language="javascript">

// change questions here -- in quotes, comma separated
var qset1 = new Array("Set 1 Question 1","Set 1 Question 2","Set 1 Question 3","Set 1 Question 4","Set 1 Question 5");

var qset2 = new Array("Set 2 Question 1","Set 2 Question 2","Set 2 Question 3","Set 2 Question 4","Set 2 Question 5");

var qset3 = new Array("Set 3 Question 1","Set 3 Question 2","Set 3 Question 3","Set 3 Question 4","Set 3 Question 5");

var qset4 = new Array("Set 4 Question 1","Set 4 Question 2","Set 4 Question 4","Set 4 Question 4","Set 4 Question 5");

var qset5 = new Array("Set 5 Question 1","Set 5 Question 2","Set 5 Question 5","Set 5 Question 4","Set 5 Question 5");



function setUP() {
var set1=Math.floor(Math.random()*qset1.length);
var set2=Math.floor(Math.random()*qset2.length);
var set3=Math.floor(Math.random()*qset3.length);
var set4=Math.floor(Math.random()*qset4.length);
var set5=Math.floor(Math.random()*qset5.length);


document.getElementById('set_1').innerHTML = qset1[set1];
document.getElementById('set_2').innerHTML = qset2[set2];
document.getElementById('set_3').innerHTML = qset3[set3];
document.getElementById('set_4').innerHTML = qset4[set4];
document.getElementById('set_5').innerHTML = qset5[set5];

}

function showQuestions() {
document.getElementById('spinner').style.display = "none";
document.getElementById('click').style.display = "none";
document.getElementById('sets').style.display = "block";


}

function showSpinner() {
document.getElementById('sets').style.display = "none";
document.getElementById('click').style.display = "block";
document.getElementById('spinner').style.display = "block";


}

// Begin Timer script

var mins;
var secs;
//adjust time limits here
function cd() {
    mins = 1 * m("1"); // change minutes here
    secs = 0 + s(":01"); // change seconds here (always add an additional second to your total)
    redo();
}

function m(obj) {
    for(var i = 0; i < obj.length; i++) {
        if(obj.substring(i, i + 1) == ":") break;
    }
    return(obj.substring(0, i));
}

function s(obj) {
    for(var i = 0; i < obj.length; i++) {
        if(obj.substring(i, i + 1) == ":") break;
    }
    return(obj.substring(i + 1, obj.length));
}

function dis(mins,secs) {
    var disp;
    if(mins <= 9) {
        disp = " 0";
    } else {
        disp = " ";
    }
    disp += mins + ":";
    if(secs <= 9) {
        disp += "0" + secs;
    } else {
        disp += secs;
    }
    return(disp);
}

function redo() {
    secs--;
    if(secs == -1) {
        secs = 59;
        mins--;
    }
    document.cd.disp.value = dis(mins,secs); 
    if((mins === 0) && (secs === 0)) {
        end();
    }
    else {
        cd = setTimeout("redo()",1000);
    }
}

function end () {
document.getElementById('txt').style.backgroundColor = "red";
}

window.onload = function() {
  setUP();
  cd();
  showQuestions();
};

</script>

<style>

 #sets div, input 
 {

    font-family:Arial, Helvetica, sans-serif; 
    font-size: 7vh;
    margin-top: 6vh;
    border: 1px solid gray;
    padding: 1vh;
    width: 100%;
    background-color: #ececff;

 }  

input[type="text"], textarea {

  background-color : #4cdc4c;
  text-align:center; 

}

#spinner {
  height: 30vw;
  width: 30vw;

  position: absolute;
  top: 12vh;
  margin-left: 35vw;
  overflow: hidden;
  -webkit-animation: rotation .6s infinite linear;
  -moz-animation: rotation .6s infinite linear;
  -o-animation: rotation .6s infinite linear;
  animation: rotation .6s infinite linear;
  border-left: 3vw solid #ececff;
  border-right: 3vw solid #ececff;
  border-bottom: 3vw solid #ececff;
  border-top: 3vw solid #4cdc4c;;
  border-radius: 100%;
}

@-webkit-keyframes rotation {
  from {
    -webkit-transform: rotate(0deg);
  }
  to {
    -webkit-transform: rotate(359deg);
  }
}

@-moz-keyframes rotation {
  from {
    -moz-transform: rotate(0deg);
  }
  to {
    -moz-transform: rotate(359deg);
  }
}

@-o-keyframes rotation {
  from {
    -o-transform: rotate(0deg);
  }
  to {
    -o-transform: rotate(359deg);
  }
}

@keyframes rotation {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(359deg);
  }
}

#click {
height: 100vh; 
width: 100vw;
}

</style>

</head>

<body> 

     <div id="sets" onclick="setUP();showSpinner();">
            <div id="set_1">???</div>
            <div id="set_2">???</div>
            <div id="set_3">???</div>
            <div id="set_4">???</div>
            <div id="set_5">???</div>

            <form name="cd">
            <input id="txt" readonly type="text" value="" border="0" name="disp">
            </form> 
    </div>

<div id="click"  onclick="location.reload();"><div id="spinner"></div></div>


</body>

</html>
\$\endgroup\$
1
\$\begingroup\$

At first:

 document.getElementById('click').onclick = location.reload;

that does work. You have to pass a function, not the result of the function.

You should shortify the code: youre calling the same functions multiple times, so its much shorter to create a function that does all these:

function question(array,output){
    var elem=Math.floor(Math.random()*array.length);
document.getElementById(output).innerHTML=array[elem];
}

And then you can do:

question(qset1,"set_1");
question(qset2,"set_2");
....

Your end() function is quite senseless, as it is only called in on place so you could remove this.

In JS, you can put arrays into arrays into arrays into objects into variables...

So in your case, you can make an array for the groups, that contains arrays for the questions:

var questions=[
 ["question 1.1", "question 1.2"],
 [" question 2.1", "question 2.2"]
 ];

Also you could create question objects if you also want to validate answers:

var set=[
[{question:"Name",answer:"Bob"}]
];

And then do

show(set[0][0].question);
function validate(answer){
if(set[0][0].answer==answer){
alert(" right!");
}
}
validate("Bob");//Right!

However this is just an example.

By the way, if you try to handle big datastructures, you should go more into OOP, youre programming really functional, wich isnt the best choice while handling a lot of data... :)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.