function UI_MouseGetX( evt ) 
{
	if ( !evt ) 		evt = window.event;
    if ( evt.pageX ) 	return evt.pageX;
    if ( evt.clientX ) 	return evt.clientX + UI_ScrollGetX();
    return 0;
}

function UI_MouseGetY( evt ) 
{
	if ( !evt ) 		evt = window.event;
    if ( evt.pageY ) 	return evt.pageY;
    if ( evt.clientY ) 	return evt.clientY + UI_ScrollGetY();
    return 0;
}

function UI_ScrollGetX()
{
    if (document.documentElement.scrollLeft) return document.documentElement.scrollLeft;
    return document.body.scrollLeft;
}

function UI_ScrollGetY()
{
    if (document.documentElement.scrollTop) return document.documentElement.scrollTop;
    return document.body.scrollTop;
}

function UI_GetStyle( e, name )
{
    if (e.currentStyle) return e.currentStyle[name];
    if (window.getComputedStyle) return window.getComputedStyle(e,null)[name];
    return '';
}

function UI_GetDocHeight()
{
    if (document.documentElement) return document.documentElement.clientHeight;
    if (document.body) return document.body.clientHeight;
    return 500;
}

function UI_GetDocWidth()
{
    if (document.documentElement) return document.documentElement.clientWidth;
    if (document.body) return document.body.clientWidth;
    return 500;
}

function UI_GetAbsolutePos_Top(e,top_e)
{
	if ( !e ) { return; }

    var pos = e.offsetTop;
    var parent = e.offsetParent;
    while (parent)
    {
        pos += parent.offsetTop;
        parent = parent.offsetParent;
        if (parent==top_e) break;
    }
    return pos;
}

function UI_GetAbsolutePos_Left(e,top_e)
{
	if ( !e ) 
	{ 
		return; 
	}
	
    var pos = e.offsetLeft;
	var parent;
	try
	{
    	parent = e.offsetParent; // REVISIT -- occasional errors here
	}
	catch(e)
	{
	}
	
    while (parent)
    {
        pos += parent.offsetLeft;
        parent = parent.offsetParent;
        if (parent==top_e) break;
    }
    return pos;
}

function UI_FitOnScreen( e, x, y )
{
    var dw = UI_ScrollGetX() + UI_GetDocWidth();
    var dh = UI_ScrollGetY() + UI_GetDocHeight();
    
    var ex = UI_GetAbsolutePos_Left( e );
    var ey = UI_GetAbsolutePos_Top( e );
    
    var w = e.offsetWidth;
    var h = e.offsetHeight;
    
    if ( ( ex + w ) >= dw )	// flip horiz
    {
		e.style.left = ( x + dw - ( ex + w ) - 5 ) + 'px';
    }
    
    if ( ( ey + h ) >= dh )	// flip vert
    {
		e.style.top = ( y - h - 10 ) + 'px';
    }
}

var gShadowThick = 3;
function UI_CreateDropShadow( e, class_name )
{
	if ( !e ) return;
	e.style.margin = '0px';
			
	var shadowOffset = 2;
    for( var step = 0; step < 2; ++step )
    {
		var sh = document.createElement( 'DIV' );
		var ms = sh.style;
    
		if ( class_name )
		{
	    	sh.className = class_name;
		}
		else
		{
	    	ms.backgroundColor = '#888888';
		    ms.opacity = '0.50';
		    ms.MozOpacity = '0.50';
	    	ms.filter = 'alpha(opacity=50)';
		}
	
		ms.position = 'absolute';
//		ms.zIndex = parseInt( e.style.zIndex ) + 3;
		ms.zIndex = e.style.zIndex ? e.style.zIndex : '10';
		ms.display = 'block';
		ms.border = '0px';
		ms.padding = '0px';
		ms.margin = '0px';
		ms.overflow = 'hidden';
		if (step) // vert
		{
			var bw = Math.floor((e.offsetWidth - e.clientWidth)*0.5);
	    	ms.left = (e.clientWidth + bw) + 'px';
		    ms.top = (shadowOffset - bw) + 'px';
		    ms.width = gShadowThick + 'px';
	    	ms.height = (e.offsetHeight - shadowOffset) + 'px';
		}
		else // horiz
		{
			var bw = Math.floor((e.offsetHeight - e.clientHeight)*0.5);
		    ms.left = (shadowOffset - bw) + 'px';
	    	ms.top = (e.clientHeight + bw) + 'px';
		    ms.width = (e.offsetWidth + gShadowThick - shadowOffset) + 'px';
		    ms.height = gShadowThick + 'px';
		}

		e.appendChild( sh );
    }
}

window.onresize = UI_WindowOnResize;

var gUI_OverlayBack;
var gUI_Overlay;

