TIP게시판

제목 ajaxcall - How can I make an AJAX call without jQuery?
글쓴이 darkninja 작성시각 2023/06/17 23:45:03
댓글 : 1 추천 : 0 스크랩 : 0 조회수 : 24666   RSS

How can I make an AJAX call without jQuery?

https://stackoverflow.com/questions/8567114/how-can-i-make-an-ajax-call-without-jquery

https://developer.mozilla.org/en-US/docs/Web/HTTP/Status

https://github.com/codeigniter4/CodeIgniter4/blob/develop/system/HTTP/Response.php

실무에 바로 적용하기에는 모자람이 있습니다

충분히 검토하고 보완해서 사용하세요!

index.php


<!doctype html>
<html>

<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
	<title>Ajaxcall</title>
	<style type="text/css" media="screen">
	</style>
</head>

<body>
	<div style="border: 1px solid #ddd; padding: 10px;">
		ajax_formdata
		<div id="ajax_formdata"></div>
	</div><br/>	

	<div style="border: 1px solid #ddd; padding: 10px;">
		ajax_info
		<div id="ajax_info"></div>
	</div><br/>		

	<div style="border: 1px solid #ddd; padding: 10px;">
		ajax_result
		<div id="ajax_result"></div>
	</div>	

	<script type="text/javascript" src="ajax.js"></script>
	<script type="text/javascript">
		var ajax_formdata = document.getElementById("ajax_formdata");
		var ajax_info = document.getElementById("ajax_info");
		var ajax_result = document.getElementById("ajax_result");
		
        var formData = {
			id          : '_id',
			subject     : '_subject',
			contents    : '_contents',
			time        : '_time'
        };
		
		ajax_formdata.innerText = "obj_param: "+obj_param(formData);
		//ajax_formdata.innerText = "obj_param: "+JSON.stringify(formData);

		function loadtext() {
			Ajaxcall({
				url: "get.php",
				type: "POST",
				data: formData,
				//contentType: "json",
				async: true, //synchronous request. Default value is true 
				timeout: 10000, //default timeout 20000
				beforeSend: function() {
					ajax_info.innerText = "loading...";
				},
				dataType: 'text',
				success: function(result, status) {
					if (status == "success") {
						if (result) {
							ajax_info.innerText = "success...";
							ajax_result.innerText = result;
						}	
						else {
							ajax_info.innerText = "resule none...";
							ajax_result.innerText = "";
						}	
					}
					else {
						ajax_info.innerText = "timeout...";
						ajax_result.innerText = "";
					}	
				},
				error: function(status, statusText) {
					alert("error code: " + status + "\n" + "error message: " + statusText);
				}
			});
		}	
		loadtext();
	</script>
</body>

</html>

get.php


<?php

$data = file_get_contents("php://input");
echo "file_get_contents('php://input')"."\n";
echo $data."\n";

if (isset($_GET) && count($_GET) > 0) {
	parse_str($data, $input); 

	echo "\n";
	echo "parse_str data to input"."\n";
	print_r($input);
	echo "\n";

	echo "_GET"."\n";
	print_r($_GET);

	echo "id => ".$_GET["id"];
}
else if (isset($_POST) && count($_POST) > 0) {
	parse_str($data, $input); 

	echo "\n";
	echo "parse_str data to input"."\n";
	print_r($input);
	echo "\n";

	echo "\n";
	echo "_POST"."\n";
	print_r($_POST);

	echo "id => ".$_POST["id"];
}
else {
	//contentType: "json"
	$param = json_decode($data, false);
	echo "\n";
	echo "json"."\n";
	echo "id => ".$param->id."\n";
	echo "subject => ".$param->subject."\n";
	echo "contents => ".$param->contents."\n";
}	

?>

ajaxcall.js


//https://stackoverflow.com/questions/8567114/how-can-i-make-an-ajax-call-without-jquery
//https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
//https://github.com/codeigniter4/CodeIgniter4/blob/develop/system/HTTP/Response.php

