Displaying Static, Random HTML And Images On A Web Page Via AJAX

Recently asked on Yahoo! Answers:

I need a script that will randomize fireworks exported html and images on my index page?

so that the html exported images from fireworks will be randomized every time the page is accessed. I can’t use an ordinary random script, because i am working with images that include html.

There are lots of ways to include a text or HTML file in a Web page. The oldest, and simplest, is to use a server-side include:

<!--#include virtual="somefile.txt" -->

Another is with an IFrame:

<iframe id="myiframe" src="somefile.html" width="500" height="400"></iframe>

You can also do it with a server-side scripting language, such as PHP:

require_once('somefile.txt');

And you can even do it with ASP.NET; in fact, you can place your code in an ASP.NET panel and toggle the panel’s visibility, or assign the copy you want included to the innerText or innerHTML properties of a DIV (which the HTMLGenericControl class conveniently ports for us from the standard DOM attribute into ASP.NET):

myPanel.Visible = True

myDiv.InnerHTML = "<p>Hello World!</p>"

myDiv.InnerText = "Hello World!"

Using a server-side scripting language, you could even create the text to be included on the fly, from a data source or the like, based on any of countless criteria. And, of course, using a server-side scripting language would allow us to “randomize” the source of the included file; an IFrame or server-side include, by themselves, have static sources.

But instead of looking to a server-side solution, we’ll use AJAX: JavaScript will randomly pick one of several files for us to include on our page, and AJAX will fetch it for us and place it inside a DIV element on our main page. As always, I’ll have a working demo and downloadable code at the end of this discussion.

Step 1: Create The Included Code Snippets

Our first step is to make the code snippets we’ll include in the main page. Each snippet will be in its own text file, and each will contain only the markup we want displayed.

That is, our code snippet files won’t contain HTML, HEAD or BODY tags. We won’t include any of the child tags normally found inside the HEAD tag, either: no TITLE, no META, etc.

So, using the question’s parameters, we’ll make some simple rollover images in Fireworks and export the images and HTML as we would any rollover image. You can see a sample of the rollover HTML that is generated by Fireworks here:

http://demo.dougv.com/ajax_snippet_include/snippet1.html

If you examine the HTML in that page, you’ll see it contains some JavaScript, some style, and a table that lays out the image for rollover image swapping purposes.

To proceed, we want to first save all the JavaScript functions on that page, from the opening SCRIPT tag to the ending SCRIPT tag, and set that aside. We’ll eventually put it into our main HTML page, but for now, we just want to remove it from this page and preserve it until we make our main HTML page.

function MM_findObj(n, d) { //v4.01
  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
  if(!x && d.getElementById) x=d.getElementById(n); return x;
}
function MM_swapImage() { //v3.0
  var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
   if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
}
function MM_swapImgRestore() { //v3.0
  var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
}

function MM_preloadImages() { //v3.0
  var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
    var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
    if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
}

Next, we want to do the same with the STYLE block: Remove it from this page, but set it aside for inclusion on our main page.

td img {display: block;}

With that coding removed and set aside, we can now strip out everything from the opening DOCTYPE declaration to the opening TABLE tag, and remove all the HTML following the final, closing TABLE tag, leaving us with just this code block:

