/**  
 * @fileoverview This file contains functions and variables related to panels.
 * @author Mark Hendrickson <mhendric@bowdoin.edu>
 * @version 1.0
 */

/**
 * Toggle the minimization of a panel.
 * @param {String} panel_name Panel name
 * @param {String} status Indicates whether to minimize or unminimize the panel ("N" or "max" for maximize, "Y" or "min" for minimize)
 * @param {Boolean} noreport Indicates whether not to report the panel minimization
 */
function togglePanelMin(panel_name,status,noreport)
{
	var panel_header_arrow = $('panel_header_arrow_'+panel_name);
	var panel_main = $('panel_main_'+panel_name);
	var minimized;

	if(status == 'max')
		status = 'N';
	else if(status == 'min')
		status = 'Y';

	if(status != 'N' && (status == 'Y' || panel_main.style.display == 'block' || !panel_main.style.display))
	{
		panel_header_arrow.style.backgroundImage = 'url('+theme_images_dir+theme_settings[panel_themes[panel_name]]["panel_header_arrow_right"]+')';
		panel_main.style.display = 'none';
		minimized = 'Y';
	}
	else
	{
		panel_header_arrow.style.backgroundImage = 'url('+theme_images_dir+theme_settings[panel_themes[panel_name]]["panel_header_arrow_down"]+')';
		panel_main.style.display = 'block';
		minimized = 'N';
	}
	
	if(username && !noreport)
	{
		if(panel_name.substring(0,8) == 'rss_feed')
		{
			var feed = panel_name.substring(9);
			panel_name = panel_name.substring(0,8);
		}
		else
			var feed = '';

		var ajax = initAjax();
		ajax.open('GET','scripts/report_panel_minimization.php?timeStamp='+new Date().getTime()+'&username='+username+'&minimized='+minimized+'&panel_name='+panel_name+'&feed='+feed,true);
		ajax.send(null);
	}

	if(!noreport)
		page_customized = true;
}

/**
 * Minimizes all panels on the page.
 */
function minPanels()
{
	var columns = new Array('c1','c2','c3');
	for(var i=0; i<columns.length; i++)
	{
		var column = $(columns[i]);
		var children = column.childNodes;
		for(var j=0; j<children.length; j++)
		{
			if(children[j].nodeType == 1 && children[j].className == 'panel' && children[j].id != 'panel_announcements')
				togglePanelMin(children[j].id.substring(6),'min');
		}
	}
}

/**
 * Maximizes all panels on the page.
 */
function maxPanels()
{
	var columns = new Array('c1','c2','c3');
	for(var i=0; i<columns.length; i++)
	{
		var column = $(columns[i]);
		var children = column.childNodes;
		for(var j=0; j<children.length; j++)
		{
			if(children[j].nodeType == 1 && children[j].className == 'panel' && children[j].id != 'panel_announcements')
				togglePanelMin(children[j].id.substring(6),'max');
		}
	}
}

// Resize panel content variables
var resizing_panel_content = false;
var resize_panel_content_panel_name;
var resize_panel_content_panel_section;
var resize_panel_content_id;
var resize_panel_content_initHeight;
var resize_panel_content_initY;
var resize_panel_content_padding;

/**
 * Resizes the height of a panel content element using input from cursor position.
 * Note: Triggered once when resize commenced. Then resizePanelContentListener() takes over.
 * @see #resizePanelContentListener
 * @param {Object} event Event object from which cursor coordinates will be grabbed.
 * @param {Integer} id ID of the panel content element
 * @param {String} panel Name of panel containing panel content element
 * @param {String} section Name of the panel section represented by panel content element
 * @param {Integer} padding Amount of bottom padding associated with panel content element
 */
function resizePanelContent(event,id,panel,section,padding)
{
	if(!event)
		var event = window.event;

	stopPropagation(event);
	
	if(!resizing_panel_content)
	{
		resizing_panel_content = true;

		var element = $(id);

		if(padding)
			resize_panel_content_padding = padding;
		else
			resize_panel_content_padding = 10;

		resize_panel_content_panel_name = panel;
		resize_panel_content_panel_section = section;
		resize_panel_content_id = id;
		resize_panel_content_initHeight = element.offsetHeight;
		resize_panel_content_initY = getEventPageY(event)+getEventLayerY(event);
		
		var body = document.getElementsByTagName('body')[0];
		body.onmousemove = resizePanelContentListener;
		body.onmouseup = resizePanelContentStop;
	}
}

/**
 * Resizes the height of a panel content element as mouse moves around page.
 * Note: Only functions once resizePanelContent() has initiated resizing.
 * @see #resizePanelContent
 * @param {Object} event Event object from which cursor coordinates will be grabbed.
 */
