/***************************************************************************

	Written By:		Ryan Faircloth
	Company:		Tension Studios
	
	This utility is used to associate a pop-up calendar with form inputs.
	Some functions are dependent on the file pointer.js
		* getObject
		* getTarget
****************************************************************************/
var _calendar;
function Calendar()
{
	var args = Calendar.arguments;
	var nargs = args.length;
	
	var d = new Date();

	if(nargs == 1)
	{
		var o = getObject(args[0]);
		
		if(o)
			d = new Date(o.value);
			
		_calendar = new ryCalendar(d.getFullYear(),d.getMonth()+1,d.getDate(),args[0]);	
	}
	else if(nargs == 2)
	{
		//d.s(Date.parse("1/1/2007"));
		//d.setFullYear(ryCalendar.currentCalendar.currentYear,ryCalendar.currentCalendar.currentMonth-1,1);
		d = new Date(args[0]);
		//Date.parse("1/1/2007");
		_calendar = new ryCalendar(d.getFullYear(),d.getMonth()+1,d.getDate(),args[1]);
	}
}

function WriteCalendar()
{
   document.write(getCalendarString());
   var win = new PopupWindow('__RYTOOLS_calendar__');
   win.offsetX = 20;
   win.autoHide();	
   win.hidePopup();
}

function getCalendarDate()
{
   var months = new Array(13);
   months[0]  = "January";
   months[1]  = "February";
   months[2]  = "March";
   months[3]  = "April";
   months[4]  = "May";
   months[5]  = "June";
   months[6]  = "July";
   months[7]  = "August";
   months[8]  = "September";
   months[9]  = "October";
   months[10] = "November";
   months[11] = "December";
   var now         = new Date();
   var monthnumber = now.getMonth();
   var monthname   = months[monthnumber];
   var monthday    = now.getDate();
   var year        = now.getYear();
   if(year < 2000) { year = year + 1900; }
   var dateString = monthnumber +
                    '/' +
                    monthday +
                    '/' +
                    year;
   return dateString;
} // function getCalendarDate()

var _CALENDAR_SYMBOL_ = "<img src='images/calendar.jpg'>";
function ryCalendar(year, month, day)
{
	var args = ryCalendar.arguments;
	var nargs = args.length;
	this.input = null;

	if(nargs > 3)
	{
		var tmp = getObject(args[3]);
		if(tmp)
			this.input = tmp;
	}

	var initDate = null;
	if(this.input)
	{
		if(this.input.value != '')
		{
		initDate = new Date(this.input.value);
		this.input.calendar = this;
		this.input.onblur = function(e){setCalendarFromInput(getTarget(e));};
		}
		else
		{
		//var calendarDate = getCalendarDate();
		initDate = new Date();
		this.input.calendar = this;
		this.input.onblur = function(e){setCalendarFromInput(getTarget(e));};
		}
	}
			
	if(initDate)
	{
		this.selectedDate = initDate;
		this.currentMonth = initDate.getMonth()+1;
		this.currentYear = initDate.getYear();
	}
	else
	{
		this.selectedDate = new Date();
		this.selectedDate.setFullYear(year,month-1,day);
		this.currentMonth = month;
		this.currentYear = year;
	}
	
	ryCalendar.currentCalendar = this;
	
	if(ryCalendar.calendarCount == 0)
	{
		//document.write(getCalendarString());
		ryCalendar.initializeCalendar();
		
		ryCalendar.win = new PopupWindow('__RYTOOLS_calendar__');
		ryCalendar.win.offsetX = 20;
		ryCalendar.win.autoHide();
		
		ryCalendar.win.hidePopup();
		//ryCalendar.hide();
	}
	
	++ryCalendar.calendarCount;	
	
	document.write('<span id=\'__ryCalendar_' + ryCalendar.calendarCount + '__\' name=\'__ryCalendar_' + ryCalendar.calendarCount + '__\' style=\'cursor: pointer;\' onclick=\'ryCalendar.changeCalendars(this); ryCalendar.show(this);\'>' + _CALENDAR_SYMBOL_ + '</span>');
	var o = getObject('__ryCalendar_' + ryCalendar.calendarCount + '__');
	o.calendar = this;
}

ryCalendar.calendarCount = 0;
ryCalendar.monthNames = new Array("JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE","JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER");
ryCalendar.monthAbbs = new Array("JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC");
ryCalendar.currentCalendar = null;

ryCalendar.incrementMonth = function (inc)
{
	var d = new Date();
	d.setFullYear(ryCalendar.currentCalendar.currentYear,ryCalendar.currentCalendar.currentMonth-1,1);
	d.setMonth(d.getMonth()+inc);
	ryCalendar.currentCalendar.changeCalendarMonth(getObject('dayContainer'),d.getYear(),d.getMonth()+1);
}

ryCalendar.incrementYear = function (inc)
{
	var d = new Date();
	d.setFullYear(ryCalendar.currentCalendar.currentYear,ryCalendar.currentCalendar.currentMonth-1,1);
	d.setYear(d.getYear()+inc);
	ryCalendar.currentCalendar.changeCalendarMonth(getObject('dayContainer'),d.getYear(),d.getMonth()+1);
}