function UI_ShowOverlay( bShow, html, overlayClass )
{
    if ( gUI_OverlayBack )
    {
		gUI_OverlayBack.style.display = 'none';
		var parent_node = gUI_OverlayBack.parentNode;
		if ( parent_node ) parent_node.removeChild( gUI_OverlayBack );
		gUI_OverlayBack = undefined;
    }
    
	if ( gUI_Overlay )
	{
		gUI_Overlay.innerHTML = '';
		gUI_Overlay.style.display = 'none';
		var parent_node = gUI_Overlay.parentNode;
		if ( parent_node ) parent_node.removeChild( gUI_Overlay );
		gUI_Overlay = undefined;
	}

	if ( bShow )
	{   
	    var bg = document.createElement('DIV');
		bg.className 		= 'overlay_back';
    	bg.innerHTML 		= '&nbsp;';
		bg.id				= 'zoo_ui_overlay_back';

		document.body.appendChild( bg );
		
		if ( gIEVersion >= 5.5 && gIEVersion < 7 )
		{
			bg.style.position = 'absolute';
		}
		
    	UI_SetAbsolutePos( bg, undefined, false );
		
		gUI_OverlayBack = bg;

	    var fm = document.createElement('DIV');
		if ( !overlayClass )
		{
			overlayClass = 'overlay';
		}
		fm.className 		= overlayClass;
		fm.id				= 'zoo_ui_overlay';	
		
//		fm.innerHTML = '<TABLE border=0 cellpadding=0 cellspacing=0 style="margin:0px;"><TR><TD>' + html + '</TD></TR></TABLE>';
		fm.innerHTML = html;
		
		document.body.appendChild( fm );
	
    	UI_SetAbsolutePos( fm, undefined, true );
    
		gUI_Overlay = fm;
	}
}

function UI_WindowOnResize()
{
	if ( gUI_OverlayBack )
	{
		var p1 = gUI_OverlayBack.parentNode;
		if ( p1 && p1 == document.body ) p1 = undefined;	
		UI_SetAbsolutePos( gUI_OverlayBack, p1, false );
	}
	if ( gUI_Overlay )
	{
		var p2 = gUI_OverlayBack.parentNode;
		if ( p2 && p2 == document.body ) p2 = undefined;	
		UI_SetAbsolutePos( gUI_Overlay, p2, true );
	}
}

function UI_SetAbsolutePos( e, frame, bCenter )
{
    var x = 0;
    var y = 0;
    var w = 1;
    var h = 1;
    
    if ( frame )
    {
		x = UI_GetAbsolutePos_Left( frame ) + 1; // +1?
		y = UI_GetAbsolutePos_Top( frame ) + 1;
		w = frame.offsetWidth - 2; // -2?
		h = frame.offsetHeight - 2;
    }
    else
    {
		w = UI_GetDocWidth();
		h = UI_GetDocHeight();
    }

	if ( bCenter )
	{
		//alert( 'x=' + e.offsetLeft + ',y=' + e.offsetTop + ',w=' + e.offsetWidth + ',h=' + e.offsetHeight );
	    e.style.left = Math.max( 0, x + Math.floor((w-e.offsetWidth)*0.5)) + 'px';
    	e.style.top = Math.max( 0, y + Math.floor((h-e.offsetHeight)*0.5)) + 'px';
	}
	else
	{
		e.style.left 	= Math.max( 0, x ) + 'px';
		e.style.top 	= Math.max( 0, y ) + 'px';
		e.style.width 	= w + 'px';
		e.style.height 	= h + 'px';
	}
}

function UI_ShowPopup( bShow, txt, maxW, evt, className )
{
    var e = GetElement( 'tmp_popup' );
    if ( e )
	{
		e.style.visibility = 'hidden';
		e.style.width = '0px';
		e.innerHTML = '';
		if ( e.parentNode )
		{
			e.parentNode.removeChild( e );
		}
	}
	
	if ( bShow )
	{
		if ( !evt ) evt = window.event;
		if ( !maxW ) maxW = 300;

		var elm  = undefined;
		if ( evt.srcElement )  elm = evt.srcElement;
		else if ( evt.target ) elm = evt.target;

		if ( elm )
		{
			if ( !elm.onmouseout )
			{
				elm.onmouseout = function() { UI_ShowPopup( false ); }
			}
		}

		var x =  UI_MouseGetX( evt ) + 8;
		var y =  UI_MouseGetY( evt ) + 8;
		
		e = document.createElement( 'DIV' );
		e.id = 'tmp_popup';
		
		e.style.left = x + 'px';
		e.style.top = y + 'px';
		e.style.visibility = 'hidden';
		
		e.className	= className ? className : 'popup';
		
		e.innerHTML = txt;

    	document.body.appendChild( e );
		
		if ( e.offsetWidth > maxW )
 		{
			e.style.width = maxW + 'px';
		}
		
		UI_FitOnScreen( e, x, y );
    
		e.style.visibility = 'visible';
    
		e.onmousemove = function() { UI_ShowPopup( false ); }
    
		UI_CreateDropShadow( e );
	}
	return e;
}

var gUI_PopupMenu;
var gUI_PopupMenuTimer;
var gSeparator = '<DIV style="padding-top:4px; padding-bottom:4px;"><DIV style="border-bottom: 1px solid #000000; width:auto;"><DIV style="width:1px; height:1px;"></DIV></DIV></DIV>';

function UI_ShowPopupMessage( bShow, txt, vAlign, hAlign, displayTime, parent, className )
{
	UI_PopupMenuTimer_Stop();

	if ( bShow && !parent )
	{
		var pname = 'ze_uipopup_parent';
		parent = GetElement( pname );
		if ( !parent )
		{
			parent = document.createElement( 'DIV' );
			document.body.appendChild( parent );

			parent.id = pname;
			parent.style.position = 'absolute';
			parent.style.left 	= Math.floor(document.body.scrollWidth*0.5) + 'px';
			parent.style.top 	= Math.floor(document.body.scrollHeight*0.5) + 'px';
//			parent.style.width	= '1px';
//			parent.style.height	= '1px';
		}
	}

	UI_ShowPopupMenu( bShow, txt, parent, vAlign, hAlign, className, undefined, undefined, true );
	if ( bShow )
	{	
		UI_PopupMenuTimer_Start( displayTime );
	}
}

