/**
 * ExtraLib JS 클래스 리스트
 * 
 * AdditionalMenu
 * FileUploadComponent
 * Font
 * HTMLLib
 */

/**
* 부가기능 메뉴클래스
*/
function AdditionalMenu ()
{
}

var AdditionalMenu_VAR_NAME = "";
var AdditionalMenu_SCROLL_NAME = "";
var AdditionalMenu_IS_SCROLL = false;
var AdditionalMenu_ROW_INDEX = -1;

/**
* 부가기능 메뉴를 실행
* @param strVarName 메뉴가 열림 아톰변수, 만약 폼이면 값은 "__FORM"이다.
* @param strModelName 실행모델명
* @param strExeVar 실행모델의 값 참조변수명 (정규식)
* @param strIsPriority 우선순위 TODO: 우선순위가 없나요?
*/
AdditionalMenu.executeMenu = function (nScriptIndex, strModelName, strExeVar, strIsPriority, nSelectedIndex)
{
	//폼_메뉴선택 스크립트 호출
	if (-1 == nScriptIndex)
	{
		ScriptFormEvent.onFormMenuSelect(nSelectedIndex);
		
		if (null != strModelName && 0 < strModelName.length)
		{
			PQConnectionModel.open(strModelName, strExeVar);
		}
		
		// 폼_메뉴선택 후처리 없음
	}
	//입력란_메뉴선택 스크립트 호출
	else
	{
		// 스크롤에 묶인 입력란
		if (AdditionalMenu_IS_SCROLL)
		{
			var objScrollAtom = ScrollAtom.getAtom(AdditionalMenu_SCROLL_NAME);
			nScriptIndex = objScrollAtom.getScriptIndex();
			if (-1 != ScriptAtomEvent.onMenuSelect(nScriptIndex, AdditionalMenu_ROW_INDEX, AdditionalMenu_VAR_NAME, nSelectedIndex))
			{
				if (null != strModelName && 0 < strModelName.length)
				{
					PQConnectionModel.open(strModelName, strExeVar);
				}
			}
			
			// 메뉴선택 후처리
			ScriptAtomEvent.onMenuSelectAfter(nScriptIndex, AdditionalMenu_ROW_INDEX, AdditionalMenu_VAR_NAME, nSelectedIndex);
		}
		// 일반 입력란
		else
		{
			if (-1 != ScriptAtomEvent.onMenuSelect(nScriptIndex, nSelectedIndex))
			{
				if (null != strModelName && 0 < strModelName.length)
				{
					PQConnectionModel.open(strModelName, strExeVar);
				}
			}
			
			// 메뉴선택 후처리
			ScriptAtomEvent.onMenuSelectAfter(nScriptIndex, nSelectedIndex);
		}	
		
		// 부가메뉴에 대한 처리 후 스크롤 정보를 초기화 한다.
		AdditionalMenu_VAR_NAME = "";
		AdditionalMenu_SCROLL_NAME = "";
		AdditionalMenu_IS_SCROLL = false;
		AdditionalMenu_ROW_INDEX = -1;
	}
}

/**
* 부가기능 mouse over event handler
* @param heMenu 선택된 메뉴 html element
*/
AdditionalMenu.onMouseOver = function (heMenu)
{
	heMenu.style.backgroundColor = "#191970"; // PQBLD에서 사용되는 색상 코드	
	heMenu.style.color = "#FFFFFF";

	heMenu.style.cursor = "default";
}
	
/**
* 부가기능 mouse out event handler
* @param heMenu ''
*/
AdditionalMenu.onMouseOut = function (heMenu)
{
	heMenu.style.backgroundColor = "#ffffff";
	heMenu.style.color = "#000000";
}
	
/**
* 부가기능 mouse blur event handler
* @heMenu heMenu ''
*/
AdditionalMenu.onBlur = function (heMenu)
{
	heMenu.style.visibility = "hidden";
}
/**
 * 부가기능 메뉴 띄우기.
 * @param strId 선택할 부가메뉴의 구분명. 폼 부가메뉴는 "FORM", 탭뷰는 "Tabpage0", "Tabpage1",... 등 이다.
 * @param objEvent window event 
 */
