//====================================================================================================================
//  ##  #   ###                     filename:      act_api.js
// #  # #   #                       last update:   23 July 2002 by Daniel Pupius
// #### #   ##   Act                description:   Abstracts certain interactions with the browser.  All functions
// #  # #   #    Learning                          are compatible with version 4 browsers and up, but some effects
// #  # ### #	 Framework                         and functionality will be lost in the earlier browsers.
//====================================================================================================================
//                                                                          [Based on the 13thAPI @ 13thparallel.org]



//object constructor for ACT DHTML library
var ACT = {

	//=========================================================================================================\\
	// SUPPORT FUNCTIONS (used by the higher-level functions to access the various browser's DOM)              \\
	//=========================================================================================================\\


				//Crossbrowser code to grab an id-based dom object
	getElement:		function(id) {
				  if(document.getElementById) return document.getElementById(id);	//DOM based browsers
				  else if(document.all) return document.all[id];			//Internet Explorer 4
				  else if(document.layers) return ACT.find(id);				//Netscape 4
				  else return null;							//Other browsers
				},


				//Crossbrowser code to grab the styles for an id-based dom object
	getStyles:		function(id) {
				  if(document.getElementById) return document.getElementById(id).style;	//DOM based browsers
				  else if(document.all) return document.all[id].style;			//Internet Explorer 4
				  else if(document.layers) return ACT.find(id);				//Netscape 4
				  else return null;							//Other browsers
				},


				//returns the x position of a layer
	x:			function(id) {
				  return parseInt(ACT.getStyles(id).left);
				},

				//returns the y position of a layer
	y:			function(id) {
				  return parseInt(ACT.getStyles(id).top);
				},

				//returns the width of a layer (as specified in the style-sheet or style-tag)
	w:			function(id) {
				  return parseInt(ACT.getStyles(id).width);
				},

				//returns the height of a layer (as specified in the style-sheet or style-tag)
	h:			function(id) {
				  return parseInt(ACT.getStyles(id).height);
				},



	//=========================================================================================================\\
	// BASIC FUNCTIONS (a set of simple functions to manipulate layers)                                        \\
	//=========================================================================================================\\

				//moves a layer to a specific screen coordinate
	moveTo:			function(id,x,y) {
				  if(document.getElementById) var unit = "px";
				  else var unit = 0;

				  ACT.getStyles(id).left = parseInt(x) + unit;
				  ACT.getStyles(id).top = parseInt(y) + unit;
				},

				//clips a layer to specific dimentions
	clipTo:			function(id,x,y,w,h) {
				  if(document.getElementById) var unit = "px";
				  else var unit = 0;

				  if(document.layers) {
				    ACT.getStyles(id).clip.top = y;
				    ACT.getStyles(id).clip.left = x;
				    ACT.getStyles(id).clip.bottom = y+h;
				    ACT.getStyles(id).clip.right = x+w;
				  } else
				    ACT.getStyles(id).clip = "rect(" + x + unit + " " + (x+w) + unit + " " + (y+h) + unit + " " + y + unit + ")";
				},

	resizeTo:			function(id,w,h) {
				  if(document.getElementById) var unit = "px";
				  else var unit = 0;

				  ACT.getStyles(id).height =  parseInt(h) + unit;
				  ACT.getStyles(id).width =  parseInt(w) + unit;
				},

				//moves a layer to by a specific number of units
	moveBy:			function(id,x,y) {
				  if(document.getElementById) var unit = "px";
				  else var unit = 0;

				  ACT.getStyles(id).left = (ACT.x(id) + x) + unit;
				  ACT.getStyles(id).top = (ACT.y(id) + y) + unit;
				},

				//shows a layer (with the optional ability to fade between states)
	show:			function(id, fade) {
				  var ie55 = (navigator.appVersion.indexOf("MSIE 5.5")>-1 && document.getElementById && !navigator.userAgent.indexOf("Opera")>-1 )?1:0;
				  var ie6 = (navigator.appVersion.indexOf("MSIE 6")>-1 && document.getElementById && !navigator.userAgent.indexOf("Opera")>-1 )?1:0;

				  if((ie55 || ie6) && fade) {
				    ACT.getStyles(id).filter = "progid:DXImageTransform.Microsoft.Fade(duration=" + fade + ")";
				    ACT.getElement(id).filters[0].apply();
				    ACT.getStyles(id).visibility = "visible";
				    ACT.getElement(id).filters[0].play();
				  } else {
				    ACT.getStyles(id).visibility = "visible";
				  }
				},

				//hides a layer
	hide:			function(id, fade) {
				  var ie55 = (navigator.appVersion.indexOf("MSIE 5.5")>-1 && document.getElementById && !navigator.userAgent.indexOf("Opera")>-1 )?1:0;
				  var ie6 = (navigator.appVersion.indexOf("MSIE 6")>-1 && document.getElementById && !navigator.userAgent.indexOf("Opera")>-1 )?1:0;

				  if((ie55 || ie6) && fade) {
				    ACT.getStyles(id).filter = "progid:DXImageTransform.Microsoft.Fade(duration=" + fade + ")";
				    ACT.getElement(id).filters[0].apply();
				    ACT.getStyles(id).visibility = "hidden";
				    ACT.getElement(id).filters[0].play();
				  } else {
				    ACT.getStyles(id).visibility = "hidden";
				  }
				},

				//toggles the visibility
	toggle:			function(id, fade) {
				  if(!fade) var fade = 0;
				  if(ACT.getStyles(id).visibility == "" || ACT.getStyles(id).visibility == "inherit" || ACT.getStyles(id).visibility == "show" || ACT.getStyles(id).visibility == "visible") ACT.hide(id, fade);
				  else ACT.show(id, fade);
				},

				//changes the background colour of a layer
	bgColor:		function(id,c) {
				  if(document.layers) ACT.getStyles(id).bgColor = c;
				  else ACT.getStyles(id).backgroundColor = c;
				},

				//changes the foreground colour of a layer
	color:			function(id,c) {
				  ACT.getStyles(id).color = c;
				},



	//=========================================================================================================\\
	// TIMESLIDE (Moves a layer between 2-points over a specified duration)                                    \\
	//=========================================================================================================\\

	moves:			new Array(),
	cancelMoves:		new Array(),
	moving:			new Array(),

	timeSlide:		function(id,x,y,duration,acc,func,cancel,timeout) {

					//clean up input - added by MU 23/10/02
					x = parseInt(x);
					y = parseInt(y);
					duration = parseInt(duration);
					acc = parseFloat(acc);
					//end clean up input
				  if(!cancel) var cancel = false;
				  if(!func) var func = "null";
				  if(!timeout) var timeout = 5;
				  if(!acc) var acc = 0;

				  if(!ACT.moves[id]) ACT.moves[id] = new Array();
				  if(!ACT.cancelMoves[id]) ACT.cancelMoves[id] = false;
				  if(!ACT.moving[id]) ACT.moving[id] = false;

				  var startTime = new Date().valueOf();
				  var endTime = startTime + duration;

				  if(!ACT.moving[id]) {	//object isn't already moving so start animation
				    ACT.moving[id] = true;
				    ACT.timeSlideAux(id,ACT.x(id),ACT.y(id),x,y,acc,startTime,endTime,func,cancel,timeout);
				  } else {
				    if(cancel) {		//cancel other moves
				      ACT.cancelMoves[id] = true;
				      ACT.moves[id] = new Array();
				    }

				    //add this movement to array of movements
				    var strExec = "ACT.timeSlide('" + id + "'," + x + "," + y + "," + duration + "," + acc + ",'" + func + "'," + cancel + "," + timeout + ")";
				    ACT.moves[id].push(strExec);
				  }
				},

	timeSlideAux:		function(id,startX,startY,endX,endY,acc,startTime,endTime,func,cancel,timeout) {

				  var curTime = new Date().valueOf();
				  if(ACT.cancelMoves[id]) {
				    ACT.moving[id] = false;
				    ACT.cancelMoves[id] = false;
				    if(ACT.moves[id][0]) eval(ACT.moves[id].shift());

				  } else if(curTime >= endTime) {
				    ACT.moveTo(id,endX,endY);
				    ACT.moving[id] = false;
				    if(func) eval(func);
				    if(ACT.moves[id][0]) eval(ACT.moves[id].shift());

				  } else {
				    var percent = (curTime - startTime) / (endTime - startTime); //percentage of way through animation
				    var startPos = new ACT.coord(1,1);
				    var endPos = new ACT.coord(0,0);

				    if(acc!=0) var c1 = new ACT.coord(0.5+(acc/2),0.5-(acc/2));
				    else c1 = null;
				    var pos = ACT.getBezier(percent,startPos,endPos,c1);
				    var stage = pos.y;

				    ACT.moveTo(id,((endX-startX)*stage)+startX,((endY-startY)*stage)+startY);

				    var strExec = "ACT.timeSlideAux('" + id + "'," + startX + "," + startY + "," + endX + "," + endY + "," + acc + "," + startTime + "," + endTime + ",'" + func + "'," + cancel + "," + timeout + ")";
				    setTimeout(strExec,timeout);
				  }
				},



	//=========================================================================================================\\
	// BEZIER SLIDE (Allows you to moves a layer between 2-points, along a curve over a specified duration)    \\
	//=========================================================================================================\\

	bezierSlide:		function(id,x,y,c1x,c1y,c2x,c2y,duration,acc,func,cancel,timeout) {
				  if(!cancel) var cancel = false;
				  if(!func) var func = "null";
				  if(!timeout) var timeout = 5;
				  if(!acc) var acc = 0;

				  if(!ACT.moves[id]) ACT.moves[id] = new Array();
				  if(!ACT.cancelMoves[id]) ACT.cancelMoves[id] = false;
				  if(!ACT.moving[id]) ACT.moving[id] = false;

				  var startTime = new Date().valueOf();
				  var endTime = startTime + duration;

				  if(!this.moving[id]) {	//object isn't already moving so start animation
				    ACT.moving[id] = true;
				    ACT.bezierSlideAux(id,ACT.x(id),ACT.y(id),x,y,c1x,c1y,c2x,c2y,acc,startTime,endTime,func,cancel,timeout);
				  } else {
				    if(cancel) {		//cancel other moves
				      ACT.cancelMoves[id] = true;
				      ACT.moves[id] = new Array();
				    }
				    //add this movement to array of movements
				    var strExec = "ACT.bezierSlide('" + id + "'," + x + "," + y + "," + c1x + "," + c1y + "," + c2x + "," + c2y + "," + duration + "," + acc + ",'" + func + "'," + cancel + "," + timeout + ")";
				    ACT.moves[id].push(strExec);
				  }
				},

	bezierSlideAux:		function(id,startX,startY,endX,endY,c1x,c1y,c2x,c2y,acc,startTime,endTime,func,cancel,timeout) {
				  var curTime = new Date().valueOf();
				  if(ACT.cancelMoves[id]) {
				    ACT.moving[id] = false;
				    ACT.cancelMoves[id] = false;
				    if(ACT.moves[id][0]) eval(ACT.moves[id].shift());

				  } else if(curTime >= endTime) {
				    ACT.moveTo(id,endX,endY);
				    ACT.moving[id] = false;
				    if(func) eval(func);
				    if(ACT.moves[id][0]) eval(ACT.moves[id].shift());

				  } else {
				    var percent = (curTime - startTime) / (endTime - startTime); //percentage of way through animation
				    var startPos = new ACT.coord(0,0);
				    var endPos = new ACT.coord(1,1);

				    if(acc!=0) var c1 = new ACT.coord(0.5-(acc/2),0.5+(acc/2));
				    else c1 = null;
				    var pos = ACT.getBezier(percent,startPos,endPos,c1);
				    var stage = pos.y;

				    var startPos = new ACT.coord(startX,startY);
				    var endPos = new ACT.coord(endX,endY);
				    var c1 = new ACT.coord(c1x,c1y);
				    var c2 = new ACT.coord(c2x,c2y);
				    var pos = ACT.getBezier(stage,startPos,endPos,c1,c2);
				    ACT.moveTo(id,pos.x,pos.y);

				    var strExec = "ACT.bezierSlideAux('" + id + "'," + startX + "," + startY + "," + endX + "," + endY + "," + c1x + "," + c1y + "," + c2x + "," + c2y + "," + acc + "," + startTime + "," + endTime + ",'" + func + "'," + cancel + "," + timeout + ")";
				    setTimeout(strExec,timeout);
				  }
				},



	//=========================================================================================================\\
	// TIMECLIP (Clips a layer between 2 sizes)                                                                \\
	//=========================================================================================================\\

	clips:			new Array(),
	cancelClips:		new Array(),
	clipping:		new Array(),

	timeClip:		function(id,x,y,w,h,duration,acc,func,cancel,timeout) {
				  if(!cancel) var cancel = false;
				  if(!func) var func = "null";
				  if(!timeout) var timeout = 5;
				  if(!acc) var acc = 0;

				  if(!ACT.clips[id]) ACT.clips[id] = new Array();
				  if(!ACT.cancelClips[id]) ACT.cancelClips[id] = false;
				  if(!ACT.clipping[id]) ACT.clipping[id] = false;


				  if(!document.layers) {
				    var c = ACT.getStyles(id).clip.split('(')[1].split(' ');
  				    for(var i=0;i<4;i++){ c[i] = parseInt(c[i]); }
				  } else var c = new Array();

				  var ct = ACT.getStyles(id).clip.top||c[0]||0;
				  var cr = ACT.getStyles(id).clip.right||c[1]||0;
				  var cb = ACT.getStyles(id).clip.bottom||c[2]||0;
				  var cl = ACT.getStyles(id).clip.left||c[3]||0;

				  var startTime = new Date().valueOf();
				  var endTime = startTime + duration;

				  if(!ACT.clipping[id]) {	//object isn't already moving so start animation
				    ACT.clipping[id] = true;
				    ACT.timeClipAux(id,cl,ct,cr-cl,cb-ct,x,y,w,h,acc,startTime,endTime,func,cancel,timeout);
				  } else {
				    if(cancel) {		//cancel other moves
				      ACT.cancelclips[id] = true;
				      ACT.clips[id] = new Array();
				    }
				    //add this movement to array of movements
				    var strExec = "ACT.timeClip('" + id + "'," + x + "," + y + "," + w + "," + h + ","+ duration + "," + acc + ",'" + func + "'," + cancel + "," + timeout + ")";
				    ACT.clips[id].push(strExec);
				  }
				},

	timeClipAux:		function(id,startX,startY,startW,startH,endX,endY,endW,endH,acc,startTime,endTime,func,cancel,timeout) {
				  var curTime = new Date().valueOf();
				  if(ACT.cancelClips[id]) {
				    ACT.clipping[id] = false;
				    ACT.cancelClips[id] = false;
				    if(ACT.clips[id][0]) eval(ACT.clips[id].shift());

				  } else if(curTime >= endTime) {
				    ACT.clipTo(id,endX,endY,endW,endH);
				    ACT.clipping[id] = false;
				    if(func) eval(func);
				    if(ACT.clips[id][0]) eval(ACT.clips[id].shift());

				  } else {
				    var percent = (curTime - startTime) / (endTime - startTime); //percentage of way through animation
				    var startPos = new ACT.coord(1,1);
				    var endPos = new ACT.coord(0,0);

				    if(acc!=0) var c1 = new ACT.coord(0.5+(acc/2),0.5-(acc/2));
				    else c1 = null;
				    var pos = ACT.getBezier(percent,startPos,endPos,c1);
				    var stage = pos.y;

				    ACT.clipTo(id,((endX-startX)*stage)+startX,((endY-startY)*stage)+startY,((endW-startW)*stage)+startW,((endH-startH)*stage)+startH);

				    var strExec = "ACT.timeClipAux('" + id + "'," + startX + "," + startY + "," + startW + "," + startH + "," + endX + "," + endY + "," + endW + "," + endH + "," + acc + "," + startTime + "," + endTime + ",'" + func + "'," + cancel + "," + timeout + ")";
				    setTimeout(strExec,timeout);
				  }
				},


	//=========================================================================================================\\
	// TIMEReSIZE (Resizes as layer)                                                                             \\
	//=========================================================================================================\\

	resizes:		new Array(),
	cancelResize:		new Array(),
	resizing:		new Array(),

	timeResize:		function(id,w,h,duration,acc,func,cancel,timeout) {
				  if(!cancel) var cancel = false;
				  if(!func) var func = "null";
				  if(!timeout) var timeout = 5;
				  if(!acc) var acc = 0;

				  if(!ACT.resizes[id]) ACT.resizes[id] = new Array();
				  if(!ACT.cancelResize[id]) ACT.cancelResize[id] = false;
				  if(!ACT.resizing[id]) ACT.resizing[id] = false;

				  var startTime = new Date().valueOf();
				  var endTime = startTime + duration;

				  if(!ACT.resizing[id]) {	//object isn't already moving so start animation
				    ACT.resizing[id] = true;
				    ACT.timeResizeAux(id,ACT.w(id),ACT.h(id),w,h,acc,startTime,endTime,func,cancel,timeout);
				  } else {
				    if(cancel) {		//cancel other moves
				      ACT.cancelResize[id] = true;
				      ACT.resizes[id] = new Array();
				    }

				    //add this movement to array of movements
				    var strExec = "ACT.timeResize('" + id + "'," + w + "," + h + "," + duration + "," + acc + ",'" + func + "'," + cancel + "," + timeout + ")";
				    ACT.resizes[id].push(strExec);
				  }
				},

	timeResizeAux:		function(id,startW,startH,endW,endH,acc,startTime,endTime,func,cancel,timeout) {

				  var curTime = new Date().valueOf();
				  if(ACT.cancelResize[id]) {
				    ACT.resizing[id] = false;
				    ACT.cancelResize[id] = false;
				    if(ACT.resizes[id][0]) eval(ACT.resizes[id].shift());

				  } else if(curTime >= endTime) {
				    ACT.resizeTo(id,endW,endH);
				    ACT.resizing[id] = false;
				    if(func) eval(func);
				    if(ACT.resizes[id][0]) eval(ACT.resizes[id].shift());

				  } else {
				    var percent = (curTime - startTime) / (endTime - startTime); //percentage of way through animation
				    var startPos = new ACT.coord(1,1);
				    var endPos = new ACT.coord(0,0);

				    if(acc!=0) var c1 = new ACT.coord(0.5+(acc/2),0.5-(acc/2));
				    else c1 = null;
				    var pos = ACT.getBezier(percent,startPos,endPos,c1);
				    var stage = pos.y;

				    ACT.resizeTo(id,((endW-startW)*stage)+startW,((endH-startH)*stage)+startH);

				    var strExec = "ACT.timeResizeAux('" + id + "'," + startW + "," + startH + "," + endW + "," + endH + "," + acc + "," + startTime + "," + endTime + ",'" + func + "'," + cancel + "," + timeout + ")";
				    setTimeout(strExec,timeout);
				  }
				},



	//=========================================================================================================\\
	// BEZIER (Used for calculations based on a cubic Bezier curve)                                            \\
	//=========================================================================================================\\

	B1:			function(t) { return (t*t*t); },
	B2:			function(t) { return (3*t*t*(1-t)); },
	B3:			function(t) { return (3*t*(1-t)*(1-t)); },
	B4:			function(t) { return ((1-t)*(1-t)*(1-t)); },

	coord:			function (x,y) { if(!x) var x=0; if(!y) var y=0; return {x: x, y: y}; },

	getBezier:		function (percent,startPos,endPos,control1,control2) {
				  //if there aren't any extra control points plot a straight line, if there is only 1
				  //make 2nd point same as 1st

				  if(!control2 && !control1) var control2 = new ACT.coord(startPos.x + 3*(endPos.x-startPos.x)/4, startPos.y + 3*(endPos.y-startPos.y)/4);
				  if(!control2) var control2 = control1;
				  if(!control1) var control1 = new ACT.coord(startPos.x + (endPos.x-startPos.x)/4, startPos.y + (endPos.y-startPos.y)/4);

				  var pos = new ACT.coord();
				  pos.x = startPos.x * ACT.B1(percent) + control1.x * ACT.B2(percent) + control2.x * ACT.B3(percent) + endPos.x * ACT.B4(percent);
				  pos.y = startPos.y * ACT.B1(percent) + control1.y * ACT.B2(percent) + control2.y * ACT.B3(percent) + endPos.y * ACT.B4(percent);

				  return pos;
				},



	//=========================================================================================================\\
	// SCHEDULER (Acts like a text based timeline, allowing the user to specify when things happen)            \\
	//=========================================================================================================\\

	state:			0,
	running:		0,
	nextState:		function() { ACT.state++; },
	jumpToState:		function(n) { ACT.state=n; },
	jobs:			new Array(),

	schedule:		function(code, time, state) {
				  var thisJob = [code,time,state,false];
				  ACT.jobs.push(thisJob);
				  //alert(ACT.jobs);
				},
	startScheduler:		function() { ACT.running=1; ACT.idle(); },
	stopScheduler:		function() { ACT.running=0; },
	idle:			function() {
				  if(ACT.running) {
				    for(var i=0; i<ACT.jobs.length; i++) {
				      if(ACT.jobs[i][2] == ACT.state && !ACT.jobs[i][3]) {
				        ACT.jobs[i][3] = true;
				        setTimeout(ACT.jobs[i][0],ACT.jobs[i][1]*1000);
				      }
				    }
				    setTimeout("ACT.idle()",50);
				  }
				},



	//=========================================================================================================\\
	// COOKIES (Allows you to save and retrieve page settings)                                                 \\
	//=========================================================================================================\\

	getCookie:		function(name, d) {
				  if (!d) var d = null;
				  var arg = name + "=";
				  var alen = arg.length;
				  var clen = document.cookie.length;
				  var i = 0;
				  while (i < clen) {
				    var j = i + alen;
				    if (document.cookie.substring(i, j) == arg) {
				      var endstr = document.cookie.indexOf (";", j);
				      if (endstr == -1) endstr = document.cookie.length;
				      return unescape(document.cookie.substring(j, endstr));
 				    }
				    i = document.cookie.indexOf(" ", i) + 1;
				    if (i == 0) break;
				  }
				  return d;
				},

	setCookie:		function(name, value, expires) {
				  if (expires) {
				    var exp = new Date();
				    exp.setTime(exp.getTime() + (expires*60*60*1000));
				    expires = exp;
				  }
				  document.cookie = name + "=" + escape(value) + ((expires == null) ? "" : ("; expires=" + expires.toGMTString()));
				},

	deleteCookie:		function(name) {
				  var exp = new Date();
				  exp.setTime (exp.getTime() - 1000);
				  var cval = ACT.getCookie (name);
				  document.cookie = name + "=" + cval + "; expires=" + exp.toGMTString();
	},



	//=========================================================================================================\\
	// IMAGES (Functions for preloading images, and creating rollovers)                                        \\
	//=========================================================================================================\\


	images:			new Array(),		//used to store precached images
	rollovers:		new Array(),		//used to store rollovers

				//preloads image(s)
	preload:		function() {
				  for(var i=0; i<arguments.length; i++) {
				    var img = new Image();
				    img.src = arguments[i];
				    ACT.images.push(img);
				  }
				},

				//creates a rollover, events are added to "caller" and affect "target"
	makeRollover:		function(target,caller,onImage) {
				  var offImage = ACT.findImg(target).src;
				  ACT.preload(onImage,offImage);
				  ACT.rollovers[caller] = {target: target, on: onImage, off: offImage};
				  ACT.getElement(caller).onmouseover = function() {
				    if(ACT.rollovers[this.id]) {
				      ACT.findImg(ACT.rollovers[this.id].target).src = ACT.rollovers[this.id].on;
				    }
				  }
				  ACT.getElement(caller).onmouseout = function() {
				    if(ACT.rollovers[this.id]) {
				      ACT.findImg(ACT.rollovers[this.id].target).src = ACT.rollovers[this.id].off;
				    }
				  }

				  if(document.layers) {
				    ACT.getElement(caller).captureEvents(Event.MOUSEOVER);
				    ACT.getElement(caller).captureEvents(Event.MOUSEOUT);
				  }
				},

	imgSwap:		function(target,img) {
				  if(ACT.findImg(target)) ACT.findImg(target).src = img;
				},


	//=========================================================================================================\\
	// GRAPHICS (Draws lines etc.)                                                                             \\
	//=========================================================================================================\\
	drawLine:		function(id,x,y) {




				},



	//=========================================================================================================\\
	// MISC (Random helper functions)                                                                          \\
	//=========================================================================================================\\

				//Opens a new page in current browser window
	redirect:		function(url) { location=url; },

				//Creates a popup window with options to set the appearance
	popup:			function(filename, title, width, height, x, y,scrollbars,statusbar,resize,toolbar) {
				  if(x=='c') x = (screen.width / 2) - (width / 2);
				  if(y=='c') y = (screen.height / 2) - (height / 2);


				  if(scrollbars == null) scrollbars=1;
				  if(statusbar == null) statusbar=0;
				  if(resize == null) resize=0;
				  if(toolbar == null) toolbar=0;

				  NewWindow = window.open(filename, title, "status="+statusbar+",scrollbars="+scrollbars+",resizable="+resize+",toolbar="+toolbar+",menubar="+toolbar+",width="+width+",height="+height+",left="+x+",top="+y);

				  if(!NewWindow.opener) {
				    NewWindow.opener = self;
				  }
				},

				//returns a random number between x and y (integers)
	rand:			function(x,y) { return (round(Math.random()*(y-x)) + x); },

				//converts degrees to radians and vice versa (used in conjunction with the Math object's trig functions)
	degToRad:		function(x) { return ( x/(360/(2*pi)) ); },
	radToDeg:		function(x) { return ( x*(360/(2*pi)) ); },



				// A function by: Michael van Ouwerkerk,  February 9 2002,  Updated for frames capability at March 19, 2002
				// find takes an id string as argument and returns a js reference to the image.
				// This method is used primarily for Netscape 4, to automatically find images that are nested in layers.
				// It can now also find an image in a frame, if the frame's name is given in the function call.
				// Example: ACT.find('imgMinimalsm', 'mainFrame')
	find:			function(id, frame, d) {
				  var img = null;
				  if (!d) {
				    if (frame && top[frame]) d = top[frame].document;
				    else d = document;
				    if (!d) return null;
				  }
				  if (d.layers) {
				    img = d.layers[id];
				    if(!img) img = d.links[id];
				    if(!img) img = d.images[id];
				  }
				  else if (d.getElementById) img = d.getElementById(id);
				  for (var i=0; !img && d.layers && i<d.layers.length; i++){
				    img = ACT.find(id, null, d.layers[i].document);
				  }
				  return img;
				},

	findImg:		function(id, frame, d) {
				  var img = null;
				  if (!d) {
				    if (frame && top[frame]) d = top[frame].document;
				    else d = document;
				    if (!d) return null;
				  }
				  if (d.images) img = d.images[id];
				  else if (d.getElementById) img = d.getElementById(id);
				  for (var i=0; !img && d.layers && i<d.layers.length; i++){
				    img = ACT.findImg(id, null, d.layers[i].document);
				  }
				  return img;
				},


	Images:		{
				data:		new Array(),
				buffer:		new Array(),
				preload:	function() {
							for(var i=0;i<ACT.Images.data.length;i++) {
								ACT.Images.buffer = new Image();
								ACT.Images.buffer.src = ACT.Images.data[i].url;
								window.status = "Preloading images: " + Math.round(100*i/ACT.Images.data.length) + "%   (" + ACT.Images.data[i].url + ")";
							}
							window.status = "Preloading images: done";
							setTimeout("window.status = '';",2500);
						},
				getImage:	function(name,state) {
							if(state=="") state="normal";
							var out = new Image();
							for(var i=0;i<ACT.Images.data.length&&out.src=="";i++) {
								if(ACT.Images.data[i].name==name && ACT.Images.data[i].state==state) out.src = ACT.Images.data[i].url;
							}
							return out;
						}
			}
}