UI_PopupMenu.mMenus = new Array();
UI_PopupMenu.Show = function( obj, bShow )
{
	if ( !(obj&&obj.mContainer) ) { return; }
	if ( bShow )
	{
		for ( var i = 0; i < UI_PopupMenu.mMenus.length; ++i )
		{
			var curr = UI_PopupMenu.mMenus[i];
			if ( curr && curr != obj && curr.mbActive )
			{
				curr.mContainer.style.visibility = 'hidden';
//				curr.mContainer.style.display = 'none';
				curr.mbActive = false;
			}
		}
	}
	obj.mContainer.style.visibility = bShow ? 'visible' : 'hidden';
//	obj.mContainer.style.display = bShow ? '' : 'none';
	obj.mbActive = bShow;
};

UI_PopupMenu.Remove = function( obj )
{
	if ( !obj ) { return; }
	for ( var i = 0; i < UI_PopupMenu.mMenus.length; ++i )
	{
		var curr = UI_PopupMenu.mMenus[i];
		if ( curr && curr == obj )
		{
			UI_PopupMenu.mMenus[i] = undefined;
			break;
		}
	}		
};

UI_PopupMenu.mMenus = new Array();


//---------------------------------------------------------------------------------//
function UI_PopupMenu( parentElement, placementElement )
{
	if ( !parentElement )
	{
		return;
	}

	if ( !placementElement )
	{
		placementElement = parentElement;
	}
	UI_PopupMenu.mMenus.push( this );
	
	var thing = this;
		
	this.mContainer = document.createElement( 'DIV' );
//	this.mContainer.style.visibility = 'hidden';
	this.mPlacementElement = placementElement;
	this.mParent = parentElement;
	if ( this.mParent.onmouseover )
	{
		this.mParent.mOnMouseOver = this.mParent.onmouseover;
//		DebugOutput( 'Clearing onmouseover for parent:' + this.mParent.id );
	}
	this.mParent.onmouseout		= function() { thing.StartTimer(); };					
	this.mParent.onmouseover 	= function() { thing.ClearTimer(); thing.Show(true); };
	document.body.appendChild( this.mContainer );	
		
	this.mContainer.onmouseover = function() 
	{ 
		thing.OnMouseOver();
	};
	
	this.mContainer.onmouseout 	= function() 
	{ 
		thing.OnMouseOut();
	}
	
	this.mContainer.onclick 	= function() { return thing.OnClick() };
	
	
	return thing;
}

UI_PopupMenu.prototype.OnMouseOver = function()
{
	this.ClearTimer(); 
	this.Show(true); 
};

UI_PopupMenu.prototype.OnMouseOut = function() 
{ 
	if ( this.mTimer ) { return; }
	this.StartTimer(); 
				
}

UI_PopupMenu.prototype.OnClick = function()
{
	var menu=this;
	window.setTimeout( function() { menu.Show(false); }, 10 ); 
	return true;
};
	
UI_PopupMenu.prototype.StartTimer = function( secs )
{
	if ( !secs )
	{
		secs = 0.5;
	}
	secs *= 1000;
	this.ClearTimer();
	var menu = this;
	this.mTimer = window.setTimeout( function(){ menu.Show(false);}, secs );
};
	
UI_PopupMenu.prototype.ClearTimer = function()
{
    if ( this.mTimer )
   	{
		window.clearTimeout( this.mTimer );
		this.mTimer = undefined;
   	}
};
	
UI_PopupMenu.prototype.SetData = function( data )
{
	if ( (typeof data) == 'object' )
	{
		if ( data.tagName == 'TABLE' && !data.style.margin )
		{
			data.style.margin = '0px'; // tables are margin auto so cancel out so the div doesn't expand to fill the entire space
		}
		data.style.display = '';
		this.mContainer.appendChild( data );
	}
	else
	{
		// if txt contains a '<sep>' tag, replace it with a menu item separator
		data = data.replace( /<sep>/g, gSeparator );
		this.mContainer.innerHTML = data;
		var child = this.mContainer.firstChild;
		if ( child )
		{
			if ( child.tagName == 'TABLE' && !child.style.margin )
			{
				child.style.margin = '0px'; // tables are margin auto so cancel out so the div doesn't expand to fill the entire space
			}
		}
	}
		
	// don't want div to be larger than the element it 'contains'
	if ( this.mContainer && this.mContainer.firstChild )
	{
		var child = this.mContainer.firstChild;
		if ( child.tagName == 'TABLE')
		{
			this.mContainer.style.width 	= child.offsetWidth + 'px';
			this.mContainer.style.height 	= child.offsetHeight + 'px';
		}
	}
};
	
