//////////////////////////////////////////////
// Column Browser Control
//////////////////////////////////////////////
// 
// The column browser object provides a 
// surface to render Column objects on, as 
// well as the functionality to handle 
// re-ordering, closing, adding and updating  
// the mSpace slice.
// 
// The column browser contains a column 
// holder Unorderd List (UL) element, which 
// it appends the Column object List Item 
// elements to.  It uses the Scriptaculous 
// Sortable library to handle the movement 
// of columns within the slice, and makes 
// AJAX calls when the slice needs to be 
// updated.
//
//////////////////////////////////////////////

var ColumnBrowser = Class.create();
ColumnBrowser.prototype = {
//
// Member Variables
//render surface
sfc: "CBSFC",
//closed cols render surface
ccsfc: "CBCCSFC",
//control surface
ctlsfc: null, 

ColHldr: null,
ColCont: null,
CBHdr: null,

DRGBTN: null,

//is closed flag
closed: false,
//col and slice arrays
openCols: new Array(),
allCols: new Array(),
allColsLookup: new Array(),
defSlice: new Array(),
//min col witdh
minColWdth: 180,
//timeout id
tmoutID: -1,
//are cols loaded
colsLoaded: false,
//intital history 
initHist: null,
//history array
histArr: null,
//histroy string
histStr: "",
//intitial breadcrumb text
initBdCrmb: "mSpace Explorer ",
//column browser has been opened
started: false,
//intital event call & params, when closed and opened from external click
initEvtCall: null, 
initEvtParams: null,
//closed columns control
ccCtl: null,
//current column browser history url
colHistURL: "",
//first data load flag
firstDataLoad: false,
//spacer padding for drag operations
spcrPdding: 0,

//Current scriptaculour sortables element
sortables: null,
//Associative array of columns
allColsMap: new Object(),
//current drag target for sortables
currentDragCol: null,


//
// Constructor
initialize: function(oo)
	{
		
		//read options
		this.sfc = oo.renderSurface || this.sfc;
		this.ccsfc = oo.closedColumnRenderSurface || this.ccsfc;
		this.initBdCrmb = oo.initialBreadcrumbText || this.initBdCrmb;
		
		window.ColumnBrowser = this;

		
		
		this.m_loaddefaultSliceBtn = Builder.node('div', {className : "loadSliceBtn", title: "Load the default slice..."});
		Event.observe(this.m_loaddefaultSliceBtn, "click", this.LoadDefaultSlice.bindAsEventListener(this));
		
		this.m_resetSliceBtn = Builder.node('div', {className : "resetSliceBtn", title: "Reset the current slice..."});
		Event.observe(this.m_resetSliceBtn, "click", this.ResetSlice.bindAsEventListener(this));
		
		
		
		this._id = "";
		l_id = this._id;
		this._pid = "CB_";
		l_pid = this._pid;		
		
		this.ColHldr = $(Builder.node('ul', {id: "ColHldr"}));
	
		this.ColCont = $(Builder.node('div', {id : "ColCont"},
																 [
																	  this.ColHldr,
																	  Builder.node('div', {id: "ColLdng"}, [Builder.node('div', {id: "SliceLoading", className: 'loading'}), "Loading Columns"]),
																	  Builder.node('div', {id: "AtoZ", style: "display:none; top:0px; left0px;"})
																 ]));
																 
		this.CBHdr	= Builder.node('div', {id : "CBHdr"},
																 [
																	Builder.node('div', {id: "BrdCrmb"}, [this.initBdCrmb]),
																	Builder.node('div', {id: "AddColsBtn"})
																 ]);
																 
		this.DRGBTN = Builder.node('a', {id: "CBDRAGBTN"});
		
		this.ctlsfc = Builder.node('div', {id : "CB", style : "display:none;"}, [ this.CBHdr, this.ColCont, this.DRGBTN ]);
		
		this.dmycol = Builder.node('div', {id : "DmyCol"},
					 [
						  Builder.node('div', {className : "spcr"}, 
									   [
										Builder.node('div', {className: "cont"})
										])						  
					 ]);		
		
		
		
		document.body.appendChild(this.ctlsfc);
		
		
		
		
		//Register custom events
		////////////////////////

		document.observe('mSpaceApplication:PageResize',			this.Resize.bindAsEventListener(this));
		document.observe('mSpaceApplication:Start',						this.Start.bindAsEventListener(this));
		document.observe('mSpaceApplication:HistoryStart',		this.HistoryStart.bindAsEventListener(this));
		
		document.observe('Column:MoveLeft',										this.ColumnMoveLeft.bindAsEventListener(this));
		document.observe('Column:MoveRight',									this.ColumnMoveRight.bindAsEventListener(this));
		document.observe('Column:Close',											this.ColumnClose.bindAsEventListener(this));
		document.observe('Column:Open',												this.ColumnOpen.bindAsEventListener(this));							// Unused?
		document.observe('Column:InitialLoad',								this.ColumnLoad.bindAsEventListener(this));							// Unused?
		document.observe('Column:SelectItem',									this.SelectItem.bindAsEventListener(this));	
		document.observe('Column:SelectItemWithSlice',				this.SelectItemWithSlice.bindAsEventListener(this));
		document.observe('Column:UnSelectItem',								this.UnSelectItem.bindAsEventListener(this));	
		document.observe('Column:UnSelectAll',								this.UnSelectAll.bindAsEventListener(this));
		
		document.observe('ColumnBrowser:ClearSelections',			this.ClearColumnSelections.bindAsEventListener(this));	// Unused?
		document.observe('ColumnBrowser:QueueColumn',					this.QueueColumn.bindAsEventListener(this));
		
		document.observe('List:Scroll',												this.ShowListScrollPopup.bindAsEventListener(this));			
		document.observe('List:LoadPartialItems',							this.LoadPartialColumnData.bindAsEventListener(this));
		
		//Listen for any clicks, in case col browser is not open
		document.observe('Item:MouseClick',										this.ExternalItemClick.bindAsEventListener(this));			
	
		document.observe('mSpaceHistory:HistoryChange',				this.HistoryChange.bindAsEventListener(this));	
		
		//Register DOM events
		/////////////////////
		
		Event.observe("AddColsBtn", "click", this.OpenClosedCols.bindAsEventListener(this));
		
		this.HistoryStart(oo.history);
		
		if(mSpaceApplication.GetConfig('ColumnBrowser.Resizing.Vertical'))
		{
			//Add the columns resize handle
			//Make the object resizable: custom scriptaculous function
			var t = this;
			var opts = {};
			opts.min = [0, 155];
			opts.constraint = "vertical"
			opts.handle = t.DRGBTN;
			opts.change = function(){
				t.Resize();
			}
			opts.onEnd = function()
			{	
				for (var i=0;i<t.ColHldr.childNodes.length;i++)
				{
					var childNode = t.ColHldr.childNodes[i];
					if (childNode)
					{
						//resize with height, and any additional space over the cols min width
						t.allColsMap[childNode.id].list.Resize();
					}
				}	
			}
			new Resizable(this.ctlsfc, opts);
		}
		else
		{
			$(this.DRGBTN).hide();
		}
	},	
	
//Resize the column browser and the columns within it
Resize: function()
	{		
			if (this.ColHldr.childNodes.length==0)
				return;
				
			//Resize the container to be the full height minus the col browser header
			this.ColCont.style.height = (this.ctlsfc.clientHeight - this.CBHdr.offsetHeight - this.DRGBTN.offsetHeight) + "px";

			//get largest width of cols, if no scrolling
			var colLength = Math.floor((this.ColCont.clientWidth-1)/this.ColHldr.childNodes.length);
			
			//loop through and get the total width of all cols, at min
			//width
			var totalMins = 0;
			for (var i=0;i<this.ColHldr.childNodes.length;i++)
			{
				var childNode = this.ColHldr.childNodes[i];
				if (childNode)
					totalMins += this.allColsMap[childNode.id].minCWdth;
			}			
			
			//Check the difference between min width and actual width
			var minWidthDifference = (this.ColCont.clientWidth-1) - totalMins;
			//Get a total amount of space each column can go bigger than their min width
			var minWidthAddition = Math.floor(minWidthDifference/this.ColHldr.childNodes.length);
			
			if (minWidthAddition<0)
				minWidthAddition = 0;
			
			
				
			var spcrPdding = 0;
			//Getting the padding only works in ie, so this compensates for the lack of 
			//moz-box-typ.? css style
			var styleString = getStyle(this.dmycol, "padding");
			if ((styleString!="undefined") && (styleString!=""))
			{
				spcrPdding = parseInt(styleString);
				this.spcrPdding = spcrPdding;
			}			
			
			//set dummy coluymn width
			this.dmycol.style.width = (colLength-(spcrPdding*2)) + "px";		
			this.dmycol.style.height = (this.ColCont.clientHeight) + "px";
				
			//force a resize of the col widths
			for (var i=0;i<this.ColHldr.childNodes.length;i++)
			{
				var childNode = this.ColHldr.childNodes[i];
				if (childNode)
				{
					//resize with height, and any additional space over the cols min width
					this.allColsMap[childNode.id].Resize(minWidthAddition, (this.ColCont.clientHeight));
				}
			}					
			//$("ColHldr").style.width = (this.openCols.length * colLength) + "px";
				
				
			//get total width again
			var totalWidth = 0;
			for (var i=0;i<this.ColHldr.childNodes.length;i++)
			{
				var childNode = this.ColHldr.childNodes[i];
				totalWidth += childNode.offsetWidth;
			}
			

			//set the holder to the right width	
			this.ColHldr.style.width = totalWidth + "px";
			
			
			//IF the width is larger than available col browser width, then take 
			//into account the scrollbar in the height.
			var scrollBarH = 0;
			if ((this.ColHldr.offsetWidth)>this.ColCont.offsetWidth)
			{
				scrollBarH = 0;
			}
			this.ColHldr.style.height = (this.ColCont.clientHeight-scrollBarH) + "px";			
			
			//Force another resize, with the scroll bar height taken into account.
			for (var i=0;i<this.ColHldr.childNodes.length;i++)
			{
				var childNode = this.ColHldr.childNodes[i];
				if (childNode)
				{
					this.allColsMap[childNode.id].Resize(minWidthAddition, (this.ColCont.clientHeight-scrollBarH-(spcrPdding*2)));
				}
			}	
						
			
			if ((browserDetails[0]!="msie"))
			{
				//Fix for Mozilla that refreshes the scroll bars on resize
				//as they stay persistant when resizing the window and 
				//NOTE: Causes overflow problem on ie though
				this.ColCont.style.overflow = "hidden";
				this.ColCont.style.overflow = "auto";
				this.ColCont.style.overflowX = "auto";
				this.ColCont.style.overflowY = "hidden";
			}		
			
	},
	
	
//Start the column browser with a history object.
//Only loads the columns, if there is a history object 
//within the startup parameters
HistoryStart: function(e)
	{
		var histObj;
		
		if(e)
		{
			if(e.memo)
				histObj = e.memo;	// This function has been called from an event trigger
			else
				histObj = e;	// Assume this function has been called from the init function
		}
			
		if (histObj && histObj != '')
		{		
			if (histObj["Column.SelectItemHistory"])
			{
				$(this.sfc).innerHTML = ""
				$(this.sfc).appendChild($("CB"));
				$("CB").style.display = "";
				
				this.ccCtl = new ClosedColumnBrowser({ renderSurface: $(this.ccsfc) });
		
				this.LoadColumns(histObj);

				mSpaceApplication.Resize(false);
				
				this.started = true;			
			}	
	
		}
		
	},

//Manual start the column browser.
//checks for a url property in the passed
//paremter so set the info box to.
Start: function(e)
	{
		var histObj = e.memo;
		
		//The mSpace application is starting, so add the column browser to the page
		$(this.sfc).innerHTML = "";
		$(this.sfc).appendChild($("CB"));	
		$("CB").style.display = "";
		
		//create a closed col control
		this.ccCtl = new ClosedColumnBrowser({ renderSurface: $(this.ccsfc) });		
		
		if (histObj)
		{
			if (histObj['url'])
			{
				document.fire('InformationControl:SetUrl', histObj['url']);
			}				
			else if (histObj['initurl'] && (!window.mSpaceInformationControl.initialized))
			{
				document.fire('InformationControl:SetUrl', histObj['initurl']);
			}			
		}
		
		//load the columns
		this.LoadColumns();
		//mSpaceApplication.Resize(false);
	
		this.started = true;
	},
	
	
//Add a new column to the column browser, either as open
//or as a closed column
AddColumn: function(cparams, display, position)
	{
			var c = new Column(cparams, position);
			
			//Add a mapping between the col surface, and the col object
			this.allColsMap[(c._pid + "SFC" + c._id)] = c;
			
			//Add col to all colls array
			this.allCols.push(c);
			this.allColsLookup[c.uri] = c;
			if (display)
			{
				//if col is to be displayed, add it to the col holder
				this.openCols.push(c);	
				this.defSlice.push(c);
				c.Append(this.ColHldr);
			}
			else
			{
				//otherwise add it to the closed column control
				this.ccCtl.AddColumn(c);
			}
			
			/*
			var colLength = (this.ColCont.offsetWidth-1)/this.ColHldr.childNodes.length;
			if (colLength<this.minColWdth)
				colLength = this.minColWdth;
			
			//An initial column resize.
			for (var i=0;i<this.ColHldr.childNodes.length;i++)
			{
				var childNode = this.ColHldr.childNodes[i];
				if (childNode)
					this.allColsMap[childNode.id].ctlsfc.style.width = colLength + "px";
			}			
			
			var temp = "blah";
			*/
	},

//Mouse Click event
MouseClick: function(e, element)
	{
		//If the reload button is clicked, then clear
		//all column selections
		if (element==this.m_reloadBtn)
		{
			this.ClearAllColumnSelections();
		}
	},

MouseOver: function(e, element)
	{
	},

MouseOut: function(e, element)
	{

	},
	
//Move column to the left, 
//takes a column object as param
ColumnMoveLeft: function(e)
	{	
		var column = e.memo;	
		if (column.ctlsfc.previousSibling)
		{
		
			$("ColHldr").insertBefore(column.ctlsfc, column.ctlsfc.previousSibling);	
			
			this.UpdateColumns({ column: column } );
		}
		
	},
	
//Move column to the right, 
//takes a column object as param	
ColumnMoveRight: function(e)
	{
		var column = e.memo;	
		if (column.ctlsfc.nextSibling)
		{
			
			$("ColHldr").insertBefore(column.ctlsfc.nextSibling, column.ctlsfc);	
			
			this.UpdateColumns({ column: column } );
		}
	},
	
//close a column,
//takes a column object as param	
ColumnClose: function(e)
	{
		var column = e.memo;	
		
		this.ccCtl.AddColumn(column);
		
		//update scriptaculous
		//sortables object
		this.UpdateSortables();
		
		mSpaceApplication.Resize(false);
		
		//update columns data
		this.UpdateColumns();
	},	
	
//open a column,
//takes a column object as param	
ColumnOpen: function(e)
	{
		var column = e.memo;	
		column.isopen = true;
		
		column.Prepend($("ColHldr"));
		
		//update scriptaculous
		//sortables object		
		this.UpdateSortables();
		//update closed columns scriptaculous
		//sortables object		
		this.ccCtl.UpdateSortables();
			
		mSpaceApplication.Resize(false);
		
		//update columns data
		this.UpdateColumns({ column: column } );
		
	},	

//Load columns
ColumnLoad: function(e)
	{
		var column = e.memo;	
		//update columns data call
		this.UpdateColumns({ column: column } );
	},
	
UpdateColumns: function(e)
	{		
		//query the server
		this.QueryServer(e);
	},
	
//Function to do a slicegetitems call
//to the mSpace server, and get the 
//contents of the column, based on the
//current slice and any click actions
QueryServer: function(e)
	{
			var eventParams;
			
			if(e)
				eventParams = e.memo;	
			
			var getColumnsUrl = window.mSpaceApplication.GetServerUrl("slicegetitems");
			
			var sliceUrl = "";
			
			if ((eventParams) && (eventParams.column))
			{
				sliceUrl += "&columnclicked=" + URLEncode(eventParams.column.uri);
			}
			
			if ((eventParams) && (eventParams.listitem))
			{
				sliceUrl += "&itemclicked=" + URLEncode(eventParams.listitem.uri);
			}	
			
			var histStr = ""
			
			if ((eventParams) && (eventParams.sliceString))
			{
				sliceUrl += eventParams.sliceString;
				histStr = eventParams.sliceString;
			}	
			else
			{			
				sliceUrl += this.GetColumnParamString();	
				histStr = this.GetColumnParamString();
			}
			
			sliceUrl += this.GetColumnFilterParamString();
						
			if (this.colHistURL!=histStr)
			{
				this.colHistURL = histStr;
				this.LoadColumnsFromUrl(getColumnsUrl += sliceUrl);
			}
		
		
		
		//this.LoadColumnContentsData();
	},
	
//Function to take column slice get items url, 
//and load the contents via AJAX
LoadColumnsFromUrl: function(url)
	{
			//Set columns as loading
			for (var i=0;i<$("ColHldr").childNodes.length;i++)
			{
				var childNode = $("ColHldr").childNodes[i];
				if (childNode)
					this.allColsMap[childNode.id].SetLoading(true);
			}
			
			var thisObj = this;
			
			if (this.ajaxRequest!=null)
				this.ajaxRequest.transport.abort();
			
			//prototype AJAX call
			this.ajaxRequest = new Ajax.Request(url, {
			  requestType: 'get',			  
			  onSuccess: function(transport) 
			  {			
			  	//load returned data
			  	thisObj.LoadColumnContentsData(eval(transport.responseText));
			  	mSpaceApplication.Resize();
					thisObj.ajaxRequest = null;
			  },
			  onFailure: function(transport) {
				  alert(transport);
				  thisObj.ajaxRequest = null;
			  }
			});				
			
	},

//Take returned JSON data and update columns
LoadColumnContentsData: function(colDeets)
	{
		if (colDeets==null)
		{
			//alert("Invalid JSON Returned From Server");

			//change loading status of all columns
			for (var i=0;i<this.ColHldr.childNodes.length;i++)
			{
				var childNode = this.ColHldr.childNodes[i];
				if (childNode)
				{
					this.allColsMap[childNode.id].SetLoading(false);
				}
			}

			return;
		}
		
		var t = this;
		
		//Loop through the columns
		for (var i = 0;i<colDeets.length;i++)
		{
			var colNewDataObject = colDeets[i];
			if (colNewDataObject.uri)
			{
				var colObject = this.GetColumn(colNewDataObject.uri);
				if (colObject!=null)
				{
					//update the column data
					colObject.UpdateColumnData(colNewDataObject, (!this.firstDataLoad));
				}
			}
		}
		
		
		//update history
		this.histStr = this.GetColumnParamString();
		
			//change loading status of all columns
			for (var i=0;i< this.ColHldr.childNodes.length;i++)
			{
				var childNode = this.ColHldr.childNodes[i];
				if (childNode)
				{
					this.allColsMap[childNode.id].SetLoading(false);
				}
			}		
		
		//fire a change event
		document.fire('ColumnBrowser:ColumnChange', this.openCols);
		
		
		//Update the breadcrumb bar
		$("BrdCrmb").innerHTML = "";		
		//$("BrdCrmb").appendChild(this.GetSliceString());
		var BrdCrmb = $("BrdCrmb");
		this.GetSliceString(BrdCrmb);
		
		if (!this.firstDataLoad)
		{
			this.firstDataLoad = true;
		}
	},
	

	

//change the column layout from a history object
LoadFirstHistory: function(historyStack)
	{
		if (historyStack['ColumnBrowser.History'])
		{
			
			var historyString = historyStack['ColumnBrowser.History'];

			this.ClearColumns();
			var historyArray = new Array();
			eval("historyArray = " + historyString + ";");
			for (var i=0; i<historyArray.length;i++)
			{
				var columnDetails = historyArray[i];
				
				var column = this.GetColumn(columnDetails.uri);
				column.ReplaceItems(columnDetails);
				
				this.ccCtl.RemoveColumn(column);
				
				this.openCols.push(column);
				column.ctlsfc.style.visibility = "hidden";
				c = column;
				c.Append($("ColHldr"));
				
			}
			
			mSpaceApplication.Resize(false);
			
			var newHistoryArray = new Array();
			for (var i=0;i<this.openCols.length;i++)
			{
				newHistoryArray.push(this.openCols[i].GetHistoryObject())
			}
			
			this.histArr = newHistoryArray;		
			//alert("5");
			var historyString = Ob2Str(this.histArr);				
				
			
			
		}		
	},

//Clear all columns
ClearColumns: function()
	{
	
		
		var tempArr = new Array();
		for (var i=0;i<$("ColHldr").childNodes.length;i++)
		{
			var childNode = $("ColHldr").childNodes[i];
			if (childNode)
				tempArr.push(this.allColsMap[childNode.id]);
		}
		
		for (var i=0;i<tempArr.length;i++)
		{
			var column = tempArr[i];
			
			$("ColHldr").removeChild(column.ctlsfc);
			
			this.ccCtl.AddColumn(column);
			
		}
		
		this.openCols = new Array();
		
	},
	
//Called when a column item is selected
SelectItem: function(e)
	{
		this.UpdateColumns(e);
	},
	
//called when an item is selected, with 
//a pre built slice string
SelectItemWithSlice: function(e)
	{
		this.UpdateColumns(e);
	},

//Called whan a column item is unselected
UnSelectItem: function(e)
	{
		this.UpdateColumns(e);
	},
//Called to unselect all items within a column
UnSelectAll: function(e)
{
		var eventParams = e.memo;
		for (var i=0;i<$("ColHldr").childNodes.length;i++)
		{
			var childNode = $("ColHldr").childNodes[i];
			
			var c = this.allColsMap[childNode.id];
			if(c == eventParams.column)
		{
			this.m_colToUpdate = c;
			break;
		}
	}
	this.UpdateColumns(eventParams);
},

//Show the A to Z popup at the location of the passed column
ShowListScrollPopup: function(e)
	{
		var eventParams = e.memo;
		
		if (this.tmoutID!=-1)
		{
			clearTimeout(this.tmoutID);
			this.tmoutID = -1;
		}
		
		// Find the absolute position from the top/left corner

		var ColContOffset = $("ColCont").cumulativeOffset();
		var LiOffset = $(eventParams.list.ctlsfc).cumulativeOffset();
		
		var AtoZLeft 	= LiOffset.left - ColContOffset.left 	+ eventParams.list.ctlsfc.offsetWidth/2;
		var AtoZTop 	= LiOffset.top 	- ColContOffset.top 	+ eventParams.list.ctlsfc.offsetHeight/2;
		
		$("AtoZ").innerHTML = eventParams.text;
		$("AtoZ").style.display = "";
		$("AtoZ").style.left = (AtoZLeft - $("ColCont").scrollLeft) + "px";
		$("AtoZ").style.top = (AtoZTop - $("ColCont").scrollTop) + "px";
		$("AtoZ").style.marginTop = -($("AtoZ").offsetHeight/2) + "px";
		$("AtoZ").style.marginLeft = -($("AtoZ").offsetWidth/2) + "px";
		
		var thisObj = this;
		this.tmoutID = setTimeout(function() { thisObj.HideListScrollPopup(); }, 1000);
	},
	
//Hide A to Z popup
HideListScrollPopup: function()
	{
		if (this.tmoutID!=-1)
		{
			clearTimeout(this.tmoutID);
			this.tmoutID = -1;
		}		
		
		$("AtoZ").innerHTML = "";
		$("AtoZ").style.display = "none";		
	},
	
//Initial Load columns call, with no history
//or current slice
LoadColumns: function(historyObject)
	{
			if (this.colsLoaded)
				return;
		
			this.colsLoaded = true;
			var thisObj = this;
			
			$("ColHldr").hide();
			$("ColLdng").show();
			
			var thisObj = this;
			
			if (this.ajaxRequest!=null)
				this.ajaxRequest.transport.abort();
			
			//AJAX Call
			this.ajaxRequest = new Ajax.Request(window.mSpaceApplication.GetServerUrl("slicegetitems"), {
			  requestType: 'get',
			  onSuccess: function(transport) 
			  {			
			  	thisObj.InitialLoadColumnData(eval(transport.responseText), historyObject);
					thisObj.ajaxRequest = null;
			  },
			  onFailure: function(transport) {
				  alert(transport);
				  thisObj.ajaxRequest = null;
			  }
			});				
	
	},
	
//Handle response from the server for intial load
InitialLoadColumnData: function(columns, historyObject)
	{
		
		if (columns==null)
		{
			alert("Error loading columns! JSON Data is null");
			return;
		}
		
		// Remove the Element from the DOM before processing
		this.ColHldr.remove();
		
		for (var i=0; i<columns.length; i++)
		{
			if ((columns[i].ctp==0) || (columns[i].ctp==1))
			{
				this.AddColumn(columns[i], (columns[i].isDefault), i);
			}
		}
		
		// Put the Element back onto the DOM in the correct place
		this.ColCont.insert({top: this.ColHldr});
		
		$("ColLdng").hide();
		$("ColHldr").show();

		for (var i=0;i<this.ColHldr.childNodes.length;i++)
		{
			var childNode = this.ColHldr.childNodes[i];
			if (childNode)
				this.allColsMap[childNode.id].isopen = true;
		}	
		
		
		if (historyObject)
		{
			this.HistoryChange(historyObject);
		}
		
		//Update the column sortables object
		this.UpdateSortables();
		
		//Notify other objects of column load, as the call may 
		//have not come from the column browser
		document.fire('AdvancedSearch:Populate', this.openCols);	
		
		if (this.initEvtCall)
		{
			document.fire(this.initEvtCall, this.initEvtParams);
			this.initEvtCall = null;
			this.initEvtParams = null;
		}
		
		document.fire('ColumnBrowser:ColumnsLoaded', columns);
		
		mSpaceApplication.Resize(false);
	},

//Function to delete any existing Sortables object
//and create a new one, that handles the dragging
//and dropping between the column browser and the
//closed column browser
UpdateSortables: function()
	{
		if (this.sortables!=null)
		{
			Sortables.destroy("ColHldr");
		}	
		var thisObj = this;
		
		var opts = new Object();
		opts.overlap 			= "horizontal";
		opts.constraint 	= "horizontal";
		opts.handle 			= "ColHrdLbl";
		opts.containment 	= ["ColHldr", "CCCCont"];
		opts.scroll 			= "ColCont";
		opts.dropOnEmpty 	= true;
		
		opts.onChange = function(element) {	
			if (element)			
			{
				thisObj.allColsMap[element.id].isopen = true;
				thisObj.allColsMap[element.id].SetHeaderLabelWidth();
			}
			thisObj.Resize();
			thisObj.currentDragCol = element;			
		}
		
		opts.onUpdate = function(cont) {
			thisObj.UpdateColumnOrder();			
		}
		
		//Create a scriptaculous sortables object
		this.sortables = Sortable.create("ColHldr", opts);
	},
	
//update the columns if the order of columns is changed
//from the sortables on change event.
UpdateColumnOrder: function(id)
	{
		if (this.currentDragCol!=null)
		{
			this.UpdateColumns({ column: this.allColsMap[this.currentDragCol.id] } );			
			this.UpdateSortables();
		}
		this.currentDragCol = null;
	},
	
//Get a column based on uri
GetColumn: function(uri)
	{
		return this.allColsLookup[uri];
		
		/*
		for (var i=0;i<this.allCols.length;i++)
		{
			if (this.allCols[i].uri==uri)
			{
				return this.allCols[i];
			}
		}
		return null;
		*/
	},
	
//Update the history string of the column browser
//MAY BE DEPRICATED
UpdateHistory: function(historyStack)
	{
		if (historyStack['ColumnBrowser.History'])
		{
			
			var historyString = historyStack['ColumnBrowser.History'];
			
			if (historyString!=this.histStr)
			{
				document.fire('mSpaceHistory:AddHistory', { name: 'ColumnBrowser.History', history: this.histStr });
			}
		}
		else if (this.histStr!="")
		{
			document.fire('mSpaceHistory:AddHistory', { name: 'ColumnBrowser.History', history: this.histStr });
		}
	},
	
//Clear all  selections in a column
ClearColumnSelections: function(column)
	{
		//Loop through all the open columns, and clear selections up till the passed columns
		if (column!=null)
		{
			for (var i=0;i<this.allCols.length;i++)
			{
				if (this.allCols[i]!=column)
				{
					this.allCols[i].ClearSelections();
				}
				else
				{
					break;
				}
			}			
		}
	},

//Clear all columns and all selections
ClearAllColumnSelections: function()
	{
		for (var i=0;i<$("ColHldr").childNodes.length;i++)
		{
			var childNode = $("ColHldr").childNodes[i];
			var c = this.allColsMap[childNode.id];
		
			c.list.m_selectedItems = new Object();
			c.list.UpdateListItems();
			c.m_allBtn.style.display='none';

		}

		document.fire('Column:UnSelectAll', {column: this.openCols[0]});
	},
	
	
//Add colummn to the slice without re-loading.. 
//used when an external click needs to open a column
QueueColumn: function(e)
	{
		var eventParams = e.memo;
		
		if (!eventParams.column)
		{
			return;
		}
			
		var column = eventParams.column;
		
		
		var newColsArray = new Array();
		
		newColsArray.push(column);
		
		for (var i=0;i<this.openCols.length;i++)
		{
			newColsArray.push(this.openCols[i]);
		}
		
		this.openCols = newColsArray;
		
		if (this.openCols.length>1)
		{
			column.Prepend($("ColHldr"));
		}
		else
		{
			column.Append($("ColHldr"));
		}
	
		mSpaceApplication.Resize(false);
		this.Resize(false);
	
	},
	
//Get a breadcrumb dom element for this column, showing
//selections and highlights etc
GetSliceString: function(BreadCrumb)
	{
		var returnDiv = Builder.node('div', {className: "float"});
		BreadCrumb.appendChild(returnDiv);
		
		returnDiv.appendChild(this.m_loaddefaultSliceBtn);
		returnDiv.appendChild(this.m_resetSliceBtn);
		
		
		for (var i=0;i<this.ColHldr.childNodes.length;i++)
		{
			var childNode = this.ColHldr.childNodes[i];
			
			var col = this.allColsMap[childNode.id];
			var colDiv = col.GetSliceString(BreadCrumb);
			
			if ((colDiv!=null))
			{
				var spacer = Builder.node('div', {className: "float"});
				spacer.innerHTML = " / ";
				returnDiv.appendChild(spacer);
			}
			
			returnDiv.appendChild(colDiv);
		}		
		
		//return returnDiv;
	},
	
//Handle an item click event from external controls
ExternalItemClick: function(e)
	{
		var eventParams = e.memo;
		
		if (!this.started)
		{
			this.initEvtCall = "Item.MouseClick";
			this.initEvtParams = eventParams;

			this.Start();			
		}
	},
	
//Open the closed column control
OpenClosedCols: function()
	{
		if (this.ccCtl!=null)
		{
				this.ccCtl.Open();
		}
	},
	
//Load the partial list items for a long list
//based column, that has been scrolled to a 
//section that has no loaded items
LoadPartialColumnData: function(e)
	{
			var eventParams = e.memo;
			if (!this.colsLoaded)
				return;
		
			var thisObj = this;
			
			if (eventParams.col)
			{
				eventParams.col.SetLoading(true, true);
			}
			
			if (this.ajaxRequest!=null)
				this.ajaxRequest.transport.abort();
				
			var start = eventParams.start - 50;
			if (start<0)
			{
				start = 0;
			}
			var url = window.mSpaceApplication.GetServerUrl("slicegetitems") + "columnrestrict=" + URLEncode(eventParams.col.uri) + "&start=" + start + "&itemscount=100" ;
			
			url += this.GetColumnParamString();
			
			//get the filter text for the partial column update in case
			//this is a server side text filter request
			url += eventParams.col.GetFilterUrlText();				
			
			this.ajaxRequest = new Ajax.Request(url, {
			  requestType: 'get',			  
			  onSuccess: function(transport) 
			  {			
			  	thisObj.PartialColumnDataResults(eval(transport.responseText), eventParams.clear);
				thisObj.ajaxRequest = null;
			  },
			  onFailure: function(transport) {
				  alert(transport);
				  thisObj.ajaxRequest = null;
			  }
			});					
				
	},
	
//Handle data results from a partial columns
//load
PartialColumnDataResults: function(columns, clear)
	{
		
		if (columns==null)
		{
			//alert("Error loading partial column data! JSON Data is null");
			
			//change loading status of all columns
			for (var i=0;i<$("ColHldr").childNodes.length;i++)
			{
				var childNode = $("ColHldr").childNodes[i];
				if (childNode)
				{
					this.allColsMap[childNode.id].SetLoading(false);
				}
			}
			
			return;
		}		
		
		for (var i=0; i<columns.length; i++)
		{
			var col = this.GetColumn(columns[i].uri);
			if (col!=null)
			{
				col.SetLoading(false, false);
				col.LoadVisibleListItems(columns[i], clear);
			}
		}
		

	},

//Get a param string for the current slice
//used in server url calls.. ie col=col:uri&col=val:selectionuri etc
GetColumnParamString: function(p)
	{
		
		var selItem = false;
		if (p && p.uri && p.coluri)
		{
			selItem = true;
		}
		
		var retString = "";
		for (var i=0;i<this.ColHldr.childNodes.length;i++)
		{
			var childNode = this.ColHldr.childNodes[i];			
			
			var col = this.allColsMap[childNode.id];
			
			var colStr = "&col[]=col:" + URLEncode(col.uri);
			
			if (selItem && (col.uri==p.coluri))
			{
				retString += colStr + "&col[]=val:" + URLEncode(p.uri);
			}
			else
			{
				var selArr = col.GetSelectedItems();
				
				var count = 0;
				for (var li in selArr)
				{
					if (selArr[li].uri)
					{
						retString += colStr + "&col[]=val:" + URLEncode(selArr[li].uri);
						count ++;					
					}
				}
				
				if (count==0)
				{
					retString += colStr + "&col[]=val:";
				}
			}
		}		
		return retString;
	},
	
//Get a param string that includes the server side filter params for columns
GetColumnFilterParamString: function()
	{
		var retString = "";
		for (var i=0;i<$("ColHldr").childNodes.length;i++)
		{
			var childNode = $("ColHldr").childNodes[i];
				
			var col = this.allColsMap[childNode.id];
			retString += col.GetFilterUrlText();
		}		
		return retString;
	},	
	
	
//Load data from a history change event
HistoryChange: function(e)
	{
		var histObj = null;
		
		if(e)
		{
			if(e.memo)
				histObj = e.memo;
			else
				histObj = e;
		}
		
		if (histObj["Column.SelectItemHistory"])
		{
			var historyUrl = histObj["Column.SelectItemHistory"];
			this.LoadFromHistory(historyUrl);
		}		
	},

//Load from a history object
LoadFromHistory: function(historyUrl)
	{		
		this.LoadColumnsFromUrl(window.mSpaceApplication.GetServerUrl("slicegetitems") + "&" + historyUrl);		
	},
	
//Load columns in the background, without
//opening the browser.
//TODO: remove use of the data controller
//		should be able to do this on own
LoadColumnsInBackground: function()
	{
		if (this.colsLoaded)
			return;
			
		var getColumnsUrl = window.mSpaceApplication.GetServerUrl("slicegetitems") + "&itemscount=-1";
		document.fire('DataController:Request', { 'sender' : this, 'id' : 'loadcolsbg', 'type' : "GET",'url' : getColumnsUrl });
	},
	
//Handle data request response
HandleResponse: function(id, data)
	{
		if (id=='loadcolsbg')
		{
			
			var columns = new Array();
			columns = eval(data);
		
			
			document.fire('ColumnBrowser:ColumnsLoaded', columns);
			
		}
	},
	
//reset the selections in each column
ResetSlice: function()
	{
		for (var i=0;i<$("ColHldr").childNodes.length;i++)
		{
			var childNode = $("ColHldr").childNodes[i];
			var c = this.allColsMap[childNode.id];
		
			c.Reset();
			
			
		}
		
		this.UpdateSortables();
		this.UpdateColumns();
	},

//load the default slice
LoadDefaultSlice: function()
	{	
		for (var i=0;i<this.openCols.length;i++)
		{
			var c = this.openCols[i];
			c.Reset();
			
			this.ccCtl.AddColumn(c);
			
			
		}
		
		this.openCols = new Array();
		
		for (var i=0;i<this.defSlice.length;i++)
		{
			var c = this.defSlice[i];			
			c.Reset();
			
			this.openCols.push(c);
			c.Append($("ColHldr"));		
			c.isopen = true;
			
		}		

		mSpaceApplication.Resize(false);
		
		this.UpdateSortables();
		this.UpdateColumns();
	}
	
	
}