ryCalendar.selectDate = function (o)
{
	if(o.day != 0)
	{
		ryCalendar.currentCalendar.selectedDate.setFullYear(ryCalendar.currentCalendar.currentYear,ryCalendar.currentCalendar.currentMonth-1,o.day);
		ryCalendar.currentCalendar.changeCalendarMonth(getObject('dayContainer'),ryCalendar.currentCalendar.currentYear,ryCalendar.currentCalendar.currentMonth);
		
		var input = ryCalendar.currentCalendar.input;
		var d = ryCalendar.currentCalendar.selectedDate;
		if(input)
		{
			input.value = (d.getMonth()+1)+"/"+d.getDate()+"/"+d.getYear();
		}
	}
}

ryCalendar.changeCalendars = function (o)
{
	ryCalendar.currentCalendar = o.calendar;
	ryCalendar.redrawCalendar();
}

ryCalendar.redrawCalendar = function()
{
	ryCalendar.currentCalendar.changeCalendarMonth(getObject('dayContainer'),ryCalendar.currentCalendar.currentYear,ryCalendar.currentCalendar.currentMonth);
}

ryCalendar.hide = function()
{
	ryCalendar.win.hidePopup();
	//getObject("__RYTOOLS_calendar__",true).display = "none";
}

ryCalendar.show = function(o)
{
	ryCalendar.win.showPopup(o.name);
	//ryCalendar.getPosition(o);
	//var pos = getAnchorPosition(o.name);
//	getObject("__RYTOOLS_calendar__",true).display = "";
	//alert("Here!");
}

ryCalendar.getPosition = function(e)
{
	var left = 0;
	var top  = 0;

	while (e.offsetParent){
		left += e.offsetLeft;
		top  += e.offsetTop;
		e     = e.offsetParent;
	}

	left += e.offsetLeft;
	top  += e.offsetTop;

	return {x:left, y:top};
}

ryCalendar.initializeCalendar = function ()
{
	var cal = getObject('dayContainer');
	var date = ryCalendar.currentCalendar.selectedDate;
	//calSelectedDate.setFullYear(year,month-1,day);
	
	var tr = document.createElement("TR");
	if (navigator.userAgent.indexOf("Firefox") != -1)
	{
	var td = document.createElements("TD",7);
	}
	else
	{
	var td = document.createElements("<TD align='right' valign='bottom' style='cursor: pointer;' onclick='if(this.active){ryCalendar.selectDate(this); ryCalendar.hide();}' onmouseover='ryCalendar.mouseOverCell(this);' onmouseout='ryCalendar.mouseOutCell(this);'>",7);
	}
	appendChildren(tr,td);
	tr = duplicateNode(tr,6);	
	
	appendChildren(cal,tr);
	
	ryCalendar.currentCalendar.changeCalendarMonth(cal,date.getFullYear(),date.getMonth()+1)
}

ryCalendar.prototype.changeCalendarMonth = function (cal,year,month)
{
	this.currentMonth = month;
	this.currentYear = year;
	var oMonth = getObject('calendarMonth');
	var oYear = getObject('calendarYear');
	var prevMonth = getObject('calPrevMonth');
	var nextMonth = getObject('calNextMonth');
	var prevYear = getObject('calPrevYear');
	var nextYear = getObject('calNextYear');
	var today = new Date();
	
	oMonth.innerHTML = ryCalendar.monthNames[month-1];
	oYear.innerHTML = year;

	var firstDay = new Date();
	firstDay.setFullYear(year,month-1,1);
	var dayOne = firstDay.getDay();
	var days = daysInMonth(month, year);
	
	var pMonth = new Date(firstDay);
	var nMonth = new Date(firstDay);
	
	pMonth.setMonth(pMonth.getMonth() - 1);
	nMonth.setMonth(nMonth.getMonth() + 1);
	
	prevMonth.innerHTML = ryCalendar.monthAbbs[pMonth.getMonth()];
	nextMonth.innerHTML = ryCalendar.monthAbbs[nMonth.getMonth()];
	prevYear.innerHTML = year - 1;
	nextYear.innerHTML = year + 1;
	
	var i;
	var count = 0;
	for(i = 0; i < 6*7; ++i)
	{
		var row = cal.rows[Math.floor(i/7)];
		var cell = row.cells[i%7];
		
		cell.className = "";
		
		if(i >= dayOne && i < dayOne+days)
		{
			cell.innerHTML = ++count;
			cell.active = true;
			cell.day = count;
			
			if(month == this.selectedDate.getMonth()+1 && year == this.selectedDate.getFullYear() && count == this.selectedDate.getDate())
				cell.className = "selectedCalendarCell";
			else if(month == today.getMonth()+1 && year == today.getFullYear() && count == today.getDate())
				cell.className = "todayCalendarCell";
			else
				cell.className = "activeCalendarCell";
		}
		else
		{
			var text = "&nbsp;";
			var d = new Date();
			
			d.setMonth(this.currentMonth-1);
			d.setFullYear(this.currentYear);
	
			if(i < dayOne)
			{
				d.setDate(1);
				d.setDate(d.getDate()-(dayOne-i));
				
				text = d.getDate() + "";
				//text = ryCalendar.monthAbbs[d.getMonth()] + "<br><span style='font-size: 7px;'>" + d.getDate() + "</span>";
				//if(d.getFullYear() != this.currentYear)
					//text += "<br>" + d.getFullYear();
			}
			else
			{
				d.setDate(days);
				d.setDate(d.getDate()+(i-days-dayOne+1));
				
				text = d.getDate() + "";
				//text = ryCalendar.monthAbbs[d.getMonth()] + "<br><span style='font-size: 7px;'>" + d.getDate() + "</span>";
				//if(d.getFullYear() != this.currentYear)
					//text += "<br>" + d.getFullYear();
			}


			//myDate.setDate(myDate.getDate()+5)			
			cell.day = 0;
			cell.active = false;
			cell.innerHTML = text;			
			
			cell.className = "inactiveCalendarCell";
		}
	}
}