AdditionalMenu.onContextMenu = function (strId, objEvent)
{
	if (2 != objEvent.button)
	{
		return;
	}
	var heMenu = document.getElementById("__ADDITIONALMENU___" + strId);
			
	if (null == heMenu || null == heMenu.rows || 0 == heMenu.rows.length)
	{
		return;
	}
	
	// 메뉴 위치 설정
	heMenu.style.left = objEvent.clientX + "px";
	heMenu.style.top = objEvent.clientY + "px";
	
	heMenu.style.zIndex = 1;
	heMenu.style.visibility = "visible";
	
	heMenu.focus();

	objEvent.cancelBubble = true;
}

AdditionalMenu.setVarName = function (strVarName)
{
	AdditionalMenu_VAR_NAME = strVarName;
}

AdditionalMenu.setIsScroll = function (bScroll)
{
	AdditionalMenu_IS_SCROLL = bScroll;
}

AdditionalMenu.setScrollName = function (strScrollName)
{
	AdditionalMenu_SCROLL_NAME = strScrollName;
}
AdditionalMenu.setRowIndex = function (nRowIndex)
{
	AdditionalMenu_ROW_INDEX = nRowIndex;
}


function FileUploadComponent (objOwner, strVarName)
{
	this.m_objOwner = objOwner;
	this.m_strVarName = strVarName;
	
	this.m_strFilePrefix = "__FILE_";
	this.m_strFileDialogDivPrefix = this.m_strFilePrefix + "D_";
	this.m_strFileListDivPrefix = this.m_strFilePrefix + "L_";
	this.m_strCancelButtonPrefix = this.m_strFilePrefix + "C_";
	
	this.m_heFileDialogDiv = document.getElementById(this.m_strFileDialogDivPrefix + strVarName);
	this.m_heFileListDiv = document.getElementById(this.m_strFileListDivPrefix + strVarName);
	this.m_heCancelButton = document.getElementById(this.m_strCancelButtonPrefix + strVarName);
	this.m_heFile = null;
	
	this.m_arFileUploadList = new Array();
}

FileUploadComponent.prototype.getPath = function ()
{
	return (null != this.m_heFile) ? this.m_heFile.value : "";
}

FileUploadComponent.prototype.getCount = function ()
{
	return this.m_arFileUploadList.length - 1;
}

/**
 *	@param nIndex - 파일업로드 리스트의 인덱스
 *	@return nIndex에 해당되는 Input File의 값
 */
FileUploadComponent.prototype.getValue = function (nIndex)
{
	var heInput = this.m_arFileUploadList[nIndex];
	
	return (null != heInput) ? heInput.value : "";
}

FileUploadComponent.prototype.show = function ()
{
	this.m_heFileDialogDiv.style.zIndex = "2";
	this.m_heFileDialogDiv.style.visibility = "visible";
}

FileUploadComponent.prototype.hide = function ()
{
	this.m_heFileDialogDiv.style.visibility = "hidden";
}

FileUploadComponent.prototype.init = function ()
{		
	this.m_heFileListDiv.innerHTML = "";
	
	this._createFileUpload(this.m_strFilePrefix);
	
	this._setPosition();
}

/**
 *	@param nStartIndex - 인덱스 시작번호
 */
FileUploadComponent.prototype.initMulti = function (nStartIndex)
{		
	this.m_heFileListDiv.innerHTML = "";
	this.m_arFileUploadList.length = 0;
	
	var strFileIdPrefix = this._getMultiFileIdPrefix();
	this._createFileUpload(strFileIdPrefix);
	
	this._addList(strFileIdPrefix);
	
	if (null != nStartIndex)
	{
		for (var i = 0; i < nStartIndex; i += 1)
		{
			this.add();
		}
	}
	
	this._setPosition();
}

FileUploadComponent.prototype.add = function ()
{
	this.m_heFile.style.display = "none";
	
	var strFileIdPrefix = this._getMultiFileIdPrefix();
	this._createFileUpload(strFileIdPrefix);
	
	this._addList(strFileIdPrefix);
	
	this.m_heFile.style.display = "block";
}