var ajax_load_process = false;

var xhr_statusCodes = {
    // 1xx: Informational
    100 : 'Continue',
    101 : 'Switching Protocols',
    102 : 'Processing', // http://www.iana.org/go/rfc2518
    103 : 'Early Hints', // http://www.ietf.org/rfc/rfc8297.txt
    // 2xx: Success
    200 : 'OK',
    201 : 'Created',
    202 : 'Accepted',
    203 : 'Non-Authoritative Information', // 1.1
    204 : 'No Content',
    205 : 'Reset Content',
    206 : 'Partial Content',
    207 : 'Multi-Status', // http://www.iana.org/go/rfc4918
    208 : 'Already Reported', // http://www.iana.org/go/rfc5842
    226 : 'IM Used', // 1.1; http://www.ietf.org/rfc/rfc3229.txt
    // 3xx: Redirection
    300 : 'Multiple Choices',
    301 : 'Moved Permanently',
    302 : 'Found', // Formerly 'Moved Temporarily'
    303 : 'See Other', // 1.1
    304 : 'Not Modified',
    305 : 'Use Proxy', // 1.1
    306 : 'Switch Proxy', // No longer used
    307 : 'Temporary Redirect', // 1.1
    308 : 'Permanent Redirect', // 1.1; Experimental; http://www.ietf.org/rfc/rfc7238.txt
    // 4xx: Client error
    400 : 'Bad Request',
    401 : 'Unauthorized',
    402 : 'Payment Required',
    403 : 'Forbidden',
    404 : 'Not Found',
    405 : 'Method Not Allowed',
    406 : 'Not Acceptable',
    407 : 'Proxy Authentication Required',
    408 : 'Request Timeout',
    409 : 'Conflict',
    410 : 'Gone',
    411 : 'Length Required',
    412 : 'Precondition Failed',
    413 : 'Content Too Large', // https://www.iana.org/assignments/http-status-codes/http-status-codes.xml
    414 : 'URI Too Long', // https://www.iana.org/assignments/http-status-codes/http-status-codes.xml
    415 : 'Unsupported Media Type',
    416 : 'Requested Range Not Satisfiable',
    417 : 'Expectation Failed',
    418 : "I'm a teapot", // April's Fools joke; http://www.ietf.org/rfc/rfc2324.txt
    // 419 (Authentication Timeout) is a non-standard status code with unknown origin
    421 : 'Misdirected Request', // http://www.iana.org/go/rfc7540 Section 9.1.2
    422 : 'Unprocessable Content', // https://www.iana.org/assignments/http-status-codes/http-status-codes.xml
    423 : 'Locked', // http://www.iana.org/go/rfc4918
    424 : 'Failed Dependency', // http://www.iana.org/go/rfc4918
    425 : 'Too Early', // https://datatracker.ietf.org/doc/draft-ietf-httpbis-replay/
    426 : 'Upgrade Required',
    428 : 'Precondition Required', // 1.1; http://www.ietf.org/rfc/rfc6585.txt
    429 : 'Too Many Requests', // 1.1; http://www.ietf.org/rfc/rfc6585.txt
    431 : 'Request Header Fields Too Large', // 1.1; http://www.ietf.org/rfc/rfc6585.txt
    451 : 'Unavailable For Legal Reasons', // http://tools.ietf.org/html/rfc7725
    499 : 'Client Closed Request', // http://lxr.nginx.org/source/src/http/ngx_http_request.h#0133
    // 5xx: Server error
    500 : 'Internal Server Error',
    501 : 'Not Implemented',
    502 : 'Bad Gateway',
    503 : 'Service Unavailable',
    504 : 'Gateway Timeout',
    505 : 'HTTP Version Not Supported',
    506 : 'Variant Also Negotiates', // 1.1; http://www.ietf.org/rfc/rfc2295.txt
    507 : 'Insufficient Storage', // http://www.iana.org/go/rfc4918
    508 : 'Loop Detected', // http://www.iana.org/go/rfc5842
    510 : 'Not Extended', // http://www.ietf.org/rfc/rfc2774.txt
    511 : 'Network Authentication Required', // http://www.ietf.org/rfc/rfc6585.txt
    599 : 'Network Connect Timeout Error' // https://httpstatuses.com/599
}

