/*****************************************************************************
 * 파일명 : kbl-package.js
 * 작성일 : 2008. 05.
 * 작성자 : 
 * 설   명 : 공통 namespace  및 전역상수 정의
 * ===========================================================================
 * 변경이력:
 * DATE				AUTHOR		DESCRIPTION
 * ---------------------------------------------------------------------------
 * 변경 이력은 이곳에 추가 합니다.
 *****************************************************************************/

/**
 * Component 용 namaspace
 */

/**
 * 업무용 namespace
 */
var jsl = {
	/* 전역 상수 */
	IS_NAV  : (navigator.appName == "Netscape"),
	IS_IE   : (navigator.appName == "Microsoft Internet Explorer"),	
	IS_WIN  : (navigator.userAgent.indexOf("Win") != -1),
	IS_MAC  : (navigator.userAgent.indexOf("Mac") != -1),
	IS_UNIX : (navigator.userAgent.indexOf("X11") != -1),
	LOGOUT_TIME_DIV   			: 'logoutTimeDiv', 		// 1분이 됐을 경우 보여줄 Alert레이어
	SHOW_TIME_DIV     			: 'showTime',      		// 화면에 보여줄 남은 시간 레이어
	ALERT_MINUTES_DIV 			: 'alertMinutes',  		// 1분이 됐을 경우 Alert레이어에 보여줄 남은 시간 레이어
	ICON_CLOCK_DIV 	  			: 'icon_clock',    		// 남은시간 보여줄 레이어영역
	PAGE_WRAP         			: 'jsl-content',   		// 페이지 영역 레이어
	SCREEN_WRAP       			: 'ScreenWRAP',    		// Page Content 영역을 가지고 있는 레이어
	LEFT_MENU_WRAP    			: 'Left',     	 		// Left 메뉴 영역 레이어
	CONTENT_WRAP      			: 'Content',  	 		// Contents 영역 레이어
	CONTENT_RESULT_WRAP      	: 'ContentResult',  	// Contents 결과 영역 레이어
	POPUP_WRAP      			: 'Popup',  	 		// Popup 영역 레이어
	POPUP_RESULT_WRAP      		: 'PopupResult',  		// Popup 결과 영역 레이어
	TAB_WRAP      				: 'Tab',  	 			// Tab 영역 레이어
	TAB_CONTENT_WRAP      		: 'TabContent',  		// TabContent 영역 레이어
	TAB_CONTENT_RESULT_WRAP     : 'TabContentResult',  	// TabContent 결과 영역 레이어
	APPLICATION_CONTEXT_ROOT 	: '',					// root 경로.
	PAGE_SIZE 					: 10,					// 1 page 아이템 갯수.
	
	changeImageObject : null,  // sortTable에서 소트상태 이미지정보를 정의

	/**
	 * 쿠키에 저장된 값을 반환한다.
	 * @param name 쿠키 이름
	 * @return 쿠키 이름에 대한 값을 반환. 없는 경우에는 ""를 반환.
	 */
	 getCookie :  function(name) {
	    var arg = name + "=";
	    var alen = arg.length;
	    var clen = document.cookie.length;
	    var i = 0;
	    while (i < clen) {
	        var j = i + alen;
	        if (document.cookie.substring(i, j) == arg) {
	            return jsl.getCookieVal(j);
	        }
	        i = document.cookie.indexOf(" ", i) + 1;
	        if (i == 0) break;
	    }
	    return "";
	},
	
	
	/**
	 * 쿠키를 저장한다.
	 * @param name 쿠키 이름
	 * @param value 쿠키 값
	 * @param expires 쿠키의 유효 일
	 * @param path
	 * @param domain
	 * @param secure
	 */
	 setCookie : function(name, value, expires, path, domain, secure) {
		
	    if (!path) {
	        path = "/";
	    }
	    document.cookie = name + "=" + escape (value) +
	                    ((expires) ? "; expires=" + expires : "") +
	                    ((path) ? "; path=" + path : "") +
	                    ((domain) ? "; domain=" + domain : "") +
	                    ((secure) ? "; secure" : "");
	    
	},
	
	
	/**
	 * 쿠키를 삭제한다.
	 * @param name 삭제할 쿠키 이름
	 * @param path
	 * @param domain
	 */
	deleteCookie : function(name, path, domain) {
	    if (!path) 
	        path = "/";
	
	    if (jsl.getCookie(name)) {
	        document.cookie = name + "=" +
	            ((path) ? "; path=" + path : "") +
	            ((domain) ? "; domain=" + domain : "") + 
	            "; expires=Thu, 01-Jan-70 00:00:01 GMT";
	    }
	},
	
	
	/**
	 * 쿠키를 저장할 때 필요한 적합한 형식의 유효기간을 반환한다.
	 * @param days 쿠키가 유효할 일 (예를 들어 3 일 동안 유효해야 하면 3을 입력)
	 * @param hours 쿠키가 유효할 시간 (예를 들어 2 시간 동안 유효해야 하면 2를 입력)
	 * @param minutes 쿠키가 유효할 분 (예를 들어 30 분 동안 유효해야 하면 30을 입력)
	 */
	getExpDate : function(days, hours, minutes) {
	    var expDate = new Date( );
	    if (typeof days == "number" && typeof hours == "number" &&
	        typeof hours == "number") {
	        expDate.setDate(expDate.getDate( ) + parseInt(days));
	        expDate.setHours(expDate.getHours( ) + parseInt(hours));
	        expDate.setMinutes(expDate.getMinutes( ) +
	        parseInt(minutes));
	        return expDate.toGMTString( );
	    }
	},

	/**
	 * 쿠키 값을 읽을 때 사용하는 보조 함수
	 * @param {Object} offset
	 */	
	getCookieVal :  function(offset) {
	    var endstr = document.cookie.indexOf (";", offset);
	    if (endstr == -1) {
	        endstr = document.cookie.length;
	    }
	    return unescape(document.cookie.substring(offset, endstr));
	},
	
	/**
	 * 입력받을 수 있는 값을 필터링한다.
	 * ex : <input type="text" ..... onkeypress="filterKey('[0-9]', event)"> ; 숫자만 키입력이 가능한 text filed
	 * ex : <input type="text" ..... onkeypress="filterKey('[0-9a-zA-Z]', event)"> ; 영문,숫자만 키입력이 가능한 text filed
	 * @param filter : 필터링할 정규표현식 ex) '[0-9]':0~9의 값만 허용, '[a-zA-Z]':알파벳만 허용
	 * @return 
	 */
	filterInputData : function(filter, e) { 
	    if (filter) {
            var evt = e || window.event;
            var kCode = evt.which || evt.keyCode;

            /* backspace ,tab(9),enter(13),shift(16),end(35),home(36),방향키(좌(37),상(38),우(49),하(40)),delete(46) 등등..*/
            var controlKeys = new Array(Event.KEY_BACKSPACE,Event.KEY_TAB,Event.KEY_RETURN,Event.KEY_ESC,Event.KEY_ESC,
                    Event.KEY_LEFT,Event.KEY_UP,Event.KEY_RIGHT,Event.KEY_DOWN,Event.KEY_DELETE,Event.KEY_HOME,
                    Event.KEY_END,Event.KEY_PAGEUP,Event.KEY_PAGEDOWN);

            /* 조작키이면 종료 */
            for (var i=0; i<controlKeys.length; i++) {
                if (controlKeys[i] == kCode) return;
            }
            
            var sKey = String.fromCharCode(kCode);
	        var re = new RegExp(filter);
	        if (!re.test(sKey)) {
                Event.stop(evt);
	        }
			var re = new RegExp('[ㄱ-ㅎ|ㅏ-ㅣ|가-힝]');
	        if (re.test(sKey)) {
                Event.stop(evt);
	        }			
	    }
	},
	
	
	/**
	 * 주어진 텍스트(source)에 특정 문자(query)가 나타나는 횟수를 반환한다.
	 * @param source 대상이 되는 텍스트
	 * @param query 검색하려는 텍스트
	 * @return 주어진 텍스트에 특정 문자가 나타나는 횟수
	 */
	countInstances : function(source, query) {
	    var re = new RegExp(query, "g");
	    var result = source.match(re);
	    return (result) ? result.length : 0;
	},
	
	/**
	 * <div> 태그의 내용 중 특정 텍스트(before)를 특정 텍스트(after)로 변경한다.
	 * @param id <div> 태그의 id 속성 값
	 * @param before 변경 전 텍스트
	 * @param after 변경 후 텍스트
	 */
	replaceTextInDiv : function(id, before, after) {
	    var element = document.getElementById(id).firstChild;
	    var re = new RegExp(before, "g");
	    element.nodeValue = element.nodeValue.replace(re, after);
	    return false;
	},
	
	/**
	 * textNode 를 추가한다. 
	 * @param {String} id
	 * @param {String} text
	 */
	writeTextInElement : function(id, text) {
	    var element = document.getElementById(id);
	    if (element.firstChild) {
	        element.firstChild.nodeValue = text;
	    } else {
	        var child = document.createTextNode(text);
	        element.appendChild(child);
	    }
	    return false;
	},
	
	/**
	 * 입력 변수에 3 자리마다 콤마(,)를 붙여 반환한다.
	 * @param field 콤마를 붙일 값
	 */
	formatCommas : function(numString) {
	    var re = /,|\s+/g;
	    numString = numString.replace(re, "");
	
	    re = /(-?\d+)(\d{3})/;
	    while (re.test(numString)) {
	        numString = numString.replace(re, "$1,$2");
	    }
		
	    return numString;
	},
	
	/**
	 * 콤마(,)를 제거하여 반환한다.
	 * @param {Object} numString 콤마를 제거할 값
	 */
	stripCommas : function(numString) {
	    var re = /,/g;
	    return numString.replace(re, "");
	},
	
	/**
	 * 텍스트 필드에 입력한 값에 3자리마다 콤마(,)를 붙인다.
	 * 텍스트 필드에 아래를 기입한다. onkeyup="toMoney(this)"
	 * @param field 텍스트 필드
	 */
	toMoney : function(field) {
	    var value = field.value;
	    var indexOfPoint = value.indexOf(".");
	    if (indexOfPoint == -1) {
	        field.value = jsl.formatCommas(value);
	    } else {
	        field.value = jsl.formatCommas(value.substring(0, indexOfPoint)) +
	                        value.substring(indexOfPoint, value.length);
	    }
	},
	
	/**
	 * 숫자타입의 문자를 한글로 표현한다. 
	 * @param {String} numStr  Number type의 String
	 * @param {String} targetDivId 한글로 표현될 DivId 
	 * @param {int} rangeLength 제한자릿수
	 * @param {HTMLElemtnt} targetEl 에러시 초기화할 Element (optional)
	 * @return {boolean} 제한자리를 통과했는지 여부
	 * 
	 */
	toKoreanFromMoney : function (numStr,targetDivId,rangeLength, targetEl){
		var arrayNum=new Array("","일","이","삼","사","오","육","칠","팔","구");
		var arrayUnit=new Array("","십","백","천","만 ","십만 ","백만 ","천만 ",		
		                    "억 ","십억 ","백억 ","천억 ","조 ","십조 ","백조");
		var arrayStr= new Array();
		var numStr = jsl.stripCommas(numStr);
		var len = numStr.length;
		
		var isValid = true;
		// 제한 자릿수가 넘으면 리턴한다. 
		if (len > rangeLength) {
			// 오류메세지를 출력한다. 
			jsl.extJS.messageBox.infoMsgBox(
				{
					isConfirm: false,
					title: "입력오류",
					message: "범위를 초과하였습니다.",
					icon: 'info',
					callback: null								
				}
			);
			if (targetEl) {
				targetEl.value = "0";
			}
			isValid = false;
		} 
		
		
		var hanStr = "";
		if (isValid) {
			for (i = 0; i < len; i++) {
				arrayStr[i] = numStr.substr(i, 1)
			}
			code = len;
			for (i = 0; i < len; i++) {
				code--;
				tmpUnit = "";
				if (arrayNum[arrayStr[i]] != "") {
					tmpUnit = arrayUnit[code];
					if (code > 4) {
						if ((Math.floor(code / 4) == Math.floor((code - 1) / 4) &&
						arrayNum[arrayStr[i + 1]] != "") ||
						(Math.floor(code / 4) == Math.floor((code - 2) / 4) &&
						arrayNum[arrayStr[i + 2]] != "")) {
							tmpUnit = arrayUnit[code].substr(0, 1);
						}
					}
				}
				hanStr += arrayNum[arrayStr[i]] + tmpUnit;
			}
		}
		
		if (targetDivId && targetDivId != "") {
			var oTargetDiv = $(targetDivId);
			if (oTargetDiv) {
				var oTextNode = new Object();
				var oChildNode = new Object();
				if (hanStr != "") {
					oTextNode = document.createTextNode('(' + hanStr + ' 원)');
					oChildNode = oTargetDiv.childNodes[0];
				} else {
					oTextNode = document.createTextNode(' ');
					oChildNode = oTargetDiv.childNodes[0];
				}
				if (oTargetDiv.childNodes.length != 0) {
					oTargetDiv.removeChild(oChildNode);
				}
				oTargetDiv.appendChild(oTextNode);
			}
		}
		return isValid;
	},
	
	
	
	/**
	 * 두 날짜 사이의 일수를 계산하여 반환한다.
	 * @param date1 문자열 데이터로 '20041012' 형식
	 * @param date2 문자열 데이터로 '20041012' 형식
	 */
	daysBetween : function(date1, date2) {
	    date1 = new Date(date1.substring(0, 4), date1.substring(4, 6)-1, date1.substring(6,8));
	    date2 = new Date(date2.substring(0, 4), date2.substring(4, 6)-1, date2.substring(6,8));
	    var DSTAdjust = 0;
	    oneMinute = 1000 * 60;
	    var oneDay = oneMinute * 60 * 24;
	    date1.setHours(0);
	    date1.setMinutes(0);
	    date1.setSeconds(0);
	    date2.setHours(0);
	    date2.setMinutes(0);
	    date2.setSeconds(0);
	    DSTAdjust = (date2.getTimezoneOffset( ) - 
	                     date1.getTimezoneOffset( )) * oneMinute;
	    var diff = date2.getTime( ) - date1.getTime() - DSTAdjust;
	    return Math.ceil(diff/oneDay);
	},
	
	
	/**
	 * 특정 노드가 가지고 있는 모든 속성을 TEXTAREA에 출력한다. 개발 편의를 위해서
	 * 제공되는 함수이다.
	 * @param obj 속성 값을 알고자 하는 노드
	 */
	listProperties : function(obj) {
	    var objName;
	
	    if (obj.nodeName) {
	        objName = obj.nodeName;
	    } else {
	        objName = "navigator";
	    }
	
	    var result = "";
	    for (var i in obj) {
	        result += objName + "." + i + "=" + obj[i] + "\n";
	    }
	
	    var area = document.createElement("textarea");
	    area.rows = 20;
	    area.cols = 50;
	    var body = document.getElementsByTagName("BODY");
	    if (body) {
	        body[0].appendChild(area);
	    } else {
	        alert("body 태그가 있어야 합니다.");
	        return false;
	    }
	    area.value = result;
	    return false;
	},
	
	/**
	 * QueryString을 반환한다.
	 */
	getQueryString : function() {
	    var result = "";
	    var queryTags = document.getElementsByTagName("input");
	    for (var i = 0; i < queryTags.length; i++) {
	        var name = queryTags[i].name;
			if (name) {
			    result += "&" + name + "=" + queryTags[i].value;
			}
	    }
	
	    queryTags = document.getElementsByTagName("select");
	    for (var i = 0; i < queryTags.length; i++) {
	        var name = queryTags[i].name;
			if (name ) {
			    result += "&" + name + "=" + queryTags[i].value;
			}
	    }
	    return result;
	},
	
	
	/**
	 * 텍스트 필드에 입력한 값에 6자리 이후에 대시(-)를 붙인다.
	 * 텍스트 필드에 아래를 기입한다. onkeyup="toSsn(this)"
	 * @param field 텍스트 필드
	 */
	toSsn : function(field) {
	    var number = String(field.value);
	    number = number.replace(/-|\s+/g, "");
	
	    var length = number.length;
	
	    if (length < 6) {
	        field.value = number;
	    } else {
	        var result = number.substring(0, 6) + "-";
	        result += number.substring(6, length);
	        field.value = result;
	    }
	},	
	
	/**
	 * 레이어 밑에 컨트롤을 숨긴다. 
	 * @param {Object} layer_id
	 */
    selectBoxHidden : function(layer_id)  {
        var ly = $(layer_id); 

        // 레이어 좌표 
        var ly_left  = ly.offsetLeft; 
        var ly_top    = ly.offsetTop; 
        var ly_right  = ly.offsetLeft + ly.offsetWidth; 
        var ly_bottom = ly.offsetTop + ly.offsetHeight; 

        // 셀렉트박스의 좌표 
        var el; 

        for (i=0; i<document.forms.length; i++) { 
            for (k=0; k<document.forms[i].length; k++) { 
                el = document.forms[i].elements[k];

                if (el.type == "select-one") { 
                    var el_left = el_top = 0; 
                    var obj = el; 
                    if (obj.offsetParent) { 
                        while (obj.offsetParent) { 
                            el_left += obj.offsetLeft; 
                            el_top  += obj.offsetTop; 
                            obj = obj.offsetParent; 
                        } 
                    } 
                    el_left  += el.clientLeft; 
                    el_top    += el.clientTop; 
                    el_right  = el_left + el.clientWidth; 
                    el_bottom = el_top + el.clientHeight; 

                    // 좌표를 따져 레이어가 셀렉트 박스를 침범했으면 셀렉트 박스를 hidden 시킴 
                    if ( (el_left >= ly_left && el_top >= ly_top && el_left <= ly_right && el_top <= ly_bottom) || 
                        (el_right >= ly_left && el_right <= ly_right && el_top >= ly_top && el_top <= ly_bottom) || 
                        (el_left >= ly_left && el_bottom >= ly_top && el_right <= ly_right && el_bottom <= ly_bottom) || 
                        (el_left >= ly_left && el_left <= ly_right && el_bottom >= ly_top && el_bottom <= ly_bottom) ) 
                        el.style.visibility = 'hidden'; 
                } 
            } 
        }
	},	

	/**
	 * 감추어진 셀렉트 박스를 모두 보이게 함 
	 */
	selectBoxVisible : function () { 
		for (i=0; i<document.forms.length; i++) { 
			for (k=0; k<document.forms[i].length; k++) { 
				el = document.forms[i].elements[k]; 
				if (el.type == "select-one" && el.style.visibility == 'hidden') 
					el.style.visibility = 'visible'; 
			} 
		} 
	},
	
	/**
	 * DIV 를 숨긴다.
	 * @param {String} divId
	 */
    hiddenDiv: function(/*String*/divId){
		var divObj = $(divId);
		divObj.style.visibility = 'hidden';
		
		jsl.selectBoxVisible(divId);
	
	},	
	
	/**
	 * DIV 를 보여준다.
	 * @param {String} divId
	 */
    showDiv: function(/*String*/divId){
		var divObj = $(divId);
		divObj.style.visibility = 'visible';
		
		jsl.selectBoxHidden(divId);
	},
	
	/**
	 * ViewPort를 가져온다.
	 */
	getViewport : function() {
		var w =0;
		var h =0;
		
		if(window.innerWidth) w=window.innerWidth;
		if(document.documentElement.clientWidth){
			var w2 = document.documentElement.clientWidth;
			if(!w || w2 && w2 < w) w=w2;
		}else if(document.body){
			w=document.body.clientWidth;
		}
	
		if(window.innerHeight) h=window.innerHeight;
		if(document.documentElement.clientHeight) h=document.documentElement.clientHeight;
		else if(document.body) h=document.body.clientHeight;		
		
		return [w,h];
	},
	
	/**
	 * Scroll Offeset을 가져온다.
	 */
	getScrollOffset : function() {
		var x = 0;
		var y = 0;
		
		// 브라우저별 scrollTop 위치 얻어오기
		if (window.pageYOffset)
		{
			x = window.pageXOffset;
			y = window.pageYOffset;
		}
		else if (document.documentElement && document.documentElement.scrollTop != undefined)
		{
			x = document.documentElement.scrollLeft;
			y = document.documentElement.scrollTop;
		}
		else if (document.body)
		{
			x = document.body.scrollLeft;
			y = document.body.scrollTop;
		}
		
		return [x,y];
	},
	
	/**
	 * clientHeight를 가져온다.
	 */
	getClientHeight : function() {
		var x = 0;
		var y = 0;
		
		if (window.innerHeight)
		{
			x = window.innerWidth;
			y = window.innerHeight;
		}
		else if (document.documentElement && document.documentElement.clientHeight != undefined)
		{
			x = document.documentElement.clientWidth;
			y = document.documentElement.clientHeight;
		}
		else if (document.body)
		{
			x = document.body.clientWidth;
			y = document.body.clientHeight;
		}
		
		return [x,y];
	},
	
	/**
	 * ScrollHeight를 가져온다.
	 */
	getScrollHeight : function() {
		var x,y;
		var _scrollHeight = document.body.scrollHeight;
		var _offsetHeight = document.body.offsetHeight
		
		if (_scrollHeight > _offsetHeight) {
			x = document.body.scrollWidth;
			y = document.body.scrollHeight;
		}
		else {
			x = document.body.offsetWidth;
			y = document.body.offsetHeight;
		}
		
		return [x,y];
	},
	
	/**
	 * dialog를 화면 가운데에 위치시킨다.
	 * @param {Object} _panelTarget 참조할 오브젝트
	 * @param {Object} _panelDlg 가운데 위치시킬 오브젝트
	 */
	centerPositioning : function (/*Object*/_panelTarget, /*Object*/ _panelDlg){
		// preparing
		var dlgPos = new Array(2);			// MaskLayer위에 올려놓을 오브젝트의 위치
		var scrViewport = new Array(2); 	// 화면 Viewport
		var elViewport = new Array(2);  	// MaskLayer를 덮을 오브젝트의 Viewport
		var tmpTarget = new Array(2);		// MaskLayer를 덮을 오브젝트의 크기
		var tmpDlg = new Array(2);			// MaskLayer위에 올려놓을 오브젝트의 크기
		var scrollOffset = new Array(2);	// 상단에서부터 스크롤된 크기
		var w;								// 지정된 오브젝트의 너비의 가운데 Position
		var h;								// 지정된 오브젝트의 높이의 가운데 Position
		
		Position.prepare();

		// set position
		var scrPos = new Array(Position.deltaX, Position.deltaY);

		// MaskLayer를 덮을 영역이 정해지지 않았다면 현재 보이는 화면을
		// 타켓으로 가운데를 설정한다.
		if (null != _panelTarget || _panelTarget != undefined) {
			//
			// MaskLayer를 덮을 영역을 정해놓은 경우
			//
			
			// MaskLayer를 덮을 영역의 좌표를 구한다. [x,y]
			elViewport = Position.cumulativeOffset(_panelTarget);
			
			// ViewPort를 가져온다. [w,h]
			scrViewport = jsl.getViewport();
			
			// MaskLayer를 덮을 영역의 크기를 구한다. (width, height)
			tmpTarget = Element.getDimensions(_panelTarget);
			
			// MaskLayer위에 올려놓을 Loading컨트롤의 크기를 구한다. (width, height)
			tmpDlg = Element.getDimensions(_panelDlg);
			
			// 스크롤 위치를 구한다. [x,y];
			scrollOffset = jsl.getScrollOffset();
			
			// MaskLayer를 덮을 영역의 총 높이가 현재 보는 화면의 높이보다 클 경우
			// 즉, MaskLayer를 덮을 영역이 현재 화면의 영역의 위 또는 아래에 계속되는 경우
			// 현재 화면에 보이는 영역에서의 가운데로 설정 
			if ((elViewport[1] + tmpTarget.height) - scrViewport[1] >= 0){
				// MaskLayer를 덮을 영역의 y좌표값이 현재 보이는 화면의 위쪽으로 넘어갔을 경우
				// 즉, MaskLayer를 덮을 영역의 상단 시작부분이 스크롤 위쪽으로 벗어났을 경우
				if (elViewport[1] - scrollOffset[1] < 0) {
					// 컨트롤의 시작부분이 스크롤 위쪽으로 벗어났으므로
					// 현재 보이는 화면의 모든 영역이 MaskLayer를 덮을 영역의 컨트롤만 보이게 된다.
					// 그래서 높이는 현재 보이는 화면의 가운데로 지정
					h = scrViewport[1] / 2;
				}
				else {
					// 컨트롤의 시작부분이 스크롤 위쪽으로 벗어나지 않은 경우.
					// 이럴 경우에는 현재 보이는 영역에서의 가운데로 지정해야 한다.
					//
					// 스크롤이 되면서 현재 화면의 MaskLayer를 덮을 영역의 높이가 변화하면
					// CenterPosition은 현재 보이는 화면의 MaskLayer를 덮을 영역의 가운데를 찾아야 한다.
					// 현재 보이는 화면에서의 컨트롤의 높이를 구할때는 현재 화면의 높이에서 컨트롤의 y좌표값을 뺀 후에
					// 스크롤된 y값 만큼 제거해줘야 실제 화면에 보이는 컨트롤의 높이를 구할 수 있다.
					// 컨트롤의 y좌표값에서 구한 높이의 가운데를 더해주면 실제 위치할 y축 좌표값을 구할 수 있다.
					h = elViewport[1] + ((scrViewport[1] - elViewport[1] - scrollOffset[1]) / 2);
				}
				
				// 높이의 경우는 현재 컨트롤의 x축 좌표값에 컨트롤의 넓이의 절반을 가운데로 구한다.
				w = elViewport[0] + tmpTarget.width / 2;
			}else {
				// MaskLayer를 덮을 영역의 총 높이가 현재 보는 화면의 높이보다 작을 경우에는
				// 현재 보이는 x, y 좌표값에 넓이와 높이를 더한 절반이 가운데가 된다.
				h = elViewport[1] + tmpTarget.height / 2;				
				w = elViewport[0] + tmpTarget.width / 2;
			}
			
			// MaskLayer를 덮을 영역의 아랫부분을 벗어날 경우 가운데 위치시킬 오브젝트는 영역의 아랫부분에서 벗어나지 않도록 고정한다.
			if ((elViewport[1] + tmpTarget.height) <= (scrollOffset[1] + h + tmpDlg.height / 2)){
				h = ((elViewport[1] + tmpTarget.height) - scrollOffset[1]) - tmpDlg.height / 2;
			}
			
			// 가운데의 위치를 구했다 하더라도
			// 그곳에 올려놓을 컨트롤의 높이와 너비의 절반씩을 빼줘야 정 가운데가 된다.
			dlgPos[0] = scrPos[0] + w - tmpDlg.width / 2;
			dlgPos[1] = scrPos[1] + h - tmpDlg.height / 2;
		}
		else {
			//
			// MaskLayer를 덮을 영역을 정하지 않은 경우 (현재 보이는 화면을 타켓으로 진행)
			//
			
			// ViewPort를 가져온다. [w,h]
			scrViewport = jsl.getViewport();
			
			// MaskLayer위에 올려놓을 Loading컨트롤의 크기를 구한다. (width, height)
			tmpDlg = Element.getDimensions(_panelDlg);
				
			// 현재 보이는 x, y 좌표값에 넓이와 높이를 더한 절반이 가운데가 된다.
			// 가운데의 위치를 구했다 하더라도
			// 그곳에 올려놓을 컨트롤의 높이와 너비의 절반씩을 빼줘야 정 가운데가 된다.
			dlgPos[0] = scrPos[0] + scrViewport[0] / 2 - tmpDlg.width / 2;
			dlgPos[1] = scrPos[1] + scrViewport[1] / 2 - tmpDlg.height / 2;
		}
		
		// drawing dialogBox
		_panelDlg.style.left = dlgPos[0] + 'px';
		_panelDlg.style.top = dlgPos[1] + 'px';
	},
	
	/**
	 * 
	 * @param {Object} furl
	 * @param {Object} fwidth
	 * @param {Object} fheight
	 * @param {Object} transoption
	 * @param {Object} id_name
	 */
	swfprint : function(furl,fwidth,fheight,transoption,id_name)	{
		var id_names = "main_flash";
		if(typeof(id_name) != 'undefined') id_names = id_name;
		document.write('<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" width="'+ fwidth +'" height="' + fheight +'" align="middle">');
		document.write('<param name="movie" value="'+ furl +'"/>');
		if (transoption == "t") {
			document.write('<param name="wmode" value="transparent"/>');
		}
		else {
			if (transoption == "o") {
				document.write('<param name="wmode" value="opaque"/>');
			}
		}
			
		document.write('<!-- Hixie method -->');
		document.write('<!--[if !IE]> <-->');
		document.write('<object type="application/x-shockwave-flash" data="'+ furl +'" width="'+ fwidth +'" height="' + fheight +'"');
		if (transoption == "t") {
			document.write(' wmode="transparent"');
		}
		else {
			if (transoption == "o") {
				document.write(' wmode="opaque"');
			}
		}
		
		document.write('></object>');
		document.write('<!--> <![endif]-->');
		document.write('</object>');
		if (id_names == "top_flash") {
			//window.onload = fn_resize_top_flash;
			window.attachEvent("onload", fn_resize_top_flash)
			window.onresize = fn_resize_top_flash;
		}
	},
	
	isMenuOver : false,
	
	/**
	 * Roll over 
	 * @param {Object} obj
	 */
	menuOver: function(obj){
		obj.src = obj.src.replace("_off.gif", "_on.gif");
		jsl.isMenuOver = true;
	},
	
	/**
	 * Roll out
	 * @param {Object} obj
	 */
	menuOut: function(obj){
		obj.src = obj.src.replace("_on.gif", "_off.gif");
	},
	
	/**
	 * Show Layer
	 * @param {Object} tgtEl
	 */ 
	showLayer: function(tgtEl){
		document.getElementById(tgtEl).style.display = "block";
	},

    /**
	 * Show Layer Inline
	 * @param {Object} tgtEl
	 */
	showInline: function(tgtEl){
		document.getElementById(tgtEl).style.display = "inline";
	},

    /**
	 * Hide Layer
	 * @param {Object} tgtEl
	 */
	hideLayer: function(tgtEl){
		document.getElementById(tgtEl).style.display = "none";
	},
	
	/**
	 * 투명이미지
	 * @param {Object} obj
	 */
	setPng24 : function(obj) { 
	    obj.width=obj.height=1; 
	    obj.className=obj.className.replace(/\bpng24\b/i,''); 
	    obj.style.filter = 
	    "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+ obj.src +"',sizingMethod='image');" 
	    obj.src='';  
	    return ''; 
	},
	
	/**
	 * Select Links
	 */
	linkAct : function()	{
		var tgtList = document.getElementById('family_urls');
		if (tgtList.style.display) {
			hideLayer('family_urls');
			tgtList.style.display = "";
			if (navigator.userAgent.indexOf("MSIE") != -1 && document.getElementById('container')) 
				document.getElementById('container').style.zIndex = "0";
		}
		else {
			showLayer('family_urls');
			if (navigator.userAgent.indexOf("MSIE") != -1 && document.getElementById('container')) 
				document.getElementById('container').style.zIndex = "-1";
		}
	},
	
	/**
	 * 
	 * @param {Object} tgtEl
	 */
	selectLinks : function(tgtEl)	{
		var tgtList = document.getElementById(tgtEl);
		if (tgtList.style.display) {
			hideLayer(tgtEl);
			tgtList.style.display = "";
		}
		else {
			showLayer(tgtEl);
		}
	},
	
	/**
	 * 
	 * @param {Object} tgtEl
	 */
	showSelectLayer : function(tgtEl)    {
		document.getElementById(tgtEl).style.display = "block";
		if ( navigator.userAgent.indexOf("MSIE") !=-1 && document.getElementById('container') ) 
			document.getElementById('container').style.zIndex = "0";
	},
	
	/**
	 * 
	 * @param {Object} tgtEl
	 */
	hideSelectLayer : function(tgtEl)    {
		document.getElementById(tgtEl).style.display = "none";
		if (navigator.userAgent.indexOf("MSIE")!=-1&&document.getElementById('container')) 
			document.getElementById('container').style.zIndex = "0";
	},	
	
	/**
	 * Float layer
	 * @param {Object} target
	 */
	initMoving : function(target) {
	    if (!target)
	    return false;
	
	    var obj = target;
		var scrollHeiht = jsl.getScrollHeight();
	    obj.initTop = 130;
	    obj.initLeft = 937;
	    obj.bottomLimit = scrollHeiht[1] - 220;
	    obj.topLimit = 150;
	    obj.style.position = "absolute";
	    obj.top = obj.initTop;
	    obj.left = obj.initLeft;
	    obj.style.top = obj.top + "px";
	    obj.style.left = obj.left + "px";
	
	    obj.getTop = function() {
			var offset = jsl.getScrollOffset();
			
			return offset[1];
		}
		
	    obj.getHeight = function(){
			var height = jsl.getClientHeight();
			
			return height[1];
		},
		
	    obj.move = setInterval(function(){
			pos = obj.getTop() + obj.getHeight() / 2;
			
			if (pos > obj.bottomLimit) 
				pos = obj.bottomLimit
			if (pos < obj.topLimit) 
				pos = obj.topLimit
			
			interval = obj.top - pos;
			obj.top = obj.top - interval / 3;
			
			obj.style.top = obj.top + "px";
		}, 40)
	},
	/**
	 * 인자로 제공된 String 을 trim 한다. 
	 * @param {String} value
	 */
	trimmed : function (value) {
	    value = value.replace(/^\s+/, "");  /* remove leading white spaces */
	    value = value.replace(/\s+$/g, ""); /* remove trailing while spaces */
	    return value;
	},
	
	/**
	 * 탭 메뉴로 구성된 이미지 클릭시 클릭한 메뉴 활성화 한다
	 * (활성화할 메뉴 이외는 모두 비활성화 처리 함)
	 * @param {Object} actionObj 클릭한 탭의 오브젝트
	 * @param {String} tabMenuDiv 탭기능을 처리할 영역의 ID
	 */
	changeTabImage : function(actionObj, tabMenuDiv) {
		var objs = $(tabMenuDiv).getElementsByTagName('img');
		
		for (var i = 0; i < objs.length; i++) {
			if (objs[i] == actionObj) {
				objs[i].onmouseover = null;
				objs[i].onmouseout = null;

				jsl.menuOver(objs[i]);
			}
			else {
				objs[i].onmouseover = function(){
					eval('jsl.menuOver(this)');
				};
				
				objs[i].onmouseout = function(){
					eval('jsl.menuOut(this)');
				};
				
				jsl.menuOut(objs[i]);
			}
		}
	},
	/**
	 * sorting 테이블 up, down 이미지 클릭시 클릭한 메뉴 활성, 비활성화 한다.
	 * (활성화할 메뉴 이외는 모두 비활성화 처리 함)
	 * @param {Object} actionObj 클릭한 탭의 오브젝트
	 */
	changeSortImage : function (actionObj) {
		
		imgObj = actionObj.getElementsByTagName('img');

		if (jsl.changeImageObject == imgObj) {
			if (imgObj[0].src.indexOf("_down00.gif") != -1) { /* 같은 td 클릭시 down을  up으로 */
				imgObj[0].src = imgObj[0].src.replace("_down00.gif", "_up00.gif");
			}
			else { /* 같은 td 클릭시 up을  down으로 */
				imgObj[0].src = imgObj[0].src.replace("_up00.gif", "_down00.gif");
			}
			jsl.changeImageObject = imgObj;
		}
		else {
			/* 다른 td 정렬시 기존 이미지 비활성화, 클릭이미지 활성화 */
			if (jsl.changeImageObject != null) { 
				/* 이전 td가 up, down모두 비활성 down */
				jsl.changeImageObject[0].src = jsl.changeImageObject[0].src.replace("_up00.gif", "_down01.gif");
				jsl.changeImageObject[0].src = jsl.changeImageObject[0].src.replace("_down00.gif", "_down01.gif");
				
				/* 현재 td를 활성 down */
				imgObj[0].src = imgObj[0].src.replace("_up00.gif", "_down00.gif");
				imgObj[0].src = imgObj[0].src.replace("_down01.gif", "_down00.gif");
			}
			else { /* 처음 클릭시 비활성화 down을 활성화 down으로 */
				imgObj[0].src = imgObj[0].src.replace("_down01.gif", "_down00.gif");
			}
			jsl.changeImageObject = imgObj;
		}
		
	},
	
	/**
	 * index값에 위치한 tabButton을 활성화 합니다.
	 * @param {String} index 인덱스
	 * @param {String} tabMenuDiv TabMenu 영역 ID
	 */
	activeTabImage: function(index, tabMenuDiv) {
		var objs = $(tabMenuDiv).getElementsByTagName('img');
		
		for (var i = 0; i < objs.length; i++) {
			if (i == index){
				objs[i].onmouseover = null;
				objs[i].onmouseout = null;

				jsl.menuOver(objs[i]);
			}
			else {
				objs[i].onmouseover = function(){
					eval('jsl.menuOver(this)');
				};
				
				objs[i].onmouseout = function(){
					eval('jsl.menuOut(this)');
				};
				
				jsl.menuOut(objs[i]);
			}
		}
	},
	
	/**
	 * 발생한 Key Event가 ReturnKey인지 검사한다.
	 */
	isReturnKey: function(keyCode){
		return keyCode == Event.KEY_RETURN;
	},
	
	/**
	 * Form을 생성하여 리턴합니다.
	 * @param {Array} data 히든필드에 저장할 데이터 [{key: value}]
	 * @return {Object} 히든필드 정보가 들어있는 form Object
	 */
	createForm: function(data){
		var form = document.createElement('form');

		for (var i = 0; i < data.length; i++){
			var input = document.createElement('input');
			
			input.type = 'hidden';
			input.id = data[i].id;
			input.name = data[i].id;
			input.value = data[i].value;
			
			form.appendChild(input); 
		}
		
		return form;
	},
	
	/**
	 * 히든폼을 생성하여 지정한 Form에 추가합니다.
	 * @param {Object} formObj 폼 오브젝트
	 * @param {Object} fieldId 필드 아이디
	 * @param {Object} value 값
	 */
	createHiddenField: function(formObj, fieldId, value){
		var fieldObj = document.createElement('input');
		
		fieldObj.type = 'hidden';
		fieldObj.id = fieldId;
		fieldObj.value = value;
		
		formObj.appendChild(fieldObj);
	},

    /**
    * 지정한 폼 내에 히든필드를 제거합니다.
    * @param {Object} formObj 폼 오브젝트
    * @param {String} fieldId 삭제할 히든필드의 ID
    */
    removeHiddenField: function(formObj, fieldId){
        for (var idx = 0; idx < formObj.childNodes.length; idx++){
            if (formObj.childNodes[idx].id == fieldId) {
                formObj.removeChild(formObj.childNodes[idx]);
            }
        }
    },

    /**
	 * 지정한 그룹의 체크박스중 한개 이상이 Checked 되어 있는지 확인합니다.
	 * @param {Object} chkListName 체크박스 Name(ID아님)
	 * @return {Boolean} 체크박스 선택유무
	 */
	isGroupChecked: function(chkListName){
		var chkList = document.getElementsByName(chkListName);
		var isChecked =  false;

        for (var idx = 0; idx < chkList.length; idx++){
			if (chkList[idx].checked){
				isChecked = true;
			}
		}
		
		return isChecked;
	},
	
	/**
	 * 체크박스 일괄 체크 토글기능
	 * @param {Boolean} isCheck 체크유무
	 * @param {String} chkListName 체크박스 Name (ID아님)
	 */
	setChkboxChecked: function(isCheck, chkListName){
		var chkAccountList = document.getElementsByName(chkListName);
		
		for (var idx = 0; idx < chkAccountList.length; idx++) {
			chkAccountList[idx].checked = isCheck;
		}
    },


    /**
	 * 체크박스 일괄 체크 토글기능
	 * @param {Object} checkbox 가 위치해 있는 formObj
	 * @param {String} toggle 기능을 수행 하는 checkbox id (NAME 아님)
	 * @param {String} chkListName 체크박스 Name (ID아님)
	 */
	toggleCheck: function(formObj, checkId, chkListName){
		var isChecked = document.getElementById(checkId).checked;

        // niceform 인 경우
        if( formObj.className == "niceform"){
            for (var idx = 0; idx < hana.JHanaNiceForms.checkboxes.length; idx++) {
                if(hana.JHanaNiceForms.checkboxes[idx].name == chkListName) {
                    //var tester = false;
                    if (isChecked) {
                        hana.JHanaNiceForms.checkboxLabels[idx].className = "chosen";
                    }
                    else {
                         hana.JHanaNiceForms.checkboxLabels[idx].className = "";
                    }
                    hana.JHanaNiceForms.checkboxes[idx].checked = isChecked;
                    hana.JHanaNiceForms.checkCheckboxes(idx, isChecked);
                }
            }
        }else{
            jsl.setChkboxChecked(isChecked,chkListName);
        }
    }
};