FileUploadComponent.prototype.del = function ()
{
	this.removeAt(this.m_arFileUploadList.length-1);
}

/**
 *	strFileIndex번째 파일을 삭제합니다.
 *	@param strFileIndex 삭제할 노드의 인덱스
 */
FileUploadComponent.prototype.removeAt = function (strFileIndex)
{
	var nFileIndex = parseInt(strFileIndex);

	if (nFileIndex < this.m_arFileUploadList.length)
	{
		var heFile = this.m_arFileUploadList[nFileIndex];			
		this.m_heFileListDiv.removeChild(heFile);			
		this.m_arFileUploadList.splice(nFileIndex, 1);
		
		for (var i = nFileIndex; i < this.m_arFileUploadList.length; i += 1)
		{
			this.m_arFileUploadList[i].id = this._getMultiFileIdPrefix(i) + this.m_strVarName;
			this.m_arFileUploadList[i].name = this._getMultiFileIdPrefix(i) + this.m_strVarName;
		}
	}
}

FileUploadComponent.prototype._getFileName = function (nIndex)
{
	return this.m_arFileUploadList[nIndex].name;
}

FileUploadComponent.prototype._createFileUpload = function (strFileIdPrefix)
{
	var strID = strFileIdPrefix + this.m_strVarName;
	
	var heNewFile = document.createElement("input");
	heNewFile.type = "file";
	heNewFile.id = strID;
	heNewFile.name = strID;

	this.m_heFileListDiv.appendChild(heNewFile);

	this.m_heFile = document.getElementById(strID);
	
	this._addEventHandler();
}

FileUploadComponent.prototype._getMultiFileIdPrefix = function (strFileIndex)
{
	if (null == strFileIndex)
	{
		strFileIndex = this.m_arFileUploadList.length;
	}
	
	var strFileIdPrefix = this.m_strFilePrefix + "_" + strFileIndex + "_";
	
	return strFileIdPrefix;
}

FileUploadComponent.prototype._addList = function (strPrefix)
{
	this.m_arFileUploadList.push(document.getElementById(strPrefix + this.m_strVarName));
}

FileUploadComponent.prototype._addEventHandler = function ()
{
	var objThis = this;
	
	this.m_heFile.onchange = function ()
	{
		// 파일이 중복되면
		if (objThis._isDuplicated())
		{
			alert("업로드 목록에 이미 \'" + objThis.m_heFile.value + "\' 파일이 있습니다.");
			
			/**
			 *	DOM Input File의 value속성은 get만 가능해서(파일 다이얼로그에 의해서만 set됨)
			 *	value를 초기화 하기 위해 엘리먼트를 없애고 새로 만듭니다.
			 */
			objThis.removeAt(objThis.m_arFileUploadList.length-1);
			objThis.add();
		}
		else
		{
			objThis.m_objOwner.onChange(objThis.m_heFile.value);
		}
	}
	
	this.m_heCancelButton.onclick = function ()
	{
		objThis.m_objOwner.onCancel();
	}
	
	this.m_heFile.onkeydown = function()
	{
		this.blur();
	}
}

/**
 *	파일이 중복되는지 여부를 알려줍니다.
 *	@return 중복되면 true, 아니면 false를 리턴합니다.
 */
FileUploadComponent.prototype._isDuplicated = function ()
{
	for (var i = 0; i < this.m_arFileUploadList.length-1; i += 1)
	{
		var heFile = this.m_arFileUploadList[i];
		
		if (this.m_heFile.value == heFile.value)
		{
			return true;
		}
	}
	
	return false;
}

FileUploadComponent.prototype._setPosition = function ()
{
	var nModelWidth = GetWindowWidth();
	var nModelHeight = GetWindowHeight();
	
	var nLayoutWidth = parseInt(this.m_heFileDialogDiv.style.width);
	var nLayoutHeight = parseInt(this.m_heFileDialogDiv.style.height);
	
	var nLeft = nModelWidth / 2 - nLayoutWidth / 2;
	var nTop = nModelHeight / 2 - nLayoutHeight / 2;
	
	this.m_heFileDialogDiv.style.top = nTop + "px";
	this.m_heFileDialogDiv.style.left = nLeft + "px";
}


