/************************************************************************
* ajax 관련 펑션
************************************************************************/

/**
* XML 리퀘스터 얻기
* XML 리퀘스터 객체를 얻습니다.
* @return 얻은 리퀘스터 객체
* @author 곽병의 (patracyu@hanmail.net)
*/
function getXMLRequester() {
    if (typeof XMLHttpRequest != "undefined") {
    	return new XMLHttpRequest();
	} else if (typeof ActiveXObject != "undefined") {
		return new ActiveXObject("MSXML2.XmlHttp");
	} else {
		throw new Error("can't find XMLRequester");
	}
}

/**
* 동기 요청 (콜백 없음)
* 결과가 Text로 반환됨
* @param url 요청 url
* @param form 요청 내용을 담은 form
* @author 곽병의 (patracyu@hanmail.net)
*/
function ajaxSyncRequest(url, form) {
	var	req;
	var	frm;
	
	req	= getXMLRequester();
	if (form == null) {
		frm	= null;
	} else {
		if (typeof(form) == "string") {
			frm	= document.forms[form];
		} else {
			frm	= form;
		}
		if (frm == null) {
			alert("주어진 이름의 폼 [" + formName + "]을 찾을 수 없습니다.");
			return null;
		}
	}	
	
    if (frm == null) {
	    req.open("GET", url, false);
    	req.setRequestHeader('Content-Type'
        , 'application/x-www-form-urlencoded');
	    req.send();
    } else {
		var	pms;

	    pms	= _getParameters4Ajax(frm);
	    req.open("POST", url, false);
    	req.setRequestHeader('Content-Type'
        , 'application/x-www-form-urlencoded');
	    req.setRequestHeader('Content-Length', pms.length);
	    req.send(pms);
    }

    if (req.status != 200) {
    	throw new Error("request fail : http status " + req.status
    		+ " " + req.statusText);
    } else {
    	return req.responseText;
    }
}

/**
 * 비동기 요청을 필터링 하는 펑션을 지정 할 수 있습니다.
 * @param url 요청 url
 * @param form 요청 폼
 * @param reqObj 요청 XMLRequester 객체
 * @return true를 리턴하면 요청 수행 false를 리턴하면 수행하지 않음
 * @author 곽병의 (patracyu@hanmail.net)
 */
var	_ajaxRequestFilter	= null;


/**
 * 비동기 요청의 응답을 필터링 하는 펑션을 지정 할 수 있습니다.
 * @param resObj ajax의 응답 객체
 * @return true를 리턴하면 지정한 callback 수행 false를 리턴하면 failback 수행
 * Ajax 비동기 요청의 응답으로 전달되는 객체의 내용
 * 속성 content(String) 	: Ajax의 결과물 (html 혹은 xml과 같은)
 * 속성 script(String) 	: Ajax의 자바스크립트 결과물 (eval을 통해 실행 하거나 객체로 변환)
 * 속성 nocMsgs(Array)  	: 참고 메세지들
 * 속성 altMsgs(Array)  	: 강조 메세지들
 * 속성 errMsg(String)  	: 오류 메세지
 * 속성 errMsgDtls(Array)	: 오류의 상세 메세지들
 * @author 곽병의 (patracyu@hanmail.net)
 */
var	_ajaxResponseFilter	= null;

