	var MostRecentTextBox = null;
	
	function CloseBox(unused)
	{
		if (MostRecentTextBox)
			MostRecentTextBox.Background.onmousedown();
	}

	// Delegate helps with event handlers retaining the correct "this" object
	//
	// Usage:
	//
	// object.onclick = new Delegate(object, EventHandler);
	
	function Delegate(Instance, Method)
	{
		return function()
		{
			return Method.apply(Instance, arguments);
		}
	}
	
	// Animates an image by darkening background, and zooming image in
	//
	// Usage:
	//
	//    <img src="Image1.jpg" onmousedown="new ImageExpander(this, 'Image2.jpg');" />
	
	function ImageExpander(ImageObject, Source)
	{
		this.ImageObject = ImageObject;
		this.Source = Source;
		
		// CREATE TRANSLUCENT BACKGROUND
		
		this.Background = document.createElement("div");
		
		this.Background.style.background = "#000000";
		this.Background.style.height = document.documentElement.clientHeight + "px";
		this.Background.style.left = document.documentElement.scrollLeft + "px";
		this.Background.style.position = "absolute";
		this.Background.style.top = document.documentElement.scrollTop + "px";
		this.Background.style.width = document.documentElement.clientWidth + "px";
		
		SetOpacity(this.Background, 0);
		
		document.body.appendChild(this.Background);
		
		this.Background.AnimationStep = 0;
		
		// CREATE IMAGE ELEMENT
		
		this.Image = document.createElement("img");

		this.Image.style.left = "0px";
		this.Image.style.position = "absolute";
		this.Image.style.top = "0px";
        this.Image.style.visibility = "hidden";
		
		this.Image.onload = new Delegate(this, function()
		{
			document.body.appendChild(this.Image);
			
			var ImageStartLeft = GetAbsoluteLeft(this.ImageObject);
			var ImageStartTop = GetAbsoluteTop(this.ImageObject);
			var ImageStartWidth = this.ImageObject.offsetWidth;
			var ImageStartHeight = this.ImageObject.offsetHeight;
			
			var ImageFinishLeft = parseInt((document.documentElement.clientWidth - this.Image.width) / 2);
			var ImageFinishTop = parseInt((document.documentElement.clientHeight - this.Image.height) / 2);
			var ImageFinishWidth = this.Image.width;
			var ImageFinishHeight = this.Image.height;
			
			this.Image.style.cursor = "pointer";
			this.Image.style.height = ImageStartHeight + "px";
			this.Image.style.left = ImageStartLeft + "px";
			this.Image.style.position = "absolute";
			this.Image.style.top = ImageStartTop + "px";
			this.Image.style.visibility = "visible";
			this.Image.style.width = ImageStartWidth + "px";
			
			this.Image.AnimationStep = 0;
			this.Image.AnimationSteps = new Array();
			
			for (var i = 0; i < 10; i++)
			{
				this.Image.AnimationSteps[i] = new Object();
				
				this.Image.AnimationSteps[i].Left = parseInt(ImageStartLeft + (ImageFinishLeft - ImageStartLeft) * i / 10);
				this.Image.AnimationSteps[i].Top = parseInt(ImageStartTop + (ImageFinishTop - ImageStartTop) * i / 10);
				this.Image.AnimationSteps[i].Width = parseInt(ImageStartWidth + (ImageFinishWidth - ImageStartWidth) * i / 10);
				this.Image.AnimationSteps[i].Height = parseInt(ImageStartHeight + (ImageFinishHeight - ImageStartHeight) * i / 10);
			}

			this.Image.AnimationSteps[10] = new Object();

			this.Image.AnimationSteps[10].Left = ImageFinishLeft;
			this.Image.AnimationSteps[10].Top = ImageFinishTop;
			this.Image.AnimationSteps[10].Width = ImageFinishWidth;
			this.Image.AnimationSteps[10].Height = ImageFinishHeight;
			
			// ASSIGN EVENT HANDLERS
			
			this.Background.AnimationTimer = setInterval(new Delegate(this, function()
			{
				if (this.Background.AnimationStep > 10)
				{
					clearInterval(this.Background.AnimationTimer);
					
					this.Background.onmousedown = this.Image.onmousedown = new Delegate(this, function()
					{
						this.Background.onmousedown = this.Image.onmousedown = null;
						
						for (var Property in this.Background)
						{
							if (Property.toLowerCase().substring(0, 2) == "on")
								this.Background[Property] = null;
						}

						for (var Property in this.Image)
						{
							if (Property.toLowerCase().substring(0, 2) == "on")
								this.Image[Property] = null;
						}
								
						this.Background.AnimationStep--;
						this.Image.AnimationStep--;
						
						this.Background.AnimationTimer = setInterval(new Delegate(this, function()
						{
							if (this.Background.AnimationStep < 0)
							{
								clearInterval(this.Background.AnimationTimer);
						
								this.Background.parentNode.removeChild(this.Background);
								
								return;
							}
							
							SetOpacity(this.Background, this.Background.AnimationStep * 6);
							
							this.Background.AnimationStep--;
						}), 75);
						
						this.Image.AnimationTimer = setInterval(new Delegate(this, function()
						{
							if (this.Image.AnimationStep < 0)
							{
								clearInterval(this.Image.AnimationTimer);

								this.Image.parentNode.removeChild(this.Image);
								
								return;
							}
							
							this.Image.style.left = this.Image.AnimationSteps[this.Image.AnimationStep].Left + "px";
							this.Image.style.top = this.Image.AnimationSteps[this.Image.AnimationStep].Top + "px";
							this.Image.style.width = this.Image.AnimationSteps[this.Image.AnimationStep].Width + "px";
							this.Image.style.height = this.Image.AnimationSteps[this.Image.AnimationStep].Height + "px";
							
							this.Image.AnimationStep--;
						}), 75);
					});
			
					return;
				}
				
				SetOpacity(this.Background, this.Background.AnimationStep * 6);
				
				this.Background.AnimationStep++;
			}), 75);
			
			this.Image.AnimationTimer = setInterval(new Delegate(this, function()
			{
				if (this.Image.AnimationStep > 10)
				{
					clearInterval(this.Image.AnimationTimer);
					
					return;
				}
				
				this.Image.style.left = this.Image.AnimationSteps[this.Image.AnimationStep].Left + "px";
				this.Image.style.top = this.Image.AnimationSteps[this.Image.AnimationStep].Top + "px";
				this.Image.style.width = this.Image.AnimationSteps[this.Image.AnimationStep].Width + "px";
				this.Image.style.height = this.Image.AnimationSteps[this.Image.AnimationStep].Height + "px";
				
				this.Image.AnimationStep++;
			}), 75);
		});
		
	    this.Image.src = Source;
	}
	
	// Animates a block of text by darkening background, and zooming external HTML in
	//
	// Usage:
	//
	//    <div onmousedown="new PageExpander(this, 'Page.htm');">Preview of content</div>
	
	function PageExpander(TextObject, Source)
	{
		MostRecentTextBox = this;
		
		// CREATE TRANSLUCENT BACKGROUND
		
		this.Background = document.createElement("div");
		
		this.Background.style.background = "#000000";
		this.Background.style.height = document.documentElement.clientHeight + "px";
		this.Background.style.left = document.documentElement.scrollLeft + "px";
		this.Background.style.position = "absolute";
		this.Background.style.top = document.documentElement.scrollTop + "px";
		this.Background.style.width = document.documentElement.clientWidth + "px";
		
		SetOpacity(this.Background, 0);
		
		document.body.appendChild(this.Background);
		
		this.Background.AnimationStep = 0;
		
		// CREATE TEXT ELEMENT
		
		this.Text = document.createElement("div");
		
		try
		{
			this.HttpRequest = new XMLHttpRequest();
		}
		catch (ex)
		{
			try
			{
				this.HttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
			}
			catch (ex)
			{
				// Note: following is not put in a try/catch block, because if we get this far and it
				// doesn't work, we can't do AJAX anyway!!!

				this.HttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
			}
		}
		
		this.HttpRequest.onreadystatechange = new Delegate(this, function()
		{
			if ((this.HttpRequest.readyState == 4)) // && (this.HttpRequest.status == 200))
			{
				this.Text.innerHTML = this.HttpRequest.responseText;
				
				document.body.appendChild(this.Text);
	    		
				var TextStartLeft = GetAbsoluteLeft(TextObject);
				var TextStartTop = GetAbsoluteTop(TextObject);
				var TextStartWidth = TextObject.offsetWidth;
				var TextStartHeight = TextObject.offsetHeight;
	    		
				// var TextFinishLeft = document.documentElement.scrollLeft;
				// var TextFinishTop = document.documentElement.scrollTop;
				// var TextFinishWidth = document.documentElement.clientWidth;
				// var TextFinishHeight = document.documentElement.clientHeight;

				var TextFinishLeft = document.documentElement.scrollLeft + (document.documentElement.clientWidth - 774) / 2;
				var TextFinishTop = document.documentElement.scrollTop + (document.documentElement.clientHeight - 495) / 2;
				var TextFinishWidth = 774;
				var TextFinishHeight = 495;
	    		
				this.Text.style.background = "#FFFFFF";
				this.Text.style.border = "5px solid #000000";
				//this.Text.style.clip = "rect(0px 784px, 505px, 0px)";
	    		//this.Text.style.cursor = "pointer";
			    this.Text.style.height = TextStartHeight + "px";
			    this.Text.style.left = TextStartLeft + "px";
				this.Text.style.overflow = "auto";
			    this.Text.style.position = "absolute";
				this.Text.style.textAlign = "left";
			    this.Text.style.top = TextStartTop + "px";
	    		this.Text.style.visibility = "visible";
			    this.Text.style.width = TextStartWidth + "px";
				
				this.Text.AnimationStep = 0;
				this.Text.AnimationSteps = new Array();
	    		
			    for (var i = 0; i < 10; i++)
			    {
				    this.Text.AnimationSteps[i] = new Object();
	    			
				    this.Text.AnimationSteps[i].Left = parseInt(TextStartLeft + (TextFinishLeft - TextStartLeft) * i / 10);
				    this.Text.AnimationSteps[i].Top = parseInt(TextStartTop + (TextFinishTop - TextStartTop) * i / 10);
				    this.Text.AnimationSteps[i].Width = parseInt(TextStartWidth + (TextFinishWidth - TextStartWidth) * i / 10);
				    this.Text.AnimationSteps[i].Height = parseInt(TextStartHeight + (TextFinishHeight - TextStartHeight) * i / 10);
			    }

				this.Text.AnimationSteps[10] = new Object();

			    this.Text.AnimationSteps[10].Left = TextFinishLeft;
			    this.Text.AnimationSteps[10].Top = TextFinishTop;
			    this.Text.AnimationSteps[10].Width = TextFinishWidth;
			    this.Text.AnimationSteps[10].Height = TextFinishHeight;
	    		
			    // ASSIGN EVENT HANDLERS
	    		
			    this.Background.AnimationTimer = setInterval(new Delegate(this, function()
			    {
				    if (this.Background.AnimationStep > 10)
				    {
					    clearInterval(this.Background.AnimationTimer);
						
						this.Text.style.overflow = "auto";
	    				
						this.Background.onmousedown = this.Text.CloseBox = new Delegate(this, function()
					    {
							this.Text.style.overflow = "hidden";
							
						    for (var Property in this.Background)
						    {
							    if (Property.toLowerCase().substring(0, 2) == "on")
								    this.Background[Property] = null;
						    }

						    for (var Property in this.Text)
						    {
							    if (Property.toLowerCase().substring(0, 2) == "on")
								    this.Text[Property] = null;
						    }

						    for (var Property in this.HttpRequest)
						    {
							    if (Property.toLowerCase().substring(0, 2) == "on")
								    this.HttpRequest[Property] = null;
						    }

						    this.Background.AnimationStep--;
							this.Text.AnimationStep--;
	    					
						    this.Background.AnimationTimer = setInterval(new Delegate(this, function()
						    {
							    if (this.Background.AnimationStep < 0)
							    {
								    clearInterval(this.Background.AnimationTimer);
	    					
								    this.Background.parentNode.removeChild(this.Background);
									
									this.Background = null;
	    							
								    return;
							    }
	    						
							    SetOpacity(this.Background, this.Background.AnimationStep * 5);
	    						
							    this.Background.AnimationStep--;
						    }), 75);

						    this.Text.AnimationTimer = setInterval(new Delegate(this, function()
						    {
							    if (this.Text.AnimationStep < 0)
							    {
								    clearInterval(this.Text.AnimationTimer);
	    					
								    this.Text.parentNode.removeChild(this.Text);
									
									this.Text = null;
									this.HttpRequest = null;
	    							
								    return;
							    }
	    						
							    this.Text.style.left = this.Text.AnimationSteps[this.Text.AnimationStep].Left + "px";
							    this.Text.style.top = this.Text.AnimationSteps[this.Text.AnimationStep].Top + "px";
							    this.Text.style.width = this.Text.AnimationSteps[this.Text.AnimationStep].Width + "px";
							    this.Text.style.height = this.Text.AnimationSteps[this.Text.AnimationStep].Height + "px";
	    						
							    this.Text.AnimationStep--;
						    }), 75);
						});
	    		
					    return;
				    }
	    			
				    SetOpacity(this.Background, this.Background.AnimationStep * 5);
	    			
				    this.Background.AnimationStep++;
			    }), 75);
	    		
				this.Text.AnimationTimer = setInterval(new Delegate(this, function()
			    {
				    if (this.Text.AnimationStep > 10)
				    {
					    clearInterval(this.Text.AnimationTimer);
	    				
					    return;
				    }

				    this.Text.style.left = this.Text.AnimationSteps[this.Text.AnimationStep].Left + "px";
				    this.Text.style.top = this.Text.AnimationSteps[this.Text.AnimationStep].Top + "px";
				    this.Text.style.width = this.Text.AnimationSteps[this.Text.AnimationStep].Width + "px";
				    this.Text.style.height = this.Text.AnimationSteps[this.Text.AnimationStep].Height + "px";
	    			
				    this.Text.AnimationStep++;
			    }), 75);
			}
		});
		
	    this.HttpRequest.open("GET", Source, true);
		this.HttpRequest.send(null);
	}

	function GetAbsoluteLeft(Object)
	{
		var AbsoluteLeft = 0;
		
		while (Object)
		{
			AbsoluteLeft += Object.offsetLeft;
			
			Object = Object.offsetParent;
		}
		
		return AbsoluteLeft;
	}

	function GetAbsoluteTop(Object)
	{
		var AbsoluteTop = 0;
		
		while (Object)
		{
			AbsoluteTop += Object.offsetTop;
			
			Object = Object.offsetParent;
		}
		
		return AbsoluteTop;
	}
	
	function SetOpacity(Object, Percentage)
	{
		Object.style.filter = "alpha(opacity=" + Percentage + ")";
		Object.style.opacity = Percentage / 100;
		
		Object._Opacity = Percentage;
	}
	
	