/*

	LIBRARY:	jjLib
	AUTHOR:		James Jackson
	DATE:		3/21/08

	NOTES:		This is a collection of functions that I use very often.  Most of these I have
				written, but others contain notes on who the original author was.  The scripts
				that I have written are Open Source.  They can be used, adjusted, ruined,
				maimed, improved, manipulated and essentially anything else you want completely
				freely.  You can even take credit for it, if you want.

				Other people may not know that I wrote it, but I will and so will you ;)

				The others are either Open Source, or are marked as unknown.  Any functions that
				are marked as "Unknown" are open to be used at your own risk, but you are
				certainly encouraged to speak with the original author.

				I hope to write equivalents of the functions that I haven't written, but for now,
				I use existing ones.  Reinventing the wheel and all that.

				In closing, all of these functions have been tested in IE6+, Firefox 2+ for PC and
				Mac.

				Enjoy!

*/

function el(elementID) {

/*

	FUNCTION:	el();

	SYNTAX:		el( elementID );

					elementID:		The ID of the element.  (e.g. 'Navigation')

	NOTES:		This function simplifies calls to functions based on their ID.

				Rather than something like this:

					document.geElementById('Navigation') ...

				You can type this:

					el('Navigation') ...

				Which will compress your code and simplify the whole process.

				NOTE: This function can work as both a query and as a statement.

				For example:

					if(el('man').offsetHeight>6) { ... }	(a query)

						or
					
					el('man').offsetHeight=6;				(a statement)

				'el' is short for Element.  That's all!

	RETURNS:	The object that was selected.

*/

	return document.getElementById(elementID);

}

function es(elementID) {

/*

	FUNCTION:	es();

	SYNTAX:		es( elementID );

					elementID:		The ID of the element.  (e.g. 'Navigation')

	NOTES:		This function is very similar to el(), except that it adds an extra touch
				that refers to the elements *styles*, and not just the element itself.

				So, rather than something like this:

					document.geElementById('Navigation').style ...

				You can type this:

					es('Navigation') ...

				Which will compress your code and simplify the whole process.

				NOTE: This function can work as both a query and as a statement.

				For example:

					if(es('man').height>6) { ... }	(a query)

						or
					
					es('man').height=6;				(a statement)

				'es' is short for Element Style.  That's all!

	RETURNS:	The object that was selected.

*/


	return document.getElementById(elementID).style;

}

function et(tagName) {

/*

	FUNCTION:	et();

	SYNTAX:		et( elementID );

					elementID:		The ID of the element.  (e.g. 'Navigation')

	NOTES:		This function is very similar to el() and es(), except that it selects HTML
				tags, specifically, rather than an individual element based on its attributes.

				For instance, if you wanted to select all the anchor tags, you would do this:

					et('a') ...

				Which is much simpler than:

					document.getElementsByTagName('a') ...

				NOTE:	This function returns an Array, since there are likely going to be multiple
						instances of the tag you specify.  Even if there is only one instance of an
						element, it will still return an Array with a single record.

	RETURNS:	The objects that were selected.

*/

	return document.getElementsByTagName(tagName);
	
}

function ec(node,searchClass) {

/*

	FUNCTION:	ec();

	SYNTAX:		ec( node , searchClass );

					node:			The HTML tags to search through (e.g. a,img,body,*,etc.)
					searchClass:	The Class of the element.  (e.g. 'red')

	NOTES:		This function is very similar to el(), except instead of selecting an element based on
				its ID, it selects elements based on their classes.

				For instance, if you wanted to select every anchor that has a class of, "red" then
				you could do the following:

					allReds = ec('a','red');

				... and then parse it as you see fit.
				

	NOTICE:		This function returns an Array, since there are likely going to be multiple
				instances of the class you specify.  Even if there is only one instance of an
				element, it will still return an Array with a single record.

	RETURNS:	The objects that were selected.

*/

	var classElements = new Array();
	var elClass = new Array();

	classElements=document.getElementsByTagName(node);

	for(i=0,j=0;i<classElements.length;i++) {

		if(classElements[i].className.match(searchClass)) {
			
			elClass[j]=classElements[i];
			j++;

		}

	}

	return elClass;
}

