var SelectBox = $Class( {
	$init : function() {
		this.info = this._initOption( arguments[0] );
		var select = $( this.info.id );
		if ( !select ) 
			return;

		this._getAttribute( select );
		this._setEvent();

		this.control = new SelectBox.Control( this );
		this.input = new SelectBox.Input( this );
		this.box = new SelectBox.NullBox( this ); // lazy initialization -> IE6 Renderer Bug
		//this.box = SelectBox.Factory.newBox( this  );

		this._initFirstValue();
		this._realignElement();

		if ( this.info.loadEvent ) {
			$Fn(this._initFirstValue, this).attach( window, "load" );
		}
	},
	_initOption : function( argu ) {
		var options = {
			keepTitle		: false,
			boxType			: "basic",
			handlerType		: "basic",
			cols			: 1,
			boxY	 		: 0,
			align			: "left",
			spanClass		: "seljs_selected",
			spanTitleClass	: "seljs_title",
			boxClass 		: "seljs_option",
			boxOverClass	: "seljs_mover",
			iframeClass		: "seljs_iframe",
			focusClass		: "sopen",
			multiClass		: "selcol",
			maxHeight		: 1200,
			useIframe		: false,
			loadEvent		: true,
			enable			: true,
			BtnClick		: false
		};
		if (typeof argu == "undefined" ) argu = new Object;
		for(var x in argu) {
			options[x] = argu[x];
		}

		if ( options.cols != 1 ) {
			options.boxType = "multicolumn";
			options.handlerType = "multicolumn";
			options.boxClass = options.boxClass + " " + options.multiClass;
		}
		return options;
	},
	_getAttribute : function( select ) {		
		this.info.base = select;
		this.info.parent = select.parentNode;
		this.info.agent = $Agent().navigator();

		this.info.title 	= select.getAttribute( "title" ) || false;
		this.info.name 		= select.getAttribute( "name" ) || "";
		this.info.width	 	= 0;
		this.info.selected 	= -1;
		this.info.list 		= new Array();
		this.info.optionType = new Array();
		this.info.imgList	= new Array();

		var children = select.getElementsByTagName( "OPTION" );
		for ( var i = 0, j = 0 ; i < children.length ; i++ ) {
			var option = children[i];

			var newValue = option.firstChild.nodeValue;
			var type = SelectBox.getOptionType( newValue );
			if ( type != SelectBox.NORMAL ) {
				newValue = ( type == SelectBox.PERIOD ? this.info.periodOption.value : type == SelectBox.URL ? this.info.urlOption.value : newValue );
			}
			this.info.optionType.push( type );
			this.info.list.push( new Array( newValue, ( option.getAttribute( "value" ) || "" ) ) );

			var imgSrc = ( this.info.agent.safari ? option.getAttribute( "style" ) || "none" : $Element( option ).css( "backgroundImage" ) );
			var imgAlt = option.getAttribute( "title" ) || "";

			if ( imgSrc != "none" ) {
				this.info.imgList.push( new Array( imgSrc.replace( /.*url\(\"?([^\"]+)\"?\)/, "$1" ), imgAlt ) );
			} else {
				this.info.imgList.push( new Array( "", "" ) );
			}
			if ( option.defaultSelected ) {
				this.info.selected = j;
			}
			j++;
		}
		this.info.width = parseInt( select.offsetWidth || select.style.width );
	},
	_setEvent : function() {
		var select = this.info.base;
		this.Onchange 		= ( this._isValidEvent( select.onchange ) || this._nullEvent );
		this.Onkeydown 		= ( this._isValidEvent( select.onkeydown ) || this._nullEvent );
		this.Onkeypress 	= ( this._isValidEvent( select.onkeypress ) || this._nullEvent );
		this.Onmouseout 	= ( this._isValidEvent( select.onmouseout ) || this._nullEvent );
		this.Onmouseover 	= ( this._isValidEvent( select.onmouseover ) || this._nullEvent );
		this.Onclick 		= ( this._isValidEvent( select.onclick ) || this._nullEvent );
		this.Onfocus 		= ( this._isValidEvent( select.onfocus ) || this._nullEvent );
		this.Onblur 		= ( this._isValidEvent( select.onblur ) || this._nullEvent );
	},
	_isValidEvent : function( func ) {
		if ( func && typeof func == "function" ) {
			return func;
		} else {
			return false;
		}
	},
	_initFirstValue : function() {
		if ( this.info.list.length == 0 ) return;

		if ( this.info.selected < 0 ) {
			if ( this.info.title ) { 
				this.input.setTitle( this.info.title );
			} else {
				this.input.setValue( this.info.list[0][0], this.info.list[0][1] );
			}
		} else {
			this.input.setValue( this.info.list[ this.info.selected ][0], this.info.list[ this.info.selected ][1] );
		}
	},
	_realignElement : function() {
		this.info.base.style.display = "none";
		this.info.base.removeAttribute( "name" );
		this.info.parent.insertBefore( this.input._span, this.info.base );
	},
	_getIndex : function( value ) {
		var index = -1;
		var list = this.info.list;

		for ( var i = 0 ; i < list.length ; i++ ) {
			if ( list[i][1] == value ) {
				index = i;
				break;
			}
		}
		return index;
	},
	length : function() {
		return this.info.list.length;
	},
	getValue : function() {
		return {
			displayValue : ( this.control.index.now == -1 ? this.info.title : this.info.list[ this.control.index.now ][0] ),
			value : ( this.control.index.now == -1 ? "" : this.info.list[ this.control.index.now ][1] ),
			index : this.control.index.now
		};
	},
	setTitle : function() {
		if ( this.info.title ) {
			this.control.changeIndex( -1 );
			this.control.initAllIndex( -1 );
			this.input.setTitle( this.info.title );
		}
		this.box.refresh();
	},
	setValue : function( value, initFirstValue ) {
		var index = this._getIndex( value );
		if ( index == -1 ) 
			return;

		this.control.changeIndex( index );
		this.control.initAllIndex( index );

		if ( initFirstValue === true ) {
			this.info.selected = index;
		}
	},
	addValue : function( viewValue, value, imgSrc, imgAlt, position ) {

		var index = this._getIndex( value );

		if ( index != -1 ) return this; 

		if (typeof imgSrc == "number") {
			position = imgSrc;
			imgSrc = "";
		}


		if ( position == null ) position = -1;
		if ( position > this.info.list.length ) return this;

		if (position == -1) {
			this.info.list.push( [viewValue, value]);
			this.info.imgList.push( [imgSrc || "", imgAlt || ""]);
		} else if ( position == 0 ){
			this.info.list.unshift( [viewValue, value]);
			this.info.imgList.unshift( [imgSrc || "", imgAlt || ""]);			
		} else if ( position ){
			var nList = this.info.list.splice( position );
			var nImgList = this.info.imgList.splice( position );
			this.info.list = this.info.list.concat( [[viewValue, value]] );
			this.info.list = this.info.list.concat( nList );
			this.info.imgList = this.info.imgList.concat( [[imgSrc || "", imgAlt || ""]] );
			this.info.imgList = this.info.imgList.concat( nImgList );
		}
		if ( !this.box.nullBox ) {
			this.box.refresh();
		}

		return this;
	},
	enable : function() {
		this.info.enable = true;
		this.input.enable();
	},
	disable : function() {
		this.info.enable = false;
		this.input.disable();
	},	
	focus : function() {
		this.input.focus();
	},
	show : function() {
		this.box.show();
	},
	hide : function() {
		this.box.hide();
	},
	_remove : function( index ) {
		this.info.list.splice( index, 1 );
		this.info.imgList.splice( index, 1 );

		if ( !this.box.nullBox ) {
			this.box.refresh();
			if ( index == this.control.index.now && this.length() != 0 ) {
				this.control.changeIndex( 0 );
				this.box.changeChildStyle( 0 );
			}
		}
	},
	removeValue : function( value ) {
		var index = this._getIndex( value );
		if ( index == -1 ) return;

		this._remove( index );
		return this;
	},
	removePart : function( size ) {
		var length = this.info.list.length;

		if ( length > size ) {
			for ( var index = length ; index >= size ; index-- ) {
				this._remove( index );
			}
		}
	},		
	recovery : function() {
		this.input._span.display = "none";
		this.info.base.style.display = "block";
		this.info.base.name = this.info.name;
		this.input._hidden.name = "";
	},
	rrecovery : function() {
		this.info.base.style.display = "none";
		this.info.base.removeAttribute( "name" );
		this.input._span.display = "block";
		this.input._hidden.name = this.info.name;
	},
	Onchange : null,
	Onkeydown : null,
	Onkeypress : null,
	Onmouseout : null,
	Onmouseover : null,
	Onclick	: null,
	Onfocus : null,
	Onblur : null,
	BtnClick : null,
	_nullEvent : function() {}
} );
SelectBox.fireEvent = function( func, event, select ) {
	func.call( select, event, select );
};
SelectBox.EXTRA_WIDTH = {
	ie 		: 0,
	firefox : 0,
	opera 	: 0,
	safari 	: 0,
	getWidth : function( agent ) {
		return ( agent.ie ? this.ie : agent.firefox ? this.firefox : agent.safari ? this.safari : this.opera );
	},
	setWidth : function( extra ) {
		for ( var p in extra ) {
			if ( this[p] < extra[p] ) 
				this[p] = extra[p];
		}
	}
}
SelectBox.Factory = {
	newHandler : function( control ) {
		var handler = null;
		switch( control.select.info.handlerType ) {
			case "basic" :
				handler = new SelectBox.Handler( control );
				break;
			case "multicolumn" :
				handler = new SelectBox.MultiColumnHandler( control );
				break;
		}
		return handler;
	},
	newBox : function( select ) {
		var box = null;
		switch( select.info.boxType ){
			case "basic" :
				box = new SelectBox.Box( select );
				break;
			case "multicolumn" :
				box = new SelectBox.MultiBox( select );
				break;
		}
		return box;
	},
	newOption : function( select, box, index ) {
		var option = null;
		var type = select.info.optionType[index];
		switch( type ) {
			case SelectBox.PERIOD :
				option = new SelectBox.PeriodOption( select, box, index ); 
				break;
			case SelectBox.URL :
				option = new SelectBox.URLOption( select, box, index );
				break;
			default :
				option = new SelectBox.Option( select, box, index );
		}
		return option;
	}
};
SelectBox.getOptionType = function( value ) {
	var type = value.toLowerCase();
	var result = SelectBox.NORMAL;
	switch( type ) {
		case SelectBox.SHARP + SelectBox.PERIOD :
			result = SelectBox.PERIOD;
			break;
		case SelectBox.SHARP + SelectBox.URL :
			result = SelectBox.URL;
			break;
		default :
	}
	return result;

}
SelectBox.SHARP = "#";
SelectBox.NORMAL = "normal";
SelectBox.PERIOD = "period";
SelectBox.URL = "url";
SelectBox.INDEX = "index";
SelectBox.DOCTYPE = "transitional";
SelectBox.BOX_LIST = new Array();
SelectBox.CHECK_AREA = function( event ) {
	var element = event.element;
	var elementID = [];

	if ( !!element ) {
		for ( var i = 0 ; element != null && element.nodeType == 1 ; i++ ) {
			elementID[i] = element.id || "";
			element = element.parentNode;
		}
	}
	var hasID = false;
	for ( var i = 0 ; i < SelectBox.BOX_LIST.length ; i++, hasID = false ) {
		var box = SelectBox.BOX_LIST[i];

		for ( var j = 0 ; j < elementID.length ; j++ ) {
			if ( box[0] == elementID[j] || box[1] == elementID[j] ) {
				hasID = true;
				break;
			}
		}
		if ( hasID == false ) {
			$( box[2] ).style.display = "none";
			$( box[1] ).style.display = "none";
		}
	}
}
$Fn( SelectBox.CHECK_AREA, window ).attach( document, "click" );
SelectBox.Input = $Class( {
	$init : function( select ) {
		this.select = select;
		this.info = select.info;

		this._createDOM();
		this._addEvent();
	},
	_createDOM : function() {
		this._span = $( "<SPAN>" );
		this._span.className = this.info.spanTitleClass;

		this._span.appendChild( this._input = this._createInput() );		
		this._span.appendChild( this._hidden = this._createHidden() );

		if ( this.info.selected > 0 ) this._onfocus();
	},
	_createInput : function() {
		var input = $( "<INPUT>" );
		var ele = $Element( input );

		ele.attr( {
			id		: ( this.id = this.info.id + "Input"),
			type 		: "text",
			readOnly 	: "readOnly",
			value		: ""
		} );
		ele.css( { width : this.info.width + "px" } );
		return input;		
	},
	_createHidden : function() {
		var hidden = $( "<INPUT>" );
		$Element( hidden ).attr({
			type 	: "hidden",
			name 	: this.info.name,
			value 	: ""
		});
		hidden.style.display = "none";
		return hidden;				
	},
	_addEvent : function() {
		$Fn(this._onfocus,this).attach(this._input, "focus");
		$Fn(this._onblur,this).attach(this._input, "blur");
		$Fn(this._onclick,this).attach(this._input, "click");
		$Fn(this._onkeydown,this).attach(this._input, "keydown");
		//$Fn(this._onmousedown,this).attach(this._input, "mousedown");
		//$Fn(this._onmouseup,this).attach(this._input, "mouseup");
		//$Fn(this._onmouseover,this).attach(this._input, "mouseover");
		//$Fn(this._onmouseout,this).attach(this._input, "mouseout");
		//$Fn(this._onkeypress,this).attach(this._input, "keypress");

	},
	setValue : function( viewValue, value ) {
		if ( this.info.keepTitle ) {
			this._hidden.value = value;
		} else {
			this._input.value = viewValue;
			this._hidden.value = value;
		}
	},
	setHiddenValue : function( value ) {
		this._hidden.value = value;
	},
	setTitle : function( title ) {
		this._input.value = title;
		this._hidden.value = "";
	},
	getPos : function() {
		var inputElement = $Element( this._input );
		var pos = inputElement.offset();
		var leftGap = Math.abs( parseInt( $Element( document.body ).css( "borderLeftWidth" ) ) );
		var topGap = parseInt( inputElement.css( "borderTopWidth" ) );
		var left = ( this.select.info.agent.firefox ? pos.left + ( leftGap * 2 ) : pos.left );
		var top = ( this.select.info.agent.ie ? pos.top - topGap : pos.top );
		return {
			x : parseInt( left ), 
			y : parseInt( top ) + parseInt( this._input.offsetHeight ) 
		};
	},
	getWidth : function() {
		return this._input.offsetWidth;
	},
	getBorderWidth : function() {			
		var ele = $Element( this._input );

		var width = 0;
		if ( SelectBox.DOCTYPE == "transitional" ) {
			if ( !this.select.info.agent.ie )
				width = parseInt( ele.css( "borderLeftWidth" ) || 0 ) + parseInt( ele.css( "borderRightWidth" ) || 0 );
		} else if ( SelectBox.DOCTYPE == "loose" || SelectBox.DOCTYPE == "xhtml" ) {
			width -= parseInt( ele.css( "marginLeft" ) || 0 ) + parseInt( ele.css( "marginRight" ) || 0 );
			width -= parseInt( ele.css( "paddingLeft" ) || 0 ) + parseInt( ele.css( "paddingRight" ) || 0 );

		}
		return width;
	},
	focus : function() {		
		this._input.focus();
	},
	enable : function() {
		this._input.disabled = false;
		this._hidden.disabled = false;
		if ( this._span.style.display == "none" )
			this._span.style.display = "inline";
	},
	disable : function( isHide ) {
		this._input.disabled = true;
		this._hidden.disabled = true;
		if ( isHide ) 
			this._span.style.display = "none";
	},
	_onclick : function( e ) {
		if ( this.info.enable == false ) return;
		this.select.box.display();
		SelectBox.fireEvent( this.select.Onclick, e, this.select );
	},
	_onfocus : function( e ) {
		this._span.className = this._span.className + " " + this.info.focusClass;
		SelectBox.fireEvent( this.select.Onfocus, e, this.select );
	},
	_blurStyle : function( cName ) {
		return cName.replace( new RegExp( this.info.focusClass ), "" );
	},
	_onblur : function( e ) {
		this._span.className = this._blurStyle( this._span.className );

		if ( !this.select.control.isFireOnchange() ) {
			this.select.control.firedOnchange();
			this.select.Onchange( e, this.select );
		}
		SelectBox.fireEvent( this.select.Onblur, e, this.select );
	},
	_onkeydown : function( e ) {
		if ( this.info.enable == false ) return;
		this.select.control.keydown( e );
		SelectBox.fireEvent( this.select.Onkeydown, e, this.select );
	}
	/*
	_onmousedown : function( e ) {
		SelectBox.fireEvent( this.select.Onmousedown, e, this.select );
	},
	_onmouseup : function( e ) {
		SelectBox.fireEvent( this.select.Onmouseup, e, this.select );
	},
	_onmouseover : function( e ) {
		SelectBox.fireEvent( this.select.Onmouseover, e, this.select );
	},
	_onmouseout : function( e ) {
		SelectBox.fireEvent( this.select.Onmouseout, e, this.select );
	},
	_onkeypress : function( e ) {
		SelectBox.fireEvent( this.select.Onkeypress, e, this.select );
	}
	*/
} );
SelectBox.Control = $Class( {
	$init : function( select ) {
		this.select = select;
		this.handler = SelectBox.Factory.newHandler( this );

		this.index = {
			now : -1, mouse : -1, old : -1, pre : -1
		};
		this._isBlur = true;
		this._initIndex();
	},
	_initIndex : function() {
		if ( this.select.info.selected < 0 ) {
			if ( !this.select.info.title ) {
				this.initAllIndex( 0 );
			}
		} else {
			this.initAllIndex( this.select.info.selected );
		}
	},
	initAllIndex : function( index ) {
		this.setIndex( index, SelectBox.Control.NOW );
		this.setIndex( index, SelectBox.Control.MOUSE );
		this.setIndex( index, SelectBox.Control.OLD );
		this.setIndex( index, SelectBox.Control.PRE );
	},
	getIndex : function() { 
		return this.index; 
	},
	setIndex : function( index, what ) { 
		this.index[ what ] = index; 
	},
	keydown : function( e ) {

		var isFireKey = false;
		var index = ( this.index.now == this.index.mouse ? this.index.now : this.index.mouse );

		var k = e.key();
		if ( k.alt && k.down ) {
			this.select.box.display();
		} else if ( k.up || k.down || k.left || k.right || ( k.keyCode >= 33 && k.keyCode <= 36 ) ) {

			var keyStr = ( k.up ? SelectBox.Control.UP : k.down ? SelectBox.Control.DOWN : k.left ? SelectBox.Control.LEFT : k.right ? SelectBox.Control.RIGHT : false );
			var next = -1;
			if ( keyStr ) {
				this.select.box.pressedArrow();
				next = this.handler.nextIndex( keyStr, index )
			} else {
				next = ( k.keyCode == 33 || k.keyCode == 36 ? 0 : this.handler.getMaxIndex() ); // 33(Home), 36(PageUP), 34(DOWN), 35(PageDown)
			}

			this.select.box.focus( next );
			e.stop();
		} else if ( k.enter ) {
			if ( this.index.mouse != -1 ) 
				this.changeIndex( parseInt( this.index.mouse ) );

			this.select.box.hide();
			isFireKey = true;
			this.select.input.focus();		
			e.stop();
		} else if ( k.keyCode == 9 ) { // Tab
			this.select.box.hide();
			isFireKey = true;
		} else if ( k.keyCode == 27 ) { // ESC
			this.select.box.hide();
		} else if ( k.keyCode >= 65 && k.keyCode <= 90 ) { // Alphabetic

			this._compareFirstChar( k.keyCode, e );
		} else if ( k.keyCode >= 48 && k.keyCode <= 57  ) { // Numeric

			this._compareFirstChar( ( k.shift ? this._matchingTable[ new String( k.keyCode ) ] : k.keyCode ), e );
		} else if ( k.keyCode >= 96 && k.keyCode <= 105 ) {
			this._compareFirstChar( k.keyCode - 48, e );
		}

		SelectBox.fireEvent( this.select.Onkeydown, e, this.select );
		if ( !this.isFireOnchange() ) {
			if ( isFireKey && k.keyCode != 27 ) {
				this.firedOnchange();
				this.select.Onchange( e, this.select );
			} 
		}
	},
	_matchingTable : {
		48 : 29, 49 : 33, 50 : 64, 51 : 35, 52 : 36,
		53 : 37, 54 : 94, 55 : 38, 56 : 42, 57 : 40
	},
	_compareFirstChar : function( code, e ) {
		var matchResult = this._matchFirstChar( code, this.index.now + 1 );
		if ( matchResult != -1 ) {
			this.select.box.focus( matchResult ); 
			e.stop();
		}
	},
	_matchFirstChar : function( code, start ) {
		var matchIndex = this._runMatching( code, start, this.select.info.list.length );

		if ( start > 0 && matchIndex == -1 ) {
			matchIndex = this._runMatching( code, 0, start );
		}
		return matchIndex;
	},
	_runMatching : function( code, start, end ) {
		var matchIndex = -1;
		var options = this.select.info.list;
		for ( var i = start ; i < end ; i++ ) {
			var value = new String( options[i][0] );
			if ( value.charAt(0).toUpperCase().charCodeAt(0) == code ) {
				matchIndex = i;
				break;
			}
		}
		return matchIndex;
	},
	changeIndex : function( index ) {
		this.changeValue( index );
		this.index.pre = this.index.now;
		this.index.now = index;
		this.index.mouse = index;
	},
	changeValue : function( index ) {
		if ( index != -1 )
			this.select.input.setValue( this.select.info.list[ index ][0], this.select.info.list[ index ][1] );
	},
	firedOnchange : function() {
		this.index.old = this.index.now;
	},
	isFireOnchange : function() {
		if ( this._isBlur == true ) {
			return this.index.old == this.index.now;
		} else {
			this._isBlur = true;
			return true;
		}
	},
	setIsBlur : function( flag ) {
		this._isBlur = flag;
	}
} );
SelectBox.Control.UP	= "UP";
SelectBox.Control.DOWN	= "DOWN";
SelectBox.Control.LEFT	= "LEFT";
SelectBox.Control.RIGHT	= "RIGHT";
SelectBox.Control.NOW	= "now";
SelectBox.Control.MOUSE	= "mouse";
SelectBox.Control.OLD	= "old";
SelectBox.Control.PRE	= "pre";
SelectBox.Handler = $Class( {
	$init : function( control ) {
		this.control = control;
		this.list = control.select.info.list;
	},
	nextIndex : function( key, index ) {

		var row = parseInt( index );
		var maxRow = this.getMaxIndex();

		var nextIndex = index;
		if ( key == "UP" ){		// || key == "LEFT" ) {
			nextIndex = ( index > 0 ? row - 1 : index );
		} else if ( key == "DOWN" ){	// || key == "RIGHT" ) {
			if ( index == -1 ) {
				nextIndex = 0;
			} else {
				if ( row != maxRow ) {
					nextIndex = row + 1;
				} else {
					nextIndex = index;
				}
			}			
		} 
		return nextIndex;		
	},
	getMaxIndex : function() {
		return this.list.length - 1;
	}
} );
/*
 * public function
 * 		changeStyle
 * 		getElement
 * 		focus
 */
SelectBox.Option = $Class( {
	$init : function( select, box, index ) {
		this.select = select;
		this._box = box;
		this._index = index;

		this._element = this._initElement();
	},
	_initElement : function() {
		var li = $( "<LI>" );
		li.setAttribute( SelectBox.INDEX, this._index );
		var imgSrc = this.select.info.imgList[ this._index ][0];
		var imgAlt = this.select.info.imgList[ this._index ][1];

		if ( imgSrc != "" ) {
			var img = $( "<IMG>" );
			img.src = imgSrc;
			img.alt = imgAlt;
			li.appendChild( img );
		}
		$Fn( this._onmouseover, this ).attach( li, "mouseover" );
		$Fn( this._onclick, this ).attach( li, "click" );
		li.appendChild( document.createTextNode( this.select.info.list[ this._index ][0] ) );
		return li;
	},
	changeStyle : function() {
		this._box.initLIStyle();
		this._element.className = this.select.info.boxOverClass;
	},
	focus : function() {
		this.changeStyle();
		this.select.control.changeIndex( this._index );
	},
	getElement : function() {
		return this._element;
	},
	_onmouseover : function( e ) {
		this.changeStyle( this._index );
		this.select.control.index.mouse = this._index;
	},
	_onclick : function( e ) {		
		var isFireOnchange = false;

		var readIndex = this._index;
		if ( this.select.control.index.now != this._index ) {
			isFireOnchange = true;
			this.focus();
			//this.select.input.focus();
		}
		this._box.hide();
		this.select.input.focus();

		if ( isFireOnchange ) {
			this.select.control.firedOnchange();
			this.select.Onchange( e, this.select );
		}
	},
	getOffset : function() {
		return {
			top : this._element.offsetTop,
			height : this._element.offsetHeight
		};
	}
} );
SelectBox.NullBox = $Class( {
	$init : function( select ) {
		this.select = select;
	},
	display : function() {
		this.select.box = SelectBox.Factory.newBox( this.select  );
		this.select.box.show();
	},
	focus : function( index ) {
		this.select.control.changeIndex( index );
	},
	changeChildStyle : function() {},
	hide : function() {},
	pressedArrow : function() {},
	refresh : function() {},
	nullBox : true
} );
SelectBox.Box = $Class( {
	$init : function( select ) {
		this.select = select;
		this.info	= select.info;
		this._optionList = new Array();

		this._hasScroll = false;
		this._isArrow = false;
		this._initBox();
		this._addEvent();
	},
	_initBox : function() {
		this._createIframe();
		this._createUL();
		this._checkHeight();
	},
	refresh : function() {
		document.body.removeChild( this.element );
		this.element = null;

		this._createUL();
		this._checkHeight();
		this._addEvent();
	},
	_createUL : function() {
		var ul = $( "<UL>" );
		ul.setAttribute( "id", this.info.id + "optionList" );
		var width = this.info.width - this.select.input.getBorderWidth() + "px";

		$Element( ul ).css( {
			left		: -1000,
			top			: -1000,
			display	 	: "block"
		} );
		document.body.appendChild( this.element = ul );

		ul.className = this.info.boxClass;
		ul.ondragstart = function() { return false; };
		ul.onselectstart = function() { return false; };

		var list = this.info.list;
		for ( var i = 0 ; i < list.length ; i++ ) {
			this._optionList[i] = SelectBox.Factory.newOption( this.select, this, i );

			ul.appendChild( this._optionList[i].getElement() );
		}
		if ( this.element.offsetWidth > parseInt( width ) ) {
			width = this.element.offsetWidth + SelectBox.EXTRA_WIDTH.getWidth( this.select.info.agent ) + "px" ;
		}
		width = this._isIE55( width );

		$Element( this.element ).css( { 
			width : width,
			display : "none" 
		} );
		$Element( this.iframe ).css( { width : width, display : "none" } );
		SelectBox.BOX_LIST.push( new Array( this.select.input.id, ul.id, this.iframe.id ) );
	},
	_isIE55 : function( width ) {
		if ( this.select.info.agent.ie && this.select.info.agent.version < 6 ) {
			var hasExtra = false;
			for ( var i = 0 ; i < this._optionList.length ; i++ ) {
				if ( this._optionList[i] instanceof SelectBox.Option ) {
					;
				} else {
					hasExtra = true;
					break;
				}
			}
			if ( hasExtra )  {
				width = "197px";
			}
		}
		return width;
	},
	_createIframe : function() {
		var iframe = $( "<IFRAME>" );
		iframe.setAttribute( "id", this.info.id + "Iframe" );

		iframe.className = this.info.iframeClass;
		this.iframe = iframe;
		document.body.appendChild( this.iframe );
	},
	_checkHeight : function() {
		var element = $Element( this.element );
		element.show();

		element.css( {
			left : "-1000px",
			top : "-1000px"
		} );

		if ( this.element.offsetHeight > this.info.maxHeight ) {
			this._hasScroll = true;
			this.iframe.style.height = this.info.maxHeight + "px";
			this.element.style.height = this.info.maxHeight + "px";
		} else {
			this.iframe.style.height = this.element.offsetHeight + "px";
		}
		element.hide();
	},
	_addEvent : function() {
		$Fn( this.hide, this ).attach( window, "resize" );
	},
	_onmouseout : function( e ) {},
	changeChildStyle : function( index ) {
		this._optionList[ index ].changeStyle();
	},
	initLIStyle : function() {
		for ( var i = 0 ; i < this._optionList.length ; i++ ) {
			this._optionList[i].getElement().className = "";
		}
	},
	focus : function( index ) {
		this._optionList[index].focus();
		if ( this._hasScroll ) { 
			if ( this._isArrow ) {
				this._moveScroll( index );
			} else {
				this._moveHotKeyScroll( index );
			}
			this._isArrow = false;
		}
	},
	pressedArrow : function() {
		this._isArrow = true;
	},
	_moveScroll : function( index ) {
		var box = {
			start : this.element.scrollTop,
			end : this.info.maxHeight + this.element.scrollTop
		};
		var offset = this._optionList[index].getOffset();

		if ( offset.top < box.start ) {
			this.element.scrollTop -= offset.height;
		} else if ( ( offset.top + offset.height ) > box.end ) {
			this.element.scrollTop += offset.height;
		} 
	},
	_moveHotKeyScroll : function( index ) {
		if ( index == -1 ) return;
		var box = {
			start : this.element.scrollTop,
			end : this.info.maxHeight + this.element.scrollTop,
			height : this.info.maxHeight
		};
		var offset = this._optionList[index].getOffset();
		var viewPosition = offset.top + offset.height;

		if ( viewPosition < box.start ) {
			this.element.scrollTop = offset.top;
		} else if ( offset.top > box.end ) {
			this.element.scrollTop = viewPosition - box.height;
		}
	},
	display : function() {

		if ( this.select.box.element.style.display == "none" ) 
			this.show();
		else
			this.hide();
	},
	show : function() {
		if ( this.select.control.index.now != -1 )
			this.changeChildStyle( this.select.control.index.now );

		var pos = this.select.input.getPos();

		var coordi = { x : 0, y : 0 };
		if ( this.info.align == "left" ) {
			coordi.x = pos.x + "px";
			coordi.y = ( pos.y + this.info.boxY ) + "px";
		}		
		$Element( this.element ).css( {	display : "block", left : coordi.x, top : coordi.y } );
		if ( this.info.useIframe ) 
			$Element( this.iframe ).css( { 	display : "block", left : coordi.x, top : coordi.y, height : this.element.offsetHeight + "px" } );

		if ( this._hasScroll ) {
			this._moveHotKeyScroll( this.select.control.index.now );
		}
	},
	hide : function() {
		if ( this.info.useIframe )
			this.iframe.style.display = "none";
		this.element.style.display = "none";
	},
	isShow : function() {
		return this.element.style.display != "none";
	}
} );