
/**
 * Cross-browser object oriented control wrapper library.
 *
 * Some stuff is taken from:
 *    http://www.quirksmode.org
 *    http://evolt.org
 *    http://www.faqts.com/knowledge_base/view.phtml/aid/13562
 */

window.jooxbrLoaded = false; // we gonna load for long

//----- Auxilary functions -----

function def( val, defval )
{
	return val == null ? defval : val;
}

function rng( val, minval /* = null */, maxval /* = null */ )
{
	if( minval != null && val < minval )
	{
		val = minval;
	}
	if( maxval != null && val > maxval )
	{
		val = maxval;
	}
	return val;
}

/**
 * Returns javascript object for the element with the specified id and of the specified parent window
 *
 * @param id {String}
 * @param parent {Object}		Window reference
 * @return HTMLElement
 */
function el( id, parent )
{
	if( typeof( id ) == 'object' )
	{
		return id;
	}
	parent = def( parent, window );
	if( parent.document.getElementById )
	{
		return parent.document.getElementById( id );
	}
	else if( parent.document.all )
	{
		return parent.document.all[ id ];
	}
	else if( parent.document.layers )
	{
		var out = parent.document.layers[ id ];
		out.style = out;
		return out;
	}
	return null;
}

/**
 * Alias to the el() function
 */
var _ = el;

function els( name, parent )
{
	parent = def( parent, window );
	return parent.document.getElementsByName( name );
}

/**
 * Returns control object wrapped in corresponding class. Supports object caching
 * to speed up consequent ctl() calls with the same id.
 *
 * @param {String or Object} control		HTML object id or object reference
 * @param {String} [type]						Forced contorl type or null to detect automatically
 * @return CHTMLObject						Actually one of the derivates of the CHTMLObject
 */
function ctl( control, type )
{
	if( typeof( control ) == 'string' || typeof( control ) == 'number' ) // object id passed
	{
		control = el( control );
		if( control == null )
		{
			Aux.triggerError( 'No object exists with the id \'' + control + '\'!' );
			return null;
		}
	}
	if( control == null )
	{
		Aux.triggerError( 'Null object supplied!' );
		return null;
	}
	var objClass = Aux.getCtlClass( type == null ? Aux.getCtlType( control ) : type );
	if( control.id != null )
	{
		if( type == null ) // cache only objects with type autodetection
		{
			if( Aux.ctlCache[ control.id ] == null )
			{
				Aux.ctlCache[ control.id ] = new objClass( control );
			}
		}
		return Aux.ctlCache[ control.id ];
	}
	return new objClass( control );
}

var $ = ctl;

var CAux = function()
{

	this.ctlCache = {};

	this.triggerError = function( error )
	{
		if( window.jooxbrErrorHandler )
		{
			window.jooxbrErrorHandler( error );
		}
	};

	this.triggerUnsupported = function( features )
	{
		if( window.jooxbrUnsupportedHandler )
		{
			window.jooxbrUnsupportedHander( features );
		}
	};

	/**
	* Returns type of the supplied control object
	*
	* @param ctl Object
	* @return String
	*/
	this.getCtlType = function( ctl )
	{
		switch( ctl.nodeName.toLowerCase() )
		{
			case 'input':
				switch( ctl.type.toLowerCase() )
				{
					case 'checkbox':
					case 'check':
						return 'check';

					case 'radio':
						return 'radio';

					case 'reset':
					case 'submit':
					case 'button':
						return 'button';

					case 'text':
					case 'password':
					case 'hidden':
						return 'textfield';
				}
			break;

			case 'textarea':
				return 'textfield';

			case 'select':
				if( ctl.size == '1' )
				{
					return 'combo';
				}
				else
				{
					return 'list';
				}
			break;

			case 'button':
				return 'button';
		}
		return ctl.nodeName.toLowerCase();
	};

	this.getCtlClass = function( type )
	{
		switch( type )
		{
			case 'button':
				return CButton;

			case 'combo':
			case 'list':
				return CList;

			case 'check':
			case 'radio':
				return CCheckBox;

			case 'textfield':
				return CTextfield;

			default:
				return CHTMLObject;
		}
	};

};
var Aux = new CAux();

