/**
* AJAX - Ajax calls for IHM
*
* Javascript 1.3 compliant
* Compatibility tested with :
* - Internet Explorer 6.5
* - Firefox 1.5
* If you tested with other browsers, please send and email to compatibility@pillot.fr
*
* Needs ihm.js to be included to work
*
* LICENCE: This source file is subject to version of the GPL license
* that is available through the world-wide-web at the following URL :
* http://www.gnu.org/licenses/gpl.txt.  If you did not receive a copy of
* the GPL License and are unable to obtain it through the web, please
* send a note to license@pillot.fr so we can mail you a copy immediately.
*
* @author    Baptiste Pillot <baptiste@pillot.fr>
* @copyright 2000-2006 Baptiste Pillot
* @license   http://www.gnu.org/licenses/gpl.txt
* @version   2.3
* @link      http://www.pillot.fr
*/

/** Is set to 1 while ajax call is being executed, reset to 0 when done */
var ajax_call_unsolved = 0;

/** Array containing last urls to ajax calls */
var ajax_call_last = new Array();

/** Memorize ajax infos */
var ajax_url = "";

/** Ajax popup window coords */
var ajax_x = 0;
var ajax_y = 0;

/** Set to true to cancel a pending ajax load */
var ajax_http_cancel = false;

/** destination frame where to load ajax call result */
var ajax_dest = "";

/** ajax call http object */
var ajax_http = null;

/** ajax queue when multiple-ajax clicks */
var ajax_queue = new Array();

/** ajax callback calls */
var ajax_callback_functions = new Array();

/** ajax close windows list : one list per dest */
var ajax_please_close = new Array();

/** write the name of a form whose content changed to disable ajax calls if form is not written */
var ajax_tag_change = new Array();

var ignore_ajax_tag_change = new Array();

