//  ------------------------------------
//
//  JAM Window Toolkit
//
//  ------------------
//
//  (c) Pete Blacker 2007.
//
//  --------------------------------------

// Time to start doing things properly, create concrete JW class to contain all JAM Window Functionality

var JW = {};
JW.Cfg = {};

// create simple helper functions
JW.GetBody = function()
{ return document.getElementsByTagName("BODY")[0]; }

// Method to get the Path from htdocs to this page 
JW.GetDocumentPath = function()
{
	var Location = document.location.toString();
	
	// remove file name
	Location = Location.substr(0, Location.lastIndexOf("/"));
	// remove protocol and domain 
	Location = Location.substr(Location.indexOf("://") + 3);

	if (Location.indexOf("/") == -1)
		return "";
	else	
		return Location.substr(Location.indexOf("/"));
}

// Method to get the relative path to htdocs root from the location of this page
JW.GetPathToRoot = function()
{
	var DocPath = JW.GetDocumentPath();
	var PathToRoot = "";
	
	while (DocPath.indexOf("/") != -1)
		{
		DocPath = DocPath.substr(DocPath.indexOf("/") + 1);
		PathToRoot += "../";
		}
		
	return PathToRoot;
}

// Function to bind to an elements event that prevents the browser default dragging behaviour (select text or drag image)
JW.Lib = {};
JW.Lib.GetDocumentPath = JW.GetDocumentPath;
JW.Lib.GetPathToRoot = JW.GetPathToRoot;
JW.Lib.Bind = function(Element, Event, Handler)
{
	// NS/Firefox	
	if (window.addEventListener)
		{
		if (typeof(capture) == "undefined" || !capture)
			Element.addEventListener(Event, Handler, false);
		else
			Element.addEventListener(Event, Handler, true);
		}
	// IE
	if (window.attachEvent)
		Element.attachEvent("on" + Event, Handler);
}

JW.Lib.DontDrag = function(e)
{
	if (typeof(e.cancelDefault) == "function")
		e.cancelDefault();
	if (typeof(e.returnValue) != "undefined")
		e.returnValue = false;
	e.cancelBubble = true;
	return false;
}
JW.Lib.DisableBrowserDrag = function(Element)
{
	JW.Lib.Bind(Element, "dragstart", JW.Lib.DontDrag);
	JW.Lib.Bind(Element, "selectstart", JW.Lib.DontDrag);
	JW.Lib.Bind(Element, "mousedown", JW.Lib.DontDrag);
}
JW.Lib.RemoveChildren = function(Ele)
{
	try	{
		for (i=Ele.childNodes.length-1; i>=0; --i)
			Ele.removeChild(Ele.childNodes[i]);
		}
	catch (e)
		{
		}
}
JW.Lib.GetComputedStyle = function(Ele, CssRule)
{
	var Value = null;
	
	if(document.defaultView && document.defaultView.getComputedStyle)
		Value = document.defaultView.getComputedStyle(Ele, "").getPropertyValue(CssRule);
	else if(Ele.currentStyle)
		{
		var Relpacer = function(strMatch, p1)
		{	return p1.toUpperCase();	}
		
		CssRule = CssRule.replace(/\-(\w)/g, Replacer);
		Value = Ele.currentStyle[CssRule];
		}
		
	return Value;
}

JW.Lib.ElementDisplayed = function(Ele)
{
	var Display = JW.Lib.GetComputedStyle(Ele, "display");
	if (Display.toLowerCase() == "none")
		return false;
	
	// if this element has a parent
	if (Ele.nodeName != "BODY" && typeof(Ele.parentNode) == "object" && Ele.parentNode != Ele)
		return JW.Lib.ElementDisplayed(Ele.parentNode);
	else
		return true;
}
JW.Lib.FormatDataSize = function(Size)
{
	if (typeof(Size) != "number")
		{
		Size = parseInt(Size);
		if (isNaN(Size))
			{
			alert("Error : trying to format a data size with a non-numeric value - \"" + Size + "\"");
			return;
			}
		}

	if (Size < 1024)
		return Size.toString(10) + " Bytes";
	if (Size < 1024*1024)
		return Math.floor(Size/1024).toString(10) + " KBytes";
	if (Size < 1024*1024*1024)
		return Math.floor(Size/(1024*1024)).toString(10) + " MBytes";
}

// create JW Document Geometry object, gets information about the screen, browser viewport and document sizes.
JW.DocGeo = new Object();

JW.DocGeo.GetViewportSize = function()
{
	var Size = new Object();
	
	// the more standards compliant browsers
	if (typeof window.innerWidth != 'undefined')
		{
		Size.Width = window.innerWidth,
		Size.Height = window.innerHeight
		}
	// IE6 in standards compliant mode
	else if (typeof document.documentElement != 'undefined'
			&& typeof document.documentElement.clientWidth != 'undefined'
			&& document.documentElement.clientWidth != 0)
		{
		Size.Width = document.documentElement.clientWidth,
		Size.Height = document.documentElement.clientHeight
		}
	// older versions of IE
	else
		{
		Size.Width = document.getElementsByTagName('body')[0].clientWidth,
		Size.Height = document.getElementsByTagName('body')[0].clientHeight
		}
		
	return Size;
}

//  --------------------------------------

// Jam Window JS loader function
JW.LoadedJSFiles = new Array();
JW.LoadJS = function(URL)
{
	if (!JW.LoadedJSFiles[URL])
		{
		var ScriptElement = document.createElement("script");
		ScriptElement.type = "text/javascript";
		ScriptElement.src = URL;
		ScriptElement.charset="UTF-8";
		document.getElementsByTagName("HEAD")[0].appendChild(ScriptElement);
		JW.LoadedJSFiles[URL] = true;
		}
}

JW.LinkCSS = function(URI)
{
	JW_LinkCSS(URI);
}

//  --------------------------------------
// JW String Helper Library

JW.Str = new Object();

JW.Str.StripHTMLTags = function(Str)
{	
	var TagPosition, TagClosePosition;
	// while there is still a "<" character in the string
	while ((TagPosition = Str.indexOf("<")) != -1)
		{
		// find the position of the first ">" character after the first "<" character
		TagClosePosition = Str.indexOf(">", TagPosition);
		
		// if a tag close was found replace tag with a space
		if (TagClosePosition != -1)
			{
			Str = Str.substr(0, TagPosition) + " " + Str.substr(TagClosePosition+1);
			}
		else	// if no tag close was found discard all of the string after and including the tag
			{
			Str = Str.substr(0, TagPosition);
			}
		}
		
	return Str;
}

JW.Str.Trim = function(string)
{
	var start = 0;
	var end = 0;
	
	// find how many characters to trim from the start
	while (string[start] == " " || string[start] == "\t")
		++start;
		
	// find how many characters to trim from the end
	while (string[string.length-1-end] == " " || string[string.length-1-end] == "\t")
		++end;
		
	trimString = string.substr(start, string.length - start - end);
	
	return trimString;
}

JW.Str.ExplodeURL = function(URL)
{
	var Result = {Protocol:"", Domain:"", Path:"", FileName:"", QueryString:""};
	
	var PTPos = URL.indexOf("://");
	if (PTPos != -1)
		{
		Result.Protocol = URL.substr(0,PTPos);
		URL = URL.substr(PTPos+3);
		}
	
	var DTPos = URL.indexOf("/");
	if (DTPos != -1)
		{
		Result.Domain = URL.substr(0, DTPos);
		URL = URL.substr(DTPos+1)
		}
		
	PTPos = URL.lastIndexOf("/");
	if (PTPos != -1)
		{
		Result.Path = URL.substr(0, PTPos+1);
		URL = URL.substr(PTPos);
		}
		
	var QSPos = URL.indexOf("?");
	if (QSPos != -1)
		{
		Result.FileName = URL.substr(0,QSPos);
		Result.QueryString = URL.substr(QSPos);
		}
	else
		Result.FileName = URL;
	return Result;
}

JW.Str.FileNameSafeStr = function(Str)
{
	var NewStr = "";

	var Zero = ("0").charCodeAt(0);
	var Nine = ("9").charCodeAt(0);
	var LcA = ("a").charCodeAt(0);
	var UcA = ("A").charCodeAt(0);
	var LcZ = ("z").charCodeAt(0);
	var UcZ = ("Z").charCodeAt(0);

	// Convert all non-alphanumeric characters to spaces
	var i;
	for (i=0; i<Str.length; ++i)
		{
		var CharCode = Str.charCodeAt(i)
		
		if ((CharCode >= Zero && CharCode <= Nine)
			||
			(CharCode >= LcA && CharCode <= LcZ)
			||
			(CharCode >= UcA && CharCode <= UcZ))
			NewStr += Str.substr(i, 1);
		else
			NewStr += " ";
		}
		
	// Collapse all whitespace gaps to a single space and trim
	NewStr = JW.Str.Trim(NewStr);
	while (NewStr != (NewStr = NewStr.replace("  ", " ")));
	
	// Convert all spaces to underscores
	while (NewStr != (NewStr = NewStr.replace(" ", "-")));
	
	return NewStr.toLowerCase();
}

//  --------------------------------------
// JW Date library. Extending Javscripts rather limited date functions

JW.DateTime = new Object();

JW.DateTime.getDateSuffix = function(DayOfMonth)
{
	switch (DayOfMonth)
		{
		case 1:
		case 21:
		case 31: return "st";
		case 2:
		case 22: return "nd";
		case 3:
		case 23: return "rd";
		default: return "th";
		}
}

JW.DateTime.getNameOfDay = function(DayNum, Long)
{
	var Days = ["Sunday", "Monday", "Tuesday", "Wednesday",
				"Thursday", "Friday", "Saturday"];
	if (Long)	return Days[DayNum];
	else		return Days[DayNum].substr(0,3);
}

JW.DateTime.getNameOfMonth = function(Month, Long)
{
	var Names =    ["January", "February", "March", "April",
					"May", "June", "July", "August",
					"September", "October", "November", "December"];
	if (Long)	return Names[Month];
	else		return Names[Month].substr(0,3);
}

JW.DateTime.DateToSQLDate = function(dateObj)
{
	monthStr = (dateObj.getMonth()+1);
	if (monthStr < 10)
		monthStr = "0" + monthStr;
		
	dayStr = dateObj.getDate();
	if (dayStr < 10)
		dayStr = "0" + dayStr;
	
	return dateObj.getFullYear() + "-" + monthStr + "-" + dayStr;
}

JW.DateTime.SQLDateToDate = function(SQLDate)
{
	jsDate = new Date();
	
	parts = SQLDate.split("-");
	
	jsDate.setFullYear(parseInt(parts[0],10));
	jsDate.setMonth(parseInt(parts[1],10)-1);
	jsDate.setDate(parseInt(parts[2],10));
	
	return jsDate;
}

JW.DateTime.HumanDateStr = function(dateObj)
{
	str = JW.DateTime.getNameOfDay(dateObj.getDay());
	str += " " + dateObj.getDate() + JW.DateTime.getDateSuffix(dateObj.getDate());
	str += " " + JW.DateTime.getNameOfMonth(dateObj.getMonth());
	str += " " + dateObj.getFullYear();
	
	return str;
}

//  --------------------------------------

// Jam Window Control default settings
JW.Cfg.Control = {};
JW.Cfg.Control.Default = {	Left:0, Top:0,
							Width:200, Height:21,
							FontSize:15,
							FontColor:"#000",
							DisabledFontColor:"#999",
							Visible:true};

// ---------------------------------------------------------------------				
// JW Control Base object
// ---------------------------------------------------------------------
JW_Control.prototype.constructor = JW_Control;
function JW_Control()
{
	// set default control properties
	for (var Param in JW.Cfg.Control.Default)
		this[Param] = JW.Cfg.Control.Default[Param];
}
JW_Control.prototype.Move = function()
{
	alert("Warning call to JW.Control base class Move method.");
}
JW_Control.prototype.SetVisible = function(NewVisible)
{
	this.Visible = NewVisible;
	if (this.Visible)
		this.DOMElement.style.display = "block";
	else
		this.DOMElement.style.display = "none";
}
JW.Control = JW_Control;

