Javascript Traffic light - javascript

<!DOCTYPE>
<html>
<body>
<img id="traffic" src="assets/red.gif">
<button type="button" onclick="ChangeLights()">Change Lights</button>
<script>
var lights = [
"assets/red.gif",
"assets/yellow.gif",
"assets/green.gif",
"assets/yellow.gif",
];
var index = 0;
function ChangeLights() {
setInterval(function () {ChangeLights();}, 1000);
index = index + 1;
if (index == lights.length) index = 0;
var image = document.getElementById('traffic');
image.src=lights[index];
}
</script>
</body>
</html>
Hi, I am trying to make an animation script using JavaScript so that a traffic light sequence changes from red - yellow - green - yellow on a timer once a button is pressed. I only want the sequence to loop once. However, when I implemented the setInterval function into the function, the lights only change from red - yellow - green - red.
Thank you for any help!

var lights = {
red: "https://upload.wikimedia.org/wikipedia/commons/thumb/4/45/Traffic_lights_red.svg/200px-Traffic_lights_red.svg.png",
yellow: "https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Traffic_lights_yellow.svg/200px-Traffic_lights_yellow.svg.png",
green: "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Traffic_lights_dark_green.svg/200px-Traffic_lights_dark_green.svg.png"
};
var sequence = ['red', 'yellow', 'green', 'yellow'];
function startChangeLights() {
for (var index = 0; index < sequence.length; index++) {
changeLight(index, sequence[index]);
}
function changeLight(index, color) {
setTimeout(function() {
var image = document.getElementById('traffic');
image.src = lights[color];
}, index * 1000);
}
}
<div>
<img height=100px id="traffic" src="https://upload.wikimedia.org/wikipedia/commons/thumb/4/45/Traffic_lights_red.svg/200px-Traffic_lights_red.svg.png">
</div>
<div>
<button type="button" onclick="startChangeLights()">Change Lights</button>
</div>
https://codepen.io/anon/pen/VbKQNj?editors=1011

If you are looking for one time sequence, you have to use "setTimeout" method in javascript and besides, define an inner function like the following:
var lights = [
"assets/red.gif",
"assets/yellow.gif",
"assets/green.gif",
"assets/yellow.gif",
];
var index = 0;
function ChangeLights() {
function innerChangeLight(){
index = index + 1;
if (index == lights.length) index = 0;
var image = document.getElementById('traffic');
image.src=lights[index];
}
innerChangeLight();
setTimeout(function () {
innerChangeLight();
}, 1000);
}
<!DOCTYPE>
<html>
<body>
<img id="traffic" src="assets/red.gif">
<button type="button" onclick="ChangeLights()">Change Lights</button>
</body>
</html>

Try this:
var lights = [
"assets/red.gif",
"assets/yellow.gif",
"assets/green.gif",
"assets/yellow.gif",
];
var index = 0;
function ChangeLights(){
setInterval(function() {
if(index == lights.length) {
return;
}
var image = document.getElementById('traffic');
image.src=lights[index];
index = index + 1;
}, 1000);
}
<img id="traffic" src="assets/red.gif"><br>
<button onclick="ChangeLights()">Change Lights</button>

New instance of 'Traffic Light':
Traffic Lights can't always be the same duration in every light....
So, i started to expand this html code..
The improved code with different seconds in every light:
// Traffic Light
// Improved with different durations in every light!
// But in this html code, i will use input tag instead
var TrafficLights = (function() {
// The image
var imageTag = document.getElementById("lightImg");
// Keep track of whether the sequence is running
var running = false;
// Different stages of the traffic light (Also defines the light)
var stages = [
{
"name": "red",
"path": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/45/Traffic_lights_red.svg/200px-Traffic_lights_red.svg.png",
},
{
"name": "green",
"path": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Traffic_lights_dark_green.svg/200px-Traffic_lights_dark_green.svg.png"
},
{
"name": "yellow",
"path": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Traffic_lights_yellow.svg/200px-Traffic_lights_yellow.svg.png"
}
];
// Different amount of seconds in every light change (Must be an positive integer!)
var seconds_every_step = [
18,
24,
3
];
// Current stage of the traffic light
var stage = 0;
// Current steps of the traffic light
var steps = 0;
// Timer for automatically changing light
var timer = null;
/** * Start the traffic light sequence * */
function start() {
// Mark that the light sequence is running
running = true;
// Tell the light to change
changeLight();
}
/** * Stop the sequence from running * */
function stop() {
// Mark that the sequence is not running
running = false;
// Stop the automatic timer from running
clearInterval(timer);
}
/** * Change the light to the next one in the sequence * */
function changeLight() {
// If the timer is not running, this function does not need to do anything
if (running === false) {
clearInterval(timer);
return;
} else {};
// If the current stage gets higher than the number of stages there are, reset to 0
if (stage >= stages.length) {
stage = 0;
} else {};
// If the current steps gets higher than the number of seconds in a step there are, reset to 0
if (steps >= seconds_every_step.length) {
steps = 0;
} else {};
// Get the image from the list of stages
var image = stages[stage];
var wait_seconds = seconds_every_step[steps];
// Update the image tag and defines the light name
imageTag.src = image.path;
imageTag.alt = String("Traffic light color is " + image.name + ".");
// Increase the current stage by 1
stage++;
// Increase the current steps by 1
steps++;
// Set a timeout to change the light at the next interval
timer = setTimeout(changeLight, wait_seconds * 1000);
}
// These functions will be available on the `TrafficLights` object to allow interaction
return {
start: start,
stop: stop
}
})();
<input type="image" width="20px" id="lightImg" src="" alt="">
<br/>
<p>
<button type="button" onclick="TrafficLights.start()">Start Sequence</button> <button type="button" onclick="TrafficLights.stop()">Stop Sequence</button>
</p>
You may see an error code. Just ignore it...