function writeFlashCode(movieName,movieWidth,movieHeight,transToggle) {

/*

	FUNCTION:	writeFlashCode();

	SYNTAX:		writeFlashCode( movieName , movieWidth , movieHeight , transToggle );

					movieName:		The name of the movie file.  (e.g. /swf/movie.swf)
					movieWidth:		The width of the Flash Movie.  (e.g. 320)
					movieHeight:	The height of the Flash Movie.  (e.g. 240)
					transToggle:	'true' makes the background of the movie clip be completely
									transparent.

	NOTES:		This function creates the code necessary for Flash Movies.  It not only saves you
				time and extra typing, but it also will create a Flash Movie that does not require
				the user to click on it to activate it in IE6 and IE7.  Nice little bonus, there.

				NOTE: The quality is always set to "best".  Anyone who does anything less than best
				is dumb and should not be making such *insane* Flash Movies!  Seriously!

				Well, no, not seriously.  You can make an extra variable that you can set for
				quality, I just didn't want 5 arguments when I could have 4.

	RETURNS:	Nothing.  It prints the code to the window.

*/

	document.write('	<object type="application/x-shockwave-flash" quality="best" data="'+movieName+'" width="'+movieWidth+'" height="'+movieHeight+'">');
	document.write('		<param name="movie" value="'+movieName+'">');
	document.write('		<param name="quality" value="best">');

	if(transToggle==true) { document.write('		<param name="wmode" value="transparent">'); }

	document.write ('	</object>');

}

function showElement(elementID) {

/*

	FUNCTION:	showElement();

	SYNTAX:		showElement( elementID );

					elementID:		The ID of the element.  (e.g. 'Navigation')

	NOTES:		This element is created to simplify javascript visual elements.  It just
				forces the element you specify to be visible, regardless of whether or not it
				was before.

	DEPENDENTS:	This function requires the es(); function included with this library.

	RETURNS:	Nothing.

*/

	es(elementID).display="block";

}

function hideElement(elementID) {

/*

	FUNCTION:	hideElement();

	SYNTAX:		hideElement( elementID );

					elementID:		The ID of the element.  (e.g. 'Navigation')

	NOTES:		This element is created to simplify javascript visual elements.  It just
				forces the element you specify to be invisible, regardless of whether or not it
				was before.

	DEPENDENTS:	This function requires the es(); function included with this library.

	RETURNS:	Nothing.

*/

	es(elementID).display="none";

}

function toggleElement(elementID) {

/*

	FUNCTION:	toggleElement();

	SYNTAX:		toggleElement( elementID );

					elementID:		The ID of the element.  (e.g. 'Navigation')

	NOTES:		This element is created to simplify javascript visual elements.  Unlike showElement()
				and hideElement(), this function will check first to see if the element is visible
				or not, and then will act appropriately.

				If the element is visible, then it will make it invisible.
				If the element is invisible, then it will make it visible.

				I actually use this function much more frequently than showElement() and hideElement().

	DEPENDENTS:	This function requires the es(); function included with this library.

	RETURNS:	Nothing.

*/

	if(es(elementID).display=="none" | es(elementID).display=="") { es(elementID).display="block"; } else { es(elementID).display="none"; }

}

function URLEncode(stringToEncode)
{

/*

	FUNCTION:	URLEncode();

	SYNTAX:		URLEncode( stringToEncode );

					stringToEncode:	The String to convert to URL-Encoding.  (e.g. 'This is Great')

	NOTES:		I've used this function for so long that I don't precisely recall where it originated.

				I've made extensive changes to it throughout the years, so use it at your own risk.  Parts of
				it may not be Open Source.

				This function will take any string you give it and convert it to a URL Encoded String.

				For instance, this string:

					This is Great

				Would be converted to:

					This+is+Great

				In order to behave properly in URL's.  This function comes in especially helpful when sending
				custom strings and values to forms and online applications such as Google Maps, etc.

	RETURNS:	The URL Encoded string.

	NOTICE:		If there's a character that cannot be encoded, then the function will alert the user that this
				is the case, but will continue to convert the rest of the string if able.

*/

	s = new String(stringToEncode);
	s.replace("&","%26");

	// The Javascript escape and unescape functions do not correspond
	// with what browsers actually do...
	var SAFECHARS = "0123456789" +					// Numeric
					"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +	// Alphabetic
					"abcdefghijklmnopqrstuvwxyz" +
					"-_.!~*'()";					// RFC2396 Mark characters
	var HEX = "0123456789ABCDEF";

	var plaintext = stringToEncode;
	var encoded = "";
	for (var i = 0; i < plaintext.length; i++ ) {
		var ch = plaintext.charAt(i);
	    if (ch == " ") {
		    encoded += "+";				// x-www-urlencoded, rather than %20
		} else if (SAFECHARS.indexOf(ch) != -1) {
		    encoded += ch;
		} else {
		    var charCode = ch.charCodeAt(0);
			if (charCode > 255) {
			    alert( "Unicode Character '" 
                        + ch 
                        + "' cannot be encoded using standard URL encoding.\n" +
				          "(URL encoding only supports 8-bit characters.)\n" +
						  "A space (+) will be substituted." );
				encoded += "+";
			} else {
				encoded += "%";
				encoded += HEX.charAt((charCode >> 4) & 0xF);
				encoded += HEX.charAt(charCode & 0xF);
			}
		}
	} // for

	return encoded;
}

