// LAMPA Platform - Linux Apache MySQL PHP AJAX
//
//		David Young
//
// File:
//		ajax.js
//
// Usage:
//		<script>
//			// instantiating the object
//			var aj = new ajax();
//			// overloading wait functions for this specific page
//			aj.wait_on = function () {
//				var w = document.getElementById("wait_div");
//				w.innerHTML = "Please wait...";
//			}
//			aj.wait_off = function () {
//				var w = document.getElementById("wait_div");
//				w.innerHTML = "";
//			}
//			// load a remote page content into a div
//			aj.fetch("http://test.com/file.html", "mydiv_1");
//			// load a remote script and execute it
//			aj.fetch("http://test.com/blah.js");
//			// to post to a url in the background without respond
//			aj.bgpost("http://test.com/post", hash_keys);
//		</script>
//		<div id="wait_div"></div>
//		<div id="mydiv_1"></div>
//		<div id="mydiv_2">
//			<form method="post" action="http://test.com"
//				onSubmit="return aj.formsubmit(this, 'mydiv_2', true);">
//			<input type=submit name="abc" value="xyz">
//			</form>
//		</div>
//
// Notes:
//	1.	When calling fetch() or formsubmit() without the "target_div" parameter,
//		the return text should be pure JavaScript code which will be loaded by eval().
//	2.	The "wait_flag" parameter for fetch() and formsubmit() is there so that you
//		can display user friendly message while it is fetching the data.  You must
//		overload your own wait_on() and wait_off() function to display and then erase
//		the wait message.
//


// AJAX Object
function ajax () {
	this.wait_on = function () {};

	this.wait_off = function () {};

	this.parseform = function (form, hash) {
		for (i = 0; i < form.elements.length; i++) {
			var input = form.elements[i];
			var type = input.type.toLowerCase();
			if (type == "text" || type == "textarea" || type == "hidden" || type == "password" || type == "submit") {
				if (hash[input.name]) {
					if (typeof(hash[input.name]) == 'object') {
						hash[input.name][hash[input.name].length] = input.value;
					} else {
						var temp = hash[input.name];
						hash[input.name] = new Array();
						hash[input.name][0] = temp;
						hash[input.name][1] = input.value;
					}
				} else {
					hash[input.name] = input.value;
				}
			} else if (type == "checkbox" || type == "radio") {
				if (hash[input.name]) {
					if (input.checked) {
						if (typeof(hash[input.name]) == 'object') {
							hash[input.name][hash[input.name].length] = input.value;
						} else {
							var temp = hash[input.name];
							hash[input.name] = new Array();
							hash[input.name][0] = temp;
							hash[input.name][1] = input.value;
						}
					}
				} else {
					hash[input.name] = '';
					if (input.checked) {
						hash[input.name] = input.value;
					}
				}
			} else if (type == "select-one" && input.selectedIndex >= 0) {
				hash[input.name] = input.options[input.selectedIndex].value;
			} else if (type == "select-multiple" && input.selectedIndex >= 0) {
				hash[input.name] = new Array();
				for (var j=0; j < input.options.length; j++) {
					if (input.options[j].selected) {
						hash[input.name][hash[input.name].length] = input.options[j].value;
					}
				}
			}
		}
		return hash;
	}

	this.formsubmit = function (form, target_div, wait_flag) {
		if (wait_flag) {
			this.wait_on();
		}
		var url = form.action;
		var hash = new Object();
		hash = this.parseform(form, hash);
		var req = new http_request();
		req.eval_flag = true;
		req.target_div = target_div;
		req.wait_flag = wait_flag;
		req.wait_off = this.wait_off;
		if (typeof(form.method) == 'string' && form.method.toLowerCase() == 'get') {
			req.post(req, url, hash, 'ajax_callback');
		} else {
			req.post(req, url, hash, 'ajax_callback');
		}
		return false;
	}

	this.fetch = function (url, target_div, wait_flag) {
		if (wait_flag) {
			this.wait_on();
		}
		var req = new http_request();
		req.target_div = target_div;
		req.eval_flag = true;
		req.wait_flag = wait_flag;
		req.wait_off = this.wait_off;
		req.get(req, url, null, 'ajax_callback');
	}

	this.bgpost = function (url, hash, wait_flag) {
		if (wait_flag) {
			this.wait_on();
		}
		var req = new http_request();
		req.wait_flag = wait_flag;
		req.wait_off = this.wait_off;
		req.eval_flag = false;
		req.post(req, url, hash, 'ajax_callback');
	}
}


// XML HTTP Request Object
function http_request () {
	try {
		this.request = new XMLHttpRequest();
	} catch (try_microsoft) {
		try {
			this.request = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (other_microsoft) {
			this.request = new ActiveXObject("Microsoft.XMLHTTP");
		}
	}
	this.callback = '';

	this.get = function (req, url, hash, cb_func_name) {
		var get_string = '';
		for (var key in hash) {
			if (typeof(hash[key]) == 'object') {
				for (var i = 0; i < hash[key].length; i++) {
					get_string += '&' + escape(key) + '=' + escape(hash[key][i]);
				}
			} else {
				get_string += '&' + escape(key) + '=' + escape(hash[key]);
			}
		}
		this.callback = cb_func_name;
		if (url.indexOf('?') >= 0) {
			url += '&' + get_string;
		} else {
			url += '?' + get_string;
		}
		this.request.open("GET", url, true);
		this.request.onreadystatechange = function() {
			if (req.request.readyState == 4) {
				eval(req.callback + "(req)");
			}
		}
		this.request.send(null);
	}

	this.post = function (req, url, hash, cb_func_name) {
		var post_data = '';
		for (var key in hash) {
			if (typeof(hash[key]) == 'object') {
				for (var i = 0; i < hash[key].length; i++) {
					post_data += '&' + key + '=' + escape(hash[key][i]);
				}
			} else {
				post_data += '&' + key + '=' + escape(hash[key]);
			}
		}
		this.callback = cb_func_name;
		this.request.open("POST", url, true);
		this.request.setRequestHeader("Method", "POST " + url + " HTTP/1.1");
		this.request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		this.request.onreadystatechange = function() {
			if (req.request.readyState == 4) {
				eval(req.callback + "(req)");
			}
		}
		this.request.send(post_data);
	}

	this.activate_js = function () {
		var script_pattern = '(?:<script.*?>)((\n|.)*?)(?:</script>)';
		var match = new RegExp(script_pattern, 'img');
		var scripts = this.request.responseText.match(match);
		var head = document.getElementsByTagName("head")[0];
		if (scripts) {
			for (var i = 0; i < scripts.length; i++) {
				var match = new RegExp(script_pattern, 'im');
				js = scripts[i].match(match)[1];
				if (js.match(/function/im)) {
					var node = document.createElement('script');
					node.type = 'text/javascript';
					node.text = js;
					head.appendChild(node);
				} else {
					eval(js);
				}
			}
		}
	}
}


// Standalone callback function
function ajax_callback (req) {
	if (req.target_div) {
		var div = document.getElementById(req.target_div);
		div.innerHTML = req.request.responseText;
		req.activate_js();
	} else {
		if (req.eval_flag) {
			eval(req.request.responseText);
		} else {
			//alert(req.request.responseText);
		}
	}
	if (req.wait_flag) {
		req.wait_off();
	}
}