// create JW controls container object
JW.Controls = {};

// ---------------------------------------------------------------------
// JW Label Control object
// ---------------------------------------------------------------------

JW.Cfg.Control.DefaultLabel = {	Label:"New Label",
								Align:"left",
								Bold:false,
								Italic:false,
								Underline:false};

JW_Controls_Label.prototype = JW.Control.prototype;
JW_Controls_Label.constructor = JW_Controls_Label;
function JW_Controls_Label(Properties, Container)
{
	// call superclass constructor
	JW.Control.call(this);

	// set default properties for label control
	for (var Param in JW.Cfg.Control.DefaultLabel)
		this[Param] = JW.Cfg.Control.DefaultLabel[Param];

	// set the properties passed to constructor
	for (var Param in Properties)
		this[Param] = Properties[Param];
		
	// create DOM element for this control
	this.DOMElement = document.createElement("div");
	this.DOMElement.style.position = "absolute";
	this.DOMElement.style.left = this.Left + "px";
	this.DOMElement.style.top = this.Top + "px";
	this.DOMElement.style.width = this.Width + "px";
	if (this.Underline)
		{
		this.DOMElement.style.height = (this.Height - 1) + "px";
		this.DOMElement.style.borderBottom = "1px solid " + this.FontColor;
		}
	else
		this.DOMElement.style.height = this.Height + "px";
	
	this.DOMElement.appendChild( document.createTextNode(this.Label) );

	this.DOMElement.style.color = this.FontColor;
	if (this.Bold)	this.DOMElement.style.fontWeigth = "bold";
	if (this.Italic) this.DOMElement.style.fontStyle = "italic";
	if (!this.Visible) this.DOMElement.style.display = "none";
	
	// if a valid alignment parameter was given
	if (this.Align == "Left" || this.Align == "Center" || this.Align == "Right")
		this.DOMElement.style.textAlign = this.Align.toLowerCase();
		
	// if a container object was given add this control to it
	if (typeof(Container) != "undefined")
		Container.appendChild( this.DOMElement );
}
JW_Controls_Label.prototype.UpdateLabel = function(NewLabel)
{
	JW.Lib.RemoveChildren(this.DOMElement);
	this.DOMElement.appendChild( document.createTextNode(NewLabel) );
}
// re-define Move method
JW_Controls_Label.prototype.Move = function(Parameters)
{
	if (typeof(Parameters.Left) == "number")
		{
		this.Left = Parameters.Left;
		this.DOMElement.style.left = this.Left + "px";
		}
	if (typeof(Parameters.Top) == "number")
		{
		this.Top = Parameters.Top;
		this.DOMElement.style.top = this.Top + "px";
		}
	if (typeof(Parameters.Left) == "number")
		{
		this.Width = Parameters.Width;
		this.DOMElement.style.width = this.Width + "px";
		}
	if (typeof(Parameters.Height) == "number")
		{
		this.Height = Parameters.Height;
		if (this.Underline)		this.DOMElement.style.height = (this.Height - 1) + "px";			
		else					this.DOMElement.style.height = this.Height + "px";
		}
}
JW.Controls.Label = JW_Controls_Label;

// ---------------------------------------------------------------------
// JW Button Control object
// ---------------------------------------------------------------------

JW.Cfg.Control.DefaultButton = {	Label:"New Label",
									Align:"Center",
									OnClick:null,
									Icon:null,
									IconWidth:21, IconHeight:21,
									FontSize:14,
									Enabled:true};

JW_Controls_Button.prototype = JW.Control.prototype;
JW_Controls_Button.constructor = JW_Controls_Button;
function JW_Controls_Button(Properties, Container)
{
	var self = this;
	
	// call superclass constructor
	JW.Control.call(this);

	// set default properties for label control
	for (var Param in JW.Cfg.Control.DefaultButton)
		this[Param] = JW.Cfg.Control.DefaultButton[Param];

	// set the properties passed to constructor
	for (var Param in Properties)
		this[Param] = Properties[Param];
		
	// create DOM element for this control
	this.DOMElement = document.createElement("div");
	this.DOMElement.style.position = "absolute";
	this.DOMElement.style.left = this.Left + "px";
	this.DOMElement.style.top = this.Top + "px";
	this.DOMElement.style.width = this.Width-4 + "px";
	this.DOMElement.style.height = this.Height-4 + "px";
	this.DOMElement.style.color = this.FontColor;
	this.DOMElement.style.cursor = "pointer";	
	this.DOMElement.style.backgroundColor = "#CCC";
	this.DOMElement.style.border = "outset 2px #CCC";
	
	this.ContentContainer = document.createElement("span");
	this.DOMElement.appendChild(this.ContentContainer);
	
	// if there is an icon for this button
	if (typeof(this.Icon) == "string")
		{
		this.IconElement = document.createElement("img");
		this.IconElement.border = 0;
		this.IconElement.width = this.IconWidth;
		this.IconElement.height = this.IconHeight;
		this.IconElement.src = this.Icon;
		this.IconElement.align = "absmiddle";
		this.IconElement.style.paddingRight = "2px";
		
		this.ContentContainer.appendChild(this.IconElement);
		}
		
	// create Label container
	this.LabelContainer = document.createElement("span")
	this.LabelContainer.style.fontSize = this.FontSize + "px";
	this.LabelContainer.style.color = this.FontColor;
	this.LabelContainer.appendChild( document.createTextNode(this.Label) );
	this.ContentContainer.appendChild( this.LabelContainer );

	// if a valid alignment parameter was given
	if (this.Align == "Left" || this.Align == "Center" || this.Align == "Right")
		this.DOMElement.style.textAlign = this.Align.toLowerCase();
	
	var MouseOver = function()
	{	self.DOMElement.style.backgroundColor = "#DDD"; }
	var MouseOut = function()
	{
		self.DOMElement.style.backgroundColor = "#CCC";
		self.DOMElement.style.border = "2px outset #CCC";
	}
	var MouseDown = function()
	{	self.DOMElement.style.border = "2px inset #CCC"; }
	var MouseUp = function()
	{	self.DOMElement.style.border = "2px outset #CCC"; }
	
	JW.Lib.Bind(this.DOMElement, "mouseover", MouseOver);
	JW.Lib.Bind(this.DOMElement, "mouseout", MouseOut);
	JW.Lib.Bind(this.DOMElement, "mousedown", MouseDown);
	JW.Lib.Bind(this.DOMElement, "mouseup", MouseUp);
	
	this.Click = function()
	{
	if (typeof(self.OnClick) == "function")
		self.OnClick();
	}
	JW.Lib.Bind(this.DOMElement, "click", this.Click);
	
	// if a container object was given add this control to it
	if (typeof(Container) != "undefined")
		Container.appendChild( this.DOMElement );
}

JW_Controls_Button.prototype.SetLabel = function(NewLabel)
{
	if (typeof(NewLabel) == "string")
		{
		JW.Lib.RemoveChildren(this.LabelContiner);
		this.LabelContainer.appendChild( document.createTextNode(NewLabel) );
		}
	else
		alert("Error : trying to set the label of a JW Button with a non-string.");
}

JW_Controls_Button.prototype.SetEnabled = function(NewEnabled)
{
	this.Enabled = (NewEnabled == true);
	
	if (this.Enabled)
		{
		this.DOMElement.style.color = this.FontColor;
		}
	else
		{
		this.DOMElement.style.color = this.DisabledFontColor;
		}	
}
// re-define Move method
JW_Controls_Button.prototype.Move = function(Parameters)
{
	if (typeof(Parameters.Left) == "number")
		{
		this.Left = Parameters.Left;
		this.DOMElement.style.left = this.Left-4 + "px";
		}
	if (typeof(Parameters.Top) == "number")
		{
		this.Top = Parameters.Top;
		this.DOMElement.style.top = this.Top-4 + "px";
		}
	if (typeof(Parameters.Left) == "number")
		{
		this.Width = Parameters.Width;
		this.DOMElement.style.width = this.Width-4 + "px";
		}
	if (typeof(Parameters.Height) == "number")
		{
		this.Height = Parameters.Height;
		this.DOMElement.style.height = this.Height-4 + "px";
		}
}
JW.Controls.Button = JW_Controls_Button;

// ---------------------------------------------------------------------
// JW ComboBox Control object
// ---------------------------------------------------------------------

JW.Cfg.Control.DefaultComboBox = {	Value:"",
									Align:"left",
									FontSize:14,
									OnChange:null};

JW_Controls_ComboBox.prototype = JW.Control.prototype;
JW_Controls_ComboBox.constructor = JW_Controls_ComboBox;
function JW_Controls_ComboBox(Properties, Container)
{
	var self = this;

	// call superclass constructor
	JW.Control.call(this);

	// set default properties for label control
	for (var Param in JW.Cfg.Control.DefaultComboBox)
		this[Param] = JW.Cfg.Control.DefaultComboBox[Param];

	// set the properties passed to constructor
	for (var Param in Properties)
		this[Param] = Properties[Param];
		
	// create DOM element for this control
	this.DOMElement = document.createElement("select");
	this.DOMElement.style.position = "absolute";
	this.DOMElement.style.left = this.Left + "px";
	this.DOMElement.style.top = this.Top + "px";
	this.DOMElement.style.width = (this.Width-1) + "px";
	this.DOMElement.style.height = (this.Height-1) + "px";
	this.DOMElement.style.color = this.FontColor;
	this.DOMElement.style.fontSize = this.FontSize + "px";
	
	// if a valid alignment parameter was given
	if (this.Align == "Left" || this.Align == "Center" || this.Align == "Right")
		this.DOMElement.style.textAlign = this.Align.toLowerCase();
	
	// set the options in this combo box
	this.SetOptions(this.Options);
	
	this.DOMElement.value = this.Value;
		
	// catch change event to update value property and fire OnChange event if registered
	var Change = function()
	{
		self.Value = self.DOMElement.value;
		
		if (typeof(self.OnChange) == "function")
			self.OnChange(self.Value);
	}
	JW.Lib.Bind(this.DOMElement, "change", Change);
		
	// if a container object was given add this control to it
	if (typeof(Container) != "undefined")
		Container.appendChild( this.DOMElement );
}

// Method to update the options list in this combo box
JW_Controls_ComboBox.prototype.SetOptions = function(NewOptions)
{
	this.Options = NewOptions;
	
	// empty existing options list
	this.DOMElement.options.length = 0;
	
	// add new options
	var i;
	for (i=0; i<this.Options.length; ++i)
		this.DOMElement.options[this.DOMElement.options.length] = new Option(this.Options[i].Label, this.Options[i].Value);
		
	// reset the value of the select element
	this.DOMElement.value = this.Value;
}

// re-define Move method
JW_Controls_ComboBox.prototype.Move = function(Parameters)
{
	if (typeof(Parameters.Left) == "number")
		{
		this.Left = Parameters.Left;
		this.DOMElement.style.left = this.Left + "px";
		}
	if (typeof(Parameters.Top) == "number")
		{
		this.Top = Parameters.Top;
		this.DOMElement.style.top = this.Top + "px";
		}
	if (typeof(Parameters.Left) == "number")
		{
		this.Width = Parameters.Width;
		this.DOMElement.style.width = this.Width + "px";
		}
	if (typeof(Parameters.Height) == "number")
		{
		this.Height = Parameters.Height;
		this.DOMElement.style.height = this.Height + "px";
		}
}
JW.Controls.ComboBox = JW_Controls_ComboBox;


// ---------------------------------------------------------------------
// JW TextBox Control object
// ---------------------------------------------------------------------

