I can't get setInterval to work for me - javascript

I have a function called start that is triggered when you push the start button. The start function calls another function called getRandomImage. I want getRandomImage to repeat every 5 seconds, but I just can't get the setInterval method to work for me. I've tried putting the interval on the start function, but that just causes it to fire off once, and doesn't repeat. I've tried putting the interval on the getRandomImages function, but then it doesn't do anything. Essentially I am trying to make a color blindness test that flashes a random image every 5 seconds until 30 images have passed or the user clicks a button. I've been banging my head against this for over 8 hours, and am really questioning my choice in programming languages right now, lol.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"
<title></title>
<link rel="stylesheet" href="ColorPerceptionTest.css">
</head>
<body>
<section>
<img src="Default.png" id="defaultimage">
<form>
<input type="button" id="Button1" value="" onClick="">
<input type="button" id="Button2" value="" onClick="">
<input type="button" id="Button3" value="" onClick="">
<br>
<input type="button" id="Start" value="Start" onClick="start()">
<input type="button" id="Help" value="Help" onClick="help()">
<br>
<p id="help"> </p>
</form>
</section>
<script>
var $ = function(id) {
return document.getElementById(id);
}
$("Button1").style.display = "none";
$("Button2").style.display = "none";
$("Button3").style.display = "none";
var imagesArray = ["3.gif", "05.gif", "5.gif", "6.gif", "7.gif",
"8.gif", "12.gif", "15.gif", "16.gif", "26.gif",
"29.gif", "42.gif", "45.gif", "73.gif",
"74.gif"];
var runTimer = setInterval(start, 5000);
function getRandomImage(imgAr, path) {
path = path || 'images/';
var num = Math.floor( Math.random() * imgAr.length );
var img = imgAr[ num ];
var imgStr = '<img src="' + path + img + '" alt = "">';
$("defaultimage").src = path + img;
$("Button1").style.display = "initial";
$("Button2").style.display = "initial";
$("Button3").style.display = "initial";
if(parseInt(img) < 8){
$("Button1").value = parseInt(img);
$("Button2").value = parseInt(img) - 2;
$("Button3").value = parseInt(img) + 1;
}else if(parseInt(img) > 7 && parseInt(img) < 29){
$("Button1").value = parseInt(img) - 2;
$("Button2").value = parseInt(img);
$("Button3").value = parseInt(img) + 1;
}else{
$("Button1").value = parseInt(img) - 5;
$("Button2").value = parseInt(img) - 9;
$("Button3").value = parseInt(img);
}
}
var start = function(){
$("help").innerHTML = "";
getRandomImage(imagesArray);
$("Start").style.display = "none";
$("Help").style.display = "none";
}
var help = function (){
$("help").innerHTML = "This is a test designed to help you determine" +
" if you have a problem with seeing colors. When you press start, a series of " +
"random images will be displayed. You have 5 seconds to read the number and " +
"select the correct button.";
}
</script>
</body>

Try moving the setInterval call to a point where start is defined...
Your code works fine in this fiddle.
var start = function(){
$("help").innerHTML = "";
getRandomImage(imagesArray);
$("Start").style.display = "none";
$("Help").style.display = "none";
}
var runTimer = setInterval(start, 5000);
Update: To make it more clear, had OP written function start() the posted code would have been properly hoisted. But, as he used a function expression, start is undefined when setInterval is called.
Another update: Here's a forked fiddle to correct the timer based on the button and the comments below.

Related

Z-index in script [duplicate]