function resizePanelContentListener(event)
{
	if(!event)
		var event = window.event;

	var new_height = resize_panel_content_initHeight+getEventPageY(event)-resize_panel_content_initY;
	
	if(new_height < 25)
		new_height = 25;
	else if(new_height > 3000)
		new_height = 3000;

	var element = $(resize_panel_content_id);
	element.style.maxHeight = new_height+'px';
	element.style.height = new_height+'px';
}

/**
 * Stops the resize process of a panel content element's height.
 */
function resizePanelContentStop()
{
	if(resizing_panel_content)
	{
		var body = document.getElementsByTagName('body')[0];
		body.onmousemove = null;
		body.onmouseup = null;

		var height = $(resize_panel_content_id).offsetHeight-resize_panel_content_padding;

		if(username)
		{
			var ajax = initAjax();
			ajax.open('GET','scripts/report_panel_content_resize.php?timeStamp='+new Date().getTime()+'&username='+username+'&panel='+resize_panel_content_panel_name+'&section='+resize_panel_content_panel_section+'&height='+height,true);
			ajax.send(null);
		}

		resize_panel_content_panel_name = '';
		resize_panel_content_panel_section = '';
		resize_panel_content_id = '';
		resize_panel_content_initHeight = '';
		resize_panel_content_initY = '';
		resize_panel_content_padding = '';

		resizing_panel_content = false;
	}
}

var default_panel_content_scroll_max_height = 195;

/**
 * Resets the height of a panel content element to its default size.
 * @param {Object} event Event object
 * @param {Integer} id Panel content element ID
 * @param {String} section Panel section represented by the panel content element
 * @param {Boolean} scroll Indicates whether panel content element is scrollable
 */
function resetPanelContentHeight(event,id,panel,section,scroll)
{
	var element = $(id);
	element.style.height = 'auto';

	if(scroll)
		element.style.maxHeight = default_panel_content_scroll_max_height+'px';

	if(username)
	{
		var ajax = initAjax();
		ajax.open('GET','scripts/report_panel_content_reset_height.php?timeStamp='+new Date().getTime()+'&username='+username+'&panel='+panel+'&section='+section,true);
		ajax.send(null);
	}
}

/**
 * Clears the settings of all panel content elements in a particular panel.
 * Note: Height is currently the only setting possible for panel content elements
 * @param {String} panel Panel name
 */
function clearPanelContentSettings(panel)
{
	var ajax = initAjax();
	ajax.open('GET','scripts/clear_panel_content_settings.php?timeStamp='+new Date().getTime()+'&panel='+panel,true);
	ajax.send(null);
}

// Variables used in panel moving
var panel_lifted = false;
var lifted_panel_name;
var lifted_panel;
var lifted_panel_adjustX;
var lifted_panel_adjustY;
var layerX;
var layerY;
var last_underlying_column_id;
var last_underlying_panel_id;
var moving_panel = false;
var setting_panel_placeholder = false;

/**
 * Lift panel for drag and drop.
 * @param {String} panel_name Panel name
 * @param {Object} event Event object from which to grab page coordinates
 * @param {Integer} pageX Optional horizontal coordinate on page to put panel
 * @param {Integer} pageY Optional vertical coordinate on page to put panel
 * @param {Boolean} new_panel Indicates whether panel is being added to page
 * @param {String} routine Optional JavaScript routine to execute after panel lifted
 */
