// Glommed together JavaScript things form various sources
//	I find these function and object rather useful.
//

// BrowserCheck Object
// provides most commonly needed browser checking variables
// 19990326

// Copyright (C) 1999 Dan Steinman
// Distributed under the terms of the GNU Library General Public License
// Available at http://www.dansteinman.com/dynapi/

// Extensions added 2000-06-27 by Jesse Chisholm
//

function BrowserCheck()
{
	var b = navigator.appName
	if (b=="Netscape") this.b = "ns"
	else if (b=="Microsoft Internet Explorer") this.b = "ie"
	else this.b = b
	this.v = parseInt(navigator.appVersion)
	this.ns = this.b=="ns"
	this.ns4 = (this.b=="ns" && this.v==4)
	this.ns5 = (this.b=="ns" && this.v==5)
	this.ns6 = (this.b=="ns" && this.v==6)
	this.ie = this.b=="ie"
	this.ie4 = (navigator.userAgent.indexOf('MSIE 4')>0)
	this.ie5 = (navigator.userAgent.indexOf('MSIE 5')>0)
	if (this.ie5) this.v = 5
	this.mac = (navigator.platform.indexOf('Mac')>=0)
	//
	this.min = ((this.ns||this.ie)&&(this.v >= 4))
	//
	this.p = navigator.platform		// Win32, MacPPC, Mac68k, ...
	this.l = navigator.language
	if (null==this.l) this.l = 'en'	// assume English as default
}

// automatically create the "is" object
is = new BrowserCheck()

// special flag for IE 3 on a MAC, the object will get lost on a page reload.
var isIE3Mac = is.ie && is.mac && (is.v == 3);

///////////////////////////////////////////////////////////////////////////////
// Gets a reference to a named object.
//	Returns null if the named object can't be found.
//	Uses the most portible way available in this browser.
//
// Copyright (C) 2003 Jesse Chisholm
// Distributed under the terms of Copyleft.
//
function safeGetElementById(objID) {
	if (typeof objID == 'undefined') return null;
	if (typeof objID != 'string') return objID;
	if (document.getElementById) return document.getElementById(objID);
	if (document.all) return document.all[objID];
	if (document.layers) return document.layers[objID];
	return eval(objID);	// risk here if objID is a JS statement with side effects.
}

///////////////////////////////////////////////////////////////////////////////
// Gets a reference to the object's STYLE information area.
//	Returns null if the object can't be found.
//	Uses the most portible way available in this browser.
//
// Copyright (C) 2003 Jesse Chisholm
// Distributed under the terms of Copyleft.
//
function safeGetStyle(obj) {
	if (typeof obj == 'undefined') return null;
	if (typeof obj == 'string') obj = safeGetElementById(obj);
	if (null == obj) return null;
	if (obj.style) return obj.style;
	if (obj.css) return obj.css;
	return obj;
}

///////////////////////////////////////////////////////////////////////////////
// Gets the internal text (value) of an object.
//	Returns "" if the object can't be found.
//	Uses the most portible way available in this browser.
//
// Copyright (C) 2003 Jesse Chisholm
// Distributed under the terms of Copyleft.
//
function safeGetText(obj)
{
	if (typeof obj == 'undefined') return '';
	if (typeof obj == 'string') obj = safeGetElementById(obj);
	if (null == obj) return '';
	if (typeof obj.tagName == 'undefined') return '';
	if (obj.tagName  == 'TEXTAREA')
		return obj.innerText;
	return obj.innerHTML;
}

///////////////////////////////////////////////////////////////////////////////
// Sets the internal text (value) of an object.
//	Returns false if the object can't be found.
//	Uses the most portible way available in this browser.
//
// Copyright (C) 2003 Jesse Chisholm
// Distributed under the terms of Copyleft.
//
function safeSetText(obj,txt)
{
	if (typeof obj == 'undefined') return false;
	if (typeof obj == 'string') obj = safeGetElementById(obj);
	if (null == obj) return false;
	if (typeof obj.tagName == 'undefined') return false;
	if (obj.tagName == 'TEXTAREA')
		obj.innerText = txt;
	else
		obj.innerHTML = txt;
	return true;
}
safeSetText.next=0;