ryCalendar.mouseOverCell = function (o)
{
	if(o.active)
	{
		o.style.backgroundColor = '#CCCCCC';
		o.style.cursor = 'pointer';
	}
	else
		o.style.cursor = 'default';
}

ryCalendar.mouseOutCell = function (o)
{
	o.style.backgroundColor = '';
}

function getCalendarString()
{
	var str='';
	str+='<div id=\'__RYTOOLS_calendar__\' style=\'position:absolute;top:115px;right:25px;width:235px;height:210px;border:none;z-index:100;\'>';
	str+='<iframe frameborder=\'0\' style=\'position:absolute;top:0px;left:0px;width:235px;height:210px;\'></iframe>';
	str+='<div class=\'calendar_div\' id=\'blah\'><table height=\'210\' width=\'235\' cellpadding=\'5\' cellspacing=\'0\' style=\'background-color: #CCCCCC; display: ;\'>';
	str+='<tr>';
	str+='	<td height=\'100%\' align=\'center\' valign=\'middle\' style=\'font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-weight: bold; color: #444444; text-transform: uppercase;\'>';
	str+='		<table height=\'100%\' width=\'100%\' cellpadding=\'4\' cellspacing=\'0\' style=\'background-color: #FFFFFF; border: 1px solid #AAAAAA;\'>';
	str+='		<tr>';
	str+='			<td height=\'20\' align=\'center\' valign=\'middle\' style=\'font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-weight: bold; color: #444444; text-transform: uppercase;\'>';
	str+='				<table height=\'100%\' width=\'100%\' cellpadding=\'1\' cellspacing=\'0\' style=\'border: 1px solid #EEEEEE; background-color: #FCFCFC;\'>';
	str+='				<tr>';
	str+='					<td height=\'50%\' style=\'border-bottom: 1px solid #F5F5F5;\'><span id=\'calPrevMonth\' style=\'font-size: 8px; float: left; cursor: pointer;\' onclick=\'ryCalendar.incrementMonth(-1);\'><\/span><\/td>';
	str+='					<td rowspan=\'2\' align=\'center\' valign=\'middle\'><span id=\'calendarMonth\' style=\'cursor: pointer;\' onclick=\'if(!this.hasField){getMonthSelectField(this);}\'><\/span>&nbsp;<span id=\'calendarYear\' style=\'cursor: pointer;\' onclick=\'if(!this.hasField){getYearSelectField(this);}\'><\/span><\/td>';
	str+='					<td style=\'border-bottom: 1px solid #F5F5F5;\'><span id=\'calNextMonth\' style=\'font-size: 8px; float: right; cursor: pointer;\' onclick=\'ryCalendar.incrementMonth(+1);\'><\/span><\/td>';
	str+='				<\/tr>';
	str+='				<tr>';
	str+='					<td height=\'50%\' style=\'border-top: 0px solid #DDDDDD;\'><span id=\'calPrevYear\' style=\'font-size: 9px; float: left; cursor: pointer;\' onclick=\'ryCalendar.incrementYear(-1);\'><\/span><\/td>';
	str+='					<td style=\'border-top: 0px solid #DDDDDD;\'><span id=\'calNextYear\' style=\'font-size: 9px; float: right; cursor: pointer;\' onclick=\'ryCalendar.incrementYear(+1);\'><\/span><\/td>';
	str+='				<\/tr>';
	str+='				<\/table>';
	str+='			<\/td>';
	str+='		<\/tr>';
	str+='		<tr>';
	str+='			<td style=\'background-color: #FFFFFF;\'>';
	str+='				<table height=\'100%\' width=\'100%\' cellpadding=\'2\' cellspacing=\'1\'>';
	str+='				<thead>';
	str+='				<tr style=\'font-family: Helvetica, Arial, sans-serif; font-size: 8px; font-weight: normal; color: #444444; text-transform: uppercase; background-color: #F8F8F8\'>';
	str+='					<td height=\'10\' align=\'center\' valign=\'middle\' class=\'dayOfWeek\'>SUN<\/td>';
	str+='					<td height=\'10\' align=\'center\' valign=\'middle\' class=\'dayOfWeek\'>MON<\/td>';
	str+='					<td height=\'10\' align=\'center\' valign=\'middle\' class=\'dayOfWeek\'>TUE<\/td>';
	str+='					<td height=\'10\' align=\'center\' valign=\'middle\' class=\'dayOfWeek\'>WED<\/td>';
	str+='					<td height=\'10\' align=\'center\' valign=\'middle\' class=\'dayOfWeek\'>THU<\/td>';
	str+='					<td height=\'10\' align=\'center\' valign=\'middle\' class=\'dayOfWeek\'>FRI<\/td>';
	str+='					<td height=\'10\' align=\'center\' valign=\'middle\' class=\'dayOfWeek\'>SAT<\/td>';
	str+='				<\/tr>';
	str+='				<\/thead>';
	str+='				<tbody id=\'dayContainer\' style=\'font-family: Helvetica, Arial, sans-serif; font-size: 8px; font-weight: normal; color: #444444; text-transform: uppercase;\'>';
	str+='				<\/tbody>';
	str+='				<\/table>';
	str+='			<\/td>';
	str+='		<\/tr>';
	str+='		<\/table>';
	str+='	<\/td>';
	str+='<\/tr>';
	str+='<\/table><\/div>';
	str+='<\/div>';
	return str;
}

