var isXblibInit = false ;

var isOther = true;	// miscellaneous non-supported browsers

var isNav4 = false;
var isNav6 = false ;
var isIE = false ;
var isIE4 = false ;
var isIE5 = false ;
var isW3C = false ;
var isWin = false;
var isMac = false;
var isMoz5 = false;

var docAll = null;

var verMajor = 0;
var verMinor = 0;

var getElem = function(){}

xblibInit();

function xblibInit ()
{
	docAll = document;

	var ver = navigator.appVersion.toLowerCase();
	var agt = navigator.userAgent.toLowerCase(); 

	isWin = (-1 != ver.indexOf( "win" ) ); 
	isMac = (-1 != ver.indexOf( "mac" ) ); 

	verMajor = parseInt( ver ); 
	verMinor = parseFloat( ver ); 

	if ( document.layers )
	{
		// check for releases prior to 4.06 - they stink!
		isNav4 = ( verMinor >= 4.06 );
		isOther = !isNav4;
	}
	else
	{
		if ( document.all )
		{
			isIE = true ;
			isIE4 = true ;
			isOther = false;
			docAll = document.all ;
		}

		if ( document.getElementById )
		{
			isIE4 = false ;
			isIE5 = isIE ;
			isMoz5 = (!isIE);
			isW3C = true ;
			isOther = false;
			docAll = document;
			isNav6 = (-1 != agt.indexOf( "netscape" ) );
		}
	}

	// assign the correct function to the getElem function pointer var
	getElem = (isIE ? (isMac ? getElemIEMac : getElemIE) : isNav4 ? getElemNav4 : getElemNav6);

	isXblibInit = true ;
}

function isObj ( objToTest )
{
	return ( (objToTest != null) &&
			 (typeof(objToTest) == "object") );
}

function addEvent ( obj, evType, fn, useCapture, Nav4EventCode )
{
	if (obj.addEventListener)	// Nav6
	{
		obj.addEventListener( evType, fn, useCapture );
	}
	else if (obj.attachEvent)	// IE 5+
	{
		obj.attachEvent( "on" + evType, fn );
	}
	// IE4, Nav4 - multiple event handlers not supported - use event chaining if
	// multiple events need to be supported
	else
	{
		var origHandler = obj[ "on" + evType ];
		obj[ "on" + evType ] = fn ;
		if ( isNav4 && useCapture && obj.captureEvents && Nav4EventCode )
		{
			obj.captureEvents( Nav4EventCode );
		}
		return origHandler ;
	}

	return null;
}


function cancelEvent ( e )
{
	if ( ! e ) return false ;
	
	if ( isIE )
	{
		e.cancelBubble = true;
		e.returnValue = false;
	}
	if ( e.cancelable )	e.cancelBubble = true;
	if ( e.stopPropagation ) e.stopPropagation();
	if ( e.preventDefault ) e.preventDefault();

	// for convenience the caller can end it's event handler by 
	// using the return	value of this function, i.e.:
	// return cancelEvent();
	return false ;
}


function getInstanceEventHandler ( obj, handlerName )
{
	function _getInstanceMethodClosure( _obj )
	{
		// Nav passes the event obj to the handler, pass it along to the real handler
		return function(evt)
		{
			return _obj[ handlerName ](evt);		
		}
	}
	
	return _getInstanceMethodClosure( obj );

}	// getInstanceEventHandler



// given and elements ID, return a ref to the corrosponding DOM obj
function getElemIE ( elem, doc ) 
{
	if (! doc ) doc = document;
	return doc.all[ elem ];
}

// given and elements ID, return a ref to the corrosponding DOM obj
function getElemIEMac ( elem, doc ) 
{
	if (! doc ) doc = document;
	if ( elem == "" ) return null; // else MacIE 5.0 will barf
	return doc.all[ elem ];
}


function getElemNav4 ( elemName, doc ) 
{
	function _searchElem( _doc )
	{
		// look for a layer
		var elem = _doc.layers[ elemName ];

		if ( isObj( elem ) )
		{
			return elem ;
		}

		// look for a form or a form field
		for ( var x = 0; x < _doc.forms.length; x++ )
		{
			if ( _doc.forms[ x ].name == elemName )
			{
				return _doc.forms[ x ] ;
			}

			// look for a form field
			elem = _doc.forms[ x ][ elemName ];
			if ( isObj( elem ) )
			{
				return elem ;
			}
		}

		// recurse down through the layers
		for ( x = 0; x < _doc.layers.length; x++ )
		{
			elem = _searchElem( _doc.layers[ x ].document );
			if ( isObj( elem ) )
			{
				return elem ;
			}
		}

		return elem ;
	}

	if (! doc ) doc = document;
	return _searchElem( doc );
}

function getElemNav6 ( elemNameOrID, doc ) 
{
	if (! doc ) doc = document;
	var elem = doc.getElementById( elemNameOrID );
	if ( elem ) return elem;
	
	elem = doc.getElementsByName( elemNameOrID );
	if ( elem[0] ) return elem[0];

	return null ;
}

function getChild ( obj, childIndex )
{
	if ( obj.childNodes )
	{
		return obj.childNodes[ childIndex ];
	}
	if ( obj.children )
	{
		return obj.children[ childIndex ];
	}
	else	// not supported
	{
		return null ;	
	}
}

// examine the obj and the ancestors of obj until 
// we find a parent element with the tag tagName
function getParentByTagName ( obj, tagName )
{
	// Nav4 does not support either parent or tagName properties 
	if ( isNav4 ) return obj;
	
	var parentObj = obj;
	while ( parentObj )
	{
		if ( tagName == parentObj.tagName )
		{
			return parentObj ;
		}
		//! IE4 uses 'parentElement'
		parentObj = parentObj.parentNode ? parentObj.parentNode : parentObj.parentElement ;
	}

	return null ;

}	// getParentByTagName


function isElemInView ( elem, win )
{
	if ( ! win ) win = window ;
	if ( isNav4 )
	{
		return (elem.top >= win.pageYOffset) &&
		      ((elem.top + elem.clip.height) <=
		       (win.innerHeight + win.pageYOffset));
	}
	else if ( isIE )
	{
		return (elem.offsetTop >= win.document.body.scrollTop) &&
		       (elem.offsetTop < (win.document.body.scrollTop + win.document.body.offsetHeight));
	}
	else if( isMoz5 )
	{
		return (elem.offsetTop >= win.scrollX) &&
		       (elem.offsetTop < (win.scrollX + win.innerHeight));
	}

}	// isElemInView

function scrollVertToElem ( elem, win )
{
	if ( !win ) win = window ;
	if ( isNav4 )
	{
		if ( (elem.top < win.pageYOffset) || 
		     ((elem.top + elem.clip.height) > 
		      (win.innerHeight + win.pageYOffset)) )
		{
			win.scroll( 0, elem.top );
		}
	}
	else if ( isIE )
	{
		elem.scrollIntoView();
	}
	else
	{
		win.scrollTo( 0, elem.offsetTop );
	}
	
}	// scrollVertToElem

function getTags ( parentObj, tagName )
{
	return (isIE4 ? parentObj.tags( tagName ) : 
			isW3C ?  parentObj.getElementsByTagName( tagName ) : null ); 
}