///////////////////////////////////////////////////////////////////////////////
// Some simple STYLE tweaking functions:
//	isDisplayed(objID)
//	isVisible(objID)
//	setDisplay(show,objID)
//	setVisible(show,objID)
//	toggleShow(objID)
//
function isDisplayed(obj) {
	var style = safeGetStyle(obj);
	if (null == style) return true;	// I suppose
	return style.display != 'none';
}
function isVisible(obj) {
	var style = safeGetStyle(obj);
	if (null == style) return true;	// I suppose
	return style.visibility != 'hidden';
}
function setDisplay(sw,obj) {
	var style = safeGetStyle(obj);
	if (null == style) return;
	style.display = (sw ? '' : 'none');
}
function setVisible(sw,obj) {
	var style = safeGetStyle(obj);
	if (null == style) return;
	style.visibility = (sw ? '' : 'hidden');
}
function toggleShow(divID)
{
	var v = isDisplayed(divID);
	setDisplay( !v, divID );
	setVisible( !v, divID );
}
function setShow(sw,divID)
{
	setDisplay( sw, divID );
	setVisible( sw, divID );
}

// Alternate Cookie Functions
//	These functions came from the DynDuo/dynapi/cookies.js by Dan Steinman
//	I added some features, and changed the names.  Rotten of me, I know.
//	some of the features came from http://www.alarmix.net/freeweb/pfaff/english/java/

// Copyright (C) 1999 Jesse Chisholm
// Distributed under the terms of Copyleft.

// largeExpDate
//	usage: setCookie( name, value, largeExpDate(days))
//
//	days		optional number of days before expiration
//				call with -1 to expire a cookie
//				0 or null or no parm given equates to 365 days
//
//	returns a Date object set to now plus the number of days
//
function largeExpDate(days)
{
	var leDate = new Date ()
	leDate.setTime(leDate.getTime() + ((days||365) * 24 * 60 * 60 * 1000))
	return leDate
}

//	"setCookie"
//		similar to "saveCookie" in DynDuo/dynapi/cookies.js
//		similar to "SetCookie" in http://www.alarmix.net/freeweb/pfaff/english/java/
//
//	usage:
//		setCookie( name, value [, expires [, path [, domain [, secure]]]] )
//
//	name		name of cookie
//	value		value of cookie (will be escaped)
//	expires	optional Date object, or #days (0==365, -1=delete)
//	path		optional path string
//	domain		optional domain string
//	secure		optional secure boolean
//
function setCookie(name,value)
{
	var argv = setCookie.arguments
	var argc = setCookie.arguments.length

	var expires = (argc > 2) ? argv[2] : null
	// check for days as expires parameter
	if ((null != expires)
	 && ("-0123456789".indexOf((''+expires).charAt(0)) != -1)
	   ) expires = largeExpDate(expires)
	var path = (argc > 3) ? argv[3] : "/"
	var domain = (argc > 4) ? argv[4] : null
	var secure = (argc > 5) ? argv[5] : false

	document.cookie = escape(name) + "=" + escape(value) +
		((expires == null) ? "" : ("; expires=" + expires.toGMTString())) +
		((path == null) ? "" : ("; path=" + path)) +
		((domain == null) ? "" : ("; domain=" + domain)) +
		((secure != true) ? "" : "; secure")
}