I made a website which consists of a display area that randomly spawns 50 circular <div> elements. I want to make it so when one of the circles is clicked, it comes to the foreground. I thought using the addEventListener function on each circle as it's created would work but I can't get it to do anything. Thank you.
HTML
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" type="text/css" href="index_styling.css">
<script type="text/javascript" src="index_scripts.js"></script>
</head>
<header>
<h1>First Last, Assignment #6</h1>
</header>
<div id="orange_strip"></div>
<body>
<form>
<ul>
<li>
<input type="button" name="add" value="Add Square">
<input type="button" name="change" value="Change All Square Colors">
<input type="button" name="reset" value="Reset All Squares">
</li>
</ul>
<div id="display">
</div>
</form>
</body>
<footer>
<div id="copyright">Copyright &copy 2016 - First Mid Last</div>
</footer>
</html>
JavaScript
window.onload = function() {
for (var i = 0; i < 50; i++) {
var display_div = document.getElementById("display");
var circle = document.createElement("div");
var randNum = getRandomDimension(5000);
circle.setAttribute("class", "circle");
circle.style.backgroundColor = getRandomColor();
circle.style.position = "absolute";
circle.style.left = getRandomDimension(550);
circle.style.top = getRandomDimension(450);
circle.addEventListener("click", bringToFront(circle));
display.appendChild(circle);
}
}
function bringToFront(element) {
element.style.zIndex = "1";
}
function getRandomColor() {
var letters = "0123456789abcdef";
var result = "#";
for (var i = 0; i < 6; i++) {
result += letters.charAt(parseInt(Math.random() * letters.length));
}
return result;
}
function getRandomDimension(max) {
var num = Math.floor((Math.random() * max) + 1);
var str = num.toString();
return str += "px";
}
This line:
circle.addEventListener("click", bringToFront(circle));
...does not add an event listener. It calls your bringToFront() method immediately and then attempts to assign its return value as a listener except the return value is undefined. (Meanwhile, the effect of calling that function immediately within the loop means all of your divs get set to z-index: 1 upon their creation.)
You should be passing a reference to the function (note there is no () after the function name):
circle.addEventListener("click", bringToFront);
...and then change the function to work with this, because this will automatically be set to the clicked element at the time the function is called for the event:
function bringToFront() {
this.style.zIndex = "1";
}
The problem is with the current line
circle.addEventListener("click", bringToFront(circle));
That is trying to execute the bringToFront function right away.
AddEventListener just needs to function, and it will execute it when the event fires
circle.addEventListener("click", bringToFront);

My JS timer clock is not stopping when clicked twice on start button [duplicate]