// vAlign: 0 = top, 1 = middle, 2 = bottom
// hAlign: 0 = left, 1 = center, 2 = right
UI_PopupMenu.prototype.Format = function( className, vAlign, hAlign, vAlignMe, hAlignMe )
{
	var m = this.mContainer;
	var p = this.mPlacementElement;
	var x = UI_GetAbsolutePos_Left( p );
	var y = UI_GetAbsolutePos_Top( p );
	if ( vAlign == 1 ) // middle
	{
		y += Math.floor( (p.offsetHeight - m.offsetHeight) * 0.5 );
	}
	else if ( vAlign == 2 ) // bottom
	{
		y += p.offsetHeight;
	}
	else
	{
		y -= m.offsetHeight;
	}
   
	if ( hAlign == 1 ) // center
	{
		x += Math.floor( (p.offsetWidth - m.offsetWidth) * 0.5 );
	}
	else if ( hAlign == 2 ) // right
	{
		if ( hAlignMe == 2 )
		{
			x -= m.offsetWidth + gShadowThick;
		}
		else
		{
			//
		}
	}
	else
	{
		if ( hAlignMe == 0 )
		{
		}
		else
		{
			x += p.offsetWidth;
		}
	}
   
   	m.className		= className ? className : 'popup_menu';
   	m.style.position='absolute';
	m.style.left 	= x + 'px';
	m.style.top 	= y + 'px';
		    
//	UI_FitOnScreen( m, x, y );
	UI_CreateDropShadow( m );
		
	// REVISIT -- fixup separator widths, if any separators
};
	
UI_PopupMenu.prototype.Show = function( bShow )
{
	var d = new Date();
	if ( bShow && !this.mTimeStart ) { this.mTimeStart = d.getTime(); }
	UI_PopupMenu.Show( this, bShow );
};
	
UI_PopupMenu.prototype.Delete = function()
{
	this.ClearTimer();
	if ( this.mContainer )
	{
		this.Show( false );
	}
	if ( this.mContainer )
	{
		this.mContainer.parentNode.removeChild( this.mContainer );
	}
		
	UI_PopupMenu.Remove( this );
		
	// restore parent's functions
	if ( this.mParent &&  this.mParent.mOnMouseOver )
	{
		this.mParent.onmouseover = this.mParent.mOnMouseOver;
	}
	this.mParent = undefined;
	this.mContainer = undefined;
};

//---------------------------------------------------------------------------------//
UI_PopupMessage.prototype = new UI_PopupMenu();
UI_PopupMessage.prototype.constructor = UI_PopupMessage;
function UI_PopupMessage( placementElement )
{
	UI_PopupMenu.call( this, placementElement );

	this.mParent.onmouseout 	= function(){}; // do nothing
	this.mParent.onmouseover 	= function(){}; // do nothing
}

UI_PopupMessage.prototype.OnMouseOver = function()
{
	if ( this.mTimer ) { return; }
	
	UI_PopupMenu.prototype.OnMouseOver.call( this );	
};

UI_PopupMessage.prototype.OnMouseOut = function() 
{ 
	var t = new Date();
	t = t.getTime();
	if ( (!this.mTimeStart || (t-this.mTimeStart)>500) )
	{
		var m = this;
		window.setTimeout( function() { var menu=m; menu.Show(false); }, 10 ); 
	}
};
//---------------------------------------------------------------------------------//


// vAlign: 0 = top, 1 = middle, 2 = bottom
// hAlign: 0 = left, 1 = center, 2 = right
function UI_ShowPopupMenu( bShow, txt, parent, vAlign, hAlign, className, vAlignMe, hAlignMe, bMessage, formatParent )  // REVISIT -- need to finish the vAlginMe and hAlignMe
{	
	UI_PopupMenuTimer_Stop();
	
	if ( gUI_PopupMenu )
	{
//	    gUI_PopupMenu.parentNode.removeChild( gUI_PopupMenu );
//		gUI_PopupMenu = null;

		gUI_PopupMenu.Delete();
	 	delete gUI_PopupMenu;
		gUI_PopupMenu = undefined;
	}
		
	if ( bShow && parent )
	{
		gUI_PopupMenu = bMessage ? new UI_PopupMessage( parent ) : new UI_PopupMenu( parent, formatParent );
		gUI_PopupMenu.SetData( txt );
		gUI_PopupMenu.Format( className, vAlign, hAlign, vAlignMe, hAlignMe );
		gUI_PopupMenu.Show( true );
	}
	return gUI_PopupMenu;
}

function UI_PopupMenuItemOnMouseOver( e ) // Basic handling for popup menu items that use the popup_menu css class
{
	if ( e )
	{
		e.className = 'wg_popup_items_over ' + e.className;
	}
}

function UI_PopupMenuItemOnMouseOut( e )   // Basic handling for popup menu items that use the popup_menu css class
{
	if ( e )
	{
		var curClasses = e.className.split( ' ' );
		e.className = '';
		for ( var i=0;i<curClasses.length;++i ) 
		{
			if ( !curClasses[i].match( /_over/ ) ) 
			{
				e.className += ' ' + curClasses[i];
			}
		}
	}
}


function UI_PopupMenuTimer_Stop()
{
    if ( gUI_PopupMenuTimer )
    {
		window.clearTimeout( gUI_PopupMenuTimer );
		gUI_PopupMenuTimer = 0;
    }
}

function UI_PopupMenuTimer_Start( secs )
{
	if ( !secs )
	{
		secs = 1;
	}
	secs *= 1000;
	
	UI_PopupMenuTimer_Stop();
    
    if ( gUI_PopupMenu )
	{
		gUI_PopupMenuTimer = window.setTimeout( 'UI_ShowPopupMenu(false)', secs );
	}
}