//----------------------------------------------------------------------------------------------------------

function dumpHelper( obj, level, out, maxLevel, showTypes )
{
	var pre = '';
	for( var i = 0; i < level; i++ )
	{
		pre += '   ';
	}
	for( var el in obj )
	{
		if( typeof( obj[ el ] ) == 'object' && level + 1 <= maxLevel )
		{
			return dumpHelper( obj[ el ], level + 1, out + pre + el + ( showTypes ? '[ ' + typeof( obj[ el ] ) + ' ]' : '' ) + ' :\n', maxLevel, showTypes );
		}
		else
		{
			out += pre + el + ( showTypes ? '[ ' + typeof( obj[ el ] ) + ' ]' : '' ) + ' = ' + obj[ el ] + '\n';
		}
	}
	return out;
}

function dump( obj, maxLevel /* = 2 */, showTypes /* = false */ )
{
	maxLevel = def( maxLevel, 2 );
	showTypes = def( showTypes, false );
	if( obj == null )
	{
		alert( 'Null object supplied!' );
		return;
	}
	return dumpHelper( obj, 0, '', maxLevel, showTypes );
}

//----------------------------------------------------------------------------------------------------------

Array.prototype.contains = function( val )
{
	for( var el in this )
	{
		if( this[ el ] == val )
		{
			return true;
		}
	}
	return false;
}

String.prototype.ltrim = function()
{
	var str = String( this );
	for( var i = 0; i < str.length && ( str.charAt( i ) == ' ' || str.charAt( i ) == '\t' || str.charAt( i ) == '\n' || str.charAt( i ) == '\r' ); i++ );
	if( i )
	{
		str = str.substr( i );
	}
	return str;
};

String.prototype.rtrim = function()
{
	var str = String( this );
	for( var i = str.length - 1; i >= 0 && ( str.charAt( i ) == ' ' || str.charAt( i ) == '\t' || str.charAt( i ) == '\n' || str.charAt( i ) == '\r' ); i-- );
	if( i != str.length - 1 )
	{
		str = str.substring( 0, i + 1 );
	}
	return str;
};

/**
 * Removes whitespace from the start and the end of the passed string
 * 
 * @return {String}
 */
String.prototype.trim = function()
{
	return this.ltrim().rtrim();
};

//----------------------------------------------------------------------------------------------------------

var Browser = {
	  agent : navigator.userAgent
 	, _lagent : navigator.userAgent.toLowerCase()
};
Browser.isGecko = Browser._lagent.indexOf( 'gecko' ) != -1;
Browser.isIE = Browser._lagent.indexOf( 'msie' ) != -1;
Browser.isOpera = Browser._lagent.indexOf( 'opera' ) != -1;

//----------------------------------------------------------------------------------------------------------