var xmlhttp;

function ajaxContent(url,elementID)
{

/*

	FUNCTION:	ajaxContent();

	SYNTAX:		ajaxContent( url , elementID );

					url:		The local address to the script you wish to run. (e.g. 'updatecounter.php')
					elementID:	The element in which you wish to show the output from the script.  (e.g. 'counterDiv')

	NOTES:		This is the first of two different types of AJAX functions.  This function will take any output that
				is returned from the script you're running and dump it into an element.  This is especially helpful
				when writing web apps, as it will automatically throw the information where it's needed, without you
				needing to write the extra code.

	RETURNS:	The output from the script you specify, put into an element based on its ID.

	NOTICE:		This code was taken from the w3schools.com.  I've not been able to locate any information regarding
				the ownership of the code, but they do offer it freely.

				So, suffice to say: I DID NOT WRITE THIS, but I very much appreciate them offering it up for usage.

				I did, however, tweak it in order to incorporate the elementID parameter.

				ADDITIONAL NOTE: The function just after this one (called state_change()) is part of this function.

*/

theElementID=elementID;

// code for Mozilla, etc.
if (window.XMLHttpRequest)
  {
  xmlhttp=new XMLHttpRequest()
  xmlhttp.onreadystatechange=state_Change
  xmlhttp.open("GET",url,true)
  xmlhttp.send(null)
  }
// code for IE
else if (window.ActiveXObject)
  {
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP")
    if (xmlhttp)
    {
    xmlhttp.onreadystatechange=state_Change;
    xmlhttp.open("GET",url,true)
    xmlhttp.send()
    }
  }
}

function state_Change()
{

// *******************************************
// state_Change():
// This is part of the ajaxContent() function.
// *******************************************

// if xmlhttp shows "loaded"
if (xmlhttp.readyState==4)
  {
  // if "OK"
  if (xmlhttp.status==200)
  {
	 document.getElementById(theElementID).innerHTML=xmlhttp.responseText;
	 theElementID="";
  }
  }
}

function ajaxRunScript(url,takeThisAction,bonusInfo)
{

/*

	FUNCTION:	ajaxRunScript();

	SYNTAX:		ajaxRunScript( url , takeThisAction , bonusInfo );

					url:		The local address to the script you wish to run. (e.g. 'updatecounter.php')
					takeThisAction:	What to do after the script is run. (e.g. 'reveal')
					bonusInfo:	Additional information that currently just specifies which element to reveal if
								takeThisAction is "reveal". (e.g. 'allDoneGraphic')

	NOTES:		This is the second of two ajax functions.  This one is similar to the first one, except that it offers
				more options as to what to do after the script specified is executed.

				I decided to have two different ajax functions so that I could have one (the first one) that is very
				simple and straight forward and does just what I want, but then to also have the other one (this one)
				offer more options in case I needed them.

				Now, the most complex of parameters is the takeThisAction argument.  You can specify one of the following
				three actions to take:

					toggle		-	Toggles an element on the page.  This comes in especially handy if you have some sort
									of, "Loading..." graphic or <div> on your page.  For instance, you can write a button
									that revelas a "Loading" animated GIF, then have this function toggle it again after
									it's done loading the script on the server.  The "Loading" graphic would stick around
									only aslong as it takes to actually load the script successfully.

									It's pretty sweet.

									NOTE: You must specify the ID of the element to reveal in the bonusInfo option.

					refresh		-	Yes, this negates one of the biggest draws to AJAX, but with this function, you
									can run a script in an iFrame or on the main page, and then refresh to show the
									current page again.  The main draw to this is that you don't *need* an iFrame to
									run a script, or series of scripts, on the server, nor do you have to directly
									link to the script you want to run, you can just do it in Javascript.  It comes in
									more handy than it sounds, I swear!

					print		-	The name of this option isn't entirely accurate.  It doesn't print anything on the
									screen by itself, but it does return the results of the AJAX call.  NOTE: It does
									not return the output from the script (that's what the other AJAX function is for),
									it simply returns the status of the AJAX call.  If there was an error, then this is
									the way to debug it.
									

	RETURNS:	Depends on the actionToTake setting.  If set to print, then it returns the value of the AJAX return
				message.

	NOTICE:		This code was taken from the w3schools.com.  I've not been able to locate any information regarding
				the ownership of the code, but they do offer it freely.

				So, suffice to say: I DID NOT WRITE THIS, but I very much appreciate them offering it up for usage.

				I did, however, tweak it in order to incorporate the elementID parameter.

				ADDITIONAL NOTE: The function just after this one (called state_change2()) is part of this function.

*/


	actionToTake=takeThisAction;
	extraInformation=bonusInfo;

// code for Mozilla, etc.
if (window.XMLHttpRequest)
  {
  xmlhttp=new XMLHttpRequest()
  xmlhttp.onreadystatechange=state_Change2
  xmlhttp.open("GET",url,true)
  xmlhttp.send(null)
  }
// code for IE
else if (window.ActiveXObject)
  {
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP")
    if (xmlhttp)
    {
    xmlhttp.onreadystatechange=state_Change2;
    xmlhttp.open("GET",url,true)
    xmlhttp.send()
    }
  }
}