function UI_TabOnMouseOver( name, tab )
{
    var o = GetElement( 'tabs-'+name );
    if (!o) return;
    if (!o.tabs_object) return;
    o.tabs_object.OnMouseOver( tab );
}

function UI_TabOnMouseOut( name, tab )
{
    var o = GetElement( 'tabs-'+name );
    if (!o) return;
    if (!o.tabs_object) return;
    o.tabs_object.OnMouseOut( tab );
}

function UI_TabClickedHandler( name, tab )
{
    var o = GetElement( 'tabs-'+name );
    if (!o) return;
    if (!o.tabs_object) return;
    o.tabs_object.tab_clicked( tab );
}

function UI_TabPostRender( name )
{
    var o = GetElement( 'tabs-'+name );
    if (!o) return;
	var obj = o.tabs_object;
    if (!o.tabs_object) return;
	o.tabs_object.PostRender();
}

function UI_TabsCreate( name, width, heading )
{
    this.main_div = document.createElement('DIV');
    this.name = name;
    this.main_div.id = 'tabs-'+name;
    this.main_div.tabs_object = this;
    this.cur_tab = 0;
    
	this.mbUniformHeight = true;
		
	this.data_w = 0;
	this.data_h = 0;
	this.mHeading = heading ? heading : '';
    
    var s = this.main_div.style;
    s.textAlign = 'left';
    s.padding = '6px';
    if (width) s.width = width+'px';

    this.tabs = new Array();
    
    this.ReplaceDiv = function( _title, _div )
    {
		var o = document.createElement('DIV');
		var p = _div.parentNode;
		p.insertBefore( this.main_div, _div );
		p.removeChild( _div );
		o.appendChild( _div );
		_div.style.padding = this.main_div.style.padding; // REVISIT -- good idea or not?
		
//		this.data_w = _div.offsetWidth;
//		this.data_h = _div.offsetHeight;
		this.tabs.push( { title: _title, div: o } );
    };

    this.AddNewTab = function( _title, html, min_height, el, subTabs )
    {
		var o = document.createElement('DIV');
		if ( subTabs )
		{
			el = subTabs.main_div;
		}
		
		if ( html )
		{
			o.innerHTML = html;
		}
		else
		if ( el )
		{
			o.appendChild( el );
			var w = el.offsetWidth;
			var h = el.offsetHeight;
			if ( w > o.offsetWidth ) 	{ o.style.width = w.toString() + 'px'; }
			if ( this.mbUniformHeight ) { if ( h > o.offsetHeight ) 	{ o.style.height = h.toString() + 'px'; } }
		}
		this.tabs.push( { title:_title, div:o, subs:subTabs } );
		if (min_height && min_height>this.data_h) this.data_h = min_height;
		
		var w = o.offsetWidth;
		var h = o.offsetHeight;
		if ( w > this.data_w ) { this.data_w = w; }
		if ( h > this.data_h ) { this.data_h = h; }
    };
    
    this.Render = function()
    {
		var t = '';
		if ( this.mHeading )
		{
			t += '<DIV style="text-align:center;padding:4px;">'+this.mHeading+'</DIV>';
		}

		t += '<TABLE border=0 cellspacing=0 cellpadding=0><TR>';

		t += '<TD><TABLE cellspacing=0 cellpadding=0 border=0 width="100%"><TR><TD class="wg_tab_empty">&nbsp;</TD>';
	
		var tabStyle = ' style="width:' + Math.round(1/this.tabs.length*100) + '%;"';
		for( var i=0; i<this.tabs.length; i++ )
		{
	    	t += '<TD id="tab-'+this.name+'-'+i+'"'+tabStyle+'><DIV onmouseover="UI_TabOnMouseOver(\''+this.name+'\','+i+');" onmouseout="UI_TabOnMouseOut(\''+this.name+'\','+i+');" onClick="UI_TabClickedHandler(\''+this.name+'\','+i+')">'+this.tabs[i].title+'</DIV></TD>';
			t += '<TD class="wg_tab_empty">&nbsp;</TD>';
		}

		t += '</TR></TABLE></TD>';

		t += '</TR>';
		t += '<TR><TD id="data-'+this.name+'" class="wg_tab_body"></TD></TR></TABLE>';

		this.main_div.innerHTML = t;
	
		var o = GetElement( 'data-'+this.name );
		if (!o) return;

		var data = document.createElement('DIV');
		o.appendChild( data );
		var s = data.style;
	   	s.overflow = 'visible'; // 'auto';
		s.padding = '2px';
		for( var i=0; i<this.tabs.length; i++ )
		{
    		var tab = this.tabs[i];
	    	data.appendChild( tab.div );
		    tab.div.style.display = 'none';
			if ( tab.subs )
			{
				tab.subs.Render();
			}
		}
		
		if ( IsIE() )
		{
			window.setTimeout( 'UI_TabPostRender("'+name+'")', 1 );
		}
		else
		{
			this.PostRender();
		}
    };
	
	this.GetHeight = function ()
	{
		var padding = 16; // REVISIT -- data element and main div padding
		var border = 2; //?
		var h = this.data_h ? (this.data_h+padding+border) : this.main_div.offsetHeight;
		var el = GetElement( 'tab-'+this.name+'-0' ); // height of the tabs
		if ( el )
		{
			h += el.offsetHeight;
		}
		return h;
	};
	
	this.PostRender = function()
	{
		var o = GetElement( 'data-'+this.name );
		if (!o) return;
		for( var i=0; i<this.tabs.length; i++ )
		{
    		var tab = this.tabs[i];
		    tab.div.style.display = 'block';
			var w = tab.div.offsetWidth;
			var h = tab.div.offsetHeight;
			if ( tab.subs )
			{
				tab.subs.PostRender();
				w = tab.subs.data_w;
				h = tab.subs.GetHeight();
			}
			if ( w > this.data_w ) 	{ this.data_w = w; }
			if ( h > this.data_h ) 	{ this.data_h = h; }
		    tab.div.style.display = 'none';
		}
		this.show_tab( 0 );
	
		if ( o.offsetWidth > this.data_w ) { this.data_w = o.offsetWidth; }
		if ( o.offsetHeight > this.data_h ) { this.data_h = o.offsetHeight; }
		var newW = (this.data_w+12)+'px'; // REVISIT -- account for padding, store padding in object
		var newH = (this.data_h+4)+'px';
		var s = o.style;
		if (this.data_w) s.width = newW;
//		DebugOutput( this.mbUniformHeight );
		if ( this.mbUniformHeight ) { if (this.data_h) s.height = newH; }
		
		// now make sure all tabs are the same size
		
		//DebugOutput( newW );
		//DebugOutput( newH );
	};
    
    this.tab_clicked = function( n )
    {
		if (n<0 || n>=this.tabs.length) return;
		this.show_tab( n );
    };
	
    this.OnMouseOver = function( n )
    {
		if (n<0 || n>=this.tabs.length || n == this.cur_tab) return;
	    var o = GetElement( 'tab-'+this.name+'-'+n );
		if (o)
	    {
			o.className = 'wg_tab_over';
		}
    };
	
    this.OnMouseOut = function( n )
    {
		if (n<0 || n>=this.tabs.length || n == this.cur_tab) return;
	    var o = GetElement( 'tab-'+this.name+'-'+n );
		if (o)
	    {
			o.className = 'wg_tab';
		}
    };

    this.show_tab = function( n )
    {
		if (n<0 || n>=this.tabs.length) return;
		this.cur_tab = n;

		for( var i=0; i<this.tabs.length; i++ )
		{
	    	var tab = this.tabs[i];
			var subs;
			if ( tab.subs )
			{
				subs = tab.subs
			}
		    var s = tab.div.style;
		    if (i==n)
	    	{
				s.display = 'block';
				if ( tab.div.offsetWidth < this.data_w )
				{
					s.width = (this.data_w+4) + 'px'; // REVISIT -- make sure the data bodies are the correct size
				}
				if ( subs )
				{
					subs.show_tab(0);
				}
		    }
		    else
	    	{
				if ( subs )
				{
					// hide subs?
				}
				s.display = 'none';
	    	}
	
		    var o = GetElement( 'tab-'+this.name+'-'+i );
		    if (o)
	    	{
				o.className = (i==n) ? 'wg_tab_sel' : 'wg_tab';
	    	}
		}
    };
    
}