function setCalendarFromInput(input)
{
	if(input && input.value != '')
	{
		var cal = input.calendar;
		var d = new Date(input.value);
	
		if(d)
		{
			cal.selectedDate = d;
			cal.changeCalendarMonth(getObject('dayContainer'), d.getYear(),d.getMonth()+1);
		}
	}
}

function getMonthSelectField(monthSpan)
{
	var sel = document.createElement("select")
	
	sel.options.length = 0;
	for(var i = 0; i < 12; ++i)
	{
		sel.options[i] = new Option(ryCalendar.monthNames[i],i);
	}
	
	monthSpan.innerHTML = "";
	monthSpan.appendChild(sel);
	
	sel.value = ryCalendar.currentCalendar.currentMonth-1;
	sel.onchange = function(e){removeMonthSelectField(getTarget(e));};
	sel.onblur = function(e){removeMonthSelectField(getTarget(e));};
	monthSpan.hasField = true;
	sel.focus();
}

function removeMonthSelectField(o)
{
	var span = o.parentNode;
	span.hasField = false;
	ryCalendar.currentCalendar.changeCalendarMonth(getObject('dayContainer'),ryCalendar.currentCalendar.currentYear,parseInt(o.value)+1);
}

function getYearSelectField(yearSpan)
{
	var nh = 5;
	var sel = document.createElement("select");
	var currentYear = ryCalendar.currentCalendar.currentYear;
	sel.options.length = 0;
	for(var i = -nh; i <= nh; ++i)
	{
		sel.options[i+nh] = new Option(currentYear+i,currentYear+i);
	}
	yearSpan.innerHTML = "";
	yearSpan.appendChild(sel);
	
	sel.value = ryCalendar.currentCalendar.currentYear;
	sel.onchange = function(e){removeYearSelectField(getTarget(e));};
	sel.onblur = function(e){removeYearSelectField(getTarget(e));};
	yearSpan.hasField = true;
	sel.focus();
}

function removeYearSelectField(o)
{
	var span = o.parentNode;
	span.hasField = false;
	ryCalendar.currentCalendar.changeCalendarMonth(getObject('dayContainer'),parseInt(o.value),ryCalendar.currentCalendar.currentMonth);
}

function daysInMonth(month,year) 
{
	var m = [31,28,31,30,31,30,31,31,30,31,30,31];
	if (month != 2) return m[month - 1];
	if (year%4 != 0) return m[1];
	if (year%100 == 0 && year%400 != 0) return m[1];
	return m[1] + 1;
}

document.createElements = createElements;
function appendChildren(n)
{
	if(appendChildren.arguments.length == 2)
	{
		for(var i=0; i < appendChildren.arguments[1].length; ++i)
			n.appendChild(appendChildren.arguments[1][i]);
		//alert("HERE");
	}
	else if(appendChildren.arguments.length > 2)
	{
		for(var i=1; i < appendChildren.arguments.length; ++i)
			n.appendChild(appendChildren.arguments[i]);
	}
}

function createElements(e, num)
{
	var a;
	if(createElements.arguments.length >= 2 && num.length)
	{
		a = new Array(createElements.arguments.length);
		
		for(var i = 0; i < createElements.arguments.length; ++i)
			a[i] = document.createElement(createElements.arguments[i]);
	}
	else
	{
		a = new Array(num);
		
		for(var i=0; i < a.length; ++i)
			a[i] = document.createElement(e);
	}
	return a;
}

function duplicateNode(n, num)
{
	a = new Array(num);
		
	for(var i=0; i < a.length; ++i)
		a[i] = n.cloneNode(true);
		
	return a;
}