//------------------------------------------------------------------------------ function ajaxCall
/** Ajax Call :
* url is the server-side script
* dest is the ID of the layer to output read html result into
* params is the optional form to send elements from,
*        or an array containing data to send to the server-size script
* mode is the sending mode of data (default is automatic, could be forced to GET or POST)
* with keep_message on, message zone will not be erased when calling ajax
* if after_what is given, content will be inserted after this html code
* if before_what is given, content will be inserted before this html code
* if queue_search is given, queue search-and-replace will be on a part of the url
* you can write in destination only between after_what and before_what */
function ajaxCall(url, dest, params, mode, keep_message, after_what, before_what, queue_search, no_callback_functions_call)
{
	var no_dest = false;
	var continue_ajax = true;
	if (dest == undefined) {
		dest = "";
	}
	if (ajax_tag_change[dest] && !ignore_ajax_tag_change[dest]) {
		continue_ajax = confirm(
			"Si vous continuez, les modifications saisies seront perdues. Confirmez-vous ?"
		);
	} else {
		continue_ajax = true;
	}
	if (continue_ajax) {
		if (ignore_ajax_tag_change[dest]) {
			ignore_ajax_tag_change[dest] --;
		}
		ajax_tag_change[dest] = 0;
		var ajax_as_iframe = false;
		// add dest into getvars
		if (dest) {
			if (url.indexOf("?") == -1) {
				url = url + "?";
			} else {
				url = url + "&";
			}
			url = url + "ajax_dest=" + dest;
		}
		// enqueue if already ajax execution
		if (ajax_call_unsolved) {
			// one ajaxcall only accepted simultaneously
			// enqueue following calls (only if not the same as current)
			if (!ajax_http || url != ajax_http_url) {
				var do_replace = false;
				var is_found = false;
				for (i = 0; i < ajax_queue.length; i++) {
					if (queue_search == undefined) {
						// strict url search
						if (ajax_queue[i][0] == url) {
							is_found = true;
						}
					} else {
						// partial url search and replace
						if (ajax_queue[i][0].indexOf(queue_search) > -1) {
							if (dest == ajax_queue[i][1]) {
								is_found = true;
								do_replace = i;
							}
						}
					}
				}
				if (!is_found) {
					// enqueue only if not already in queue
					ajax_queue.reverse();
					ajax_queue.push(new Array(url, dest, params, mode, keep_message, after_what, before_what, no_callback_functions_call));
					ajax_queue.reverse();
				} else if (do_replace !== false) {
					// replace mode when partial url found
					ajax_queue[do_replace][0] = url;
				}
			}
		} else if (url.substr(0,3) == "js:") {
			// only javascript call, no ajax
			eval(url.substr(3));
		} else {
			// calculate params string
			var prm = "";
			if (params) {
				if (typeof(params) == "string") {
					// - works with simple param=value&param=value
					prm = params;
				} else if (params.elements) {
					// - can be a form element : included inputs will be sent
					prm = formToUrl(params);
					// - if form contains file fields, form will be post in a hidden iframe instead of pure-ajax
					if (formContainsFiles(params)) {
						ajax_as_iframe = true;
						ajax_as_iframe_form = params;
						if (!layerFind("ajax_file_upload_iframe")) {
							var body = document.getElementsByTagName("BODY");
							body = body[0];
							var iframe = document.createElement("iframe");
							iframe.setAttribute("id", "ajax_file_upload_iframe");
							iframe.setAttribute("name", "ajax_file_upload_iframe");
							iframe.setAttribute("style", "display:none;");
							body.appendChild(iframe);
						}
						var iframe_layer = layerFind("ajax_file_upload_iframe");
						if (iframe_layer.contentDocument != undefined) {
							// others
							iframe_layer.contentDocument.body.innerHTML = "ajax_file_upload_iframe";
						} else {
							// IE
							var idoc = iframe_layer.contentWindow.document; 
							idoc.open();
							idoc.write("ajax_file_upload_iframe");
							idoc.close();
						}
						params.enctype = "multipart/form-data";
						params.method = "post";
						params.target = "ajax_file_upload_iframe";
						params.action = url + "&ajax_iframe=1";
						params.submit();
					}
				}
			}
			// ajax call mode
			ajax_call_unsolved++;
			if (!mode) {
				if (prm.length) mode = "POST";
				else mode = "GET";
			}
			// prepare http request
			ajax_http = null;
			try {
				if (ajax_as_iframe) {
					ajax_http = new Object();
				} else {
					ajax_http = new XMLHttpRequest();
				}
			} catch (e) {
				try {
					ajax_http  = new ActiveXObject("Microsoft.XMLHTTP");
				} catch (e) {
					try {
						ajax_http  = new ActiveXObject("Msxml2.XMLHTTP");
					} catch (e) {
						ajax_http = false;
						alert("AJAX Error: Your browser is not Ajax compatible !");
					}
				}
			}
			// clear messages layer
			if (!keep_message && dest != "app_messages" && layerFind("app_messages")) {
				layerWrite(layerFind("app_messages"), "");
				layerToFront(layerFind("app_messages"));
				// please wait message
				//layerWrite(layerFind(dest), "... please wait ...");
			}
			// memorize some parameters to use it on response
			ajax_http_x = mouse_x + 1;
			ajax_http_y = mouse_y + 1;
			ajax_http_dest = dest;
			ajax_http_url = url;
			ajax_http_after_what = after_what;
			ajax_http_before_what = before_what;
			ajax_http_no_callback_functions_call = no_callback_functions_call;
			//-------------------------------------------------------------------------- function ajax_http.onreadystatechange
			// ajax callback function
			ajax_http.onreadystatechange = function()
			{
				if (ajax_http.readyState == 4) {
					ajax_call_unsolved--;
					if (ajax_http.status == 200) {
						if (ajax_http_cancel) {
							// erase ajax_http object
							ajax_http_dest = "";
							// cancel
							ajax_http_cancel = false;
						} else {
							// close opened windows that depend on this dest
							if (ajax_http_dest && ajax_please_close[ajax_http_dest]) {
								var object_to_close;
								while (ajax_please_close[ajax_http_dest].length) {
									object_to_close = ajax_please_close[ajax_http_dest].pop();
									if (typeof(object_to_close) == "object") {
										object_to_close.free();
									} else if (typeof(controls.elements[object_to_close]) == "object") {
										controls.elements[object_to_close].free();
									} else if (layerFind(object_to_close)) {
										layerFind(object_to_close).parentNode.removeChild(layerFind(object_to_close));
									}
								}
							}
							if (typeof(ajax_http_dest) != "string" || ajax_http_dest != "") {
								// display ajax returned html
								var layer = (typeof(ajax_http_dest)) == "string" ? layerFind(ajax_http_dest) : ajax_http_dest;
								//var layer = layerFind(ajax_http_dest);
								var response_text = ajax_http.responseText;
								// extract ajax javascript
								var deb = 0;
								var fin = 0;
								var response_javascript = "";
								i = 0;
								while ((deb = response_text.indexOf("<SCRIPT", fin)) > -1) {
									var cut_deb = deb;
									deb = response_text.indexOf(">", deb) + 1;
									fin = response_text.indexOf("</SCRIPT>", deb);
									var cut_fin = fin + 9;
									response_javascript = response_javascript + response_text.substr(deb, fin - deb);
									response_text = response_text.substr(0, cut_deb) + response_text.substr(cut_fin);
									fin = cut_deb;
								}
								if (layer) {
									// with after_what and before_what options,
									// you can write wherever you want in layer
									if (ajax_http_after_what && ajax_http_before_what) {
										text  = layer.innerHTML;
										i = text.indexOf(ajax_http_after_what) + ajax_http_after_what.length;
										j = text.indexOf(ajax_http_before_what, i);
										text = text.substr(0, i)
										+ response_text
										+ text.substr(j);
										layerWrite(layer, text);
										layerToFront(layer);
									} else {
										layerWrite(layer, response_text);
										layerToFront(layer);
									}
									var app_debug = layerFind("app_debug");
									if (app_debug && !ajax_http_no_callback_functions_call) {
										app_debug.innerHTML = "&nbsp;" + Math.round((response_text.length / 1024)) + "Ko&nbsp;";
									}
								} else {
									layer = new SimpleWindow(ajax_http_dest, "",response_text, ajax_http_x, ajax_http_y);
								}
							}
							// record last ajax call getvars
							var params = ajax_http_url.split("?");
							ajax_call_last[ajax_http_dest] = new Array();
							ajax_call_last[ajax_http_dest][""] = params[0];
							if (params.length > 1) {
								params = params[1].split("&");
								for (var i = 0; i < params.length; i++) {
									var prm = params[i].split("=");
									if (prm.length > 2) {
										for (var j = 2; j < prm.length; j++) {
											prm[1] = prm[1] + '=' + prm[j];
										}
										while (prm.length > 2) {
											prm.pop();
										}
									}
									ajax_call_last[ajax_http_dest][prm[0]] = prm[1];
								}
							}
							// erase ajax_http object
							last_ajax_http_dest = ajax_http_dest;
							ajax_http_dest = "";
							// execute ajax returned javascript
							if (response_javascript) {
								try {
									// uses htmlspecialchars_decode as we've got strange problems with iframes
									eval(htmlspecialchars_decode(response_javascript));
								} catch(e) {
									// catch javascript errors
									alert("JS error " + e.name + " " + e.message + " on ajax returned javascript code :\n" + htmlspecialchars_decode(response_javascript));
								}
							}
							// ajax callback functions call
							if (!ajax_http_no_callback_functions_call) {
								for (var i = 0; i < ajax_callback_functions.length; i++) {
									try {
										eval(ajax_callback_functions[i]);
									} catch(e) {
										alert("JS error " + e.name + " " + e.message + " on ajax callback call :\n" + ajax_callback_functions[i]);
									}
								}
							}
						}
					} else {
						alert("AJAX Error: returned status code " + ajax_http.status + " : " + ajax_http.statusText);
						// erase ajax_http object
						ajax_http_dest = "";
					}
					// pop ajax call queue, if there are enqueued calls
					if (ajax_queue.length) {
						call = ajax_queue.pop();
						ajaxCall(call[0], call[1], call[2], call[3], call[4], call[5], call[6], undefined, call[7]);
					}
				}
			};
			//-------------------------------------------------------------------------- ajaxCall (end)
			// do the call
			window.setTimeout("ajaxClock(" + ajax_as_iframe + ");", 1000);
			if (!ajax_as_iframe) {
				ajax_http.open(mode, url, true);
				if (mode == "POST") {
					ajax_http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
				}
				ajax_http.send(prm);
			}
		}
	}
}