function obj_param(obj) {
	var parts = [];
	for (var key in obj) {
		if (obj.hasOwnProperty(key)) {
			parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));
		}
	}
	return parts.join('&');
}

//create an XMLHttpRequest object
function GetXMLHttpRequest() {   
	var xhr = false;
    if (typeof XMLHttpRequest !== 'undefined') {
		xhr = new XMLHttpRequest();
		if (xhr.overrideMimeType) {
			xhr.overrideMimeType('text/xml');
		}
	} 
	else if (window.ActiveXObject) {
		//var versions = [ "MSXML2.XmlHttp.6.0", "MSXML2.XmlHttp.5.0", "MSXML2.XmlHttp.4.0", "MSXML2.XmlHttp.3.0", "MSXML2.XmlHttp.2.0", "Microsoft.XmlHttp" ];
		//for (var i = 0; i < versions.length; i++) {
		//	try { xhr = new ActiveXObject(versions[i]); break; } catch (e) {}
		//}
		try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) {
			try { xhr = new ActiveXObject("Microsoft.XMLHTTP");	} catch(e) {}
		}
	}
	if (!xhr) { return 0; }
	return xhr;
}

function Ajaxcall(param, response) 
{
	if (ajax_load_process == true) {
		return;
	}
	if (param.async == undefined) {
		param.async = true;
	}
	if (param.async == false) {
		ajax_load_process = true;
	}
	if (param.beforeSend != undefined) {
		param.beforeSend();
	};

	var xhr = GetXMLHttpRequest();
	if (!xhr) { return 0; }

	if (param.timeout != undefined) {
		xhr.timeout = param.timeout;
	}
	else {
		xhr.timeout = 20000;
	}

	if (param.type != "GET") {
		xhr.open(param.type, param.url, param.async);

		if (param.processData != undefined && param.processData == false && param.contentType != undefined && param.contentType == false) {
		}
		else if (param.contentType != undefined && param.contentType == "json") {
			xhr.setRequestHeader("Content-type", "application/json; charset=utf-8");
		}
		else if (param.contentType != undefined || param.contentType == true) {
			xhr.setRequestHeader('Content-type', param.contentType);
		}
		else {
			xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");			
		}
	}
	else {
		if (param.data) {
			xhr.open(param.type, param.url + "?" + obj_param(param.data), param.async);
		}
		else {
			xhr.open(param.type, param.url, param.async);
		}	
	}

	xhr.onprogress = function(loadTime) {
		if (param.progress != undefined) {
			param.progress({ loaded: loadTime.loaded }, "success");
		}
	}

	xhr.ontimeout = function () {
		this.abort(response);
		param.success("timeout", "timeout");
		ajax_load_process = false;
	};

	xhr.onerror = function() {
		if (param.error != undefined) {
			param.error(xhr, xhr_statusCodes[xhr.status], xhr.statusText);
		}	
		ajax_load_process = false;
	};
	
    xhr.onreadystatechange = function() {
		if(xhr.readyState == 0) { //UNSENT  Client has been created. open() not called yet.
		}
		else if(xhr.readyState == 1) { //OPENED  open() has been called.
		}
		else if(xhr.readyState == 2) { //HEADERS_RECEIVED  send() has been called, and headers and status are available.
		}
		else if(xhr.readyState == 3) { //LOADING  Downloading; responseText holds partial data.
		}
		else if (xhr.readyState == 4) { //DONE  The operation is complete.
			if (xhr.status == 200) { //request succesfull
			}
			else { //request failled
			}
		}
	}

	xhr.onload = function() {
		if (xhr.status == 200) {
			var data;
			if (param.dataType != undefined) {
				if (param.dataType == "document") {
					data = xhr.responseXML;
				}	
				else if (param.dataType == "json") {
					try { data = JSON.parse(xhr.responseText); } catch (err) { data = null; }
				} 
				else if (param.dataType == "stringify") {
					data = JSON.stringify(xhr.responseText);
				}
				else if (param.dataType == "text") {
					data = xhr.responseText;
				}	
				else { //"arraybuffer", "blob", "html"
					data = xhr.response;
				}	
			}	
			else {
				data = xhr.responseText;
			}
			param.success(data, "success");
		}
		else {
			if (param.error != undefined) {
				param.error(xhr, xhr_statusCodes[xhr.status], xhr.statusText);
			}	
		}
		ajax_load_process = false;
	};
		
	if (param.data != null || param.data != undefined) {
		if (param.processData != undefined && param.processData == false && param.contentType != undefined && param.contentType == false) {
			xhr.send(param.data);
		}
		else if (param.contentType != undefined && param.contentType == "json") {
			xhr.send(JSON.stringify(param.data));
		}
		else {
			xhr.send(obj_param(param.data));
		}
	}
	else {
		xhr.send();
	}
		
	this.abort = function(response) {
		if (XMLHttpRequest != null) {
			xhr.abort();
			ajax_load_process = false;
			if (response != undefined) {
				response({ status: "success" });
			}
		}
	}

}