var red = document.getElementById("red");
var yellow = document.getElementById("yellow");
var green = document.getElementById("green");
var btn = document.createElement("BUTTON");
btn.innerHTML = "CLICK ME";
document.body.appendChild(btn);
red.style.opacity = "1";
yellow.style.opacity = "0.2";
green.style.opacity = "0.2";
btn.onclick = function () {
setTimeout(function(){red.style.opacity = "0.2";yellow.style.opacity = "1"; setTimeout(function(){yellow.style.opacity = "0.2";green.style.opacity = "1"; setTimeout(function(){green.style.opacity = "0.2";red.style.opacity = "1"}, 1000);}, 1000);
}, 1000);
}
html{
background: linear-gradient(#08f, #fff);
padding: 40px;
width: 170px;
height: 100%;
margin: 0 auto;
}
.trafficlight{
background: #222;
background-image: linear-gradient(transparent 2%, #111 2%, transparent 3%, #111 30%);
width: 170px;
height: 400px;
border-radius: 20px;
position: relative;
border: solid 5px #333;
}
#red{
background: red;
background-image: radial-gradient(brown, transparent);
background-size: 5px 5px;
width: 100px;
height: 100px;
border-radius: 50%;
position: absolute;
top: 20px;
left: 35px;
animation: 13s red infinite;
border: dotted 2px red;
box-shadow:
0 0 20px #111 inset,
0 0 10px red;
}
#yellow{
background: yellow;
background-image: radial-gradient(orange, transparent);
background-size: 5px 5px;
width: 100px;
height: 100px;
border-radius: 50%;
border: dotted 2px yellow;
position: absolute;
top: 145px;
left: 35px;
animation: 13s yellow infinite;
box-shadow:
0 0 20px #111 inset,
0 0 10px yellow;
}
#green{
background: green;
background-image: radial-gradient(lime, transparent);
background-size: 5px 5px;
width: 100px;
height: 100px;
border-radius: 50%;
border: dotted 2px lime;
position: absolute;
top: 270px;
left: 35px;
box-shadow:
0 0 20px #111 inset,
0 0 10px lime;
animation: 13s green infinite;
}
<div class="trafficlight">
<div id="red"></div>
<div id="yellow"></div>
<div id="green"></div>
</div>
I make a simple HTML and CSS Traffic light from an online example. Then I just create the condition for it to loop red-yellow-green-red.

Related

How to make a count down reset

I'm trying to make a count down so that every 20 sec an alert pops up. I want it to go from 20 to 0 to 20 over and over. I have it working, but it only works once. The rage function dosen't need to be changed, it's the msg function i'm having trouble with. Here's my code.
function rage() {
var i = document.getElementsByName("msg")[6];
var message = document.getElementById("message");
const affichemsg = document.querySelector("msg");
for (i = 0; i < 1; i++) {
message.innerHTML += "Es-tu près ";
}
}
setInterval(rage, 350);
var decompteur = setInterval(msg, 1000);
var temps;
function msg() {
var idTemps = document.getElementById("temps");
temps = parseInt(idTemps.innerHTML);
temps = temps - 1;
idTemps.innerHTML = temps;
if (--temps <= 0) {
alert("!!!!!ES-TU PRÈS!!!!!");
clearInterval(temps);
msg();
idTemps = 20;
var decompteur = setInterval(msg, 1000);
}
}
.titre2 {
width: 650px;
margin: auto;
text-align: center;
border-radius: 35px;
color: #000000;
background-color: #ff0000;
padding: 5px;
margin-bottom: 30px;
}
.bouton {
transition-duration: 0.4s;
border-width: 1px;
cursor: pointer;
}
.boutonOui {
background-color: rgb(234, 234, 234);
}
.boutonOui:hover {
background-color: rgb(177, 177, 177);
}
<div class="header">
<h1 class="titre2">Es-tu près</h1>
</div>
<button
class="bouton boutonOui"
id="boutonOui"
onclick="window.location.href='jeu_educatifs2.html'"
>
Oui
</button>
<div id="temps">20</div>
<div id="message"></div>
<div id="msg" value="6"></div>
the first problem here is that you don't use correctly the method clearInterval. It takes as argument the id of the "timer" created with setInterval. setInterval return directly the id so actually stored it in your variable decompteur and you should use something like that to clear the timer : clearInterval(decompteur).
Also be sure to reset the idTemps with idTemps.innerHTML = 20. Then I don't really understand... Why would you clear the interval then rebuild the same again when you can just set the idTemps.innerHTML so your interval will use the 20 for temps at the next iteration ?
PS: ça fait plaisir de voir un peu de français sur stack :)
You should rewrite your code this way :
function rage() {
var i = document.getElementsByName("msg")[6];
var message = document.getElementById("message");
const affichemsg = document.querySelector("msg");
for (i = 0; i < 1; i++) {
message.innerHTML += "Es-tu près ";
}
}
setInterval(rage, 350);
var decompteur = setInterval(msg, 1000);
function msg() {
var idTemps = document.getElementById("temps");
var temps = parseInt(idTemps.innerHTML) - 1;
idTemps.innerHTML = temps;
if (--temps == 0) {
alert("!!!!!ES-TU PRÈS!!!!!");
idTemps.innerHTML = "20";
}
}
// when you need to, stop decompteur with :
// clearInterval(decompteur);
.titre2 {
width: 650px;
margin: auto;
text-align: center;
border-radius: 35px;
color: #000000;
background-color: #ff0000;
padding: 5px;
margin-bottom: 30px;
}
.bouton {
transition-duration: 0.4s;
border-width: 1px;
cursor: pointer;
}
.boutonOui {
background-color: rgb(234, 234, 234);
}
.boutonOui:hover {
background-color: rgb(177, 177, 177);
}
<div class="header">
<h1 class="titre2">Es-tu près</h1>
</div>
<button class="bouton boutonOui" id="boutonOui" onclick="window.location.href='jeu_educatifs2.html'">
Oui
</button>
<div id="temps">20</div>
<div id="message"></div>
<div id="msg" value="6"></div>
This keep as much of your code as possible, but as Rojo said, your code is very inefficent and there are a lot of things to improve.
Currently, your code is very inefficient. Rather than having your variable temps read from the DOM, you should have the variable update itself:
var temps = 20;
function msg() {
--temps;
}
setInterval(msg, 1000);
Second, you shouldn't be including var inside of that if statement:
if (countdown === 0) {
alert("!!!!!ES-TU PRÈS!!!!!");
clearInterval(decompteur);
// msg(); // You don't need this
temps = 20;
decompteur = setInterval(msg, 1000); // I removed the var
}
Also, you had your variables mixed up (which I fixed)
function rage() {
var i = document.getElementsByName("msg")[6];
var message = document.getElementById("message");
const affichemsg = document.querySelector("msg");
for (i = 0; i < 1; i++) {
message.innerHTML += "Es-tu près ";
}
}
setInterval(rage, 350);
var decompteur = setInterval(msg, 1000);
var temps = 20;
var idTemps = document.getElementById("temps"); // I also moved this outside
function msg() {
--temps;
idTemps.innerHTML = temps;
if (temps === 0) {
alert("!!!!!ES-TU PRÈS!!!!!");
clearInterval(decompteur);
//msg(); //You don't need this
temps = 20;
decompteur = setInterval(msg, 1000);
}
}
.titre2 {
width: 650px;
margin: auto;
text-align: center;
border-radius: 35px;
color: #000000;
background-color: #ff0000;
padding: 5px;
margin-bottom: 30px;
}
.bouton {
transition-duration: 0.4s;
border-width: 1px;
cursor: pointer;
}
.boutonOui {
background-color: rgb(234, 234, 234);
}
.boutonOui:hover {
background-color: rgb(177, 177, 177);
}
<div class="header">
<h1 class="titre2">Es-tu près</h1>
</div>
<button
class="bouton boutonOui"
id="boutonOui"
onclick="window.location.href='jeu_educatifs2.html'"
>
Oui
</button>
<div id="temps">20</div>
<div id="message"></div>
<div id="msg" value="6"></div>
The following code prints the counter value each second and every 20 seconds it prints ALERT. Try to use a similar code for your example because your code is not very clear.
let counter = 0;
setInterval(() => {
counter++;
if (counter % 20 == 0) {
console.log("ALERT! ");
}
console.log("Counter Value: " + (counter % 20));
}, 1000);