function state_Change2()
{

// *******************************************
// state_Change2():
// This is part of the ajaxContent() function.
// *******************************************

// if xmlhttp shows "loaded"
if (xmlhttp.readyState==4)
  {
  // if "OK"
  if (xmlhttp.status==200)
  {
	 if(actionToTake=="refresh") { window.location.reload(); }
	 if(actionToTake=="toggle") { toggle(extraInformation); }
	 if(actionToTake=="print") { return xmlhttp.responseText; }
  }
  }
}


function replaceContent(contentCode,elementID) {

/*

	FUNCTION:	replaceContent();

	SYNTAX:		replaceContent( contentCode , elementID );

					contentCode:	The new content for the element. (e.g. 'Hello, World!')
					elementID:		The element in which you want to fill with new content.  (e.g. 'helloWorld')

	NOTES:		This is a very straight forward function that I use quite often.  All you do is spcify an element and some
				content, and it fills that element with the new content.
				
				That's it!

	RETURNS:	Nothing.

*/

	document.getElementById(elementID).innerHTML = contentCode;

}

function debugCode(codeToDebug) {

/*

	FUNCTION:	debugCode();

	SYNTAX:		debugCode( codeToDebug );

					codeToDebug:	The code you wish to debug.

	NOTES:		This is another very simple function.  I use it when I need to see the value of an element.  It's more helpful
				than using, "alert" because it creates it's own little browser window that you can keep around and select the
				text of.
				
				That's it!

	RETURNS:	Nothing.

*/

	openedWindow = window.open("","popup","width=780,height=500,toolbars=no,status=no,scrolling=yes");
	openedWindow.document.write(codeToDebug);

}

function popUp(popUpPage,popUpWidth,popUpHeight,scrollBars) {

/*

	FUNCTION:	popUp();

	SYNTAX:		popUp( popUpPage , popUpWidth , popUpHeight , scrollBars );

					popUpPage:		The URL of the page/file to pop up. (e.g. 'moreinfo.hml?article=151')
					popUpWidth:		The width of the new window. (e.g. 130)
					popUpHeight:	The height of the new window. (e.g. 200)
					scrollBars:		A boolean value of whether or not you want scrollbars. (e.g. false)

	NOTES:		This function will open a new popup window, without requiring you to write a bunch of javascript unnecessarily.
				All you do is specify a few parameters of your window, and it takes care of the rest.

				It can point to images, word documents, html pages, plain text... anything your browser can handle, it can
				pop up.

	RETURNS:	Nothing.

*/

	if(scrollBars==true) { scrollBars="auto"; }

	window.open(popUpPage,'popup','width='+popUpWidth+',height='+popUpHeight+',scrollbars='+scrollBars+',title=no,status=no');

}

function waitAndRedirect(url,timeWait) {

/*

	FUNCTION:	waitAndRedirect();

	SYNTAX:		waitAndRedirect( url , timeWait );

					url:			The URL of the page to redirect to. (e.g. 'index2.html')
					timeWait:		The number of seconds to wait before redirecting. (e.g. 5)

	NOTES:		This function simply waits a set number of seconds and then redirects to a new page.

				This comes in especially handy for, "Please wait, redirecting..." pages.

	RETURNS:	Nothing.

	DEPENDENTS:	This function requires the redirect(); function included with this library.

*/

	setTimeout("redirect('"+url+"');",(timeWait*1000));

}

function redirect(url) {

/*

	FUNCTION:	redirect();

	SYNTAX:		redirect( url );

					url:			The URL of the page to redirect to. (e.g. 'index2.html')

	NOTES:		This function will redirect the user to a new page.  It uses the "window.location" method
				so it retains the History function of the user's browser (as opposed to the location.replace
				method, which takes the page out of the user's history).

	RETURNS:	Nothing.

*/

	window.location.href=url;

}

