I am working on an optional exercise for a course, being optional no one has posted any helpful feedback on the course forum. I have finished the code as instructed, to the best of my ability and cannot located the problem.

The script is supposed to activate a red ball when clicked to travel around a national park map. Whenever the ball hits a landmark it is supposed to stop, a text description is supposed to appear as well as a photo in some cases. Once the ball makes it to the end of the map it is supposed to reload the page after a 7 second delay.

Below is my js file and my htm file. I have placed comments within the code to explain whenever possible what I have been asked to do. There are quite a few pictures for this so I won't post them unless asked.

I think this is a very interesting way to use JavaScript and would really like to get the program working. A lot of the content inside is a first for me, so be patient please when you run into an error and help me to correct my ways. Thanks to you!

/*
Filename: trail.js

   Function List:
   placeIt(id, x, y)
      Places the id object at the coordinates (x,y)

   hideIt(id)
      Hides the id object by setting its visibility style to "hidden"

   showIt(id)
      Hides the id object by setting its visibility style to "visible"

*/

function placeIt(id, x, y) {
   object=document.getElementById(id);
   object.style.left=x+"px";
   object.style.top=y+"px";
}

function showIt(id) {
   object=document.getElementById(id);
   object.style.visibility="visible";
}

function hideIt(id) {
   object=document.getElementById(id);
   object.style.visibility="hidden";
}
<html>
<head>
<!-- 
 
   Filename:         trail.htm
   Supporting files: photo2.gif-photo8.gif, redball.gif, text1.gif-text9.gif,
                     trail.css, trail.gif, trail.js
-->
<title>Heart of Rocks Trail</title>
<link href="trail.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="trail.js"> </script>
<script type="text/javascript">

/*
   Trail Map

   Variable List:
   x
      Contains an array of the x-coordinates of the trail map path
   y
      Contains an array of the y-coordinates of the trail map path
*/
var xArray = new Array(304,306,310,314,318,323,327,330,332,333,334,335,336,
     336,335,333,330,327,324,322,321,322,325,328,331,334,337,339,340,338,337,
     338,339,340,342,343,345,347,349,351,353,355,358,361,365,368,373,378,384,
     391,397,404,411,418,426,434,442,451,458,465,472,479,484,490,499,504,505,
     506,507,507,502,497,492,486,480,474,468,462,457,453,450,447,443,438,433,
     429,424,418,413,408,404,400,396,389,386,381,379,378,378,377,377,364,342,
     336,330,323,316,309,301,293,285,277,270,263,257,251,245,236,230,224,219,
     213,209,204,200,196,191,187,182,177,172,166,162,159,155,152,148,143,137,
     130,123,116,110,103,97,93,93,94,94,93,91,88,85,81,78,75,73,72,75,80,85,
     90,95,99,103,108,112,116,120,122,123,122,121,119,118,118,121,126,129,132,
     135,140,146,154,163,172,180,185,188,192,198,204,210,212,215,225,230,236,
     242,248,255,262,270,278,286,293,300,306,312,317,322,330,334,336,337,337,
     338,338,339,339,339,339,335,330,328,325,323,321,324,330,337,344,352,360,
     367,373,379,384,385,385,391,397,405,412,421,430,438,445,452,457,462,464,
     467,471,475,480,486,491,498,504,510,516,521,525,529,527,527,532,537,543);

var yArray = new Array(438,432,426,422,419,415,410,405,400,395,389,382,375,
     367,359,354,350,345,341,336,330,325,320,315,310,305,301,296,290,285,279,
     271,266,260,254,248,241,234,226,220,213,207,202,197,192,189,187,185,184,
     183,182,182,182,182,182,182,183,183,183,183,184,184,183,183,181,179,175,
     170,164,157,151,149,147,146,145,143,142,139,135,131,126,122,117,113,110,
     107,104,102,99,97,95,93,91,87,84,80,78,77,76,76,75,71,67,66,66,65,64,63,
     63,62,61,61,60,59,58,58,57,56,55,54,52,49,46,43,39,35,31,27,24,21,19,20,
     23,27,31,35,39,41,42,42,41,40,39,39,41,47,54,61,68,75,80,85,90,95,100,
     105,110,115,120,122,124,126,127,130,133,137,141,145,150,155,161,168,174,
     180,185,190,196,198,203,209,212,216,218,219,218,218,219,222,226,229,229,
     229,229,234,238,241,241,242,242,242,242,242,242,242,242,242,242,242,243,
     243,243,250,250,255,260,266,273,280,288,295,301,307,313,316,321,326,332,
     339,346,348,348,348,348,348,348,348,349,353,358,363,366,367,367,366,365,
     365,364,364,365,367,369,372,375,379,382,385,387,390,393,396,399,402,405,
     408,416,422,428,433,436,439);
 