function UI_GetHTML_MenuItem( index, txt, onclickTxt, bEnabled )
{
	if ( bEnabled != false ) { bEnabled = true; }
	if ( onclickTxt == undefined )
	{
		onclickTxt = '';
	}
	else
	if ( onclickTxt != '' )
	{
		onclickTxt = ' onclick="' + onclickTxt + '"';
	}
	var html = '';
	if ( bEnabled ) 
	{	
		var id = 'wg_menuitem' + index.toString();
		html += '<DIV id="' + id  + '" class="wg_popup" onmouseover="var e=GetElement(\''+ id +'\'); UI_PopupMenuItemOnMouseOver(e);" onmouseout="var e=GetElement(\''+ id +'\'); UI_PopupMenuItemOnMouseOut(e);"' + onclickTxt + '>' + txt + '</DIV>';
	}
	else
	{
		html += '<DIV class="wg_popup_disabled wg_popup">' + txt +'</DIV>'
	}	
	return html;
}

function UI_ShowGenericErrorPopup()
{
	UI_ShowPopupMessage( true, '<TABLE><TR><TD style="vertical-align:top; padding-right:4px;">' + GetHTML_StatusIcon(3) + '</TD><TD style="vertical-align:middle;">Unexpected error.<BR>Please try again later.</TD></TR></TABLE>', 1, 1, 3 );
}

function UI_ShowRequestTimeoutPopup()
{
	UI_ShowPopupMessage( true, '<TABLE><TR><TD style="vertical-align:top; padding-right:4px;">' + GetHTML_StatusIcon(3) + '</TD><TD style="vertical-align:middle;">Request could not be completed.<BR>Please try again later.</TD></TR></TABLE>', 1, 1, 3 );
}

function UI_ScrollToBottom(div_name)
{
	var o = div_name;
	if ( (typeof o) == 'string' )
	{
	    o = GetElement(o);
    }
   	if (!o) return;
    o.scrollTop = o.scrollHeight;
}