//	"getCookie"
//		similar to "readCookie" in DynDuo/dynapi/cookies.js
//		similar to "GetCookie" in http://www.alarmix.net/freeweb/pfaff/english/java/
//
//	name		name of cookie
//	dflt		optional default value of cookie
//
function getCookie(name)
{
	var argv = getCookie.arguments
	var argc = getCookie.arguments.length

	var nEQ = name + "="
	var ca = document.cookie.split(';')
	for(var i=0; i<ca.length; i++)
        {
		var c = ca[i];
		if (c.charAt(0)==' ') c = c.substring(1,c.length)
		var nv = c.split('=',2);
		if (unescape(nv[0])==name) return unescape(nv[1]);
	}
	return (argc>1) ? argv[1] : null
}

//	"delCookie"
//		same as "deleteCookie" in DynDuo/dynapi/cookies.js
//
//	name		name of cookie
//	path		optional path string
//	domain		optional domain string
//
function delCookie(name)
{
	var argv = delCookie.arguments
	var argc = delCookie.arguments.length

	if (argc > 2)
	{
		setCookie( name, '', '-7', argv[1], argv[2] );
	}
	else if (argc > 1)
	{
		setCookie( name, '', '-7', argv[1] );
	}
	else
	{
		setCookie( name, '', '-7' );
	}
}

// get dictionary style dump of current cookies.
//
function dumpCookies()
{
	var s = '';
	var ca = document.cookie.split(';')
	s += "<H1>Debug Dump of Cookies</H1>\n<dl>\n";
	for(var i=0; i<ca.length; i++)
	{
		var c = ca[i];
		if (c.charAt(0)==' ') c = c.substring(1,c.length)
		nv = c.split('=',2);
		s += "<dt>"+nv[0]+"</dt><dd>"+nv[1]+"</dd>\n";
	}
	s += "</dl>\n";

	return s;
}


// utility function
//  for making HTML displayable as if it were simple text.
//	doesn't do as much as escape(...); just does enough.
//
function uglify( s )
{
    var ugly = '';

    for(var i=0; i<s.length; ++i)
    {
        var c = s.substring(i,i+1);

        if      ("<" == c) ugly += "&lt;";
        else if (">" == c) ugly += "&gt;";
        else if ("&" == c) ugly += "&amp;";
        else if ("\n" == c) ugly += "<br>\n";
        else ugly += c;
    }

    return ugly;
}
function deuglify( s )
{
    var normal = '';

    for(var i=0; i<s.length; ++i)
    {
        var c = s.substring(i,i+1);
        if (c != '&' && c != '<')
            normal += c;
        else
        {
            if      (s.substring(i,i+4) == '&lt;') { normal += '<'; i += 3; }
            else if (s.substring(i,i+4) == '&gt;') { normal += '>'; i += 3; }
            else if (s.substring(i,i+5) == '&amp;') { normal += '&'; i += 4; }
            else if (s.substring(i,i+5) == '<br>\n') { normal += '\n'; i += 4; }
            else normal += c;
        }
    }

    return normal;
}
// utility function to remove all markups from a string.
//
function stripMarkups( s )
{
	var ugly = '';

	for(var i=0; i<s.length; ++i)
	{
		var c = s.substring(i,i+1);

		if      ("<" != c)
		{
			if ("\\" == c)
			{
				ugly += c;
				++i;
				c = s.substring(i,i+1);
			}
			ugly += c;
		}
		else
		{
			// check for <br>
			//
			if ((s.substring(i,i+4) == '<br>')
			 || (s.substring(i,i+6) == '<br />')
			 || (s.substring(i,i+4) == '<BR>')
			 || (s.substring(i,i+6) == '<BR />'))
			{
				ugly += '\r\n';
			}
			// NOW remove the markup
			//
			for(; i<s.length; ++i)
			{
				c = s.substring(i,i+1);
				if (">" == c) break;
				else
				if (("'" == c) || ('"' == c))
				{
					var q = c;
					for(; i<s.length; ++i)
					{
						c = s.substring(i,i+1);
						if (c == q) break;
					}
				}
				else
				if ("\\" == c)
				{
					++i;
					c = s.substring(i,i+1);
				}
			}
		}
	}

	return ugly;
}

