// @author Park Kyungil
// email : kyungil_park@tmax.co.kr
// last updated 2009/03/03
// import prototype.js
// import prowave.js
// known issue : item에서 memory leak이 있음
var pwComboBox = function() {}
pwComboBox._createController = function() {
	pwComboBox.ctl = document.createElement("div");
	pwComboBox.ctl.id = "pw:comboBox";
	pwComboBox.ctl.style.position = "absolute";
	pwComboBox.ctl.style.left = "0";
	pwComboBox.ctl.style.top = "0";
	document.body.appendChild(pwComboBox.ctl);
	pwComboBox.gc = document.createElement("div");
	pwComboBox.gc.id = "pw:comboBox:gc";
	pwComboBox.gc.style.display = "none";
	pwComboBox.ctl.appendChild(pwComboBox.gc);
}
pwComboBox.ctl = document.getElementById("pw:comboBox");
if (!pwComboBox.ctl) {
	if (document.body) {
		pwComboBox._createController();
	} else {
		Event.observe(window, "load", function() {
			pwComboBox._createController();
		}, false);
	}
}
pwComboBox.viewportOffset = function(forElement) {
	var valueT = 0, valueL = 0;
	//2009/03/03:border관련보정값 계산방법 수정 
	// TODO:Safari는 테이블 관련 추가 보정 필요함 (table의 border style이 있으면서 td에는 border가 없는 경우, 계산방법이 없음)
	// TODO:상위에 relative가 있는 경우, border width 계산이 안됨.
	// add cumulativeOffset
	var element = forElement;
	if (Prototype.Browser.IE) { // IE의 경우 table계산이 특이해서 clientTop, clientLeft를 사용해야 함
		do {
			valueT += element.offsetTop  || 0;
			valueL += element.offsetLeft || 0;
			if (element.tagName == "TABLE") { // table인 경우, skip
				continue;
			}
			if (element.tagName=="TD") {
				// table인 경우 td의 clientTop, clientLeft로 border를 보정함
				valueT += element.clientTop || 0;
				valueL += element.clientLeft || 0;
			} else if (Element.getStyle(element,'display') == "block") {
				// block 인 경우 border를 보정함 
				// 주의: border color값이 이상하게 들어갈 경우, 실제 렌더링시 borderWidth는 무시되는데 api에서 가져오는 값은 유지되는 경우가 있음
				valueT += parseInt(Element.getStyle(element,'borderTopWidth')) || 0;
				valueL += parseInt(Element.getStyle(element,'borderLeftWidth')) || 0;
			}
		} while (element = element.offsetParent);
	} else {
		do {
			valueT += element.offsetTop  || 0;
			valueL += element.offsetLeft || 0;
			if (Prototype.Browser.Opera) continue; // Opera는 다른 보정 필요없음
			if (Element.getStyle(element,'position') && Element.getStyle(element,'position') != "static") {
				// absolute position에 border style이 있는 경우 add
				valueT += parseInt(Element.getStyle(element,'borderTopWidth')) || 0;
				valueL += parseInt(Element.getStyle(element,'borderLeftWidth')) || 0;
			}
			if (element.tagName == "TABLE") {
				if (element.border && element.border > 0) { // table.border 값이 있는 경우 보정
					valueT += 1;
					valueL += 1;
				}
				if (Prototype.Browser.WebKit) { // WebKit인 경우, style의 border도 추가
					valueT += parseInt(Element.getStyle(element,'borderTopWidth')) || 0;
					valueL += parseInt(Element.getStyle(element,'borderLeftWidth')) || 0;
				}
			}
// Safari fix
//		if (element.offsetParent == document.body &&
//			Element.getStyle(element, 'position') == 'absolute') break;
		} while (element = element.offsetParent);
	}
	// substract cumulativeScrollOffset
	element = forElement;
	do {
		if (Prototype.Browser.Opera) {
			if (element.tagName == 'BODY') {
				valueT -= element.scrollTop  || 0;
				valueL -= element.scrollLeft || 0;
			} else if (element.style) {
				if (element.style.overflow) {
					valueT -= element.scrollTop  || 0;
					valueL -= element.scrollLeft || 0;
				}
			}
		} else {
			valueT -= element.scrollTop  || 0;
			valueL -= element.scrollLeft || 0;
		}
	} while (element = element.parentNode);
	return [valueL, valueT];
}

