/**
*	Javascript file for AJAX select widget
*	
*	@author Nathan Gray <nathangray@sourceforge.net>
*
*	@param widget_id the id of the ajax_select_widget
*	@param onchange function to call if the value of the select widget is changed
*	@param options the query object containing callback and settings
*	
*   @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
*   @package etemplate
*   @subpackage extensions
*   @link http://www.egroupware.org
*
*   @version $Id$
*/

//xajaxDebug = 1;
var current_app = 'etemplate';

/**
 * Settings for the timeout to prevent flooding the server with requests
 *
 * Adjust ajax_select_timeout to change how long to wait before sending the request (in ms)
 */
var ajax_select_timer_id = 0;
var ajax_select_timeout = 300;

var ajax_select_event = null;

// These keys will not trigger a search if the results box is currently displayed
var no_search_keys = [
	'9',		// Tab
	'38', '63232', 	// Up
	'40', '63233'	// Down
];

function ajax_select_widget_setup(widget_id, onchange, options, currentapp) {
	current_app = currentapp;
	if(onchange) {
		if(onchange == 1) {
			onchange = function() {submitit(this.form, this.value);};
		} else {
			eval("onchange = function(e) { " + onchange + ";}");
		}

		var value = document.getElementById(widget_id + '[value]');
		if(value) {
			if(value.addEventListener) {
				value.addEventListener('change', onchange, true);
			} else {
				var old = (value.onchange) ? value.onchange : function() {};
				value.onchange = function(e) {
					old(e);
					onchange(e);
				};
			}
		}
	}

	var widget = document.getElementById(widget_id + '[search]');
	if(widget) {
		widget.setAttribute('autocomplete', 'off');

		if(widget.addEventListener) {
			widget.addEventListener('keydown', checkKey, true);
			widget.addEventListener('keyup', timer_change, false);
			widget.addEventListener('blur', hideBox, false);
		} else {
			widget.onkeyup = timer_change;
			widget.onblur = hideBox;
			widget.onkeydown = checkKey;
		}

		// Set results
		var results = document.createElement('div');
		results.id = widget_id + '[results]';
		results.className = 'resultBox';
		results.style.position = 'absolute';
		// check if IE, if it is, fix the position
		if (document.all) {
			results.style.marginLeft = 0 - widget.offsetWidth - 2 * widget.offsetLeft - 1;
			results.style.marginTop = widget.offsetHeight + 1;
		}
		results.style.zIndex = 50;
		results.options = options;
		results.innerHTML = "";

		widget.parentNode.appendChild(results);
	}

	var value = document.getElementById(widget_id + '[value]');
	if(value) {
		value.style.display = 'none';
	}
}