// getAnchorPosition(anchorname)
//   This function returns an object having .x and .y properties which are the coordinates
//   of the named anchor, relative to the page.
function getAnchorPosition(anchorname) {
	// This function will return an Object with x and y properties
	var useWindow=false;
	var coordinates=new Object();
	var x=0,y=0;
	// Browser capability sniffing
	var use_gebi=false, use_css=false, use_layers=false;
	if (document.getElementById) { use_gebi=true; }
	else if (document.all) { use_css=true; }
	else if (document.layers) { use_layers=true; }
	// Logic to find position
 	if (use_gebi && document.all) {
		x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);
		y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);
		}
	else if (use_gebi) {
		var o=document.getElementById(anchorname);
		x=AnchorPosition_getPageOffsetLeft(o);
		y=AnchorPosition_getPageOffsetTop(o);
		}
 	else if (use_css) {
		x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);
		y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);
		}
	else if (use_layers) {
		var found=0;
		for (var i=0; i<document.anchors.length; i++) {
			if (document.anchors[i].name==anchorname) { found=1; break; }
			}
		if (found==0) {
			coordinates.x=0; coordinates.y=0; return coordinates;
			}
		x=document.anchors[i].x;
		y=document.anchors[i].y;
		}
	else {
		coordinates.x=0; coordinates.y=0; return coordinates;
		}
	coordinates.x=x;
	coordinates.y=y;
	return coordinates;
	}

// getAnchorWindowPosition(anchorname)
//   This function returns an object having .x and .y properties which are the coordinates
//   of the named anchor, relative to the window
function getAnchorWindowPosition(anchorname) {
	var coordinates=getAnchorPosition(anchorname);
	var x=0;
	var y=0;
	if (document.getElementById) {
		if (isNaN(window.screenX)) {
			x=coordinates.x-document.body.scrollLeft+window.screenLeft;
			y=coordinates.y-document.body.scrollTop+window.screenTop;
			}
		else {
			x=coordinates.x+window.screenX+(window.outerWidth-window.innerWidth)-window.pageXOffset;
			y=coordinates.y+window.screenY+(window.outerHeight-24-window.innerHeight)-window.pageYOffset;
			}
		}
	else if (document.all) {
		x=coordinates.x-document.body.scrollLeft+window.screenLeft;
		y=coordinates.y-document.body.scrollTop+window.screenTop;
		}
	else if (document.layers) {
		x=coordinates.x+window.screenX+(window.outerWidth-window.innerWidth)-window.pageXOffset;
		y=coordinates.y+window.screenY+(window.outerHeight-24-window.innerHeight)-window.pageYOffset;
		}
	coordinates.x=x;
	coordinates.y=y;
	return coordinates;
	}

// Functions for IE to get position of an object
function AnchorPosition_getPageOffsetLeft (el) {
	var ol=el.offsetLeft;
	while ((el=el.offsetParent) != null) { ol += el.offsetLeft; }
	return ol;
	}
function AnchorPosition_getWindowOffsetLeft (el) {
	return AnchorPosition_getPageOffsetLeft(el)-document.body.scrollLeft;
	}	
function AnchorPosition_getPageOffsetTop (el) {
	var ot=el.offsetTop;
	while((el=el.offsetParent) != null) { ot += el.offsetTop; }
	return ot;
	}
function AnchorPosition_getWindowOffsetTop (el) {
	return AnchorPosition_getPageOffsetTop(el)-document.body.scrollTop;
	}
	
	
	
	
	
// ===================================================================
// Author: Matt Kruse <matt@mattkruse.com>
// WWW: http://www.mattkruse.com/
//
// NOTICE: You may use this code for any purpose, commercial or
// private, without any further permission from the author. You may
// remove this notice from your final code if you wish, however it is
// appreciated by the author if at least my web site address is kept.
//
// You may *NOT* re-distribute this code in any way except through its
// use. That means, you can include it in your product, or your web
// site, or any other form where the code is actually being used. You
// may not put the plain javascript up on your site for download or
// include it in your javascript libraries for download. 
// If you wish to share this code with others, please just point them
// to the URL instead.
// Please DO NOT link directly to my .js files from your site. Copy
// the files to your server and use them there. Thank you.
// ===================================================================