var CEvent = function( evt )
{

	// <constructor>
		this._evt = def( evt, window.event );
	// </constructor>

	/**
	 * Returns the reference to the control that fired the event.
	 *
	 * @return Object
	 */
	this.target = function()
	{
		var out = null;
		if( this._evt.target )
		{
			out = this._evt.target;
		}
		else if( this._evt.srcElement)
		{
			out = this._evt.srcElement;
		}
		if( out && out.nodeType == 3 ) // fix Safari bug
		{
			return out.parentNode;
		}
		return out;
	};

	this.targetCtl = function()
	{
		return ctl( this.target().id );
	};

	this.fromElement = function()
	{
		if( this._evt.relatedTarget )
		{
			return this._evt.relatedTarget;
		}
		else if( this._evt.fromElement )
		{
			return this._evt.fromElement;
		}
		return null;
	};

	this.fromElementCtl = function()
	{
		var obj = this.fromElement();
		if( obj )
		{
			return ctl( obj );
		}
		return null;
	};

	this.toElement = function()
	{
		if( this._evt.relatedTarget )
		{
			return this._evt.relatedTarget;
		}
		else if( this._evt.toElement )
		{
			return this._evt.toElement;
		}
		return null;
	};

	this.toElementCtl = function()
	{
		var obj = this.toElement();
		if( obj )
		{
			return ctl( obj );
		}
		return null;
	};

	/**
	 * clientX/Y -- relative to the control that fired the event
	 */
	this.clientX = function()
	{
/*		if( this._evt.offsetX )
		{
			return this._evt.offsetX;
		}*/
		return this.docX() - this.targetCtl().gx();
	};

	this.clientY = function()
	{
/*		if( this._evt.offsetY )
		{
			return this._evt.offsetY;
		}*/
		return this.docY() - this.targetCtl().gy();
	};

	/**
	 * viewX/Y -- relative to the current viewport of the browser (maybe not cross-browser)
	 */
	this.viewX = function()
	{
		return this._evt.clientX;
	};

	this.viewY = function()
	{
		return this._evt.clientY;
	};

	/**
	 * screenX/Y -- relative to the whole screen
	 */
	this.screenX = function()
	{
		return this._evt.screenX;
	};

	this.screenY = function()
	{
		return this._evt.screenY;
	};

	/**
	 * docX/Y -- relative to the document origin disregarding any scrolling
	 */
	this.docX = function()
	{
		if( this._evt.pageX )
		{
			return this._evt.pageX;
		}
		else if( this._evt.clientX )
		{
			return this._evt.clientX + ( Browser.isIE ? document.body.scrollLeft : 0 );
		}
		return 0;
	};

	this.docY = function()
	{
		if( this._evt.pageY )
		{
			return this._evt.pageY;
		}
		else if( this._evt.clientY )
		{
			return this._evt.clientY + ( Browser.isIE ? document.body.scrollTop : 0 );
		}
		return 0;
	};

	this.keyCode = function()
	{
		if( this._evt.keyCode)
		{
			return this._evt.keyCode;
		}
		else if( this._evt.which )
		{
			return this._evt.which;
		}
		return 0;
	};

	this.keyChar = function()
	{
		return String.fromCharCode( this.keyCode() );
	};

	this.leftButton = function()
	{
		if( this._evt.which )
		{
			return this._evt.which == 1;
		}
		else if( this._evt.button )
		{
			if( Browser.isGecko )
			{
				return this._evt.button == 0;
			}
			else
			{
				return Boolean( this._evt.button & 1 );
			}
		}
		return false;
	};

	this.rightButton = function()
	{
		if( this._evt.which )
		{
			return this._evt.which == 3;
		}
		else if( this._evt.button )
		{
			return Boolean( this._evt.button & 2 );
		}
		return false;
	};

	this.middleButton = function()
	{
		if( this._evt.which )
		{
			return this._evt.which == 2;
		}
		else if( this._evt.button )
		{
			if( Browser.isGecko )
			{
				return this._evt.button == 1;
			}
			else
			{
				return Boolean( this._evt.button & 4 );
			}
		}
		return false;
	};

	this.mouseButtons = function()
	{
		return this.leftButton() * 1 | this.rightButton() * 2 | this.middleButton() * 4;
	};

};

//----------------------------------------------------------------------------------------------------------

var CWindow = function( wnd )
{

	// <constructor>
		this._wnd = def( wnd, window );
	// </constructor>

	this.innerWidth = function()
	{
		if( this._wnd.window.innerWidth )
		{
			return this._wnd.window.innerWidth;
		}
		else if( this._wnd.document.body.clientWidth )
		{
			return this._wnd.document.body.clientWidth;
		}
		return 0;
	};

	this.innerHeight = function()
	{
		if( this._wnd.window.innerHeight )
		{
			return this._wnd.window.innerHeight;
		}
		else if( this._wnd.document.body.clientHeight )
		{
			return this._wnd.document.body.clientHeight;
		}
		return 0;
	};

};

var Window = new CWindow();

//----------------------------------------------------------------------------------------------------------

