/*
 * 
 Copyright Xibis Limited 2007
 
 All rights are reserved. Reproduction or transmission in whole or in part, in
 any form or by any means, electronic, mechanical or otherwise, is strictly prohibited
 without the prior written consent of the copyright owner.

  
*/


/*
Formatting functions
*/

// a global month names array
var gsMonthNames = new Array(
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
);
// a global day names array
var gsDayNames = new Array(
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday'
);

Number.prototype.zf = function(figures){
	var str = "" + this;
	while(str.length < figures) str = "0" + str;
	return str;
}

// the date format prototype
Date.prototype.format = function(f)
{
    if(-2174774400000 == this.getTime()){
        return '&nbsp;';
    }

    if (!this.valueOf())
        return '&nbsp;';

    var d = this;

    return f.replace(/(yyyy|mmmm|mmm|mm|dddd|ddd|dd|hh|nn|ss|a\/p)/gi,
        function($1)
        {
            switch ($1.toLowerCase())
            {
            case 'yyyy': return d.getFullYear();
            case 'mmmm': return gsMonthNames[d.getMonth()];
            case 'mmm':  return gsMonthNames[d.getMonth()].substr(0, 3);
            case 'mm':   return (d.getMonth() + 1).zf(2);
            case 'dddd': return gsDayNames[d.getDay()];
            case 'ddd':  return gsDayNames[d.getDay()].substr(0, 3);
            case 'dd':   return d.getDate().zf(2);
            case 'hh':   return ((h = d.getHours() % 12) ? h : 12).zf(2);
            case 'nn':   return d.getMinutes().zf(2);
            case 'ss':   return d.getSeconds().zf(2);
            case 'a/p':  return d.getHours() < 12 ? 'a' : 'p';
            }
        }
    );
}