/* 
PopupWindow.js
Author: Matt Kruse
Last modified: 02/16/04

DESCRIPTION: This object allows you to easily and quickly popup a window
in a certain place. The window can either be a DIV or a separate browser
window.

COMPATABILITY: Works with Netscape 4.x, 6.x, IE 5.x on Windows. Some small
positioning errors - usually with Window positioning - occur on the 
Macintosh platform. Due to bugs in Netscape 4.x, populating the popup 
window with <STYLE> tags may cause errors.

USAGE:
// Create an object for a WINDOW popup
var win = new PopupWindow(); 

// Create an object for a DIV window using the DIV named 'mydiv'
var win = new PopupWindow('mydiv'); 

// Set the window to automatically hide itself when the user clicks 
// anywhere else on the page except the popup
win.autoHide(); 

// Show the window relative to the anchor name passed in
win.showPopup(anchorname);

// Hide the popup
win.hidePopup();

// Set the size of the popup window (only applies to WINDOW popups
win.setSize(width,height);

// Populate the contents of the popup window that will be shown. If you 
// change the contents while it is displayed, you will need to refresh()
win.populate(string);

// set the URL of the window, rather than populating its contents
// manually
win.setUrl("http://www.site.com/");

// Refresh the contents of the popup
win.refresh();

// Specify how many pixels to the right of the anchor the popup will appear
win.offsetX = 50;

// Specify how many pixels below the anchor the popup will appear
win.offsetY = 100;

NOTES:
1) Requires the functions in AnchorPosition.js

2) Your anchor tag MUST contain both NAME and ID attributes which are the 
   same. For example:
   <A NAME="test" ID="test"> </A>

3) There must be at least a space between <A> </A> for IE5.5 to see the 
   anchor tag correctly. Do not do <A></A> with no space.

4) When a PopupWindow object is created, a handler for 'onmouseup' is
   attached to any event handler you may have already defined. Do NOT define
   an event handler for 'onmouseup' after you define a PopupWindow object or
   the autoHide() will not work correctly.
*/ 

// Set the position of the popup window based on the anchor
function PopupWindow_getXYPosition(anchorname) {
	var coordinates;
	if (this.type == "WINDOW") {
		coordinates = getAnchorWindowPosition(anchorname);
		}
	else {
		coordinates = getAnchorPosition(anchorname);
		}
	//alert(anchorname + " [" + coordinates.x + ", " + coordinates.y + "]");
	this.x = coordinates.x;
	this.y = coordinates.y;
	}
// Set width/height of DIV/popup window
function PopupWindow_setSize(width,height) {
	this.width = width;
	this.height = height;
	}
// Fill the window with contents
function PopupWindow_populate(contents) {
	this.contents = contents;
	this.populated = false;
	}
// Set the URL to go to
function PopupWindow_setUrl(url) {
	this.url = url;
	}
// Set the window popup properties
function PopupWindow_setWindowProperties(props) {
	this.windowProperties = props;
	}
// Refresh the displayed contents of the popup
function PopupWindow_refresh() {
	if (this.divName != null) {
		// refresh the DIV object
		if (this.use_gebi) {
			document.getElementById(this.divName).innerHTML = this.contents;
			}
		else if (this.use_css) { 
			document.all[this.divName].innerHTML = this.contents;
			}
		else if (this.use_layers) { 
			var d = document.layers[this.divName]; 
			d.document.open();
			d.document.writeln(this.contents);
			d.document.close();
			}
		}
	else {
		if (this.popupWindow != null && !this.popupWindow.closed) {
			if (this.url!="") {
				this.popupWindow.location.href=this.url;
				}
			else {
				this.popupWindow.document.open();
				this.popupWindow.document.writeln(this.contents);
				this.popupWindow.document.close();
			}
			this.popupWindow.focus();
			}
		}
	}
// Position and show the popup, relative to an anchor object
function PopupWindow_showPopup(anchorname) {
	this.getXYPosition(anchorname);
	this.x += this.offsetX;
	this.y += this.offsetY;
	if (!this.populated && (this.contents != "")) {
		this.populated = true;
		this.refresh();
		}
	if (this.divName != null) {
		// Show the DIV object
		if (this.use_gebi) {
			document.getElementById(this.divName).style.left = this.x + "px";
			document.getElementById(this.divName).style.top = this.y + "px";
			document.getElementById(this.divName).style.visibility = "visible";
			}
		else if (this.use_css) {
			document.all[this.divName].style.left = this.x;
			document.all[this.divName].style.top = this.y;
			document.all[this.divName].style.visibility = "visible";
			}
		else if (this.use_layers) {
			document.layers[this.divName].left = this.x;
			document.layers[this.divName].top = this.y;
			document.layers[this.divName].visibility = "visible";
			}
		}
	else {
		if (this.popupWindow == null || this.popupWindow.closed) {
			// If the popup window will go off-screen, move it so it doesn't
			if (this.x<0) { this.x=0; }
			if (this.y<0) { this.y=0; }
			if (screen && screen.availHeight) {
				if ((this.y + this.height) > screen.availHeight) {
					this.y = screen.availHeight - this.height;
					}
				}
			if (screen && screen.availWidth) {
				if ((this.x + this.width) > screen.availWidth) {
					this.x = screen.availWidth - this.width;
					}
				}
			var avoidAboutBlank = window.opera || ( document.layers && !navigator.mimeTypes['*'] ) || navigator.vendor == 'KDE' || ( document.childNodes && !document.all && !navigator.taintEnabled );
			this.popupWindow = window.open(avoidAboutBlank?"":"about:blank","window_"+anchorname,this.windowProperties+",width="+this.width+",height="+this.height+",screenX="+this.x+",left="+this.x+",screenY="+this.y+",top="+this.y+"");
			}
		this.refresh();
		}
	}