var CDocument = function( doc )
{

	// <constructor>
		this._doc = def( doc, window.document );
	// </constructor>

	this.write = function( text )
	{
		this._doc.open();
		this._doc.write( text );
	};

	this.writeLine = function( text )
	{
		this.write( text + '<br />\n' );
	};

	this.stitle = function( text )
	{
		this._doc.title = text;
	};

	this.gtitle = function()
	{
		return this._doc.title;
	};

};

var Document = new CDocument();

//----------------------------------------------------------------------------------------------------------

var CScreen = function()
{
	
	// <constructor>
		this._dpix = 96;
		this._dpiy = 96;
	// </constructor>
	
	this.initDPI = function( testObj )
	{
		testObj = ctl( testObj );
		testObj._elem.style.position = 'absolute';
		testObj._elem.style.left = '1in';
		testObj._elem.style.top = '1in';
		this._dpix = testObj.gx();
		this._dpiy = testObj.gy();
		testObj.svisible( false );
	};
	
	this.getDPI = function()
	{
		return this.getXDPI();
	};
	
	this.getXDPI = function()
	{
		if( screen.logicalXDPI )
		{
			return screen.logicalXDPI;
		}
		return this._dpix;
	};
	
	this.getYDPI = function()
	{
		if( screen.logicalYDPI )
		{
			return screen.logicalYDPI;
		}
		return this._dpiy;
	};
	
};

var Screen = new CScreen();

//----------------------------------------------------------------------------------------------------------

var CHTMLObject = function( id )
{

	// <constructor>
		this._elem = null;
		if( id != null )
		{
			this._elem = el( id );
		}
	// </constructor>

	this.getAncestors = function()
	{
		var out = [];
		var curParent = this._elem.parentNode;
		while( curParent )
		{
			out.push( curParent );
			curParent = curParent.parentNode;
		}
		return out;
	};

	this.getAncestorsCtl = function()
	{
		var out = this.getAncestors();
		for( var i = 0; i < out.length; i++ )
		{
			out[ i ] = ctl( out[ i ] );
		}
		return out;
	};

	this.isChildOf = function( elem )
	{
		var curParent = this._elem.parentNode;
		while( curParent )
		{
			if( curParent == elem )
			{
				return true;
			}
			curParent = curParent.parentNode;
		}
		return false;
	};
	
	this.isChildOfCtl = function( ctl )
	{
		return this.isChildOf( ctl._elem );
	};

	this.attach = function( id )
	{
		var elem = el( id );
		if( elem == null )
		{
			return false;
		}
		var out = this._elem;
		this._elem = elem;
		return out;
	};

	this.id = function()
	{
		return this._elem.id;
	};

	this.focus = function()
	{
		this._elem.focus();
	};

	this.blur = function()
	{
		this._elem.blur();
	};

	this.svisible = function( visible )
	{
		this._elem.style.display = visible ? '' : 'none';
	};

	this.gvisible = function()
	{
		return this._elem.style.display != 'none';
	};

	/**
	 * x position relative to the document origin
	 */
	this.sx = function( x )
	{
		this._elem.style.left = Number( x ) + 'px';
	};

	this.gx = function()
	{
		var curleft = 0;
		var obj = this._elem;
		if( obj.offsetParent )
		{
			while( obj.offsetParent )
			{
				curleft += obj.offsetLeft;
				obj = obj.offsetParent;
			}
		}
		else if( obj.x )
		{
			return obj.x;
		}
		return curleft;
	};

	/**
	 * y position relative to the document origin
	 */
	this.sy = function( y )
	{
		this._elem.style.top = Number( y ) + 'px';
	};

	this.gy = function()
	{
		var curtop = 0;
		var obj = this._elem;
		if( obj.offsetParent )
		{
			while( obj.offsetParent )
			{
				curtop += obj.offsetTop;
				obj = obj.offsetParent;
			}
		}
		else if( obj.y )
		{
			return obj.y;
		}
		return curtop;
	};

	/**
	 * width
	 */
	this.setWidth = function( width )
	{
		this._elem.style.width = Number( width ) + 'px';
	};

	this.getWidth = function()
	{
		return Number( this._elem.style.width );
	};

	/**
	 * height
	 */
	this.setHeight = function( height )
	{
		this._elem.style.height = Number( height ) + 'px';
	};

	this.getHeight = function()
	{
		return Number( this._elem.style.height );
	};

	this.setStyle = function( style, value )
	{
		this._elem.style[ style ] = value;
	};

	this.getStyle = function( style )
	{
		return this._elem.style[ style ];
	};

};

