Automated and Animated Traffic Lights

Right then, I’m having a little bit of a problem with some animation using JavaScript and the DOM. I first created a little page and script that mimics a set of traffic lights (UK traffic lights at least - Only one light is allowed on at any one time, so if amber is lit up then red and green must be out and so on.) that the user could control by clicking the appropriate link. See my Traffic Lights Controller page. Right click, view the source, and click on the external JS file to see the script. :slight_smile: It looks messy now but I’m going to post a separate JS Code Review for that script later, for now, I want to concentrate on the next stage…

What I’ve been trying to do (and failing miserably at) is to remove the controls and have the traffic lights automated so when you load up the page it goes through each of them being on whilst the others are off. I’m pretty sure that the mistake I’ve made with this new script is minimal or I’ve only missed something small out (or otherwise I was totally off the ball!) but if somebody could help me to get this work then I’d be very grateful of the help.

Automatic Traffic Lights




```html4strict
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<title>Automatic Traffic Lights</title>
		<link rel="stylesheet" type="text/css" media="screen" href="stylesheet.css">
		<script type="text/javascript" src="automatic-traffic-lights.js"></script>
	</head>

	<body>
		<div id="wrapper">
			<h1>Automatic Traffic Lights</h1>

			<div id="red-light"></div>
			<div id="amber-light"></div>
			<div id="green-light"></div>
		</div>
	</body>
</html>

Automatic Traffic Lights [JS]

function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	} else {
		window.onload = function() {
			oldonload();
			func();
		}
	}
}

function trafficLightsControllerAutomated() {
	if (!document.getElementById) return false;
	var greenLight = document.getElementById("green-light");
	var amberLight = document.getElementById("amber-light");
	var redLight = document.getElementById("red-light");

	redLight.style.height = "20px";
	redLight.style.width = "20px";
	redLight.style.margin = "1px 0";
	redLight.style.backgroundColor = "black";

	amberLight.style.height = "20px";
	amberLight.style.width = "20px";
	amberLight.style.margin = "1px 0";
	amberLight.style.backgroundColor = "black";

	greenLight.style.height = "20px";
	greenLight.style.width = "20px";
	greenLight.style.margin = "1px 0";
	greenLight.style.backgroundColor = "black";

	function changeLightsToRed() {
		greenLight.style.backgroundColor = "black";
		amberLight.style.backgroundColor = "black";
		redLight.style.backgroundColor = "red";
		setTimeout ("changeLightsToAmber()", 2000);
	}

	function changeLightsToAmber() {
		greenLight.style.backgroundColor = "black";
		amberLight.style.backgroundColor = "orange";
		redLight.style.backgroundColor = "black";
		setTimeout ("changeLightsToGreen()", 2000);
	}

	function changeLightsToGreen() {
		greenLight.style.backgroundColor = "green";
		amberLight.style.backgroundColor = "black";
		redLight.style.backgroundColor = "black";
		setTimeout ("changeLightsToAmberTwo()", 2000);
	}

	function changeLightsToAmberTwo() {
		greenLight.style.backgroundColor = "black";
		amberLight.style.backgroundColor = "orange";
		redLight.style.backgroundColor = "black";
		setTimeout ("changeLightsToRed()", 2000);
	}

	changeLightsToRed();
	changeLightsToAmber();
	changeLightsToGreen();
	changeLightsToAmberTwo();
}

addLoadEvent(trafficLightsControllerAutomated);

Cheers,

Andrew Cooper

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<title>Traffic Lights Controller</title>
		<link rel="stylesheet" type="text/css" media="screen" href="stylesheet.css">
		<script type="text/javascript" >
function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	} else {
		window.onload = function() {
			oldonload();
			func();
		}
	}
}

function trafficLightsAuto(nu,redLight,amberLight,greenLight) {
 var args=trafficLightsAuto.arguments,cnt=args[0];
 if (trafficLightsAuto.lst){
  trafficLightsAuto.lst.style.backgroundColor = 'black';
 }
 if (args[cnt]){
  args[cnt].style.backgroundColor = cnt==1?'red':cnt==2?'orange':'green';
  trafficLightsAuto.lst=args[cnt];
  cnt++;
  trafficLightsAuto.to=setTimeout(function(){  trafficLightsAuto(cnt,redLight,amberLight,greenLight); },1000);
 }
}

function trafficLightsController() {
	if (!document.getElementById) return false;
	var greenLight = document.getElementById("green-light");
	var amberLight = document.getElementById("amber-light");
	var redLight = document.getElementById("red-light");
	var greenControlOn = document.getElementById("green");
	var amberControlOn = document.getElementById("amber");
	var redControlOn = document.getElementById("red");

	greenLight.style.height = "20px";
	greenLight.style.width = "20px";
	greenLight.style.margin = "1px 0";
	greenLight.style.backgroundColor = "black";

	amberLight.style.height = "20px";
	amberLight.style.width = "20px";
	amberLight.style.margin = "1px 0";
	amberLight.style.backgroundColor = "black";

	redLight.style.height = "20px";
	redLight.style.width = "20px";
	redLight.style.margin = "1px 0";
	redLight.style.backgroundColor = "black";

	greenControlOn.onclick = function() {
        clearTimeout(trafficLightsAuto.to);
		greenLight.style.backgroundColor = "green";
		amberLight.style.backgroundColor = "black";
		redLight.style.backgroundColor = "black";
	}

	amberControlOn.onclick = function() {
        clearTimeout(trafficLightsAuto.to);
		greenLight.style.backgroundColor = "black";
		amberLight.style.backgroundColor = "orange";
		redLight.style.backgroundColor = "black";
	}

	redControlOn.onclick = function() {
        clearTimeout(trafficLightsAuto.to);
		greenLight.style.backgroundColor = "black";
		amberLight.style.backgroundColor = "black";
		redLight.style.backgroundColor = "red";
	}
 trafficLightsAuto(1,redLight,amberLight,greenLight)
}

addLoadEvent(trafficLightsController);



        </script>
	</head>

	<body>
		<div id="wrapper">
			<h1>Traffic Lights Controller</h1>

			<ul>
				<li><a href="#" id="red">Red - On</a></li>
				<li><a href="#" id="amber">Amber - On</a></li>
				<li><a href="#" id="green">Green - On</a></li>

			</ul>

			<div id="red-light"></div>
			<div id="amber-light"></div>
			<div id="green-light"></div>
		</div>
	</body>
</html>

Here is a different way to do the same thing. The traffic light div objects are gathered as a collection so that they can be accessed easily by the script. The required colour (red, yellow, green) for each traffic light is stored as a property of each div object. The cycle continues indefinitely.

[HIGHLIGHT=“”]
<!doctype HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”>
<html>

<head>

<meta http-equiv=“Content-Type” content=“text/html; charset=windows-1252”>
<title>Traffic Lights</title>
<script type=“text/javascript”>
<!–
var allDivs, tOut=null, pointer=-1; // global
window.onload=function(){
var allLightsObj=document.getElementById(“allLights”);
// build collection of div objects
allDivs=allLightsObj.getElementsByTagName(“div”);
// set div colours as property of each div
var i, cols=[“#F00”,“#FF0”,“#0F0”];
for(i=0;i<allDivs.length;i++){ allDivs[i].color=cols[i]; }
tOut=setTimeout(switchIt,100);
}
// ------------
function switchIt()
{ clearTimeout(tOut);
++pointer;
pointer=(pointer>2)? 0 : pointer;
var i, thisColour;
// cycle through each div a reset background colour
for(i=0;i<allDivs.length;i++)
{ thisColour=(pointer==i)? allDivs[i].color : “#000”;
allDivs[i].style.backgroundColor=thisColour;
}
// recall
tOut=setTimeout(switchIt,1000);
}
//–>
</script>
<style type=“text/css”>
<!–
body { font-family:arial, helvetica, sans-serif; font-weight:bold; font-size:18px; color:#000; text-align:left; margin:3px 0px; }
#wrap { position:relative; top:20px; left:0px; width:900px; height:500px; margin-left:100px; }
#allLights { position: absolute; top:50px; left:50px; width:40px; height:100px; }
#red-light { background-color:#F00; }
.lights { position:relative; top:0px; left:0px; margin-bottom:5px; width:40px; height:40px; background-color:#000; }
–>
</style>
</head>

<body>

<div id=“wrap”>
<h3>Automatic Traffic Lights</h3>
<div id=“allLights”>
<div id=“red-light” class=“lights”>
</div>
<div id=“amber-light” class=“lights”>
</div>
<div id=“green-light” class=“lights”>
</div>
</div>
<!-- end allLights –>
</div>
<!-- end wrap –>

</body>

</html>

That’s not quite the way they’re sequenced.

"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<style type='text/css'>

#wrapper div{ height : 40px ; width : 40px; margin : 1px; background-color : black; border-radius : 20px; border: solid 1px #000 }

</style>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Traffic Lights Controller</title>

<script type="text/javascript" >

function trafficLights()
{ 
 var sequenceData = [ [ 5, 1, 0, 0 ], [ 2, 1, 1, 0 ], [ 5, 0, 0, 1 ], [ 3, 0, 1, 0 ]  ],
     lights = [],
     index = 0;

 for( var i = 0, elemId; ( elemId = arguments[ i ] ); i++ )     
  lights[ i ] = document.getElementById( elemId );
  
 function display()
 {
  if( index >= sequenceData.length ) 
   index = 0;
   
  for( var i = 0, cv, dLen = lights.length; i < dLen; i++ )
   lights[ i ].style.backgroundColor = ( sequenceData[ index ][ i+1 ] ? lights[ i ].id.match(/^[a-z]+/i).toString() : '#000' );  
   
  setTimeout( display, sequenceData[ index++ ][ 0 ] * 1000 );
 } 
 
 display(); 
}


window.onload = function(){ trafficLights( "red-light", "yellow-light", "green-light" ); };

</script>
</head>
	<body>
		<div id="wrapper">
			<h1>Traffic Lights Controller</h1>
			<div id="red-light"></div>
			<div id="yellow-light"></div>
			<div id="green-light"></div>
		</div>
	</body>
</html>