//------------------------------------------------------------------------------ function ajaxClock
var ajax_clock = 0;
function ajaxClock(ajax_as_iframe)
{
	if (ajax_as_iframe) {
		var iframe_layer = layerFind("ajax_file_upload_iframe");
		var iframe_text;
		if (iframe_layer.contentDocument != undefined) {
			// others
			iframe_text = iframe_layer.contentDocument.body.innerHTML;
		} else {
			// IE
			iframe_text = iframe_layer.contentWindow.document.body.innerHTML;
		}
		if (iframe_text != "ajax_file_upload_iframe") {
			ajax_http.readyState = 4;
			ajax_http.status = 200;
			if (iframe_layer.contentDocument != undefined) {
				// others
				ajax_http.responseText = iframe_layer.contentDocument.body.innerHTML;
			} else {
				// IE
				ajax_http.responseText = iframe_layer.contentWindow.document.body.innerHTML;
			}
			while (ajax_http.responseText.indexOf("<ajax_script") > -1) {
				ajax_http.responseText = ajax_http.responseText.replace("<ajax_script", "<SCRIPT").replace("</ajax_script", "</SCRIPT");
			}
			while (ajax_http.responseText.indexOf("<AJAX_SCRIPT") > -1) {
				ajax_http.responseText = ajax_http.responseText.replace("<AJAX_SCRIPT", "<SCRIPT").replace("</AJAX_SCRIPT", "</SCRIPT");
			}
			ajax_http.onreadystatechange();
			if (iframe_layer.contentDocument != undefined) {
				// others
				iframe_layer.contentDocument.body.innerHTML = "";
			} else {
				// IE
				var idoc = iframe_layer.contentWindow.document; 
				idoc.open();
				idoc.write("stop");
				idoc.close();
			}
		}
	}
	if (!ajax_clock) {
		ajax_clock = new Control("ajax_clock", "<IMG SRC=img/clock.gif>", mouse_x + 16, mouse_y + 16, 11, 16);
	} else {
		ajax_clock.setPosXY(mouse_x + 16, mouse_y + 16);
	}
	if (!ajax_call_unsolved) {
		ajax_clock.free();
		ajax_clock = 0;
	} else {
		window.setTimeout("ajaxClock(" + ajax_as_iframe + ");", 20);
	}
}