function liftPanel(panel_name,event,pageX,pageY,new_panel,routine)
{	
	if(!event && !(pageX || pageY))
		var event = window.event;

	// Check that there is no panel currently lifted and that mouse clicked on the right place
	if(event)
	{
		var target = getEventTarget(event);
		var target_class = target.className;
	}

	if(!panel_lifted && (new_panel || target_class == 'panel_header' || target_class == 'panel_header_menu_move' || sally == 3))
	{
		// Start lifting and turn off tooltips and blurbs
		panel_lifted = true;
		toggleBlurb(event,'off');
		toggleTooltip(event,'off');
		toggleThemePicker(current_theme_picker_panel,'off');
		
		if(event)
			stopPropagation(event);

		// Store information about panel and the cursor position
		lifted_panel_name = panel_name;
		if(event)
		{
			layerX = getEventLayerX(event);
			layerY = getEventLayerY(event);
		}
		else
		{
			layerX = 60;
			layerY = 12;
		}

		// Determine coordinate adjustments depending on where mouse clicked
		if(target_class == 'panel_header' || new_panel)
		{
			lifted_panel_adjustX = 0;
			lifted_panel_adjustY = 0;
		}
		else
		{
			lifted_panel_adjustX = 193;
			lifted_panel_adjustY = 3;
		}

		if(event)
		{
			var pageX = getEventPageX(event);
			var pageY = getEventPageY(event);
		}

		// Cover page with transparent div for cursor glitch protection
		togglePageCover('on');
	
		// Absolutely position panel in body and make it translucent, and insert placeholder
		var panel = $('panel_'+panel_name);
		lifted_panel = panel;

		var column = panel.parentNode;
		var panel_placeholder = document.createElement('div');
		panel_placeholder.setAttribute('id','panel_placeholder');
		panel_placeholder.style.height = (panel.offsetHeight-2)+'px';
		column.insertBefore(panel_placeholder, panel);
		
		panel.style.position = 'absolute';
		panel.style.zIndex = 25;
		panel.style.left = (pageX-layerX-lifted_panel_adjustX)+'px';
		panel.style.top = (pageY-layerY-lifted_panel_adjustY)+'px';
		panel.style.opacity = 0.85;
		//panel.style.filter = 'alpha(opacity=100)';

		// IE transparency fix for header menu
		var panel_header = $('panel_header_'+panel_name);
		panel_header.style.filter = 'alpha(opacity=100)';

		// Tell body to watch for mouse movements and mouse up
		var body = document.getElementsByTagName('body')[0];
		body.insertBefore(panel,body.firstChild);
		body.onmousemove = movePanel;
		body.onmouseup = dropPanel;

		if(routine)
			eval(routine);
	}
}

/**
 * Move panel during drag and drop.
 * @param {Object} event Event object from which to grab page coordinates
 */
function movePanel(event)
{
	if(!event)
		var event = window.event;
	
	if(!moving_panel)
	{
		moving_panel = true;

		// Set new coordinates for panel
		lifted_panel.style.left = (getEventPageX(event)-layerX-lifted_panel_adjustX)+'px';
		lifted_panel.style.top = (getEventPageY(event)-layerY-lifted_panel_adjustY)+'px';

		// Calculate x and y for setPanelPlaceholder
		var x = getEventPageX(event);
		var y = getEventPageY(event);

		// Move panel placeholder if necessary
		setPanelPlaceholder(x,y,event);
		moving_panel = false;
	}
}

/**
 * Determine where panel placeholder should be during drag and drop and put it there.
 * @param {Integer} x Horizontal coordinate of cursor
 * @param {Integer} y Vertical coordinate of cursor
 * @param {Object} event Event object from which to grab cursor coordinates
 */