function checkKey(e, value) {
	if(!e) {
		var e = window.event;
	}
	/*
	 * We check for Tab, Up and Down
	 */
	var interested = false;
	for(var i = 0; i < no_search_keys.length; i++) {
		if(e.keyCode == no_search_keys[i]) {
			interested = true;
			break;
		}
	}
	if (!interested) {
		return; // The user has not pressed anything we're interested in
	}

	if(e.target) {
		var target = e.target;
	} else if (e.srcElement) {
		var target = e.srcElement;
	}
	if(target) {
		if (target.nodeType == 3) { // defeat Safari bug
			target = target.parentNode;
		}
	}

	var id = target.id;
	var base_id = id.substr(0, id.lastIndexOf('['));
	var results = document.getElementById(base_id + '[results]');
	
	// Consume event so search doesn't go
	if(results.childNodes.length > 0) {
		e.cancelBubble = true;
		if(e.stopPropegation) e.stopPropegation();
		clearTimeout(ajax_select_timer_id);
	} else {
		return false;
	}

	// Up and down arrows
	switch (e.keyCode) {
		// Up
		case 38:
		case 63232:
			if(results.current) {
				results.current.className = results.current.className.replace(' resultBoxSelected','');
			}
			if(results.current && results.current.previousSibling && results.current.previousSibling.childNodes.length > 2) {
				results.current = results.current.previousSibling;
			} else {
				var elements = results.childNodes;
				results.current = elements[elements.length - 1];
			}
			results.current.className += ' resultBoxSelected';
		break;

		// Down
		case 40:
		case 63233:
			if(results.current) {
				results.current.className = results.current.className.replace(' resultBoxSelected','');
			}
			if(results.current && results.current.nextSibling && results.current.nextSibling.childNodes.length > 2) {
				results.current = results.current.nextSibling;
			} else {
				var elements = results.childNodes;
				for (var i = 0; i < elements.length; i++) {
					elem = elements.item(i);
					if (elem.value) {
						results.current = elem;
						break; // We have found the first selection
					}
				}
			}
			results.current.className += ' resultBoxSelected';
		break;
			
	// Tab: Select current element 
		case 9:
			var elem;
			if(results.current && results.current.value) {
				elem = results.current;
			} else {
				var elements = document.getElementById(base_id + '[results]').childNodes;
				for (var i = 0; i < elements.length; i++) {
					elem = elements.item(i);
					if (elem.value) {
						break; // We have found the first selection
					}
				}
			}
			if (!elem) return;
			var event;
			if(document.createEvent && document.dispatchEvent) {
				// Most
				event = document.createEvent('MouseEvents');
				event.initEvent('click', true, true);
				elem.dispatchEvent(event);
			} else {
				// IE
				event = document.createEventObject();
				elem.fireEvent('onclick', event);
			}
		break;
	}
}

/**
 * Set a timeout to prevent user from flooding the server with requests as
 * they type.  Waits to see if the user is still typing before sending the 
 * request.  Adjust ajax_select_timeout to change how long to wait (in ms).
 */
function timer_change(e, value) {
	if ( ajax_select_timer_id != 0) {
		clearTimeout(ajax_select_timer_id);
	}
	if(!e) {
		var e = cloneObject(window.event);
	} else {
		var e = cloneObject(e);
	}
	ajax_select_event = e;
	ajax_select_timer_id = setTimeout(
		function() {
			change(e, value);
		}, 
		ajax_select_timeout
	);
}

function change(e, value) {
	if(!e) {
		var e = window.event;
	}
	
	if(e.target) {
		var target = e.target;
	} else if (ajax_select_event) {
		var e = ajax_select_event;
		ajax_select_event = null;
		if(e.target) {
			var target = e.target;
		} else if (e.srcElement) {
			var target = e.srcElement;
		} 
	} else if (e.srcElement) {
		var target = e.srcElement;
	} 
	if(target) {
		if (target.nodeType == 3) { // defeat Safari bug
			target = target.parentNode;
		} 
		var id = target.id;
		var value = target.value;
	} else if (typeof(e) == 'string' ) {
		var id = e;
		if(value) {
			var value = value;
		} else {
			var value = e.value;
		}
		var set_id = id.substr(0, id.lastIndexOf('['));
	} else {
		alert('Error in events');
		return;
	}

	var base_id = id.substr(0, id.lastIndexOf('['));

	if(document.getElementById(base_id + '[results]')) {
		set_id = base_id + '[results]'; 

		/*
		 * We check for Tab, Up and Down
		 */
		var interested = false;
		var keycode = '';
		for(var i = 0; i < no_search_keys.length; i++) {
			if(e.which) {
				keycode = e.which;
			} else if(e && e.keyCode) {
				keycode = e.keyCode;
			}
			if(keycode == no_search_keys[i]) {
				interested = true;
				break;
			}
		}
		if (interested && document.getElementById(set_id).style.display == 'block') {
			clearTimeout(ajax_select_timer_id);
			return; // Results are shown, allow keys to move the selection cursor
		}

	} else {
		set_id = base_id + '[search]';
	}

	var query = document.getElementById(set_id).options;
	if(document.getElementById(base_id + '[filter]')) {
		query.filter = document.getElementById(base_id + '[filter]').value;
	}

	// Hide selectboxes for IE
	if(document.all) {
		var selects = document.getElementsByTagName('select');
		for(var i = 0; i < selects.length; i++) {
			selects[i].style.visibility = 'hidden';
		}
	}
	xajax_doXMLHTTP(current_app + ".ajax_select_widget.ajax_search.etemplate", id, value, set_id, query, document.getElementById('etemplate_exec_id').value);
}