function isIE() {

	if (parseInt(navigator.appVersion)>3) {

		if (navigator.appName.indexOf("Microsoft")!=-1) {
			return true;
		} else { return false; }

	}

}

function windowWidth() {

/*

	FUNCTION:	windowWidth();

	SYNTAX:		windowWidth( none );

	NOTES:		Simply returns the current width of the browser window.

	RETURNS:	An integer containing the width of the current browser window.

*/

	if (parseInt(navigator.appVersion)>3) {
		if (navigator.appName=="Netscape") {
			return window.innerWidth;
		}

		if (navigator.appName.indexOf("Microsoft")!=-1) {
			return document.body.offsetWidth;
		}
	}

}

function windowHeight() {

/*

	FUNCTION:	windowHeight();

	SYNTAX:		windowHeight( none );

	NOTES:		Simply returns the current height of the browser window.

	RETURNS:	An integer containing the height of the current browser window.

*/

	if (parseInt(navigator.appVersion)>3) {
		if (navigator.appName=="Netscape") {
			return window.innerHeight;
		}

		if (navigator.appName.indexOf("Microsoft")!=-1) {
			return document.body.offsetHeight;
		}
	}

}

function jjPopInit() {

/*

	FUNCTION:	jjPopInit();

	SYNTAX:		jjPopInit( none );

	NOTES:		This is going to be a long 'NOTES' section.

				jjPop is a function that behaves very similarly to LightBox, LightBox 2 and ThickBox
				(all of which are very popular image-viewing javascript libraries).

				The reason I decided to write my own is a combination of a personal challenge, and to
				write something that was much (MUCH) lighter weight than the other ones out there.

				I wanted something extremely straight forward, without all the frills, that would simply
				show an image enlarged in the center of the browser window with a "Close" link and an
				optional image caption (held in the title attribute of the anchor tag).  I have
				accomplished this, and am proud of how tiny it is.

				That said, here is the information:

				This function runs almost entirely on its own.  You need to do the following things for
				jjPop to work (it's very simple):

					1.	Add "jjPop" to the class of a link.  If the anchor tag has no class yet, then
						add one (i.e. class="jjPop").  If there's already a class present, then just add
						jjPop to the list (i.e. class="red jjPop").

					2.	Make the href of the link point to the larger version of the image.  This will give
						jjPop the information it needs, and will also make jjPop backward compatible (i.e.
						on browsers with Javscript turned off, or older browsers).  On browsers where
						Javascript is not enabled for some reason, the links will merely point to larger
						versions of the images contained within.

					3.	Put the thumbnail (or a bit of text describing the image) within the link.

					4.	Give the anchor tag a title if you want an image caption. (optional)

					5.	Done!  When you click on the link/image, a new jjPop window should appear at the
						very center of the browser window, showing an enlarged version of the image you
						chose.

	RETURNS:	Nothing.

	DEPENDENTS:	This function requires the es() and el() functions included with this library.

*/

	allAnchors = ec("a","jjPic");

	totalAnchors=allAnchors.length;

//	Count through each anchor tag on the page, one at a time.

	for(thisAnchor=0;thisAnchor<totalAnchors;thisAnchor++) {

//	... we assign an onClick function, for when the visitor clicks on the link.

//	This is where the magic happens.

	allAnchors[thisAnchor].onclick=function() {

//			First off, the href of the anchor holds the priceless URL of the larger image.  We're gonna have
//			to go ahead and sort of kind of get that.

			linkedIMG=this.href;

//			Oh, and we'll need to get some time variables down, too.  They get tacked onto the end of the ID's
//			we assign to each of these created elements.  By using the time/date in the ID (i.e. jjPic030308, etc.)
//			Then we don't have to worry so much about overlapping ID's.  If we just went with, "popUpPic" or something
//			then there would be a big risk of clashing with an ID already present on the user's page.  Which is bad
//			juju.

			var d = new Date();
			var t = d.getTime();

//			Alright, we've written all of our variables.  Now, let's get crackin' at those new elements!

//			First off, we're going to create the largerIMGDiv, which is the <div> tag that surrounds the larger, popup
//			image.  This will give us a lot more control over how it looks.

			largerIMGDiv=document.createElement("div");
//			Here's that ID I told you about.
			largerIMGDiv.id="jjDiv"+t;
//			We position it absolutely in order to put it at the center of the browser window.
			largerIMGDiv.style.position="absolute";
//			Gotta set that class.  99% of this is just allowing the user of this library to skin the popup any way
//			they want.
			largerIMGDiv.className="jjDiv";
//			This creates a tool tip that will inform the visitor that they can close the popup by clicking on the
//			image itself.
			largerIMGDiv.title="Click image to close popup.";
//			Stupid IE.
			largerIMGDiv.alt="Click image to close popup.";

//			And now for the paragraph tag with the close link!

			largerIMGDivP=document.createElement("p");
			largerIMGDivP.innerHTML="<a href=\"javascript:void(hideElement('"+"jjDiv"+t+"'));\">[x] Close</a>";

//			Fantastic.  Now, let's drop that <div> onto the scene.

			this.parentNode.appendChild(largerIMGDiv);

//			Great.  *Now* let's create our image element (for the larger, pop up image).

			largerIMG=document.createElement("img");
//			Here's that src we needed from before (that was the original anchor's href).
			largerIMG.src=linkedIMG;
//			Hey, this one has a class, too!  What am I, a CSS nutcase?
			largerIMG.className="largerIMG";
//			New ID.  This one is different from the <div> since it's called jjPic instead of jjDiv.
			largerIMG.id="jjPic"+t;

//			Pop that image into there.

			largerIMGDiv.appendChild(largerIMG);

//			Now we have to see if there is a title on the anchor tag to use as an image caption.

//			If so...

			if(this.title) {

//				... let's create a caption.  It goes by the title information on the anchor tag.
					
				imgCaption=this.title;

//				Create the paragraph tag...
				
				largerIMGCaption=document.createElement("p");
//				Add yet another class...
				largerIMGCaption.className="imgCaption";
//				And then put the parent anchor's title into the paragraph as text/html.
				largerIMGCaption.innerHTML=imgCaption;

//				Pop that paragraph into the jjDiv.
					
				largerIMGDiv.appendChild(largerIMGCaption);
				
			}

//			Now put that [close] link into the div, at the very bottom (i.e. pop it in last).

			largerIMGDiv.appendChild(largerIMGDivP);

//			Now for the not-so-much-fun-for-me stuff.  We're gonna put that popup into the middle
//			of the browser window, no matter what their resolution is set to.

//			First, in order to put the image in the middle, we need to get what the full width and
//			height of the window is, and then cut that in half, right?

			winWidth=windowWidth();
			winHeight=windowHeight();

//			Right.  Next, we need to assign a width to the jjDiv.  It will be the same width as the
//			larger image on the inside, but will be just a touch taller.

			el("jjDiv"+t).width=el("jjPic"+t).width;
			el("jjDiv"+t).height=el("jjPic"+t).height+30;

//			Next comes the formula.  It goes like this:

//				Centered = width of window divided by 2,
//				minus width of image, divided by 2.
//
//			... cut both of them in half and you have your centered image!

			imgLeftPosition=(winWidth/2)-(el("jjDiv"+t).width/2);
			imgTopPosition=(winHeight/2)-(el("jjDiv"+t).height/2);				

//			Put the whole ordeal into place.

			es("jjDiv"+t).left=imgLeftPosition;
			es("jjDiv"+t).top=imgTopPosition;

//			Set that onClick function to close the popup if the user clicks on the larger image.

			el("jjPic"+t).onclick=function() { hideElement("jjDiv"+t); };

//			... in closing, don't let that anchor tag do anything.  Just make it popup.

			return false;

		}

	}

}