pwComboBox.current = null;
pwComboBox.replacePopup = function(popup) {
	popup.parentNode.removeChild(popup);
	var gPopupId = "pw:comboBox:"+popup.id;
	var prevPopup = document.getElementById(gPopupId);
	if (prevPopup) {
		pwComboBox.ctl.replaceChild(popup,prevPopup);
		pwComboBox.gc.appendChild(prevPopup);
		pwComboBox.gc.innerHTML="";
	} else {
		pwComboBox.ctl.appendChild(popup);
	}
	popup.id = gPopupId;
	return popup;
}
pwComboBox.hidePopup = function() {
	if (!pwComboBox.current) return; // popup된 combo가 있는지 확인
	if (pwComboBox.current.pwtype!="pw:comboBox") { // reference가 comboBox가 맞는지 확인
		pwComboBox.current = null;
		return;
	}
	if (!pwComboBox.current.popup.isShow) return; // 정말 열려있는지 확인
	if (pwComboBox.current.bEventOnCombobox) { // combo 내에서 발생한 이벤트이면 skip
		pwComboBox.current.bEventOnCombobox = false;
	} else {
		pwComboBox.current._hidePopup();
		pwComboBox.current = null;
	}
}
pwComboBox._scrollhandler = function() {
	if (!pwComboBox.current) return; // popup된 combo가 있는지 확인
	if (pwComboBox.current.pwtype!="pw:comboBox") { // reference가 comboBox가 맞는지 확인
		pwComboBox.current = null;
		return;
	}
	if (!pwComboBox.current.popup.isShow) return; // 정말 열려있는지 확인
	if (pwComboBox.current.bEventOnCombobox) { // combo 내에서 발생한 이벤트이면 skip
		pwComboBox.current.bEventOnCombobox = false;
	} else {
		pwComboBox.current.textbox.blur(); // blur해줄것!!
		pwComboBox.current._hidePopup();
		pwComboBox.current = null;
	}
}
// hide current popup in case of click/mousewheel on outside of combo
Event.observe(document, "click", pwComboBox.hidePopup, false);
if (Prototype.Browser.IE) {
	Event.observe(document, "mousewheel", pwComboBox._scrollhandler, false);
} else {
	Event.observe(window, "scroll", pwComboBox._scrollhandler, false);
}

pwComboBox.setCurrent = function(combo) {
	// set current combo
	if(pwComboBox.current) {
		if(pwComboBox.current != combo) {
			pwComboBox.current._hidePopup();
			pwComboBox.current = combo;
		}
	} else {
		pwComboBox.current = combo;
	}
}

ProWaveComboBox = function(params) {
	this.pwtype = "pw:comboBox";
	// params set
	this.id = params.id;
	this.multiSelect = params.multiSelect||false;
	this.editable = params.editable||false;
	this.hasTextLabel = params.hasTextLabel||false;
	this.columns = params.columns||1;
	this.showCheckbox = params.showCheckbox||false;
	this.showCheckbox = this.multiSelect&&this.showCheckbox;
	// constants
	this.themePrefix = "comboBox";
	this.sItemStyle = this.themePrefix + "-item";
	this.sItemOverStyle = this.sItemStyle + " " + this.themePrefix + "-item-hover";
	this.sItemSelectedStyle = this.sItemStyle + " " + this.themePrefix + "-item-selected";
	this.bEventOnCombobox = false;
	this.bLoadPopup = false;

	// onload에서 init할 경우 ajax시 update안됨
	this._init();
}