//------------------------------------------------------------------------------ function ajaxHintOn
/** Show hint popup, loaded with ajax */
function ajaxHintOn(url, params, mode)
{
	if (!ajax_call_unsolved) {
		// hide old popup
		ajaxHintOff();
		// when setTimeout, reload params
		if (!url) {
			url = ajax_hint_on_url;
			params = ajax_hint_on_params;
			mode = ajax_hint_on_mode;
		}
		// ajax call
		return ajaxCall(url, 'app_hint', params, mode, true);
	} else {
		// if ajax call already pending, must wait
		if (url) {
			// - save params
			ajax_hint_on_url = url;
			ajax_hint_on_params = params;
			ajax_hint_on_mode = mode;
		}
		// - try again in 1/5 sec
		setTimeout('ajaxHintOn()', 200);
	}
}

//---------------------------------------------------------------------------- function ajaxHintOff
/** Hide hint popup */
function ajaxHintOff()
{
	if (controls.app_hint) {
		// close loaded hint popup
		controls.app_hint.free();
	}
	if (ajax_http_dest == "app_hint") {
		// cancel current ajax popup load if not already displayed
		if (!ajax_http_cancel) {
			ajax_http_cancel = true;
			setTimeout("ajaxHintOff()", 200);
		}
	}
}

//-------------------------------------------------------------------------- function ajaxWillClose
/**
 * Declare that window-layer named "window" should close when "dest" is closed or reloaded
 */
function ajaxWillClose(dest, window)
{
	if (!ajax_please_close[dest]) {
		ajax_please_close[dest] = new Array();
	}
	ajax_please_close[dest].push(window);
}

//------------------------------------------------------------------------------- function dynPopup
var dyn_popup_input    = "dyn_popup_input";
var dyn_popup_value    = "dyn_popup_value";
var dyn_popup_form     = "dyn_popup_form";
var dyn_popup_id_field = "dyn_popup_id_field";
/**
 * Transforms text input into Dynamic popup, loading data from a specific url
 * Popup into correctly positionned and dimensionned window
 * Needs ajax.js library !
 */
function dynPopup(text_input, url, force_popup, id_field, post_vars)
{
	if (!controls.app_dyn_popup || !controls.app_dyn_popup.visible || force_popup) {
		if (dyn_popup_value != text_input.value
		|| dyn_popup_form != text_input.form.name
		|| dyn_popup_id_field != id_field
		|| dyn_popup_input != text_input) {
			if (!controls.app_dyn_popup) {
				// create popup control
				new Control(
					"app_dyn_popup",
					"",
					layerPosX(text_input),
					layerPosY(text_input) + layerHeight(text_input),
					layerWidth(text_input)
				);
			} else {
				controls.app_dyn_popup.write("");
			}
			// fill in content with ajax call
			ajaxCall(
				url + "&a[begin]=" + urlEncode(text_input.value) + "&a[form]=" + urlEncode(text_input.form.name) + (id_field ? "&a[view_fields]=&a[id_field]=" + urlEncode(id_field) : ""),
				"app_dyn_popup",
				post_vars,
				undefined,
				true,
				undefined,
				undefined,
				url + "&a[begin]="
			);
			// reset position and show control
			controls.app_dyn_popup.setPosXY(
				layerPosX(text_input),
				layerPosY(text_input) + layerHeight(text_input)
			);
			dyn_popup_input = text_input;
			dyn_popup_value = text_input.value;
			dyn_popup_form = text_input.form.name;
			dyn_popup_id_field = id_field;
		}
		controls.app_dyn_popup.show();
	} else {
		// release popup control
		//if (dyn_popup_input != undefined) {
		//dyn_popup_input.focus();
		//}
		controls.app_dyn_popup.hide();
		dyn_popup_value = "dyn_popup_value";
		dyn_popup_form = "dyn_popup_form";
	}
}