//============================================================================================================\\
// EXTRA ARRAY PROTOTYPES (Since some browsers don't have all the Array functions, we need to add them here)  \\
//============================================================================================================\\

// Internet Explorer 5 didn't have Push, Pop and Shift so here we create them.
// Split and Join are normally supported by every DHTML capable browser,
// but they were broken in IE5/MacOSX, madness.

// push appends new elements to an array, and returns the new length
if (Array.prototype && !Array.prototype.push) {
	Array.prototype.push = function() {
		for (var i=0; i<arguments.length; i++) this[this.length] = arguments[i];
		return this.length;
	};
}

// pop removes the last element from an array and returns it
if (Array.prototype && !Array.prototype.pop) {
	Array.prototype.pop = function() {
		var lastitem = this.length > 0 ? this[this.length - 1] : undefined;
		if (this.length > 0) this.length--;
		return lastitem;
	};
}

// shift removes the first element from an array and returns it
if (Array.prototype && !Array.prototype.shift) {
	Array.prototype.shift = function() {
		var firstitem = this.length > 0 ? this[0] : undefined;
		for (var i=0; i<this.length-1; i++) this[i] = this[i + 1];
		if (this.length > 0) this.length--;
		return firstitem;
	};
}

// join returns a string value consisting of all the elements of an array
// concatenated together and separated by the separator argument
if (Array.prototype && !Array.prototype.join) {
	Array.prototype.join = function(separator) {
		if (typeof separator != "string") separator = ",";
		var s = "";
		for (var i=0; i<this.length; i++) {
			if (this[i] != null && this[i] != undefined) s += this[i];
			if (i != this.length - 1) s += separator;
		}
		return s;
	};
}
function printMe()
   {
   window.print();
   }