function ToHTML(str){
	if (str==null) return "&nbsp;";
	if(parseInt(str) == 0) return "0";
	if (str=="") return "&nbsp;";
	if(parseInt(str) == -1 && parseInt(str)+"" == str) str="New";
	str = "" + str;
	str = str.replace(/&/gi, "&amp;");
	str = str.replace(/\</gi, "&lt;");
	str = str.replace(/\>/gi, "&gt;");
	str = str.replace(/"/gi, "&quot;");
	str = str.replace(/\r\n/gi, "<br />");
	str = str.replace(/\"/gi, "&quot;");
	str = str.replace(/\'/gi, "&rsquo;");
	return(str);
}

function ToHTMLID(str){
	if(str == null) str="New";
	str = "" + str;
	str = str.replace(/\</gi, "&lt;");
	str = str.replace(/\>/gi, "&gt;");
	return(str);
}

function FromHTML(str) {
    str = "" + str;
	str = str.replace(/\&lt;/gi, "<");
	str = str.replace(/\&gt;/gi, ">");
	str = str.replace(/\&quot;/gi, '"');
	return(str);
}

/* This method returns a string representing the number to a fixed 
   number of places.  */
function DecimalPlaces(number, numberOfPlaces){
    if (number == null) return "";
    var tmp = Math.round(number * Math.pow(10, numberOfPlaces));
    var sTmp = "" + tmp;
    //var iTmp = Math.floor(1-(Math.log(number)/Math.LN10));
    //if (iTmp>=0 && iTmp!=Infinity) for (i=0;i<Math.floor(1-(Math.log(number)/Math.LN10));i++) sTmp = "0" + sTmp;
    while(sTmp.length < numberOfPlaces+1)sTmp = "0" + sTmp;
    sTmp = sTmp.substring(0, sTmp.length-numberOfPlaces) + (sTmp.substring(sTmp.length-numberOfPlaces)!="" ? "." + sTmp.substring(sTmp.length-numberOfPlaces) : "");
    return(sTmp);
    
}

/*
################################################
#    END FORMAT FUNCTIONS
################################################
*/



/*
	If passed a string, this method gets the element and returns it.
	If passed an element, it simply returns the element.
*/
function el(elementId){
	if(typeof elementId == "string") return document.getElementById(elementId);
	return elementId
}

/*
################################################
#    START GENERIC AJAX FUNCTIONS
################################################
*/
function XibAjax(){
}

XibAjax.DataMergeHtml = function(html, o, oTable, jsonCode){
	var MergedHtml = html;	
	var oRe = new RegExp("\\$\\%([^\\%])*\\%\\$", "gm");
	var match = oRe.exec(html);
	while(match != null){
		var startPos = MergedHtml.indexOf(match[0]);
		var length = match[0].length;
		var contentEval = match[0].substring(2, length-2);
		
		contentEval = contentEval.replace(/&amp;/g, "&");
		
		var content;
		try{
			content = eval(contentEval);
		}
		catch(oErr){
			content =  "ERROR:[" + oErr.message + "]";
		}
		
		MergedHtml = MergedHtml.substring(0, startPos) + content + MergedHtml.substring(length + startPos);
		
		match = oRe.exec(html);
		
	}
	return(MergedHtml);
}


//Clears the content of an input
XibAjax.ClearInput = function(inputId){
	(window.top.document.getElementById(inputId)).value = "";
}

/*
	This method fills a div or other element with HTML.
*/
XibAjax.DisplayInfo = function(baseId, html){
	var oElement = window.top.document.getElementById(baseId);
	if(oElement != null) oElement.innerHTML = html;
}

var Ajax_UniqueIdCounter=0;

//Creates a unique ID for a new element.
XibAjax.UniqueId = function(){
	return("uid_" + (++window.top.Ajax_UniqueIdCounter));
}

XibAjax.FindChildNodeByClassname = function(item, className){
    for(var i=0; i<item.childNodes.length; i++){
        if(item.childNodes[i].className == className) return(item.childNodes[i]);
    }
    return null;
}

XibAjax.ElementIsFloatingControl = function(oElement){
	if(oElement.attributes["AutoClose"] == null) return false;
	return((oElement.attributes["AutoClose"].value == "true"));
}

XibAjax.PopupControl = function(elementId, parameters, controlClicked, Url){
	var oElement = window.top.document.getElementById(elementId);
	
	
	//If the element does not exist, create it.
	if(oElement == null){
		var oDiv = window.top.document.createElement("div");
		oDiv.id = elementId;
		oDiv.setAttribute("Url", Url);
		oDiv.setAttribute("AutoClose", "true");
		XibAjax.HideElement(oDiv);
		window.top.document.body.appendChild(oDiv);
	}
	
	XibAjax.LoadShowOrHideHtml(elementId, parameters, controlClicked);
}

//Added by Ian
document.onmouseup = function () { setTimeout("XibAjax.ShowHideSelect()", 10); }

XibAjax.ShowHideSelect = function (){

    //Only for IE...
    if (navigator.userAgent.toUpperCase().indexOf("MSIE") > -1) {
        //Collect all of the relevant divs
        var allDivs = document.getElementsByTagName("DIV");
        var floatingDivs = new Array();
        var floatingDivsIndex = 0;
        for (var i = 0; i< allDivs.length; ++i) {
            if (XibAjax.ElementIsFloatingControl(allDivs[i])) {
                if (allDivs[i].style.display != "none")
                    floatingDivs[floatingDivsIndex++] = allDivs[i];
            }
        }
        
        debug("reset");
        debug("floatingDivs.length" + floatingDivs.length);
        
        var allSelects = document.getElementsByTagName("SELECT");
        
        //Show all by default
        for (var i = 0; i <  allSelects.length; ++i)
        {
            if (allSelects[i].style.visibility == "hidden")
            {
                allSelects[i].style.visibility = "visible";
            }
        }
        
        debug("allSelects.length" + allSelects.length)
        
        if (floatingDivs.length > 0) {
        
            for (var i = 0; i < floatingDivs.length; ++i) {
            
                for (var j = 0; j < allSelects.length; ++j) {
                    if (XibAjax.ElementOverlap(floatingDivs[i], allSelects[j])) {
                        debug("overlap");
                        var NotContained = true;
                        var SelectParent = allSelects[j].parentNode;
                        while (SelectParent != null)
                        {
                            if (SelectParent.id == floatingDivs[i].id)
                            {
                                NotContained = false;
                                break;
                            }
                            SelectParent = SelectParent.parentNode;
                        }
                        
                        if (NotContained)
                        {
                            allSelects[j].style.visibility = "hidden";                    
                        }
                    } else {
                        debug("no overlap");
                    }
                }
            }
        }
    }
}

XibAjax.ElementOverlap = function (oElement1, oElement2) {
    
    var oLeft = new Object();
    oLeft.pos = XibAjax.GetAbsolutePosition (oElement1);
    oLeft.left = oLeft.pos.x;
    oLeft.top = oLeft.pos.y;
    oLeft.height = oElement1.offsetHeight;
    oLeft.width = oElement1.offsetWidth;
    
    debug("oLeft.height:" + oLeft.offsetHeight);
    
    var oRight = new Object();
    oRight.pos = XibAjax.GetAbsolutePosition (oElement2);
    oRight.left = oRight.pos.x;
    oRight.top = oRight.pos.y;
    oRight.height = oElement2.offsetHeight;
    oRight.width = oElement2.offsetWidth;
    
    oRight.topLeft = new Object();
    oRight.topLeft.x = oRight.left;
    oRight.topLeft.y = oRight.top;
    
    oRight.topRight = new Object();
    oRight.topRight.x = oRight.left + oRight.width;
    oRight.topRight.y = oRight.top;
    
    oRight.bottomLeft = new Object();
    oRight.bottomLeft.x = oRight.left;
    oRight.bottomLeft.y = oRight.top + oRight.height;
    
    oRight.bottomRight = new Object();
    oRight.bottomRight.x = oRight.left + oRight.width;
    oRight.bottomRight.y = oRight.top + oRight.height;
    
    
    //Check all 4 points of the right el If any are inside the left el
    //return true;
    if (XibAjax.Contains(oRight.topLeft.x, oRight.topLeft.y,
                        oLeft.left, oLeft.top, oLeft.width, oLeft.height))
        return true;
        
    if (XibAjax.Contains(oRight.topRight.x, oRight.topRight.y,
                        oLeft.left, oLeft.top, oLeft.width, oLeft.height))
        return true;
        
    if (XibAjax.Contains(oRight.bottomLeft.x, oRight.bottomLeft.y,
                        oLeft.left, oLeft.top, oLeft.width, oLeft.height))
        return true;
        
    if (XibAjax.Contains(oRight.bottomRight.x, oRight.bottomRight.y,
                        oLeft.left, oLeft.top, oLeft.width, oLeft.height))
        return true;
        
    return false;

}

XibAjax.Contains = function (px , py, elx, ely, elw, elh) {
    
    //debug("px:" + px + ", py:" + py + ", elx:" + elx + ", ely:" + ely + ", elw:" + elw + ", elh:" + elh);
    
    if ((px >= elx && px <= (elx + elw)) &&
        (py >= ely && py <= (ely + elh))) {
        return true;    
    }
    
    return false;
}

function AjaxM2M() {
}

AjaxM2M.CombineNameAndId  = function (Names, Ids) {
	var arrNames = Names.split("{[[split]]}");
	var arrVals = Ids.split(",");
	var strRet = "";
	for (var i=0;i<arrVals.length;i++) {
		if (arrVals[i]!="") {
			strRet+=(strRet!=""?",":"") + "{id:" + arrVals[i] + ",name:'" + arrNames[i].replace("'","\\'") + "'}";
		}
	}
	if (strRet == "") {
		return new Array();
	}
	return eval("[" + strRet + "]");
}

AjaxM2M.RemoveSelected = function (IDCont, NameCont, List) {
	var oIDCont = document.getElementById(IDCont);
	var oNameCont = document.getElementById(NameCont);
	var oList = document.getElementById(List);
	var arrIDs = oIDCont.value.split(",");
	var arrNames = oNameCont.value.split("{[[split]]}");
	for (var i=oList.options.length-1;i>=0;i--) {
		if (oList.options[i].selected) {
			arrIDs[i] = null;
			arrNames[i] = null;
			oList.options[i] = null;
		}
	}
	var arrID2s = new Array();
	for (var i=0;i<arrIDs.length;i++) if (arrIDs[i]!=null) arrID2s[arrID2s.length] = arrIDs[i];
	var arrName2s = new Array();
	for (var i=0;i<arrNames.length;i++) if (arrNames[i]!=null) arrName2s[arrName2s.length] = arrNames[i];
	oIDCont.value = arrID2s.join(",");
	oNameCont.value = arrName2s.join("{[[split]]}");
	for (var i=0;i<oList.options.length;i++) oList.options[i].className = (i%2==1?"odd":"");
}

XibAjax.ShowElement = function(oElement){
	if(oElement.tagName == "TD"){
		if(Calendar.is_ie) oElement.style.display = "block";
		else oElement.style.display = "table-cell";
	}
	else oElement.style.display = "block";
}
XibAjax.HideElement = function(oElement){
	oElement.style.display = "none";
	if (oElement.OnHide) oElement.OnHide();
}

//Gets the absolute position of an element within a top-level element.
XibAjax.GetAbsolutePosition = function(oElement){
	var p = Calendar.getAbsolutePos(oElement);
	
	
	if((oElement.ownerDocument.window) && (oElement.ownerDocument.parentWindow != window.top)){
		var framePos = Calendar.getAbsolutePos(oElement.ownerDocument.parentWindow.frameElement);
		p.x += framePos.x;
		p.y += framePos.y;
	}
	
	return p;
}

XibAjax.LoadShowOrHideHtml = function(elementId, parameters, controlClicked, OpenInCustomTab, Url, TitleOfNewArea){
	var oElement;
	
	if(OpenInCustomTab){
		oElement = (new AjaxCustomTab(TitleOfNewArea)).div;
		oElement.innerHTML = "";
		oElement.style.display = "none";
		if (oElement.OnHide) oElement.OnHide();
	}else{
		oElement = window.top.document.getElementById(elementId);
	}
	
	var oControlClicked = el(controlClicked);
	if((oElement.style.display != "none")){
		oElement.style.display = "none";
		XibAjax.SetOpenCloseLink(controlClicked, false);
		if (oElement.OnHide) oElement.OnHide();
	}else{
		XibAjax.ShowElement(oElement);
		XibAjax.SetOpenCloseLink(controlClicked, true);
		if (oElement.OnShow) oElement.OnShow();
		//If it's an auto-close element, fix the position
		if(XibAjax.ElementIsFloatingControl(oElement)){
//			var p = Calendar.getAbsolutePos((controlClicked));
			var p = XibAjax.GetAbsolutePosition(oControlClicked);
			oElement.style.position = "absolute";
			
			oElement.style.left = p.x + "px";
			oElement.style.top = p.y + "px";
		}
	
		if(oElement.innerHTML == ""){
			XibAjax.LoadHtml(oElement.id, parameters, Url);
		}else{
			oElement.style.display = "";
			IECorrectedScrollintoView(oElement, false);
		}
		if(XibAjax.ElementIsFloatingControl(oElement)){
			XibAjax.RegisterOpenControl(oElement);
		}
		
		if(OpenInCustomTab) XibAjax.OpenTab(oElement.id);
	}
	
}
XibAjax.LoadShowOrHideHtmlInIFrame = function(elementId, parameters, controlClicked){
	var oElement = document.getElementById(elementId);

	
	if((oElement.style.display != "none")){
		oElement.style.display = "none";
		XibAjax.SetOpenCloseLink(controlClicked, false);
		if (oElement.OnHide) oElement.OnHide();
	}else{
		XibAjax.ShowElement(oElement);
		XibAjax.SetOpenCloseLink(controlClicked, true);
	
		//Create the IFrame
		oElement.innerHTML = '<iframe style="AutoSizeIFrame" scrolling="no" frameborder="none" style="border:0px;width:100%;height:0px;" src="' + oElement.getAttribute("Url") + '"></iframe>';
		
	}
	
}

XibAjax.CloseAllTabs = function(elementId){
	var oTab = document.getElementById(elementId);
	var oTabGroup = oTab.parentNode;
	var tabs = oTabGroup.childNodes;
	
	for(var i=0; i<tabs.length; i++){
		if((tabs[i].tagName == "DIV") && (tabs[i].className == "Tab")){
			tabs[i].style.display = "none";
			if (tabs[i].OnHide) tabs[i].OnHide();
		}
	}
	
	var oCustomTabSelect = document.getElementById("CustomTabSelect");
	if(oCustomTabSelect != null) oCustomTabSelect.selectedIndex = 0;
	oTabGroup.AnyOpen = false;
}
XibAjax.OpenTab = function(elementId, parameters){
	
	XibAjax.CloseAllTabs(elementId);
	var oCustomTabSelect = document.getElementById("CustomTabSelect");
	if(oCustomTabSelect != null){
	    for(var i=0; i<oCustomTabSelect.options.length; i++){
		    var oOption = oCustomTabSelect.options[i];
		    if(oOption.value == elementId) oCustomTabSelect.selectedIndex = i;
	    }
	}
	
	
	var oTab = document.getElementById(elementId);
	var oTabGroup = oTab.parentNode;
	oTabGroup.AnyOpen = true;
	/*
	var tabs = oTabGroup.childNodes;
	for(var i=0; i<tabs.length; i++){
		if((tabs[i].tagName == "DIV") && (tabs[i].className == "Tab")){
			tabs[i].style.display = "none";
		}
	}
	*/
	XibAjax.LoadHtml(elementId, parameters);
	
	
}


/*
	This method takes the ID of a div with an additional attribute
	"Url" and loads it with the content found at that URL.
	baseElementId is the element to get the information from (i.e. you can URL parameters
		in one div, then load it into another, for instance for custom tabs.)
*/

XibAjax.CleanUrl = function(originalUrl){
    var url = originalUrl.replace("[AjaxLocation]", AjaxLocation);
    return(url);
}

//Executes a method on the server and puts the returning information
//in the specified DIV.
XibAjax.Execute = function(className, id, methodName, elementId){
    var strQS = "?COMMAND=EXECUTE_METHOD&class=";
    strQS += className + "&id=" + id;
    strQS += "&exec=" + methodName;
    
    XibAjax.LoadHtml(elementId, null, XibAjax.AddToQueryString("[AjaxLocation]/json.aspx" + strQS, "t", new Date().getTime()));
    
}

XibAjax.LoadHtml = function(elementId, parameters, Url){

	var oElement = document.getElementById(elementId);
	if (!oElement) oElement = window.top.document.getElementById(elementId);
	
	if(oElement.tagName == "DIV") oElement.style.display = "block";	
	if(oElement.tagName == "SPAN") oElement.style.display = "inline";
	if(oElement.LoadComplete) {
		if (oElement.OnShow) {
			oElement.OnShow();
		}
		return;
	}
	if((!oElement.attributes["Url"]) && (Url == null)) return;

	if(Url == null) Url = oElement.attributes["Url"].value;

	var oAjaxRequest = new AjaxRequest();
	oAjaxRequest.XmlRequest.open("GET", XibAjax.CleanUrl(Url), true);
	
	oAjaxRequest.oElement = oElement;
	if(typeof parameters == "string"){
		oAjaxRequest.PassedParameters = document.getElementById(parameters);
		if (oAjaxRequest.PassedParameters==null) {
			oAjaxRequest.PassedParameters = eval(parameters);
			if(oAjaxRequest.PassedParameters.length)oAjaxRequest.PassedParameters = oAjaxRequest.PassedParameters[0];
		}
	}	else {
		oAjaxRequest.PassedParameters = parameters;
	}


	
	oAjaxRequest.oncomplete = "XibAjax.LoadHtml_finalise";
	oAjaxRequest.XmlRequest.send(null);
	IncrementProcessCounter();

	
}

AjaxTable.SortTable = function(RC) {
    Sortable.destroy(RC.id);
    var arrLIs = RC.getElementsByTagName("LI");
    
    var iSort =new Array();
    var iLowest = -1;
    for (var i=0;i<arrLIs.length;i++) {
        iSort[iSort.length] = arrLIs[i].id.substring(arrLIs[i].id.lastIndexOf("_")+1) - 0;
        if (iLowest==-1 || iLowest>iSort[iSort.length - 1]) iLowest = iSort[iSort.length - 1];
    }
    var iMoved = -1;
    var bDragDown = false;
    for (var i=0;i<iSort.length-1;i++) {
        if (iSort[i]>iSort[i+1]) {
            var MoveePos = ((bDragDown ? iSort[i+1] : iSort[i])-iLowest);
            //alert(MoveePos + " moved " + (i - MoveePos + (bDragDown?1:0)));
            var oMovedCB = arrLIs[i + (bDragDown?1:0)].getElementsByTagName("INPUT")[0];
            var iMovedID = oMovedCB.id.substring(oMovedCB.id.lastIndexOf("_")+1)-0;
            var oMovedToCB = arrLIs[i + (bDragDown?0:1)].getElementsByTagName("INPUT")[0];
            var iMovedToID = oMovedToCB.id.substring(oMovedToCB.id.lastIndexOf("_")+1)-0;
            AjaxTable.DragPriority(RC.parentNode.id,iMovedID, iMovedToID);
            return;
        }
        if (iSort[i]-iLowest - i!=0 && !bDragDown) bDragDown = true;
    }
}

XibAjax.LoadHtml_finalise = function(oAjaxRequest){
	var html = oAjaxRequest.XmlRequest.responseText;
	
	//replace "UNIQUEID" within the HTML with one
	//specialist to this element.
	var UniqueId = XibAjax.UniqueId();
	
	html = html.replace(/UNIQUEID/g, UniqueId);
	
	//Create a dummy init script
	eval("function " + UniqueId + "_Init(){}");
	
	//paste the html into the div
	oAjaxRequest.oElement.innerHTML = html;
	
	//Find script tags within the HTML
	//var oRe = new RegExp("<script[^>]*>([\s\S\n])+?</script[^>]*>", "gi");
	var oRe = /<script[^>]*>([\s\S\n]+?)<\/script[^>]*>/gi

	//execute each script tag in turn
	var match = oRe.exec(html);
	while(match != null){
		eval(match[1]);
		match = oRe.exec(html);
	}
	
	//alert("1." + oAjaxRequest.PassedParameters.Finder.ClassName);
	//run the init functions of the script.
	var InitFunctionCall = "" + UniqueId + "_Init(oAjaxRequest.PassedParameters);";
	eval(InitFunctionCall);
	
	if (eval("typeof(" + UniqueId + "_Show)")=="function") {
		oAjaxRequest.oElement.OnShow = eval("" + UniqueId + "_Show");
		eval("" + UniqueId + "_Show()");
	}
	if (eval("typeof(" + UniqueId + "_Hide)")=="function") {
		oAjaxRequest.oElement.OnHide = eval("" + UniqueId + "_Hide");
	}
	if (eval("typeof(" + UniqueId + "_TabShow)")=="function") {
		oAjaxRequest.oElement.TabShow = eval("" + UniqueId + "_TabShow");
	}
	if (eval("typeof(" + UniqueId + "_TabHide)")=="function") {
		oAjaxRequest.oElement.TabHide = eval("" + UniqueId + "_TabHide");
	}
	if (eval("typeof(" + UniqueId + "_Refresh)")=="function") {
		document.getElementById(UniqueId).__OnRefresh = eval("" + UniqueId + "_Refresh");
		
	}	
	oAjaxRequest.oElement.AjaxUniqueId = UniqueId;
	oAjaxRequest.oElement.LoadComplete = true
	DecrementProcessCounter();

}

XibAjax.ReenableWYSIWYG = function(id,sType)
{
    if (typeof(window['FCKeditorAPI'])=="undefined") return;
    var oNode = el(id);
    var i=0;
    for (i=0;i<oNode.childNodes.length;i++)
    {
        childNode = oNode.childNodes.item(i);
        editor = FCKeditorAPI.GetInstance(childNode.name);
        if (editor && editor.EditorDocument && editor.EditMode == FCK_EDITMODE_WYSIWYG)
        {
            //editor.EditorDocument.designMode = sType;
           editor.SwitchEditMode()
           editor.SwitchEditMode()
        }
        XibAjax.ReenableWYSIWYG(childNode,sType);
    }
}

/*
	Gets a instance of the XMLHttpRequest class. 
	Cross browser.
*/
XibAjax.GetXmlRequestObject = function(){
	if(window.XMLHttpRequest){
		return(new XMLHttpRequest());
	}
	return(new ActiveXObject("MSXML2.XMLHTTP.3.0"));	
}

/*
	This takes a name value pair, encodes it and adds it to
	the end of a query string.
*/
XibAjax.AddToQueryString = function(qs, name, value){
	if(qs != ""){
		qs += "&";
	}
	
	qs += encodeURIComponent(name);
	qs += "=";
	qs += encodeURIComponent(value);
	
	return qs;
}




//If a pop-up control that should be auto-closed is used,
//it is stored here so it can be closed.
XibAjax.LastControlOpenned = null;

//This method is called when openning an auto-closing
//div to set the events to automatically close it.
XibAjax.RegisterOpenControl = function(oElement){
	if(oElement == null){
		Calendar.removeEvent(document, "mousedown", XibAjax.CheckForOpenControls);
		Calendar.removeEvent(XibAjax.LastControlOpenned, "mousedown", Calendar.stopEvent);
		XibAjax.LastControlOpenned = null;

	}
	else{
		XibAjax.LastControlOpenned = oElement;
		Calendar.addEvent(document, "mousedown", XibAjax.CheckForOpenControls);
		Calendar.addEvent(oElement, "mousedown", Calendar.stopEvent);
	}
}

// This method handles event which may close any
// auto-closing divs.
XibAjax.CheckForOpenControls = function(ev){
	if(XibAjax.LastControlOpenned == null) return;
	ev || (ev = window.event);
	var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev);
	
	for (; el != null && el != XibAjax.LastControlOpenned; el = el.parentNode);
	
	if (el == null) {
		XibAjax.CloseControl(XibAjax.LastControlOpenned);
	}	
}

XibAjax.CloseControl = function(oElement){
	oElement.style.display = "none";
	if (oElement.OnHide) oElement.OnHide();
	XibAjax.RegisterOpenControl(null);
}

//Changes the classname of an htmlObject to show if it is open or
//closed.
XibAjax.SetOpenCloseLink = function(oLink, isOpen){
	var className = oLink.className;
	if(className + "" == "undefined") return;
	
	var index = className.lastIndexOf("_OPEN");
	if(index == -1) index = className.lastIndexOf("_CLOSED");
	if(index == -1) return;
	
	var BaseClassName = className.substring(0, index);
	oLink.className = BaseClassName + (isOpen ?  "_OPEN" : "_CLOSED");
	
}


XibAjax.Logout = function(){
	XibAjax.ProcessLogin("", "", false);
}

XibAjax.ProcessLogin = function(username, password, loginPersist){
	
	var oAjaxRequest = new AjaxRequest();
	oAjaxRequest.XmlRequest.open("POST", XibAjax.CleanUrl("[AjaxLocation]/json.aspx"), true);
	oAjaxRequest.XmlRequest.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
	
	qs = "";
	
	qs = XibAjax.AddToQueryString(qs, "COMMAND", "PROCESS_LOGIN_INFO");
	qs = XibAjax.AddToQueryString(qs, "username", username);
	qs = XibAjax.AddToQueryString(qs, "password", password);
	qs = XibAjax.AddToQueryString(qs, "loginPersist", loginPersist);
	oAjaxRequest.oncomplete = "XibAjax.HandleProcessLogin";
	oAjaxRequest.XmlRequest.send(qs);
	IncrementProcessCounter();
	debug(qs);
}

XibAjax.HandleProcessLogin = function(oAjaxRequest){
	
	var ResponseArray = eval(oAjaxRequest.XmlRequest.responseText);
	var ResponseObject = ResponseArray[0];
	
	if(ResponseObject.Success){
		el("AdminArea").style.display = "block";
		el("Login").style.display = "none";
		
	}else{
		location.href="./";
	}
	DecrementProcessCounter();
}

XibAjax.ForwardToLogin = function(){
	//Show the login div on top
	location.href = "login.aspx";
}

XibAjax.InitialiseAdmin = function(){
	var oAjaxRequest = new AjaxRequest();
	oAjaxRequest.XmlRequest.open("POST", XibAjax.CleanUrl("[AjaxLocation]/json.aspx"), true);
	oAjaxRequest.XmlRequest.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
	
	qs = "";
	
	qs = XibAjax.AddToQueryString(qs, "COMMAND", "GET_LOGIN_INFO");
	oAjaxRequest.oncomplete = "XibAjax.HandleInitialiseAdmin";
	oAjaxRequest.XmlRequest.send(qs);
	IncrementProcessCounter();
	debug(qs);
}

XibAjax.HandleInitialiseAdmin = function(oAjaxRequest){
	
	var ResponseArray = eval(oAjaxRequest.XmlRequest.responseText);
	var ResponseObject = ResponseArray[0];
	
	if(ResponseObject.AllowAdminAccess){
		el("AdminArea").style.display = "block";
		el("Login").style.display = "none";
		
	}else{
		el("AdminArea").style.display = "none";
		el("Login").style.display = "block";
	}
	DecrementProcessCounter();
}


/*
################################################
#    END GENERIC AJAX FUNCTIONS
################################################
*/



/*
################################################
#    START AJAXCUSTOMTAB FUNCTIONS
################################################
*/
function AjaxCustomTab(name, divId){
	this.name = name;
	
	if(divId == null) divId = XibAjax.UniqueId();
	
	this.divId = divId;
	AjaxCustomTabList[AjaxCustomTabList.length] = this;
	
	//Get the div that contains the tabs.
	var TabContainer = document.getElementById("Tabs");
	
	//Add a new tab item
	this.div = document.createElement("DIV");
	this.div.id = divId;
	this.div.className = "Tab";
	TabContainer.appendChild(this.div);
	
	//Refresh the select menu to add it to the tabs list.
	AjaxCustomTab.RefreshSelect();
	

}
AjaxCustomTab.OnSelectChange = function(){
	var oSelect = document.getElementById("CustomTabSelect");
	if(oSelect.selectedIndex == 0) return;
	tabId = oSelect.options[oSelect.selectedIndex].value;
	XibAjax.OpenTab(tabId);
	
}

AjaxCustomTab.prototype.Open = function(){
	XibAjax.OpenTab(this.divId);
}

var AjaxCustomTabList = new Array();


AjaxCustomTab.RefreshSelect = function(){
	var oSelect = document.getElementById("CustomTabSelect");
	while(oSelect.options.length > 1) oSelect.options[1] = null;
	
	for(var i=0;i<AjaxCustomTabList.length;i++){
		oAjaxCustomTab = AjaxCustomTabList[i];
		oSelect.options.add(new Option(oAjaxCustomTab.name, oAjaxCustomTab.divId));
	}
	
}
AjaxCustomTab.Test = function(){
	var oTab = new AjaxCustomTab("Bob");
	oTab.div.innerHTML = "ahhhhhhhh " + oTab.divId;
	oTab.Open();
	
}

/*
################################################
#    END AJAXCUSTOMTAB FUNCTIONS
################################################
*/



/*
################################################
#    START CLASS THAT WRAPS XMLRequestObject
################################################
*/

/*
	This global variable holds the requests so
	that they can be found once they have returned.
*/
var AjaxRequest_RequestStack = new Array();

function AjaxRequest(){
	this.oncomplete = "";

	//Put this object in the list.
	this.RequestId = AjaxRequest_RequestStack.length;
	AjaxRequest_RequestStack[this.RequestId] = this;
	//Get the XmlRequest class.
	this.XmlRequest = new XibAjax.GetXmlRequestObject();
	eval("this.XmlRequest.onreadystatechange = function(){OnReadyStateChange(" + this.RequestId + ")}");
	
}
function OnReadyStateChange(requestId){
	oRequest = AjaxRequest_RequestStack[requestId];
	if(oRequest.XmlRequest.readyState == 4){
	
		if(oRequest.XmlRequest.responseText == "ACCESS_DENIED"){
			XibAjax.ForwardToLogin();
			return;
		}
	
		if(oRequest.oncomplete != ""){
			eval(oRequest.oncomplete + "(oRequest);");
			AjaxRequest_RequestStack[requestId] = null;
		}
	}
	

}




/*
################################################
#    END CLASS THAT WRAPS XMLRequestObject
################################################
*/


/*
################################################
#    START TABLE AJAX FUNCTIONS
################################################
*/

function AjaxTable(){
}


/*
	Updates paging information for the user.
	
	This includes the displays telling the user which page they are on,
	how many records etc.
*/



AjaxTable.ExecuteMethodOnTable = function(tableId, MethodName, FeedbackDiv) {
	var oTable = AjaxTable.GetTable(tableId);
	if (AjaxTable.GetSelectedIdList(oTable)=="") {
		document.getElementById(tableId + "_ActionSelect").selectedIndex=0;
		return;
	}
	if (document.getElementById(tableId + "_ActionSelect").options[document.getElementById(tableId + "_ActionSelect").selectedIndex].className=='true') {
		if (!confirm("Are you sure?")) {
			document.getElementById(tableId + "_ActionSelect").selectedIndex=0;
			return;
		}
	}
	AjaxTable.StartWaitMode(tableId);
	document.getElementById(FeedbackDiv).LoadComplete = false;
	var Parameters = new Object();
	Parameters.tableId = tableId;
	XibAjax.LoadHtml(FeedbackDiv,Parameters,XibAjax.CleanUrl("[AjaxLocation]/json.aspx?COMMAND=ExecuteMultiMethod&Finder=" + escape(oTable.Finder.Serialize()) + "&Method=" + escape(MethodName) + "&IDList=" + escape(AjaxTable.GetSelectedIdList(oTable))));
}

AjaxTable.ExecuteMethodOnTableWithParams = function(tableId, MethodName, FeedbackDiv) {
    var Params = "";
    var arrTmp = MethodName.split("|");
    var MethodNameToRun = arrTmp[0];
    if (arrTmp.length>1) Params = "&" + MethodName.substring(MethodNameToRun.length+1);
	var oTable = AjaxTable.GetTable(tableId);
	if (AjaxTable.GetSelectedIdList(oTable)=="") {
		document.getElementById(tableId + "_ActionSelect").selectedIndex=0;
		return;
	}
	if (document.getElementById(tableId + "_ActionSelect").options[document.getElementById(tableId + "_ActionSelect").selectedIndex].className=='true') {
		if (!confirm("Are you sure?")) {
			document.getElementById(tableId + "_ActionSelect").selectedIndex=0;
			return;
		}
	}
	AjaxTable.StartWaitMode(tableId);
	document.getElementById(FeedbackDiv).LoadComplete = false;
	var Parameters = new Object();
	Parameters.tableId = tableId;
	XibAjax.LoadHtml(FeedbackDiv,Parameters,XibAjax.CleanUrl("[AjaxLocation]/json.aspx?COMMAND=ExecuteMultiMethod&Finder=" + escape(oTable.Finder.Serialize()) + "&Method=" + escape(MethodNameToRun) + "&IDList=" + escape(AjaxTable.GetSelectedIdList(oTable)) + Params));
}

AjaxTable.HideIfNotExpandable = function(uid, imgref) {
	var oI = document.getElementById(imgref);
	var oUL = document.getElementById(uid + "_Rows");
	var oT = document.getElementById(uid);
	
	if (oT.__HideIfNotExpandable) return;
	
	var oParent = oT.parentNode;
	while (oParent!=null) {
	    if (oParent.style && oParent.style.display=="none") return;
	    oParent = oParent.parentNode;
	}
	
    var w = 0;
    if (oUL) {
        for (var i=0;i<oUL.childNodes.length;i++) {
            var oN = oUL.childNodes[i];
            if (oN.tagName && oN.tagName=="LI") {
                for (var j=0;j<oN.childNodes.length;j++) {
                    var oSB = oN.childNodes[j];
                    if (oSB.tagName && oSB.tagName=="SPAN") w += oSB.clientWidth + 1;
                }
                break;
            }
        }
    }
    var agt=navigator.userAgent.toLowerCase();
    oI.parentNode.parentNode.parentNode.style.display = (w>636) ? "block" : "none";
    oT.__HideIfNotExpandable = true;
    if (w>636) {
	//Is expandable
	var body = document.getElementsByTagName('body');
	var bodyExtended = null;
	if (body != null && body.length == 1) {
		bodyExtended = body[0];
		Element.extend(bodyExtended);
	}
	if (bodyExtended != null) {
		Element.addClassName(bodyExtended, "expandable");
	}
    }
}

AjaxTable.ExpandTable = function(uid, imgref) {
	var oI = document.getElementById(imgref);
	var oUL = document.getElementById(uid + "_Rows");
	var oT = document.getElementById(uid);
	var body = document.getElementsByTagName('body');
	var bodyExtended = null;
	if (body != null && body.length == 1) {
		bodyExtended = body[0];
		Element.extend(bodyExtended);
	}
	
	var expandText = document.getElementById(imgref + "Text");
	if (oI.src.indexOf("images/expand.gif")>0) {
	
	    var w = 0;
	    if (oUL) {
	        for (var i=0;i<oUL.childNodes.length;i++) {
	            var oN = oUL.childNodes[i];
	            if (oN.tagName && oN.tagName=="LI") {
	                for (var j=0;j<oN.childNodes.length;j++) {
	                    var oSB = oN.childNodes[j];
	                    if (oSB.tagName && oSB.tagName=="SPAN") w += oSB.clientWidth + 1;
	                }
	                break;
	            }
	        }
	    }
	    
	    
	    var agt=navigator.userAgent.toLowerCase();
	    if (w>636) {
            if (agt.indexOf("msie") != -1) w+=3;
            oI.src="images/reduce.gif";
		    oT.style.width = w + "px";
		}
		oT.style.position="relative";
		
		if (expandText != null) {
			expandText.innerHTML = "CONTRACT COLUMNS";
		}
	} else {
		oI.src="images/expand.gif";
		oT.style.position="relative";
		oT.style.width="636px";

		if (expandText != null) {
			expandText.innerHTML = "EXPAND COLUMNS";
		}
	}
	
	if (bodyExtended != null) {
		Element.toggleClassName(bodyExtended, "expanded");
	}
}

AjaxTable.UpdatePagingInfo = function(oTable){
	
	var PageNavigationDiv = window.top.document.getElementById(oTable.id + "_RecordNavigation");
	var DisplayPageNavigationDiv = AjaxTable.NoOfPages(oTable) > 1;
	if((oTable.DisplayPageNavigationDiv == null)||(DisplayPageNavigationDiv)) oTable.DisplayPageNavigationDiv = DisplayPageNavigationDiv;
	
	//PageNavigationDiv.style.display = oTable.DisplayPageNavigationDiv ? "block" : "none";
	
	var NoRecordsFoundDiv = window.top.document.getElementById(oTable.id + "_NoRecordsFound");
	NoRecordsFoundDiv.style.display = (oTable.NumberOfRecords == 0) ? "block" : "none";
	
	var pageString = "";
	
	var start = 0;
	var end = 0;
	
	var sections = 7;
	var secSmall = Math.floor(sections/2);
	var secLarge = secSmall+1;
	
	if (AjaxTable.NoOfPages(oTable)<sections+1) {
		start = 0;
		end = AjaxTable.NoOfPages(oTable);
	} else {
		start = (oTable.CurrentPage<secLarge) ? 0 : ( (oTable.CurrentPage + secLarge>AjaxTable.NoOfPages(oTable)) ? AjaxTable.NoOfPages(oTable) - sections : (oTable.CurrentPage - secSmall) );
		end = (oTable.CurrentPage + secLarge>AjaxTable.NoOfPages(oTable)) ? AjaxTable.NoOfPages(oTable) : (oTable.CurrentPage<secLarge ? sections : oTable.CurrentPage + secLarge);
	}
	for (var i=start;i<end;i++) {
		if (i==oTable.CurrentPage) {
			pageString+='<strong>' + (i+1) + '</strong> ';
		} else {
			pageString+='<a href="Javascript:AjaxTable.SetPage(\'' + oTable.id + '\',' + i + ')">' + (i+1) + '</a> ';
		}
	}
	
	XibAjax.DisplayInfo(oTable.id + "_PageLinkSpan", pageString);
	
	XibAjax.DisplayInfo(oTable.id + "_NumberOfRecordsDisplay", oTable.NumberOfRecords);
	XibAjax.DisplayInfo(oTable.id + "_CurrentPageDisplay", oTable.CurrentPage + 1);
	XibAjax.DisplayInfo(oTable.id + "_TotalPages", AjaxTable.NoOfPages(oTable));
	XibAjax.DisplayInfo(oTable.id + "_ShowingRecordFrom", AjaxTable.ShowingRecordFrom(oTable));
	XibAjax.DisplayInfo(oTable.id + "_ShowingRecordTo", AjaxTable.ShowingRecordTo(oTable));
}


AjaxTable.SetPageSize = function(tableId, newSize){
	var oTable = AjaxTable.GetTable(tableId);
	oTable.PageSize = newSize;
	oTable.CurrentPage = 0;
	AjaxTable.Refresh(tableId);
}

XibAjax.JavaScriptEncode = function(text){
	text = text.replace(/\\/g, "\\\\");
	text = text.replace(/\\/g, "\\\"");
	text = text.replace(/'/g, "\\\'");
	return text;
}


/*
	This handles the onclick event of the checkboxes in 
	an object picker.
*/
AjaxTable.HandleCheckboxClick = function(tableId, idClicked, description, newValue){
	var oTable = AjaxTable.GetTable(tableId);
	oTable.SelectedIdList.AddOrRemoveItem(idClicked, newValue, description);
	
	if(oTable.SelectedIdList.PickerType == "Single"){
		//Un-check the other checkboxes.
		var ArrCheckboxes = oTable.getElementsByTagName("input");
		var chkPrefix = tableId + "_chkbox_";
		for(var i=0; i<ArrCheckboxes.length; i++){
			var oItem = ArrCheckboxes[i];
			if(oItem.id.indexOf(chkPrefix) == 0){
				var id = oItem.id.substring(chkPrefix.length);
				if(id != idClicked + "") oItem.checked = false;
			}
		}
		
		XibAjax.CloseControl(XibAjax.LastControlOpenned);
	}	
}

AjaxTable.CreateAutoCheckbox = function(oTable, jsonCode, id, description){
	var onchange=" window.top.document.getElementById('" + oTable.id + "').SelectedIdList.AddOrRemoveItem(" + id + ",this.checked,'" + XibAjax.JavaScriptEncode(description) + "'); ";
	var onchange="AjaxTable.HandleCheckboxClick('" + oTable.id + "'," + id + ",'" + XibAjax.JavaScriptEncode(description) + "',this.checked); ";
	
	
	return("<input type=checkbox onclick=\"" + onchange + "\" id='" + oTable.id + "_chkbox_" + id + "' />");
}

/*
	This method runs through the checkboxes
	loaded into a picker table and updates the values
	with those previously set by the user before update. 
*/
AjaxTable.LoadCheckboxes = function(table_id){
	var oTable = window.top.document.getElementById(table_id);
	var ArrCheckboxes = oTable.getElementsByTagName("input");
	var chkPrefix = table_id + "_chkbox_"
	for(var i=0; i<ArrCheckboxes.length; i++){
		var oItem = ArrCheckboxes[i];
		if(oItem.id.indexOf(chkPrefix) == 0){
			var id = oItem.id.substring(chkPrefix.length);
			
			if(oTable.PickerType == "Single"){
				if(id + "" == oTable.AddInput.value) oItem.checked = true;
				else oItem.checked = false;
			}else{
				var isSelected = oTable.SelectedIdList.IsSelected(parseInt(id));
				if(isSelected) oItem.checked = true;
				if(!isSelected) oItem.checked = false;
			}
		}
	}
}


AjaxTable.AddNewRow= function(oTable){
				AjaxTable.AddRow(oTable, oTable.NewDataItem);
}
var uidAddRow;

AjaxTable.AddRow= function(oTable, DataItem){
oTable.IsEvenRow = !oTable.IsEvenRow;
var isEvenRow = oTable.IsEvenRow;
				var oTBody = XibAjax.FindChildNodeByClassname(oTable, "TableData");

   var rowHtml = oTable.DataItemTemplate;
   var lastUid = uidAddRow;
   uid = XibAjax.UniqueId();
   uidAddRow = uid;
   rowHtml = rowHtml.replace(/UNIQUEROWID/g, uid);
   

   
   rowHtml = XibAjax.DataMergeHtml(rowHtml, DataItem, oTable, null);
   oTBody.innerHTML += rowHtml;
   
   //If there is a form, load the data in
   AjaxForm.Init(uid, oTable);
   AjaxForm.PutDataIntoForm(AjaxForm.Get(uid), DataItem);
   
//now unique id set and data inserted, execute any scripts in the row (e.g. calendar set-up)    
				var oRe = new RegExp("<script[^>]*>([^<]*)</SCRIPT[^>]*>", "gmi");
				var match = oRe.exec(rowHtml);

				while(match != null){
								eval(match[1]);
								match = oRe.exec(rowHtml);
				}

   //var isEvenRow = (parseInt(iData/2) * 2 != iData);
   if(isEvenRow){
     var lastIndex = oTBody.childNodes.length-1;
     while(lastIndex > 0){
         if(oTBody.childNodes[lastIndex].tagName == "LI"){
             //oTBody.childNodes[lastIndex].className = "TableItem alt";
	     
	     //Keeps existing classes e.g. already defined in the csstable
	     var row = oTBody.childNodes[lastIndex];
	     Element.extend(row);
	     row.addClassName('alt');
	     row.addClassName('TableItem');
             lastIndex = 0;
         }
         lastIndex--;
     }

	/*var otherRow = oTBody.childNodes[oTBody.childNodes.length-1];
	if (otherRow != null && otherRow.nodeType == 1) {
		Element.extend(otherRow);
		otherRow.addClassName('alt');
		otherRow.addClassName('TableItem');
	}*/

	//oTBody.childNodes[oTBody.childNodes.length-1].className = "alt";
   }
}



/*
	When passed some JSON code and a tableID, this
	function deletes the current information in the 
	table and fills it back up with the new data.
*/
AjaxTable.FillWithData = function(tableId, jsonCode, ClearTableFirst){

	//find the table
	var oTable = AjaxTable.GetTable(tableId);
	
	//Get the body
	var oTBody;
	if(oTable.isCssTable == true){
	 	oTBody = XibAjax.FindChildNodeByClassname(oTable, "TableData");
    }else{
	    oTBody = oTable.getElementsByTagName("tbody").item(0);
	    //get the first (template row)
	    var templateRow = oTBody.rows[0];
	}

	
	
	
	if(ClearTableFirst){
	    if(oTable.isCssTable){
	        var FoundTemplateRow = false;
		    //delete all the rows apart from the template.
            for(var i=0; i<oTBody.childNodes.length; i++){
                if(oTBody.childNodes[i].tagName != null){
                    oTBody.removeChild(oTBody.childNodes[i]);
                    i--;
                }
            }
	    }else{
		    //delete all the rows apart from the template.
		    while(oTBody.rows.length > 1){
			    var oRow = oTBody.getElementsByTagName("tr").item(1);
			    oTBody.removeChild(oRow);
		    }
	    }
	
	
	}
	
	var JsonObject;
	try{
		JsonObject = eval(jsonCode);
	}
	catch(oerr){
		debug("Error in returned JSON:" + jsonCode);
	}
	
	oTable.NumberOfRecords = JsonObject[0];
	
	var DataObj = eval(jsonCode)[1];
	
	oTable.NewDataItem = eval(jsonCode)[2];
	var isEvenRow = false;;
	for(var iData=0; iData<DataObj.length; iData++){
	  var DataItem = DataObj[iData];
	  
	  if(oTable.isCssTable){
//	      var rowHtml = oTable.DataItemTemplate;
//	      
//	      var uid = XibAjax.UniqueId();
//	      rowHtml = rowHtml.replace(/UNIQUEROWID/g, uid);
//	      
//	
//	      
//	      rowHtml = XibAjax.DataMergeHtml(rowHtml, DataItem, oTable, jsonCode);
//	      oTBody.innerHTML += rowHtml;
//	      
//	      //If there is a form, load the data in
//	      AjaxForm.Init(uid, oTable.Finder);
//	      AjaxForm.PutDataIntoForm(AjaxForm.Get(uid), DataItem);
//	      
//	 //now unique id set and data inserted, execute any scripts in the row (e.g. calendar set-up)    
//								var oRe = new RegExp("<script[^>]*>([^<]*)</SCRIPT[^>]*>", "gmi");
//								var match = oRe.exec(rowHtml);
//								
//								while(match != null){
//												eval(match[1]);
//												match = oRe.exec(rowHtml);
//								}
//	//AjaxTable.AddItem(tableId,3);

//	      isEvenRow = (parseInt(iData/2) * 2 != iData);
//	      if(isEvenRow){
//	        var lastIndex = oTBody.childNodes.length-1;
//	        while(lastIndex > 0){
//	            if(oTBody.childNodes[lastIndex].tagName == "DIV"){
//	                oTBody.childNodes[lastIndex].className = "alt";
//	                lastIndex = 0;
//	            }
//	            lastIndex--;
//	        }
//	      oTBody.childNodes[oTBody.childNodes.length-1].className = "alt";
//	      }
							AjaxTable.AddRow(oTable, DataItem);

	  
	  }else{
	  
	      //Create a new row
	      var oRow = window.top.document.createElement("TR");
	      oRow.id = tableId + "_row_" + DataItem.id;
    	  
	      //sets class on odd rows only to "alt".
	      if(parseInt(iData/2) * 2 != iData) oRow.className = "alt"
    	  
	      //Create each td
	      var cols = templateRow.getElementsByTagName("TD");
	      for(var iTd=0; iTd<cols.length; iTd++){
		    var oTD = window.top.document.createElement("TD");
		    var oTemplateTd = cols[iTd];
    		
		    var html = oTemplateTd.innerHTML;
    		
    		
		    oTD.innerHTML = XibAjax.DataMergeHtml(html, DataItem, oTable, jsonCode);
    		
    		
		    oRow.appendChild(oTD);
	      }
    	  
    	  
    	  
	      //oTBody.appendChild(templateRow);
	      oTBody.appendChild(oRow);
	    }
	}
			if(oTable.isCssTable && oTable.isEditable){
							AjaxTable.AddRow(oTable, oTable.NewDataItem);
		  }

	
    XibAjax.ShowHideSelect();	
	AjaxTable.UpdatePagingInfo(oTable);
  
}

/*
	This is ran after an item is added to drop it into the
	table.
*/
AjaxTable.AddItem = function(tableId, objectId){
	var oTable = AjaxTable.GetTable(tableId);


	
	var oAjaxRequest = new AjaxRequest();
	oAjaxRequest.XmlRequest.open("POST", XibAjax.CleanUrl(oTable.Url), true);
	oAjaxRequest.XmlRequest.setRequestHeader('Content-Type','application/x-www-form-urlencoded');

	oAjaxRequest.tableId = tableId;
	
	//Set this value so that the table knows to add
	//rather than clear and restart.
	oAjaxRequest.Purpose = "AddItemToTable";
	
	var qs = "";
	//qs = XibAjax.AddToQueryString(qs, "ClassName", oTable.XiClass);
	qs = XibAjax.AddToQueryString(qs, "PageSize", 1);
	qs = XibAjax.AddToQueryString(qs, "CurrentPage", 0);
	qs = XibAjax.AddToQueryString(qs, "Order", oTable.OrderRequests);
	
	/*
	if(oTable.ReferringObjectClass) qs = XibAjax.AddToQueryString(qs, "ReferringObjectClass", oTable.ReferringObjectClass);
	if(oTable.ReferringObjectId) qs = XibAjax.AddToQueryString(qs, "ReferringObjectId", oTable.ReferringObjectId);
	if(oTable.ReferringObjectProperty) qs = XibAjax.AddToQueryString(qs, "ReferringObjectProperty", oTable.ReferringObjectProperty);
	if(oTable.ReferringObjectFinder) qs = XibAjax.AddToQueryString(qs, "ReferringObjectFinder", oTable.ReferringObjectFinder);
	*/
	qs = XibAjax.AddToQueryString(qs, "Finder", oTable.Finder.Serialize());

	
	qs = XibAjax.AddToQueryString(qs, "s_id", objectId);
	
	//remove possibility of cache/proxy servers
	qs = XibAjax.AddToQueryString(qs, "t", new Date().getTime());
	
	oAjaxRequest.oncomplete = "AjaxTable.HandleTableRefreshData";
	oAjaxRequest.XmlRequest.send(qs);
	IncrementProcessCounter();
	debug(qs);
}


AjaxTable.ExportData = function(tableId, dataType){
	var oTable = AjaxTable.GetTable(tableId);
	var qs = AjaxTable.CreateQueryString(oTable);
	//qs = XibAjax.AddToQueryString(qs, "DataType", dataType);
	//window.open("Ajax/json.aspx?" + qs);
	
	if(dataType == "CSV") window.open(XibAjax.CleanUrl("[AjaxLocation]/ExportCSV.aspx?" + qs));
	if(dataType == "HTMLREPORT") window.open(XibAjax.CleanUrl("[AjaxLocation]/ExportHtmlReport.aspx?" + qs));
}

AjaxTable.CreateQueryString = function(oTable){

	var qs = "";
	//qs = XibAjax.AddToQueryString(qs, "ClassName", oTable.XiClass);
	qs = XibAjax.AddToQueryString(qs, "PageSize", oTable.PageSize);
	qs = XibAjax.AddToQueryString(qs, "CurrentPage", oTable.CurrentPage);
	qs = XibAjax.AddToQueryString(qs, "Order", oTable.OrderRequests);
	
	if (!oTable.Refreshed)
	{
	    qs = XibAjax.AddToQueryString(qs, "Refreshed", oTable.Refreshed);
	}
	qs = XibAjax.AddToQueryString(qs, "TableID", oTable.id);
	
	qs = XibAjax.AddToQueryString(qs, "Finder", oTable.Finder.Serialize());
	
	
	for(var i=0; i<oTable.SearchParameters.length; i++){
		var oParam = oTable.SearchParameters[i];
		qs = XibAjax.AddToQueryString(qs, "s_" + oParam.name, oParam.value);
	}
	
	//remove possibility of cache/proxy servers
	qs = XibAjax.AddToQueryString(qs, "t", new Date().getTime());
	
	return(qs);
}


AjaxTable.RegisterTable = function(tableId) {
    var oTable = AjaxTable.GetTable(tableId);
    if (!oTable.__registered) {
        if (!AjaxTable.AllTables) {
            AjaxTable.AllTables = new Array();
        }
        AjaxTable.AllTables[AjaxTable.AllTables.length] = tableId;
        oTable.__registered = true;
    }
}

AjaxTable.RefreshAll = function() {
    if (AjaxTable.AllTables) {
        for (var iLop=0;iLop<AjaxTable.AllTables.length;iLop++)
            AjaxTable.Refresh(AjaxTable.AllTables[iLop]);
    }
}


/*
	Starts the process of refreshing a table's data.
*/
AjaxTable.Refresh = function(tableId) {
    $(tableId).show();
    AjaxTable.RegisterTable(tableId);
    var oTable = AjaxTable.GetTable(tableId);
    AjaxTable.StartWaitMode(tableId);

    var oAjaxRequest = new window.top.AjaxRequest();

    oAjaxRequest.XmlRequest.open("POST", XibAjax.CleanUrl(oTable.Url), true);
    oAjaxRequest.XmlRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

    oAjaxRequest.tableId = tableId;

    var qs = AjaxTable.CreateQueryString(oTable);

    oAjaxRequest.oncomplete = "AjaxTable.HandleTableRefreshData";
    oAjaxRequest.XmlRequest.send(qs);
    IncrementProcessCounter();
    oTable.Refreshed = true;
    debug(qs);

}


AjaxTable.StartWaitMode = function(tableId){
	var oTable = AjaxTable.GetTable(tableId);
	oTable.CurrentProcessCount++;
	
	oTable.style.filter = "alpha(opacity=50)";
	oTable.style.MozOpacity=0.5;
	
    window.status = "Refreshing data (" + oTable.CurrentProcessCount + ") ......";
    oTable.enabled = false;
}
AjaxTable.EndWaitMode = function(tableId){
	var oTable = AjaxTable.GetTable(tableId);
	oTable.CurrentProcessCount--;
	if(oTable.CurrentProcessCount <= 0){
	    oTable.CurrentProcessCount = 0;
	    oTable.style.filter = "none";
	    oTable.style.MozOpacity=1.0;
	    window.status = "";
	}else{
        window.status = "Refreshing data (" + oTable.CurrentProcessCount + ")......";
	}
}

/*
	Runs when the data requested in AjaxTable_Refresh is returned.
*/
AjaxTable.HandleTableRefreshData = function(Request){

    var oTable = AjaxTable.GetTable(Request.tableId);


    //Session defaults...
    var ResponseText = Request.XmlRequest.responseText;
    var oSessionDefaultsRegExp = new RegExp("<SessionDefaults>([^<]*)</SessionDefaults>");
    
    if (oSessionDefaultsRegExp.test(ResponseText))
    {   
        var Defaults = oSessionDefaultsRegExp.exec(ResponseText)[0].toString();        
        var DefaultsArr = Defaults.split(",");
        
        var oNumberRegExp = new RegExp("([0-9]+)");
        
        var CurrentPageInt = parseInt(oNumberRegExp.exec(DefaultsArr[0])[0].toString());
        if (!isNaN(CurrentPageInt))
        {
            oTable.CurrentPage = CurrentPageInt;
        }
        
        var PageSizeInt = parseInt(oNumberRegExp.exec(DefaultsArr[1])[0].toString());
        if (!isNaN(PageSizeInt))
        {        
            oTable.PageSize = PageSizeInt;
            
            var pageSizeSelectEl = el(oTable.id + '_PageSizeSelect');
            if (pageSizeSelectEl != null)
            {
                for (var i = 0; i < pageSizeSelectEl.options.length; ++i)
                {
                    if (pageSizeSelectEl.options[i].text == PageSizeInt)
                    {
                        pageSizeSelectEl.selectedIndex = i;
                        break;
                    }
                }
            }
        }
     
    }

	AjaxTable.FillWithData(Request.tableId, Request.XmlRequest.responseText, Request.Purpose != "AddItemToTable");
	//debug("<hr/>" + Request.XmlRequest.responseText);
	
	//If there is an "OnRefresh" attribute in the table, execute the code.
	if(oTable.attributes["OnRefresh"]) eval(oTable.attributes["OnRefresh"].value);
	if(oTable.__OnRefresh) oTable.__OnRefresh();
	AjaxTable.EndWaitMode(oTable.id);
	DecrementProcessCounter();
	
}

AjaxTable.ShowingRecordFrom = function(oTable){
	return(oTable.CurrentPage * oTable.PageSize + 1);
}
AjaxTable.ShowingRecordTo = function(oTable){
	var last = (oTable.CurrentPage + 1) * oTable.PageSize;
	if(last > oTable.NumberOfRecords) last = oTable.NumberOfRecords;
	return(last);
}
AjaxTable.NoOfPages = function(oTable){
	if(oTable.NumberOfRecords == null) return(null);
	return Math.ceil(oTable.NumberOfRecords / oTable.PageSize);
}

AjaxTable.Next = function(tableId){
	var oTable = AjaxTable.GetTable(tableId);
	
	if(oTable.CurrentPage + 1 >= AjaxTable.NoOfPages(oTable)) return;
	oTable.CurrentPage++;
	AjaxTable.Refresh(tableId);
}
AjaxTable.Previous = function(tableId){
	var oTable = AjaxTable.GetTable(tableId);
	if(	oTable.CurrentPage <= 0) return;
	oTable.CurrentPage--;
	AjaxTable.Refresh(tableId);
}

AjaxTable.SetPage = function(tableId, pageNo){
	var oTable = AjaxTable.GetTable(tableId);
	if(	pageNo < 0 || pageNo>=AjaxTable.NoOfPages(oTable)) return;
	oTable.CurrentPage = pageNo;
	AjaxTable.Refresh(tableId);
}

AjaxTable.GetTable = function(tableId){
	var oTable = window.top.document.getElementById(tableId)
	return(oTable);
}

//This is called when the HTML table is loaded in to the page.
AjaxTable.Initialise = function(tableId, parameters, dontRefresh){
	var oTable = AjaxTable.GetTable(tableId);
	
	oTable.CurrentProcessCount = 0;
	
	oTable.parameters = parameters;
	
	oTable.isCssTable = (oTable.tagName == "DIV");
	oTable.isEditable = parameters.EditableTable;
	
	oTable.initialized = true;
	oTable.Refreshed = false;
	oTable.OrderRequests = new Array();
	oTable.Url = oTable.attributes["Url"].value;
	//oTable.XiClass = oTable.attributes["XiClass"].value;
	oTable.NumberOfRecords = null;
	oTable.SearchParameters = new Array();
	
	oTable.PageSize = parseInt(oTable.attributes["PageSize"].value);
	if(isNaN(oTable.PageSize)) oTable.PageSize = 20;
	
	oTable.CurrentPage = 0;	
	
	oTable.Finder = parameters.Finder;
	oTable.LinkDefaultParameter = parameters.LinkDefaultParameter;
	
	if(oTable.isCssTable){
		
		//The template should be the only thing within the body
		//We can grab it, then remove it.
	    var oTBody = XibAjax.FindChildNodeByClassname(oTable, "TableData");

		oTable.DataItemTemplate = oTBody.innerHTML;
		

        for(var i=0; i<oTBody.childNodes.length; i++){
            if(oTBody.childNodes[i].tagName != null){
                oTBody.removeChild(oTBody.childNodes[i]);
                i--;
            }
        }
        
        //Resize the table to coincide with the data in the header row.
        var oTHead = XibAjax.FindChildNodeByClassname(oTable, "TableHeader");
        var Spans = oTHead.getElementsByTagName("SPAN");
        var totalWidth = 0;
        for(var i=0; i<Spans.length; i++){
            totalWidth += (Spans[i].offsetWidth + 0);
        }
        
        //oTable.style.width = (totalWidth + 5) + "px";
        //oTable.style.width = "800px";


    }		
	
	/*
	if(parameters != null){
		if(parameters.finder != null){
			AjaxTable.Finder = parameters.finder;
			oTable.ReferringObjectClass = parameters.finder.containingClass;
			oTable.ReferringObjectId = parameters.finder.id;
			oTable.ReferringObjectFinder = parameters.finder.finderProperty;
		}
	}
	*/

    if (!dontRefresh) AjaxTable.Refresh(tableId);
	
}

XibAjax.HitPage = function(url, qs) {
	if (!qs) qs = "";
    var oAjaxRequest = new window.top.AjaxRequest();
	oAjaxRequest.XmlRequest.open("POST", XibAjax.CleanUrl(url), true);
	oAjaxRequest.XmlRequest.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
	oAjaxRequest.oncomplete = "XibAjax.HandleHitPage";
	oAjaxRequest.XmlRequest.send(qs);
	IncrementProcessCounter();
}

XibAjax.HandleHitPage = function() {
    DecrementProcessCounter();
}


AjaxTable.DragPriority = function(tableId, Id, ToId) {
    var oTable = AjaxTable.GetTable(tableId);
	AjaxTable.StartWaitMode(tableId);
	var oAjaxRequest = new window.top.AjaxRequest();
	oAjaxRequest.XmlRequest.open("POST", XibAjax.CleanUrl("[AjaxLocation]/json.aspx"), true);
	oAjaxRequest.XmlRequest.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
	
	var qs = "";
	qs = XibAjax.AddToQueryString(qs, "COMMAND", "DRAG_ORDER");
	qs = XibAjax.AddToQueryString(qs, "id", Id);
	qs = XibAjax.AddToQueryString(qs, "toid", ToId);
	qs = XibAjax.AddToQueryString(qs, "Finder", oTable.Finder.Serialize());

	
	//remove possibility of cache/proxy servers
	qs = XibAjax.AddToQueryString(qs, "t", new Date().getTime());
	
	oAjaxRequest.oncomplete = "AjaxTable.HandleChangePriority";
	oAjaxRequest.Table = oTable;
	
	debug("del:" +  qs);
	oAjaxRequest.XmlRequest.send(qs);
	IncrementProcessCounter();
	
}

AjaxTable.ChangePriority = function(tableId, Id, moveUp) {
	var oTable = AjaxTable.GetTable(tableId);
	AjaxTable.StartWaitMode(tableId);
	var oAjaxRequest = new window.top.AjaxRequest();
	oAjaxRequest.XmlRequest.open("POST", XibAjax.CleanUrl("[AjaxLocation]/json.aspx"), true);
	oAjaxRequest.XmlRequest.setRequestHeader('Content-Type','application/x-www-form-urlencoded');

	var qs = "";
	qs = XibAjax.AddToQueryString(qs, "COMMAND", "CHANGE_ORDER");
	qs = XibAjax.AddToQueryString(qs, "id", Id);
	qs = XibAjax.AddToQueryString(qs, "up", moveUp);
	qs = XibAjax.AddToQueryString(qs, "Finder", oTable.Finder.Serialize());

	
	//remove possibility of cache/proxy servers
	qs = XibAjax.AddToQueryString(qs, "t", new Date().getTime());
	
	oAjaxRequest.oncomplete = "AjaxTable.HandleChangePriority";
	oAjaxRequest.Table = oTable;
	
	debug("del:" +  qs);
	oAjaxRequest.XmlRequest.send(qs);
	IncrementProcessCounter();
}

AjaxTable.HandleChangePriority = function(Request) {
	var oTable = Request.Table;
	AjaxTable.Refresh(oTable.id);
	AjaxTable.EndWaitMode(oTable.id);
	DecrementProcessCounter();
}


AjaxTable.ReOrder = function(tableId, OrderText, isDescending){
	if(!isDescending) isDescending = false;
	var oTable = AjaxTable.GetTable(tableId);

	
	if(oTable.OrderRequests[oTable.OrderRequests.length-1] == OrderText){
		if(!isDescending) isDescending = true;
	}
	if(oTable.OrderRequests[oTable.OrderRequests.length-1] == "!" + OrderText){
		if(isDescending) isDescending = false;
	}
	
	for(var i=0; i<oTable.OrderRequests.length;i++){
		orderStr = oTable.OrderRequests[i];
		if((orderStr == OrderText)||(orderStr == "!" + OrderText)){
			oTable.OrderRequests.splice(i, 1);
		}
	}
	
	
	
	oTable.OrderRequests[oTable.OrderRequests.length] = (isDescending ? "!" : "")  + OrderText;
	
	oTable.CurrentPage = 0;
	
	AjaxTable.Refresh(tableId);
}


AjaxTable.ClearSearch = function(oTable){
	var oTable = AjaxTable.GetTable(tableId);
	oTable.SearchParameters = null;
	AjaxTable.Refresh(tableId);
	
	
}

AjaxTable.AddSearchParamter = function(oTable, oElement){
	var oParam = null;
	
	if((oElement.type == "text")||(oElement.type == "hidden")){
		oParam = new Object();
		oParam.name = oElement.name;
		oParam.value = oElement.value;
	}
	
	if(oElement.type == "select-one"){
		oParam = new Object();
		oParam.name = oElement.name;
		oParam.value = oElement.options[oElement.selectedIndex].value;
	}
	
	if(oElement.type == "checkbox"){
	    if(oElement.checked){
   		    oParam = new Object();
		    oParam.name = oElement.name;
		    oParam.value = oElement.value;
		}
	}
	
	if(oParam != null){
		oTable.SearchParameters[oTable.SearchParameters.length] = oParam;
	}
}
AjaxTable.ClearSearch = function(tableId){
	var oTable = AjaxTable.GetTable(tableId);
	
	//Clear previous parameters
	oTable.SearchParameters = new Array();
	
	oTable.CurrentPage = 0;
	AjaxTable.Refresh(tableId);
}
AjaxTable.RunSearch = function(oDivFormId, tableId){
	var oTable = AjaxTable.GetTable(tableId);
	var oDivForm = document.getElementById(oDivFormId);
	
	//Clear previous parameters
	oTable.SearchParameters = new Array();
	
	var Inputs = oDivForm.getElementsByTagName("INPUT");
	
	//loop through the elements of the table
	for(var i=0; i<Inputs.length; i++){
		AjaxTable.AddSearchParamter(oTable, Inputs[i]);
	}

	var Inputs = oDivForm.getElementsByTagName("SELECT");
	
	//loop through the elements of the table
	for(var i=0; i<Inputs.length; i++){
		AjaxTable.AddSearchParamter(oTable, Inputs[i]);
	}
	
	oTable.CurrentPage = 0;
	AjaxTable.Refresh(tableId);
	
}

/*
	RowId: The id of the TR element to open.
	DataItem_id: The id of the object you want to load into the row.
	Url: The Url of the template to load in.
	newItemId: The Id of the new element you wish to create.
	linkClicked: The link that was clicked on.
*/
AjaxTable.OpenRow = function(RowId, DataItem_id, Url, newItemId, tableId, linkClicked){
	var oTable = AjaxTable.GetTable(tableId);
		
	if(newItemId == null) newItemId = RowId + "_insert";
	
	var oNewTD;
	var isNew = false;
	
	//does it already exist?
	var oItem = window.top.document.getElementById("edit" + newItemId);
	if(oItem) oNewTD = oItem;
	else{
		//The item doesnt exist, create it.
		isNew = true;

		//Get the old row.
		var oTR = window.top.document.getElementById(RowId);
		var oTBody = oTR.parentNode;

		//Create the new row.
		var oNewTR = oTBody.insertRow(oTBody.tagName=="TFOOT" ? -1 : oTR.rowIndex);
		oNewTD = window.top.document.createElement("TD");
		oNewTD.id = "edit" + newItemId;
		oNewTD.setAttribute("Url", Url);
		oNewTD.className = "EditDataContainer";
		
		oNewTD.colSpan = oTR.cells.length;
		oNewTR.appendChild(oNewTD);
		XibAjax.HideElement(oNewTD);
	}
	
	//cs = document.defaultView.getComputedStyle(oNewTD,null);
	//alert(cs.display);
	
	
	XibAjax.LoadShowOrHideHtmlInIFrame("edit" + newItemId, DataItem_id, linkClicked);
	
	if(DataItem_id > 0){
		//Add the div for the sublists
		var SubListDivId = XibAjax.UniqueId();
		oNewTD.innerHTML += "<div id=\"" + SubListDivId + "\" Url=\"" + oTable.Finder.ClassName + "/Sublists.html\"></div>";
		var parameters = new Object();
		parameters.DataItem_id = DataItem_id;
		XibAjax.LoadHtml(SubListDivId, parameters);
	}
	
}



AjaxTable.SelectAllDeleteCheckboxes = function(tableId, checked){
	var oTable = AjaxTable.GetTable(tableId);
	var oTable = AjaxTable.GetTable(tableId);
	var DeleteList = "";
	
	var actionToDo = false;
	
	var colInputs = oTable.getElementsByTagName("INPUT");
	for(var i=0; i<colInputs.length; i++){
		var oInput = colInputs[i];
		if(oInput.id.indexOf(oTable.id + "_DeleteCheckbox_") == 0){
			var intObjectId = parseInt(oInput.id.substring((oTable.id + "_DeleteCheckbox_").length));
			if(!isNaN(intObjectId)){
				if (!oInput.checked) actionToDo = true;
			}
		}
	}
	
	//find all the checkboxes in the document.
	var colInputs = oTable.getElementsByTagName("INPUT");
	for(var i=0; i<colInputs.length; i++){
		var oInput = colInputs[i];
		if(oInput.id.indexOf(oTable.id + "_DeleteCheckbox_") == 0){
			var intObjectId = parseInt(oInput.id.substring((oTable.id + "_DeleteCheckbox_").length));
			if(!isNaN(intObjectId)){
				oInput.checked = actionToDo;
			}
		}
	}
	
}

AjaxTable.GetActionDropdown = function(oTable){
	return document.getElementById(oTable.id + "_ActionSelect");
}

AjaxTable.GetSelectedIdList = function(oTable){
	var SelectedIdList = "";
	
	//find all the checkboxes in the document.
	var colInputs = oTable.getElementsByTagName("INPUT");
	for(var i=0; i<colInputs.length; i++){
		var oInput = colInputs[i];
		if(oInput.id.indexOf(oTable.id + "_DeleteCheckbox_") == 0){
			if(oInput.checked){
				var intObjectId = parseInt(oInput.id.substring((oTable.id + "_DeleteCheckbox_").length));
				if(!isNaN(intObjectId)){
					if(SelectedIdList != "") SelectedIdList += ",";
					SelectedIdList += intObjectId;
				}
			}
		}
		
	}
	return SelectedIdList;
}

AjaxTable.DeleteSelected = function(tableId){
	var oTable = AjaxTable.GetTable(tableId);
	
	//Get a list of the items that have been selected.
	DeleteList = AjaxTable.GetSelectedIdList(oTable);
	
	//If the user has not checked any checkboxes.
	if(DeleteList == ""){
		alert("Please select some items to delete.");
		return;
	}
	
	if(confirm("Are you sure you wish to delete these items and all related objects?")){
		AjaxTable.DeleteItems(DeleteList, oTable);
	}
}

AjaxTable.DeleteItems = function(IdList, oTable){
	var oAjaxRequest = new window.top.AjaxRequest();
	oAjaxRequest.XmlRequest.open("POST", XibAjax.CleanUrl("[AjaxLocation]/json.aspx"), true);
	oAjaxRequest.XmlRequest.setRequestHeader('Content-Type','application/x-www-form-urlencoded');

	var qs = "";
	qs = XibAjax.AddToQueryString(qs, "COMMAND", "DELETE_ID_LIST");
	qs = XibAjax.AddToQueryString(qs, "IdList", IdList);
	qs = XibAjax.AddToQueryString(qs, "Finder", oTable.Finder.Serialize());

	
	//remove possibility of cache/proxy servers
	qs = XibAjax.AddToQueryString(qs, "t", new Date().getTime());
	
	oAjaxRequest.oncomplete = "AjaxTable.HandleDeleteItems";
	oAjaxRequest.Table = oTable;
	
	debug("del:" +  qs);
	oAjaxRequest.XmlRequest.send(qs);
	IncrementProcessCounter();
	
}

AjaxTable.HandleDeleteItems = function(Request){
	var oTable = Request.Table;
	
	var ResponseArray = eval(Request.XmlRequest.responseText);
	var ResponseObject = ResponseArray[0];
	
	if(ResponseObject.Success){
		AjaxTable.Refresh(oTable.id);
	}else{
		alert(ResponseObject.ErrorMessage);
	}
	DecrementProcessCounter();
}



/*
################################################
#    END TABLE AJAX FUNCTIONS
################################################
*/






/*
################################################
#    START FORM AJAX FUNCTIONS
################################################
*/
function AjaxForm(){
}

AjaxForm.Get = function(formId){
	var oForm = document.getElementById(formId);
	return(oForm);
}


AjaxForm.Init = function(formId, oTable, id){
   	var oForm = AjaxForm.Get(formId);
   	oForm.ContainingTable = oTable;
   	oForm.SerializedFinder = oForm.ContainingTable.Finder.Serialize();
   	
   	oForm.ElementList = "";
   	
   	if(id != null){
   	    AjaxForm.GetDataFromServer(formId, id);
   	}
    
}

/*
	This method gets the data from the server to load into a form.
	Typically used by the edit pages.
*/
AjaxForm.GetDataFromServer = function(formId, itemId){

	var oAjaxRequest = new window.top.AjaxRequest();
	oAjaxRequest.XmlRequest.open("POST", XibAjax.CleanUrl("[AjaxLocation]/json.aspx"), true);
	oAjaxRequest.XmlRequest.setRequestHeader('Content-Type','application/x-www-form-urlencoded');

	oAjaxRequest.formId = formId;
	var oForm = AjaxForm.Get(formId);
	
	var qs = "";
	qs = XibAjax.AddToQueryString(qs, "COMMAND", "GET_BY_ID");
	//qs = XibAjax.AddToQueryString(qs, "ClassName", oForm.attributes["XiClass"].value);
	qs = XibAjax.AddToQueryString(qs, "id", itemId);
	
	//WE NEED TO USE THIS SORT OF CODE TO GET THIS TO WORK:
	qs = XibAjax.AddToQueryString(qs, "Finder", oForm.SerializedFinder);

	//remove possibility of cache/proxy servers
	//qs = XibAjax.AddToQueryString(qs, "t", new Date().getTime());
	debug(qs);
	oAjaxRequest.oncomplete = "AjaxForm.GetDataFromServer_finalise";
	
	oAjaxRequest.XmlRequest.send(qs);
	IncrementProcessCounter();
}


AjaxForm.GetDataFromServer_finalise = function(oAjaxRequest){
	var DataReturned = oAjaxRequest.XmlRequest.responseText;
	
	var oForm = AjaxForm.Get(oAjaxRequest.formId);
	var data = eval("(" + DataReturned + ")");
	
	// Give the form itself a reference to the 
	// json data.
//	oForm.jsonData = data;
	
	AjaxForm.PutDataIntoForm(oForm, data);
	DecrementProcessCounter();
	
}	

AjaxForm.PutDataIntoForm = function(oForm, data){
	oForm.jsonData = data;
	for(property in oForm.jsonData){
		propertyName = property;
		value = data[propertyName];
		
		AjaxForm.PutDataItemInForm(oForm, propertyName, value);
		
	}
	
	oForm.object_id = data.id;
}

XibAjax.GetAttribute = function(oElement, attributeName){
	var oAttr = oElement.attributes[attributeName];
	if(oAttr){
		return oAttr.value;
	}
	return "";
}

AjaxForm.InputType = function(oElement){
	if(oElement == null) return null;
	
	if(oElement.tagName == "DIV") return "div";
	
	if(oElement.type == "checkbox") return "checkbox";
	
	var datatype = XibAjax.GetAttribute(oElement, "datatype");
	if(datatype == "DateTime") return "DateTime";
	
	return("text");
}


AjaxForm.Save = function(formId){
    var oForm = AjaxForm.Get(formId);
				var resultDiv = oForm.childNodes[0];//document.getElementById(oForm.id+"_"+oForm.object_id+"_id");
				resultDiv.style.fontWeight = "bold";
				resultDiv.style.backgroundColor = "orange";
    var qs = XibAjax.AddToQueryString("", "COMMAND", "UPDATE_OBJECT");
    qs = XibAjax.AddToQueryString(qs, "id", oForm.object_id);
    qs = XibAjax.AddToQueryString(qs, "Finder", oForm.SerializedFinder);
    qs = AjaxForm.SerializeData(oForm, qs);
    var oAjaxRequest = new AjaxRequest();
				oAjaxRequest.XmlRequest.open("GET",  XibAjax.CleanUrl("[AjaxLocation]/json.aspx?"+qs), true);
				oAjaxRequest.oElement = oForm;
				oAjaxRequest.oncomplete = "AjaxForm.Save_finalise";
				oAjaxRequest.XmlRequest.send(null)
				IncrementProcessCounter();
				debug(qs);

				   
    
    //AjaxTable.Refresh(oForm.ContainingTable.id);

}

AjaxForm.Save_finalise = function(oAjaxRequest){
    var oForm = oAjaxRequest.oElement;
    var resultDiv = oForm.childNodes[0];
				//var resultDiv = document.getElementById(oForm.id+"_"+oForm.object_id+"_id");
				resultDiv.style.fontWeight = "bold";
				var success = eval(oAjaxRequest.XmlRequest.responseText)[0];
				var o = eval(oAjaxRequest.XmlRequest.responseText)[1];
				if(success){
								resultDiv.style.fontWeight = "bold";
								resultDiv.style.backgroundColor = "lightGreen";
								var arrSpans = oForm.getElementsByTagName("span");
								var iStartOfPropertyID = (oForm.id+"_"+oForm.object_id+"_").length;
								for(var i = 0; i < arrSpans.length; i++){
												var span = arrSpans[i];
												if(span.id){
																var spanPropertyID = span.id.substring(iStartOfPropertyID);
																if(span.getElementsByTagName("input").length == 0 && o[spanPropertyID]){
																				span.innerHTML = ToHTML(o[spanPropertyID]);
																}
												}
								}
								if(oForm.object_id == -1){
												oForm.object_id = o.id;
												resultDiv.innerHTML = o.id;
												resultDiv.id = oForm.id+"_"+oForm.object_id;
												AjaxTable.AddNewRow(oForm.ContainingTable);
								}
				} else {
								var errorMessage = o.Message;
								for(var i = 0; i < o.Reasons.length; i++){
												errorMessage += "\r\n - "+o.Reasons[i];
								}
								alert(errorMessage);
								resultDiv.style.backgroundColor = "red";
								resultDiv.title = 	errorMessage;
				}
				DecrementProcessCounter();
}


AjaxForm.SerializeData = function(oForm, qs){
    var ArrElements = oForm.ElementList.split("|");
    
    var index = 0;
    
    for(var i=0; i<ArrElements.length; i++){
        var val = AjaxForm.GetDataItemFromForm(oForm, ArrElements[i]);
        if(val != null){
            qs = XibAjax.AddToQueryString(qs, "n" + index, ArrElements[i]);
            qs = XibAjax.AddToQueryString(qs, "v" + index, val);
            index++;
        }
    }
    
    return(qs);

}
AjaxForm.GetDataItemFromForm = function(oForm, name){
	var oElement = document.getElementById(oForm.id + "_" + name);
	var strType = AjaxForm.InputType(oElement);
	switch (strType){
		case "text":
		case "DateTime":
			return(oElement.value);
		break;
		case "checkbox":
			return(oElement.checked);
		break;
    }
    return null;
}



AjaxForm.AddElementToList = function(oForm, name){
    if(oForm.ElementList != "") oForm.ElementList += "|";
    oForm.ElementList += name;
}

AjaxForm.PutDataItemInForm = function(oForm, name, value){
	var oElement = document.getElementById(oForm.id + "_" + name);
	
	
	var strType = AjaxForm.InputType(oElement);
	switch (strType){
		case "text":
			oElement.value = value;
			AjaxForm.AddElementToList(oForm, name);
		break;
		
		case "checkbox":
			oElement.checked = value;
			AjaxForm.AddElementToList(oForm, name);
		break;
		
		case "DateTime":
			oElement.value = value.print("%d/%m/%Y %H:%M");
			AjaxForm.AddElementToList(oForm, name);
		break;
		
		case "div":
			oElement.innerHTML = value;
		break;
		
	}
	

}


/*
################################################
#    END FORM AJAX FUNCTIONS
################################################
*/





/*
################################################
#    START AJAXFINDER FUNCTIONS
################################################

The AjaxFinder represents which finder to use.  Each table is
given a finder property, which is used in all list, search, delete
and add functions.
*/

/*
ClassName: 
	The name of the class.  If you are producing a table of categories, ClassName = "Category".
	
ReferringObjectClassName:
	If the finder is found via an existing object, this holds the class name of the existing object.
	For instance, if you are retreiving the products within a category, this will hold "Category".
	
ReferringObjectId:
	If the finder is found via an existing object, this holds the id of the existing object.
	For instance, if you are retreiving the products within category 5, this will hold the number 5.
	
ReferringObjectProperty:
	If the finder is used to look for possibilities of a property within an existing object, this
	is set to the name of the property.  For instance if you have tblProducts with category_id referring
	to a category, ReferringObjectProperty will	be set to category_id.
	
ReferringObjectFinder:
	If the table is showing a sublist - e.g. list of products within a category, this is
	set to the name of the finder property within the category class.

*/
function AjaxFinder(ClassName, ReferringObjectClassName, ReferringObjectId, ReferringObjectProperty, ReferringObjectFinder){
	if(!ReferringObjectClassName) ReferringObjectClassName = "";
	if(!ReferringObjectId) ReferringObjectId = "";
	if(!ReferringObjectProperty) ReferringObjectProperty = "";
	if(!ReferringObjectFinder) ReferringObjectFinder = "";

	this.ClassName = ClassName;
	this.ReferringObjectClassName = ReferringObjectClassName;
	this.ReferringObjectId = ReferringObjectId;
	this.ReferringObjectProperty = ReferringObjectProperty;
	this.ReferringObjectFinder = ReferringObjectFinder;
}

AjaxFinder.prototype.Serialize = function(){
	var str = "";
	str += this.ClassName;
	str += "|" + this.ReferringObjectClassName;
	str += "|" + this.ReferringObjectId;
	str += "|" + this.ReferringObjectProperty;
	str += "|" + this.ReferringObjectFinder;
	
	return(str);
}


/*
################################################
#    END AJAXFINDER FUNCTIONS
################################################
*/



















/*
################################################
#    START ID LIST AJAX FUNCTIONS
################################################

The ID List class handles 2 lists - on a list of ids which need to be removed 
and one a list of ids that need to be added.

*/

function IdListItem(id,name){
	this.id = id;
	this.name = name;
}


function IdList(AddInputId, RemoveInputId, SummaryElementId, PickerType){
	this.ItemsToAdd = new Array();
	this.ItemsToRemove = new Array();
	this.PersistentSummaryElement = null;
	this.AddInput = document.getElementById(AddInputId);
	this.RemoveInput = document.getElementById(RemoveInputId);
	this.SummaryElement =  document.getElementById(SummaryElementId);
	this.PickerType = PickerType;
	
	//If it's a single element picker, we need to load the data into the 
	//list item data.
	if(this.PickerType == "Single"){
		var tmp = parseInt(this.AddInput.value);
		if(!isNaN(tmp)){
			this.AddItem(new IdListItem(tmp, this.SummaryElement.innerHTML));
		}
	}
}


IdList.GetIds = function(theArray){
	var textIdList = "";
	for(var i=0; i<theArray.length; i++){
		if(textIdList != "") textIdList += ",";
		textIdList += theArray[i].id;
	}
	
	return textIdList;
}


IdList.AddToArray = function(theArray, id){
	for(var i=0; i<theArray.length; i++){
		if(theArray[i] == id) return;
	}
	theArray[theArray.length] = id;
}
IdList.RemoveFromArray = function(theArray, item){
	var newArray = new Array();
	var found=0;
	for(var i=0; i<theArray.length; i++){
		if(theArray[i].id == item.id) found++;
		else newArray[i-found] = theArray[i];
	}
	return newArray;
}

IdList.prototype.SetInputValues = function(){
	if(this.AddInput) this.AddInput.value = IdList.GetIds(this.ItemsToAdd);
	if(this.RemoveInput) this.RemoveInput.value = IdList.GetIds(this.ItemsToRemove);
	
	if (this.PickerType=="Single") {
		var summary = "";
		for(var i=0; i<this.ItemsToAdd.length; i++){
			if(summary != "") summary += ", ";
			summary += this.ItemsToAdd[i].name;
		}
		this.SummaryElement.innerHTML = summary;
	} else {
		this.SummaryElement.innerHTML = "";
		for(var i=0; i<this.ItemsToAdd.length; i++){
			var newOpt = document.createElement("option");
			newOpt.text = this.ItemsToAdd[i].name;
			newOpt.value = this.ItemsToAdd[i].id;
			if (i%2==1)newOpt.className = "odd";
			this.SummaryElement.options.add(newOpt);
		}
	}
	if (this.PersistentSummaryElement!=null) {
		var summary2 = "";
		for(var i=0; i<this.ItemsToAdd.length; i++){
			if(summary2 != "") summary2 += "{[[split]]}";
			summary2 += this.ItemsToAdd[i].name;
		}
		this.PersistentSummaryElement.value = summary2;
	}
	
}


IdList.prototype.AddItem = function(id){
	if(this.PickerType == "Single"){
		this.ItemsToAdd = new Array();
		this.ItemsToAdd[0] = id;
	}else{
		IdList.AddToArray(this.ItemsToAdd, id);
		this.ItemsToRemove = IdList.RemoveFromArray(this.ItemsToRemove, id);
	}
	this.SetInputValues();
}

IdList.prototype.AddItems = function(arrItems){
	for (var iLop=0;iLop<arrItems.length;iLop++) {
		this.AddItem(arrItems[iLop]);
	}
}


IdList.prototype.RemoveItem = function(id){
	if(this.PickerType == "Single"){
		this.ItemsToAdd = new Array();
	}else{
		IdList.AddToArray(this.ItemsToRemove, id);
		this.ItemsToAdd = IdList.RemoveFromArray(this.ItemsToAdd, id);
	}
	this.SetInputValues();
}

IdList.prototype.AddOrRemoveItem = function(id, isAdd, description){
	var item = new IdListItem(id, description);

	if(isAdd) this.AddItem(item);
	else this.RemoveItem(item);
	
	debug(this.ItemsToAdd + ".. rem:" + this.ItemsToRemove);
}

/*
	Returns true if is has been selected on the client side,
	false if it has been unselected on the client side.  Null if
	neither has occurred.
*/
IdList.prototype.IsSelected = function(id){
	for(var i=0; i<this.ItemsToRemove.length; i++){
		if(this.ItemsToRemove[i].id == id) return false;
	}
	for(var i=0; i<this.ItemsToAdd.length; i++){
		if(this.ItemsToAdd[i].id == id) return true;
	}
	
	return null;
}
/*
################################################
#    END ID LIST AJAX FUNCTIONS
################################################
*/




function debug(text){
  var odiv = window.top.document.getElementById("debugDiv");
  if(odiv == null) return;
  odiv.innerHTML += "<hr/>" + text+"";
 // odiv.innerHTML += "<hr/><textarea rows=\"10\" cols=\"50\">" + text+"</textarea>";
  
}

/*
 * LOADING BAR
 *
 */
 
var GlobalProcessCount = 0;
function GetProcessCount()
{
    
    return GlobalProcessCount;
}

function IncrementProcessCounter()
{
    debug("GlobalProcessCount:" + GlobalProcessCount);
    ++GlobalProcessCount;
    LoadingBar.ShowLoading();
}

function DecrementProcessCounter()
{
    debug("GlobalProcessCount:" + GlobalProcessCount);
    --GlobalProcessCount;
    if (GlobalProcessCount <= 0)
    {
        GlobalProcessCount = 0;
        LoadingBar.HideLoading();
    }
}

function LoadingBar() { }
LoadingBar.LoadingEl = null;

LoadingBar.ShowLoading = function()
{
	if (LoadingBar.LoadingEl == null)
	{
		LoadingBar.LoadingEl = document.getElementById('AjaxLoading');
	}
	if (LoadingBar.LoadingEl != null)
	{
		LoadingBar.LoadingEl.style.display = "block";
		
		LoadingBar.FadeLoading(true);
	}
}
 
LoadingBar.LoadingTimer = null;
LoadingBar.MaxOpacity = 80;
LoadingBar.MinOpacity = 0;
LoadingBar.OpacityInc = 20;
LoadingBar.OpacityTimeout = 20;
LoadingBar.FadeLoading = function(Out, Continue)
{
	if (LoadingBar.LoadingEl == null)
	{
		LoadingBar.LoadingEl = el('AjaxLoading');
	}
	
	if (LoadingBar.LoadingEl != null)
	{
		clearTimeout(LoadingBar.LoadingTimer);
		var oAlphaRegExp = new RegExp("([0-9]+)");
		var Alpha = null;
		if (LoadingBar.LoadingEl.style.filters)
		{
		    parseInt(oAlphaRegExp.exec(LoadingBar.LoadingEl.style.filter));
		}
		else
		{
		    Alpha = parseInt(parseFloat(LoadingBar.LoadingEl.style.opacity) * 100);
		}

		if (!isNaN(Alpha))
		{
			if (Out)
			{
				if (Alpha == LoadingBar.MaxOpacity)
				{
					return;
				}
				else
				{
					Alpha += LoadingBar.OpacityInc;
					
					if (Alpha > LoadingBar.MaxOpacity)
					{
						Alpha = LoadingBar.MaxOpacity;
					}
					
				    LoadingBar.LoadingEl.style.filter = 'alpha(opacity=' + Alpha + ')';
				    LoadingBar.LoadingEl.style.opacity = (Alpha / 100);
					if (Alpha != LoadingBar.MaxOpacity)
					{
						LoadingBar.LoadingTimer = setTimeout('LoadingBar.FadeLoading(true)', LoadingBar.OpacityTimeout);
					}
				}
			}	
			else
			{
			    Alpha -= LoadingBar.OpacityInc;
			    if (Alpha < LoadingBar.MinOpacity)
			    {
				    Alpha = LoadingBar.MinOpacity;
			    }
		        LoadingBar.LoadingEl.style.filter = 'alpha(opacity=' + Alpha + ')';
		        LoadingBar.LoadingEl.style.opacity = (Alpha / 100);
			    if (Alpha != LoadingBar.MinOpacity)
			    {
				    LoadingBar.LoadingTimer = setTimeout('LoadingBar.FadeLoading(false)',LoadingBar.OpacityTimeout);
			    }
			    else
			    {
				    LoadingBar.LoadingEl.style.display = "none";
			        return;
			    }
			}
		}
	}
	
	//window.status = "Alpha:" + Alpha;
}

LoadingBar.HideLoading = function()
{
	if (LoadingBar.LoadingEl == null)
	{
		LoadingBar.LoadingEl = el('AjaxLoading');
	}	
	if (GetProcessCount() < 0)
		GlobalProcessCount = 0;
		
	//window.status = "RequestCount:" + RequestCount;
	
	if (LoadingBar.LoadingEl != null && GetProcessCount() <= 0)
	{
		LoadingBar.FadeLoading(false);
		//LoadingEl.style.display = "none";
	}
}



/* FEEDBACK CODE */
/* FEEDBACK CODE */
/* FEEDBACK CODE */
/* FEEDBACK CODE */
/* FEEDBACK CODE */

function HideFeedback()
    {
        var El = el("Feedback");
        if (El != null)
        {
            if (typeof(El.Hide) == 'function' ||
                typeof(El.Hide) == 'object')
            {
                El.Hide();
            }
        }
    }

function ShowFeedback(FeedbackId, Message, ShowMask, Title, OnConfirmFunc, ConfirmButtonText, OnCancelFunc, CancelButtonText)
{
    var FeedbackDiv = el(FeedbackId);
    
    if (FeedbackDiv != null)
    {
        var AllSpans = FeedbackDiv.getElementsByTagName("SPAN");
        
        for (var i = 0; i < AllSpans.length; ++i)
        {
            if (AllSpans[i].className == "Title")
            {
                FeedbackDiv.TitleEl = AllSpans[i];
            }
            if (AllSpans[i].className == "Body")
            {
                FeedbackDiv.BodyEl = AllSpans[i];
            }
            if (AllSpans[i].className == "Button Ok")
            {
                FeedbackDiv.OkEl = AllSpans[i];
            }
            if (AllSpans[i].className == "Button Cancel")
            {
                FeedbackDiv.CancelEl = AllSpans[i];
            }
        }
        
        //Variables
        FeedbackDiv.ShowMask = ShowMask;
        FeedbackDiv.OnConfirmFunc = OnConfirmFunc;
        FeedbackDiv.OnCancelFunc = OnCancelFunc;
        FeedbackDiv.ConfirmButtonText = ConfirmButtonText;
        FeedbackDiv.CancelButtonText = CancelButtonText;
        
        //Functions
        FeedbackDiv.OkClicked = Feedback_OkClicked;
        FeedbackDiv.CancelClicked = Feedback_CancelClicked;
        FeedbackDiv.Hide = Feedback_Hide;
        FeedbackDiv.Show = Feedback_Show;
        
        FeedbackDiv.Show(Message, Title);
    }
}


function Feedback_OkClicked()
{
    if (typeof(this.OnConfirmFunc) == 'function')
    {
        this.OnConfirmFunc();
    }
}

function Feedback_CancelClicked()
{
    if (typeof(this.OnCancelFunc) == 'function')
    {
        this.OnCancelFunc();
    }
}

function Feedback_Show(Message, Title)
{

    if (this.TitleEl != null && Title != null)
    {
        this.TitleEl.innerHTML = ToHTML(Title);
    }
    
    if (this.BodyEl != null && Message != null)
    {
        this.BodyEl.innerHTML = ToHTML(Message);
    }
    
    if (this.OkEl != null &&
        this.ConfirmButtonText != null &&
        this.OnConfirmFunc != null)
    {
        this.OkEl.style.display = "inline";
        this.OkEl.innerHTML = ToHTML(this.ConfirmButtonText);
    }
    else
    {
        this.OkEl.style.display = "none";
    }
    
    if (this.CancelEl != null &&
        this.CancelButtonText != null &&
        this.OnCancelFunc != null)
    {
        this.CancelEl.style.display = "inline";
        this.CancelEl.innerHTML = ToHTML(this.CancelButtonText);
    }
    else
    {
        this.CancelEl.style.display = "none";
    }

    if (this.ShowMask)
    {
        ShowMask();
    }
    ShowEl(this.id);
    CenterEl(this.id);
}

function Feedback_Hide()
{

    HideEl(this.id);
    if (this.ShowMask)
    {
        HideMask();
    }
}



function ShowMask()
{
    ShowEl("Mask");
    var AllSelects = document.getElementsByTagName("SELECT");
    document
    
    XibAjax.DoShowHideSelect = false;
    
    for (var i = 0; i < AllSelects.length; ++i)
    {
        AllSelects[i].style.visibility = "hidden";
    }
}

function HideMask()
{
    HideEl("Mask");
    
    var AllSelects = document.getElementsByTagName("SELECT");
    XibAjax.DoShowHideSelect = true;
    for (var i = 0; i < AllSelects.length; ++i)
    {
        AllSelects[i].style.visibility = "";
    }
}

function ShowEl(ElID)
{
    var El = el(ElID);
    if (El != null)
    {
        El.style.display = "block";
    }
}

function HideEl(ElID)
{
    var El = el(ElID);
    if (El != null)
    {
        El.style.display = "none";
    }
}

function CenterEl(ElID)
{
    var El = el(ElID);
    if (El != null)
    {
        El.style.left = ((document.body.clientWidth / 2) - (El.offsetWidth / 2)).toString() + "px";
        El.style.top = ((document.body.clientHeight / 2) - (El.offsetHeight / 2)).toString() + "px";
    }
}