This question already has an answer here:
JavaScript countdown timer with on key press to reset the timer
(1 answer)
Closed 11 months ago.
I have a simple HTML stopwatch logic where I can start and stop the clock with the button click. By clicking on the start button, one can start the timer (shows current time) and update every second. One can stop it by clicking stop button. But if one clicks on start button twice, there is nothing I can do to stop the timer. Below is my code:
var hour = document.getElementById("hoursOut");
var minute = document.getElementById("minsOut");
var second = document.getElementById("secsOut");
var btnStart = document.getElementById("btnStart");
var btnStop = document.getElementById("btnStop");
var waitTimer;
function displayTime() {
var currentTime = new Date();
var currentHour = currentTime.getHours();
var currentMinute = currentTime.getMinutes();
var currentSeconds = currentTime.getSeconds();
hour.innerHTML = twoDigit(currentHour) + ":";
minute.innerHTML = twoDigit(currentMinute) + ":";
second.innerHTML = twoDigit(currentSeconds);
}
function twoDigit(digit) {
if (digit < 10) {
digit = "0" + digit;
}
return digit;
}
function startClock() {
waitTimer = setInterval(displayTime, 1000);
}
function stopClock() {
clearInterval(waitTimer);
}
btnStart.onclick = startClock;
btnStop.onclick = stopClock;
<h1>JavaScript Clock</h1>
<div id="calendarBox">
<!-- OUTPUT TIME VALUES -->
<p class="timeDisplay">
<span id="hoursOut">00:</span>
<span id="minsOut">00:</span>
<span id="secsOut">00</span>
</p>
<!-- BUTTON SET -->
<input id="btnStart" type="button" value="START" />
<input id="btnStop" type="button" value="STOP" />
</div>
I have checked some answers in stackoverflow but most solutions uses a for-loop from 0 to 1000 until it finds the interval id and stop all of them using loop. I am confident there should be an elegant solution than that.
// some stackoverflow suggested answer
for (var i = 1; i < 99999; i++)
window.clearInterval(i);
A possible solution is to prevent the problem before it happens. You can place a check on the running timer (Is there a way to check if a var is using setInterval()?).
In this case you could just have a global timer variable var timer = false the with add a check to the start function. Then the stop function will set the timer variable back to false.
function startClock() {
if(!timer){
timer = true
waitTimer = setInterval(displayTime, 1000);
}
else return
}
function stopClock() {
clearInterval(waitTimer);
timer = false
}
when you double click you start a new setInterval(). So you now have two set intervals running. Only problem is you can't access the first one cause you named the second one the same name. Check if waitTimer exists and if it does stop it. see code:
UPDATE: actually you don't even need an if statement. just call stopClock() before you set waitTimer -- code snippet adjusted
var hour = document.getElementById("hoursOut");
var minute = document.getElementById("minsOut");
var second = document.getElementById("secsOut");
var btnStart = document.getElementById("btnStart");
var btnStop = document.getElementById("btnStop");
var waitTimer;
function displayTime() {
var currentTime = new Date();
var currentHour = currentTime.getHours();
var currentMinute = currentTime.getMinutes();
var currentSeconds = currentTime.getSeconds();
hour.innerHTML = twoDigit(currentHour) + ":";
minute.innerHTML = twoDigit(currentMinute) + ":";
second.innerHTML = twoDigit(currentSeconds);
}
function twoDigit(digit) {
if (digit < 10) {
digit = "0" + digit;
}
return digit;
}
function startClock() {
stopClock();
waitTimer = setInterval(displayTime, 1000);
}
function stopClock() {
clearInterval(waitTimer);
}
btnStart.onclick = startClock;
btnStop.onclick = stopClock;
<h1>JavaScript Clock</h1>
<div id="calendarBox">
<!-- OUTPUT TIME VALUES -->
<p class="timeDisplay">
<span id="hoursOut">00:</span>
<span id="minsOut">00:</span>
<span id="secsOut">00</span>
</p>
<!-- BUTTON SET -->
<input id="btnStart" type="button" value="START" />
<input id="btnStop" type="button" value="STOP" />
</div>

how can i put my randomized answer placement in different divs...Read Post

