 
/****************************************************************************** 
* description : 
* XMLHttpRequest을 이용하여 비동기식 데이터 전송 컨트롤(AJAX 컨트롤) 
* HTML의 Form 객체의 Method, prototype 참조
* **
*
* 기존 버전에 비해 달라진 점
* 1. 여러 개의 컨트롤을 인스턴스하더라도, 처리는 단일 처리만 가능하였으나, 
*     Function의 apply prototype를 이용하여 다중 처리가 가능해짐.
* 2. 몇 가지의 프로퍼티의 이름이 기존 프로퍼티와 달리 변경됨
* 3. 수신 데이터의 Header에 따른 되돌림 값을 달리함. 또한 전송 시 Header부분에 대한 추가적 정보 전송
* 4. XML 데이터 수신시 Object 형태로 변환하는 함수 추가
* - COOKIE 부분에 대한 테스트가 없어 차후 필요로할 듯 싶음
* - XML 데이터 변환부분에 대한 추가적인 연구가 필요할 듯 싶음
* 
* last update : 2007.01 
* x-wiz by lee n.thu 
* e-mail : N.thu <support@x-wiz.com> 
* 사람이면 누구나 사용이 가능하며, 소스 수정은 들키지만 않음 수정 가능합니다. 
* ** 
/**
* AJAX Control
* ver 2.0b
* @Param strName {String}	선택값, 배열고유값 지정
*/