// Hide the popup
function PopupWindow_hidePopup() {
	if (this.divName != null) {
		if (this.use_gebi) {
			document.getElementById(this.divName).style.visibility = "hidden";
			}
		else if (this.use_css) {
			document.all[this.divName].style.visibility = "hidden";
			}
		else if (this.use_layers) {
			document.layers[this.divName].visibility = "hidden";
			}
		}
	else {
		if (this.popupWindow && !this.popupWindow.closed) {
			this.popupWindow.close();
			this.popupWindow = null;
			}
		}
	}
// Pass an event and return whether or not it was the popup DIV that was clicked
function PopupWindow_isClicked(e) {
	if (this.divName != null) {
		if (this.use_layers) {
			var clickX = e.pageX;
			var clickY = e.pageY;
			var t = document.layers[this.divName];
			if ((clickX > t.left) && (clickX < t.left+t.clip.width) && (clickY > t.top) && (clickY < t.top+t.clip.height)) {
				return true;
				}
			else { return false; }
			}
		else if (document.all) { // Need to hard-code this to trap IE for error-handling
			var t = window.event.srcElement;
			while (t.parentElement != null) {
				if (t.id==this.divName) {
					return true;
					}
				t = t.parentElement;
				}
			return false;
			}
		else if (this.use_gebi && e) {
			//var t = e.originalTarget;
			var t = e.target;
			while (t.parentNode != null) {
				if (t.id==this.divName) {
					return true;
					}
				t = t.parentNode;
				}
			return false;
			}
		return false;
		}
	return false;
	}

// Check an onMouseDown event to see if we should hide
function PopupWindow_hideIfNotClicked(e) {
	if (this.autoHideEnabled && !this.isClicked(e)) {
		this.hidePopup();
		}
	}
// Call this to make the DIV disable automatically when mouse is clicked outside it
function PopupWindow_autoHide() {
	this.autoHideEnabled = true;
	}
// This global function checks all PopupWindow objects onmouseup to see if they should be hidden
function PopupWindow_hidePopupWindows(e) {
	for (var i=0; i<popupWindowObjects.length; i++) {
		if (popupWindowObjects[i] != null) {
			var p = popupWindowObjects[i];
			p.hideIfNotClicked(e);
			}
		}
	}
// Run this immediately to attach the event listener
function PopupWindow_attachListener() {
	if (document.layers) {
		document.captureEvents(Event.MOUSEUP);
		}
	window.popupWindowOldEventListener = document.onmouseup;
	if (window.popupWindowOldEventListener != null) {
		document.onmouseup = new Function("window.popupWindowOldEventListener(); PopupWindow_hidePopupWindows();");
		}
	else {
		document.onmouseup = PopupWindow_hidePopupWindows;
		}
	}
// CONSTRUCTOR for the PopupWindow object
// Pass it a DIV name to use a DHTML popup, otherwise will default to window popup
function PopupWindow() {
	if (!window.popupWindowIndex) { window.popupWindowIndex = 0; }
	if (!window.popupWindowObjects) { window.popupWindowObjects = new Array(); }
	if (!window.listenerAttached) {
		window.listenerAttached = true;
		PopupWindow_attachListener();
		}
	this.index = popupWindowIndex++;
	popupWindowObjects[this.index] = this;
	this.divName = null;
	this.popupWindow = null;
	this.width=0;
	this.height=0;
	this.populated = false;
	this.visible = false;
	this.autoHideEnabled = false;
	
	this.contents = "";
	this.url="";
	this.windowProperties="toolbar=no,location=no,status=no,menubar=no,scrollbars=auto,resizable,alwaysRaised,dependent,titlebar=no";
	if (arguments.length>0) {
		this.type="DIV";
		this.divName = arguments[0];
		}
	else {
		this.type="WINDOW";
		}
	this.use_gebi = false;
	this.use_css = false;
	this.use_layers = false;
	if (document.getElementById) { this.use_gebi = true; }
	else if (document.all) { this.use_css = true; }
	else if (document.layers) { this.use_layers = true; }
	else { this.type = "WINDOW"; }
	this.offsetX = 0;
	this.offsetY = 0;
	// Method mappings
	this.getXYPosition = PopupWindow_getXYPosition;
	this.populate = PopupWindow_populate;
	this.setUrl = PopupWindow_setUrl;
	this.setWindowProperties = PopupWindow_setWindowProperties;
	this.refresh = PopupWindow_refresh;
	this.showPopup = PopupWindow_showPopup;
	this.hidePopup = PopupWindow_hidePopup;
	this.setSize = PopupWindow_setSize;
	this.isClicked = PopupWindow_isClicked;
	this.autoHide = PopupWindow_autoHide;
	this.hideIfNotClicked = PopupWindow_hideIfNotClicked;
	}
	