function setPanelPlaceholder(x,y,event)
{
	if(!event)
		var event = window.event;

	var panel_placeholder = $('panel_placeholder');

	// Check to ensure that process is not already underway
	if(!setting_panel_placeholder)
	{
		// Start process
		setting_panel_placeholder = true;

		// Determine cursor coordinates
		if((!x || !y) && event)
		{
			x = getEventPageX(event);
			y = getEventPageY(event);
		}

		// Check for whether cursor is over panel placeholder
		if(isWithin(x,y,panel_placeholder,false))
		{
			// turn off tooltip warning that panel cannot be dropped here (if necessary)
			toggleTooltip(event,'off');
			
			setting_panel_placeholder = false;
			return;
		}

		// Check for whether cursor is over the last panel it was over
		if(last_underlying_panel_id)
		{
			var last_underlying_panel = $(last_underlying_panel_id);
			var hemisphere = isWithin(x,y,last_underlying_panel,true);
		}

		// If so, place panel appropriately
		if(hemisphere)
		{
			// turn off tooltip warning that panel cannot be dropped here (if necessary)
			if(last_underlying_panel.id != 'panel_announcements')
				toggleTooltip(event,'off');

			var column = last_underlying_panel.parentNode;

			if(hemisphere == 'upper' && (last_underlying_panel.id != 'panel_announcements' || lifted_panel_name == 'links'))
			{
				if(last_underlying_panel.previousSibling != panel_placeholder)
					column.insertBefore(panel_placeholder,last_underlying_panel);
			}
			else
			{
				if(hemisphere == 'upper')
					toggleTooltip(event,'on','Sorry, this panel cannot be placed above the announcements.',true);
				
				if(last_underlying_panel.nextSibling && last_underlying_panel.nextSibling != panel_placeholder)
					column.insertBefore(panel_placeholder,last_underlying_panel.nextSibling);
				else if(!last_underlying_panel.nextSibling)
					column.appendChild(panel_placeholder);
			}

			setting_panel_placeholder = false;
			return;
		}
		// Otherwise, check for whether cursor is over the panels container
		else if(isWithin(x,y,$('panels_container'),false))
		{
			// Determine column checking order based on last column cursor was over
			if(last_underlying_column_id == 'c1' || !last_underlying_column_id)
				var columns = new Array('c1','c2','c3');
			else if(last_underlying_column_id == 'c2')
				var columns = new Array('c2','c1','c3');
			else if(last_underlying_column_id == 'c3')
				var columns = new Array('c3','c2','c1');

			// Check for whether cursor is over each column
			for(var j=0; j < columns.length; j++)
			{
				if(isWithin(x,y,$(columns[j]),false))
				{
					// Check for whether cursor is over each panel in this column
					var c = $(columns[j]);
					var children = c.childNodes;
					var panel_num = 0;

					for(i = 0; i < children.length; i++)
					{
						if(children[i].nodeType == 1 && children[i].className == 'panel')
						{	
							panel_num++;

							var hemisphere = isWithin(x,y,children[i],true);
							if(hemisphere)
							{	
								// do not allow the placeholder to move if cursor is over the links panel in the upper-left corner
								if(panel_num == 1 && columns[j] == 'c1' && children[i].id == 'panel_links')
								{
									toggleTooltip(event,'on','Sorry, this panel cannot be placed above the announcements.',true);
									setting_panel_placeholder = false;
									return;
								}
								else
									toggleTooltip(event,'off');

								if(hemisphere == 'upper' && (children[i].id != 'panel_announcements' || lifted_panel_name == 'links'))
								{
									if(children[i].previousSibling != panel_placeholder)
										c.insertBefore(panel_placeholder,children[i]);
								}
								else
								{
									if(hemisphere == 'upper')
										toggleTooltip(event,'on','Sorry, this panel cannot be placed above the announcements.',true);
									
									if(children[i].nextSibling && children[i].nextSibling != panel_placeholder)
										c.insertBefore(panel_placeholder,children[i].nextSibling);
									else if(!children[i].nextSibling)
										c.appendChild(panel_placeholder);
								}
								

								last_underlying_column_id = columns[j];
								last_underlying_panel_id = children[i].id;
								setting_panel_placeholder = false;
								return;
							}
						}
					}

					// Check for whether cursor is over the bottom of this column
					var lastChild = c.lastChild;
					
					if(lastChild)
					{
						while(lastChild && lastChild.nodeType != 1)
							lastChild = lastChild.previousSibling;

						if(!lastChild || (lastChild && y > (getY(lastChild)+lastChild.offsetHeight) && lastChild != panel_placeholder))
						{
							c.appendChild(panel_placeholder);

							last_underlying_column_id = columns[j];
							last_underlying_panel_id = '';
							setting_panel_placeholder = false;
							return;
						}
					}
					else
					{
						c.appendChild(panel_placeholder);

						last_underlying_column = columns[j];
						last_underlying_panel = '';
						setting_panel_placeholder = false;
						return;
					}

					last_underlying_column_id = columns[j];
				}
			}
		}
		else
		{
			last_underlying_column_id = '';
			last_underlying_panel_id = '';
		}

		setting_panel_placeholder = false;
	}
}

/**
 * Drop panel at end of drag and drop.
 */
function dropPanel()
{
	if(lifted_panel)
	{
		// turn off tooltip warning that panel cannot be dropped here (if necessary)
		toggleTooltip(null,'off');

		var body = document.getElementsByTagName('body')[0];
		var panel = $('panel_'+lifted_panel_name);
		var panel_placeholder = $('panel_placeholder');
		var column = panel_placeholder.parentNode;

		body.onmousemove = null;
		body.onmouseup = null;

		if(drift_panels)
			driftPanel();
		else
			dropPanel2();
	}
}

/**
 * Called exclusively by dropPanel() or driftPanelSub(); if panel drifting is disabled, or panel has finished drifting, just drop panel into its resting place.
 * @see #dropPanel
 * @see #driftPanelSub
 */
function dropPanel2()
{
	var body = document.getElementsByTagName('body')[0];
	var panel = $('panel_'+lifted_panel_name);
	var panel_placeholder = $('panel_placeholder');
	var column = panel_placeholder.parentNode;
	
	// Put panel back in column and revert its properties
	panel.style.position = 'relative';
	panel.style.zIndex = 1;
	panel.style.opacity = 1;
	panel.style.left = 0;
	panel.style.top = 0;
	//panel.style.filter = 'alpha(opacity=100)';

	// Swap panel for panel placeholder
	column.replaceChild(panel,panel_placeholder);

	// Get rid of page cover
	togglePageCover('off');

	// Reset general drag and drop variables
	panel_lifted = false;
	lifted_panel = '';
	lifted_panel_name = '';
	lifted_panel_adjustX = '';
	lifted_panel_adjustY = '';
	layerX = '';
	layerY = '';
	last_underlying_column_id = '';
	last_underlying_panel_id = '';
	moving_panel = false;
	setting_panel_placeholder = false;

	// Report panels to database
	reportPanels();

	panel_lifted = false;
	page_customized = true;
}