// utility function supporting dumpObj
//
function isMember( obj, List )
{
	for(var i=0; i<List.length; i++)
	{
		if (obj == List[i]) return true
	}
	return false
}

// utility function used for debugging other stuff
//	dumps javascript objects to requested depth
//
function dumpObj(obj,oName,deep,level,seenList)
{
	if (deep==null) deep = 1
	if (level==null) level = 0
	if (seenList==null) seenList = new Array()

	var str = oName + ' = '
	var val = '';

	if (!is.ns) { val += obj; }
	else
	{
		if (typeof obj == "string") { val = 'String="'+obj+'"'; }
		else if (typeof obj == "undefined") { val = 'NULL'; }
		else if (typeof obj == "number") { val = 'Number='+obj; }
		else if (typeof obj == "boolean") { val = 'Bool='+obj; }
		else if (typeof obj == "window") { val = '[object Window]'; }
		else if (typeof obj == "history") { val = '[object History]'; }
		else if (typeof obj == "location") { val = '[object Location]'; }
		else if (typeof obj == "frame") { val = '[object Frame]'; }
		else if (typeof obj == "date") { val = '[object Date]'; }
		else if (typeof obj == "image") { val = '[object Image]'; }
		else if (typeof obj == "function") { val = '[object Function]'; }
		else if (typeof obj == "array") { val = '[array ...]'; }
		else if (typeof obj == "object") { val = '[object ...]'; }
		else { val = "[??? ...]"; }
	}

	// special case objects that have a "toString" member function
	//
	if (oName=='location') val = '[object Location]'

	if ((val.substring(0,7)=='[object') && (level < deep))
        {
		if (isMember(obj,seenList))
                {
			str += val + ' already dumped!'
		}
                else
                {
			seenList[ seenList.length ] = obj

			if (obj['length'] != null)
                        {
				str += "\n"
				for(var j=0; j<=level; j++) str += '.'
				str += 'length = ' + obj.length
				for(var i = 0; i < obj.length; i++)
                                {
					str += "\n"
					for(var j=0; j<=level; j++) str += '.'
					str += dumpObj(obj[i], '['+i+']', deep, level+1,seenList)
				}
			}
			for(var i in obj)
                        {
				var ii = ''+i
				if (ii=='length') continue	// already handled above
				if ((obj['length'] != null) && (ii==obj['name'])) continue
				if ((ii.substring(0,4)=='data')
				 || (ii.substring(0,6)=='parent')
				 || (ii.substring(ii.length-6,ii.length)=='Parent')
				   )
                                {
					str += "\n"
					for(var j=0; j<=level; j++) str += '.'
					str += ii + ' = [' + ii + ']'
					continue
				}
				str += "\n"
				for(var j=0; j<=level; j++) str += '.'
				if ((ii != 'document')
				 && (ii != 'top')
				 && (ii != 'all')
				 && (ii != 'self')
//				 && (ii != 'frames')
				   )
                                {
					str += dumpObj(obj[i], ii, deep, level+1,seenList)
				}
                                else
                                {
					str += ii + ' = ' + obj[i]
				}
			}
		}
	}
        else if (val.substring(0,9)=='function ')
        {
		str += val.substring(0,val.indexOf('(')) + ' ...'
	}
        else if (val.substring(1,10)=='function ')
        {
		str += val.substring(1,val.indexOf('(')) + ' ...'
	}
        else
        {
		str += (null==obj) ? 'null' : val
	}

	return str;
}