/**********
	function loadsatimg() {
		var satimg = document.getElementById("satimg");
		Ajaxcall({
			url: "<?php echo site_url(); ?>/home/satimg",
			type: "GET",
			data: null,
			contentType: null,
			dataType: 'json',
			async: true,//synchronous request. Default value is true 
			timeout: 10000,//default timeout 20000
			beforeSend:function(){
				satimg.src = "<?php echo base_url(); ?>images/ajax-loading.gif";
				satimg.width = "150";
				satimg.height = "150"
			},
			success:function(result, status){
				if (result) {
					//alert(result['imgsrc']);
					satimg.src = result['imgsrc'];
					satimg.title = result['title'];
				}	
				else
					satimg.src = "<?php echo base_url(); ?>images/no-image.gif";
			},
			error:function(xhr,statusCodes,statusText){
				alert("status:"+xhr.status+"\n"+"statusCodes:"+statusCodes+"\n"+"statusText:"+statusText+"\n"+"responseText:"+xhr.responseText);
			}
		});
	}	

	//for abort previous requests
    my_ajaxCall.abort(function(result) { console.log(result); });
*/

 

 

 다음글 PHP 8.2 CLI Xdebug 사용 방법
 이전글 풀다운 메뉴(pulldown menu) css, js

댓글

darkninja / 2024/05/03 23:40:14 / 추천 0

수정 : ontimeout에서 param.timeout을 호출하는데

param.timeout은 xhr.timeout에 대응하는 값이므로 사용할수 없는 이름입니다;

param.abort가 비슷한 역할을 하여 메세지만 다르게 전달하여 공통으로 사용합니다.

 

생각보다 많은 관심을 보여주셨는데

미흡한 부분에 대한 지적은 아무도 안하시네요;

실력이 부족하다 보니 업데이트가 년단위로 진행됩니다.

함수 호출에서 xhr를 리턴하여 외부에서 취소를 하는 코드를 추가하였습니다.

async를 false로 할때 timeout값을 내부에서 0으로 만듭니다.

  관련 코드를 없애고 호출시에 timeout값을 0으로 주어도 되겠죠.

async값이 false일때 responseType값이 있으면 에러가 나더군요 이것도 timeout값과 같은 방식으로 처리하면 되겠네요.

windows 11 Edge에서만 테스트 했습니다.