var xwzAjax=function(strName)
{
	if(window.xwzAjaxs ==null) window.xwzAjaxs=[];
	this.name			= strName || window.xwzAjaxs.length;
	window.xwzAjaxs[this.name] = this;

	this.XmlHttp		= null;/*XMLHttpRequest Object*/

	this.Method		= null;/*전송 방식, GET, POST, COOKIE,...*/
	this.Action		= null;/*호출할 파일 URL*/
	this.DecType	= null;/*데이터 파싱*/
	/* AUTO[=responseText(text/plain, text/javascript, text/html), responseXML(application/xml, text/xml) or XML or TEXT */

	this.method		= null;/*Method 동기화*/
	this.action		= null;/*Action 동기화*/
	this.dectype	 	= null;/*DataType 동기화*/
	this.decType		= null;/*DataType 동기화*/

	this.onLoad		= null;/*데이터 전송 완료 시 사용자 정의함수 참조 핸들러*/
	this.onError		= null;/*오류 발생시 사용자 정의함수 참조 핸들러*/
	this.onChange	= null;/*진행 상태 변경에 따른 사용자 정의함수 참조 핸들러*/

	this.onload		= null;/*onLoad 동기화*/
	this.onerror		= null;/*onerror 동기화*/
	this.onchange	= null;/*onchange 동기화*/

	this.onComplete=null;/*기존 버전과의 호환을 위한 프로퍼타*/
	this.DataType	= null;/*기존 버전과의 호환을 위한 프로퍼타*/

	this.Parameters=[];/*파라미터*/
	this.Submit=this.submit;/*submit 동기화*/
	/*
	* Function prototype 생성. XMLHttpRequest Object의 onreadystatechange 프로퍼티에 생성된 컨트롤 객체를 참조하기 위함 
	* 출처 : Prototype JavaScript framework 
	*/
	if(typeof Function.prototype.bind=='undefined')
			Function.prototype.bind = function() {	var _$=this,args =[],object=null;	for(var i=0,len=arguments.length;i<len;i++) args[i]=arguments[i];object = args.shift();return  function(){return _$.apply(object, args);}}
}
/** 파라미터 입력 함수
* @Param sName {String} 파라미터 이름(nodeName, nodeName[1], nodeName[],...)
* @Param mxVal {String, Number} 파라미터 전송 값
*/
xwzAjax.prototype.addParam=function(sName, mxVal){this.Parameters[sName] = (mxVal).toString();}
/** 파라미터 출력 함수
* @Param sName {String}
* @Return {String, Number}
*/
xwzAjax.prototype.getParam=function(sName){return this.Parameters[sName];}
/** 전송 함수
* @Return {Boolean}
*/
xwzAjax.prototype.submit=function()
{
	/*각 처리 프로세스의 function*/
	this.onload				= this.onload || this.onLoad||this.onComplete;
	this.onerror				= this.onerror || this.onError;
	this.onchange			= this.onchange || this.onChange;

	this.method		= this.method || this.Method || 'GET';
	this.action		= this.action || this.Action || window.location.href;
	this.decType		= this.decType || this.dectype || this.DecType||this.DataType|| 'AUTO';
	/*XMLHttpRequest Object 생성*/
	if(window.ActiveXObject){
		try{this.XmlHttp = new ActiveXObject("Msxml2.XMLHTTP");}catch(e){try{this.XmlHttp = new ActiveXObject("Microsoft.XMLHTTP");}catch(e){}}
	}else if(window.XMLHttpRequest){
		this.XmlHttp = new XMLHttpRequest();
	}
	/*XMLHttpRequest Object 생성 실패시 오류 처리 후 중단*/
	if(this.XmlHttp==null  && typeof this.onerror == "function"){this.onerror(-1, 'Problem creating AJAX');return false;}

	var URL			= this.action;
	var Entry = '', QUERY_STRING	= '';
	var QUERYS	= [];
	var Headers	={
		'Content-type' : 'application/x-www-form-urlencoded; charset=UTF-8',
		'Expires' : 'Sat, 01 Jan 2000 00:00:00 GMT',
		'Cache-Control' : 'no-store, no-cache, must-revalidate,post-check=0, pre-check=0',
		'Pragma' : 'no-cache',
		'X-Requested-By' : 'XMLHttpRequest',
		'Accept' : 'text/plain, text/javascript, text/html, application/xml, text/xml, */*'
	};
	/*파라미터값을 URL형태로 변경*/
	for(var Name in this.Parameters){Entry=Name+"="+encodeURIComponent(this.Parameters[Name]);QUERYS.push(Entry);}
	QUERY_STRING = QUERYS.join("&");

	/*GET 형식으로 전송할 경우*/
	if(this.method.toUpperCase() == 'GET'){URL += (URL.indexOf("?") === -1 ? '?' : '&' ) + QUERY_STRING;QUERY_STRING = null;	}

	/*응답 받은 데이터 처리 함수 프로퍼티 설정*/
	this.XmlHttp.onreadystatechange=this.ondataavailable .bind(this);

	/*데이터 전송 처리*/
	this.XmlHttp.open(this.method.toUpperCase(),URL, true);
	for(var n in Headers){this.XmlHttp.setRequestHeader(n, Headers[n]);}
	this.XmlHttp.send(QUERY_STRING);
   	this.ondataavailable ();/**/
	return true;
}
/** 전송받은 데이터에 대한 각 단계별 처리 함수 
* XML 데이터의 경우 Object형식으로 전달 함 
*/ 
xwzAjax.prototype.ondataavailable =function() 
{ 
    var stateText =['Uninitialized', '로딩중', 'Loaded', 'Interactive', 'Complete']; 
    var contentType=this.decType.toUpperCase(); 
    var resMimeType=''; 
    var resData=null; 
    /*상태값 변경에 따른 사용자 정의 함수가 설정되어 있는 경우 각 상태값을 해당 함수 인자로 전달한다.*/ 
    if(typeof this.onchange == 'function') this.onchange(this.XmlHttp.readyState, stateText[this.XmlHttp.readyState]); 

    /*모든 데이터 수신이 완료된 경우*/ 
    if(this.XmlHttp.readyState == 4){ 
        if(this.XmlHttp.status == 200){ 
            if(typeof this.onload=='function'){ 
                /*데이터 수신 타입을 자동으로 설정할 경우*/ 
                if(contentType=='AUTO'){ 
                    resMimeType=this.XmlHttp.getResponseHeader('Content-type'); 
                    contentType = ((resMimeType=='text/javascript'||resMimeType=='application/x-javascript')?'JS':null)||((resMimeType=='application/xml'||resMimeType=='text/xml')?'XML':null)||'TEXT'; 
                } 
                /** 수신 데이터 전달 
                *    Javascript load 
                *    출처 : svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/tapestry/core.js?view=diff&r1=418656&r2=418657&pathrev=418657 
                */ 
                if(contentType=='JS'){ 
                    try{eval(this.XmlHttp.responseText);}catch(err){if(typeof this.onerror=='function') this.onerror((err.number>>16 & 0xFFFF), err.description);} 
                }else if(contentType=='XML'){ 
                    resData=this.parseXML(this.XmlHttp.responseXML); 
                }else if(contentType=='TEXT'){ 
                    resData=this.XmlHttp.responseText; 
                } 
                this.onload(resData); 
            } 
        }else if(typeof this.onerror=='function'){/*HTML 페이지 오류가 발생할 경우 error 사용자 정의 함수 호출*/ 
            this.onerror(this.XmlHttp.status, this.XmlHttp.statusText); 
        } 
        /*초기화*/ 
        this.XmlHttp.onreadystatechange=function(){}; 
    } 
} 
/** responseXML 데이터를 Object형식으로 변환하는 함수
* @Param XML {Object} responseXML 
* @Return {Object}
*/
xwzAjax.prototype.parseXML=function(Data)
{
	var XML=null;
	if(Data.documentElement.hasChildNodes())
	{
		XML={childNodes:[]};/*최상위 객체 생성*/
		/*XML documentElement객체를 Node의 하위 객체로 생성한다.*/
		XML.childNodes[0]={nodeIndex:0,nodeName:Data.documentElement.nodeName,nodeValue:null,parentNode:XML,childNodes:[],prevNode:null,nextNode:null};
		XML[Data.documentElement.nodeName]={};/**/
		this.transmuteElement(XML.childNodes[0],XML[Data.documentElement.nodeName],Data.documentElement);/*하위 element 객체를 object 객체로 변경*/
	}
	return XML;
}

