namespace(
		'jindo2',
		function() {
			eval(namespace.imports('jindo2'));
			var Timer = function() {
				this.initialize.apply(this, arguments);
			};
			Timer.prototype = {
				_bInterval :false,
				_oInstance :null,
				initialize : function(sType) {
					this._bInterval = sType.toLowerCase() == "interval";
				},
				start : function(nTime, fCallback, pThis) {
					this.stop();
					if (this._bInterval) {
						this._oInstance = window.setInterval(fCallback, nTime);
					} else {
						var self = this;
						this._oInstance = window.setTimeout( function() {
							pThis ? fCallback.call(pThis) : fCallback();
							self.stop();
						}, nTime);
					}
				},
				stop : function() {
					var fFunc = window[this._bInterval ? "clearInterval"
							: "clearTimeout"];
					if (this._oInstance)
						fFunc(this._oInstance);
					this._oInstance = null;
				}
			};
			$Element._box_addon = {
				compatMode :document.compatMode || "BackCompat",
				getCSS : function(o, sPrefix, sPostfix, aWhich) {
					var size = 0;
					size += parseInt(o.css(sPrefix + aWhich[0] + sPostfix)) || 0;
					size += parseInt(o.css(sPrefix + aWhich[1] + sPostfix)) || 0;
					return size;
				},
				oldWidth :$Element.prototype.width,
				oldHeight :$Element.prototype.height,
				oldSize :$Element.prototype.size,
				adjustSize : function(o, nSize, sInclude, aWhich) {
					var addon = $Element._box_addon;
					var getCSS = addon.getCSS;
					if ($Agent().navigator().ie
							&& addon.compatMode == "BackCompat") {
						if (sInclude == "margin")
							nSize -= getCSS(o, "margin", "", aWhich);
						if (sInclude != "margin" && sInclude != "border")
							nSize += getCSS(o, "border", "Width", aWhich);
						if (sInclude != "margin" && sInclude != "padding"
								&& sInclude != "border")
							nSize += getCSS(o, "padding", "", aWhich);
					} else {
						switch (sInclude) {
						case "margin":
							nSize -= getCSS(o, "margin", "", aWhich);
						case "border":
							nSize -= getCSS(o, "border", "Width", aWhich);
						case "padding":
							nSize -= getCSS(o, "padding", "", aWhich);
						}
					}
					return nSize;
				},
				getElementSize : function(o, sInclude, aWhich) {
					var addon = $Element._box_addon;
					var getCSS = addon.getCSS;
					var nSize = o.$value()["offset" + aWhich[2]];
					if (nSize == 0 && !o.visible())
						return 0;
					switch (sInclude) {
					case "margin":
						nSize += getCSS(o, "margin", "", aWhich);
						break;
					case "border":
						break;
					default:
						if (sInclude != "padding")
							nSize -= getCSS(o, "padding", "", aWhich);
						nSize -= getCSS(o, "border", "Width", aWhich);
					}
					return nSize;
				},
				setWidth : function(nSize, sInclude) {
					this.$value().style.width = $Element._box_addon
							.adjustSize(this, nSize, sInclude, [ "Left",
									"Right", "Width" ]) + 'px';
					return this;
				},
				setHeight : function(nSize, sInclude) {
					this.$value().style.height = $Element._box_addon
							.adjustSize(this, nSize, sInclude, [ "Top",
									"Bottom", "Height" ]) + 'px';
					return this;
				},
				getWidth : function(sInclude) {
					return $Element._box_addon.getElementSize(this, sInclude, [
							"Left", "Right", "Width" ]);
				},
				getHeight : function(sInclude) {
					return $Element._box_addon.getElementSize(this, sInclude, [
							"Top", "Bottom", "Height" ]);
				}
			};
			$Element.prototype.width = function() {
				var len = arguments.length;
				var last;
				if (len == 0 || typeof arguments[len - 1] == 'number')
					return $Element._box_addon.oldWidth.apply(this, arguments);
				if (len > 1)
					return $Element._box_addon.setWidth.apply(this, arguments);
				else
					return $Element._box_addon.getWidth.apply(this, arguments);
			};
			$Element.prototype.height = function() {
				var len = arguments.length;
				var last;
				if (len == 0 || typeof arguments[len - 1] == 'number')
					return $Element._box_addon.oldHeight.apply(this, arguments);
				if (len > 1)
					return $Element._box_addon.setHeight.apply(this, arguments);
				else
					return $Element._box_addon.getHeight.apply(this, arguments);
			};
			$Element.prototype.fireEvent = function(sType, oParams) {
				var el = this.$value();
				var orgEvent = null;
				if (typeof sType != 'string') {
					orgEvent = sType._event || sType;
					sType = sType.type;
				}
				if (document.createEventObject) {
					var e = orgEvent;
					if (!e || oParams) {
						e = document.createEventObject();
						if (orgEvent)
							for ( var k in orgEvent)
								try {
									e[k] = orgEvent[k];
								} catch (ex) {
								}
						if (oParams)
							for ( var k in oParams)
								e[k] = oParams[k];
					}
					return el.fireEvent('on' + sType, e);
				}
				var e;
				var params = {
					canBubble :true,
					cancelable :true,
					view :window,
					detail :1,
					screenX :0,
					screenY :0,
					clientX :0,
					clientY :0,
					ctrlKey :false,
					altKey :false,
					shiftKey :false,
					metaKey :false,
					button :1,
					relatedTarget :null,
					keyCode :0,
					charCode :0
				};
				if (orgEvent)
					for ( var k in orgEvent)
						try {
							params[k] = orgEvent[k];
						} catch (ex) {
						}
				if (oParams)
					for ( var k in oParams)
						params[k] = oParams[k];
				switch (sType) {
				case 'click':
				case 'mousedown':
				case 'mouseup':
				case 'mouseover':
				case 'mouseout':
				case 'mousemove':
					e = document.createEvent('MouseEvents');
					e
							.initEvent(sType, params.canBubble,
									params.cancelable, params.view,
									params.detail, params.screenX,
									params.screenY, params.clientX,
									params.clientY, params.ctrlKey,
									params.altKey, params.shiftKey,
									params.metaKey, params.button,
									params.relatedTarget);
					break;
				case 'keydown':
				case 'keypress':
				case 'keyup':
					if (window.KeyEvent) {
						e = document.createEvent('KeyEvents');
						e.initKeyEvent(sType, params.cancelBubble,
								params.cancelable, params.view, params.ctrlKey,
								params.altKey, params.shiftKey, params.metaKey,
								params.keyCode, params.charCode);
						break;
					} else {
						e = document.createEvent('Events');
						e.initEvent(sType, params.cancelBubble,
								params.cancelable);
						e.view = params.view;
						e.altKey = params.altKey;
						e.ctrlKey = params.ctrlKey;
						e.shiftKey = params.shiftKey;
						e.metaKey = params.metaKey;
						e.keyCode = params.keyCode;
						e.charCode = params.charCode;
					}
				default:
					e = document.createEvent('HTMLEvents');
					e.initEvent(sType, params.canBubble, params.cancelable);
					break;
				}
				return el.dispatchEvent(e);
			};
			var SimulateFocus = $Class(
					{
						_object :null,
						_dummy :null,
						_timer :null,
						_options :null,
						_focused :false,
						$init : function(oEl, oOptions) {
							var e = $Element(oEl);
							this._options = {
								scrollable :false
							};
							for ( var k in oOptions)
								this._options[k] = oOptions[k];
							this._object = oEl;
							var self = this;
							this._object.focus = function() {
								self._dummy.disabled = false;
								return self._dummy.focus();
							};
							this._object.blur = function() {
								return self._dummy.blur();
							};
							this._createDummy();
							this._bindEvents();
						},
						_createDummy : function() {
							this._dummy = $(this._options.scrollable ? '<button>'
									: '<textarea>');
							with (this._dummy.style) {
								position = 'absolute';
								display = 'block';
								left = '-999999px';
								width = '50px';
							}
							;
							this._dummy.value = 'dummy';
							this._dummy.readOnly = true;
							this._rePositionDummy();
						},
						_rePositionDummy : function() {
							this._object.parentNode.insertBefore(this._dummy,
									this._object);
						},
						_fireFocusEvent : function(oEvent) {
							if (this._timer)
								clearTimeout(this._timer);
							this._timer = null;
							if (this._focused == true)
								return;
							this._focused = true;
							this.fireEvent('focus', oEvent);
						},
						_fireBlurEvent : function(oEvent) {
							var self = this;
							if (this._timer)
								clearTimeout(this._timer);
							var cloneEvent = document.createEventObject ? document
									.createEventObject(oEvent._event)
									: oEvent._event;
							this._timer = setTimeout( function() {
								if (self._focused == false)
									return;
								self._focused = false;
								self.fireEvent('blur', cloneEvent);
								delete cloneEvent;
								cloneEvent = null;
							}, 10);
						},
						_onDummyEvents : function(oEvent) {
							if (!this.fireEvent(oEvent.type, oEvent))
								oEvent.stop();
						},
						setFriend : function(oFriend) {
							var textboxes = cssquery(
									'textarea, input, button, select, a',
									oFriend);
							var oToss = $Fn(this._onDummyEvents, this);
							for ( var i = 0, textbox; textbox = textboxes[i]; i++) {
								var o = $Element(textbox);
								if (o.hasClass('-simfocus-friend'))
									return;
								o.addClass('-simfocus-friend');
								$Fn( function(oEvent) {
									this._dummy.disabled = true;
									this._fireFocusEvent(oEvent);
									this.fireEvent('fieldfocus', oEvent);
								}, this).attach(textbox, 'focus');
								$Fn( function(oEvent) {
									this._dummy.disabled = false;
									this._fireBlurEvent(oEvent);
									this.fireEvent('fieldblur', oEvent);
								}, this).attach(textbox, 'blur');
								oToss.attach(textbox, 'keydown');
								oToss.attach(textbox, 'keypress');
								oToss.attach(textbox, 'keyup');
							}
							return this;
						},
						_bindEvents : function() {
							$Fn(
									function(oEvent) {
										var el = oEvent.element;
										if (cssquery.test(el,
												'input, textarea, button, a'))
											return;
										var self = this;
										setTimeout( function() {
											try {
												self._dummy.focus();
											} catch (e) {
											}
										}, 0);
									}, this).attach(this._object, 'mousedown');
							$Fn(this._fireFocusEvent, this).attach(this._dummy,
									'focus');
							$Fn(this._fireBlurEvent, this).attach(this._dummy,
									'blur');
							var oToss = $Fn(this._onDummyEvents, this);
							oToss.attach(this._dummy, 'keydown');
							oToss.attach(this._dummy, 'keypress');
							oToss.attach(this._dummy, 'keyup');
							this.setFriend(this._object);
						}
					}).extend(nhn.Component);
			var Selectbox = $Class(
					{
						tagName :'select',
						_agent :$Agent().navigator(),
						_object :null,
						_options :null,
						_focusTimer :null,
						_comboTimer :null,
						_customTimer :null,
						_simfocus :null,
						_items :null,
						_customs :null,
						_title :'',
						_selectedIndex :-1,
						_hoveredIndex :-1,
						_heightFitted :false,
						_heightOverflowed :false,
						_comboChanged :false,
						_needle :'',
						_handlers : {
							box : {
								focus : function(oEvent) {
									var o = this._object;
									if (o.source.disabled)
										return;
									var sPrefix = this.option('classPrefix');
									this._focusTimer.stop();
									var selectbox = $Element(o.selectbox);
									if (selectbox.hasClass(sPrefix + 'focused'))
										return;
									selectbox.addClass(sPrefix + 'focused');
									this.fireEvent('focus');
								},
								blur : function(oEvent) {
									var o = this._object;
									var sPrefix = this.option('classPrefix');
									this._focusTimer.start(50, function() {
										$Element(o.selectbox).removeClass(
												sPrefix + 'focused');
										this._showLayer(false);
										this.fireEvent('blur');
									}, this);
								},
								keydown : function(oEvent) {
									var o = this._object;
									var keyCode = oEvent.key().keyCode;
									if (o.source.disabled)
										return;
									var el = oEvent.element;
									if (this.fireEvent('keydown', oEvent)) {
										switch (keyCode) {
										case 38:
											this.selectAbove(1);
											this._paintLabel();
											oEvent.stop();
											break;
										case 40:
											this.selectBelow(1);
											this._paintLabel();
											oEvent.stop();
											break;
										case 33:
											this.selectAbove(Infinity);
											this._paintLabel();
											oEvent.stop();
											break;
										case 34:
											this.selectBelow(Infinity);
											this._paintLabel();
											oEvent.stop();
											break;
										case 13:
											if (this._isVisibleLayer())
												this._showLayer(false);
											oEvent.stop();
											break;
										}
										var item = this._items[this._selectedIndex];
										if (el == o.combobox) {
											var orgValue = o.combobox.value;
											this._comboTimer
													.start(
															0,
															function() {
																var newValue = o.combobox.value;
																if (orgValue == newValue)
																	return;
																this._comboChanged = true;
																o.source.selectedIndex = this._pseudoIndex;
																this._pseudo.value = newValue;
																this
																		._paintItem();
															}, this);
										} else if (item && !item.custom) {
											switch (keyCode) {
											case 37:
												this.selectAbove(1);
												this._paintLabel();
												oEvent.stop();
												break;
											case 39:
												this.selectBelow(1);
												this._paintLabel();
												oEvent.stop();
												break;
											default:
												var sChar = String
														.fromCharCode(keyCode);
												if (/[a-z0-9 ]/i.test(sChar)) {
													this._needle += sChar
															.toUpperCase();
													var idx = this
															._findMatchItem();
													if (idx != -1)
														this
																._setSelectedIndex(idx);
													oEvent.stop();
												}
												this._paintLabel();
												break;
											}
										} else if (this.option('customValue')) {
											var orgValue = this.option(
													'customValue').call(this,
													item.custom, item.object);
											this._comboTimer
													.start(
															0,
															function() {
																item = this
																		._setCustomValue(item);
																if (orgValue == item.source.value)
																	return;
																this._comboChanged = true;
																this
																		._paintLabel();
															}, this);
										}
									}
									this._paintItem();
								},
								mousedown : function(oEvent) {
									var o = this._object;
									if (o.source.disabled)
										return;
									if (oEvent.element == o.combobox) {
										this._showLayer(false);
										return;
									}
									this._showLayer();
									if (o.combobox)
										setTimeout( function() {
											o.combobox.focus();
										}, 10);
								}
							},
							combobox : {
								keyup : function(oEvent) {
								}
							},
							layer : {
								mousedown : function(oEvent) {
									var o = this._object;
									if (o.source.disabled)
										return;
									var isForm = cssquery.test(oEvent.element,
											'input, textarea, button, a');
									var idx = this
											._getItemIndexFromEvent(oEvent);
									if (idx != -1 && this._items[idx].custom
											&& isForm)
										return;
									this._delayCall(0, function() {
										try {
											o.box.focus();
										} catch (e) {
										}
									});
								}
							},
							list : {
								mouseover : function(oEvent) {
									var idx = this
											._getItemIndexFromEvent(oEvent);
									if (idx == -1)
										return;
									var item = this._items[idx];
									if (item.disable)
										return;
									this._addHoveredClass(idx);
								},
								mousedown : function(oEvent) {
									var idx = this
											._getItemIndexFromEvent(oEvent);
									if (idx == -1)
										return;
									if (!this.fireEvent('itemclick', {
										itemIndex :idx,
										itemObject :item
									}))
										return;
									var item = this._items[idx];
									if (item.disable)
										return;
									this._setSelectedIndex(idx);
									this._paintLabel();
									this._paintItem();
									if (this.option('closeOnClickItem')
											&& !item.custom)
										this._showLayer(false);
								}
							},
							field : {
								focus : function(oEvent) {
									var el = oEvent.element;
									var sPrefix = this.option('classPrefix');
									this._customTimer
											.start(
													10,
													function() {
														for (; el && el.tagName; el = el.parentNode) {
															var e = $Element(el);
															if (e
																	.hasClass(sPrefix + 'item-selected'))
																return;
															if (e
																	.hasClass(sPrefix + 'list'))
																return this
																		._showLayer(false);
														}
													}, this);
								}
							}
						},
						$init : function(vEl, oOptions) {
							var o = this._object = {};
							var uniq = Math.round(new Date().getTime() * 10000)
									+ Math.random() * 10000;
							var uniqid = 'selectbox(' + uniq + ')';
							this.option( {
								useHtml :false,
								closeOnClickItem :true,
								classPrefix :'selectbox-'
							});
							this.option(oOptions || {});
							var sPrefix = this.option('classPrefix');
							o.selectbox = $(vEl);
							if (cssquery.test(o.selectbox, 'select'))
								o.selectbox = cssquery(
										'! .' + sPrefix + 'naked', o.selectbox)[0];
							o.source = cssquery('select.' + sPrefix + 'source',
									o.selectbox)[0];
							o.box = cssquery('.' + sPrefix + 'box', o.selectbox)[0];
							o.label = cssquery('.' + sPrefix + 'label',
									o.selectbox)[0];
							o.combobox = cssquery(
									'input.' + sPrefix + 'combobox',
									o.selectbox)[0];
							var sLayer = this.option('layer');
							if (sLayer) {
								o.layer = $(sLayer);
								document.body.insertBefore(o.layer,
										document.body.firstChild);
							} else {
								o.layer = cssquery('.' + sPrefix + 'layer',
										o.selectbox)[0];
							}
							o.list = cssquery.test(o.layer,
									'ul.' + sPrefix + 'list') ? o.layer
									: cssquery('ul.' + sPrefix + 'list',
											o.layer)[0];
							if (o.combobox)
								o.label.appendChild(o.combobox);
							$Element(o.selectbox)
									.removeClass(sPrefix + 'naked');
							$Element(o.selectbox).addClass(sPrefix + 'applied');
							$Element(o.source).css( {
								position :'absolute',
								visibility :'hidden',
								display :'block'
							});
							this._processCustoms();
							this._showLayer(false);
							this._focusTimer = new Timer('timeout');
							this._comboTimer = new Timer('timeout');
							this._customTimer = new Timer('timeout');
							this._simfocus = new SimulateFocus(o.box);
							this._bindEvents();
							this.paint();
							$Element(o.selectbox).addClass(uniqid);
							$Element(o.layer).addClass(uniqid);
							Selectbox._instanceKeys[uniq] = this;
						},
						_toRegExp : function(sStr) {
							return sStr.replace(/\-/g, '\\-');
						},
						_getCustom : function(oEl) {
							var sPrefix = this.option('classPrefix');
							if (new RegExp(
									'\\b' + this._toRegExp(sPrefix) + 'item\\-custom\\(([^\\)]+)\\)')
									.test(oEl.className))
								return RegExp.$1;
						},
						_processCustoms : function() {
							var o = this._object;
							var lis = cssquery('> li', o.list);
							this._custom = [];
							var custom;
							for ( var i = 0, li; li = lis[i]; i++) {
								if (custom = this._getCustom(li)) {
									var q = cssquery('input', li)[0];
									this._custom[custom] = li.cloneNode(true);
								}
							}
						},
						_paintPseudoItem : function() {
							var sPrefix = this.option('classPrefix');
							var o = this._object;
							if (!o.combobox)
								return;
							var pseudo = cssquery(
									'option.' + sPrefix + 'item-pseudo',
									o.source)[0];
							if (pseudo) {
								this._pseudo = pseudo;
								this._pseudoIndex = pseudo.index;
								return;
							}
							var pseudo = this._pseudo = $('<option>');
							this._pseudoIndex = o.source.options.length;
							pseudo.className = sPrefix + 'item-pseudo '
									+ sPrefix + 'invisible';
							pseudo.innerHTML = '�޺��ڽ� �׸�';
							o.source.appendChild(pseudo);
						},
						_findMatchItem : function(nGap) {
							var len = this._items.length;
							var start = this._object.source.selectedIndex;
							var needle = this._needle;
							var offset = -1;
							if (typeof nGap == 'undefined')
								nGap = 0;
							for ( var i = start + nGap; i < start + len; i++) {
								var idx = i % len;
								var found = this._items[idx].found;
								if (found.indexOf(needle) == 0) {
									offset = idx;
									break;
								}
							}
							if (offset == -1 && needle.length > 1) {
								this._needle = needle = needle
										.substr(needle.length - 1);
								offset = this._findMatchItem(1);
							}
							return offset;
						},
						_delayCall : function(nDelay, fpFunc) {
							setTimeout($Fn(fpFunc, this).bind(), nDelay);
						},
						_text : function(option) {
							var oOptions = this._options;
							return oOptions.useHtml ? (option.textContent || option.innerText)
									: option.innerHTML;
						},
						_value : function(option) {
							return option.getAttribute('value') || '';
						},
						_isVisibleLayer : function() {
							var layer = this._object.layer;
							return $Element(layer).visible();
						},
						_showLayer : function(bFlag) {
							var layer = $Element(this._object.layer);
							var visible = layer.visible();
							if (typeof bFlag == 'undefined')
								bFlag = !visible;
							if (bFlag != visible
									&& !this
											.fireEvent(bFlag ? 'open' : 'close'))
								return;
							layer[bFlag ? 'show' : 'hide']();
							if (bFlag) {
								this._paintHeight();
								this._paintItem();
								this._paintLayer();
							} else {
								this._fireChangeEvent();
							}
						},
						_fireChangeEvent : function() {
							var o = this._object;
							if (this._comboChanged) {
								this._comboChanged = false;
								this._onCustomSelect();
								var nSelectedIndex = o.source.selectedIndex;
								$Element(o.source).fireEvent('change');
								this.fireEvent('change', {
									custom :this._items[nSelectedIndex].custom
								});
							}
						},
						_onCustomSelect : function() {
							var o = this._object;
							var sPrefix = this.option('classPrefix');
							if (!$Element(o.selectbox).hasClass(
									sPrefix + 'focused'))
								return;
							var item = this._setCustomValue();
							if (!item)
								return;
							if (!this._isVisibleLayer())
								this._showLayer(true);
							var self = this;
							if (this.option('customSelect'))
								setTimeout( function() {
									self.option('customSelect').call(self,
											item.custom, item.object);
								}, 0);
						},
						_setCustomValue : function(item) {
							var o = this._object;
							if (!item)
								item = this._items[o.source.selectedIndex];
							if (!item.custom)
								return;
							var value = this.option('customValue').call(this,
									item.custom, item.object);
							item.source.value = value;
							return item;
						},
						_getItemIndexFromEvent : function(oEvent) {
							var el = oEvent.element;
							if (el.tagName.toLowerCase() != 'li')
								el = cssquery('! li', el)[0];
							return this._getItemIndex(el);
						},
						_getItemIndex : function(item) {
							var sPrefix = this.option('classPrefix');
							if (item
									&& new RegExp(
											'\\b' + this._toRegExp(sPrefix) + 'item\\(([0-9]+)\\)')
											.test(item.className)) {
								var r = parseInt(RegExp.$1);
								return isNaN(r) ? -1 : r;
							}
							return -1;
						},
						selectAbove : function(nOffset) {
							return this._addSelectedIndex(-nOffset);
						},
						selectBelow : function(nOffset) {
							return this._addSelectedIndex(nOffset);
						},
						_addSelectedIndex : function(nOffset) {
							var o = this._object;
							var tarIndex = -1;
							var orgIndex = this._selectedIndex;
							var newIndex = orgIndex + nOffset;
							var len = this._items.length;
							if (newIndex < 0)
								newIndex = 0;
							if (newIndex > len - 1)
								newIndex = len - 1;
							if (orgIndex < newIndex) {
								for (tarIndex = newIndex; tarIndex < len
										&& this._items[tarIndex].disable; tarIndex++) {
								}
								if (tarIndex >= len)
									for (tarIndex = newIndex; tarIndex >= orgIndex
											&& this._items[tarIndex].disable; tarIndex--) {
									}
							} else {
								for (tarIndex = newIndex; tarIndex >= 0
										&& this._items[tarIndex].disable; tarIndex--) {
								}
								if (tarIndex < 0)
									for (tarIndex = newIndex; tarIndex <= orgIndex
											&& this._items[tarIndex].disable; tarIndex++) {
									}
							}
							this._setSelectedIndex(tarIndex);
						},
						_setSelectedIndex : function(nIndex) {
							var o = this._object;
							if (o.source.selectedIndex == nIndex)
								return;
							o.source.selectedIndex = nIndex;
							this._comboChanged = true;
							this._fireChangeEvent();
						},
						_bindEvents : function() {
							var o = this._object;
							this._simfocus
									.attach( {
										focus :$Fn(this._handlers.box.focus,
												this).bind(),
										blur :$Fn(this._handlers.box.blur, this)
												.bind(),
										fieldfocus :$Fn(
												this._handlers.field.focus,
												this).bind()
									});
							this._simfocus.attach(
									this._agent.opera ? 'keypress' : 'keydown',
									$Fn(this._handlers.box.keydown, this)
											.bind());
							$Fn(this._handlers.box.mousedown, this).attach(
									o.box, 'mousedown');
							$Fn(this._handlers.combobox.keyup, this).attach(
									o.box, 'keyup');
							$Fn(this._handlers.layer.mousedown, this).attach(
									o.layer, 'mousedown');
							$Fn(this._handlers.list.mouseover, this).attach(
									o.list, 'mouseover');
							$Fn(this._handlers.list.mousedown, this).attach(
									o.list, 'mousedown');
						},
						_removeSelectedClass : function() {
							var sPrefix = this.option('classPrefix');
							var item;
							var nIndex = this._selectedIndex;
							if (nIndex == -1)
								return;
							if ((item = this._items[nIndex]) && item.object) {
								$Element(item.object).removeClass(
										sPrefix + 'item-selected');
							}
							this._selectedIndex = -1;
						},
						_addSelectedClass : function(nIndex) {
							var sPrefix = this.option('classPrefix');
							this._removeSelectedClass();
							var item;
							if (nIndex == -1)
								return;
							if ((item = this._items[nIndex]) && item.object) {
								$Element(item.object).addClass(
										sPrefix + 'item-selected');
								this._selectedIndex = nIndex;
							}
						},
						_removeHoveredClass : function() {
							var sPrefix = this.option('classPrefix');
							var item;
							var nIndex = this._hoveredIndex;
							if (nIndex == -1)
								return;
							if ((item = this._items[nIndex]) && item.object) {
								$Element(item.object).removeClass(
										sPrefix + 'item-hovered');
							}
							this._hoveredIndex = -1;
						},
						_addHoveredClass : function(nIndex) {
							var sPrefix = this.option('classPrefix');
							this._removeHoveredClass();
							var item;
							if (nIndex == -1)
								return;
							if ((item = this._items[nIndex]) && item.object) {
								$Element(item.object).addClass(
										sPrefix + 'item-hovered');
								this._hoveredIndex = nIndex;
							}
						},
						paint : function() {
							var o = this._object;
							var sPrefix = this.option('classPrefix');
							this._paintWidth();
							this._paintPseudoItem();
							this._paintItems();
							this._paintLabel();
							this._paintItem();
							var bDisabled = o.source.disabled;
							this._simfocus._object.disabled = bDisabled;
							$Element(o.selectbox)[bDisabled ? 'addClass'
									: 'removeClass'](sPrefix + 'disabled');
							if (bDisabled) {
								this._showLayer(false);
								this._handlers.box.blur.call(this);
							}
						},
						paintValue : function() {
							this._setCustomValue();
							this._paintLabel();
						},
						_paintWidth : function() {
							var o = this._object;
							var oOptions = this._options;
							var toPx = function(width) {
								if (typeof width == 'string') {
									if (/^[0-9]+%$/.test(width))
										width = Math.round(parseInt(width)
												* o.source.offsetWidth / 100);
									else
										width = parseInt(width);
								}
								return width;
							};
							$Element(o.source).show();
							var boxWidth = toPx(oOptions.boxWidth
									|| oOptions.width);
							var layerWidth = toPx(oOptions.layerWidth
									|| oOptions.width);
							$Element(o.source).hide();
							if (!isNaN(boxWidth))
								$Element(o.box).css( {
									width :boxWidth + 'px'
								});
							if (!isNaN(layerWidth))
								$Element(o.layer).css( {
									width :layerWidth + 'px'
								});
						},
						_paintHeight : function() {
							var height = this.option('height');
							if (!height || this._heightFitted)
								return;
							var o = this._object;
							if (o.list.offsetHeight > height) {
								o.list.style.height = height + 'px';
								if (this._agent.safari) {
									o.list.style.overflow = 'scroll';
									o.list.style.overflowX = 'hidden';
								} else {
									o.list.style.overflow = 'auto';
								}
								this._heightOverflowed = true;
							}
							this._heightFitted = true;
						},
						_paintLayer : function() {
							var o = this._object;
							var sPrefix = this.option('classPrefix');
							var layer = $Element(o.layer);
							var box = $Element(o.box);
							var pos = box.offset();
							var layerHeight = layer.height('margin');
							var boxHeight = box.height('margin');
							var layerBottom = pos.top + o.box.offsetHeight
									+ layerHeight;
							var scrBottom = (document.documentElement.scrollTop || document.body.scrollTop)
									+ (window.innerHeight
											|| document.documentElement.clientHeight || document.body.clientHeight);
							var overflowed = layerBottom > scrBottom;
							layer[overflowed ? 'addClass' : 'removeClass']
									(sPrefix + 'layer-above');
							if (this.option('layer')) {
								if (overflowed) {
									o.layer.style.top = pos.top - layerHeight
											+ 'px';
									o.layer.style.left = pos.left + 'px';
								} else {
									o.layer.style.top = pos.top + boxHeight
											+ 'px';
									o.layer.style.left = pos.left + 'px';
								}
							}
						},
						_paintItems : function() {
							var o = this._object;
							var sPrefix = this.option('classPrefix');
							var aOptions = cssquery('option', o.source);
							this._items = [];
							o.list.innerHTML = '';
							o.list.style.height = 'auto';
							for ( var i = 0, eOption; eOption = aOptions[i]; i++) {
								var oOption = $Element(eOption);
								var invisible = oOption
										.hasClass(sPrefix + 'invisible');
								var disable = invisible
										|| oOption
												.hasClass(sPrefix + 'item-pseudo')
										|| eOption.disabled;
								var custom = this._getCustom(eOption);
								var li = null;
								var text = this._text(eOption) || '';
								if (!invisible) {
									if (custom && this._custom[custom]) {
										li = this._custom[custom]
												.cloneNode(true);
									} else {
										li = $('<li>');
										li.style.cssText = eOption.style.cssText;
										li.innerHTML = text;
									}
									li.className = (eOption.className || '')
											+ ' ' + sPrefix + 'item(' + i + ')';
									o.list.appendChild(li);
								}
								this._items[i] = {
									'index' :i,
									'source' :eOption,
									'object' :li,
									'text' :text,
									'found' :text.toUpperCase(),
									'invisible' :invisible,
									'disable' :disable,
									'custom' :custom
								};
							}
							this._simfocus.setFriend(o.list);
							this._heightFitted = false;
							this._heightOverflowed = false;
						},
						_paintLabel : function() {
							var o = this._object;
							var idx = o.source.selectedIndex;
							if (idx == -1)
								return;
							var item = this._items[idx];
							if (o.combobox) {
								if (item.custom) {
									o.combobox.value = this._value(item.source);
								} else {
									o.combobox.value = this._value(item.source);
									o.combobox.select();
								}
								return;
							}
							var label = o.source.title;
							if (!label)
								label = item.text;
							$Element(o.label).html(label);
						},
						_paintItem : function() {
							var o = this._object;
							var nIndex = o.source.selectedIndex;
							this._customTimer.stop();
							this._addSelectedClass(nIndex);
							this._addHoveredClass(nIndex);
							var item = this._items[nIndex];
							if (!item)
								return;
							var li = item.object;
							if (li && this._isVisibleLayer()
									&& this._heightOverflowed) {
								var wrapper = li.offsetParent;
								var top = li.offsetTop
										- li.parentNode.offsetTop;
								var range = [ o.list.scrollTop,
										o.list.scrollTop + o.list.clientHeight ];
								var itemrgn = [ top, top + li.offsetHeight ];
								if (range[0] > itemrgn[0])
									o.list.scrollTop = itemrgn[0];
								if (range[1] < itemrgn[1])
									o.list.scrollTop += itemrgn[1] - range[1];
							}
						}
					}).extend(nhn.HTMLComponent);
			Selectbox._instanceKeys = {};
			Selectbox.getInstance = function(o) {
				var regexp = /\bselectbox\(([0-9]+)\)/;
				for ( var className; o && (className = o.className); o = o.parentNode)
					if (regexp.test(className))
						return Selectbox._instanceKeys[RegExp.$1];
				return null;
			};
			eval(namespace.exports('Selectbox'));
		});