function jjMenuInit() {

/*

	FUNCTION:	jjMenuInit();

	SYNTAX:		jjMenuInit( none );

	NOTES:		jjMenu is a function that will emulate what CSS2 does naturally, only for IE6.

				As most web developers know, IE6 does not support hovering on any elements except
				for anchor tags.  Most of the time, this is not very inconvenient, however when
				it comes to menus built with embedded lists it's a real headache.

				With CSS alone in Firefox, Opera, Safari, Mozilla, etc. (i.e. any browser that
				supports hovering over elements other than anchor tags) you can create CSS-based
				menus with dropped down, embedded menus.

				For instance:

					+---------+
					| Menu #1 |
					+---------+
					+---------+
					| Menu #2 |
					+---------+

				... then, when hovered over:

					+---------+
					| Menu #1 |
					+---------+
						+-------------+
						| Sub-menu #1 |
						+-------------+
						+-------------+
						| Sub-menu #2 |
						+-------------+
						+-------------+
						| Sub-menu #3 |
						+-------------+
					+---------+
					| Menu #2 |
					+---------+

				This technique, however, requires the ability to hover over elements other than
				anchor tags, as anchor tags cannot contain embedded lists and be considered valid
				X/HTML.

				With jjMenu, however, this is no longer an issue.  You can build your list to work
				in a valid CSS-rendering browser engine (i.e. Firefox, Mozilla, Opera, Safari, etc.)
				with CSS alone, and then to make it work in IE6, as well, all you need to do is add
				"jjMenu" as a class to the container around your menu.

				For example:

					<div class="nav jjMenu" id="topNav">

						<ul>

							<li> ...
								
								<ul class="subMenu">
									<li> ... </li>
								</ul>

							</li>

						</ul>

					</div>

				... and it will behave the same in IE6 as it does in the properly rendering 
				browser engines.  It's that simple!

				NOTE: You *MUST* put the class of "jjMenu" onto the container AROUND your <ul>'s, not
				on the <ul>'s themselves.  If you put the class on a <ul> tag that is part of the menu
				itself, then it will not be able to properly find the embedded lists.  YOU'VE BEEN
				WARNED!
					

	RETURNS:	Nothing.

	DEPENDENTS:	This function requires the ec() and el() functions included with this library.

*/

	if(isIE()) {

//		Grab all elements with a class of, "jjMenu".

		theMenus=ec("*","jjMenu");

//		Run through each one...
	
		for(i=0;i<theMenus.length;i++) {

//			Grab the dates to tack onto the end of the ID's of the menus.
	
			var d = new Date();
			var t = d.getTime();

//			Add forementioned ID's with timestamp (to make them near-unique).
	
			theMenus[i].id="jjMenu"+t;

//			Convert the item into an object so we can take a turn to Object Oriented Programming.

			menuObject = el("jjMenu"+t);

//			Grab all the <ul> tags within the menu.
	
			menuLists=menuObject.getElementsByTagName("ul");

//			Run through each one.
	
			for(ii=0;ii<menuLists.length;ii++) {

//				Grab each <li> tag within the <ul> tag.
	
				menuListItems = menuLists[ii].getElementsByTagName("li");

//				Run through all of *those*.
	
				for(iii=0;iii<menuListItems.length;iii++) {

//					Grab the content of each <li> tag.
	
					liContent = menuListItems[iii].innerHTML;

//					Check to see if there are any embedded lists within...
	
					if (liContent.match("<UL") || liContent.match("<ul")) {

//						If there are embedded lists, then...
	
						menuListItems[iii].onmouseover=function() {

//							Make the top one visible when the parent <li> is hovered over.
	
							liUL=this.getElementsByTagName("ul");	
							liUL[0].style.display="block";
	
						}
	
						menuListItems[iii].onmouseout=function() {

//							Make it invisible when the parent <li> is no longer hovered over.
	
							liUL=this.getElementsByTagName("ul");	
							liUL[0].style.display="none";
	
						}
	
					}
	
				}		
	
			}
	
		}

	}
	
}