function UI_ScrollTo( scroll_div, el, bOnlyIfNeeded )
{
	if (!(scroll_div&&el)) return;
	var o = scroll_div;
	if ( (typeof o) == 'string' )
	{
	    o = GetElement(o);
    }
   	if (!o) return;
	
	var e0 = el.offsetTop;
	var scroll_to = e0;
	
	if (bOnlyIfNeeded)
	{
    	var e1 = e0 + el.offsetHeight;
	    var s0 = o.scrollTop;
	    var s1 = s0 + o.clientHeight;
	    
	    if (e0<s0)	// above
	    {
			scroll_to = e0;
	    }
	    else
    	if (e1>s1)	// below
    	{
			scroll_to = s0 + ( e1 - s1 ) + 2;	// shift so element bottom is aligned with scroll bottom
    	}
    	else
    	{
			return;
    	}
	}
	
	o.scrollTop = scroll_to;
}

function UI_ShowYesNoForm( bShow, bSubmit, title, desc, url, sendTxt, completionFunc )
{
	if ( bShow === undefined ) 	{ bShow = true; }
	if ( !completionFunc )		{ completionFunc = UI_PostHandler_Complete; }
	
	var html = '';
	if ( bSubmit )
	{
		var bDoGenericError = true;
		if ( url && sendTxt )
		{
			var rr = RemoteRequest.NewRequest( url, sendTxt, {mCompletion:completionFunc, mTimeout:UI_ShowRequestTimeoutPopup}, false );
			bDoGenericError = !(rr && rr.Issue()) ? true : false;
		}
		if ( bDoGenericError )	{ UI_ShowGenericErrorPopup(); }
	}
	
	if ( bShow )
	{
		html = GetHTML_YesNoForm( title, desc, url, sendTxt, completionFunc );
	}

	UI_ShowOverlay( bShow, html );
	
	var el = GetElement('ze_yes_no_form_btn_yes');
	if ( el )
	{
		el.onclick = function() {
			var thingy = this;
			window.setTimeout( function(){ thingy.disabled = true; }, 10 );
			UI_ShowYesNoForm( false, true, undefined, undefined, url, sendTxt, completionFunc );
		};
	}
}

function GetHTML_YesNoForm( title, desc, url, sendTxt, completionFunc )
{
	if ( !(title&&desc&&url&&sendTxt) ) { return; }

	var html = '';
	html += '<TABLE class="yes_no_form" border=0 cellspacing=0 cellpadding=0>';
	html += 	'<TR><TH>'+title+'</TH></TR>';
	html += 	'<TR><TD>'+desc+'</TD></TR>';
	html += 	'<TR><TD><INPUT id="ze_yes_no_form_btn_yes" type="button" value=" Yes ">&nbsp;<INPUT type="button" value=" No " onclick="UI_ShowYesNoForm(false);"></TD></TR>';
	html += '</TABLE>';
	
	return html;
}

function UI_ShowReportForm( bShow, bReport, username, timeStr, refid, url )
{
	if ( bShow === undefined ) { bShow = true; 	}
	
	var html = '';
	if ( bReport )
	{
		var bDoGenericError = true;
		var el = GetElement( 'report_note' );
		if ( el && url )
		{
			var curState = el.value;
			if ( curState )
			{
				curState = StringEncodeJS( curState );
			}
			else
			{
				curState = '';
			}
			
			var reqTxt = 'report=1&refid=' +refid+ '&note=' + curState;
			var rr = RemoteRequest.NewRequest( url, reqTxt, {mCompletion:UI_PostHandler_Complete, mTimeout:UI_ShowRequestTimeoutPopup}, false );
			bDoGenericError = !(rr && rr.Issue()) ? true : false;
		}

		if ( bDoGenericError )	{ UI_ShowGenericErrorPopup(); }
	}
	
	if ( bShow )
	{
		html = GetHTML_ReportForm( username, timeStr, refid, url );
	}
	UI_ShowOverlay( bShow, html );
}


function GetHTML_ReportForm( username, timeStr, refid, url )
{	
	var html = '';
	if ( !timeStr ) { timeStr = ''; }
	
	if ( username && refid )
	{
		html += '<TABLE class="forum_form" border=0 cellspacing=4 cellpadding=4 style="padding:8px;margin:0px;">';
		html += 	'<TR><TD colspan=2 class="forum_form_title">Report Abusive Message</TD></TR>';
		html += 	'<TR><TD colspan=2 style="text-align:left;">Report message by ' + username + (timeStr ? (' made on ' + timeStr) : '') + '</TD></TR>';
		html += 	'<TR><TD style="text-align:right;vertical-align:middle;">Complaint:</TD><TD style="text-align:left;"><INPUT type="text" id="report_note" size="50" maxlength="200"></TD></TR>';
		html += 	'<TR><TD colspan=2 style="text-align:center;"><INPUT type="button" name="SubmitIt" value=" Report " onclick="UI_ShowReportForm(false,true,\''+username+'\',\''+timeStr+'\','+refid+',\''+url+'\');">&nbsp;<INPUT type="button" value=" Cancel " onclick="UI_ShowReportForm(false);"></TD></TR>';
		html += '</TABLE>';
	}
	return html;
}