저는 실력이 부족한 초보이므로 저의 지식과 코드조각들은 완벽하지 않습니다!

//2024.05.10
//https://stackoverflow.com/questions/8567114/how-can-i-make-an-ajax-call-without-jquery

//https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
//https://github.com/codeigniter4/CodeIgniter4/blob/develop/system/HTTP/Response.php
var ajaxcall_statusCodes = {
    // 1xx: Informational
    100 : 'Continue',
    101 : 'Switching Protocols',
    102 : 'Processing', // http://www.iana.org/go/rfc2518
    103 : 'Early Hints', // http://www.ietf.org/rfc/rfc8297.txt
    // 2xx: Success
    200 : 'OK',
    201 : 'Created',
    202 : 'Accepted',
    203 : 'Non-Authoritative Information', // 1.1
    204 : 'No Content',
    205 : 'Reset Content',
    206 : 'Partial Content',
    207 : 'Multi-Status', // http://www.iana.org/go/rfc4918
    208 : 'Already Reported', // http://www.iana.org/go/rfc5842
    226 : 'IM Used', // 1.1; http://www.ietf.org/rfc/rfc3229.txt
    // 3xx: Redirection
    300 : 'Multiple Choices',
    301 : 'Moved Permanently',
    302 : 'Found', // Formerly 'Moved Temporarily'
    303 : 'See Other', // 1.1
    304 : 'Not Modified',
    305 : 'Use Proxy', // 1.1
    306 : 'Switch Proxy', // No longer used
    307 : 'Temporary Redirect', // 1.1
    308 : 'Permanent Redirect', // 1.1; Experimental; http://www.ietf.org/rfc/rfc7238.txt
    // 4xx: Client error
    400 : 'Bad Request',
    401 : 'Unauthorized',
    402 : 'Payment Required',
    403 : 'Forbidden',
    404 : 'Not Found',
    405 : 'Method Not Allowed',
    406 : 'Not Acceptable',
    407 : 'Proxy Authentication Required',
    408 : 'Request Timeout',
    409 : 'Conflict',
    410 : 'Gone',
    411 : 'Length Required',
    412 : 'Precondition Failed',
    413 : 'Content Too Large', // https://www.iana.org/assignments/http-status-codes/http-status-codes.xml
    414 : 'URI Too Long', // https://www.iana.org/assignments/http-status-codes/http-status-codes.xml
    415 : 'Unsupported Media Type',
    416 : 'Requested Range Not Satisfiable',
    417 : 'Expectation Failed',
    418 : "I'm a teapot", // April's Fools joke; http://www.ietf.org/rfc/rfc2324.txt
    // 419 (Authentication Timeout) is a non-standard status code with unknown origin
    421 : 'Misdirected Request', // http://www.iana.org/go/rfc7540 Section 9.1.2
    422 : 'Unprocessable Content', // https://www.iana.org/assignments/http-status-codes/http-status-codes.xml
    423 : 'Locked', // http://www.iana.org/go/rfc4918
    424 : 'Failed Dependency', // http://www.iana.org/go/rfc4918
    425 : 'Too Early', // https://datatracker.ietf.org/doc/draft-ietf-httpbis-replay/
    426 : 'Upgrade Required',
    428 : 'Precondition Required', // 1.1; http://www.ietf.org/rfc/rfc6585.txt
    429 : 'Too Many Requests', // 1.1; http://www.ietf.org/rfc/rfc6585.txt
    431 : 'Request Header Fields Too Large', // 1.1; http://www.ietf.org/rfc/rfc6585.txt
    451 : 'Unavailable For Legal Reasons', // http://tools.ietf.org/html/rfc7725
    499 : 'Client Closed Request', // http://lxr.nginx.org/source/src/http/ngx_http_request.h#0133
    // 5xx: Server error
    500 : 'Internal Server Error',
    501 : 'Not Implemented',
    502 : 'Bad Gateway',
    503 : 'Service Unavailable',
    504 : 'Gateway Timeout',
    505 : 'HTTP Version Not Supported',
    506 : 'Variant Also Negotiates', // 1.1; http://www.ietf.org/rfc/rfc2295.txt
    507 : 'Insufficient Storage', // http://www.iana.org/go/rfc4918
    508 : 'Loop Detected', // http://www.iana.org/go/rfc5842
    510 : 'Not Extended', // http://www.ietf.org/rfc/rfc2774.txt
    511 : 'Network Authentication Required', // http://www.ietf.org/rfc/rfc6585.txt
    599 : 'Network Connect Timeout Error' // https://httpstatuses.com/599
}