function jjPreviewInit() {

/*

	FUNCTION:	jjPreviewInit();

	SYNTAX:		jjPreviewInit( none );

	NOTES:		jjPreview is a function that allows you to attach small preview windows to any link
				on your site.

				In order to make the preview window appear when you hover over a link, you must add
				"jjPreview" to that anchor's tag list.  This option only works on anchor tags, and it
				determines the preview's location based on the href of the anchor tag.

				Therefore, if you wish to offer a preview of an external site, or an image, or anything
				else, you must add class="jjPreview" or add "jjPreview" to whatever classes already exist.

				The preview window itself is fully skinnable via CSS.  The positioning is absolute by
				default, but a simple "position: relative !important" should override that easily.
				
				It has a class name of, "jjPreviewDiv".

				By default, the jjPreview window will be visible until the user rolls their mouse off
				of the preview and the original anchor tag.  If the user clicks on the preview, then
				it opens the anchor tag as though *it* was clicked on.  Therefore, any target=""'s or
				rel=""'s or anything else will carry on through and still apply.

	RETURNS:	Nothing.

	DEPENDENTS:	This function requires the ec() and es() functions included with this library.

*/

//	Grab all anchor tags with a class of jjPreview.

	allLinks=ec("a","jjPreview");

//	Go through them all...

	for(i=0;i<allLinks.length;i++) {

//		Create the preview <div>'s and hide them.

		previewDiv=document.createElement("div");
		previewDiv.className="jjPreviewDiv";
		previewDiv.id="jjPreviewDiv"+i;
		previewDiv.style.display="none";
		previewDiv.style.position="absolute";

//		Set the Rel of each anchor tag to jjP# (where # is the order of anchor tags)

		allLinks[i].rel="jjP"+i;

//		Add the preview <div> to the anchor tag.

		allLinks[i].appendChild(previewDiv);

//		Create the iFrame that contains the preview.

		previewIFrame=document.createElement("iframe");
		previewIFrame.src=allLinks[i].href;
		previewIFrame.frameBorder=0;

//		Add the iFrame to the preview <div>.

		previewDiv.appendChild(previewIFrame);

//		Add mouse events.  If the user rolls over the preview anchor...

		allLinks[i].onmouseover=function() {

//			Display the preview <div>.

			anchorNum=this.rel.substr(3);
			es("jjPreviewDiv"+anchorNum).display="block";

		}

//		If the user rolls off of the preview anchor...

		allLinks[i].onmouseout=function() {

//			Hide the preview <div>.

			anchorNum=this.rel.substr(3);
			es("jjPreviewDiv"+anchorNum).display="none";
			
		}

	}

}