var index = 1;
// hide all text and photo objects on the screen as the red ball travels around the trail
function hideAll() {
	hideIt("text1");
	hideIt("text2");
	hideIt("photo2");
	hideIt("text3");
	hideIt("photo3");
	hideIt("text4");
	hideIt("text5");
	hideIt("photo5");
	hideIt("text6");
	hideIt("photo6");
	hideIt("text7");
	hideIt("photo7");
	hideIt("text8");
	hideIt("photo8");
	hideIt("text9");	
}
//display the text description and photo for a given landmark

/* since not every landmark has a photo use object detection to determine whether a div element with the value of the photo parameter exists and if it does call the showIt() function to display the photo */

function describeIt(text, photo) {
		showIt("text1");
		if (document.getElementById("photo1")) { 
		showIt("photo1"); }
			showIt("text2");
			if (document.getElementById("photo2")) {
			showIt("photo2"); }
				showIt("text3");
				if (document.getElementById("photo3")) {
				showIt("photo3"); }
					showIt("text4");
					if(document.getElementById("photo4")) {
					showIt("photo4");}
						showIt("text5");
						if(document.getElementById("photo5")) {
						showIt("photo5"); }
							showIt("text6");
							if(document.getElementById("photo6")) {
							showIt("photo6"); }
								showIt("text7");
								if(document.getElementById("photo7")) {
								showIt("photo7"); }
									showIt("text8");
									if(document.getElementById("photo8")) {
									showIt("photo8") ; }
										showIt("text9"); {
										if (document.getElementById("photo9")) {
										showIt("photo9"); }	
	}
}
// move the red ball along the hiking trail, stopping if the red ball encounters one of the landmarks
function runPath() {
	hideAll(); // call the hideAll() function to ensure that all text and photos are hidden on the page
	index ++;  // increase the value of the index variable by 1
	placeIt("redBall", xArray[index], yArray[index]) // place the redball at the xArray index, and yArray index
	
	switch(index) {
		case 0: 
		describeIt("text1");
		break;
		case 16: 
		describeIt("text2", "photo2");
		break;
		case 68: 
		describeIt("text3", "photo3");
		break;
		case 82: 
		describeIt("text4", "photo4");
		break;
		case 97: 
	 	describeIt("text5", "photo5");
		break;
		case 130: 
		describeIt("text6", "photo6");
		break;
		case 188: 
		describeIt("text7", "photo7");
		break;
		case 231: 
		describeIt("text8", "photo8");
		break;
		case 269: 
		describeIt("text9"); //call the describeIt() function with "text9"
		var index = 0; // set the value of the index variable to 0
		window.location.reload(7000); // reload the web page after a seven-second delay.
		break;
		default: 
		// the default behaviour is to call the runPath() function agasin after a 10th of a second
		setTimeout("runPath()", 100); 
	}
		
}
</script>
</head>

<body>

<div id="trail">
   <img src="trail.gif" width="650" height="490" alt="Heart of Rocks Trail" />
</div>

<!-- Mark the redBall.gif inline image as a link and set the href attricute of the link to run the runPath() function when the ball is clicked -->
<div id="redBall" onClick="runPath()">
     <img src="redball.gif"  alt="Click to follow trail" />
</div>


<div id="text1">
   <img src="text1.gif" alt="A Welcome Message" />
</div>


<div id="text2">
   <img src="text2.gif" alt="The Big Balanced Rock" />
</div>
<div id="photo2">
   <img src="photo2.jpg" width="200" height="155" alt="Big Balanced Rock" />
</div>


<div id="text3">
   <img src="text3.gif" alt="Duck on a Rock" />
</div>
<div id="photo3">
   <img src="photo3.jpg" width="200" height="155" alt="Duck on a Rock" />
</div>


<div id="text4">
   <img src="text4.gif" alt="The Camels Head" />
</div>
<div id="photo4">
   <img src="photo4.jpg" width="200" height="155" alt="Camels Head" />
</div>


<div id="text5">
   <img src="text5.gif" alt="Punch and Judy" />
</div>
<div id="photo5">
   <img src="photo5.jpg" width="200" height="155" alt="Punch and Judy" />
</div>


<div id="text6">
   <img src="text6.gif" alt="Thors Hammer" />
</div>
<div id="photo6">
   <img src="photo6.jpg" width="200" height="155" alt="Thors Hammer" />
</div>


<div id="text7">
   <img src="text7.gif" alt="The Pinnacle Balanced Rock" />
</div>
<div id="photo7">
   <img src="photo7.jpg" width="125" height="200" alt="Pinnacle Balanced Rock" />
</div>


<div id="text8">
   <img src="text8.gif" alt="The Balanced Rock" />