//----------------------------------------------------------------------------------------------------------

var CTextfield = function( id )
{

	// <constructor>
		this._elem = el( id );
	// </constructor>

// private:

	this._trans = function( index )
	{
		while( index < 0 ) // convert negative indices
		{
			index = this.gtext().length + 1 + index;
		}
		return index;
	};

// public:

	/**
	 * Selects the entire text field
	 * Often faster alternative to setSel() with no arguments
	 */
	this.selectAll = function()
	{
		if( this._elem.select )
		{
			this._elem.select();
			this.focus();
		}
		else
		{
			this.setSel();
		}
	};

	/**
	 * Sets selection to the specified bounds
	 * If length is omitted then selection stretches to the end
	 *
	 * @param start Number or null
	 * @param length Number or null
	 */
	this.setSel = function( start /* = 0 */, length /* = textfield length */ )
	{
		start = this._trans( def( start, 0 ) );
		length = def( length, this.gtext().length );
		if( this._elem.setSelectionRange )
		{
			this.focus();
			this._elem.setSelectionRange( start, start + length );
		}
		else if( this._elem.createTextRange )
		{
			var range = this._elem.createTextRange();
			range.collapse( true );
			range.moveEnd( 'character', start + length );
			range.moveStart( 'character', start );
			range.select();
		}
	};

	this.setSelStart = function( index )
	{
		index = this._trans( index );
		if( this._elem.selectionStart )
		{
			this.focus();
			this._elem.selectionStart = index;
		}
		else if( this._elem.createTextRange )
		{
			var end = this.getSelEnd();
			var range = this._elem.createTextRange();
			range.collapse( true );
			range.moveEnd( 'character', end );
			range.moveStart( 'character', index );
			range.select();
		}
	};

	this.getSelStart = function()
	{
		if( this._elem.selectionStart )
		{
			return this._elem.selectionStart;
		}
		else if( document.selection && document.selection.createRange ) // this section really sucks as IE itself does
		{
			var range = document.selection.createRange().duplicate();
			var offset = 0;
			var actMove;
			while( actMove = range.moveStart( 'character', -1024 ) )
			{
				offset += Math.abs( actMove );
			}
			if( this._elem.tagName.toLowerCase() == 'textarea' ) // in textareas count begins from 1, not 0
			{
				offset--;
			}
			return offset;
		}
		return 0;
	};

	this.setSelEnd = function( index )
	{
		index = this._trans( index );
		if( this._elem.selectionEnd )
		{
			this.focus();
			this._elem.selectionEnd = index;
		}
		else if( document.selection && document.selection.createRange )
		{
			var start = this.getSelStart();
			var range = this._elem.createTextRange();
			range.collapse( true );
			range.moveEnd( 'character', index );
			range.moveStart( 'character', start );
			range.select();
		}
	};

	this.getSelEnd = function()
	{
		if( this._elem.selectionEnd )
		{
			return this._elem.selectionEnd;
		}
		else if( document.selection && document.selection.createRange ) // this section really sucks as IE itself does
		{
			var range = document.selection.createRange().duplicate();
			var offset = 0;
			var actMove;
			while( actMove = range.moveEnd( 'character', -1024 ) )
			{
				offset += Math.abs( actMove );
			}
			return offset;
		}
		return 0;
	};

	this.setCursorPos = function( index )
	{
		this.setCurSel( this._trans( index ), 0 );
	};

	this.replaceSel = function( text )
	{
		if( this._elem.setSelectionRange )
		{
			/*
			    var selectionStart = input.selectionStart;
    var selectionEnd = input.selectionEnd;
    input.value = input.value.substring(0, selectionStart)
                  + replaceString
                  + input.value.substring(selectionEnd);
    if (selectionStart != selectionEnd) // has there been a selection
      setSelectionRange(input, selectionStart, selectionStart + 
replaceString.length);
    else // set caret
      setCaretToPos(input, selectionStart + replaceString.length);
			*/

			var selectionStart = this._elem.selectionStart;
			var selectionEnd = this._elem.selectionEnd;
			window.status = selectionStart + ', ' + selectionEnd;
			this.stext( this.gtext().substring( 0, selectionStart ) + text + this.gtext().substring( selectionEnd ) );
			if( selectionStart != selectionEnd )
			{
				this.setSel( selectionStart, text.length );
			}
			else
			{
				this.setCursorPos( selectionStart + text.length );
			}
		}
		else if( document.selection )
		{
			this.focus();
			var range = document.selection.createRange();
			var isCollapsed = range.text == '';
			range.text = text;
			if( !isCollapsed ) // there has been a selection
			{
				// it appears range.select() should select the newly 
				// inserted text but that fails with IE
				range.moveStart( 'character', -text.length );
				range.select();
			}
		}
	};

	this.stext = function( value )
	{
		this._elem.value = String( value );
	};

	this.gtext = function()
	{
		return String( this._elem.value );
	};

	/**
	 * Returns true if text field contains only whitespace or is of zero length
	 */
	this.isEmpty = function()
	{
		return this.gtext().trim() == '';
	};

};