var ajaxcall_process = false;

function Ajaxcall(param, call_back) 
{
	//create an XMLHttpRequest object
	function GetXMLHttpRequest() {   
		var xhr = false;
		if (typeof XMLHttpRequest !== 'undefined') {
			xhr = new XMLHttpRequest();
			if (xhr.overrideMimeType) {
				xhr.overrideMimeType('text/xml');
			}
		} 
		else if (window.ActiveXObject) {
			//var versions = [ "MSXML2.XmlHttp.6.0", "MSXML2.XmlHttp.5.0", "MSXML2.XmlHttp.4.0", "MSXML2.XmlHttp.3.0", "MSXML2.XmlHttp.2.0", "Microsoft.XmlHttp" ];
			//for (var i = 0; i < versions.length; i++) {
			//	try { xhr = new ActiveXObject(versions[i]); break; } catch (e) {}
			//}
			try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) {
				try { xhr = new ActiveXObject("Microsoft.XMLHTTP");	} catch(e) {}
			}
		}
		if (!xhr) { return 0; }
		return xhr;
	}

	function obj_param(obj) {
		var parts = [];
		for (var key in obj) {
			if (obj.hasOwnProperty(key)) {
				parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));
			}
		}
		return parts.join('&');
	}

	if (ajaxcall_process == true) {
		return;
	}

	if (param.async == undefined) {
		param.async = true;
	}
	
	if (param.async == false) {
		ajaxcall_process = true;
	}
	
	if (param.beforeSend != undefined) {
		param.beforeSend();
	};

	var xhr = GetXMLHttpRequest();
	if (!xhr) { return 0; }

	//https://xhr.spec.whatwg.org/#the-open()-method
	//If async is false, 
	//the current global object is a Window object, 
	//and either this’s timeout is not 0 or 
	//this’s response type is not the empty string, 
	//then throw an "InvalidAccessError" DOMException.
	if (param.async == false) {
		xhr.timeout = 0; 
		if (param.responseType == "json") {
			param.responseType = undefined;
		}	
	}
	else if (param.timeout != undefined) {
		xhr.timeout = param.timeout;
	}
	else {
		xhr.timeout = 20000;
	}

	//open GET
	if (param.type == "GET") {
		if (param.data) {
			xhr.open(param.type, param.url + "?" + obj_param(param.data), param.async);
		}
		else {
			xhr.open(param.type, param.url, param.async);
		}	
	}
	//other POST...
	else {
		xhr.open(param.type, param.url, param.async);

		if (param.processData != undefined && param.processData == false && 
			param.contentType != undefined && param.contentType == false) {
		}
		else if (param.contentType != undefined && param.contentType == "json") {
			xhr.setRequestHeader("Content-type", "application/json; charset=utf-8");
		}
		else if (param.contentType != undefined || param.contentType) {
			xhr.setRequestHeader('Content-type', param.contentType);
		}
		else {
			xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");			
		}
	}

	//responseType
	//"" : An empty responseType string is the same as "text", the default type.
	//"arraybuffer" : The response is a JavaScript ArrayBuffer containing binary data.
	//"blob" : The response is a Blob object containing the binary data.
	//"document" : The response is an HTML Document or XML XMLDocument, as appropriate based on the MIME type of the received data. See HTML in XMLHttpRequest to learn more about using XHR to fetch HTML content.
	//"json" : The response is a JavaScript object created by parsing the contents of received data as JSON.
	//"text" : The response is a text in a string.	
	if (param.responseType != undefined) {
		xhr.responseType = param.responseType;
	}	
	
	//if (param.responseType == "document") {
		// Force the response to be parsed as XML
	//	xhr.overrideMimeType("text/xml");
	//}	

	xhr.onprogress = function(loadTime) {
		if (param.progress != undefined) {
			param.progress({ loaded: loadTime.loaded }, "Ajaxcall progress.");
		}
	}

	xhr.ontimeout = function () {
		var status = "timeout";
		var msg = "Ajaxcall time out. (timeout : "+param.timeout+")";
		xhr.abort();
		if (call_back != undefined) {
			call_back({ status: status, msg: msg });
		}

		if (param.abort != undefined) {
			param.abort(status, msg); //call abort, not timeout. 
		}	
		ajaxcall_process = false;
	};

	xhr.onabort = function () {
		var status = "abort";
		var msg = "Ajaxcall abort.";
		xhr.abort();
		if (call_back != undefined) {
			call_back({ status: status, msg: msg });
		}

		if (param.abort != undefined) {
			param.abort(status, msg);
		}	
		ajaxcall_process = false;
	};

	xhr.onerror = function() {
		if (param.error != undefined) {
			param.error(xhr, ajaxcall_statusCodes[xhr.status], xhr.statusText);
		}	
		ajaxcall_process = false;
	};
	
    xhr.onreadystatechange = function() {
		if(xhr.readyState == 0) { //UNSENT  Client has been created. open() not called yet.
		}
		else if(xhr.readyState == 1) { //OPENED  open() has been called.
		}
		else if(xhr.readyState == 2) { //HEADERS_RECEIVED  send() has been called, and headers and status are available.
		}
		else if(xhr.readyState == 3) { //LOADING  Downloading; responseText holds partial data.
		}
		else if (xhr.readyState == 4) { //DONE  The operation is complete.
			if (xhr.status == 200) { //request succesfull
			}
			else { //request failled
			}
		}
	}

	//success	
	xhr.onload = function() {
		if (xhr.status == 200) {
			var data = false;
			var onload_status = "Ajaxcall load success.";

			if (param.dataType != undefined) {
				if (param.dataType == "document") {
					data = xhr.responseXML;
				}	
				else if (param.dataType == "json") {
					if (param.responseType == "json") {
						data = xhr.response; 
					}
					else { //param.responseType : text
						try { 
							data = JSON.parse(xhr.response); 
						} 
						catch (err) { 
							data = false; onload_status = "Ajaxcall load 'JSON parse Error'.";
						}
					}	
				} 
				else if (param.dataType == "text") {
					data = xhr.responseText;
				}	
				else if (param.dataType == "url") {
					data = xhr.responseURL;
				}	
				else { 
					data = xhr.response;
				}	
			}	
			else {
				data = xhr.response;
			}
			param.success(data, onload_status, xhr);
		}
		else {
			if (param.error != undefined) {
				param.error(xhr, ajaxcall_statusCodes[xhr.status], xhr.statusText);
			}	
		}
		ajaxcall_process = false;
	};
	
	//data send	
	if (param.data != null || param.data != undefined) {
		if (param.processData != undefined && param.processData == false && 
			param.contentType != undefined && param.contentType == false) {
			xhr.send(param.data);
		}
		else if (param.contentType != undefined && param.contentType == "json") {
			xhr.send(JSON.stringify(param.data));
		}
		else {
			xhr.send(obj_param(param.data));
		}
	}
	else {
		xhr.send();
	}

	return xhr;
}