</div>
<div id="photo8">
   <img src="photo8.jpg" width="200" height="155" alt="Big Balanced Rock" />
</div>


<div id="text9">
   <img src="text9.gif" alt="A Short Exit Message" />
</div>

</body>
</html>

Recommended Answers

All 3 Replies

Good for you to try to learn this. There are many rooms in your code for improvement, but I am not going to tell you all right now because it could be too much.

Anyway, there are some immediate problem in the way you try.
1)Your trial image and ball image are not overlaid. As a result, it shows trial image first, and then the ball. What you may do is to use your div which holds the trial.jpg image as the real map. Give the div the trial.jpg background instead of place the image inside the div. Now, place your ball div inside the trial div. Finally, assign proper style properties to both of the div. A sample below shows you how to do it and the 'class' is the CSS part.

// CSS part
  .trial_bg {
    position: relative;
    background-image: url('trail.jpg');
    width: 650;
    height: 490;
  }
  .the_ball {
    position: absolute;
    /* assign the starting poition (top-left of div) of the ball here */
    top: 0px;
    left: 0px;
    /* assign to the same size of the ball image */
    width: 16px;
    height: 16px;
  }

// HTML part

  <div id="trail" class="trial_bg">
    <!-- Mark the redBall.gif inline image as a link and set the href attricute of the link to run the runPath() function when the ball is clicked -->
    <div id="redBall" class="the_ball" onClick="runPath()">
      <img src="redball.gif"  alt="Click to follow trail" />
    </div>
  </div>

2)You should hide all images when the page is loaded. You could simply assign the hidden property to all images. Also, use CSS in this case is safer when working on hiding and showing element because IE has had a bug with JavaScript when dynamically manipulating with 'visibility' property. Also, instead of having a div for each photo and text, why not having a div holding them inside? Doing so, you just need to change the hide/show property on only one 'div' instead of both? One more, you may consider the 'text' part to be just text which should be easier to work with. Below is the sample code.

// CSS part
  .show {
    /* actually no need anything here because properties are visible by default */
    /* when you switch from 'hide' to this one, it trigger default visibility */
  }
  .hide {
    display: none;
    visibility: hidden;
  }

// HTML part
<div id="location1" class="hide">
  <div id="text1">
    Here is the text for location 2
  </div>
</div>

<div id="location2" class="hide">
  <div id="text2">
    Here is the text for location 2
  </div>
  <div id="photo2">
    <img src="photo2.jpg" width="200" height="155" alt="Big Balanced Rock" />
  </div>
</div>

 ...

3)If you give the hidden property to all descriptions by default, you don't need the hideAll() function. By the way, the way you call it should not be inside your runPath() but should be in the body tag as <body onload="hideAll()"> because you want all descriptions to be hidden when the page is loaded. Still, if you do the #2 above, you should not need this.

4)In your script part, you should always declare variable as local using 'var' keyword if the variable has a purpose of use only inside the function or scope. It could create confusion and unexpected result if you do not do that. By the way, as I mentioned earlier about using CSS rather than manipulate visibility style using Javascript, it will show up here. The reason is that IE will throw an error when you try to use JavaScript to change the visibility property of an element. And because you are doing so, you may need to move the code from your trial.js into the same location with other's script.

function placeIt(id, x, y) {
    var object=document.getElementById(id); // make 'object' variable local
    object.style.left=x+"px";
    object.style.top=y+"px";
  }

  function showIt(id) {
    var object=document.getElementById(id); // make 'object' variable local
    object.className = "show";
  }

  function hideIt(id) {
    var object=document.getElementById(id); // make 'object' variable local
    object.className = "hide";
  }

Hmm... It gets too long here... Let me stop for now and wait for your response. :)

Thank you for all the helpful suggestions, being as new to coding as I am it is going to take me some time to sort through all of them.

The one problem I notice is that my text book has instructed us (more or less) or do the entire animation in JavaScript, it is a JavaScript course. I'm not arguing that this is the most efficient way, in fact I agree with you and trust your opinion. I'm wondering however how I might make this work following the instructions in the book?

If I create a new file and try it your way, will you try it the text book way? My comments are usually taken right from the text.

There are always many ways to do things, often too many :)

Hmm... Well, I could try that. However, you still have to overlay 'trail.gif' and 'redball.gif' still. The way you display will never overlay both images, and that will not create the animation you want. Therefore, you must choose one -- set trail.gif to be the div background image and put the redball.gif div inside the div OR set both trial.gif and redball.gif divs inside a div which has position relative, and set both gif's divs position to absolute.

I am still not sure about going through the arrayX & arrayY. I understand that you want to go through each point. However, the structure is not uniform and your script won't know when to stop at what point inside the array. You could either add another variable array to tell the script when to stop OR you redesign the structure of the array to be a path set for each location using hash-liked.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.