// Borrowed from Axis pages (see: www.Axis.com)
//
//	Opens a popup window with a specified page.  Names the new window
//	for reference by scripts, also specifies the size of the new window.
//
//	arguments:
//		thePage			the URL of the page to load
//		theName			the name of this new window for script reference
//		theWidth		desired width of the new window
//		theHeight		desired height of the new window
//		extraFeatures	optional comma separated list of tweaks to options
//						only specify options you wish to change
//						from the defaults listed below.
//
//	if extraFeatures is not provided, assume:
//		"scrollbars=1,toolbar=0,location=0,directories=0,status=0,menubar=0,resizable=1"
//
function openPopUp(thePage, theName, theWidth, theHeight, extraFeatures)
{
if (!theWidth) theWidth=590;
if (!theHeight) theHeight=410;
if (!thePage) thePage = 'about:blank';
  var someFeatures = 'width=' + theWidth + ',height=' + theHeight;
  if (extraFeatures) someFeatures += ',' + extraFeatures;
  if (someFeatures.indexOf(',scrollbars=')<0) someFeatures +=',scrollbars=1'
  if (someFeatures.indexOf(',toolbar=')<0) someFeatures +=',toolbar=0'
  if (someFeatures.indexOf(',location=')<0) someFeatures +=',location=0'
  if (someFeatures.indexOf(',directories=')<0) someFeatures +=',directories=0'
  if (someFeatures.indexOf(',status=')<0) someFeatures +=',status=0'
  if (someFeatures.indexOf(',menubar=')<0) someFeatures +=',menubar=0'
  if (someFeatures.indexOf(',resizable=')<0) someFeatures +=',resizable=1'

//  var aWindowName = makeWindowName( theName );
  var aWindowName = makeAlphaNumeric(theName);

  var aPopUpWin    = window.open(thePage, aWindowName, someFeatures);
  if (null==aPopUpWin) return null;

  if (is.ns)
  {
    aPopUpWin.focus();

	// set the opener if it's not already set.  it's set automatically
	// in netscape 3.0+ and ie 3.0+.
	if( is.ns && !is.ns4 )
	{
		aPopUpWin.location = thePage;
		aPopUpWin.opener = self;
	}
  }
  return aPopUpWin;
}


// Borrowed from Axis pages (see: www.Axis.com)
//

//	Opens a popup window with a specified flat text.  Names the new window
//	as requested
//
//	arguments:
//		theText			the text to display in a simple window
//		theName			the title of this text
//		theWidth		optional pixels width of window, default 590
//		theHeight		optional pixels height of window, default 410
//
function openTextWindow( theText, theName, theWidth, theHeight )
{
	if (!theText) theText = "No Text Provided!";
	if (!theName) theName = "No Name Provided!";
	var tWin = openPopUp( "", theName, (theWidth||'590'), (theHeight||'410') );
	tWin.document.write("<HTML><HEAD><TITLE>"
                + theName + "</TITLE></HEAD><BODY><H1>"
                + theName + "</H1><hr><PRE>\n"
		+ theText + "\n</PRE>"
		+ "<hr><P ALIGN='RIGHT'><FORM><INPUT TYPE='BUTTON' Value='Close' ONCLICK='window.close()'></FORM></P>"
		+ "</BODY></HTML>\n"
		);
        tWin.document.close();
        return tWin;
}
function openHtmlWindow( theHtml, theName, theWidth, theHeight )
{
	if (!theHtml) theHtml = "<html><body><H1>No Html Provided!</H1></body></html>\n";
	if (!theName) theName = "No Name Provided!";
	var tWin = openPopUp( "", theName, (theWidth||'590'), (theHeight||'410') );
	tWin.document.write(theHtml);
	tWin.document.close();
	return tWin;
}

// Borrowed from Axis pages (see: www.Axis.com)
//
//	Converts a URL into a legal window name, by removing all
//	characters that are NOT alpha-numeric.
//
function makeAlphaNumeric(theOriginalName)
{
  var anAlphaNumName = "";
  var aPos           = 0;
  while (aPos < theOriginalName.length)
  {
    var c = theOriginalName.charAt(aPos);
    if ((c >= '0' && c <= '9')
	 || (c >= 'A' && c <= 'Z')
	 || (c >= 'a' && c <= 'z'))
    {
      anAlphaNumName = anAlphaNumName + c;        
    }               
    aPos++;
  }       
  return anAlphaNumName;
}
function makeWindowName( theName )
{
	return makeAlphaNumeric("W_" + window.location.host + "_" + theName);
}