JW.Cfg.Control.DefaultTextBox = {	Value:"",
									Type:"Plain",
									Align:"left",
									FontSize:14,
									MaxLen:null,
									OnChange:null,
									OnEnter:null};

JW_Controls_TextBox.prototype = JW.Control.prototype;
JW_Controls_TextBox.constructor = JW_Controls_TextBox;
function JW_Controls_TextBox(Properties, Container)
{
	var self = this;

	// call superclass constructor
	JW.Control.call(this);

	// set default properties for label control
	for (var Param in JW.Cfg.Control.DefaultTextBox)
		this[Param] = JW.Cfg.Control.DefaultTextBox[Param];

	// set the properties passed to constructor
	for (var Param in Properties)
		this[Param] = Properties[Param];
		
	// create DOM element for this control
	this.DOMElement = document.createElement("input");
	this.DOMElement.style.position = "absolute";
	this.DOMElement.style.left = this.Left + "px";
	this.DOMElement.style.top = this.Top + "px";
	this.DOMElement.style.width = this.Width + "px";
	this.DOMElement.style.height = this.Height + "px";
	this.DOMElement.style.color = this.FontColor;
	this.DOMElement.style.fontSize = this.FontSize + "px";
	this.DOMElement.value = this.Value;
	
	// if a valid alignment parameter was given
	if (this.Align == "Left" || this.Align == "Center" || this.Align == "Right")
		this.DOMElement.style.textAlign = this.Align.toLowerCase();
	
	// if a valid max len parameter was given
	if (typeof(this.MaxLen) == "string")
		{
		var Temp = parseInt(this.MaxLen);
		if (!isNaN(Temp))
			this.MaxLen = Temp;
		}
	if (typeof(this.MaxLen) == "number" && this.MaxLen > 0)
		this.DOMElement.maxLength = this.MaxLen;
	
	// add a keydown type event if this text box needs one
	if (this.Type == "Integer")
		{
		bindEvent(this.DOMElement, "keyup", JAM_ForceInputInt);
		bindEvent(this.DOMElement, "change", JAM_ForceInputInt);
		}
	if (this.Type == "PosInteger")
		{
		bindEvent(this.DOMElement, "keyup", JAM_ForceInputPosInt);
		bindEvent(this.DOMElement, "change", JAM_ForceInputPosInt);
		}
	if (this.Type == "Float")
		{
		bindEvent(this.DOMElement, "keyup", JAM_ForceInputFloat);
		bindEvent(this.DOMElement, "change", JAM_ForceInputFloat);
		}
	
	var KeyDown = function(e)
	{
		var KeyCode = null;
		
		if (e.charCode) KeyCode = e.charCode;
		if (e.keyCode)	KeyCode = e.keyCode;
		
		if (KeyCode == 13 && typeof(self.OnEnter) == "function")
			self.OnEnter();
	}
	JW.Lib.Bind(this.DOMElement, "keydown", KeyDown);
	
	// catch change event to update value property and fire OnChange event if registered
	var Change = function()
	{
		self.Value = self.DOMElement.value;
		if (typeof(self.OnChange) == "function")
			self.OnChange(self.Value);
	}
	bindEvent(this.DOMElement, "keyup", Change);
	bindEvent(this.DOMElement, "change", Change);
		
	// if a container object was given add this control to it
	if (typeof(Container) != "undefined")
		Container.appendChild( this.DOMElement );
}
// re-define Move method
JW_Controls_TextBox.prototype.Move = function(Parameters)
{
	if (typeof(Parameters.Left) == "number")
		{
		this.Left = Parameters.Left;
		this.DOMElement.style.left = this.Left + "px";
		}
	if (typeof(Parameters.Top) == "number")
		{
		this.Top = Parameters.Top;
		this.DOMElement.style.top = this.Top + "px";
		}
	if (typeof(Parameters.Left) == "number")
		{
		this.Width = Parameters.Width;
		this.DOMElement.style.width = this.Width + "px";
		}
	if (typeof(Parameters.Height) == "number")
		{
		this.Height = Parameters.Height;
		this.DOMElement.style.height = this.Height + "px";
		}
}
JW.Controls.TextBox = JW_Controls_TextBox;

// ---------------------------------------------------------------------
// JW Checkbox Control object
// ---------------------------------------------------------------------

JW.Cfg.Control.DefaultCheckbox =   {Label:"Checkbox",
									Align:"Right",
									Checked:false,
									Bold:false,
									Italic:false,
									Underline:false,
									OnChange:null};

JW_Controls_Checkbox.prototype = JW.Control.prototype;
JW_Controls_Checkbox.constructor = JW_Controls_Checkbox;
function JW_Controls_Checkbox(Properties, Container)
{
	var self = this;	

	// call superclass constructor
	JW.Control.call(this);

	// set default properties for checkbox control
	for (var Param in JW.Cfg.Control.DefaultCheckbox)
		this[Param] = JW.Cfg.Control.DefaultCheckbox[Param];

	// set the properties passed to constructor
	for (var Param in Properties)
		this[Param] = Properties[Param];
		
	// create DOM element for this control
	this.DOMElement = document.createElement("div");
	this.DOMElement.style.position = "absolute";
	this.DOMElement.style.left = this.Left + "px";
	this.DOMElement.style.top = this.Top + "px";
	this.DOMElement.style.width = this.Width + "px";
	this.DOMElement.style.height = this.Height + "px";
	
	// create label child control
	var LabelLeft = 0;
	if (this.Align == "Left")	LabelLeft = 20;
	this.LabelControl = new JW.Controls.Label({ Left:LabelLeft, Top:0,
												Width:this.Width-20, Height:this.Height,
												Align:this.Align, Label:this.Label,
												Bold:this.Bold, Italic:this.Italic,
												Underline:this.Underline}, this.DOMElement);
	
	// create checkbox element
	this.CheckboxElement = document.createElement("input");
	this.CheckboxElement.type = "checkbox";
	this.CheckboxElement.style.position = "absolute";
	if (this.Align == "Left")	this.CheckboxElement.style.left = "0px";
	else						this.CheckboxElement.style.left = (this.Width - 18) + "px";
	this.CheckboxElement.style.top = "1px";
	this.CheckboxElement.style.width = "12px";
	this.CheckboxElement.style.height = "12px";
	this.CheckboxElement.checked = this.Checked;
	this.DOMElement.appendChild(this.CheckboxElement);
	
	// create change event
	this.ChangeFn = function()
	{
		self.Checked = self.CheckboxElement.checked;
		if (typeof(self.OnChange) == "function")
			self.OnChange(self.Checked);
	}
	bindEvent(this.CheckboxElement, "change", this.ChangeFn);
	
	// if a container object was given add this control to it
	if (typeof(Container) != "undefined")
		Container.appendChild( this.DOMElement );
}
// re-define Move method
JW_Controls_Checkbox.prototype.Move = function(Parameters)
{
	//-------------------
}
JW.Controls.Checkbox = JW_Controls_Checkbox;


// ---------------------------------------------------------------------
// JW Tab box control Includes the tab button sub control
// ---------------------------------------------------------------------

JW.Cfg.Control.DefaultTabButton =  {Label:"Tab",
								Selected:false,
								FontSize:16,
								ZIndex:40};

JW_Controls_TabButton.prototype = JW.Control.prototype;
JW_Controls_TabButton.constructor = JW_Controls_TabButton;
function JW_Controls_TabButton(Properties, Container)
{
	var self = this;	

	// call superclass constructor
	JW.Control.call(this);

	// set default properties for tab button control
	for (var Param in JW.Cfg.Control.DefaultTabButton)
		this[Param] = JW.Cfg.Control.DefaultTabButton[Param];

	// set the properties passed to constructor
	for (var Param in Properties)
		this[Param] = Properties[Param];
		
	// force the height to be 24px
	this.Height = 24;
	
	// create container element
	this.DOMElement = document.createElement("div");
	this.DOMElement.style.position = "absolute";
	this.DOMElement.style.left = this.Left + "px";
	this.DOMElement.style.top = this.Top + "px";
	this.DOMElement.style.width = this.Width + "px";
	this.DOMElement.style.height = this.Height + "px";
	this.DOMElement.style.maxHeight = this.Height + "px";
	
	// disable text selection for this element
	JW.Lib.DisableBrowserDrag(this.DOMElement);
	
	// create edge images
	this.ImgLeft = this.CreateEdgeImage("inc/jw_tab_left_w.gif", 0);
	this.ImgLeftSel = this.CreateEdgeImage("inc/jw_tab_left_g.gif", 0);
	this.ImgRight = this.CreateEdgeImage("inc/jw_tab_right_w.gif", this.Width-12);
	this.ImgRightSel = this.CreateEdgeImage("inc/jw_tab_right_g.gif", this.Width-12);
	
	// create label div
	this.LabelElement = document.createElement("div");
	this.LabelElement.style.position = "absolute";
	this.LabelElement.style.left = "12px";
	this.LabelElement.style.width = this.Width - 24 + "px";
	this.LabelElement.style.height = "23px";
	this.LabelElement.style.borderTop = "1px solid #000";
	this.LabelElement.style.textAlign = "center";
	this.LabelElement.style.cursor = "pointer";
	this.LabelElement.style.fontSize = this.FontSize;
	this.LabelElement.style.color = this.Color;
	this.LabelElement.appendChild( document.createTextNode(this.Label) );
	this.DOMElement.appendChild( this.LabelElement );
	
	// setup click event handler
	var OnClick = function()
	{
		if (!self.Selected)
			{
			self.SetSelected(true);
			if (typeof(self.OnClick) == "function")
				self.OnClick(self);
			}
	}
	
	bindEvent(this.LabelElement, "click", OnClick);
	
	// set the selection state
	this.SetSelected(this.Selected);

	// if a container object was given add this control to it
	if (typeof(Container) != "undefined")
		Container.appendChild( this.DOMElement );
}
JW_Controls_TabButton.prototype.CreateEdgeImage = function(Src, Left)
{
	var Img = document.createElement("img");
	Img.width = 12;
	Img.height = 24;
	Img.src = Src;
	Img.style.position = "absolute";
	Img.style.left = Left + "px";
	Img.style.top = "0px";
	Img.style.width = "12px";
	Img.style.height = "24px";
	Img.style.cursor = "pointer";
	this.DOMElement.appendChild(Img);
	
	return Img;
}
JW_Controls_TabButton.prototype.SetSelected = function(NewSelected)
{
	this.Selected = NewSelected;
	
	if (this.Selected)
		{
		this.ImgLeft.style.display = "none";
		this.ImgRight.style.display = "none";
		this.ImgLeftSel.style.display = "block";
		this.ImgRightSel.style.display = "block";
		this.LabelElement.style.fontWeight = "bold";
		this.LabelElement.style.backgroundColor = "#dedede";
		this.DOMElement.style.zIndex = this.ZIndex + 10;
		}
	else
		{
		this.ImgLeft.style.display = "block";
		this.ImgRight.style.display = "block";
		this.ImgLeftSel.style.display = "none";
		this.ImgRightSel.style.display = "none";
		this.LabelElement.style.fontWeight = "";
		this.LabelElement.style.backgroundColor = "#fff";
		this.DOMElement.style.zIndex = this.ZIndex;
		}
}
JW.Controls.TabButton = JW_Controls_TabButton;

// Main Tab box control object
JW.Cfg.Control.DefaultTabBox = {TabWidth:120,
								Tabs:["Default Tab"],
								InitialTab:0};