Random Box Generator

I'm trying to generate 100 random coloured boxes within the div with the existing by clicking generate button that has top and left position 0-400. Also if I hover over any coloured box it disappears until the last that will give me an alert last box with last box left.
I managed to create a box that generates different colours but im not sure how to generate a 100 let alone hover over and delete the boxes when it is, how would one go about doing that?
My HTML:
<!doctype html>
<html lang="en">
<head>
<title> Generator </title>
<meta charset="utf-8">
<script src="prototype.js"></script>
<script src="task4.js"></script>
<style>
#container {
height: 500px;
}
p {
width: 70px;
height: 70px;
background-color: rgb(100, 100, 255);
border: solid 2px black;
position: absolute;
}
</style>
</head>
<body>
<div id="container">
</div>
<button id="myButton"
onclick="createBoxes()"> Generate More
</button>
</body>
</html>
My JS
window.onload = function()
{
createBoxes();
}
function createBoxes()
{
var colors = ["red", "green", "blue", "purple", "yellow"];
var newP = document.createElement("p");
var top = 10 + "px";
var left = 10 + "px";
newP.style.top = top;
newP.style.left = left;
newP.style.backgroundColor = colors[ Math.floor( Math.random() *5 )];
$("container").appendChild(newP);
}
window.onload = function() {
createBoxes();
}
Let's get this done step by step.
While creating box element, you should not use p tag, div is the best choice here.
I have implemented as far as I understood from your question.
Let me know in the comments if I missed something.
I added comments in the code, check if you get it.
window.onload = function() {
createBoxes();
}
function createBoxes() {
var left = 0;
var top = 0;
var colors = ["red", "green", "blue", "purple", "yellow"];
// create a for loop and run 99 times;
for (var i = 1; i < 100; i++) {
var newDiv = document.createElement("div");
newDiv.classList.add('box')
newDiv.style.backgroundColor = colors[Math.floor(Math.random() * 5)];
newDiv.style.top = top + 'px';
newDiv.style.left = left + 'px';
// now add the event on this one;
newDiv.addEventListener('mouseover', removeBoxes);
$("#container").append(newDiv);
left += 70; // increase left 70px each time in the loop
if (i % 5 == 0) { // if the we have 5 boxes in one row, reset left to 0px and increase top property by 70px to get another row;
left = 0;
top += 70;
}
}
}
// function to remove the boxes on hover;
function removeBoxes() {
$(this).remove();
}
// add the mouseover event listener;
$('div.box').on('mouseover', removeBoxes);
#container {
min-height: 200px;
}
div.box {
width: 70px;
height: 70px;
background-color: rgb(100, 100, 255);
border: solid 2px black;
display: inline-block;
position: absolute;
box-sizing: border-box;
}
#myButton {
position: absolute;
right: 0;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
</div>
<button id="myButton" onclick="createBoxes()"> Generate 99 More
</button>

Creating a back button to use in an array