I'm currently making a simple math game where it generates random multiplication problems and there is multiple choices that the user can pick from. Right now I am getting stuck on how to place my shuffled answers into separate divs for the multiple choices. Also if you notice any collisions that may arise in the future a heads up would be greatly appreciated
Here's the Javascript:
var gameOn = false;
var score;
var interval;
Array.prototype.shuffle = function(){
var i = this.length, j, temp;
while(--i > 0){
j = Math.floor(Math.random() * (i+1));
temp = this[j];
this[j] = this[i];
this[i] = temp;
}//while loop bracket
return this;
}
function stopGame() {
gameOn = false;
if (interval) {
clearInterval(interval);
interval = null;
}//if interval bracket
document.getElementById("startreset").innerHTML = "Start Game";
document.getElementById("time-remaining").style.display = "";
}//function stopGame bracket
//if we click on the start/reset
document.getElementById("startreset").onclick = function () {
//if we are not playing
if (gameOn) {
stopGame();
}/*if gameOn bracket*/ else {
//change mode to playing
gameOn = true;
//set score to 0
score = 0;
document.getElementById("scorevalue").innerHTML = score;
//show countdown box
document.getElementById("time-remaining").style.display = "block";
document.getElementById("startreset").innerHTML = "Reset Game";
var counter = 60;
//reduce time by 1sec in loops
interval = setInterval(timeIt, 1000);
function timeIt(){
document.getElementById("timer-down").innerHTML = counter;
counter--;
//timeleft?
//no->gameover
if ( counter === 0) {
stopGame();
document.getElementById("game-over").style.display = "block";
document.getElementById("game-over").innerHTML = "Game Over" + "<br />" + "<br />" + "Your Score is " + score + "!";
}//if counter bracket
}//timeIt function bracket
//generate new Q&A
generateQA();
function generateQA(){
//this is the first number in the equation
var Na = 1+ Math.round(Math.random() * 9);
//this is the second number in the equation
var Nb = 1+ Math.round(Math.random() * 9);
//the correct answer is when you multiply both together
correctAnswer = Na * Nb;
//these are the randomly generated wrong answers
var w1 = 1+ Math.round(Math.random() * 16);
var w3 = 1+ Math.round(Math.random() * 22);
var w4 = 1+ Math.round(Math.random() * 92);
document.getElementById("question").innerHTML = Na + "x" + Nb;
console.log(correctAnswer);
var myArray = [w1, correctAnswer, w3, w4];
var result = myArray.shuffle();
document.getElementById("box1", "box2", "box3", "box4").innerHTML = result;
}//generateQA function bracket
}//else statement bracket
}//startreset button function bracket
Here's the HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Math Game</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes">
<link rel="stylesheet" href="styling.css">
</head>
<body>
<div id="title">
The Matheroo
</div>
<div id="sunYellow">
<!--Because the score value is going to change as the user plays the game we need to place it in a span and refer to it later with some JAVA-->
<div id="score">
Score: <span id="scorevalue">0</span>
</div>
<div id="correct">
Correct!
</div>
<div id="wrong">
Try Again
</div>
<div id="question">
<span id="firstInt"></span><span id="secondInt"></span>
</div>
<div id="instruction">
Click on the Correct Answer
</div>
<div id="choices">
<div id="box1" class="boxes"></div>
<div id="box2" class="boxes"></div>
<div id="box3" class="boxes"></div>
<div id="box4" class="boxes"></div>
</div>
<div id="startreset">
Start Game
</div>
<div id="time-remaining">
Time Remaining: <span id="timer-down">60</span> sec
</div>
<div id="game-over">
<br />
Game Over
</div>
</div>
<script src="Javascript.js"></script>
</body>
</html>
You can't select multiple elements with getElementById as you did in this line document.getElementById("box1", "box2", "box3", "box4").innerHTML = result;. Selecting multiple elements will be done with querySelectorAll.
But for your case, just do it this way:
document.getElementById("box1").innerHTML = result[0];
document.getElementById("box2").innerHTML = result[1];
document.getElementById("box3").innerHTML = result[2];
document.getElementById("box4").innerHTML = result[3];
You can also do it with a for loop.

Javascript highscore counter not updating