JW_Controls_TabBox.prototype = JW.Control.prototype;
JW_Controls_TabBox.constructor = JW_Controls_TabBox;
function JW_Controls_TabBox(Properties, Container)
{
	var self = this;	

	// call superclass constructor
	JW.Control.call(this);

	// set default properties for tab button control
	for (var Param in JW.Cfg.Control.DefaultTabBox)
		this[Param] = JW.Cfg.Control.DefaultTabBox[Param];

	// set the properties passed to constructor
	for (var Param in Properties)
		this[Param] = Properties[Param];
	
	// create the DOM element for this tab box
	this.DOMElement = document.createElement("div");
	this.DOMElement.style.position = "absolute";
	this.DOMElement.style.left = this.Left + "px";
	this.DOMElement.style.top = this.Top + "px";
	this.DOMElement.style.width = this.Width + "px";
	this.DOMElement.style.height = this.Height + "px";
	
	// create the tab buttons and containers
	var TabClick = function(TabButton)
	{
		// disable all other tab buttons
		var i;
		for (i=0; i<self.TabButtons.length; ++i)
			{
			if (self.TabButtons[i] != TabButton)
				{
				self.TabButtons[i].SetSelected(false);
				self.TabAreas[i].style.display = "none";
				}
			else
				{
				self.TabAreas[i].style.display = "block";
				if (typeof(self.OnTabOpen[i]) == "function")
					self.OnTabOpen[i]();
				}
			}
	}
	this.TabButtons = [];
	this.TabAreas = [];
	this.OnTabOpen = [];
	var i;
	for (i=0; i<this.Tabs.length; ++i)
		{
		this.TabButtons[i] = new JW.Controls.TabButton({Left:i*(this.TabWidth-12),Top:0,
														Width:this.TabWidth,
														Label:this.Tabs[i],
														Selected:(i==this.InitialTab),
														OnClick:TabClick}, this.DOMElement);
		
		this.TabAreas[i] = document.createElement("div");
		this.TabAreas[i].style.position = "absolute";
		this.TabAreas[i].style.border = "1px solid #000";
		this.TabAreas[i].style.left = "0px";
		this.TabAreas[i].style.top = "24px";
		this.TabAreas[i].style.width = this.Width - 2 + "px";
		this.TabAreas[i].style.height = this.Height - 26 + "px";
		if (i != this.InitialTab)
			this.TabAreas[i].style.display = "none";
		this.DOMElement.appendChild(this.TabAreas[i]);
		
		this.OnTabOpen[i] = null;
		}
		
	// if a container object was given add this control to it
	if (typeof(Container) != "undefined")
		Container.appendChild( this.DOMElement );
}
JW.Controls.TabBox = JW_Controls_TabBox;

// ---------------------------------------------------------------------
// JW Image Select Control
// ---------------------------------------------------------------------

JW.Cfg.Control.DefaultImageSelect =    {ImageUID:-1,
										BackgroundColor:"FFFFFF",
										EmptyImage:"inc/cross_box_80x80.gif",
										OnChange:null,
										Padding:3, Border:true};

JW_Controls_ImageSelect.prototype = JW.Control.prototype;
JW_Controls_ImageSelect.constructor = JW_Controls_ImageSelect;
function JW_Controls_ImageSelect(Properties, Container)
{
	var self = this;	

	// call superclass constructor
	JW.Control.call(this);

	// set default properties for tab button control
	for (var Param in JW.Cfg.Control.DefaultImageSelect)
		this[Param] = JW.Cfg.Control.DefaultImageSelect[Param];

	// set the properties passed to constructor
	for (var Param in Properties)
		this[Param] = Properties[Param];
	
	this.ImgWidth = this.Width - 2 * this.Padding;
	this.ImgHeight = this.Height - 2 * this.Padding;
	if (this.Border)
		{
		--this.ImgWidth;
		--this.ImgHeight;
		}
	
	// create image element
	this.DOMElement = document.createElement("img");
	this.DOMElement.style.position = "absolute";
	this.DOMElement.style.left = this.Left + "px";
	this.DOMElement.style.top = this.Top + "px";
	this.DOMElement.style.width = this.ImgWidth + "px";
	this.DOMElement.style.height = this.ImgHeight + "px";
	this.DOMElement.style.padding = this.Padding + "px";
	if (this.Border)
		this.DOMElement.style.border = "1px solid #000";
	this.DOMElement.style.cursor = "pointer";
	this.DOMElement.border = 0;
	
	// disable text selection for this element
	JW.Lib.DisableBrowserDrag(this.DOMElement);
	
	this.SetImageUID(this.ImageUID);

	// bind the click event to choosing a new image
	this.Click = function()
	{	self.ChooseImage();	}
	bindEvent(this.DOMElement, "click", this.Click);
	
	// if a container object was given add this control to it
	if (typeof(Container) != "undefined")
		Container.appendChild( this.DOMElement );		
}
JW_Controls_ImageSelect.prototype.SetImageUID = function(UID)
{
	var OldUID = this.ImageUID;

	if (typeof(UID) == "string")
		{
		var Temp = parseInt(UID);
		if (!isNaN(Temp))
			this.ImageUID = Temp;
		}
	else if (typeof(UID) == "number")
		this.ImageUID = UID;
		
	if (this.ImageUID != OldUID && typeof(this.OnChange) == "function")
		this.OnChange(this.ImageUID);
	
	if (this.ImageUID == -1)
		this.DOMElement.src = this.EmptyImage;
	else
		this.DOMElement.src = "db/" + this.ImageUID + "&Thumb=" + (this.Width-2*this.Padding) + "," + (this.Height-2*this.Padding) + "," + this.BackgroundColor + ",0";
}
JW_Controls_ImageSelect.prototype.ChooseImage = function()
{
	var self = this;
	
	// create image select dialog
	var PathToRoot = JW.GetPathToRoot();
	var ImgDlg = new JAM_ImageSel_Dlg(PathToRoot + "pageman/image_op.php?Op=ImageList", this.ImageUID, true);
	
	ImgDlg.ImageSelected = function(uid, width, height)
	{
		self.SetImageUID(uid);
	}
	
	ImgDlg.Execute();
}
JW.Controls.ImageSelect = JW_Controls_ImageSelect;

//  --------------------------------------

// Jam Window Popup menu library

// define settings for the Popup menu library

JW.Cfg.PopupMenu = {};
JW.Cfg.PopupMenu.BackgroundColor = "#FFF";
JW.Cfg.PopupMenu.AutoCloseTime = 2000;
JW.Cfg.PopupMenu.HighlightColor = "#4444FF";
JW.Cfg.PopupMenu.DefaultZIndex = 5000;

// Jam Winow menu item Object
JW_MenuItem.prototype.constructor = JW_MenuItem;
function JW_MenuItem(Def, Parent)
{
	var self = this;
	
	// store the parent menu reference
	this.Parent = Parent;
	this.TimeoutId = null;
	
	// if a UID was givem in the Definition store it
	if (typeof(Def.UID) == "undefined")
		this.UID = false;
	else
		this.UID = Def.UID;
	
	// if this is a divider element it's simple
	if (Def.Label == "-")
		{
		this.Element = document.createElement("div");
		this.Element.style.marginTop = "2px";
		this.Element.style.marginBottom = "2px";
		this.Element.style.borderTop = "1px solid #888";
		this.Element.style.borderBottom = "1px solid #FFF";
		this.Element.style.height = "0px";
		this.Element.style.fontSize = "0px";
		return;
		}
	
	// this is a menu item create it
	this.Element = document.createElement("div");
	this.Element.style.paddingLeft = "18px";
	this.Element.style.color = "#000";
	this.Element.appendChild( document.createTextNode(Def.Label) );
	this.Label = Def.Label;
	
	// if  a handler was given then this is a menu item
	this.Type = "Undefines";
	if (typeof(Def.Handler) != "undefined")
		{
		this.Type = "Item";
		this.Handler = Def.Handler;
		}
	if (typeof(Def.SubMenu) != "undefined")
		{
		this.Type = "SubMenu";
		this.SubMenu = Def.SubMenu;
		this.Element.style.backgroundImage = "url(inc/icon_right_small.gif)";
		this.Element.style.backgroundRepeat = "no-repeat";
		this.Element.style.backgroundPosition = "100% 50%";
		}
		
	if (typeof(Def.Enabled) != "undefined")
		this.Enabled = Def.Enabled;
	else
		this.Enabled = true;
	
	if (this.Enabled)
		this.Element.style.cursor = "pointer";
	else
		this.Element.style.color = "#BBB";

	var PopupSubMenu = function()
	{
	if (self.Parent.OpenSubMenu != null)
		self.Parent.OpenSubMenu.Close();
	self.SubMenu.PopupAt(140, self.Element.offsetTop-3, self);
	self.TimeoutId = null;
	self.Parent.OpenSubMenu = self.SubMenu;
	}
	
	// define mouse over and out events
	this.MouseOver = function()
	{
		if (self.Enabled)
			{
			self.Element.style.backgroundColor = JW.Cfg.PopupMenu.HighlightColor;
			self.Element.style.color = "#FFF";
			if (self.Type == "SubMenu")
				{
				self.Element.style.backgroundImage = "url(inc/icon_right_white_small.gif)";
		
				if (!self.Parent.Open)
					self.TimeoutId = setTimeout(PopupSubMenu, 500);
				}
			}
	}
	this.MouseOut = function()
	{
		if (self.Enabled)
			{
			self.Element.style.backgroundColor = "";
			self.Element.style.color = "#000";
			if (self.TimeoutId != null)
				clearTimeout(self.TimeoutId);
			if (self.Type == "SubMenu")
				self.Element.style.backgroundImage = "url(inc/icon_right_small.gif)";
			}
	}
	bindEvent(this.Element, "mouseover", this.MouseOver);
	bindEvent(this.Element, "mouseout", this.MouseOut);
	
	// on click event
	this.Click = function()
	{
		if (self.Enabled)
			{
			if (self.Type == "Item")
				{
				self.Handler(self);
				self.Element.style.backgroundColor = "";
				self.Element.style.color = "";
				self.Parent.Close(true);
				}
			if (self.Type == "SubMenu")
				{
				if (self.TimeoutId != null)
					clearTimeout(self.TimeoutId);
				PopupSubMenu();
				}
			}
	}
	bindEvent(this.Element, "click", this.Click);
}

JW_MenuItem.prototype.ResetHighlight = function()
{
	if (this.Enabled)
		{
		this.Element.style.backgroundColor = "";
		this.Element.style.color = "#000";
		if (this.Type == "SubMenu")
			this.Element.style.backgroundImage = "url(inc/icon_right_small.gif)";
		}
}

JW_MenuItem.prototype.SetEnabled = function(Enabled)
{
	this.Enabled = Enabled;
	if (this.Enabled)
		{
		this.Element.style.color = "";
		this.Element.style.cursor = "pointer";
		}
	else
		{
		this.Element.style.color = "#BBB";
		this.Element.style.cursor = "";
		}
}
JW.MenuItem = JW_MenuItem;

// Jam Window Popup menu Object
//JW.PopupMenu = new Object();
JW_PopupMenu.prototype.constructor = JW_PopupMenu;
function JW_PopupMenu(Menu, ZIndex)
{
	if (typeof(ZIndex) == "undefined")
		var ZIndex = JW.Cfg.PopupMenu.DefaultZIndex;

	var TimeoutId = null;
	var self = this;
	this.Open = false;
	this.SubMenuOpen = null;
	
	// check the given Menu parameter is an array
	if (typeof(Menu) != "array" && typeof(Menu) != "object")
		return false;
		
	// create array of menu items
	this.Items = new Array();
	var i;
	for (i=0; i<Menu.length; ++i)
		this.Items[i] = new JW.MenuItem(Menu[i], this);
		
	// create dis-embodies DOM element of this menu this.MenuElement = document.createElement("div");
	this.MenuElement = document.createElement("div");
	this.MenuElement.style.position = "absolute";
	this.MenuElement.style.border = "1px solid #000";
	this.MenuElement.style.backgroundColor = JW.Cfg.PopupMenu.BackgroundColor;
	this.MenuElement.style.padding = "2px";
	this.MenuElement.style.zIndex = ZIndex;
	this.MenuElement.style.width = "150px";
	
	// mouse over and out methods, to close the menu if the mouse isn't over it for  more than n seconds
	var Timeout = function()
	{ self.Close(); }
	this.MouseOut = function()
	{
		TimeoutId = setTimeout(Timeout, JW.Cfg.PopupMenu.AutoCloseTime);
	}
	this.MouseOver = function()
	{
		if (TimeoutId != null)
			clearTimeout(TimeoutId);
	}
	bindEvent(this.MenuElement, "mouseout", this.MouseOut);
	bindEvent(this.MenuElement, "mouseover", this.MouseOver);
	
	// add menu item elements
	for (i=0; i<this.Items.length; ++i)
		this.MenuElement.appendChild(this.Items[i].Element);
}