/**
*  Deep copy an object
*  Used because IE thinks its a good idea to use a global var for events
*/
function cloneObject(obj) {
	var clone = {};
	for(var i in obj) {
		clone[i] = obj[i];
	}
	return clone;
}

/* Remove options from a results box
*  @param id - The id of the select
*/
function remove_ajax_results(id) {
	if(document.getElementById(id)) {
		var element = document.getElementById(id);
		if (element.tagName == 'DIV') {
			element.innerHTML = '';
		}
	}
}

/* Add an option to a result box
*  @param id - The id of the result box
*  @param key - The key of the option
*  @param value - The value of the option
*  @param row - The html for the row to display
*/
function add_ajax_result(id, key, value, row) {
	var resultbox = document.getElementById(id);
	if(resultbox) {
		if (resultbox.tagName == 'DIV') {
			var base_id = resultbox.id.substr(0, resultbox.id.lastIndexOf('['));
			var search_id = base_id + '[search]';
			var value_id = base_id + '[value]';

			resultbox.style.display = 'block';
			var result = document.createElement('div');

			result.className = (resultbox.childNodes.length % 2) ? 'row_on' : 'row_off';
			if(key) {
				result.value = new Object();
				result.value.key = key;
				result.value.value = value;
				result.value.search_id = search_id;
				result.value.value_id = value_id;

				result.innerHTML = row;

				// when they click, add that item to the value hidden textbox
				if(result.addEventListener) {
					result.addEventListener('click', select_result, true);
				} else {
					result.onclick = select_result;
				}
			} else {
				result.innerHTML += row + "<br />";
			}
			resultbox.appendChild(result);
		}
	}
}

function select_result(e) {
	// when they click, add that item to the value textbox & call onchange()
	if(!e) {
		var e = window.event;
	}
	if(e.target) {
		var target = e.target;
	} else if (e.srcElement) {
		var target = e.srcElement;
	}
	while(!target.value && target != document) {
		target = target.parentNode;
	}

	var value = document.getElementById(target.value.value_id);
	var search = document.getElementById(target.value.search_id);
	if(value) {
		value.value = target.value.key;
	}
	if(search) {
		var string = target.value.value;
		string = string.replace(/&amp;/g, '&');
		string = string.replace(/&lt;/g, '<');
		string = string.replace(/&gt;/g, '>');

		search.value = string;
		var event;
		if(document.createEvent) {
			// Most
			event = document.createEvent('HTMLEvents');
			event.initEvent('change', true, true);
			return value.dispatchEvent(event);
		} else {
			// IE
			event = document.createEventObject();
			return value.fireEvent('onchange', event);
		}
	}
}

function hideBox(e) {
	if(!e) {
		var e = window.event;
	}
	if(e.target) {
		var target = e.target;
	} else if (e.srcElement) {
		var target = e.srcElement;
	}
	if(target) {
		if (target.nodeType == 3) { // defeat Safari bug
			target = target.parentNode;
		} 
	}
	var set_id = target.id.substr(0, target.id.lastIndexOf('[')) + '[results]';
	setTimeout("document.getElementById('" + set_id + "').style.display = 'none'", 200);
	var selects = document.getElementsByTagName('select');

	// Un-hide select boxes for IE
	if(document.all) {
		for(var i = 0; i < selects.length; i++) {
			selects[i].style.visibility = 'visible';
		}
	}
}