function Ajaxcall_abort(xhr) {
	if (xhr) {
		xhr.abort();
	}
}	

/**********
node.json file
[
	{ 
		"name" : "手机", 
		"open" : "true",
		"nodes" : [
			{ "name" : "诺基亚" },
			{ "name" : "三星" },
			{ "name" : "索爱" },
			{ "name" : "多普达" }
		]
	},
	{ 
		"name" : "电脑", 
		"open" : "true",
		"nodes" : [
			{ 
				"name" : "硬件", 
				"checked" : "true" 
			},
			{ 
				"name" : "整机", 
				"checked" : "true" 
			},
			{ 
				"name" : "网络", 
				"checked" : "true" 
			}
		]
	},
	{ 
		"name" : "家电", 
		"open" : "true",
		"nodes" : [
			{ 
				"name" : "电视", 
				"checked" : "true" 
			},
			{ "name" : "冰箱" },
			{ "name" : "空调" }
		]
	}
]


        var formData = {
			id   : '_id',
			name : '_name'
        };

		var setting = {
			treeObjId: "tree1",
			checkable: true,
			async: true,
			asyncUrl: "node.json",  //?取?点?据的URL地址
			asyncParam: formData //其??? ( key, value ???格式)
		};

			{
				key: "asyncGetNode",
				value: function asyncGetNode(parentNode) {
					var _thisasyncGetNode = this;

					var _async = false;
					//var _result, _status;

					var _xhr = Ajaxcall({
						url: this.asyncUrl,
						type: "GET",
						data: this.asyncParam,
						responseType: "json",
						dataType: "json",
						async: _async, //synchronous request. Default value is true 
						timeout: 10000, //default timeout 20000
						beforeSend:function(){
						},
						success: function(result, status, xhr) {
							_xhr = null;

							//if (_async == false) {
							//	_result = result;
							//	_status = status;
							//}	

							//alert(result[0].name);

							if (! result || result.length == 0) {
								alert(status +"\n"+ xhr.response);
								return;
							}
							if (result) {
								_thisasyncGetNode.addTreeNodes(parentNode, result);
							}
							var myAsyncSuccessEvent = new CustomEvent(ZTREE_ASYNC_SUCCESS, {
								'detail': {
									treeObjId: _thisasyncGetNode.treeObjId,
									result: result,
									status: status,
									xhr: xhr
								}
							});
							document.querySelector("#" + _thisasyncGetNode.treeObjId).dispatchEvent(myAsyncSuccessEvent);
						},
						abort:function(status, msg){
							_xhr = null;
							alert(status+"\n"+msg); //abort, time out
						},
						error: function(xhr,statusCodes,statusText) {
							_xhr = null;
							alert("status:"+xhr.status+"\n"+"statusCodes:"+statusCodes+"\n"+"statusText:"+statusText+"\n"+"responseText:"+xhr.responseText);
							var myAsyncErrorEvent = new CustomEvent(ZTREE_ASYNC_ERROR, {
								'detail': {
									treeObjId: _thisasyncGetNode.treeObjId,
									xhr: xhr,
									statusCodes: statusCodes,
									statusText: statusText
								}
							});
							document.querySelector("#" + _thisasyncGetNode.treeObjId).dispatchEvent(myAsyncErrorEvent);
						}
					});
					//Ajaxcall_abort(_xhr);

					//
					//if (_async == false) {
					//	if (! _result || _result.length == 0) {
					//		alert(status +"\n"+ _xhr.response);
					//		return;
					//	}
					//	if (_result) {
					//		this.addTreeNodes(parentNode, _result);
					//	}
					//	var myAsyncSuccessEvent = new CustomEvent(ZTREE_ASYNC_SUCCESS, {
					//		'detail': {
					//			treeObjId: _thisasyncGetNode.treeObjId,
					//			result: _result,
					//			status: _status,
					//			xhr: _xhr
					//		}
					//	});
					//	document.querySelector("#" + this.treeObjId).dispatchEvent(myAsyncSuccessEvent);
					//}	
					//

					this.saveState();
				}
			},	

***********/