JW_PopupMenu.prototype.PopupAt = function(DocX, DocY, Parent)
{
	if (typeof(Parent) == "undefined")
		{
		var ParentElement = JW.GetBody();
		this.ParentMenu = false;
		}
	else
		{
		var ParentElement = Parent.Element;
		this.ParentMenu = Parent;
		}

	// set menu position
	this.MenuElement.style.left = DocX + "px";
	this.MenuElement.style.top = DocY + "px";
	
	// append to body
	ParentElement.appendChild(this.MenuElement);
	this.Open = true;
}

JW_PopupMenu.prototype.Close = function(All)
{
	if (!this.Open)
		return;

	if (typeof(All) == "undefined")
		var All = false;

	// remove the menu element from the Document Object tree
	this.MenuElement.parentNode.removeChild(this.MenuElement);
	
	// there is a sub menu that's open, then close it
	if (this.OpenSubMenu != null)
		this.OpenSubMenu.Close();
	
	// remove the highlight from all menu items in this menu
	var i;
	for (i=0; i<this.Items.length; ++i)
		this.Items[i].ResetHighlight();
	
	// if there is a parent menu mark this sub-menu as not open
	if (typeof(this.ParentMenu) == "object")
		this.ParentMenu.Parent.OpenSubMenu = null;
	
	// if recurrive Close was true and this menu has a parent close that
	if (All && typeof(this.ParentMenu) == "object")
		this.ParentMenu.Parent.Close();
		
	this.Open = false;
}
JW.PopupMenu = JW_PopupMenu;

//  --------------------------------------

// Detect if the browser is IE or not.
// If it is not IE, we assume that the browser is NS.
var IE = document.all?true:false;
var AJ_mouseX;
var AJ_mouseY;
var D_mouseX;
var D_mouseY;

var AJ_RegHandler = false;
var AJ_RegUpHandler = false;
var AJ_RegObj = false;

var SourceScroll = false;;
var TargetScroll = false;

// If NS -- that is, !IE -- then set up for mouse capture
if (!IE)
	{
	document.captureEvents(Event.MOUSEMOVE);
	document.captureEvents(Event.MOUSEUP);
	}
	
// Set-up to use getMouseXY function onMouseMove
document.onmousemove = getMouseXY;
document.onmouseup = getMouseUp;

function getMouseUp()
{
	if (typeof(AJ_RegUpHandler) == "function")
		AJ_RegUpHandler();
	else
		{
		AJ_RegHandler = false;
		AJ_RegObj = false;
		}
}

// mouse movement event handler
function getMouseXY(e)
{
if (!e)
	var e = event;

if (!e || typeof(e) == "undefined")
	return;

var New_mouseX = 0;
var New_mouseY = 0;

if (IE && e.clientX && e.clientY)
	{
	if (document && document.documentElement)
		{
		//alert("typeof document.documentElement.scrollLeft is " + typeof(document.documentElement.scrollLeft) + "\nValue is " + document.documentElement.scrollLeft + "\nValue of top is " + document.documentElement.scrollTop);
		New_mouseX = e.clientX + document.documentElement.scrollLeft;
		New_mouseY = e.clientY + document.documentElement.scrollTop;
		}
	else if (document && body)
		{	
		//alert("typeof document.body.scrollLeft is " + typeof(document.body.scrollLeft) + "\nValue is " + document.body.scrollLeft + "\nValue of top is " + document.body.scrollTop);
		New_mouseX = e.clientX + document.body.scrollLeft;
		New_mouseY = e.clientY + document.body.scrollTop;
		}
	else
		{
		New_mouseX = e.clientX;
		New_mouseY = e.clientY;
		}
 	}
else if (!IE)
	{  
    New_mouseX = e.pageX;
    New_mouseY = e.pageY;
	}
	  
// catch possible negative values
if (New_mouseX < 0) New_mouseX = 0;
if (New_mouseY < 0) New_mouseY = 0;

D_mouseX = New_mouseX - AJ_mouseX;
D_mouseY = New_mouseY - AJ_mouseY;

AJ_mouseX = New_mouseX;
AJ_mouseY = New_mouseY;

if (AJ_RegHandler)
	{
	if (AJ_RegObj != false)
		AJ_RegHandler.call(AJ_RegObj);
	else
		AJ_RegHandler();
	}
	
if (SourceScroll && TargetScroll)
	{
	TargetScroll.scrollLeft = SourceScroll.scrollLeft;
	}
}

function JW_IsCSSLinked(URI)
{
	var Links = document.getElementsByTagName("LINK");
	var i;
	
	var Base = document.URL;
	Base = Base.substr(0, Base.lastIndexOf("/")+1);
	URI = Base + URI.toLowerCase();
	
	for (i=0; i<Links.length; ++i)
		if (typeof(Links[i].rel) == "string" && Links[i].rel == "stylesheet")
			if (typeof(Links[i].type) == "string" && Links[i].type == "text/css")
				if (typeof(Links[i].href) == "string" && Links[i].href.toLowerCase() == URI)
					return true;
		
	return false;
}

function JW_LinkCSS(URI)
{
	if (!JW_IsCSSLinked(URI))
		{
		var css = document.createElement("link");
		css.href = URI;
		css.rel = "stylesheet";
		css.type = "text/css";
		document.getElementsByTagName("HEAD")[0].appendChild(css);
		}
}

function ExplodeFilePath(Path, DirectorySeparator)
{
	// if the Directory Separator wasa not given assume "/"
	if (typeof(DirectorySeparator) != "string")
		var DirectorySeparator = "/";

	// object to store the path components in
	var Parts = new Object();
	
	// split the filename and path
	var LastSlash = Path.lastIndexOf(DirectorySeparator);
	if (LastSlash == -1)
		{
		Parts.FileName = Path;
		Parts.Path = "";
		}
	else
		{
		Parts.FileName = Path.substr(LastSlash+1);
		Parts.Path = Path.substr(0, LastSlash);
		}
		
	// if the path doesn't start with a slash add one
	if (Parts.Path.substr(0,1) != DirectorySeparator)
		Parts.Path = DirectorySeparator + Parts.Path;
		
	// get the extension of this file
	var LastStop = Parts.FileName.lastIndexOf(".");
	if (LastStop == -1)
		Parts.Ext = "";
	else
		Parts.Ext = Parts.FileName.substr(LastStop+1);
		
	// return object containing parts of file path
	return Parts;
}

var DebugFirst = true;

function getDocumentOffsetPosition(Element)
{
	var PosWithScroll = getBodyOffsetPosition(Element);
	
	PosWithScroll.offsetTop += GetScrollOffsetTop();
	PosWithScroll.offsetTop += GetScrollOffsetLeft();
	
	return PosWithScroll;
}

function getBodyOffsetPosition(Element)
{
	var result = new Object();
	
	//var Debug = "";
	
	result.offsetLeft = Element.offsetLeft;
	result.offsetTop = Element.offsetTop;
	
	//Debug += "St " + result.offsetLeft + "x" + result.offsetTop + " ";
	//var sc_count = 0;
	
	// compensate for scroll offsets of all ancestor elements
	var Element2 = Element.parentNode;
	while (typeof(Element2) == "object" && Element2 != null && typeof(Element2.scrollTop) == "number")
		{
		//++sc_count;
		//if (Element2.scrollLeft != 0 || Element2.scrollTop != 0)
		//	{
		//	Debug += " Sc off \"" + Element2.nodeName + "\" " + Element2.scrollLeft + "x" + Element2.scrollTop + " ";
		//	}
			
		result.offsetLeft -= Element2.scrollLeft;
		result.offsetTop -= Element2.scrollTop;
		Element2 = Element2.parentNode;
		}
		
	//Debug += "chkd " + sc_count + " scr offs";
	
	//document.getElementById("Debug").innerHTML += Debug;
	//alert("Sommat");

	// sum up all Parent offsets.
	if (Element.offsetParent != null)
		do	{
			Element = Element.offsetParent;
			result.offsetLeft += Element.offsetLeft;
			result.offsetTop += Element.offsetTop;
			}
		while (Element.nodeName != "HTML" && Element.nodeName != "BODY")
		
	return result;
}

// Function to set the opacity of the given DOM element
// Opacity is in the range of 0-100
function SetElementOpacity(Element, NewOpacity)
{
	setElementOpacity(Element, NewOpacity);
}
function setElementOpacity(Element, NewOpacity)
{
if (NewOpacity < 0)
	NewOpacity = 0;
if (NewOpacity > 100)
	NewOpacity = 0;
	
// create range value values
ZeroToOne = (NewOpacity/100.0).toFixed(2);
ZeroTo100 = NewOpacity.toFixed(0);

// create filter style string
FilterStr = "alpha(opacity=" + ZeroTo100 + ")";

Element.style.position = "relative";
if (IE)	Element.style.filter = FilterStr;
Element.style.opacity = ZeroToOne;
Element.style.mozOpacity = ZeroToOne;
}

function clearElementOpacity(Element)
{
Element.style.filter = "";
Element.style.opacity = "";
Element.style.opacity = "";
}

// A function foefully lacking from JS
// TRIM
function trimStr(string)
{
var start = 0;
var end = 0;

// find how many characters to trim from the start
while (string[start] == " " || string[start] == "\t")
	++start;
	
// find how many characters to trim from the end
while (string[string.length-1-end] == " " || string[string.length-1-end] == "\t")
	++end;
	
trimString = string.substr(start, string.length - start - end);

return trimString;
}

// Function to bind the given function to an event on the given element
// cross browser compatible.
function bindEvent(Element, Event, Handler, capture)
{
	// NS/Firefox	
	if (window.addEventListener)
		{
		if (typeof(capture) == "undefined" || !capture)
			Element.addEventListener(Event, Handler, false);
		else
			Element.addEventListener(Event, Handler, true);
		}
	// IE
	if (window.attachEvent)
		Element.attachEvent("on" + Event, Handler);
}

function JAM_EventTarget(e)
{
var targ;
if (!e) var e = window.event;
if (e.target) targ = e.target;
else if (e.srcElement) targ = e.srcElement;
if (targ.nodeType == 3) // defeat Safari bug
	targ = targ.parentNode;
	
return targ;
}

function forceInt(oldStr, allowNegative)
{
var newStr = "";
for (i=0; i<=oldStr.length; ++i)
	{
	var c;
	c = oldStr.substr(i,1);
	if (allowNegative == true)
		{
		if (/-|\d/.test(c))
			newStr = newStr + c;
		}
	else
		{
		if (/\d/.test(c))
			newStr = newStr + c;
		}
	}
return newStr;
}

// function that will force a text input to be numeric, bind it to an inputs key up event
function JAM_ForceInputInt(e)
{
	var Input = JAM_EventTarget(e);
	
	if (Input.value)
		Input.value = forceInt(Input.value, true);
}

// function that will force a text input to be positive integer, bind it to an inputs key up event
function JAM_ForceInputPosInt(e)
{
	var Input = JAM_EventTarget(e);
	
	if (Input.value)
		Input.value = forceInt(Input.value, false);
}

function forceFloat(oldStr)
{
var newStr = "";
for (i=0; i<=oldStr.length; ++i)
	{
	var c;
	c = oldStr.substr(i,1);
	if (/\.|-|\d/.test(c))
		newStr = newStr + c;
	}
return newStr;
}