//////////////////////////////////////////////////////////////////////////
//

// Return the currently checked value of a radio group
//	<input type="radio" name="itm" value="1">Item 1
//	<input type="radio" name="itm" value="2">Item 2
//	<input type="radio" name="itm" value="3">Item 3
//	<input type="radio" name="itm" value="4">Item 4
//
//	var idx = radioIndex( document.form[0].itm ); // or whatever
//	radioIndex( document.form[0].itm, idx+1 ); // or whatever
//
//	var val = radioValue( document.form[0].itm ); // or whatever
//	setRadio( document.form[0].itm, 'val' ); // or whatever
//
function radioIndex( itm )
{
	var argv = radioIndex.arguments
	var argc = radioIndex.arguments.length

	if (argc == 1)
	{
		// look exhaustively
		//
		for( var i = 0; i < itm.length; ++i )
		{
			if (itm[i].checked)
			{
				return i;	// return index of checked item
			}
		}

		return -1;		// return -1 for none checked
	} else {
		// clear all, then set chosen
		//
		for( var i = 0; i < itm.length; ++i )
			itm[i].checked = false;
		itm[parseInt(argv[1])].checked = true;
	}
}
function radioValue( itm )
{
	// look exhaustively
	//
	for( var i = 0; i < itm.length; ++i )
	{
		if (itm[i].checked)
			return itm[i].value;
	}

	// return optional default value, or null
	//
	return radioValue.arguments.length > 1 ? radioValue.arguments[1] : null;
}
function setRadio( itm, val )
{
	// look exhaustively
	//
	for( var i = 0; i < itm.length; ++i )
	{
		// unselect all
		if (itm[i].checked)
			itm[i].checked = false;

		// select chosen one
		if (itm[i].value == val)
			itm[i].checked = true;
	}
}

// Return the currently checked value of a select list
//	<select name="itm">
//		<option value="1">Item 1</option>
//		<option value="2">Item 2</option>
//		<option value="3">Item 3</option>
//		<option value="4">Item 4</option>
//	</select>
//
//	var idx = selectIndex( document.form[0].itm ); // or whatever
//	selectIndex( document.form[0].itm, idx+1 ); // or whatever
//
//	var val = selectValue( document.form[0].itm ); // or whatever
//	selectValue( document.form[0].itm, val ); // or whatever
//
function selectIndex( itm )
{
	// first, try the short cut
	//
	if ((typeof itm.selectedIndex != undefined)
	 && (typeof itm[itm.selectedIndex] != undefined)
	 && (typeof itm[itm.selectedIndex].value != undefined))
		return itm.selectedIndex;

	// then look exhaustively
	//
	for( var i = 0; i < itm.length; ++i )
	{
		if (itm[i].selected)
			return i;	// return index of selected item
	}

	return -1;			// return -1 for none selected
}
function selectValue( itm )
{
	// first, try the short cut
	//
	if ((typeof itm.selectedIndex != undefined)
	 && (typeof itm[itm.selectedIndex] != undefined)
	 && (typeof itm[itm.selectedIndex].value != undefined))
		return itm[itm.selectedIndex].value;

	// then look exhaustively
	//
	for( var i = 0; i < itm.length; ++i )
	{
		if (itm[i].selected)
			return itm[i].value;
	}

	// return optional default value, or null
	//
	return arguments.length > 1 ? arguments[1] : null;
}
function setSelect( itm, val )
{
	// look exhaustively
	//
	for( var i = 0; i < itm.length; ++i )
	{
		// unselect all
		if (itm[i].selected)
			itm[i].selected = false;
	}
	itm.selectedIndex = -1;

	for( i = 0; i < itm.length; ++i )
	{
		// select chosen one
		if (itm[i].value == val)
		{
			itm[i].selected = true;
			itm.selectedIndex = i;
			return;
		}
	}
}