var drift_panels = false;

/**
 * Called exclusively by dropPanel(); if panel drifting is enabled, drift the panel to its resting place.
 * @see #dropPanel
 */
function driftPanel()
{
	var panel_placeholder = $('panel_placeholder');
	var targetX = getX(panel_placeholder);
	var targetY = getY(panel_placeholder);
	var currentX = getX(lifted_panel);
	var currentY = getY(lifted_panel);
	
	if(targetX != currentX || targetY != currentY)
		driftPanelSub(targetX,targetY);
}

/**
 * Called exclusively by driftPanel; does the work to drift panel into its resting place.
 * @see #dropPanel
 * @param {Integer} targetX Horizontal coordinate of panel's resting place
 * @param {Integer} targetY Vertical coordinate of panel's resting place
 */
function driftPanelSub(targetX,targetY)
{
	var currentX = getX(lifted_panel);
	var currentY = getY(lifted_panel);

	var offX = Math.abs(currentX-targetX);
	var offY = Math.abs(currentY-targetY);

	if(offX > 300 || offY > 300)
	{
		if(offX > offY)
			var factor = offX/20;
		else
			var factor = offY/20;
	}
	else
		var factor = 15;

	if(offX > offY)
	{
		var steps = offX/factor;
		var moveX = factor;
		var moveY = offY/steps;
	}
	else
	{
		var steps = offY/factor;
		var moveY = factor;
		var moveX = offX/steps;
	}
	
	if(moveX > offX)
		var moveX = offX;

	if(moveY > offY)
		var moveY = offY;
	
	if(targetX > currentX)
		lifted_panel.style.left = (currentX + moveX)+'px';
	else if(targetX < currentX)
		lifted_panel.style.left = (currentX - moveX)+'px';

	if(targetY > currentY)
		lifted_panel.style.top = (currentY + moveY)+'px';
	else if(targetY < currentY)
		lifted_panel.style.top = (currentY - moveY)+'px';

	if(targetX != currentX || targetY != currentY)
		setTimeout('driftPanelSub('+targetX+','+targetY+')',1);
	else
		dropPanel2();
}

/**
 * Closes panel.
 * @param {String} panel_name Panel name
 * @param {Boolean} noconfirm Indicates whether not to ask for confirmation from user
 * @param {Boolean} report Indicates whether to report closing of panel
 * @param {String} routine Optional JavaScript routine to evaluate after panel has been closed
 */
function closePanel(panel_name,noconfirm,report,routine)
{
	// verify that user does indeed want to close the panel
	var close;
	if(!noconfirm)
		close = confirm('Are you sure you want to close this panel?');
	else
		close = true;

	if(close)
	{
		// run cleanup routine if appropriate
		if(routine)
			eval(routine);

		// clear memory of panel section and theme
		current_panel_sections[panel_name] = '';
		panel_themes[panel_name] = '';
		
		var panel = $('panel_'+panel_name);

		// remove panel from column
		var column = panel.parentNode;
		column.removeChild(panel);

		// hide tooltip
		toggleTooltip(false,'off');

		// reactivate add panel link
		toggleAddPanelLink(panel_name,'on');

		// delete rss feed if appropriate
		if(panel_name.substring(0,8) == 'rss_feed' && !noconfirm)
		{
			var ajax = initAjax();
			ajax.open('GET','scripts/delete_rss_feed.php?feed='+panel_name.substring(9),true);
			ajax.send(null);
		}

		// report panels
		if(report)
		{
			clearPanelContentSettings(panel_name);
			reportPanels();
		}

		page_customized = true;
	}
}

var panels_loading = 0;
var loading_panels_signals = new Array();
var loading_panels_signals_marker = 0;

/**
 * Loads panel into gateway.
 * @param {String} panel_name Panel name
 * @param {Integer} column Column to load panel into
 * @param {Boolean} minimized Indicates whether panel should be minimized
 * @param {Integer} feed If a panel for an RSS feed, the ID of that feed
 * @param {Object} event Event object
 * @param {Boolean} selected Indicates whether panel has just been selected, or added to page
 * @param {Boolean} report Indicates whether to report loading of panel
 */