// function that will force a text input to be positive integer, bind it to an inputs key up event
function JAM_ForceInputFloat(e)
{
	var Input = JAM_EventTarget(e);
	
	if (Input.value)
		Input.value = forceFloat(Input.value);
}



function JAM_InitGetWindowSize()
{
res = new Object();

res.width = 800;
res.height = 600;

// proper web browsers (mozilla, netscape, opera)
if (typeof window.innerWidth != 'undefined')
	{
	res.width = window.innerWidth,
	res.height = window.innerHeight
	}
// IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)
else if (typeof document.documentElement != 'undefined'
		  && typeof document.documentElement.clientWidth != 'undefined'
		  && document.documentElement.clientWidth != 0)
	{
	res.width = document.documentElement.clientWidth,
	res.height = document.documentElement.clientHeight
	}
// older versions of IE
else
	{
	var Body = document.getElementsByTagName('body')[0];
	if (typeof(Body) == "object")
		{
		res.width = Body.clientWidth,
		res.height = Body.clientHeight
		}
	}
	
return res;
}

// Inline Pause function
// messy but it's the best that can be done in JS

function JAM_Pause(duration) // in milliseconds
{
	var endTime = new Date();
	endTime += duration;
	
	while (endTime > new Date());
}

// get the window size once on startup then return a copy of this if requested
JAM_WindowSize = JAM_InitGetWindowSize();

function JAM_GetWindowSize()
{
	return JAM_WindowSize;
}

function JAM_D_AnalyzeVar(Var, Target)
{
	// get the type of the Variable
	var Type = typeof(Var);
	var Output = "Variable is a \"" + Type + "\"<br />";
	if (Type == "object")
		{
		Output + "looking for properties\n";
		for (var Property in Var)
			{
			try	{
				var Prop = Var[Property];
				var SProp = ""; SProp += Prop;
				var PType = typeof(Prop);
				
				if (PType == "object")
					Output += "  <font color=\"blue\">" + Property + " " + Prop + "</font><br />";
				else if (PType == "function")
					Output += "  <font color=\"green\">" + SProp.substr(0, SProp.indexOf("{")) + "</font><br />";
				else
					Output += "  <font color=\"red\">" + Property + " (" + PType + ") [" + Prop + "]</font><br />";
				}
			catch (e)
				{
				Output += "  " + Property + " (failed to get details)<br />";
				}
			}
		}
		
	if (Target)
		Target.innerHTML = Output;
	else
		alert(Output);
}

JAM_GetComputedStyle = function(ele, style)
{
	var computedStyle;
	if (typeof ele.currentStyle != 'undefined')
		computedStyle = ele.currentStyle;
	else
		computedStyle = document.defaultView.getComputedStyle(ele, null);
		
	return computedStyle[style];
}

// Method to set the absolute positioning of block type element
function PlaceElement(ele, left, top, width, height, zIndex)
{
	if (!zIndex)
		zIndex = 30;
	
	//alert("Placing element at position " + left + "x" + top + " size " + width + "x" + height);
	
	ele.style.position = "absolute";
	ele.style.zIndex = zIndex;
	ele.style.left = left + "px";
	ele.style.top = top + "px";
	ele.style.width = width + "px";
	ele.style.height = height + "px";
}

// Method to place an element at the center of the screen
function PlaceElementScreenCenter(ele, width, height, zIndex)
{
	SS = JAM_GetWindowSize();
	
	//alert("window size " + SS.width + "x" + SS.height);
		
	var left = ((SS.width/2) - (width/2)).toFixed(0);
	var top = ((SS.height/2) - (height/2)).toFixed(0);
	
	docBody = document.getElementsByTagName("BODY")[0];
	
	PlaceElement(ele, left, top, width, height, zIndex);
	docBody.appendChild(ele);
}

// Method to remove all children of the given element from the DOM tre
function RemoveChildren(Ele)
{
	try	{
		for (i=Ele.childNodes.length-1; i>=0; --i)
			Ele.removeChild(Ele.childNodes[i]);
		}
	catch (e)
		{
		}
}

// Method to get the scrolling offset of the page document
function GetScrollOffsetTop()
{
	var OffsetTop = 0;
	
	if (document.documentElement && document.documentElement.scrollTop)
		OffsetTop = document.documentElement.scrollTop;
	else if (document.body)
		OffsetTop = document.body.scrollTop;
		
	return OffsetTop;
}
function GetScrollOffsetLeft()
{
	var OffsetLeft = 0;
	
	if (document.documentElement && document.documentElement.scrollLeft)
		OffsetLeft = document.documentElement.scrollLeft;
	else if (document.body)
		OffsetLeft = document.body.scrollLeft;
		
	return OffsetLeft;
}

// Method to get the document size and scroll offsets
function GetDocumentGeometry()
{
	var Geo = new Object();
	
	if (document.documentElement && document.documentElement.scrollLeft)
		{
		Geo.Width = document.documentElement.scrollWidth;
		Geo.Height = document.documentElement.scrollHeight;
		Geo.ScrollLeft = document.documentElement.scrollLeft;
		Geo.ScrollTop = document.documentElement.scrollTop;
		}
	else if (document.body)
		{
		Geo.Width = document.body.scrollWidth;
		Geo.Height = document.body.scrollHeight;
		Geo.ScrollLeft = document.body.scrollLeft;
		Geo.ScrollTop = document.body.scrollTop;
		}
			
	return Geo;
}

function JW_CreateThrobberImg()
{
	var Img = document.createElement("img");
	Img.width = 32;
	Img.height = 32;
	Img.border = 0;
	Img.align = "absmiddle";
	Img.src = "inc/icon_loading.gif";
	return Img;
}

function CreatePartialScreen(position, color, opacity, z_index, id)
{
switch (color)
	{
	case false:	color = "FFFFFF";	break;
	case "black":	color = "000000";	break;
	case "white":	color = "FFFFFF";	break;
	}
	
element = document.createElement("div");

setElementOpacity(element, opacity);

element.style.backgroundColor = "#" + color;
element.style.position = "absolute";
element.style.top = position.Top + "px";
element.style.left = position.Left + "px";
element.style.width = position.Width + "px";
element.style.height = position.Height + "px";
element.style.zIndex = z_index;

element.innerHTML = "&nbsp;";
if (id)
	element.id = id;

document.getElementsByTagName("BODY")[0].appendChild(element);

return element;
}

// Method to create a 50% alpha screen of the given colour and add it to the body element
function CreateScreen(color, opacity, z_index, id)
{
switch (color)
	{
	case false:	color = "FFFFFF";	break;
	case "black":	color = "000000";	break;
	case "white":	color = "FFFFFF";	break;
	}
	
var element = document.createElement("div");

var Geometry = GetDocumentGeometry();
//alert("creating a screen with a height of : " + Geometry.Height + "px\nAnd a width of : " + Geometry.Width + "px");

setElementOpacity(element, opacity);

element.style.backgroundColor = "#" + color;
element.style.position = "absolute";
element.style.top = "0px";
element.style.left = "0px";
element.style.width = Geometry.Width + "px";
element.style.height = Geometry.Height + "px";
element.style.zIndex = z_index;

element.innerHTML = "&nbsp;";
if (id)
	element.id = id;

document.getElementsByTagName("BODY")[0].appendChild(element);

return element;
}

function getStyleDim(str)
{
return (parseInt( str.substr(0, str.length-2) ));
}

// function to remove the given element from the DOM tree
function RemoveElement(element)
{ removeElement(element); }
function removeElement(element)
{
	element.parentNode.removeChild(element);
}

function JW_SetClass(Element, Class)
{
	//Element.setClass(Class);
	Element.className = Class;
}

//----------------------------------------------------------------------
// JAM blocker message object
//----------------------------------------------------------------------

function JAM_Blocker(Msg)
{
	// create background screen
	this.Screen = CreateScreen("white", 75, 65534, "blocker_screen");
	
	// create message div
	this.MsgDiv = document.createElement("div");
	this.MsgDiv.style.backgroundColor = "#FFFFFF";
	this.MsgDiv.style.border = "1px solid black";
	this.MsgDiv.style.textAlign = "center";
	this.MsgDiv.appendChild( document.createElement("br") );
	this.MsgDiv.appendChild( document.createTextNode(Msg) );
	this.MsgDiv.appendChild( document.createElement("br") );
	this.MsgDiv.appendChild( document.createElement("br") );
	
	this.Throber = document.createElement("img");
	this.Throber.src = "inc/icon_loading.gif";
	this.Throber.width = "32";
	this.Throber.height = "32";
	this.MsgDiv.appendChild( this.Throber );

	// place the message div at the center of the screen (a bit messy but it works on IE 5.5 which doesn't support fixed positioning
	SS = JAM_GetWindowSize();
	
	ScrollTop = GetScrollOffsetTop();
	
	var width = 300;
	var height = 200;
		
	var left = ((SS.width/2) - (width/2)).toFixed(0);
	var top = (ScrollTop + (SS.height/2) - (height/2)).toFixed(0);
	
	Body = document.getElementsByTagName("BODY")[0];

	Body.appendChild(this.MsgDiv);

	PlaceElement(this.MsgDiv, left, top, width, height, 65535);
}

//---------------------------------------------------------------------- 
// JAM progress bar object
//----------------------------------------------------------------------

function JAM_ProgressBar(Target)
{	
	this.StartTime = new Date();
	this.Target = 100;
	this.Position;
	
	this.ForcastText = "Waiting. . .";
	this.RemainingSecs = null;
	
	this.Element = document.createElement("div");
	this.Element.style.borderTop = "2px solid gray";
	this.Element.style.borderLeft = "2px solid grey";
	this.Element.style.borderBottom = "2px solid black";
	this.Element.style.borderRight = "2px solid black";
	
	
	//this.Element.style.topBorder = "2px solid grey";
	//this.Element.style.leftBorder = "2px solid grey";
	//this.Element.style.borderTop = "2px solid white";
	//this.Element.style.borderLeft = "2px solid white";
	this.BorderWidth = 2;
	
	this.BarElement = document.createElement("div");
	this.BarElement.style.display = "none";
	this.BarElement.style.border = "1px solid blue";
	this.BarElement.style.zIndex = 200;
	this.BarElement.style.backgroundColor = "blue";
	this.Element.appendChild(this.BarElement);
	
	this.ForecaseChange = function() { }
	
	this.Completed = false;
	
	// if a target size was given set it
	if (typeof(Target) == "number")
		{
		if (Target == 0)
			alert("Error : Attempt to set a target value of zero in Progress Bar constructor.");
			
		this.Target = Target;
		}
}

// Empty forecast change event, can be overridden to keep a text element upto date.
//JAM_ProgressBar.prototype.ForecastChange = function(NewText, NewSeconds)
//{ }

// Method to format the remaining text string
JAM_ProgressBar.prototype.FormatForecastText = function(RemainingSecs)
{
	if (RemainingSecs != 0)
		this.ForecastText = Math.round(RemainingSecs) + " Seconds Left";
	else
		this.ForecastText = "Complete";
	
	return this.ForecastText;
}

// Method to set the position of the progress bar
JAM_ProgressBar.prototype.Update = function(Progress)
{
	var Factor;
	var Now;
	var ElapsedSecs;
	
	// if a numeric progress value was not given show error and return
	if (typeof(Progress) != "number")
		{
		alert("Error : progress parameter to Update method not numeric.");
		return;
		}
	
	// calculate the current progress as a factor
	this.Position = Progress;
	Factor = Math.min(this.Position / this.Target, 1);
	
	// if the progress bas has completed set flag
	if (Factor == 1)
		this.Completed = true;
	
	// if there has been any progress update the forecast
	if (Factor > 0)
		{
		Now = new Date();
		ElapsedSecs = (Now.getTime() - this.StartTime.getTime()) / 1000;
		
		this.RemainingSecs = (1-Factor) * (ElapsedSecs / Factor);
		
		this.FormatForecastText(this.RemainingSecs);
		
		this.ForecastChange(this.ForecastText, this.ForecastSecs);
		}
		
	// position the bar element
	Top = 0;
	Left = 0;
	Width = this.Element.offsetWidth - (2 * this.BorderWidth) - 2;
	Height = this.Element.offsetHeight - (2 * this.BorderWidth) - 2;

	PlaceElement(this.BarElement, Top,Left, Width*Factor,Height);
	this.BarElement.style.display = "block";
}