// ===================================================================
// Author: Matt Kruse <matt@mattkruse.com>
// WWW: http://www.mattkruse.com/
//
// NOTICE: You may use this code for any purpose, commercial or
// private, without any further permission from the author. You may
// remove this notice from your final code if you wish, however it is
// appreciated by the author if at least my web site address is kept.
//
// You may *NOT* re-distribute this code in any way except through its
// use. That means, you can include it in your product, or your web
// site, or any other form where the code is actually being used. You
// may not put the plain javascript up on your site for download or
// include it in your javascript libraries for download. 
// If you wish to share this code with others, please just point them
// to the URL instead.
// Please DO NOT link directly to my .js files from your site. Copy
// the files to your server and use them there. Thank you.
// ===================================================================

/* 
AnchorPosition.js
Author: Matt Kruse
Last modified: 10/11/02

DESCRIPTION: These functions find the position of an <A> tag in a document,
so other elements can be positioned relative to it.

COMPATABILITY: Netscape 4.x,6.x,Mozilla, IE 5.x,6.x on Windows. Some small
positioning errors - usually with Window positioning - occur on the 
Macintosh platform.

FUNCTIONS:
getAnchorPosition(anchorname)
  Returns an Object() having .x and .y properties of the pixel coordinates
  of the upper-left corner of the anchor. Position is relative to the PAGE.

getAnchorWindowPosition(anchorname)
  Returns an Object() having .x and .y properties of the pixel coordinates
  of the upper-left corner of the anchor, relative to the WHOLE SCREEN.

NOTES:

1) For popping up separate browser windows, use getAnchorWindowPosition. 
   Otherwise, use getAnchorPosition

2) Your anchor tag MUST contain both NAME and ID attributes which are the 
   same. For example:
   <A NAME="test" ID="test"> </A>

3) There must be at least a space between <A> </A> for IE5.5 to see the 
   anchor tag correctly. Do not do <A></A> with no space.
*/ 

// getAnchorPosition(anchorname)
//   This function returns an object having .x and .y properties which are the coordinates
//   of the named anchor, relative to the page.
function getAnchorPosition(anchorname) {
	// This function will return an Object with x and y properties
	var useWindow=false;
	var coordinates=new Object();
	var x=0,y=0;
	// Browser capability sniffing
	var use_gebi=false, use_css=false, use_layers=false;
	if (document.getElementById) { use_gebi=true; }
	else if (document.all) { use_css=true; }
	else if (document.layers) { use_layers=true; }
	// Logic to find position
 	if (use_gebi && document.all) {
		x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);
		y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);
		}
	else if (use_gebi) {
		var o=document.getElementById(anchorname);
		x=AnchorPosition_getPageOffsetLeft(o);
		y=AnchorPosition_getPageOffsetTop(o);
		}
 	else if (use_css) {
		x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);
		y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);
		}
	else if (use_layers) {
		var found=0;
		for (var i=0; i<document.anchors.length; i++) {
			if (document.anchors[i].name==anchorname) { found=1; break; }
			}
		if (found==0) {
			coordinates.x=0; coordinates.y=0; return coordinates;
			}
		x=document.anchors[i].x;
		y=document.anchors[i].y;
		}
	else {
		coordinates.x=0; coordinates.y=0; return coordinates;
		}
	coordinates.x=x;
	coordinates.y=y;
	return coordinates;
	}

// getAnchorWindowPosition(anchorname)
//   This function returns an object having .x and .y properties which are the coordinates
//   of the named anchor, relative to the window
function getAnchorWindowPosition(anchorname) {
	var coordinates=getAnchorPosition(anchorname);
	var x=0;
	var y=0;
	if (document.getElementById) {
		if (isNaN(window.screenX)) {
			x=coordinates.x-document.body.scrollLeft+window.screenLeft;
			y=coordinates.y-document.body.scrollTop+window.screenTop;
			}
		else {
			x=coordinates.x+window.screenX+(window.outerWidth-window.innerWidth)-window.pageXOffset;
			y=coordinates.y+window.screenY+(window.outerHeight-24-window.innerHeight)-window.pageYOffset;
			}
		}
	else if (document.all) {
		x=coordinates.x-document.body.scrollLeft+window.screenLeft;
		y=coordinates.y-document.body.scrollTop+window.screenTop;
		}
	else if (document.layers) {
		x=coordinates.x+window.screenX+(window.outerWidth-window.innerWidth)-window.pageXOffset;
		y=coordinates.y+window.screenY+(window.outerHeight-24-window.innerHeight)-window.pageYOffset;
		}
	coordinates.x=x;
	coordinates.y=y;
	return coordinates;
	}

// Functions for IE to get position of an object
function AnchorPosition_getPageOffsetLeft (el) {
	var ol=el.offsetLeft;
	while ((el=el.offsetParent) != null) { ol += el.offsetLeft; }
	return ol;
	}
function AnchorPosition_getWindowOffsetLeft (el) {
	return AnchorPosition_getPageOffsetLeft(el)-document.body.scrollLeft;
	}	
function AnchorPosition_getPageOffsetTop (el) {
	var ot=el.offsetTop;
	while((el=el.offsetParent) != null) { ot += el.offsetTop; }
	return ot;
	}
function AnchorPosition_getWindowOffsetTop (el) {
	return AnchorPosition_getPageOffsetTop(el)-document.body.scrollTop;
	}