function loadPanel(panel_name,column,minimized,feed,event,selected,report)
{
	if(!event)
		var event = window.event;
	
	// check for panel's existence before proceeding
	if(!$('panel_'+panel_name))
	{
		// indicate load initiation
		panels_loading++;
		indicateLoad('start');
		
		// deactivate add panel link
		toggleAddPanelLink(panel_name,'off');

		var c = $(column);
		var placeholder = document.createElement('div');
		
		if(selected && c.hasChildNodes())
			c.insertBefore(placeholder,c.firstChild)
		else
			c.appendChild(placeholder);

		if(selected && event)
		{
			var x = getEventPageX(event);
			var y = getEventPageY(event);
		}

		loading_panels_signals_marker++;
		var loading_panels_signals_index = loading_panels_signals_marker;
		loading_panels_signals[loading_panels_signals_index] = true;

		var ajax = initAjax();
		ajax.open('GET','panel_'+panel_name+'.php?timeStamp='+new Date().getTime()+'&content_type=xml&feed='+feed,true);
		ajax.onreadystatechange = function() { loadPanelProcess(panel_name,column,minimized,feed,x,y,selected,report,placeholder,ajax,loading_panels_signals_index) };
		ajax.send(null);
	}
}

/**
 * Called exclusively by loadPanel(); continues the operations of that function.
 * @see #loadPanel
 * @param {String} panel_name Panel name
 * @param {Integer} column Column to load panel into
 * @param {Boolean} minimized Indicates whether panel should be minimized
 * @param {Integer} feed If a panel for an RSS feed, the ID of that feed
 * @param {Integer} x Horizontal coordinate on page to load panel
 * @param {Integer} y Vertical coordinate on page to load panel
 * @param {Boolean} selected Indicates whether panel has just been selected, or added to page
 * @param {Boolean} report Indicates whether to report loading of panel
 * @param {Object} placeholder Element of panel placeholder
 * @param {Object} ajax Ajax element
 * @param {Integer} loading_panels_signals_index Array index meant to keep track of which panel is loading (can't really remember why I have this...must serve a purpose)
 */
function loadPanelProcess(panel_name,column,minimized,feed,x,y,selected,report,placeholder,ajax,loading_panels_signals_index)
{
	if(ajax.readyState == 4)
	{
		if(ajax.status == 200 && loading_panels_signals[loading_panels_signals_index])
		{
			var xml = ajax.responseXML;
			var html = xml.getElementsByTagName('html')[0];
			var panel = firstElement(html);

			// insert panel into column
			var c = $(column);
			appendNodeBefore(panel,c,placeholder);
			c.removeChild(placeholder);
			
			// if rss feed, specify in panel name
			if(feed && panel_name == 'rss_feed')
				panel_name = panel_name+'_'+feed;
			
			// set panel section if appropriate
			var section = xml.getElementsByTagName('panel')[0].getAttribute('section');
			if(section)
				selectSection(section,panel_name,true);
			
			// set panel theme if appropriate
			var theme = xml.getElementsByTagName('panel')[0].getAttribute('theme');
			setPanelTheme(panel_name,theme);

			// set minimization <---- change way processed
			if(minimized)
				togglePanelMin(panel_name,'min');

			// run initialization routine if appropriate
			var routine = xml.getElementsByTagName('panel')[0].getAttribute('routine');
			if(routine)
				eval(routine);

			// lift panel if it was selected
			if(selected && !(x == 0 && y == 0))
				liftPanel(panel_name,null,x,y,true);
		}

		// indicate finished load
		panels_loading--;
		indicateLoad('finish');

		// report panels if appropriate
		if(panels_loading == 0 && report)
			reportPanels();
	}
}

/**
 * Reloads panels on the page by removing all of them and reloading
 * @param {Boolean} report Indicates whether to report panel reload
 */
function loadPanels(report)
{
	// stop any panel loading and remove existing panels
	stopLoadingPanels();
	removePanels(false);

	var ajax = initAjax();
	ajax.open('GET','scripts/load_panels.php?timeStamp='+new Date().getTime()+'&username='+username,true);
	ajax.onreadystatechange = function() { loadPanelsProcess(ajax,report) };
	ajax.send(null);
}

/**
 * Called exclusively by loadPanels(); continues the operations of that function by adding panels to gateway
 * @param {Object} ajax Ajax object
 * @param {Boolean} report Indicates whether to report panel reload
 */
function loadPanelsProcess(ajax,report)
{
	if(ajax.readyState == 4)
	{
		if(ajax.status == 200)
		{
			if(report != true)
				report = false;

			var xml = ajax.responseXML;
			var panels = xml.getElementsByTagName('panel');

			if(panels.length)
			{
				var minimized;

				for(var i=0; i<panels.length; i++)
				{
					if(panels[i].getAttribute('minimized') == 'Y')
						minimized = true;
					else
						minimized = false;

					loadPanel(panels[i].firstChild.nodeValue,'c'+panels[i].getAttribute('col'),minimized,panels[i].getAttribute('feed'),null,null,report);
				}
			}
			else
				loadDefaultPanels();
		}
	}
}