// Method to reset the start time of this progress bar (for prediction)
JAM_ProgressBar.prototype.Reset = function()
{
	this.StartTime = new Date();
	this.Update(0);
}


//----------------------------------------------------------------------
// JAM Button object
//----------------------------------------------------------------------

function JAM_Button(title)
{
	this.Title = title;
	this.Element = document.createElement("div");
	if (typeof(title) != "object")
		this.Element.innerHTML = title;
	else
		{
		title.style.cursor = "pointer";
		this.Element.appendChild(title);
		}
	//this.Element.appendChild( document.createTextNode(title) );
	this.Element.setAttribute("class", "jam_w_button");
	this.Element.className = "jam_w_button";
	this.Element.style.cursor = "pointer";
	
	this.Enabled = true;
	
	var self = this;
	
	// internal event handlers
	mouseIn = function()
	{
	if (self.Enabled)
		{
		self.Element.setAttribute("class", "jam_w_button_hover");
		self.Element.className = "jam_w_button_hover";
		}
	}
	mouseOut = function()
	{
	if (self.Enabled)
		{
		self.Element.setAttribute("class", "jam_w_button");
		self.Element.className = "jam_w_button";
		}
	}
	mouseDown = function()
	{
	if (self.Enabled)
		{
		self.Element.setAttribute("class", "jam_w_button_down");
		self.Element.className = "jam_w_button_down";
		}
	}
	mouseUp = function()
	{
	if (self.Enabled)
		{
		self.Element.setAttribute("class", "jam_w_button");
		self.Element.className = "jam_w_button";
		}
	}
	mouseClick = function()
	{
	if (self.Enabled)	self.OnClick();
	}
	
	bindEvent(this.Element, "mouseover", mouseIn);
	bindEvent(this.Element, "mouseout", mouseOut);
	bindEvent(this.Element, "mousedown", mouseDown);
	bindEvent(this.Element, "mouseup", mouseUp);
	bindEvent(this.Element, "click", mouseClick);
}

// external event handler prototype
JAM_Button.prototype.OnClick = function() { }

// method to change the button label
JAM_Button.prototype.SetLabel = function(newLabel)
{
	this.Title = newLabel;
	this.Element.innerHTML = newLabel;
}
JAM_Button.prototype.setLabel = function(newLabel)
{ this.SetLabel(newLabel); }

JAM_Button.prototype.SetEnabled = function(newEnabled)
{
	this.Enabled = newEnabled;
	
	if (this.Enabled)
		{
		this.Element.setAttribute("class", "jam_w_button");
		this.Element.className = "jam_w_button";
		}
	else
		{
		this.Element.setAttribute("class", "jam_w_button_disabled");
		this.Element.className = "jam_w_button_disabled";
		}
}

//----------------------------------------------------------------------
// JAM Tab Box object
//----------------------------------------------------------------------

function JAM_TabBox(width, height, tabList)
{
	var self = this;
	
	// create main container div
	this.Container = document.createElement("div");
	this.Container.style.width = width + "px";
	this.Container.style.height = height + "px";
	
	this.TabPages = new Array(tabList.length);
	this.TabBtns = new Array(tabList.length);
	this.TabLabels = tabList;
	this.ActiveTab = 0;
	
	// tab btn click event handler
	TabClick = function(e)
	{
		targ = JAM_EventTarget(e);
		
		while (isNaN(parseInt(targ.id)))
			targ = targ.parentNode;
		
		self.SetTab(targ.id);
	}
	
	// for each tab create the tab button
	for (i=0; i<tabList.length; ++i)
		{
		Btn = document.createElement("div");
		if (i==0)
			{
			Btn.setAttribute("class", "jam_w_tab_btn_active");
			Btn.className = "jam_w_tab_btn_active";
			}
		else
			{
			Btn.setAttribute("class", "jam_w_tab_btn");
			Btn.className = "jam_w_tab_btn";
			}
		//Btn.setAttribute("style", "float:left");	// everything else
		Btn.style.cssFloat = "left";		// standards method
		Btn.style.styleFloat = "left";		// IE.
		Btn.style.cursor = "pointer";
		Btn.style.height = "21px";
		Btn.style.border = "1px solid black";
		Btn.style.marginLeft = "8px";
		Btn.style.zIndex = "35";
		Btn.id = i;
		Btn.appendChild( document.createTextNode(tabList[i]) );
		
		bindEvent(Btn, "click", TabClick);
		
		this.Container.appendChild( Btn );
		this.TabBtns[i] = Btn;
		}
		
	// create a tab page for each tab
	for (i=0;  i<tabList.length; ++i)
		{
		Page = document.createElement("div");
		Page.setAttribute("class", "jam_w_tab_page");
		Page.className = "jam_w_tab_page";
		if (i>0)
			Page.style.display = "none";
		Page.style.clear = "left";
		Page.style.border = "1px black solid";
		Page.style.position = "relative";
		Page.style.top = "-1px";
		Page.style.width = (width) + "px";
		Page.style.height = (height - 24) + "px";
		Page.fontSize = "small";
		
		this.Container.appendChild(Page);
		this.TabPages[i] = Page;
		}
}

// Method to set the active tab
JAM_TabBox.prototype.SetTab = function(TabIndex)
{
	// hide the currennt tab
	this.TabPages[this.ActiveTab].style.display = "none";
	this.TabBtns[this.ActiveTab].setAttribute("class", "jam_w_tab_btn");
	this.TabBtns[this.ActiveTab].className = "jam_w_tab_btn";
	
	this.ActiveTab = TabIndex;
	this.TabPages[TabIndex].style.display = "block";
	this.TabBtns[TabIndex].setAttribute("class", "jam_w_tab_btn_active");
	this.TabBtns[TabIndex].className = "jam_w_tab_btn_active";
}

// Method to get a tab page element
JAM_TabBox.prototype.GetTabPage = function(TabIndex)
{
	return this.TabPages[TabIndex];
}

// Method to get the main tab container
JAM_TabBox.prototype.GetContainer = function()
{
	return this.Container;
}

//----------------------------------------------------------------------
// JAM Window object
//----------------------------------------------------------------------

function JAM_Window(title, width, height, position_left, right, noScreen, zIndex)
{
	if (!zIndex)
		zIndex = 21;
		
	// if no width or height was given don't bother
	if (!width || !height)
		return;
	
	if (position_left == "center")
		{
		SS = JAM_GetWindowSize();
		ScrollTop = GetScrollOffsetTop();	
		var left = ((SS.width/2) - (width/2)).toFixed(0);
		var top = (ScrollTop + (SS.height/2) - (height/2)).toFixed(0);
		}
	else
		left = position_left;
		
	// save the size of the window for future reference
	this.Width = width;
	this.Height = height;
	
	this.LoadingDiv = null;
	
	// init buttons array
	this.JW_Buttons = new Array();
	
	if (!noScreen)
		this.Screen = CreateScreen("white", 0, zIndex-1);
	else
		this.Screen = CreateScreen("white", 0, zIndex-1);
	
	this.Window = document.createElement("div");
	Body = document.getElementsByTagName("BODY")[0];
	Body.appendChild(this.Window);
	
	PlaceElement(this.Window, left, top, width, height, zIndex);
	this.Window.style.border = "1px black solid";
	this.Window.style.backgroundColor = "white";
	
	if (typeof(title) == "string" && title != "")
		this.AddTitle(title);
	
	this.DSOffset = 1;
	if (IE)
		this.DSOffset = -1
	
	// add drop shadow images (if this is not IE 6 in which case don't bother it's crap)
	this.DSImageTopRight = document.createElement("img");
	this.DSImageTopRight.width = 20;
	this.DSImageTopRight.height = 30;
	this.DSImageTopRight.src = "inc/jw_ds_tr.png";
	this.Window.appendChild(this.DSImageTopRight);
	
	this.DSImageRight = document.createElement("img");
	this.DSImageRight.width = 20;
	this.DSImageRight.height = height-40+this.DSOffset;
	this.DSImageRight.src = "inc/jw_ds_r.png";
	this.Window.appendChild(this.DSImageRight);
	
	this.DSImageBottomRight = document.createElement("img");
	this.DSImageBottomRight.width = 30;
	this.DSImageBottomRight.height = 30;
	this.DSImageBottomRight.src = "inc/jw_ds_br.png";
	this.Window.appendChild(this.DSImageBottomRight);
	
	this.DSImageBottom = document.createElement("img");
	this.DSImageBottom.width = width-40+this.DSOffset;
	this.DSImageBottom.height = 20;
	this.DSImageBottom.src = "inc/jw_ds_b.png";
	this.Window.appendChild(this.DSImageBottom);
	
	this.DSImageBottomLeft = document.createElement("img");
	this.DSImageBottomLeft.width = 30;
	this.DSImageBottomLeft.height = 20;
	this.DSImageBottomLeft.src = "inc/jw_ds_bl.png";
	this.Window.appendChild(this.DSImageBottomLeft);
	
	this.ResizeWindow(width, height);
}

JAM_Window.prototype.ResizeWindow = function(width, height)
{
	this.Window.style.width = width + "px";
	this.Window.style.height = height + "px";

	PlaceElement(this.DSImageTopRight, width+this.DSOffset,0, 20,30, 30);
	PlaceElement(this.DSImageRight, width+this.DSOffset,30, 20,height-40+this.DSOffset, 30);
	PlaceElement(this.DSImageBottomRight, width-10+this.DSOffset,height-10+this.DSOffset, 30,30, 30);
	PlaceElement(this.DSImageBottom, 30,height+this.DSOffset, width-40+this.DSOffset,20, 30);
	PlaceElement(this.DSImageBottomLeft, 0,height+this.DSOffset, 30,20, 30);
}

JAM_Window.prototype.SetupButton = function(Content, Event)
{
	// add button details to JW_Buttons array
	var Button = new Object();
	Button.Content = Content;
	Button.Event = Event;
	
	var Index = this.JW_Buttons.length;
	this.JW_Buttons[Index] = Button;
}

JAM_Window.prototype.CreateButtons = function()
{
	var ButtonTop = this.Height-40;
	var TotalWidth = (120 * this.JW_Buttons.length) - 20;
	var LeftEdge = (this.Width - TotalWidth) / 2;
	var i;
	
	for (i=0; i<this.JW_Buttons.length; ++i)
		{
		var NewButton = new JAM_Button(this.JW_Buttons[i].Content);
		NewButton.OnClick = this.JW_Buttons[i].Event;
		this.JW_Buttons[i].Btn = NewButton;
		PlaceElement(NewButton.Element, LeftEdge + (120*i),ButtonTop, 100,18, 30);
		this.Window.appendChild( NewButton.Element );
		}
}

JAM_Window.prototype.CreateWaitingDiv = function(Msg, Show)
{	
	var Width = 200;
	var Height = 50;
	
	if (typeof(Show) == "undefined")
		var Show = false;
	
	this.LoadingDiv = document.createElement("div");
	
	if (!Show)
		this.LoadingDiv.style.display = "none";
	
	PlaceElement(this.LoadingDiv, (this.Width - Width) / 2, (this.Height - Height) / 2, Width, Height, 30);
	this.LoadingDiv.style.textAlign = "center";
	this.LoadingDiv.style.fontSize = "small";
	this.LoadingDiv.style.width = "250px";
	this.LoadingDiv.style.border = "1px solid black";
	this.LoadingDiv.style.backgroundColor = "#FFF";
	this.LoadingDivMsg = document.createElement("span");
	this.LoadingDivMsg.appendChild( document.createTextNode(Msg) );
	this.LoadingDiv.appendChild( this.LoadingDivMsg );
	this.LoadingDiv.appendChild( document.createElement("br") );
	Icon = document.createElement("img");
	Icon.src = "../shared/icons/icon_loading.gif";
	Icon.width = 32;
	Icon.height = 32;
	this.LoadingDiv.appendChild(Icon);
	this.Window.appendChild(this.LoadingDiv);
}