So I'm currently working on a little project website, which basically has changes the background color when pressing a button. But I am also trying to implement a "back" button to go backwards in the color array which I created and in which all color codes that are being generated will be saved. But as you may see when testing the project the back button doesn't quite work and I get that thats due to the "i" variable not being saved when calling the "prevColor" function´.
function prevColor() {
(i == randomColors.length ? bodyStyle.backgroundColor = randomColors[i-2] : bodyStyle.backgroundColor = randomColors[i-1])
};
This is the part that doesnt work out for me, but feel free to check the whole code on jsfiddle.net through the link provided below, or through the snippet (click to Open).
https://jsfiddle.net/jamal000/kobmajyx/
var button = document.querySelector("#change");
var buttonStyle = button.style;
var bodyStyle = document.querySelector("body").style;
var p = document.querySelector("p");
var i = 0;
var randomColors = [];
var hue;
var HSLcolor;
var back = document.querySelector("#back");
button.addEventListener("click", randomHSL);
back.addEventListener("click", prevColor);
function randomHSL(){
hue = Math.floor((Math.random() * 360) + 1);
HSLcolor = `HSL(${hue}, 80%, 70%)`;
bodyStyle.backgroundColor = HSLcolor;
randomColors.push(`${HSLcolor}`);
p.textContent = "Color: " + randomColors[i];
i++;
p.style.color, buttonStyle.borderColor = `HSL(${hue + 180}, 80%, 70%)`;
p.style.color = buttonStyle.borderColor;
};
function prevColor(){
(i == randomColors.length ? bodyStyle.backgroundColor = randomColors[i-2] : bodyStyle.backgroundColor = randomColors[i-1])
};
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
overflow: hidden;
margin: 0;
padding: 0;
width: 100vw;
height: 100vh;
transition: all 0.5s ease;
}
#change {
height: 40.6px;
width: 200px;
outline: none;
font-family: Raleway;
font-size: 15px;
font-weight: 600;
text-decoration: none;
border: 2px solid darkgrey;
border-radius: 10px;
background-color: #f1f1f1;
color: black;
box-shadow: 5px 7px 40px rgba(0,0,0,0.5);
}
#change:hover {
color: #666666;
box-shadow: 7px 10px 40px rgba(0,0,0,0.4);
transition: all 0.5s ease;
}
:active {
border-color: #666666;
transition: all 0.5s ease;
}
p {
font-family: Raleway;
font-weight: 500;
}
#back {
outline: none;
margin-right: 5px;
background-color: inherit;
border: 2px solid #2f2f2f;
border-radius: 5px;
}
#back:hover {
border-color: #aaa;
transition: all 0.5s ease;
}
#back:active {
transition: all 0.2s ease;
color: #aaa;
background-color: inherit;
}
div {
margin-right: 38.172px;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Color Toggle</title>
<link rel="stylesheet" href="style.css" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Raleway:500" rel="stylesheet">
</head>
<body>
<p>Color: White</p>
<div>
<button id="back"> ◄ </button>
<button id="change">Click for a surprise!!!</button>
</div>
<script src="toggle.js"></script>
</body>
</html>
Firstly I want to clarify the UI
<p id="color"></p>
<p id="current"></p>
<button id="back"> ◀ </button>
<button id="new">Click for a surprise!!!</button>
<button id="next"> ▶ </button>
If we want to go back and forward, let's have separate buttons. And one more button for the surprise that will push new color to the array and set the index to that new color.
Then I would extract all DOM manipulations into a single method, let's call it applyColor. Also, I would have a default color value as the first item of the colors array. And index set to 0 appropriately. So the script should can push new color to the colors array, shift color index and update the UI by the applyColor() calls.
const colors = ['white'];
let index = 0;
function applyColor() {
const color = colors[index];
bodyStyle.backgroundColor = color;
colorElement.textContent = "Color: " + color;
currentElement.textContent = (index + 1) + " / " + colors.length;
}
function generateColor() { // bound with click on "new" button
const hue = Math.floor((Math.random() * 360) + 1);
const HSLcolor = `HSL(${hue}, 80%, 70%)`;
colors.push(HSLcolor);
index = colors.length - 1;
applyColor();
}
function prevColor(){ // bound with click on "back" button
index -= index > 0 ? 1 : 0;
applyColor();
}
function nextColor(){ // bound with click on "next" button
index += index < colors.length - 1 ? 1: 0;
applyColor();
}
applyColor();
Here's the updated demo: https://jsfiddle.net/dhilt/fz2dktxu/36/
You are not updating the i value in the prevColor() method. Try this:
function prevColor() {
if (randomColors.length > 0 && i > 0) {
i--;
bodyStyle.backgroundColor = randomColors[i]
console.log(randomColors, i)
}
};
PLease check the link. I have updated your code by declaring the variables.
var HSLcolor;
var back = document.querySelector("#back");
> var randomColors = [];var i =0;
https://jsfiddle.net/kobmajyx/6/
You have to start separating your presentation function from event handling, processing.
Your code should be something like https://jsfiddle.net/ryx2gn01/19/
you have 2 actions : prevColor and newColor both change the state of the aplication and trigger a change on presentation:
one internal processing function that would be the generation of your color (randomHSL)
one presentation function that sets the values where you want them (setColor)
Now you have an array of hues (randomColors), and when you press "Suprise me" it should add a new hue value to the array and set the current index (variavel i) to the last color (because you want to show the color you just pushed into the array), so i = randomColors.length - 1
Upon pressing "Previous Color" you have 2 cases, your index is already in the beginning of the list (i <= 0) or is not the first (i > 0). In the first case you don't want to change your index, but on the second case you want to decrease by one, there fore the if...then...else you see on the function prevColor. Finally after change the state you call the function responsible for displaying the results setColor(i) passing the current index.
Hope you enjoy my solution, its not perfect but hope it helps you

Can I insert multiple setTimeouts in a setInterval?

I just started learning JavaScript and right now, I'm making a virtual traffic light that lights up red, green and orange. I would like to make a loop by adding a setInterval to the outside. Is this possible or should i use some other method of making a loop. I tried making a a for(;;){} but this causes an error and the webpage never loads. Here is my current code.
var red = document.getElementById("circleRed");
var orange = document.getElementById('circleOrange')
var green = document.getElementById('circleGreens');
setInterval(
setTimeout( function(){
red.style.backgroundColor = "red";
}, 2000),
setTimeout(function(){
green.style.backgroundColor = "green";
red.style.backgroundColor = "black";
}, 5000),
setTimeout(function(){
orange.style.backgroundColor = "orange";
green.style.backgroundColor = "black";
}, 10000),
5000);
#circleRed, #circleGreens, #circleOrange {
width: 50px;
height: 50px;
-webkit-border-radius: 25px;
-moz-border-radius: 25px;
border-radius: 25px;
margin-bottom: 10px;
background-color: "black";
}
.back {
width: 60px;
margin: 10px 0px 10px 20px;
padding-left: 10px;
padding-top: 10px;
padding-bottom: 10px;
background-color: black;
}
body{
margin: 0;
}
<div class="back">
<div id="circleRed">
</div>
<div id="circleOrange">
</div>
<div id="circleGreens">
</div>
</div>
You can cal your all setTimeout function in a loop function. And call this loop function with setInterval.
Note : I also changed some of the color changing sections in your code .
jsfiddle link : https://jsfiddle.net/zgdx5xan/
var red = document.getElementById("circleRed");
var orange = document.getElementById('circleOrange')
var green = document.getElementById('circleGreens');
loop();
setInterval(loop,11000);
function loop(){
console.log("loop started")
setTimeout( function(){
red.style.backgroundColor = "red";
orange.style.backgroundColor = "black";
green.style.backgroundColor = "black";
console.log("red opened")
}, 2000);
setTimeout(function(){
green.style.backgroundColor = "green";
red.style.backgroundColor = "black";
console.log("green opened")
}, 5000);
setTimeout(function(){
orange.style.backgroundColor = "orange";
green.style.backgroundColor = "black";
red.style.backgroundColor = "black";
console.log("orange opened")
}, 10000);
}
#circleRed, #circleGreens, #circleOrange {
width: 50px;
height: 50px;
-webkit-border-radius: 25px;
-moz-border-radius: 25px;
border-radius: 25px;
margin-bottom: 10px;
background-color: "black";
}
.back{
width: 60px;
margin: 10px 0px 10px 20px;
padding-left: 10px;
padding-top: 10px;
padding-bottom: 10px;
background-color: black;
}
body{
margin: 0;
}
<div class="back">
<div id="circleRed">
</div>
<div id="circleOrange">
</div>
<div id="circleGreens">
</div>
</div>
setInterval, like setTimeout also requires a function to be passed as a first argument, in that function you would then be able to compose your setTimeout's.
var red = document.getElementById("circleRed");
var orange = document.getElementById('circleOrange');
var green = document.getElementById('circleGreens');
setInterval(function () {
red.style.backgroundColor = "black";
orange.style.backgroundColor = "black";
green.style.backgroundColor = "black";
setTimeout(function () {
red.style.backgroundColor = "red";
}, 2000);
setTimeout(function () {
green.style.backgroundColor = "green";
red.style.backgroundColor = "black";
}, 5000);
setTimeout(function () {
orange.style.backgroundColor = "orange";
green.style.backgroundColor = "black";
}, 8000);
}, 10000)
I have adjusted your timings a little as your final timeout was longer than the interval. You can see this working here: codepen example
Think to the traffic lights as an object with 3 states, redOn, greenOn and OrangeOn. You need to loop through states, so starting from redOn pass the next one in the sequence and reset in the last one. I think setInterval here is not required as it cause you to care about the total time that's irrelevant.
var red = document.getElementById("circleRed");
var orange = document.getElementById('circleOrange')
var green = document.getElementById('circleGreens');
var redFor = 200 //2000
var greenFor = 500 //5000
var orangeFor = 1000 //10000
let redOn = function(next) {
red.style.backgroundColor = "red";
orange.style.backgroundColor = "black";
setTimeout(next, redFor);
}
let orangeOn = function(next) {
orange.style.backgroundColor = "orange";
green.style.backgroundColor = "black";
setTimeout(next, orangeFor);
}
let greenOn = function(next) {
green.style.backgroundColor = "green";
red.style.backgroundColor = "black";
setTimeout(next, greenFor);
}
let start = function() {
redOn(function() {
greenOn(function() {
orangeOn(start)
})
})
}
start()
#circleRed,
#circleGreens,
#circleOrange {
width: 50px;
height: 50px;
-webkit-border-radius: 25px;
-moz-border-radius: 25px;
border-radius: 25px;
margin-bottom: 10px;
background-color: "black";
}
.back {
width: 60px;
margin: 10px 0px 10px 20px;
padding-left: 10px;
padding-top: 10px;
padding-bottom: 10px;
background-color: black;
}
body {
margin: 0;
}
<html>
<head>
<link rel="stylesheet" type="text/css" href="object2.css">
<meta charset="utf-8">
<title></title>
</head>
<body>
<div class="back">
<div id="circleRed"></div>
<div id="circleOrange"></div>
<div id="circleGreens"></div>
</div>
<script src="objects1.js"></script>
</body>
</html>
Here's an alternative implementation with equal times for every light.
var red = document.getElementById('circleRed');
var orange = document.getElementById('circleOrange');
var green = document.getElementById('circleGreens');
/* Set an array with the desired order to turn on lights */
var lights = [red, green, orange];
function open(light) {
light.classList.add('opened');
}
function close(light) {
light.classList.remove('opened');
}
function change() {
close(lights[i]);
i = (i + 1) % lights.length;
open(lights[i]);
}
/* Start */
var i = 0;
open(lights[i]);
setInterval(change, 1000);
.circle {
width: 50px;
height: 50px;
border-radius: 25px;
margin: 5px;
opacity: 0.2;
transition: opacity 200ms;
}
.circle.opened {
opacity: 1;
}
#circleRed {
background-color: red;
}
#circleOrange {
background-color: orange;
}
#circleGreens {
background-color: green;
}
.back {
width: 60px;
padding: 5px;
background-color: black;
}
<div class="back">
<div id="circleRed" class="circle"></div>
<div id="circleOrange" class="circle"></div>
<div id="circleGreens" class="circle"></div>
</div>
Explanation:
Instead of changing the background color of every circle from black to its own color to light up the circle or viceversa to switch off, in my example all circles have their respective color (red, green or orange) faded to (almost) transparent with opacity: 0.2 (originally I used 0, but I think it looks better with 0.2) See: opacity.
So, all elements with class .circle have:
.circle {
/* Other properties */
opacity: 0.2;
}
Then, I use a class called opened to turn the opacity to 1 making the circle visible.
.circle.opened {
opacity: 1;
}
Since .circle.opened has higher specificity than just .circle, opacity: 1 prevails on those elements having both classes (circle and opened).
To add or remove the class opened from a light item I use two simple functions open and close that manipulate the element's classList. This is important. In general it's more recommended to define element's properties (styles) in classes and use JS to add or remove this classes to alter the element that to modify element's styles directly with JS.
So, it's cleaner and more recommended to do:
/* CSS */
.red { background-color: red }
/* Javascript */
var element = document.getElementById('#element_ID');
element.classList.add('red');
than:
/* Javascript */
var element = document.getElementById('#element_ID');
element.style.backgroundColor = 'red';
Even though it may seem easier this second way.
To change the lights, I made an array with the elements in the desired order:
var lights = [red, green, orange];
As you can see, every element of the lights Array is one of the circles, we already stored in variables with document.getElementById() (if you're not familiar with arrays, dedicate some time to read and understand what they are and how they work. They're one of the most basic data structures in any programming language, so it's important to master them.)
To start, I initiate a global variable to 0 (var i = 0) and I light up the first light with:
open(lights[i]);
Since i equals 0, lights[i], so lights[0] is red (In JS, as in most languages, arrays start counting their elements from 0). This way, open(lights[i]) is the same as open(red).
Then I do a setInterval(change, 1000) so every second the function change() is called. And what does this change function do?
Basically:
// Turn off the current light
close(lights[i]);
// Increment i, so that lights[i] points to the next element...
i = (i + 1) % lights.length;
// Turn on this next element
open(lights[i]);
The rarest thing here may be the increment. Why do I do i = (i + 1) % lights.length instead of just i++.
If I do i++ after successive calls to change, i will be: 0, 1, 2, 3, 4, 5, 6... so, when I try to access lights[i] I'll get an error, because there is no element in positions 3, 4, 5... of the lights array.
I need my sequence to be: 0, 1, 2, 0, 1, 2, 0, 1, 2...
How do I get this desired sequence instead of 0, 1, 2, 3, 4, 5, 6... ?
Maybe a more understandable way could be:
i++;
if (i > 2) {
i = 0;
}
But I'm using the Remainder operator (%) to achieve the same effect.
I hope this helps!
And another one with easily configurable duration for every light:
var lights = {
red: {
node: document.getElementById('circleRed'),
duration: 4000,
},
green: {
node: document.getElementById('circleGreens'),
duration: 2000,
},
orange: {
node: document.getElementById('circleOrange'),
duration: 800,
}
};
var order = ['red', 'green', 'orange'];
function open(light) {
light.node.classList.add('opened');
}
function close(light) {
light.node.classList.remove('opened');
}
function change() {
close(lights[order[i]]);
i = (i + 1) % order.length;
open(lights[order[i]]);
setTimeout(change, lights[order[i]].duration);
}
/* Start */
var i = 0;
open(lights[order[i]]);
setTimeout(change, lights[order[i]].duration);
.circle {
width: 50px;
height: 50px;
border-radius: 25px;
margin: 5px;
opacity: 0;
transition: opacity 200ms;
}
.circle.opened {
opacity: 1;
}
#circleRed {
background-color: red;
}
#circleOrange {
background-color: orange;
}
#circleGreens {
background-color: green;
}
.back {
width: 60px;
padding: 5px;
background-color: black;
}
<div class="back">
<div id="circleRed" class="circle"></div>
<div id="circleOrange" class="circle"></div>
<div id="circleGreens" class="circle"></div>
</div>
put all setTimeout( function(){}) in one function, then it will work
Note: to make setInterval work properly, the milliseconds must be at least the total of setTimeout functions.
also you forgot to set the orange to black when the red is appearing.
var red = document.getElementById("circleRed");
var orange = document.getElementById('circleOrange')
var green = document.getElementById('circleGreens');
setInterval(function(){ myTimer() }, 17000);
function myTimer() {
setTimeout( function(){
red.style.backgroundColor = "red";
orange.style.backgroundColor = "black";
}, 2000),
setTimeout(function(){
green.style.backgroundColor = "green";
red.style.backgroundColor = "black";
}, 5000),
setTimeout(function(){
orange.style.backgroundColor = "orange";
green.style.backgroundColor = "black";
}, 10000)
}
myTimer();
#circleRed, #circleGreens, #circleOrange {
width: 50px;
height: 50px;
-webkit-border-radius: 25px;
-moz-border-radius: 25px;
border-radius: 25px;
margin-bottom: 10px;
background-color: "black";
}
.back {
width: 60px;
margin: 10px 0px 10px 20px;
padding-left: 10px;
padding-top: 10px;
padding-bottom: 10px;
background-color: black;
}
body{
margin: 0;
}
<div class="back">
<div id="circleRed">
</div>
<div id="circleOrange">
</div>
<div id="circleGreens">
</div>
</div>