function jjTableInit() {

/*

	FUNCTION:	jjTableInit();

	SYNTAX:		jjTableInit( none );

	NOTES:		This function facilitates more control over your tables with CSS.

				By default, you're stuck with very few controls over your tables with CSS unless
				you go in and insert a ton of classes and id's to each row, column, etc.  So, instead
				of inserting all that (and in the interest of unobtrusive javascript), this function
				will insert all of that information for you (and more!).

				You are free to write an extremely basic table in your HTML.  You don't even need
				to add in the ubiquitous: border="0" cellspacing="0" cellpadding="0".  This function
				will remove all of those elements for you, and allow you to spruce it up using your CSS
				wizardry instead.

				What it does, exactly, is add a class of "r#" to each <tr> (where # is the number of row)
				and "c#" to each <td> (where # is the number of column).  Then, in your CSS you can apply
				colors, graphics, backgrounds, borders, etc. to paint your table any way you like.

				For example:

				<table class="jjTable">
					<tr>
						<td>Cost</td>
						<td>Quantity</td>
						<td>SKU #</td>
					</tr>
					<tr>
						<td>$15</td>
						<td>236</td>
						<td>kr30</td>
					</tr>
					<tr>
						<td>$27</td>
						<td>77</td>
						<td>ey02</td>
					</tr>
					<tr>
						<td>$637</td>
						<td>10</td>
						<td>pe13</td>
					</tr>
				</table>

				... would automatically translate to this when the page renders:

				<table class="jjTable">
					<tr class="r1">
						<td class="c1">Cost</td>
						<td class="c2">Quantity</td>
						<td class="c3">SKU #</td>
					</tr>
					<tr class="r2">
						<td class="c1">$15</td>
						<td class="c2">236</td>
						<td class="c3">kr30</td>
					</tr>
					<tr class="r3">
						<td class="c1">$27</td>
						<td class="c2">77</td>
						<td class="c3">ey02</td>
					</tr>
					<tr class="r4">
						<td class="c1">$637</td>
						<td class="c2">10</td>
						<td class="c3">pe13</td>
					</tr>
				</table>

				... after which time you could apply special colors and font sizes to the
				top row to designated it your "Title Row" with the following CSS:

					.r1 td { background: #00a; color: #fff; font-weight: bold; }

				The styles would only apply to the top row, without any sort of HTML designation.
				You can apply the same logic to each column or only certain columns.

				FUTURE ADDITIONS: Odd and Even row designations.

	RETURNS:	Nothing.

	DEPENDENTS:	This function requires the ec() functions included with this library.

*/

//	Grab all <table>s that have a class of, "jjTable".

	prettyTable=ec("table","jjTable");

//	Run through them all.

	for(i=0;i<prettyTable.length;i++) {

//		Take off borders, cellspacing and cellpadding so that CSS can take care of these.

		prettyTable[i].borderWidth=0;
		prettyTable[i].cellPadding=0;
		prettyTable[i].cellSpacing=0;

//		Grab each <tr> tag to sort them as r1, r2, r3, etc.

		TRs=prettyTable[i].getElementsByTagName("tr");

//		Run through them all.

		for(t=0;t<TRs.length;t++) {

//			Give each row a class that corresponds to where the <tr> is in the table.  The first one is given a class
//			of, "r1" and the second as "r2" and so forth.

			TRs[t].className="r"+(t+1);

//			... but it doesn't end there.  Let's grab the <td> tags, too.

			TDs=TRs[t].getElementsByTagName("td");

//			And run through them, of course.

			for(tt=0;tt<TDs.length;tt++) {

//				And apply c1, c2, c3, etc. classes to designate columns.

				TDs[tt].className="c"+(tt+1);

			}

		}

	}

}

// This is what runs when the page  loads.

window.onload=function(){

	//	Initialize all jjLib passive functions.

	jjPopInit();
	jjMenuInit();
	jjPreviewInit();
	jjTableInit();

}