JAM_Window.prototype.SetWaitingDivMsg = function(Msg, Show)
{
	if (typeof(Show) == "undefined")
		var Show = false;
	
	if (typeof(this.LoadingDiv) == "object")
		{
		RemoveChildren(this.LoadingDivMsg);
		this.LoadingDivMsg.appendChild( document.createTextNode(Msg) );
		
		if (Show)
			this.LoadingDiv.style.display = "block";
		}
}

JAM_Window.prototype.ShowWaitingDiv = function()
{
	if (typeof(this.LoadingDiv) == "object")
		this.LoadingDiv.style.display = "block";
}

JAM_Window.prototype.HideWaitingDiv = function()
{
	if (typeof(this.LoadingDiv) == "object")
		this.LoadingDiv.style.display = "none";
}

JAM_Window.prototype.AddTitle = function(Content)
{
	this.TitleDiv = document.createElement("div");
	if (IE)
		PlaceElement(this.TitleDiv, 0,0, this.Width,20, 30);
	else
		PlaceElement(this.TitleDiv, 0,0, this.Width,20, 30);
	this.TitleDiv.style.borderBottom = "1px solid black";
	this.TitleDiv.style.fontSize = "16px";
	this.TitleDiv.style.fontWeight = "bold";
	this.TitleDiv.style.textAlign = "center";
	this.TitleDiv.style.paddingTop = "5px";
	this.TitleDiv.style.paddingBottom = "5px";
	//this.TitleDiv.style.backgroundColor = "#acb4ff";
	this.TitleDiv.style.backgroundImage = "url(inc/jw_title_bg.jpg)";
	this.TitleDiv.style.backgroundPosition = "0%0%";
	this.TitleDiv.style.backgroundRepeat = "no-repeat";
	
	if (typeof(Content) == "string")
		this.TitleDiv.appendChild( document.createTextNode(Content) );
	else
		this.TitleDiv.appendChild( Content );
	
	this.Window.appendChild(this.TitleDiv);
	this.MakeDraggable(this.TitleDiv);
}

JAM_Window.prototype.SetTitle = function(Content)
{
	RemoveChildren(this.TitleDiv);

	if (typeof(Content) == "string")
		this.TitleDiv.appendChild( document.createTextNode(Content) );
	else
		this.TitleDiv.appendChild( Content );
}

JAM_Window.prototype.MakeDraggable = function(Element)
{
	if (typeof(Element) != "object")
		Element = this.Window;
	
	var self = this;
	
	// set the element cursor to the pointer
	Element.style.cursor = "pointer";
	
	// Start Dragging Event
	function dragStartEvent(e)
	{
		D_mouseX = 0;
		D_mouseY = 0;
		
		AJ_RegObj = self;
		AJ_RegHandler = JAM_Window.prototype.DragEvent;
		
		// stop default browser behavior (start selection)
		if (typeof(e.preventDefault) == "function")
			e.preventDefault();
		e.returnValue = false;
	}
	bindEvent(Element, "mousedown", dragStartEvent);
		
	// IE specific events that need to have their default behavior prevented
	function stopIE(e)
	{
		// stop default browser behavior (start selection)
		if (typeof(e.preventDefault) == "function")
			e.preventDefault();
		e.returnValue = false;
	}
	bindEvent(Element, "selectstart", stopIE);
	bindEvent(Element, "dragstart", stopIE);
}

JAM_Window.prototype.DragEvent = function()
{
	// get the current left and top position of the window
	var CurLeft = this.Window.offsetLeft;
	var CurTop = this.Window.offsetTop;
	
	// calculate new position
	var NewLeft = CurLeft + D_mouseX;
	var NewTop = CurTop + D_mouseY;
	
	// set new position
	this.Window.style.left = NewLeft + "px";
	this.Window.style.top = NewTop + "px";
}

JAM_Window.prototype.Remove = function()
{
	Body = document.getElementsByTagName("BODY")[0];
	
	Body.removeChild(this.Window);
	if (this.Title)
		Body.removeChild(this.Title);
	if (this.Screen)
		Body.removeChild(this.Screen);
}

//----------------------------------------------------------------------
// JAM IframeTarget object
//----------------------------------------------------------------------

function JAM_IframeTarget(Name, Container)
{
	var self = this;
	
	// store name of iframe
	this.Name = Name;
	
	// create iframe element
	this.UplIFrame = document.createElement("iframe");
	this.UplIFrame.name = Name;
	this.UplIFrame.style.width = "0px";
	this.UplIFrame.style.height = "0px";
	this.UplIFrame.style.border = "0px";
	
	if (Container == "undefined")
		document.getElementsByTagName("body")[0].appendChild(this.UplIFrame);
	else
		Container.appendChild(this.UplIFrame);
		
	// IE BUG FIX (yes another one!)
	// ensure the iframe name still matches what it should be
	frames[frames.length-1].name = Name;
	
	//JAM_D_AnalyzeDialog(frames, "frames");
	
	// create polling function to check content of iframe
	this.UplPoll = function()
	{	
		var Content = "";
	
		try {
			// get new refernce to the document object of the iframe window
			// it changes when the frame reloads
			var FrameDoc = self.UplIFrame.contentWindow || self.UplIFrame.contentDocument;
			if (FrameDoc.document)
				FrameDoc = FrameDoc.document;
			
			// get the html content of iframe
			Content = FrameDoc.body.innerHTML;
			}
		catch (e) {}

		if (Content != "")
			{
			// call the onChange event
			self.OnChange(Content);
			
			// clear iframe content
			FrameDoc.body.innerHTML = "";
			}
	
		// restart callback
		setTimeout(self.UplPoll, 500);
	}
	
	// start polling iframe
	this.UplPoll();
}

// on change event definition
JAM_IframeTarget.prototype.OnChange = function (Content) {}


//----------------------------------------------------------------------
// JAM MsgBox object
//----------------------------------------------------------------------

function JAM_MsgBox(Type, Message)
{
	this.Type = Type;
	this.Message = Message;

	this.Window = false;
}

// empty event handler functions
JAM_MsgBox.prototype.Cancel = function() {}
JAM_MsgBox.prototype.Ok = function() {}
JAM_MsgBox.prototype.Yes = function() {}
JAM_MsgBox.prototype.No = function() {}

// execute method to create the messagebox
JAM_MsgBox.prototype.Execute = function()
{
	var self = this;
	
	this.Window = new JAM_Window("", 400, 130, "center", false, true, 200);
	
	this.MsgDiv = document.createElement("div");
	this.MsgDiv.style.textAlign ="center";
	this.MsgDiv.style.fontSize = "small";
	PlaceElement(this.MsgDiv, 100, 30, 200, 70, 31);
	this.MsgDiv.appendChild( document.createTextNode(this.Message) );
	this.Window.Window.appendChild(this.MsgDiv);
	
	if (this.Type == "YesNo")
		{
		this.YesBtn = new JAM_Button("Yes");
		PlaceElement(this.YesBtn.Element, 210, 90, 80, 20, 31);
		this.YesBtn.OnClick = function()
		{
			self.Window.Remove();
			self.Yes();
		};
		this.Window.Window.appendChild(this.YesBtn.Element);
		
		this.NoBtn = new JAM_Button("No");
		PlaceElement(this.NoBtn.Element, 110, 90, 80, 20, 31);
		this.NoBtn.OnClick = function()
		{
			self.Window.Remove();
			self.No();
		};
		this.Window.Window.appendChild(this.NoBtn.Element);
		
		this.Icon = document.createElement("img");
		this.Icon.src = "../shared/icons/icon_msgbox_question.gif";
		this.Icon.width = 64;
		this.Icon.height = 64;
		PlaceElement(this.Icon, 318, 20, 64, 64, 31);
		this.Window.Window.appendChild(this.Icon);
		
		}
		
	else if (this.Type == "Ok")
		{
		this.OkBtn = new JAM_Button("OK");
		PlaceElement(this.OkBtn.Element, 160, 90, 80, 20, 31);
		this.OkBtn.OnClick = function()
		{
			self.Window.Remove();
			self.Ok();
		};
		this.Window.Window.appendChild(this.OkBtn.Element);
		
		}
		
	else if (this.Type == "OkCancel")
		{
		this.CancelBtn = new JAM_Button("Cancel");
		PlaceElement(this.CancelBtn.Element, 110, 90, 80, 20, 31);
		this.CancelBtn.OnClick = function()
		{
			self.Window.Remove();
			self.Cancel();
		};
		this.Window.Window.appendChild(this.CancelBtn.Element);
		
		this.OkBtn = new JAM_Button("OK");
		PlaceElement(this.OkBtn.Element, 210, 90, 80, 20, 31);
		this.OkBtn.OnClick = function()
		{
			self.Window.Remove();
			self.Ok();
		};
		this.Window.Window.appendChild(this.OkBtn.Element);
		
		}
	else
		{
		alert("Error unknown message box type \"" + this.Type + "\"");
		}
}

JW.MsgBox = JAM_MsgBox;

// Create Standard Dialogs
JW.Dlgs = {};

JW_Dlgs_ValueDialog.prototype = new JAM_Window;
JW_Dlgs_ValueDialog.prototype.constructor = JW_Dlgs_ValueDialog;
function JW_Dlgs_ValueDialog(Params)
{
	var self = this;

	// defaults
	this.TitleText = "Value Dialog";
	this.Label = "Value";
	this.InputType = "Plain";
	this.MaxLen = null;
	this.Value = "";
	this.AllowBlank = true;
	this.OnCancel = null;
	this.OnOk = null;

	// add parameters to default values
	for (Param in Params)
		this[Param] = Params[Param];
	
	// create window	
	JAM_Window.call(this, false, 300,130, "center", false, false, 65000);
	
	// add title
	this.AddTitle(this.TitleText);
	
	// add buttons
	var CancelClick = function()
	{
		self.Remove();
		if (typeof(self.OnCancel) == "function")
			self.OnCancel();
	}
	var OkClick = function()
	{
		self.Remove();
		if (typeof(self.OnOk) == "function")
			self.OnOk(self.Value);
	}
	
	this.SetupButton("Cancel", CancelClick);
	this.SetupButton("OK", OkClick);
	this.CreateButtons();
	
	// set initial ok button enabled state
	this.JW_Buttons[1].Btn.SetEnabled(JW.Str.Trim(this.Value) != "");
	
	// create label
	this.LabelControl = new JW.Controls.Label( {Left:20,Top:52,
												Width:60,Height:18,
												Align:"Right",
												Label:this.Label}, this.Window);
												
	var InputChange = function(NewValue)
	{
		self.Value = NewValue;
		
		if (!self.AllowBlank)
			self.JW_Buttons[1].Btn.SetEnabled(JW.Str.Trim(NewValue) != "");
	}
	
	var InputEnter = function()
	{
		//alert("on enter");
		
		if (self.JW_Buttons[1].Btn.Enabled)
			OkClick();
	}
												
	this.InputControl = new JW.Controls.TextBox(   {Left:90,Top:50,
													Width:190,Height:21,
													Value:this.Value,
													Type:this.InputType,
													MaxLen:this.ManLen,
													OnChange:InputChange,
													OnEnter:InputEnter}, this.Window);
	this.InputControl.DOMElement.focus();
}
JW.Dlgs.ValueDialog = JW_Dlgs_ValueDialog;