Resetting timer and score values to 0 before a new game starts

Im new to this but I've been having some trouble with trying to get my timer and score values back to 0 before a new game of memory starts. The values do reset, but don't show it until that value is affected. For example, the value for the number of matches never goes back to 0, it stays on 10(the max number of pairs) until you find the first match of the next game where it will then turn to 1. Does anybody know how to get the values to show 0 again when a new board is called up instead of just resetting when that value is affected?
I have already set
var turns = 0
var matches = 0
and called in them up as 0 in the function newBoard().
My timer code is:
var c = 0;
var t;
var timer_is_on = 0;
function timedCount() {
document.getElementById('txt').value = c;
c = c+1;
t = setTimeout(timedCount, 1000);
}
function startTimer() {
if (!timer_is_on) {
timer_is_on = 1;
timedCount();
}
}
function stopCount() {
clearTimeout(t);
timer_is_on = 0;
}
function resetTime(){
clearTimeout(t);
timer_is_on = 0;
c = 0
Where I have called up the resetTime() function in the function newBoard().
My full code is:
body{
background:#FFF;
font-family: Cooper Black;
}
h1{
font-family: Cooper Black;
text-align: center;
font-size: 64px;
color: #FF0066;
}
footer{
height: 150px;
background: -webkit-linear-gradient(#99CCFF, #FFF); /* For Safari 5.1 to 6.0 */
background: -o-linear-gradient(#99CCFF, #FFF); /* For Opera 11.1 to 12.0 */
background: -moz-linear-gradient(#99CCFF, #FFF); /* For Firefox 3.6 to 15 */
background: linear-gradient(#99CCFF, #FFF); /* Standard syntax (must be last) */
}
div#memory_board{
background: -webkit-radial-gradient(#FFF, #CC99FF); /* For Safari 5.1 to 6.0 */
background: -o-radial-gradient(#FFF, #CC99FF); /* For Opera 11.1 to 12.0 */
background: -moz-radial-gradient(#FFF, #CC99FF); /* For Firefox 3.6 to 15 */
background: radial-gradient(#FFF, #CC99FF); /* Standard syntax (must be last) */
border:#FF0066 10px ridge;
width:510px;
height:405px;
padding:24px;
}
div#memory_board > div{
background:url(tile_background.png) no-repeat;
border:#000 1px solid;
width:45px;
height:45px;
float:left;
margin:7px;
padding:20px;
cursor:pointer;
}
alert{
background: #FF0066;
}
button{
font-family: Cooper Black;
font-size: 20px;
color: #FF0066;
background: #5CE62E;
border: #C2E0FF 2px outset;
border-radius: 25px;
padding: 10px;
cursor: pointer;
}
input#txt{
background: yellow;
color: #FF0066;
font-family: Times New Roman;
font-size: 84px;
height: 150px;
width: 150px;
border-radius: 100%;
text-align: center;
border: none;
}
input#pause{
font-family: Cooper Black;
font-size: 18px;
color: #FF0066;
background: #C2E0FF;
border: #C2E0FF 2px outset;
border-radius: 25px;
padding: 10px;
cursor: pointer;
margin-top: 10px;
}
div.goes{
text-align: center;
border: #C2E0FF 5px double;
height: 160px;
width: 120px;
margin-top: 48px;
margin-left: 5px;
}
div.matches{
text-align: center;
border: #C2E0FF 5px double;
height: 160px;
width: 120px;
margin-top: 30px;
margin-left: 10px;
}
p{
font-size: 28px;
}
span{
font-family: Times New Roman;
font-size: 84px;
}
.sprite {
width:96px;
height:96px;
position: relative;
margin:15px;
}
.toon{
background: url(explode.png);
}
}
#dialogoverlay{
display: none;
opacity: 0.8;
position: fixed;
top: 0px;
left: 0px;
background: #FFF;
width: 100%;
z-index: 10;
}
#dialogbox{
display: none;
position: fixed;
background: #FF0066;
border-radius:7px;
width:400px;
z-index: 10;
}
#dialogbox > div{ background: #FFF; margin:8px; }
#dialogbox > div > #dialogboxhead{ background: linear-gradient(#99CCFF, #FFF); height: 40px; color: #CCC; }
#dialogbox > div > #dialogboxbody{ background: #FFF; color: #FF0066; font-size: 36px; text-align:center;}
#dialogbox > div > #dialogboxfoot{ background: linear-gradient(#FFF, #99CCFF); padding-bottom: 20px; text-align:center; }
<!DOCTYPE html>
<html>
<head>
<title>Memory Card Game</title>
<meta http-equiv="Content-type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="reset.css" />
<link rel="stylesheet" type="text/css" href="text.css" />
<link rel="stylesheet" type="text/css" href="960.css" />
<link rel="stylesheet" type="text/css" href="mystyles.css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type='text/javascript' src='jquery.animateSprite.js'></script>
<script>
var memory_array = ['A','A','B','B','C','C','D','D','E','E','F','F','G','G','H','H','I','I','J','J'];
var memory_values = [];
var memory_tile_ids = [];
var tiles_flipped = 0;
var turns = 0
var matches = 0
Array.prototype.memory_tile_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;
}
}
function newBoard(){
tiles_flipped = 0;
var output = '';
memory_array.memory_tile_shuffle();
for(var i = 0; i < memory_array.length; i++){
output += '<div id="tile_'+i+'" onclick="memoryFlipTile(this,\''+memory_array[i]+'\')"></div>';
}
document.getElementById('memory_board').innerHTML = output;
//fade in
$(document).ready(function () {
$('#memory_board > div').hide().fadeIn(1500).delay(6000)
});
resetTime();
turns = 0;
matches = 0;
}
function memoryFlipTile(tile,val){
startTimer();
playClick();
if(tile.innerHTML == "" && memory_values.length < 2){
tile.style.background = '#FFF';
tile.innerHTML = '<img src="' + val + '.png"/>';
if(memory_values.length == 0){
memory_values.push(val);
memory_tile_ids.push(tile.id);
} else if(memory_values.length == 1){
memory_values.push(val);
memory_tile_ids.push(tile.id);
if(memory_values[0] == memory_values[1]){
tiles_flipped += 2;
//sound
playMatch();
//animation
//number of clicks
turns = turns + 1;
document.getElementById("Count").innerHTML = turns;
//number of matches
matches = matches + 1;
document.getElementById("matchNumber").innerHTML = matches;
// Clear both arrays
memory_values = [];
memory_tile_ids = [];
// Check to see if the whole board is cleared
if(tiles_flipped == memory_array.length){
playEnd();
Alert.render("Congratulations! Board Cleared");
//resetTime()
//stopCount();
document.getElementById('memory_board').innerHTML = "";
newBoard();
}
} else {
function flipBack(){
// Flip the 2 tiles back over
var tile_1 = document.getElementById(memory_tile_ids[0]);
var tile_2 = document.getElementById(memory_tile_ids[1]);
tile_1.style.background = 'url(tile_background.png) no-repeat';
tile_1.innerHTML = "";
tile_2.style.background = 'url(tile_background.png) no-repeat';
tile_2.innerHTML = "";
//number of clicks
turns = turns + 1;
document.getElementById("Count").innerHTML = turns;
//clickNumber()
// Clear both arrays
memory_values = [];
memory_tile_ids = [];
}
setTimeout(flipBack, 700);
}
}
}
}
//timer
var c = 0;
var t;
var timer_is_on = 0;
function timedCount() {
document.getElementById('txt').value = c;
c = c+1;
t = setTimeout(timedCount, 1000);
}
function startTimer() {
if (!timer_is_on) {
timer_is_on = 1;
timedCount();
}
}
function stopCount() {
clearTimeout(t);
timer_is_on = 0;
}
function resetTime(){
clearTimeout(t);
timer_is_on = 0;
c = 0
}
//sound effects /*sounds from http://www.freesfx.co.uk*/
function playClick(){
var sound=document.getElementById("click");
sound.play();
}
function playMatch(){
var sound=document.getElementById("match_sound");
sound.play();
}
function playEnd(){
var sound=document.getElementById("finished");
sound.play();
}
//custom alert
function CustomAlert(){
this.render = function(dialog){
var winW = window.innerWidth;
var winH = window.innerHeight;
var dialogoverlay = document.getElementById('dialogoverlay');
var dialogbox = document.getElementById('dialogbox');
dialogoverlay.style.display = "block";
dialogoverlay.style.height = winH+"px";
dialogbox.style.left = (winW/2) - (400 * .5)+"px";
dialogbox.style.top = "200px";
dialogbox.style.display = "block";
document.getElementById('dialogboxhead').innerHTML = "";
document.getElementById('dialogboxbody').innerHTML = dialog;
document.getElementById('dialogboxfoot').innerHTML = '<button onclick="Alert.ok()">New Game</button>';
}
this.ok = function(){
document.getElementById('dialogbox').style.display = "none";
document.getElementById('dialogoverlay').style.display = "none";
}
}
var Alert = new CustomAlert();
</script>
<script>//sparkle effect: http://www.rigzsoft.co.uk/how-to-implement-animated-sprite-sheets-on-a-web-page/
$(document).ready(function(){
$("#memory_board").click(function animation(){
$(".toon").animateSprite({
columns: 10,
totalFrames: 50,
duration: 1000,
});
});
});
</script>
</head>
<body>
<audio id = "click" src = "click.mp3" preload = "auto"></audio>
<audio id = "match_sound" src = "match.mp3" preload = "auto"></audio>
<audio id = "finished" src = "finished.wav" preload = "auto"></audio>
<div id = "dialogoverlay"></div>
<div id = "dialogbox">
<div>
<div id = "dialogboxhead"></div>
<div id = "dialogboxbody"></div>
<div id = "dialogboxfoot"></div>
</div>
</div>
<div class = "container_16">
<div id = "banner" class = "grid_16">
<p><br></p>
<h1>Memory</h1>
</div>
<div class = "grid_3">
<input type="text" id="txt" value="0"/>
<p><br></p>
<p><br></p>
<div class = "goes">
<p>Turns <br><span id = "Count">0</span></p>
</div>
</div>
<div class = "grid_10">
<div id="memory_board"></div>
<script>newBoard();</script>
<div style="position: relative; height: 110px;">
<div class="sprite toon"></div>
</div>
</div>
<div class = "grid_3">
<button id = "new_game" onclick="newBoard()">New Game</button>
<input type="button" id="pause" value="Pause Game" onclick="stopCount()">
<p><br></p>
<p><br></p>
<p><br></p>
<div class = "matches">
<p>Matches <br><span id = "matchNumber">0</span></p>
</div>
</div>
</div>
<footer> </footer>
</body>
</html>
Both of the variables you are settings are displayed in HTML span objects.
What seems to be happening is that when you reset the Javascript variable, the value is being changed, but the span object where it is displayed to the user is being left at its previous value until it needs to be updated again.
As far as I can tell, your objects have the ids: matchNumber and Count for the match and turn variables respectively. If this is the case, try changing your code to reset the values to zero in the HTML when the variables are reset to zero.
For example:
// Reset the Javascript Count
var turns = 0
// Reset the HTML object
document.getElementById('Count').innerHTML = 0;
// Reset the Javascript Match Count
var matches = 0
// Reset the HTML object
document.getElementById('matchNumber').innerHTML = 0;
If I failed to explain this well, please comment and I'll try to clarify further.
I am not 100% sure, but you can try replacing your function with this one:
function timedCount() {
if(c>10){
//flipBack();
resetTime();
return;
}
document.getElementById('txt').value = c;
c = c+1;
t = setTimeout(timedCount, 1000);
}

Categories

Resources