/** element object를 Javascript Object 형식으로 변환
* @Param item {Object} Javascript Object 각 Attribute Object가 존재함.
* @Param object {Object} Javascript Object로 link됨
* @Param elementNode {Object} responseXML 로 받은 XML Object의 element object
*/
xwzAjax.prototype.transmuteElement=function(item, object,elementNode)
{
	var itmN=null,n=0,hasChildNode=false;
	if(elementNode.hasChildNodes()){
		/*if(elementNode.nodeName=='parsererror'){sourcetext}*/
		for(var i=0,len=elementNode.childNodes.length;i<len, itmN=elementNode.childNodes[i];i++){
			if(itmN.nodeType!=1) continue;/*object element가 아닌 경우 실행하지 않음*/
			if(typeof item.childNodes =='undefined') item.childNodes=[];
			n = item.childNodes.length;/*현재 상위 객체의 각 하위 자식들의 갯수가 현재 생성될 객체의 index가 됨*/
			item.childNodes[n]={nodeIndex:n,nodeName:itmN.nodeName,nodeValue:null,parentNode:item,prevNode:null,nextNode:null};
			this.transmuteElement(item.childNodes[n],object[itmN.nodeName]={}, itmN);
			/*하위 element가 element object가 아닌 Text object인경우*/
			if(item.childNodes[n].nodeValue!=null) object[itmN.nodeName]=item.childNodes[n].nodeValue;
			if(n > 0){
				item.childNodes[n].prevNode=item.childNodes[n-1];
				if(typeof item.childNodes[n-1] == 'object') item.childNodes[n-1].nextNode=item.childNodes[n];
			}
			hasChildNode=true;
		}
		/*하위 객체들 중에 element 객체가 존재하지 않으며, 첫번째 하위 객체가 text element 객체인 경우 */
		if(hasChildNode!=true && elementNode.childNodes[0].nodeType==3){
			item.parentNode.childNodes[item.nodeIndex].nodeValue=elementNode.childNodes[0].nodeValue.toString();
		}
	}
}