/**
* 비동기 요청
* @param url 요청 url
* @param form 요청 내용을 담은 form
* @param callback 요청 결과를 수신할 콜백 펑션으로 인수로 전달되는 값은 content, script 입니다.
* 인수 content(String) 	: Ajax의 결과물 (html 혹은 xml과 같은)
* 인수 script(String) 	: Ajax의 자바스크립트 결과물 (eval을 통해 실행 하거나 객체로 변환)
* @param failback 요청 실패시 호출되는 펑션. 인수는 없습니다.
* @param precall 요청 하기 바로 전에 호출하는 펑션. 리턴값이 false 이면 요청을 중단합니다.
* @author 곽병의 (patracyu@hanmail.net)
*/
function ajaxRequest(url, form, callback, failback, precall) {
	var	req;
	var	frm;
	
	req	= getXMLRequester();
	if (form == null) {
		frm	= null;
	} else {
		if (typeof(form) == "string") {
			frm	= document.forms[form];
			if (frm == null) {
				alert("주어진 이름의 폼 [" + form + "]을 찾을 수 없습니다.");
				return;
			}
		} else {
			frm	= form;
		}
	}	

    req.onreadystatechange	= function() {
    	var resObj;
    	var	callFlag;
    	
    	if (req.readyState != 4) {
    		return;
    	}

		if (req.status != 200) {
	    	alert("request fail : http status " + req.status
	    		+ " " + req.statusText);
	    	if (failback != null) {
	    		failback();
	    	}
	    	return;
		}
		
		try {
			resObj	= eval(req.responseText);
		} catch (error) {
		    alert("올바른 AJAX 응답이 아닙니다.");
			//window.location.reload();
	    	if (failback != null) {
	    		failback();
	    	}
	    	return;
		}
		
		if (resObj.id != "AjaxResponse") {
			alert("올바른 AJAX 응답이 아닙니다.");
	    	if (failback != null) {
	    		failback();
	    	}
	    	return;
		}
		
		if (_ajaxResponseFilter != null) {
			callFlag	= _ajaxResponseFilter(resObj);
		} else {
			callFlag	= true;
		}
		
		if (callFlag) {
			if (callback != null) {
				callback(resObj.content, resObj.script);
			}
		} else {
			if (failback != null) {
				failback();
			}
		}
    }
	
    if (frm == null) {
	    req.open("GET", url, true);
    	req.setRequestHeader('Content-Type'
        , 'application/x-www-form-urlencoded');
        if (_ajaxRequestFilter == null || _ajaxRequestFilter(url, frm, req)) {
        	var sendFlag;
        	
        	if (precall != null) {
	        	sendFlag	= precall();
			} else {
				sendFlag	= true;
			}
			if (sendFlag) {
			    req.send();
			}
		}
    } else {
		var	pms;

	    pms	= _getParameters4Ajax(frm);
	    req.open("POST", url, true);
    	req.setRequestHeader('Content-Type'
        , 'application/x-www-form-urlencoded');
	    req.setRequestHeader('Content-Length', pms.length);
        if (_ajaxRequestFilter == null || _ajaxRequestFilter(url, frm, req)) {
        	var sendFlag;
        	
        	if (precall != null) {
	        	sendFlag	= precall();
			} else {
				sendFlag	= true;
			}
			if (sendFlag) {
			    req.send(pms);
			}
		}
    }
}

/**
* 보다 일반화 된 비동기 요청
* 주어진 대상 HTMK 요소에 요청결과를 innerHTML에 반영하고, 스크립트는 eval 함스를 호출하여 수행
* 시킵니다.
* @param url 요청 url
* @param form 요청 내용을 담은 form
* @param target 요청 결과를 innerHTML로 설정할 대상 HTML 요소 객체 혹은 아이디.
* @param onResponsed 요청 결과 수신후 실행 해야할 스크립트 펑션을 지정합니다.
* @author 곽병의 (patracyu@hanmail.net)
*/
function ajaxGenericRequest(url, form, target, onResponsed) {
	var	backupHtml;
	
	if (target != null) {
		if (typeof(target) == "string") {
			target	= document.all[target];
		}
		backupHtml	= target.innerHTML;
	}
	ajaxRequest(url, form,
		function(content, script) {
			if (target != null) {
				target.innerHTML	= content;
			}
			try {
				eval(script);
			} catch (e) {
				alert("수신된 스크립트를 수행하는데 오류가 발생했습니다.\n"
					+ e.message + "\n"
					+ script);
			}
			if (onResponsed != null) {
				eval(onResponsed)();
			}
		},
		function () {
			if (target != null) {
				target.innerHTML	= backupHtml;
			}
		},
		function () {
			if (target != null) {
			}
			return true;
		}
		
	);
}

/**
 * 내부 사용 펑션.
 * ajax 콜을 위해 주어진 from 객체에서 파라메터들을 식을 얻습니다.
 * @param frm 대상 폼
 * @return 대상 폼이 가지는 파라메터들을 폼 파라메터 인코딩 한 문자열
 * @author 곽병의 (patracyu@hanmail.net)
 */
function _getParameters4Ajax(frm) {

	if (frm.elements.length == 0) {
		return "";
	} else {
		var	rv;
		
		rv	= "";
		for (var i=0 ; i<frm.elements.length; i++) {
			var work;
			
			work	= _getParameter4Ajax(frm.elements[i]);
			if (rv.length > 0
				&& work.length > 0) {
				rv += "&";
			}
			rv	+= work;
		}
		return rv;
	}
}

/**
 * 내부 사용 펑션
 * _getParameters4Ajax() 펑션에 의해 호출되며, 하나의 폼 엘리먼트의 이름과 값을 
 * 폼 파라메터 인코딩 문자열로 반환합니다.
 * @return 주어진 폼 엘리먼트의 폼 파라메터 문자열 
 * @author 곽병의 (patracyu@hanmail.net)
 */
function _getParameter4Ajax(elm) {
	var	elmt;

	if (elm.disabled) {
		return "";
	}

	elmt	= elm.type.toLowerCase();
	if (elmt == "checkbox"
		|| elmt == "radio") {
		if (!elm.checked) {
			return "";
		}
	}
	
	return encodeURIComponent(elm.name) + "=" + encodeURIComponent(elm.value);
}