I'm trying to make a game that measures your reaction time, but my fastest score tracker is very buggy. It works during the first reaction test but after that stops working. Thanks in advance to anyone that can help.
<!DOCTPYE html>
<html>
<head>
<script>
window.onload = alert("Press START to start the game. As soon as the screen turns red click the stop button. Get the fastest time you can. Good luck");
var button = document.getElementById("reactionTester");
var start = document.getElementById("start");
var startTime;
var scoreContainer = document.getElementById("p");
var css = document.createElement("style");
css.type= "text/css";
var counter = 0;
var timer = null;
var highscore = document.getElementById("highscore");
var currentRecord = 0;
var highscoreCounter = 0;
function init(){
var startInterval/*in milliseconds*/ = Math.floor(Math.random()*10)*1000;
clearTimeout(timer);
timer = setTimeout(startTimer,1/*startInterval*/);
document.body.appendChild(css);
css.innerHTML = "html{background-color: blue;}";
}
function startTimer(){
startTime = Date.now();
css.innerHTML="null";
css.innerHTML = "html{background-color: red;}";
if(counter==1){
p1 = document.getElementsByTagName('p')[1];
p1.parentNode.removeChild(p1);
counter++;
}
}
function stopTimer(){
if(startTime){
var stopTime = Date.now();
var dif = stopTime - startTime;
alert("Your time is " + dif + " ms");
startTime = null;
css.innerHTML = null;
var p = document.createElement("p");
document.body.appendChild(p);
p.innerHTML = dif;
counter=1;
if (highscoreCounter != 0){
if(dif < currentRecord){
Phighscore2 = document.getElementsByTagName('p')[0];
Phighscore2.parentNode.removeChild(Phighscore2);
document.getElementById("highscore").appendChild(highscoreP);
currentRecord = dif;
highscoreP.innerHTML = currentRecord;
}
else{}
}
else{
var highscoreP = document.createElement("p");
document.getElementById("highscore").appendChild(highscoreP);
currentRecord = dif;
highscoreP.innerHTML = currentRecord;
highscoreCounter++;
}
}
else{
alert("don't trick me");
}
}
</script>
</head>
<body>
<div id="highscore">
</div>
<form id="form">
<div class="tableRow">
<input type="button" value="start" id="start" onclick="init()">
</div>
<div class="tableRow">
<input type="button" id="reactionTester" onclick="stopTimer()" value="stop">
</div>
<div id="p">
</div>
</form>
</body>
</html>
Your problem is caused by the fact that variable highscoreP is defined locally in function stopTimer. Local variables lose their value upon function return. Make it a global variable (and do not forget to remove its 'var' keyword inside the function).
I cannot resist making some additional remarks about your code:
Do not create the same DOM elements over and over again; it complicates your code and stresses out the browser's memory manager. Define all elements statically and refer to them by ID as you already did with the containers (highscore, p).
Do not build a style element dynamically, this is really bad practice. Instead, define CSS classes statically, then assign the classes dynamically by setting attribute className.
Even though you are doing a pretty good job programming in plain javascript, you may want to consider using jQuery.

Can't figure out Javascript Countdown

I need help making a Countdown timer!
The user types a value into a text field, the timer starts when a button is clicked.
The timer text decreases by one every second until it reaches zero.
I have code for the first step, but can't seem to get the second step to work. I know it needs to include a setTimeout and loop.
Heres the code so far :
HTML-
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<div id="form">
<h2> COUNTDOWN</h2>
Seconds: <input type="text" name="seconds" id="seconds" /> <input type="button" value="Start!" id="start" /> <input type="button" value="Pause" id="pause" />
</div>
<div id="info">
</div>
<div id="countdown">
</div>
<script src="script.js"></script>
</body>
</html>
JAVASCRIPT-
window.onload = function(){
var startButton = document.getElementById("start");
var form = document.getElementById("seconds");
var pause = document.getElementById("pause");
var secDiv = document.getElementById("countdown");
var editSec = document.createElement("h1");
startButton.onclick = function (){
editSec.innerHTML = form.value;
secDiv.appendChild(editSec);
};
};
Here it goes:
var globalTime = form.value; //receive the timer from the form
var secDiv = document.getElementById("countdown");
function decreaseValue() {
globalTime = globalTime - 1;
secDiv.innerHTML = globalTime;
}
startButton.onclick = function (){
setTimeout(decreasValue(),1000);
};
//clear out the timers once completed
You need to use setInterval, not setTimeout. Add this code to the onclick function:
editSec.id = "editSec";
window.cdint = setInterval(function(){
var origVal = parseInt(document.getElementById("editSec").innerHTML);
document.getElementById("editSec").innerHTML = origVal - 1;
if(origVal - 1 <= 0){
window.cdint = clearInterval(window.cdint);
}
}, 1000);
Use setInterval
var time = 100;
var countdown = function(){
secdiv.innerHTML = time;
time--;
}
setInterval(countdown,1000);
You can use setTimeout if you want :
startButton.onclick = function () {
var value = parseInt(form.value);
editSec.innerHTML = value;
secDiv.appendChild(editSec);
setTimeout(function () {
editSec.innerHTML = --value < 10
? '<span style="color:red">' + value + '</span>'
: value;
if (value) {
setTimeout(arguments.callee, 1000);
}
}, 1000);
};

Categories

Resources