/**
 * 글꼴 정보를 관리한다.
 * @author 김지환
 */

function Font (strFontName, nFontSize, nFontStyle, strFontColor)
{
	this.m_strFontName = strFontName;
	this.m_nFontSize = nFontSize;
	this.m_nFontStyle = nFontStyle;
	this.m_strFontColor = strFontColor;
	
	this.s_PLAIN = 0;
	this.s_BOLD = 1;
	this.s_ITALIC = 2;
	this.s_UNDERLINE = 4;
	this.s_STRIKEOUT = 8;
}

Font.prototype.getFontName = function ()
{
	return this.m_strFontName;
}

Font.prototype.setFontName = function (strFontName)
{
	this.m_strFontName = strFontName;
}

Font.prototype.getFontSize = function ()
{
	return this.m_nFontSize;
}

Font.prototype.setFontSize = function (nFontSize)
{
	this.m_nFontSize = nFontSize;
}


Font.prototype.getFontColor = function ()
{
	return this.m_strFontColor;
}

Font.prototype.setFontColor = function (strFontColor)
{
	this.m_strFontColor = strFontColor;
}

Font.prototype.getFontStyle = function ()
{
	return this.m_nFontStyle;
}

Font.prototype.isBold = function ()
{
	return (this.m_nFontStyle & this.s_BOLD) == this.s_BOLD;
}

Font.prototype.isItalic = function () 
{
	return (this.m_nFontStyle & this.s_ITALIC) == this.s_ITALIC;
}

Font.prototype.isUnderLine = function ()
{
	return (this.m_nFontStyle & this.s_UNDERLINE) == this.s_UNDERLINE;
}

Font.prototype.isStrikeOut = function ()
{
	return (this.m_nFontStyle & this.s_STRIKEOUT) == this.s_STRIKEOUT;
}

Font.prototype.setBold = function ()
{
	if (!this.isUnderLine())
	{
		this.m_nFontStyle |= this.s_BOLD;
	}
}

Font.prototype.removeBold = function ()
{
	if (this.isUnderLine())
	{
		this.m_nFontStyle ^= this.s_BOLD;
	}
}

Font.prototype.setItalic = function ()
{
	if (!this.isItalic())
	{
		this.m_nFontStyle |= this.s_ITALIC;
	}
}

Font.prototype.removeItalic = function ()
{
	if (this.isItalic())
	{
		this.m_nFontStyle ^= this.s_ITALIC;
	}
}

Font.prototype.setUnderLine = function ()
{
	if (!this.isUnderLine())
	{
		this.m_nFontStyle |= this.s_UNDERLINE;
	}
}

Font.prototype.removeUnderLine = function ()
{
	if (this.isUnderLine())
	{
		this.m_nFontStyle ^= this.s_UNDERLINE;
	}
}

Font.prototype.setStrikeOut = function ()
{
	if (!this.isStrikeOut())
	{
		this.m_nFontStyle |= this.s_STRIKEOUT;
	}
}

Font.prototype.removeStrikeOut = function ()
{
	if (this.isStrikeOut())
	{
		this.m_nFontStyle ^= this.s_STRIKEOUT;
	}
}

function HTMLLib ()
{
}

HTMLLib.getEventX = function (objEvent)
{
	if (is_ie)
	{
		return objEvent.offsetX;
	}
	else if(is_nav)
	{
		return objEvent.layerX;
	}
}

HTMLLib.getEventY = function (objEvent)
{
	if (is_ie)
	{
		return objEvent.offsetY;
	}
	else if(is_nav)
	{
		return objEvent.layerY;
	}
}

/**
 * 숫자키를 눌렀으면 true, 아니면 false
 * 48~57 : '0'~'9',  96~105 : 키패드 '0'~'9'
 */	