ProWaveComboBox.prototype._init = function() {
	// init
	this.container = document.getElementById(this.id+":container");
	this.textbox = document.getElementById(this.id);
	this.textbox.style.cursor = "default";
	this.textbox.sNormalStyle = this.textbox.className;
	this.select = document.getElementById(this.id+".select");
	this.popup = document.getElementById(this.id+".popup");
	this.popup.isShow = false;
	this.popup.bSizeSet = false;

	// attach combobox Event Listener
	if (ProWave.oldIE) { // for under IE6:IE6이하에서는 <a>태그만 hover를 인식하므로 event를 달아줌
		Event.observe(this.textbox, "mouseout", function(event)
		{
			this.textbox.className = this.textbox.sNormalStyle;
			Event.stop(event);
		}.bind(this), false);
		Event.observe(this.textbox, "mouseover", function(event)
		{
			this.textbox.className = this.textbox.sNormalStyle + " " + this.textbox.sNormalStyle + "-hover";
			Event.stop(event);
		}.bind(this), false);
	}
	Event.observe(this.textbox, "click", function(event)
	{
		//this._togglePopup();
		//this.bEventOnCombobox = true;
		Event.stop(event);
	}.bind(this), false);
	Event.observe(this.textbox, "focus", function(event)
	{
		if (!pwComboBox.ctl) {
			this.textbox.blur(); // 2008/12/23: validation 오류시 focus때문에 ctl이 만들어지기 전에 호출되어 문제가 됨
			return;
		}
		pwComboBox.setCurrent(this);
		this._togglePopup();
	}.bind(this), false);
	// hide popup list in case of keydown by ESC, ENTER, TAB
	Event.observe(this.textbox, "keydown", this._keydownhandler.bind(this), false);
	//Event.observe(this.container, "mousewheel", function(){this.bEventOnCombobox = true;}.bind(this), false);
	if (Prototype.Browser.IE) {
		Event.observe(this.popup, "mousewheel", function(){this.bEventOnCombobox = true;}.bind(this), false);
	} else {
		Event.observe(this.popup, "scroll", function(){this.bEventOnCombobox = true;}.bind(this), false);
	}

	// set combobox value or textlabel
	this._setTextLabel(this._getSelectedString());
	// if multiSelect=true && ajax update
	if(this.multiSelect && pwComboBox.current && pwComboBox.current.id == this.id) {
		this.textbox.focus();
	}
}

ProWaveComboBox.prototype._setTextLabel = function(text) {
	if (!this.hasTextLabel) {
		this.textbox.value = text;
/* Table 내에 있으면 init시 width 계산이 안되므로 css의 expression으로 변경함
		if (Prototype.Browser.IE) {
			if (this.textbox.offsetWidth < this.textbox.scrollWidth) {
				var len = text.length;
				len = parseInt(len*this.textbox.offsetWidth/this.textbox.scrollWidth);
				this.textbox.value = text.substring(0,len-1);
			}
		}
*/		
	}
}

ProWaveComboBox.prototype._loadPopup = function() {	// lazy load popuplist
	if (!this.bLoadPopup) {
		pwComboBox.replacePopup(this.popup);

		// popup list items setting
		this.items = new Array();
		for (var i=0, max=this.select.options.length; i < max; i++) {
			this.items[i] = document.getElementById(this.id+".item"+i);
			this.items[i].bind = this.select.options[i];	// hidden select의 option을 바인딩한다.
	
			if (this.items[i].bind.disabled) {
			} else {
				// item style
				this._setItemStyle(this.items[i]);
				// attach item Event Listener 
				if (ProWave.oldIE) { // for under IE6:IE6이하에서는 <a>태그만 hover를 인식하므로 event를 달아줌
					Event.observe(this.items[i], "mouseover", function(event, item)
					{
						item.className = this.sItemOverStyle;
						Event.stop(event);
					}.bindAsEventListener(this, this.items[i]), false);

					Event.observe(this.items[i], "mouseout", function(event, item)
					{
						item.className = item.sNormalStyle;
						Event.stop(event);
					}.bindAsEventListener(this, this.items[i]), false);
				}

				if (this.multiSelect) {
					if (this.showCheckbox) {
						var first = this.items[i].firstChild;
						var checkbox = document.createElement("input");
						checkbox.type = "checkbox";
//						checkbox.readonly = "readonly";
						if (this.items[i].bind.selected) {
							checkbox.checked = "checked";
						}
						this.items[i].insertBefore(checkbox, first);
						this.items[i].checkbox = checkbox;
					}
	
					Event.observe(this.items[i], "click", function(event, item)
					{
						// toggle selected & set style
						item.bind.selected = !(item.bind.selected);
						if(item.checkbox) {
							if (item.bind.selected) {
								item.checkbox.checked = true;
							} else {
								item.checkbox.checked = false;
							}
						}
						this._setItemStyle(item);
						this._setTextLabel(this._getSelectedString());
						ProWave.fireEvent(this.textbox, "change");
						this.bEventOnCombobox = true;
						// Event.stop(event);하면 showCheckbox일 경우 checked가 제대로 안됨
					}.bindAsEventListener(this, this.items[i]), false);
				} else {
					Event.observe(this.items[i], "click", function(event, item)
					{
						// toggle selected & set style
						if (!item.bind.selected) {
							item.bind.selected = true;
							for (i = 0, max = this.items.length; i < max ; i++) {
								this._setItemStyle(this.items[i]);
							}
							this._setTextLabel(item.bind.text);
							ProWave.fireEvent(this.textbox, "change");
						}
						this._hidePopup();
						Event.stop(event);
					}.bindAsEventListener(this, this.items[i]), false);
				}
			}
		}
	
		if (this.editable) {
			Event.observe(this.textbox, "keyup", function(event)
			{
				var idx = this.select.selectedIndex;
				if (idx > 0) {
					this.select.selectedIndex = 0;
					this._setItemStyle(this.items[idx]);
				}
				this.items[0].bind.value=this.textbox.value;
			}.bind(this), false);
			// FF,safari에서 change이벤트 발생 후 key이벤트가 발생하기 때문에 event를 stop함.
			Event.observe(this.textbox, "change", function(event)
			{
				this.textbox.blur();
				Event.stop(event);
			}.bind(this), false);
		}
		this.bLoadPopup = true;
	}
}