<table border="0" cellpadding="0" cellspacing="0" width="300">
<!-- fwtable fwsrc="Untitled" fwbase="snippet1.gif" fwstyle="Dreamweaver" fwdocid = "1158489763" fwnested="0" -->
  <tr>
   <td><img src="images/spacer.gif" width="10" height="1" border="0" alt="" /></td>
   <td><img src="images/spacer.gif" width="280" height="1" border="0" alt="" /></td>
   <td><img src="images/spacer.gif" width="10" height="1" border="0" alt="" /></td>
   <td><img src="images/spacer.gif" width="1" height="1" border="0" alt="" /></td>
  </tr>

  <tr>
   <td colspan="3"><img name="snippet1_r1_c1" src="images/snippet1_r1_c1.gif" width="300" height="10" border="0" id="snippet1_r1_c1" alt="" /></td>
   <td><img src="images/spacer.gif" width="1" height="10" border="0" alt="" /></td>
  </tr>
  <tr>
   <td rowspan="2"><img name="snippet1_r2_c1" src="images/snippet1_r2_c1.gif" width="10" height="140" border="0" id="snippet1_r2_c1" alt="" /></td>
   <td><a href="#" onmouseout="MM_swapImgRestore();" onmouseover="MM_swapImage('snippet1_r2_c2','','images/snippet1_r2_c2_f2.gif',1);"><img name="snippet1_r2_c2" src="images/snippet1_r2_c2.gif" width="280" height="130" border="0" id="snippet1_r2_c2" alt="" /></a></td>
   <td rowspan="2"><img name="snippet1_r2_c3" src="images/snippet1_r2_c3.gif" width="10" height="140" border="0" id="snippet1_r2_c3" alt="" /></td>
   <td><img src="images/spacer.gif" width="1" height="130" border="0" alt="" /></td>
  </tr>
  <tr>
   <td><img name="snippet1_r3_c2" src="images/snippet1_r3_c2.gif" width="280" height="10" border="0" id="snippet1_r3_c2" alt="" /></td>
   <td><img src="images/spacer.gif" width="1" height="10" border="0" alt="" /></td>
  </tr>
</table>

With just the code block above remaining, we now save that snippet as a text file: in our case, we’ll save it as snippet1.txt, which you can see here:

http://demo.dougv.com/ajax_snippet_include/snippet1.txt

For all the remaining Fireworks HTML files we might want to include on our home page, we strip all the code before the opening TABLE tag, and all the code following the closing TABLE tag, then save the results as text files.

We can do that because thankfully, Fireworks uses the same basic JavaScript functions to preload, find and swap images. Because of that, we only need the functions and style from the first Fireworks rollover page, and it will work for all four.

Step 2: Make The Main Page

Our main page is a normal XHTML page. First, we paste in the STYLE and SCRIPT blocks that we copied from the first Fireworks rollover page:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
		<title>Displaying Static, Random HTML And Images On A Web Page Via AJAX</title>
		<link href="../demo.css" rel="stylesheet" type="text/css" />
		<style type="text/css">td img {display: block;}</style>
		<script language="JavaScript1.2" type="text/javascript">
			<!--
			function MM_findObj(n, d) { //v4.01
			  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
				d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
			  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
			  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
			  if(!x && d.getElementById) x=d.getElementById(n); return x;
			}
			function MM_swapImage() { //v3.0
			  var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
			   if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
			}
			function MM_swapImgRestore() { //v3.0
			  var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
			}

			function MM_preloadImages() { //v3.0
			  var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
				var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
				if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
			}

			//-->
		</script>
	</head>


At this point, we have a decision to make: do we want to preload images?

If you want your images to appear automatically due to a mouseover or other event, you'll need to preload all possible images -- since you're not sure which Fireworks code snippet will load.

Therefore, if you have lots and lots of images to preload, you may want to skip this step. Just be advised that if you don't preload the images, there will be a delay between the mouseover event and the image displaying, because the Web browser will have to retrieve the image. For this demo, I'll be preloading images.

To preload all images, you basically add, as an argument to the MM_preloadImages() function, each and every image in all the code snippet pages you intend to include.

The problem with the preload is that it's not the only onload event we need to trigger in the BODY tag; we also need to trigger it to get a random code snippet to display. Unfortunately, the BODY tag can only accept one argument for the onload event.

We work around that problem by creating a JavaScript function called pageLoad(). That function will trigger both the MM_preloadImages() function and the function to get our code snippet:


<body onload="pageLoad()">
function pageLoad() {
	MM_preloadImages('images/snippet1_r1_c1.gif','images/snippet1_r1_c1_f2.gif','images/snippet1_r2_c1.gif','images/snippet1_r2_c1_f2.gif','images/snippet1_r2_c2.gif','images/snippet1_r2_c2_f2.gif','images/snippet1_r2_c3.gif','images/snippet1_r2_c3_f2.gif','images/snippet1_r3_c2.gif','images/snippet1_r3_c2_f2.gif','images/snippet2_r1_c1.gif','images/snippet2_r1_c1_f2.gif','images/snippet2_r2_c1.gif','images/snippet2_r2_c1_f2.gif','images/snippet2_r2_c2.gif','images/snippet2_r2_c2_f2.gif','images/snippet2_r2_c3.gif','images/snippet2_r2_c3_f2.gif','images/snippet2_r3_c2.gif','images/snippet2_r3_c2_f2.gif','images/snippet3_r1_c1.gif','images/snippet3_r1_c1_f2.gif','images/snippet3_r2_c1.gif','images/snippet3_r2_c1_f2.gif','images/snippet3_r2_c2.gif','images/snippet3_r2_c2_f2.gif','images/snippet3_r2_c3.gif','images/snippet3_r2_c3_f2.gif','images/snippet3_r3_c2.gif','images/snippet3_r3_c2_f2.gif','images/snippet4_r1_c1.gif','images/snippet4_r1_c1_f2.gif','images/snippet4_r2_c1.gif','images/snippet4_r2_c1_f2.gif','images/snippet4_r2_c2.gif','images/snippet4_r2_c2_f2.gif','images/snippet4_r2_c3.gif','images/snippet4_r2_c3_f2.gif','images/snippet4_r3_c2.gif','images/snippet4_r3_c2_f2.gif');
	getSnippet();
}

With the BODY tag set to preload images, we can move on to the page proper. For our system to work, all we need to do is declare a DIV, in which we will display the text snippets we created earlier, and provide a unique ID:

<div id="snippet"></div>

Step 3: Create The Snippet HTTP Request Function

We’re ready to get down to the nuts and bolts of making our code snippets appear on our page.

First, we declare our HTTPRequest function. Its first part is an array of all the URLs to our code snippet pages. We can use relative HTTP paths here; modern browsers will make HTTP requests relative to the page containing the AJAX code.

function getSnippet() {
	var theUrls = new Array('snippet1.txt', 'snippet2.txt', 'snippet3.txt', 'snippet4.txt');

With that out of the way, we declare the httprequest object, and then try to create the object. Since Internet Explorer and Mozilla-based browsers create HTTP Request objects differently, we need to try two different methods.

var httpRequest;

if (window.XMLHttpRequest) {
	httpRequest = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
	try {
		httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
	}
	catch (e) {
		try {
			httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
		}
		catch (e) {}
	}
}

if (!httpRequest) {
	alert('Cannot create an XMLHTTP instance');
	return false;
}

If we successfully created an HTTP Request object, we need to instruct the script what to do with what we get from the request. That’s the purpose of the following code:

httpRequest.onreadystatechange = function() {
	eventListener(httpRequest);
};

Finally, we need to tell the Request object what to get. We do that by generating a random number somewhere between 0 and the highest index of our URL array; we then select the cell of the array corresponding to our random number and set that to a string variable.

var i = Math.random() * theUrls.length;
i = Math.floor(i);
var url = theUrls[i];

Lastly, we make our HTTP Request using the URL we just got.


	httpRequest.open('GET', url, true);
	httpRequest.send(null);
}

Step 4: Create The HTTP Request Ready State Event Handler / Snippet Rendering Function

The HTTP Request ready state event handler will check for us when the Request object has successfully retrieved the code snippet.

Once we get it, we’re ready to add that code to our main page; we do that by getting the snippet DIV, then setting its innerHTML property to be the code in our snippet file.

function eventListener(httpRequest) {
	if (httpRequest.readyState == 4) {
		if (httpRequest.status == 200) {
			var theDiv = document.getElementById('snippet');
			theDiv.innerHTML = httpRequest.responseText;
		}
		else {
			alert('Error requesting code snippet from server');
		}
	}
}

And that’s all there is to it. You can see a working demo here:

http://demo.dougv.com/ajax_snippet_include/

Please keep in mind that because I’m only using four snippets, you may need to refresh the page several times in order to get a different snippet to show.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  • Check out the Commenting Guidelines before commenting, please!
  • Want to share code? Please put it into a GitHub Gist, CodePen or pastebin and link to that in your comment.
  • Just have a line or two of markup? Wrap them in an appropriate SyntaxHighlighter Evolved shortcode for your programming language, please!