// inheritance
CTextfield.prototype = new CHTMLObject();

//----------------------------------------------------------------------------------------------------------

var CButton = function( id )
{

	// <constructor>
		this._elem = el( id );
	// </constructor>

};

// inheritance
CButton.prototype = new CHTMLObject();

//----------------------------------------------------------------------------------------------------------

var CList = function( id )
{

	// <constructor>
		this._elem = el( id );
		this._coll = this._elem.options; // shortcut
	// </constructor>

	this.addItem = function( caption, value )
	{
		this._coll[ this._coll.length ] = new Option( caption, value );
	};

	this.removeItem = function( value )
	{
		if( value == null )
		{
			value = this.getCurSel();
		}
		if( typeof( value ) == 'string' )
		{
			value = this.getIndexByValue( value );
		}
		if( typeof( value ) == 'number' )
		{
			this._coll[ value ] = null;
		}
	};

	this.getCurSel = function()
	{
		return this._coll.selectedIndex;
	};

	this.gvalue = function()
	{
		var idx = this.getCurSel();
		if( idx == -1 )
		{
			return null;
		}
		return this._coll[ idx ].value;
	};

	this.getCaption = function()
	{
		var idx = this.getCurSel();
		if( idx == -1 )
		{
			return null;
		}
		return this._coll[ idx ].text;
	};

	/**
	 * Sets selected state of the select box.
	 *   if value == null, then clears the selection
	 *   if value is a number, then selects item with the specified zero-based index
	 *   if value is a string, then selects item with the the specified value
	 *   returs true on success and false on failure (when no such item exists)
	 *
	 * @param value null, Number or String
	 * @return Boolean
	 */
	this.svalue = function( value )
	{
		if( value == null )
		{
			for( var i = 0; i < this._coll.length; i++ )
			{
				this._coll[ i ].selected = false;
			}
			return true;
		}
		var elem = this.getOption( value );
		if( elem != null )
		{
			elem.selected = true;
			return true;
		}
		return false;
	};

	this.getIndexByValue = function( value )
	{
		for( var i = 0; i < this._coll.length; i++ )
		{
			if( this._coll[ i ].value == value )
			{
				return i;
			}
		}
		return null;
	};

	this.getOption = function( elem )
	{
		if( typeof( elem ) == 'string' )
		{
			elem = this.getIndexByValue( elem );
		}
		if( typeof( elem ) == 'number' )
		{
			if( this._coll.length <= 0 || elem >= this._coll.length )
			{
				return null;
			}
			return this._coll[ elem ];
		}
		return elem;
	};

};

// inheritance
CList.prototype = new CHTMLObject();

//----------------------------------------------------------------------------------------------------------