ProWaveComboBox.prototype._keydownhandler = function(event) {
	if (!this.popup.isShow) return;
	try {
		if (event && (event.keyCode == 27 || event.keyCode == 13 || event.keyCode == 9)) { //KEY_ESC||KEY_RETURN||KEY_TAB
			this._hidePopup();
		}
	} catch(ex) {}
}

ProWaveComboBox.prototype._togglePopup = function() {
	if (this.popup.isShow) {
		this._hidePopup();
	} else  {
		this._showPopup();
	}
}

ProWaveComboBox.prototype._hidePopup = function() {
	this.popup.style.display = "none";
	this.popup.isShow = false;
	if (ProWave.oldIE) {
		ProWave.showMSCtl(this.popup, pwComboBox.ctl); //sharing global iframe
	}
}

ProWaveComboBox.prototype._showPopup = function() {
	this._loadPopup();

	this.popup.style.display = "block";
	if (!this.popup.bSizeSet) {
		if (!this.popup.style.width) {
//			var w = parseInt(this.textbox.style.width)||this.textbox.offsetWidth;
			var w = this.textbox.offsetWidth*this.columns;
			this.popup.style.width = w+"px";
			if (this.popup.offsetWidth > w) { // offset 보정
				this.popup.style.width = (w*2-this.popup.offsetWidth)+"px";
			}

		}
		this.popup.bSizeSet = true;
	}
	var bodyRect = ProWave.getVisibleRect();
	var left = bodyRect.left;
	var top = bodyRect.top;
	var viewportOffset = pwComboBox.viewportOffset(this.textbox);
	left = left + viewportOffset[0];
	top = top + viewportOffset[1]+this.textbox.offsetHeight;
	if (top + this.popup.offsetHeight > bodyRect.bottom) {
		top = top - this.textbox.offsetHeight - this.popup.offsetHeight;
		if (top < bodyRect.top) {
			top = bodyRect.top + viewportOffset[1] + this.textbox.offsetHeight;
		}
	}
	this.popup.style.left = left + "px";
	this.popup.style.top = top + "px";
	this.popup.isShow = true;

	pwComboBox.setCurrent(this);
	if (ProWave.oldIE) {
		ProWave.hideMSCtl(this.popup, pwComboBox.ctl); //sharing global iframe
	}
}

ProWaveComboBox.prototype._getSelectedString = function() {
	var selectedItems = new Array();
	for (i = 0, max = this.select.options.length; i < max ; i++) {
		if (this.select.options[i].selected) {
			selectedItems.push(this.select.options[i].text);
		}
	}

	return selectedItems.toString();
}

ProWaveComboBox.prototype._setItemStyle = function(item) {
	if (item.bind.selected) {
		item.sNormalStyle = this.sItemSelectedStyle;
	} else {
		item.sNormalStyle = this.sItemStyle;
	}
	item.className = item.sNormalStyle;
}