/**
 * Loads all the default panels onto the page.
 * Note: This function must be tweaked in addition to the index.php file to change which panels are default.
 */
function loadDefaultPanels()
{
	loadPanel('links','c1',null,false,null,false,true);
	loadPanel('announcements','c1',null,false,null,false,true);
	loadPanel('weather','c1',null,false,null,false,true);
	loadPanel('webcams','c1',null,false,null,false,true);
	loadPanel('student_profile','c1',null,false,null,false,true);
	loadPanel('travel','c1',null,false,null,false,true);

	loadPanel('calendars','c2',null,false,null,false,true);
	loadPanel('news','c2',null,false,null,false,true);
	loadPanel('dining','c2',null,false,null,false,true);

	loadPanel('search','c3',null,false,null,false,true);

	if(username)
		loadPanel('student_digest','c3',null,false,null,false,true);
	else
		loadPanel('snapshots','c3',null,false,null,false,true);

	loadPanel('stories','c3',null,false,null,false,true);
	loadPanel('library','c3',null,false,null,false,true);
	loadPanel('athletics','c3',null,false,null,false,true);
}

/**
 * Report all panels to save configuration for user.
 */
function reportPanels()
{ 
	if(username)
	{
		var k;
		var children;
		var panel_name;
		var minimized;
		var feed;
		var theme;
		var section;
		
		// Produce XML with information about panels
		var xml = '<panels>';
		for(var j=1; j <= 3; j++)
		{
			children = $('c'+j).childNodes;
			k = 0;
			
			for(var i=0; i < children.length; i++)
			{
				if(children[i].nodeType == 1 && children[i].className == 'panel')
				{ 
					k++; 
					
					// determine panel name
					panel_name = children[i].id.substring(6); 
					
					// determine minimization
					if($('panel_main_'+panel_name).style.display != 'none')
						minimized = 'N';
					else
						minimized = 'Y';

					// determine theme
					if(panel_themes[panel_name] && panel_themes[panel_name] != 'undefined')
						theme = panel_themes[panel_name];
					else
						theme = '';

					// determine section
					if(current_panel_sections[panel_name])
						section = current_panel_sections[panel_name];
					else
						section = '';

					// determine rss feed
					if(panel_name.substring(0,8) == 'rss_feed')
					{
						feed = panel_name.substring(9);
						panel_name = panel_name.substring(0,8);
					}
					else
						feed = '';
					
					xml += '<panel col="'+j+'" place="'+k+'" minimized="'+minimized+'" feed="'+feed+'" theme="'+theme+'" section="'+section+'">'+panel_name+'</panel>';
				}
			}
		}
		xml += '</panels>';

		var ajax = initAjax();
		ajax.open('POST','scripts/report_panels.php?timeStamp='+new Date().getTime()+'&username='+username,true);
		ajax.setRequestHeader("Content-Type","text/xml;");
		ajax.send(xml);
	}
}

/**
 * Reload all default panels onto the page by clearing existing panels first.
 */
function restorePanels()
{
	stopLoadingPanels();
	removePanels(false);
	loadDefaultPanels();
}

/**
 * Stops panels from loading.
 * Note: I'm not sure this function actually works...is c actually a global array? hmmm, something to check into
 */
function stopLoadingPanels()
{
	c = new Array();
}

/**
 * Remove all panels from the page.
 * @param {Boolean} report Indicates whether to report the removal of all panels
 */
function removePanels(report)
{
	current_panel_sections = new Array();
	panel_themes = new Array();
	
	var children;
	var panel_name;

	for(var j=1; j <= 3; j++)
	{
		children = $('c'+j).childNodes;
		var i = 0;
		while(children.length)
		{
			if(children[i] && children[i].nodeType == 1 && children[i].className == 'panel')
			{
				panel_name = children[i].id.substring(6);

				if(report)
					closePanel(panel_name,true,true);
				else
					closePanel(panel_name,true,false);
				
				i = 0;
			}
			else if(i >= children.length)
				break;
			else
				i++;
		}
	}

	clearPanelContentSettings('all');
}

// panel sections array
var current_panel_sections = new Array();

/**
 * Select a section of a panel.
 * @param {String} new_section Section name
 * @param {String} panel_name Panel name
 * @param {Boolean} noreport Indicates whether not to report section selection
 */