var CCheckBox = function( id )
{

	// <constructor>
		this._elem = el( id );
	// </constructor>

	this.svalue = function( value )
	{
		this._elem.value = value;
	};

	this.gvalue = function()
	{
		return this._elem.value;
	};

	this.schecked = function( check )
	{
		this._elem.checked = check;
	};

	this.gchecked = function()
	{
		return this._elem.checked;
	};

};

CCheckBox.prototype = new CHTMLObject();

//----------------------------------------------------------------------------------------------------------

var CRadioGroup = function( name )
{

	// <constructor>
		this._coll = els( name ); // internal html elements collection
	// </constructor>

// private:

// public:

	this.attach = function( name )
	{
		this._coll = els( name );
	};

	this.getElemByIndex = function( ind )
	{
		if( this._coll.length <= 0 || ind >= this._coll.length )
		{
			return null;
		}
		return this._coll[ ind ];
	};

	this.getElemByValue = function( val )
	{
		for( var i = 0; i < this._coll.length; i++ )
		{
			if( this._coll[ i ].value == val )
			{
				return this._coll[ i ];
			}
		}
		return null;
	};

	this.getElem = function( elem )
	{
		if( typeof( elem ) == 'number' )
		{
			elem = this.getElemByIndex( elem );
		}
		else if( typeof( elem ) == 'string' )
		{
			elem = this.getElemByValue( elem );
		}
		return elem;
	};

	/**
	 * Sets focus to the radio group.
	 *   if element is supplied and is a number, then tries to set focus to the number'th element counting from zero
	 *   if element is a string; tries to focus element with the value == element
	 *   returns true of success and false on failure
	 *
	 * @param null, Number or String
	 * @return Boolean
	 */
	this.focus = function( element )
	{
		element = def( element, 0 );
		var elem = this.getElem( element );
		if( elem != null )
		{
			elem.focus();
			return true;
		}
		return false;
	};

	/**
	 * @return Void
	 */
	this.removeFocus = function()
	{
		for( var i = 0; i < this._coll.length; i++ )
		{
			this._coll[ i ].blur();
		}
	};

	/**
	 * Sets selected state of the radio group.
	 *   if value == null, then clears all the checks
	 *   if value is a number, then checks radio button with the specified zero-based index
	 *   if value is a string, then check radio button with the the same value
	 *   returs true on success and false on failure (when no such button exists)
	 *
	 * @param value null, Number or String
	 * @return Boolean
	 */
	this.svalue = function( value )
	{
		if( value == null )
		{
			for( var i = 0; i < this._coll.length; i++ )
			{
				this._coll[ i ].checked = false;
				return true;
			}
			return true;
		}
		var elem = this.getElem( value );
		if( elem != null )
		{
			elem.checked = true;
			return true;
		}
		return false;
	};

	/**
	 * Returns value of the currently selected radiobutton or null if nothing is selected
	 *
	 * @return String
	 */
	this.gvalue = function()
	{
		for( var i = 0; i < this._coll.length; i++ )
		{
			if( this._coll[ i ].checked != false )
			{
				return this._coll[ i ].value;
			}
		}
		return null;
	};

	/**
	 * Returns zero based index of the currently selected radio button or -1 if nothing is selected
	 *
	 * @return Number
	 */
	this.getIndex = function()
	{
		for( var i = 0; i < this._coll.length; i++ )
		{
			if( this._coll[ i ].checked != false )
			{
				return i;
			}
		}
		return -1;
	};

};

// inheritance
//CRadioGroup.prototype = new CHTMLObject();

//----------------------------------------------------------------------------------------------------------

var CStatusBar = function()
{

	this.stext = function( text )
	{
		window.status = text;
	};

	this.gtext = function()
	{
		return window.status;
	};

	this.restoreText = function()
	{
		if( Browser.isGecko )
		{
			this.stext( '' );
		}
		else // this is crude hack, sorry
		{
			this.stext( 'Done' );
		}
	};

};

var StatusBar = new CStatusBar();

window.jooxbrLoaded = true;
