I have written the code below which should do a traffic light sequence but the setInterval and setTimeout do not seem to be working as I expected them to.
What I want to do is do a set repeating time for each function that changes the colour of the light.
setInterval(function multipleFunction() {
setInterval(trafficOne, 1000);
setTimeout(setInterval(trafficTwo, 1000), 1000);
setTimeout(setInterval(trafficThree, 1000), 2000);
setTimeout(setInterval(trafficFour, 1000), 3000);
}, 4000)
function trafficOne() {
document.getElementById('circle1').style.backgroundColor = 'red'
document.getElementById('circle2').style.backgroundColor = 'yellow'
}
function trafficTwo() {
document.getElementById('circle1').style.backgroundColor = 'black'
document.getElementById('circle2').style.backgroundColor = 'black'
document.getElementById('circle3').style.backgroundColor = 'green'
}
function trafficThree() {
document.getElementById('circle1').style.backgroundColor = 'black'
document.getElementById('circle2').style.backgroundColor = 'yellow'
document.getElementById('circle3').style.backgroundColor = 'black'
}
function trafficFour() {
document.getElementById('circle1').style.backgroundColor = 'red'
document.getElementById('circle2').style.backgroundColor = 'black'
document.getElementById('circle3').style.backgroundColor = 'black'
}
#container {
width: 80px;
height: 230px;
border-style: solid;
padding: 10px;
margin: 10px;
border-width: 1px;
border-color: black;
}
#container2 {
width: 60px;
height: 180px;
border-style: solid;
background: black;
margin: 10px;
border-width: 1px;
border-color: black;
}
#circle1 {
width: 50px;
height: 50px;
border-radius: 25px;
background: red;
margin: 5px;
}
#circle2 {
width: 50px;
height: 50px;
margin: 5px;
border-radius: 25px;
background: black;
}
#circle3 {
width: 50px;
height: 50px;
margin: 5px;
border-radius: 25px;
background: black;
}
<div id="container">
<button id="change" onClick="multipleFunction()">Start traffic</button>
<div id="container2">
<div id="circle1"></div>
<div id="circle2"></div>
<div id="circle3"></div>
</div>
</div>
You don't define you functions well.
Try this one and try to unserdstand whats going on. If you need help just ask :)
EDIT: Add some comments, hope it helps
<!DOCTYPE html>
<html>
<head>
<style>
#container{
width:80px;
height:230px;
border-style:solid;
padding:10px;
margin:10px;
border-width: 1px;
border-color:black;
}
#container2{
width:60px;
height:180px;
border-style: solid ;
background:black;
margin:10px;
border-width: 1px;
border-color: black;
}
#circle1 {
width: 50px;
height: 50px;
border-radius: 25px;
background: red;
margin:5px;
}
#circle2 {
width: 50px;
height: 50px;
margin:5px;
border-radius: 25px;
background: black;
}
#circle3 {
width: 50px;
height: 50px;
margin:5px;
border-radius: 25px;
background: black;
}
</style>
<script>
// init state of timer, no timer set
var timer = null;
// function to start and stop the traffic light
function toggle(){
// test if a timer is set and running
if(timer != null){
// the timer is running --> stop that timer
clearInterval(timer);
// reset the timer
timer = null;
// set the traffic light to an inital state
document.getElementById('circle1').style.backgroundColor='red';
document.getElementById('circle2').style.backgroundColor='black';
document.getElementById('circle3').style.backgroundColor='black';
}else{
// no timer is running --> start the first step
trafficOne();
}
}
function trafficOne() {
// set the light of this state
document.getElementById('circle1').style.backgroundColor='red';
document.getElementById('circle2').style.backgroundColor='yellow';
document.getElementById('circle3').style.backgroundColor='black';
// set a timeout of 1s, if it is over start the next function
timer = window.setTimeout(trafficTwo, 1000);
}
function trafficTwo() {
// set the light of this state
document.getElementById('circle1').style.backgroundColor='black'
document.getElementById('circle2').style.backgroundColor='black'
document.getElementById('circle3').style.backgroundColor='green'
// set a timeout of 1s, if it is over start the next function
timer = window.setTimeout(trafficThree, 1000);
}
function trafficThree() {
// set the light of this state
document.getElementById('circle1').style.backgroundColor='black'
document.getElementById('circle2').style.backgroundColor='yellow'
document.getElementById('circle3').style.backgroundColor='black'
// set a timeout of 1s, if it is over start the next function
timer = window.setTimeout(trafficFour, 1000);
}
function trafficFour() {
// set the light of this state
document.getElementById('circle1').style.backgroundColor='red'
document.getElementById('circle2').style.backgroundColor='black'
document.getElementById('circle3').style.backgroundColor='black'
// set a timeout of 1s, if it is over start the next function
timer = window.setTimeout(trafficOne, 1000);
}
</script>
</head>
<body>
<div id="container">
<button id ="change" onClick="toggle()" >Start traffic</button>
<div id="container2">
<div id="circle1"></div>
<div id="circle2"></div>
<div id="circle3"></div>
</div>
</div>
</body>
</html>
I rewrote your script, should help you hopefully:
<div id="container">
<button id="change">Start traffic</button>
<div id="container2">
<div id="circle1"></div>
<div id="circle2"></div>
<div id="circle3"></div>
</div>
</div>
...
var currentState = 0;
var trafficLights;
var setBgColor = function(id, color){
document.getElementById(id).style.backgroundColor = color;
};
function setTrafficLights(){
switch(currentState){
case 0:
setBgColor('circle1', 'red');
setBgColor('circle2', 'yellow');
break;
case 1:
setBgColor('circle1', 'black');
setBgColor('circle2', 'black');
setBgColor('circle3', 'green');
break;
case 2:
setBgColor('circle1', 'black');
setBgColor('circle2', 'yellow');
setBgColor('circle3', 'black');
break;
case 3:
setBgColor('circle1', 'red');
setBgColor('circle2', 'black');
setBgColor('circle3', 'black');
break;
}
currentState = (currentState + 1) % 4;
}
document.getElementById('change').addEventListener("click", function(){
clearInterval(trafficLights);
trafficLights = setInterval(setTrafficLights, 1000);
});
Related
I have 10 links and each of them is different from the others.I want when user hovers on them background image of the div changes and a tooltip text be shown on top of the links with a fade-in animation .
i have tried to make several functions using JS and it works but it's a lot of code and mostly repetitive.I want a good shortcut through all of that useless coding.
document.getElementById("d1").onmouseover = function() {
mouseOver1()
};
document.getElementById("d2").onmouseover = function() {
mouseOver2()
};
document.getElementById("d3").onmouseover = function() {
mouseOver3()
};
document.getElementById("d1").onmouseout = function() {
mouseOut1()
};
document.getElementById("d2").onmouseout = function() {
mouseOut2()
};
document.getElementById("d3").onmouseout = function() {
mouseOut3()
};
function mouseOver1() {
document.getElementById("dogs").style.background = "blue";
document.getElementById("tooltiptext1").style.visibility = "visible";
}
function mouseOut1() {
document.getElementById("dogs").style.background = "black";
document.getElementById("tooltiptext1").style.visibility = "hidden";
}
function mouseOver2() {
document.getElementById("dogs").style.background = "green";
document.getElementById("tooltiptext2").style.visibility = "visible";
}
function mouseOut2() {
document.getElementById("dogs").style.background = "black";
document.getElementById("tooltiptext2").style.visibility = "hidden";
}
function mouseOver3() {
document.getElementById("dogs").style.background = "red";
document.getElementById("tooltiptext3").style.visibility = "visible";
}
function mouseOut3() {
document.getElementById("dogs").style.background = "black";
document.getElementById("tooltiptext3").style.visibility = "hidden";
}
#dogs {
float: right;
margin-top: 5%;
background: black;
width: 150px;
height: 150px;
}
#d-list {
color: white;
direction: ltr;
float: right;
width: 60%;
height: 60%;
}
#tooltiptext1,
#tooltiptext2,
#tooltiptext3 {
color: black;
background-color: gray;
width: 120px;
height: 30px;
border-radius: 6px;
text-align: center;
padding-top: 5px;
visibility: hidden;
}
<div id="animals">
<div id="dogs"></div>
<div id="d-list">
<pre style="font-size:22px; color:darkorange">dogs</pre><br />
<pre>white Husky</pre>
<p id="tooltiptext1">Tooltip text1</p>
<pre>black Bull</pre>
<p id="tooltiptext2">Tooltip text2</p>
<pre>brown Rex</pre>
<p id="tooltiptext3">Tooltip text3</p>
</div>
</div>
Please have in mind that all of links will change same outer div object and the idea is to change the background image of that div and the tooltip shoud appear on the top of the links....so,
any ideas?
edit: added animation requested.
CSS is almost always better done in script by using classes when multiple elements are being manipulated with similar functions so I used that here. Rather than put some complex set of logic in place I simply added data attributes for the colors - now it works for any new elements you wish to add as well.
I did find your markup to be somewhat strangely chosen and would have done it differently but that was not part of the question as stated.
I took the liberty of removing the style attribute from your dogs element and put it in the CSS also as it seemed to belong there and mixing markup and css will probably make it harder to maintain over time and puts all the style in one place.
Since you DID tag this with jQuery here is an example of that.
$(function() {
$('#d-list').on('mouseenter', 'a', function(event) {
$('#dogs').css('backgroundColor', $(this).data('colorin'));
$(this).parent().next('.tooltip').animate({
opacity: 1
});
}).on('mouseleave', 'a', function(event) {
$('#dogs').css('backgroundColor', $(this).data('colorout'));
$(this).parent().next('.tooltip').animate({
opacity: 0
});
});
});
#dogs {
float: right;
margin-top: 5%;
background: black;
width: 150px;
height: 150px;
}
#d-list {
color: white;
direction: ltr;
float: right;
width: 60%;
height: 60%;
}
.dog-header {
font-size: 22px;
color: darkorange;
margin-bottom: 2em;
}
.tooltip {
color: black;
background-color: gray;
width: 120px;
height: 30px;
border-radius: 6px;
text-align: center;
padding-top: 5px;
opacity: 0;
position:relative;
top:-4.5em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div id="animals">
<div id="dogs"></div>
<div id="d-list">
<pre class="dog-header">dogs</pre>
<pre>white Husky</pre>
<p id="tooltiptext1" class="tooltip">Tooltip text1</p>
<pre>black Bull</pre>
<p id="tooltiptext2" class="tooltip">Tooltip text2</p>
<pre>brown Rex</pre>
<p id="tooltiptext3" class="tooltip">Tooltip text3</p>
</div>
</div>
Updated
This answer was written before the question was edited to show the intended markup/styling and before all the details were included. The code has been updated to work with that structure.
I think the simplest thing is just to create a configuration object to detail the varying bits, and then use common code for the rest. Here's one approach:
const configs = [
['d1', 'tooltiptext1', 'blue'],
['d2', 'tooltiptext2', 'green'],
['d3', 'tooltiptext3', 'red'],
];
configs.forEach(([id, tt, color]) => {
const dogs = document.getElementById('dogs');
const el = document.getElementById(id);
const tip = document.getElementById(tt);
el.onmouseover = (evt) => {
dogs.style.background = color
tip.style.visibility = "visible";
}
el.onmouseout = (evt) => {
dogs.style.background = "black";
tip.style.visibility = "hidden";
}
})
#dogs{float:right;margin-top:5%;background:#000;width:150px;height:150px}#d-list{color:#fff;direction:ltr;float:right;width:60%;height:60%}#tooltiptext1,#tooltiptext2,#tooltiptext3{color:#000;background-color:gray;width:120px;height:30px;border-radius:6px;text-align:center;padding-top:5px;visibility:hidden}
<div id="animals"> <div id="dogs"></div><div id="d-list"> <pre style="font-size:22px; color:darkorange">dogs</pre><br/> <pre>white Husky</pre> <p id="tooltiptext1">Tooltip text1</p><pre>black Bull</pre> <p id="tooltiptext2">Tooltip text2</p><pre>brown Rex</pre> <p id="tooltiptext3">Tooltip text3</p></div></div>
Obviously you can extend this with new rows really easily. And if you want to add more varying properties, you can simply make the rows longer. If you need to add too many properties to each list, an array might become hard to read, and it might become better to switch to {id: 'demo', tt: 'dem', color: 'blue'} with the corresponding change to the parameters in the forEach callback. (That is, replacing configs.forEach(([id, tt, color]) => { with configs.forEach(({id, tt, color}) => {.) But with only three parameters, a short array seems cleaner.
Older code snippet based on my made-up markup.
const configs = [
['demo', 'dem', 'blue'],
['dd', 'dem1', 'green']
];
configs.forEach(([id1, id2, color]) => {
const a = document.getElementById(id1)
const b = document.getElementById(id2)
a.onmouseover = (evt) => {
a.style.background = color
b.style.visibility = "visible";
}
a.onmouseout = (evt) => {
a.style.background = "black";
b.style.visibility = "hidden";
}
})
div {width: 50px; height: 50px; float: left; margin: 10px; background: black; border: 1px solid #666; color: red; padding: 10px; text-align: center}
#dem , #dem1{visibility:hidden;}
<div id="demo">demo</div>
<div id="dem">dem</div>
<div id="dd">dd</div>
<div id="dem1">dem1</div>
my way of seeing that => zero Javascript:
div[data-info] {
display: inline-block;
margin:80px 20px 0 0;
border:1px solid red;
padding: 10px 20px;
position: relative;
}
div[data-bg=blue]:hover {
background-color: blue;
color: red;
}
div[data-bg=green]:hover {
background-color: green;
color: red;
}
div[data-info]:hover:after {
background: #333;
background: rgba(0, 0, 0, .8);
border-radius: 5px;
bottom: 46px;
color: #fff;
content: attr(data-info);
left: 20%;
padding: 5px 15px;
position: absolute;
z-index: 98;
min-width: 120px;
max-width: 220px;
}
div[data-info]:hover:before {
border: solid;
border-color: #333 transparent;
border-width: 6px 6px 0px 6px;
bottom: 40px;
content: "";
left: 50%;
position: absolute;
z-index: 99;
}
<div data-info="Tooltip for A Tooltip for A" data-bg="blue">with Tooltip CSS3 A</div>
<div data-info="Tooltip for B" data-bg="green" >with Tooltip CSS3 B</div>
I want to do a simple timer who can run from 25 to 0 and reset whenever we want to.
For this I've made a clickable div, and I want one click to start the timer and another one to reset it to 25 and stop the timer, is this possible ?
A toggable start/reset timer?
This is what I came up with so far :
HTML
<div id="result" onclick="playReset"><p id="output"></p> </div>
CSS
#result {
background: pink;
height: 200px;
width: 200px;
border-radius: 50%;
margin-left: 400px;
margin-top: 200px;
}
#result:hover {
border: black solid;
}
#output{
margin-left: 70px;
position: fixed;
font-size: 60px;
}
And the most important the JS :
var duree=25;
var toggle = true;
function playReset () {
if(toggle == true) {
var time = setInterval(function(){
duree--;
document.getElementById('output').innerHTML = duree;
}, 1000);
toggle = false
}
else if (toggle == false) {
clearInterval(time);
duree = 25;
toggle = true;
}
}
document.getElementById('output').innerHTML = duree;
Thank's if someone can give me a hand, I have SO MUCH trouble understanding setInterval/timeout, clearInterval/timeout ...
I simplified that code a little, where you can use the actual time variable to check whether it is running or not.
Stack snippet
var duree = 2;
var time;
function playReset() {
if (time) {
clearInterval(time);
time = null;
duree = 25;
document.getElementById('output').innerHTML = duree;
} else {
time = setInterval(function() {
duree--;
document.getElementById('output').innerHTML = duree;
if (duree == 0) {
clearInterval(time);
}
}, 1000);
}
}
document.getElementById('output').innerHTML = duree;
#result {
background: pink;
height: 200px;
width: 200px;
border-radius: 50%;
margin-left: 40px;
margin-top: 20px;
border: transparent solid;
}
#result:hover {
border: black solid;
}
#output {
margin-left: 70px;
position: fixed;
font-size: 60px;
}
<div id="result" onclick="playReset();">
<p id="output"></p>
</div>
When you later on have increased your skills, you likely want these stuff and their variable hidden from the global environment.
With closure one can do something like this, where only the function name is public.
Stack snippet
(function (output,duree,time) { //declared as static variables
this.init_time = duree;
this.playReset = function() {
if (time) {
clearInterval(time);
time = null;
output.innerHTML = duree = init_time; // set init value
} else {
time = setInterval(function() {
output.innerHTML = --duree;
if (duree == 0) {
clearInterval(time);
}
}, 1000);
}
}
window.playReset = this.playReset; //make it public
output.innerHTML = duree; // set init value
})(document.getElementById('output'),25); // pass in the output element and default time
#result {
background: pink;
height: 200px;
width: 200px;
border-radius: 50%;
margin-left: 40px;
margin-top: 20px;
border: transparent solid;
}
#result:hover {
border: black solid;
}
#output {
margin-left: 70px;
position: fixed;
font-size: 60px;
}
<div id="result" onclick="playReset();">
<p id="output"></p>
</div>
Here is same solution, but with the event listener and I check the count to know if a reset is to be done. You can try this here:
https://jsfiddle.net/0bej5tyn/
html
<div id="timer">
25
</div>
css
#timer{
width:150px;
height:100px;
line-height:100px;
border-radius:100px;
border:5px solid #444;
background:#555;
font-size:50px;
text-align:center;
color:#fff;
font-family:arial;
}
#timer:hover{
border:5px solid #333;
}
js
var timerButton = document.getElementById("timer");
var countStart = timerButton.innerHTML
var count = countStart;
var timer;
timerButton.addEventListener('click',function(){
if (count == countStart){
timer = setInterval(function(){
count--;
timerButton.innerHTML = count;
if (count == 0){
clearInterval(timer);
}
},1000);
}
else{
/* Reset here */
clearInterval(timer);
count = countStart;
timerButton.innerHTML = count;
}
});
I tried to write a program to practice my js skills. There are 3 balls and they are hidden at first. I want the ball_1 shows up first, and after 1 sec, ball_1 disappears. Next, ball_2 shows up and after 1 sec it disappears; same logic goes with ball_3. When I run my code, the first two balls does not hide. I am not sure what is going wrong. The code below are the html, css, and js code that i wrote. Hope someone could help me out. Thank you in advance.
$(document).ready(function() {
var notes = ['ball_1', 'ball_2', 'ball_3'];
for (i = notes.length; i > 0; i--) {
var note = notes.shift();
$('#' + note).addClass('shown');
setTimeout(function() {
$('#' + note).removeClass('shown');
}, 1000);
}
});
#ball_1 {
width: 10px;
height: 10px;
background: #000000;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_2 {
width: 10px;
height: 10px;
background: #0000FF;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_3 {
width: 10px;
height: 10px;
background: #7FFF00;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_1,
#ball_2,
#ball_3 {
width: 10px;
height: 10px;
border: 2px solid #ccc;
border-radius: 50%;
}
.not_shown {
display: none;
}
.shown {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div id="ball">
<div id="ball_1" class="not_shown"></div>
<div id="ball_2" class="not_shown"></div>
<div id="ball_3" class="not_shown"></div>
</div>
In general never modify an array when iterating using a for loop. The shift method will remove the first item from the array thus modifying it's length. Instead do this:
$(document).ready(function() {
var notes = ['ball_1','ball_2','ball_3'];
var i; // You were declaring "i" in global namespace before. Don't do that.
for(i = 0; i < notes.length; i++){
var note = notes[i];
$('#' + note).addClass('shown');
setTimeout(function() {
$('#' + note).removeClass('shown');
},1000);
}
});
Also you will see from my note that you were defining "i" in the global namespace. It is never good to do that so always make sure to define your variables at the beginning of the function block if using "var".
EDIT: missed a semicolon
EDIT2: completely missed that i needed to change up the loop condition.
You are looking for an asnychronous play of events - first ball_1 shows up for 1 sec and after that ball_2 shows up for 1 sec and so forth.
Something like this won't work:
for( var i = 0; i < notes.length; i++){
$('#' + notes[i]).addClass('shown');
setTimeout(function() {
$('#' + notes[i]).removeClass('shown');
},1000);
}
because the timeouts will be registered one after the other in quick succession and all the balls will show up and hide in little over one second.
So you can create a callback and set the timeout for the next ball only after the previous ball has been shown fully for 1 sec - see demo below:
$(document).ready(function() {
var notes = ['ball_1', 'ball_2', 'ball_3'];
hideBall(notes,0);
});
function hideBall(notes,i) {
$('#' + notes[i]).addClass('shown');
hide(function() {
if(++i < notes.length) {
hideBall(notes,i);
}
}, notes[i]);
}
function hide(callback, note) {
setTimeout(function() {
$('#' + note).removeClass('shown');
callback();
}, 1000);
}
#ball_1 {
width: 10px;
height: 10px;
background: #000000;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_2 {
width: 10px;
height: 10px;
background: #0000FF;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_3 {
width: 10px;
height: 10px;
background: #7FFF00;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_1,
#ball_2,
#ball_3 {
width: 10px;
height: 10px;
border: 2px solid #ccc;
border-radius: 50%;
}
.not_shown {
display: none;
}
.shown {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div id="ball">
<div id="ball_1" class="not_shown"></div>
<div id="ball_2" class="not_shown"></div>
<div id="ball_3" class="not_shown"></div>
</div>
Hope this is what you need
$(document).ready(function() {
var notes = ['ball_1','ball_2','ball_3'];
for(i = notes.length; i > 0; i--){
var note = notes[i];
$('#' + note).addClass('shown');
hideBall(note, i)
}
});
function hideBall(note) {
setTimeout(function() {
$('#' + note).removeClass('shown');
},1000 * i);
}
#ball_1{
width: 10px;
height: 10px;
background: #000000;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_2{
width: 10px;
height: 10px;
background: #0000FF;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_3{
width: 10px;
height: 10px;
background: #7FFF00;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_1, #ball_2, #ball_3 {
width: 10px;
height: 10px;
border: 2px solid #ccc;
border-radius: 50%;
}
.not_shown {
display: none;
}
.shown {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id = "ball">
<div id = "ball_1" class = "not_shown"></div>
<div id = "ball_2" class = "not_shown"></div>
<div id = "ball_3" class = "not_shown"></div>
</div>
What you are trying won't work as it will run the for loop all in one go, setting up 3x timeouts.
try something like this
jQuery(document).ready(function($) {
function myBallLoop(){
// increment as needed
if(typeof note == 'undefined') {
var note = 1;
} else if (note == 3){
break; // end loop
} else {
note ++;
}
// show current ball qickly
$('#ball_' + note).show('fast', function(){
// call back after show event
// hide current ball after 1 sec
r = setTimeout(function(){$('#ball_' + note).hide()}, 1000);
// self call function after 2 seconts
t = setTimeout(function(){myBallLoop();, 2000}
});
}
// loop start
myBallLoop();
});
Take advantage of what jquery gives you.
Iterate using $.each is also the same as ES5's forEach. Using delay method to delay a function of adding classes is similar to setTimeout.
$(document).ready(() => {
var notes = ['ball_1','ball_2','ball_3'];
let showBalls = (i, item) => {
$('#' + item).delay(i * 1000).queue(() => {
$('#' + item).addClass('shown');
$('#' + notes[i - 1]).removeClass('shown').clearQueue();
});
}
$.each(notes, (i, item) => {
showBalls(i, item);
});
});
#ball_1{
width: 10px;
height: 10px;
background: #000000;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_2{
width: 10px;
height: 10px;
background: #0000FF;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_3{
width: 10px;
height: 10px;
background: #7FFF00;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_1, #ball_2, #ball_3 {
width: 10px;
height: 10px;
border: 2px solid #ccc;
border-radius: 50%;
}
.not_shown {
display: none;
}
.shown {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id = "ball">
<div id = "ball_1" class = "not_shown"></div>
<div id = "ball_2" class = "not_shown"></div>
<div id = "ball_3" class = "not_shown"></div>
</div>
I've a function called fadeIn and I want to return it until a condition is met.
I tried to put an alert in the else line along with clearInterval(myVar), but it just keeps alerting.
CSS:
* {
background-color: black;
padding: 0;
margin: 0;
height: 100%;
}
#title {
background-color: white;
height: 50px;
}
audio {
display: none;
}
#audio-icon {
width: 50px;
background-color: white;
}
#focus {
background-color: black;
margin: auto;
width: 100%;
height: 700px;
border: 5px, solid, grey;
border-style: inset;
border-radius: 10px;
}
#text-box {
background-color: black;
width: 100%;
height: 200px;
margin-top: 500px;
float: left;
border: 5px, solid, grey;
border-style: inset;
border-radius: 10px;
}
#command-line {
background-color: black;
width: 100%;
height: 50px;
margin-top: 150px;
float: left;
border: 5px, solid, grey;
border-style: inset;
border-radius: 10px;
}
#element {
opacity: 0.1;
}
HTML:
<audio id="background-audio" controls autoplay="autoplay" loop>
<source src="Darkness.mp3" type="audio/mpeg">
</audio>
<div id="title">
<img id="audio-icon" src="unmute.png" onclick="mute()">
<img id="element" src="123.png">
</div>
<div id="focus">
<div id="text-box">
<div id="command-line"></div>
</div>
</div>
JavaScript:
function fadeIn() {
var myVar = setInterval(fadeIn, 500);
var element = document.getElementById('element');
if (element.style.opacity < 1) {
element.style.opacity -= '-0.1';
} else {
clearInterval(myVar);
}
}
function mute() {
var audio = document.getElementById('background-audio');
var img = document.getElementById('audio-icon');
if (audio.muted) {
audio.muted = false;
img.src = 'unmute.png';
} else {
audio.muted = true;
img.src = 'mute.png';
}
}
document.onload = fadeIn();
UPDATE:
I have put the variables outside of the function and all of the sudden my code seems to work correctly. Not sure how this is possible since I have tried this already. My code wouldn't run at all and alert would keep alerting. Anyway thanks for all the help. This was my first question so apart from a few typos and the way I listed my code I don't really know why I get downvoted so any feedback about that is welcome! Here is my current working code:
<script>
var myVar = setInterval(fadeIn, 500);
var element = document.getElementById('element');
function fadeIn() {
console.log(element.style.opacity)
if (element.style.opacity < 1) {
element.style.opacity -= '-0.1';
} else {
clearInterval(myVar);
}
}
function mute() {
var audio = document.getElementById('background-audio');
var img = document.getElementById('audio-icon');
if (audio.muted) {
audio.muted = false;
img.src = 'unmute.png';
} else {
audio.muted = true;
img.src = 'mute.png';
}
}
document.onload = fadeIn();
</script>
See the snippet .it will stop the reach with 1 .see the console.log
var myVar;
var element = document.getElementById('element');
function fadeIn() {
console.log(element.style.opacity)
if (element.style.opacity < 1) {element.style.opacity -= -0.1;
}
else {
clearInterval(myVar);
}
}
function mute(){
var audio = document.getElementById('background-audio');
var img = document.getElementById('audio-icon');
if (audio.muted) {
audio.muted = false;
img.src = 'unmute.png';
}
else {
audio.muted = true;
img.src = 'mute.png';
}
}
window.onload =function(){
myVar = setInterval(fadeIn, 500);
}
* {
background-color: black;
padding: 0;
margin: 0;
height: 100%;
}
#title {
background-color: white;
height: 50px;
}
audio {
display: none;
}
#audio-icon {
width: 50px;
background-color: white;
}
#focus {
background-color: black;
margin: auto;
width: 100%;
height: 700px;
border: 5px, solid, grey;
border-style: inset;
border-radius: 10px;
}
#text-box {
background-color: black;
width: 100%;
height: 200px;
margin-top: 500px;
float: left;
border: 5px, solid, grey;
border-style: inset;
border-radius: 10px;
}
#command-line {
background-color: black;
width: 100%;
height: 50px;
margin-top: 150px;
float: left;
border: 5px, solid, grey;
border-style: inset;
border-radius: 10px;
}
#element {
opacity: 0.1;
}
<audio id="background-audio" controls autoplay="autoplay" loop>
<source src="Darkness.mp3" type="audio/mpeg">
</audio>
<div id="title">
<img id="audio-icon" src="unmute.png" onclick="mute()">
<img id="element" src="123.png">
</div>
<div id="focus">
<div id="text-box">
<div id="command-line"></div>
</div>
</div>
var myVar ;
var element = document.getElementById('element');
function fadeIn() {
console.log(element.style.opacity)
if (element.style.opacity < 1) {
element.style.opacity -= -0.1;
}
else {
clearInterval(myVar);
}
}
window.onload= function (){
myVar = setInterval(fadeIn, 100);
}
<p id="element">hi</p>
The problem here is that setInterval is called independently of the if clauses, and that you're spamming unobserved intervals, intervals on which you don't have access anymore in the fadeIn function's block.
In this case you could have also used setTimeout instead, because it asynchronously evaluate its first argument just once, and because you don't have access to the intervals in the way you handle them.
Note: your condition for fade in is wrong, because you're decreasing the element opacity while its opacity is only bigger than 1... i just changed this 1 by 0.
var element, lastFadeInTimeout;
element = document.getElementById('element');
function fadeIn() {
// The element is not totally
// transparent yet
if (element.style.opacity > 0) {
element.style.opacity -= 0.1;
// Let's wait 500ms to fade the element
// again, only once
lastFadeInTimeout = setTimeout(fadeIn, 500);
}
}
Now, if you want to stop your fade-in action you can call clearTimeout with lastFadeInTimeout, where lastFadeInTimeout is the identifier of the last timeout created by the fade-in action.
clearTimeout(lastFadeInTimeout);
You call the fadIn func onload (that's fine) but then you create a queue to execute the function every half a second, in each iteration you create another queue to execute the functio every half a sec.... sooner or later you're going to kill the browser with this.
What you're looking for is probably more like so:
function fadeIn() {
if (opacity < 1) {
opacity += 0.1;
setTimeout(fadeIn, 500);
}
}
document.onLoad = fadeIn();
If not for purpose of learning JavaScript you should probably do things like fadeIn / fadeOut using CSS transitions rather than JavaScript.
I am trying to build a simple traffic light with HTML, CSS and Javascript. Clicking on the light should change the color of the light (if I click when it is Green, it changes to Yellow and so on).
HTML:
<div id="outer_box" onclick = "change()">
<div id ="red"></div>
<div id ="yellow"></div>
<div id ="green"></div>
</div>
CSS:
#outer_box{
width: 70px;
height:150px;
background:black;
}
#red{
width: 50px;
height:50px;
margin: auto;
border-radius: 50%;
background: red;
}
#yellow{
width: 50px;
height:50px;
margin: auto;
border-radius: 50%;
background: yellow;
}
JavaScript:
var state;
state = "green"
function change(){
if (state=="green"){
state = "yellow";
}
else if (state== "yellow"){
state = "red";
//state_def();
}
else{
state = "green";
//state_def();
}
console.log(state);
state_def();
}
function state_def(){
console.log("inside state def")
console.log(state);
if (state == "green"){
document.getElementById("yellow").disabled = true;
//$("#yellow").prop('disabled',true);
//$("#red").prop('disabled',true);
}
else if (state == "yellow"){
$("#green").prop('disabled',true);
$("#red").prop('disabled',true);
}
else{
$("#yellow").prop('disabled',true);
$("#green").prop('disabled',true);
}
}
Here is the jsFiddle link: https://jsfiddle.net/taniachanda86/mx7r0hrL/
Please help me understand what is that I am doing wrong?
Following way you can do using JQuery. Add and remove active class.
First display one light. On click it will change.
var items = $('div.light');
var currentItem = items.filter('.active');
$('#outer_box').on('click', function() {
var nextItem = currentItem.next();
currentItem.removeClass('active');
if ( nextItem.length ) {
currentItem = nextItem.addClass('active');
} else {
currentItem = items.first().addClass('active');
}
});
#outer_box{
width: 70px;
height:150px;
background:black;
}
#red{
width: 50px;
height:50px;
margin: auto;
border-radius: 50%;
background: red;
display:none;
}
#yellow{
width: 50px;
height:50px;
margin: auto;
border-radius: 50%;
background: yellow;
display:none;
}
#green{
width: 50px;
height:50px;
margin: auto;
border-radius: 50%;
background: green;
display:none;
}
.active{
display:block !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="outer_box">
<div id ="red" class="light active"></div>
<div id ="yellow" class="light"></div>
<div id ="green" class="light"></div>
</div>
The solution is quite simple.
$("#green").attr('disabled', true);
will show that your div is actually being disabled while you inspect element. However, it will not quite get you to point of having the css color affected by it.
Instead defining the opacity attribute will help you achieve your need.
Here is the plunker: https://plnkr.co/edit/mdlAS68gpFBm64jfiCCu?p=preview. I hope this is what you are asking for.
var colors = ["red", "yellow", "green"];
var state = 1;//because red already visible
//addEventListener method to add onclick handler
document.getElementById('outer_box').addEventListener('click', function(){
if (state==3){//if state reaches to 3, reset to 0
state = 0;
}
var allLights = document.querySelectorAll('.light');
for(var i = 0; i < allLights.length; i++) {//remove active class from all light
allLights[i].className = "light";
}
document.getElementById(colors[state]).className = "light active"; //add active class on the next light;
state++;//increment state
}, false);
I have updated your fiddle. check here
Open your javascript console and see the failure:
Uncaught ReferenceError: change is not defined
change is not in scope of the onclick of the <div>.
This is because the Javascript part of jsfiddle is executed in the onload function. See https://stackoverflow.com/a/5468370/189058
I guess you wanted a traffic light which on click will glow the clicked light.If so, can be achieved by the below code.
$( document ).ready(function() {
$('#red').css("background-color", "red");
$('#yellow').css("background-color", "white");
$('#green').css("background-color", "white");
$('.trafficlight').click(function(){
var selected_id=$(this).attr("id");
if(selected_id=='green')
{
$('#green').css("background-color", "green");
$('#red').css("background-color", "white");
$('#yellow').css("background-color", "white");
}
else if(selected_id=='yellow')
{
$('#yellow').css("background-color", "yellow");
$('#red').css("background-color", "white");
$('#green').css("background-color", "white");
}
else
{
$('#red').css("background-color", "red");
$('#yellow').css("background-color", "white");
$('#green').css("background-color", "white");
}
});
});
#outer_box{
width: 70px;
height:150px;
background:black;
}
#red{
width: 50px;
height:50px;
margin: auto;
border-radius: 50%;
background:red;
}
#yellow{
width: 50px;
height:50px;
margin: auto;
border-radius: 50%;
background: yellow;
}
#green{
width: 50px;
height:50px;
margin: auto;
border-radius: 50%;
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="outer_box" >
<div id ="red" class="trafficlight"></div>
<div id ="yellow" class="trafficlight"></div>
<div id ="green" class="trafficlight"></div>
</div>