HTMLLib.isNumberKeyDown = function (objEvent)
{
	var nKeyCode = objEvent.keyCode;
	
	if ((48 <= nKeyCode && nKeyCode <= 57 && false == objEvent.shiftKey) 
			|| 96 <= nKeyCode && nKeyCode <= 105)
	{
		return true;
	}
	return false;
}

/**
 * 문자키를 눌렀으면 true, 아니면 false
 */	
HTMLLib.isCharacterKeyDown = function (nKeyCode)
{
	if (HTMLLib.isAlphabetKeyDown(nKeyCode) || (106 <= nKeyCode && nKeyCode <= 111) 
		|| (186 <= nKeyCode && nKeyCode <= 192) || (219 <= nKeyCode && nKeyCode <= 222))
	{
		return true;
	}
	return false;
}

/**
 * 알파벳키를 눌렀으면 true, 아니면 false
 * 65~90 : 'a'~'z'
 */	
HTMLLib.isAlphabetKeyDown = function (nKeyCode)
{
	if (65 <= nKeyCode && nKeyCode <= 90)
	{
		return true;
	}
	return false;
}

/**
 * 이동키, 시스템키 눌렀으면 true, 아니면 false
 */	
HTMLLib.isDirectionKeyDown = function (nKeyCode)
{
	if ((34 <= nKeyCode && nKeyCode <= 40))
	{
		return true;
	}
	return false;
} 

HTMLLib.isOperationKeyDown = function (nKeyCode)
{
	if ((33 <= nKeyCode && nKeyCode <= 47) || (8 <= nKeyCode && nKeyCode <= 20) || (112 <= nKeyCode && nKeyCode <= 127))
	{
		return true;
	}
	return false;
}

/**
 * 입력란에서 커서의 현재 위치를 알아낸다.
 *
 * @param heAtom : input type="text" 또는 TextArea  html 객체
 *	 
 * @return 커서의 현재 위치
 */
HTMLLib.getCursorPosition = function (heAtom)
{
	var nCursorPos = 0;	
	
	if (document.selection)
	{
		if ("textarea" == heAtom.type)		// TextArea에서 커서의 위치를 얻음
		{
			var strTemp = "\17\24\01";
			var objRange = document.selection.createRange();	// 빈 선택 범위 생성
			if (0 < objRange.text.length)
			{
				// 선택된 range가 있으면 리턴
				return -1;
			}
			var dupRange = objRange.duplicate();				// 생성한 범위의 복제
	
			dupRange.moveToElementText(heAtom);				// 아톰에 있는 원본 값을 가져옴
			objRange.text = strTemp;						// 빈범위에 문자를 넣으면, 복제본의 커서위치에 동일한 문자가 들어감
			nCursorPos = dupRange.text.indexOf(strTemp);	// 복제본에서 문자의 위치가 커서의 위치가 됨
				
			objRange.moveStart("character", -3);		// 문자 넣은것을 삭제하기 위해 앞으로 한칸 선택
			objRange.text= "";							// 넣은 문자를 삭제
				
			if (nCursorPos < 0)			// 문자열의 마지막에 커서가 있을 경우
			{
				nCursorPos = dupRange.text.length;
			}
		}
		else	// Input 입력란에서 커서의 위치를 얻음
		{
			// 커서 위치를 얻기 위해, 빈 selection range를 얻음
			var objRange = document.selection.createRange ();
			// selection range를 시작 위치인 0으로 이동
			objRange.moveStart ('character', -heAtom.value.length);
	
			// cursor position은 선택된 길이가 된다.
			nCursorPos = objRange.text.length;
		}
	}
	// Firefox에서 동작?
	else if (heAtom.selectionStart || heAtom.selectionStart == '0')
	{
		nCursorPos = heAtom.selectionStart;
	}
	
	return nCursorPos;
}

/**
 * 입력란에서 nPos의 위치로 커서를 이동시킨다.
 *
 * @param heAtom : input type="text" 또는 TextArea  html 객체 
 * @param	nPos : 커서를 이동시킬 위치
 */	