function UI_PostHandler_Complete( response )
{
	var args = response ? response.split( '&' ) : [];
	var icon = GetHTML_StatusIcon(3);
	var val = 'Unexpected error.<BR>Please try again later.';
	if ( args && args[0] && args[0] == 'ze_ok' )
	{
		var val = '';
		for ( var i = 1; i < args.length; ++i )
		{
			var vals = args[i];
			vals = vals.split( '=' );
			var key = vals[0];
			val = vals[1];
			if ( key == 'msg_ok' )
			{
				icon = GetHTML_StatusIcon(1);
				break;
			}
			else
			if ( key == 'msg_err' )
			{
				break;
			}
			else
			if ( key == 'msg_warn' )
			{
				icon = GetHTML_StatusIcon(2);
				break;
			}
		}
		
	}
	
	var msg = '<TABLE style="padding:4px; margin:0px;"><TR><TD style="vertical-align:top; padding-right:4px;">' +icon+ '</TD><TD style="vertical-align:middle;">' +val+ '</TD></TR></TABLE>';
	UI_ShowPopupMessage( true, msg, 1, 1, 3 );
};

function UI_PostHandler_Timeout( response )
{
	UI_ShowGenericErrorPopup();
};

/*
function UI_GetHTML_Table( cols, data, tblAttrs)
{
	if ( !(cols&&data) ) 	{ return '' };
	
	if ( !tblAttrs ) 		{ tblAttrs = ' border=0 cellpadding=0 cellspacing=0 width="100%"'; }
	
	var bgc = 0;
	var html = '';
	html += '<TABLE class="forum_table"'+tblAttrs+'>';

	//--- Cols ---//
	var colData = '';
	for( var i=0; i < cols.length; ++i )
	{
		if ( !col ) { continue; }
		
		var title = $col->{title};
		next unless $title;
				
		my $cl = $col->{class};
		$cl = $cl ? " class=\"$cl\"" : '';
		
		my $att = $col->{attrs};
		$att = '' unless $att;
		
		my $style = $col->{style};
		$style = $style ? " style=\"$style\"" : '';
		$colData .= "<TD$cl$style $att>$title</TD>";
	}
	
	html += '<TR class="forum_table_heading">'+colData+'</TR>';
	
	//--- Rows ---//
	if ( data && data.length )
	{		
		foreach my $row (@$data)
		{
			next unless $row;
			
			my $rowData = '';
			foreach my $entry (@$row)
			{
				my $stuff = $entry->{entry};
				next unless $stuff;
				
				my $cl = $entry->{class};
				$cl = $cl ? " class=\"$cl\"" : '';
				
				my $style = $entry->{style};
				$style = $style ? " style=\"$style\"" : '';
				
				my $att = $entry->{attrs};
				$att = '' unless $att;
				
				$rowData .= "<TD$cl$style $att>$stuff</TD>";
			}
			
			if ( $rowData )
			{
				my $cl = 'forum_table_entry_' . ($bgc?'0':'1');
				html += '<TR class="'+cl+'">'+rowData+'</TR>';

				bgc = !$gc;
			}
		}
	}

	html +='</TABLE>';
	return html;
}
*/

function UI_CreateMouseCapture( el )
{
    this.b_capture = 1;
    this.parent = el;
    this.b_autorelease = 1;
    
    this.handler_stop_event = function(evt) 
    { 
    	Event_Cancel(evt);
		return false; 
    };

    this.mouse_move_event = function(ev)
    {
		if (!this.b_capture) return;
		this.parent.onmousemove(ev);
    	Event_Cancel(ev);
		return false;
    };
    
    this.get_handler_move_event = function()
    {
		var obj = this;
		return function(evt) { return obj.mouse_move_event(evt); }
    };

    this.handler_move_event = this.get_handler_move_event();

    this.mouse_release_event = function(ev)
    {
		if (!this.b_capture) return;
		if (this.b_autorelease) this.release_mouse_capture();
		this.parent.onmouseup(ev);
		Event_Cancel(ev);
		return false;
    };

    this.get_handler_release_event = function()
    {
		var obj = this;
		return function(evt) { return obj.mouse_release_event(evt); }
    };

    this.handler_release_event = this.get_handler_release_event();

    this.set_mouse_capture = function()
    {
		if ((typeof this.parent.setCapture) != 'undefined')
		{
	    	this.parent.setCapture();
		    return;
		}
		this.b_capture = 1;
		document.addEventListener("mousemove",this.handler_move_event,true);
		document.addEventListener("mouseover",this.handler_stop_event,true);
		document.addEventListener("mouseout",this.handler_stop_event,true);
		document.addEventListener("mouseenter",this.handler_stop_event,true);
		document.addEventListener("mouseleave",this.handler_stop_event,true);
		document.addEventListener("mouseup",this.handler_release_event,true);
    };

    this.release_mouse_capture = function()
    {
		if (!this.b_capture) return;
		if ((typeof this.parent.releaseCapture)!='undefined')
		{
	    	this.parent.releaseCapture();
		    return;
		}
		this.b_capture = 0;
        document.removeEventListener("mousemove",this.handler_move_event,true);
		document.removeEventListener("mouseover",this.handler_stop_event,true);
		document.removeEventListener("mouseout",this.handler_stop_event,true);
		document.removeEventListener("mouseenter",this.handler_stop_event,true);
		document.removeEventListener("mouseleave",this.handler_stop_event,true);
		document.removeEventListener("mouseup",this.handler_release_event,true);
    };
    
    this.set_mouse_capture();
};