function selectSection(new_section,panel_name,noreport)
{
	var old_section = current_panel_sections[panel_name];

	if(new_section && new_section != old_section)
	{
		var new_tab = $('panel_nav_tab_'+panel_name+'_'+new_section);
		var old_tab = $('panel_nav_tab_'+panel_name+'_'+old_section);

		var new_content = $('panel_content_'+panel_name+'_'+new_section);
		var old_content = $('panel_content_'+panel_name+'_'+old_section);

		if(old_tab)
			old_tab.className = 'panel_nav_tab';
		if(old_content)
			old_content.style.display = 'none';
		
		if(new_tab)
			new_tab.className = 'panel_nav_tab_selected';
		if(new_content)
			new_content.style.display = 'block';

		current_panel_sections[panel_name] = new_section;

		if(!noreport)
			reportSection(panel_name,new_section);
	}
}

/**
 * Report the current section of a panel
 * @param {String} panel_name Panel name
 * @param {String} section Section name
 */
function reportSection(panel_name,section)
{
	if(username)
	{
		var ajax = initAjax();
		ajax.open('GET','scripts/report_section.php?panel_name='+panel_name+'&section='+section,true);
		ajax.send(null);
	}
}

/**
 * Select a section of a panel using a pulldown menu.
 * @param {String} panel_name Panel name
 * @param {String} new_section Section name
 */
function selectSectionPulldown(panel_name,new_section)
{
	var select = $('panel_nav_pulldown_select_'+panel_name);
	var old_section = current_panel_sections[panel_name];

	if(!new_section)
		var new_section = select.value;

	if(new_section != old_section)
	{
		var new_content = $('panel_content_'+panel_name+'_'+new_section);
		var old_content = $('panel_content_'+panel_name+'_'+old_section);
		
		old_content.style.display = 'none';
		new_content.style.display = 'block';

		current_panel_sections[panel_name] = new_section

		reportSection(panel_name,new_section);
	}
}

var header_contents = new Array('panel_header_menu','panel_header_arrow','panel_header_menu_close','panel_header_menu_theme');
var shown_header_menu;

/**
 * Toggle the display of a panel header menu (with buttons such as "Close panel" and "Set panel theme").
 * @param {String} panel_name Panel name
 * @param {String} status Indicates whether to show or hide the header menu ("on" or "off")
 * @param {Object} event Event object
 */
function toggleHeaderMenu(panel_name,status,event)
{
	if(!event)
		var event = window.event;
	
	var target = getEventTarget(event);
	var related_target = getEventRelatedTarget(event);

	var panel_header_menu = $('panel_header_menu_'+panel_name);
	var target_id = target.id;
	if(related_target)
		var related_target_id = related_target.id;
	
	if(status == 'on' && (panel_header_menu.style.opacity != 1 || panel_header_menu.style.filter == 'opacity(alpha=100)') && ((target_id == 'panel_header_'+panel_name && !searchArray(related_target_id,header_contents,'_'+panel_name)) || (related_target_id != 'panel_header_'+panel_name && searchArray(target_id,header_contents,'_'+panel_name) && !searchArray(related_target_id,header_contents,'_'+panel_name))))
	{
		if(shown_header_menu && shown_header_menu != 'panel_header_menu_'+panel_name && $(shown_header_menu))
			fadeOut(shown_header_menu);
		fadeIn('panel_header_menu_'+panel_name);
		shown_header_menu = 'panel_header_menu_'+panel_name;
		
	}
	else if(status == 'off' && ((target_id == 'panel_header_'+panel_name && !searchArray(related_target_id,header_contents,'_'+panel_name)) || (related_target_id != 'panel_header_'+panel_name && searchArray(target_id,header_contents,'_'+panel_name) && !searchArray(related_target_id,header_contents,'_'+panel_name))))
	{
		fadeOut('panel_header_menu_'+panel_name);
		shown_header_menu = '';
	}
}

/**
 * Loads RSS feed content into appropriate panel.
 * @param {Integer} rss_feed RSS feed ID
 */
function loadRssFeed(rss_feed)
{
	var ajax = initAjax();
	ajax.open('GET','rss_feed.php?timeStamp='+new Date().getTime()+'&content_type=xml&feed='+rss_feed,true);
	ajax.onreadystatechange = function() { loadRssFeedCallback(ajax,rss_feed) };
	ajax.send(null);
}

/**
 * Called exclusively by loadRssFeed(); continues operations of that function.
 * @param {Object} ajax Ajax object
 * @param {Integer} rss_feed RSS feed ID
 * @see #loadRssFeed
 */
function loadRssFeedCallback(ajax,rss_feed)
{
	if(ajax.readyState == 4)
	{
		if(ajax.status == 200)
		{
			var xml = ajax.responseXML;
			var panel_content_scroll = $('panel_content_scroll_rss_feed_'+rss_feed);

			if(xml && panel_content_scroll)
			{
				removeChildren(panel_content_scroll);
				
				var html = xml.getElementsByTagName('html')[0];
				var div = firstElement(html);
				appendNode(div,panel_content_scroll);
			}
		}
	}
}