HTMLLib.setCursorPosition = function (heAtom, nPos)
{
	if (heAtom.createTextRange)
	{
		// 빈 selection range 생성
		var objRange = heAtom.createTextRange();
			
		objRange.move("character", nPos);	// nPos 만큼 이동

		objRange.select();	// 현재위치에서 선택하면 -> 커서 이동
	}
	// FireFox 동작?
	else if (heAtom.selectionStart)
	{
		heAtom.focus();
		heAtom.setSelectionRange(pos, pos);
	}
}

HTMLLib.getEvent = function (objEvent)
{
	if (null == objEvent && window.event)
	{
		objEvent = window.event;
	}
	
	return objEvent;
	//return HTMLLib.clone(objEvent);
}

HTMLLib.clone = function (obj)
{
	if ('object' != typeof(obj))
	{
		return obj;
	}
	
	if (null == obj)
	{
		return obj;
	}

	var newObj = new Object();

	for(var i in obj)
	{
		if ('object' != typeof(obj[i]))
		{
			newObj[i] = HTMLLib.clone(obj[i]);
		}
		else
		{
			newObj[i] = obj[i];
		}
	}

	return newObj;
}

HTMLLib.importNode = function (objDocument, oNode, bImportChildren)
{
	if (objDocument.importNode)
	{
		return objDocument.importNode(oNode, bImportChildren)
	}
	else
	{
		var oNew;
	
		if(Node.ELEMENT_NODE == oNode.nodeType)
		{
			oNew = objDocument.createElement(oNode.nodeName);
	
			for(var i = 0; i < oNode.attributes.length; i++)
			{
				if(oNode.attributes[i].nodeValue != null && oNode.attributes[i].nodeValue != '')
				{
					var attrName = oNode.attributes[i].name;
	
					if(attrName == "class")
						oNew.setAttribute("className", oNode.attributes[i].value);
					else
						oNew.setAttribute(attrName, oNode.attributes[i].value);
				}
			}
	
			if(oNode.style != null && oNode.style.cssText != null)
			oNew.style.cssText = oNode.style.cssText;
		}
		else if(Node.TEXT_NODE == oNode.nodeType)
		{
			oNew = objDocument.createTextNode(oNode.nodeValue);
		}
	
		if(bImportChildren && oNode.hasChildNodes())
		{
			for(var oChild = oNode.firstChild; oChild; oChild = oChild.nextSibling)
			{
				oNew.appendChild(HTMLLib.importNode(objDocument, oChild, true));
			}
		}
	
		return oNew;
	}
}

/**
 * DOM Object의 어트리뷰트로 설정한 JS Object 함수를 해제한다.
 * 루프를 돌면서 하위 앨리먼트의 어트리뷰트도 해제한다.
 *
 * DOM Object와 JS Object의 순환참조에 의한, 메모리 누수를 예방하기 위해서 사용한다.
 * 엘리먼트가 removeChild 메소드나 innerHTML 속성으로 삭제되기 전에 호출되어야 한다.
 *
 * postscript by siamdaarc 
 * 시간을 단축하기 위해, 루프를 돌지않고, 실제로 해제되는 attribute 속성만 null로 초기화 하도록 하였으나, 메모리 해제 되지 않았다.
 * debug 해보면, null로 초기화 되는 속성 목록은 일치하는데, 루프를 돌면 동작하고, 돌지 않으면 동작하지 않는 차이를 알수 없었음 --;
 */
HTMLLib.purge = function (heDom)
{
	var attr = heDom.attributes, i, nLen, name;
	if (attr)
	{
		nLen = attr.length;
		for (i = 0; i < nLen; i += 1)
		{
			name = attr[i].name;
			if (typeof heDom[name] == 'function')
			{
				heDom[name] = null;
			}
		}
	}
	
	attr = heDom.childNodes;
	if (attr)
	{
		nLen = attr.length;
		for (i = 0; i < nLen; i += 1)
		{
			HTMLLib.purge(heDom.childNodes[i]);
		}
	} 
}

HTMLLib.SELECT_BG_COLOR = "#191970"; //선택행 바탕 색상, 빌더 색상
HTMLLib.SELECT_FONT_COLOR = "#ffffff"; //선택행 글씨 색상, 빌더 색상