/**
 * Start of namespace
 */
jsl.login = {};
jsl.main = {};
jsl.svfq = {};
jsl.examples = {};
/**
 * Extension Javascript Module namespace
 */
jsl.extJS = {};

/**
 * Form Event Module namespace
 */
jsl.form = {};

/**
 * tag lib
 */
jsl.tag = {};

/**
 * 업무단위 namespace
 */
var biz = {};

biz.index = {};
biz.login = {};
biz.main = {};
biz.member = {};
biz.prdt = {};
biz.cart = {};
biz.buy = {};
biz.pay = {};
biz.largebuy = {};

/**
 * Menu Navigation
 */
jsl.menu = {
	/**
	 * 왼쪽메뉴 페이지 이동
	 * 
	 * @param {Object} pageURL
	 * @param {Object} formObj
	 */
	goMenu : function(pageURL, destDiv, formObj) {
		
		var hanaAjax = null;
		
		if ( destDiv == undefined || destDiv == null ) {
			destDiv = jsl.CONTENT_WRAP;
		}
		
		hanaAjax = new hana.JHanaAjax(destDiv, true, true);	
	
		//alert(jsl.APPLICATION_CONTEXT_ROOT + pageURL);
		hanaAjax.ajaxCommSubmit(jsl.APPLICATION_CONTEXT_ROOT + pageURL, formObj);
		
	}
};

/**
 * Ajax Utilities
 */
jsl.ajax = {
	/**
	 * Ajax의 Callback함수로 넘겨받은 데이터를 가공/처리한다.
	 * 데이터가 json타입일 경우 가공/처리 하지 않는다.
	 * @param {Object} res response 데이터
	 * @param {boolean} isDebug 에러일경우 추가정보를 볼것인지?
	 */
	parseData : function(res, isDebug){	
		var resType = res.getResponseHeader('json-type');
		if (resType == 'error') {
			jsl.ajax.callMsgBox('ERROR', jsl.ajax.setErrParsing(res.responseText,isDebug));
			return;			
		} else if (resType == 'normal') {
			// callback에서 처리한다.
		} else if (resType == 'redirect') {
			var redirectURL = eval('(' + res.responseText + ')');
			location.href = jsl.APPLICATION_CONTEXT_ROOT+redirectURL;
			return;
		}
//		else {
//			jsl.ajax.callMsgBox('ERROR', '결과 TYPE이  정의되지 않았습니다.');
//		}
	},
	
	/**
	 * Json Type으로 Return된 ErrorData를 가공된 ErrorMessage로 리턴한다.
	 * @param {String} data responseText 데이터
	 * @param {boolean} isDebug 추가정보를 파싱할것인지?
	 */
	setErrParsing : function(data,isDebug){
		var _data = eval('(' + data + ')');
		var errorContent = '';
		if (_data) {
			var errorCount = _data.length;
			var errorCode = '';
			var errorMessage = '';
			var errorProgram = '';
			var errorPost ='';
			if (errorCount == 1) {
				// 에러가 한개 이다.
				errorCode = _data[0].errorCode;
				errorMessage = _data[0].errorMessage;
				errorProgram = _data[0].errorProgram;
				errorPost = _data[0].errorPost;
				
				if (null==errorProgram || errorProgram =='null' || errorProgram == '') {
					errorContent += errorCode + ' : ' + errorMessage;
				} else {
					errorContent += errorCode + ' : ' + errorMessage +' , '+errorProgram+' : '+errorPost;	
				}
				
			}
			else if(errorCount > 1){
				for (var i = 0; i < errorCount; i++) {
					errorCode = _data[i].errorCode;
					errorMessage = _data[i].errorMessage;
					errorProgram = _data[i].errorProgram;
					errorPost = _data[i].errorPost;
					
					if (null == errorProgram || errorProgram == 'null' || errorProgram == '') {
						errorContent += errorCode + ' : ' + errorMessage  + '<br/>';						
					} else {
						// 나타낼 메세지를 구성한다.
						errorContent += errorCode + ' : ' + errorMessage +' , '+errorProgram+' : '+errorPost + '<br/>';						
					}
				}
				
			}
		} else {
			// 알수 없는 오류
			errorContent += 'XXXX : 알수없는 오류 유형입니다.';
		}
		
		return errorContent;
	},
	
	/**
	 * Json 타입으로 리턴된 데이터를 지정한 필드 순으로 정렬하여 리턴합니다.
	 * @param {Object} data Json 데이터
	 * @param {String} field 정렬 기준필드명
	 * @return {Object} 정렬된 Json 데이터
	 */
	jsonSorting: function(data, field){
		for (var i = 0; i < data.length; i++){
			for (var j = i + 1; j < data.length; j++){
				if (eval('data[i].' + field) > eval('data[j].' + field)){
					var changeObj = data[i];
					
					data[i] = data[j];
					data[j] = changeObj;
				}
			}
		}
		
		return data;
	},

	/**
	 * Alert 창을 보여준다.
	 * @param {String} errorTitle Alert창에 보여줄 Title
	 * @param {String} errorContent Alert창에 보여줄 Content
	 */	
	callMsgBox : function(errorTitle, errorContent){
		// TO-DO 에러페이지가 본문인 경우가 있고,
		// 시스템 에러인 경우 별도 지정된 DIV 를 띄워 준다. (에러메세지가 고정되어 있는 경우 - 마스터에 지정)
		// Ext.MessageBox 를 쓸 경우는 지정된 스타일을 임포트한다.(마스터에 지정 )
 
 		jsl.extJS.messageBox.errMsgBox({
			isConfirm: false,
			title: '오류',
			message: errorContent,
			callback: function(e){
				
			}
		});
	}
// TO-DO 
//	,
//	
//	/**
//	 * 더블클릭 방지 트랜잭션 관련
//	 */
//	dblClickTran : {
//		
//		/**
//		 * 클릭수 누적 데이터
//		 */
//		dblClickCount : 0,
//		
//		/**
//		 * 더블클릭 트랜잭션 설정
//		 */
//		begin : function() {
//			jsl.ajax.dblClickTran.dblClickCount++;
//		},
//		
//		/**
//		 * 더블클릭 트랜잭션 해제
//		 */
//		end : function() {
//			jsl.ajax.dblClickTran.dblClickCount = 0;
//		},
//		
//		/**
//		 * 더블클릭 여부
//		 */
//		isDblClick : function() {
//			return !(jsl.ajax.dblClickTran.dblClickCount == 1);
//		}
//	}
}
/**
 * End of namespace
 */

var windowH = window.screen.height;
var windowY = window.screen.width;

//Ext.BLANK_IMAGE_URL = jsl.APPLICATION_CONTEXT_ROOT+"/resource/js/ext-2.1/resources/images/default/s.gif";
//Event.observe(window, 'load', function(){jsl.initMoving($('mymenu'))});
