/*
 * selector - The selector for grids
 * Copyright (C) 2010 Ipportunities
 *
 * This is the integration file for JavaScript.
 *
 * It defines the selector class that can be used to create selector
 * instances in a HTML page in the client side.
 *
 * requires jquery
 * see http://www.jquery.com
 *
 */

// array to keep track of the selectors
var selectors = new Array();


var userAgent = navigator.userAgent.toLowerCase();
var browser = {version:(userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[])[1], safari:/webkit/.test(userAgent), opera:/opera/.test(userAgent), msie:/msie/.test(userAgent)&&!/opera/.test(userAgent), mozilla:/mozilla/.test(userAgent)&&!/(compatible|webkit)/.test(userAgent)};



/*
* creates an input assistant and binds it to the parent input element
*/
function bindSelector(inputId, parentId, hiddenId, containerId, infoFile, fileParameters, callBack, defaultId, options_object)
{
	var create_new_selector = true;
	if(selectors[inputId])
	{
		//alert(selectors[inputId].getVar("ParentId"));
		if( (selectors[inputId].getVar("ParentId") == parentId) && (selectors[inputId].getVar("HiddenId") == hiddenId) && (selectors[inputId].getVar("ContainerId") == containerId) && (selectors[inputId].getVar("InfoFile") == infoFile) && (selectors[inputId].getVar("FileParameters") == fileParameters) && (selectors[inputId].getVar("CallBack") == callBack) )
		{
			
			create_new_selector = false;
		}
	}
	
	if(create_new_selector)
	{
		var selector = new inputSelector(inputId, parentId, hiddenId, containerId, infoFile, fileParameters, callBack, defaultId, options_object);

		if(! (document.getElementById(inputId) && document.getElementById(parentId) && document.getElementById(hiddenId) && document.getElementById(containerId)) )
		{
			return false;
		}
		
		var el = document.getElementById(inputId);
		var type = "keyup";
		var handle = _updateSelector;
		
		if(el.addEventListener)
		{
			el.addEventListener(type, handle, false);
		} else if(el.attachEvent)
		{
			el.attachEvent("on" + type, handle);
		}
		
		selectors[inputId] = selector;
	} else
	{
		selectors[inputId].setVar("DefaultId", defaultId);
		for(var variable in options_object)
		{
			selectors[inputId].setVar(variable, options_object[variable]);
		}

		selectors[inputId].resetOptions();
		selectors[inputId].open();
	}
}

/*
* keyup handler of the parent element
*/
function _updateSelector(event)
{
	//alert(event);
	var el = event.target ? event.target : event.srcElement;
	
	var value = new String(el.value).replace(/^\s*/g, "");
	//alert('-'+value+'-');
	
	if(selectors[el.getAttribute("id")])
	{
		var selector = selectors[el.getAttribute("id")];
		
		// escape
		if(27 == event.keyCode)
		{
			selector.close();
			return false;
		}

		if(!selector.isOpen())
		{
			selector.open();
		}

		if(selector.isOpen())
		{
			selector.proceedEvent(event, value);
		}
	}
}


/*
* close all assistants if escape key is pressed
*/
var el = document;
var type = "keyup";
var handle = _escapeHandlerSelector;

if(el.addEventListener)
{
	el.addEventListener(type, handle, false);
} else if(el.attachEvent)
{
	el.attachEvent("on" + type, handle);
}

/*
* handles escape key to close the open selectors
*/
function _escapeHandlerSelector(event)
{
	if(27 == event.keyCode)
	{
		closeSelectors();
	}
}

/*
* closes all selectors
*/
function closeSelectors()
{
	for(var ia in selectors)
	{
		selectors[ia].close();
	}
}

/*
* reloads all selectors
*/
function reloadSelectors()
{
	for(var ia in selectors)
	{
		selectors[ia].getInfo();
	}
}


/*
* kill all selectors
*/
function killSelectors()
{
	for(var ia in selectors)
	{
		selectors[ia] = null;
	}
	selectors = new Array();
}


/*
* selects value from the list
*/
function _s_selectValue(input_id, parent_id, hidden_id, id, value)
{
	document.getElementById(hidden_id).value = id;
	//alert(value + " " + new String(value).replace(/&quot;/g, '"'));
	document.getElementById(parent_id).value = new String(value).replace(/&quot;/g, '"').replace(/#34;/g, '"').replace(/#39;/g, "'");
	document.getElementById(parent_id).focus();

	if(selectors)
	{
		if(selectors[input_id])
		{
			selectors[input_id].close();
		}
	}
}

/*
* sets the start page
*/
function _s_setPageStart(input_id, parent_id, start)
{
	if(selectors)
	{
		if(selectors[input_id])
		{
			selectors[input_id].setPageStart(start);
		}
	}
}


// selector Class
var inputSelector = function(inputId, parentId, hiddenId, containerId, infoFile, fileParameters, callBack, defaultId, options_object)
{
	// Properties
	this.ie = browser.msie;
	
	this.InputId = inputId;
	this.ParentId = parentId;
	this.HiddenId = hiddenId;
	this.ContainerId = containerId;

	this.InfoFile = infoFile;
	this.FileParameters = fileParameters;
	this.CallBack = callBack || "";
		
	this.AllOptions = new Array();
	this.CurrentOptions = new Array();
	this.Options = new Array();
	this.DefaultId = defaultId || "";
	this.PageStart = 0;
	this.MaxOptions = 25;
	this.MaxNumberOfHeaders = 7;
	
	this.idPrefix = "_is_" + parentId + "_";
	
	this.ClassTDheader = "selector_header";
	this.ClassTD = "selector";
	this.ClassTDhover = "selector_hover";
	this.ClassTDdefault = "selector_default";
	this.ClassTDmatch = "selector_match";
	
	this.Separator = "=";
	
	this.RowHeight = 1;
	
	this.Top = 0;
	this.Left = 0;
	
	this.BorderWidth = 1;

	this.SelectedIndex = null;
	
	this.isShown = false;

	this.Width = 150;
	for(var variable in options_object)
	{
		this.setVar(variable, options_object[variable]);
	}
	
	this.Height = (this.RowHeight + (this.ie ? 5 : 0)) * (this.MaxOptions + 1);

	if(document.getElementById(this.ContainerId))
	{
		var container = document.getElementById(this.ContainerId);
		
		container.className = "selector_container";
		
		container.style.width = this.Width;
		//container.style.height = this.Height;
		
		container.style.borderWidth = this.BorderWidth;
	}

	
	this.Header = "<table border='0' cellspacing='0' cellpadding='0' style='width:" + this.Width + "px;'><tr><td id='" + this.idPrefix + "header' class='" + this.ClassTDheader + "' style='height:" + this.RowHeight + "px;' align='center'><br/></td></tr>";
	
	this.Footer = "</table>";
	this.Line = "<tr><td id='" + this.idPrefix + "%index%' class='%class_name%' onmouseover='this.className=\"" + this.ClassTDhover + "\"' onmouseout='this.className=\"%class_name%\"' onclick='_s_selectValue(\"" + this.InputId + "\", \"" + this.ParentId + "\", \"" + this.HiddenId + "\", \"%id%\", \"%option%\");' style='height:" + this.RowHeight + "px;'>%option_show%</td></tr>";

	this.getInfo();
	this.open();
}


/**
* resets all the values
*/
inputSelector.prototype.resetOptions = function()
{
	this.CurrentOptions = new Array();
	
	for(var index in this.AllOptions)
	{
		this.CurrentOptions[index] = trim(this.AllOptions[index]);
		var id = this.getID(this.AllOptions[index]);
		
		if(("" != this.DefaultId) && (this.DefaultId == id) )
		{
			if(this.CurrentOptions.length > this.MaxOptions)
			{
				this.PageStart = Math.floor(index / this.MaxOptions) * this.MaxOptions;
			}
		}
	}
	this.getOptionsPage();
}


/**
* sets the start index
*/
inputSelector.prototype.setPageStart = function(page_start)
{
	this.PageStart = page_start;
	this.getOptionsPage();
	document.getElementById(this.InputId).focus();
}


/**
* sets the vars values
*/
inputSelector.prototype.setVar = function(variable, value)
{
	if(("MaxOptions" == variable) || ("MaxNumberOfHeaders" == variable) || ("PageStart" == variable))
	{
		var check_string = 'this.' + variable + ' = ' + value + ';';
	} else
	{
		var check_string = 'this.' + variable + ' = "' + value + '";';
	}
	eval(check_string);
}

/**
* gets the var value
*/
inputSelector.prototype.getVar = function(variable)
{
	var check_string = 'var value = this.' + variable + ';';
	eval(check_string);
	
	return value;
}


/**
* opens the assistant
*/
inputSelector.prototype.open = function()
{
	document.getElementById(this.InputId).value = "";

	if(document.getElementById(this.ContainerId))
	{
		this.isShown = true;
		document.getElementById(this.ContainerId).style.display = "block";
	}
}
/**
* closes the assistant
*/
inputSelector.prototype.close = function()
{
	this.isShown = false;
	
	if(document.getElementById(this.ContainerId))
	{
		var container = document.getElementById(this.ContainerId);
		container.innerHTML = "";
		container.style.display = "none";
		
		this.SelectedIndex = null;
	}
	
	if(this.CallBack)
	{
		eval(this.CallBack + "()");
	}
}

/**
* checks if the assistant is open
*/
inputSelector.prototype.isOpen = function()
{
	return this.isShown;
}


/**
* reads the info file
*/
inputSelector.prototype.readInfoFile = function()
{
	var data;
	var query = "";

	$.ajax({
		type: "GET",
		url: this.InfoFile + "?nd=" + new Date().getTime() + this.FileParameters,
		data: query,
		async: false,
		timeout: 5000,
		success: function(reply)
			{
				//alert(reply);
				data = reply;
			},
		error: function(e)
			{
				data = "";
				//alert(e);
			}
	});
	return data;
}

/**
* gets list of all available options
*/
inputSelector.prototype.getInfo = function()
{
	var reply = this.readInfoFile();
	if("" == reply)
	{
		var options = new Array();
	} else
	{
		var options = new String(trim(reply)).split("\n");
	}

	this.AllOptions = options;
	this.resetOptions();
}


/**
* sets options array to work with
*/
inputSelector.prototype.getOptionsPage = function()
{
	this.Options = new Array();
	for(var io = this.PageStart; ((io < (this.PageStart + this.MaxOptions)) && (io < this.CurrentOptions.length)) ; io ++)
	{
		if(trim(this.CurrentOptions[io]))
		{
			this.Options[io] = trim(this.CurrentOptions[io]);
		}
	}
	this.setOptions();
}

/**
* sets options array to work with
*/
inputSelector.prototype.setOptions = function()
{
	if(document.getElementById(this.ContainerId))
	{
		var container = document.getElementById(this.ContainerId);
		
		var input = trim(document.getElementById(this.InputId).value);
		
		var content = this.Header;
		for(var index in this.Options)
		{
			var id = this.getID(this.Options[index]);
			var option = this.getOption(this.Options[index]);
			
			if("" == input)
			{
				var option_show = option;
			} else
			{
				if(1 == new String(input).length)
				{
					if(input.toLowerCase() == String(option).substring(0, 1).toLowerCase())
					{
						var option_show = "<span class='" + this.ClassTDmatch + "'>" + input + "</span>" + new String(option).substring(1);
					} else
					{
						var option_show = option;
					}
				} else
				{
					var re = new RegExp(input, "gi");
					var option_show = new String(option).replace(re, "<span class='" + this.ClassTDmatch + "'>" + input + "</span>");
				}
			}
			
			if(id == this.DefaultId)
			{
				var class_name = this.ClassTDdefault;
			} else
			{
				var class_name = this.ClassTD;
			}

			option = new String(option).replace(/&quot;/g, "#34;").replace(/'/g, "#39;");
			var line = new String(this.Line).replace(/%option%/g, option).replace(/%option_show%/g, option_show).replace(/%index%/g, index).replace(/%id%/g, id).replace(/%class_name%/g, class_name);
			//var x = new String("'\"");
			//alert(line);
			content += line;
		}
		content += this.Footer;
		
		container.innerHTML = content;
		
		this.setHeader();
	}
}


/**
* sets header navigation to scroll pages
*/
inputSelector.prototype.setHeader = function()
{
	var header_id = this.idPrefix + "header";
	if(this.CurrentOptions.length <= this.MaxOptions)
	{
		if(0 == this.CurrentOptions.length)
		{
			var header_content = "niets gevonden";
		} else
		{
			var header_content = "1-" + this.CurrentOptions.length;
		}
	} else
	{
		var header_content = "";
		var number_of_headers = Math.ceil(this.CurrentOptions.length / this.MaxOptions);
		var last_header = (number_of_headers - 1) * this.MaxOptions;
		var points_position_distance = Math.floor(this.MaxNumberOfHeaders / 2) - 1;
		
		for(var np = 0; np < this.CurrentOptions.length; np += this.MaxOptions)
		{
			var end = Math.min((np + this.MaxOptions), (this.CurrentOptions.length - 0));
			if(np == this.PageStart)
			{
				header_content += " " + (np + 1) + "-" + end;
			} else
			{
				var current_distance = Math.abs(np - this.PageStart) / this.MaxOptions;
				if( (number_of_headers < this.MaxNumberOfHeaders) || (0 == np) || (last_header == np) || (current_distance < points_position_distance) )
				{
					header_content += " <a href=\"javascript:void(0)\" onclick=\"_s_setPageStart('" + this.InputId + "', '" + this.ParentId + "', " + np + ")\">" + (np + 1) + "-" + end + "</a>";
				} else if( ((np - (points_position_distance * this.MaxOptions)) == this.PageStart) || ((np + (points_position_distance * this.MaxOptions)) == this.PageStart) )
				{
					header_content += " ...";
				}
			}
		}
	}
	document.getElementById(header_id).innerHTML = header_content;
}


/**
* processes a key event
*/
inputSelector.prototype.proceedEvent = function(event, value)
{
	// PageDown
	if(34 == event.keyCode)
	{
		this.left();
		return true;
	}
	// PageUp
	if(33 == event.keyCode)
	{
		this.right();
		return true;
	}
	
	// arrow down
	if(40 == event.keyCode)
	{
		this.next();
		return true;
	}
	// arrow up
	if(38 == event.keyCode)
	{
		this.prev();
		return true;
	}
	
	// enter
	if(13 == event.keyCode)
	{
		this.setValue();
		return true;
	}
	
	this.suggest(value);
}


/**
* switches to the previous page selection
*/
inputSelector.prototype.left = function()
{
	var new_start = parseInt(this.PageStart - this.MaxOptions);
	if(this.PageStart > 0)
	{
		this.setPageStart(new_start);
	}
}

/**
* switches to the next page selection
*/
inputSelector.prototype.right = function()
{
	var new_start = parseInt(this.PageStart + this.MaxOptions);
	if(this.PageStart <= (this.CurrentOptions.length - this.MaxOptions))
	{
		this.setPageStart(new_start);
	}
}


/**
* switches to the next option
*/
inputSelector.prototype.next = function()
{
	if(0 == this.Options.length)
	{
		return false;
	}
	
	if(this.MaxOptions < this.CurrentOptions.length)
	{
		if(0 == this.Options.length % this.MaxOptions)
		{
			var lastIndex = this.PageStart + this.MaxOptions - 1;
		} else
		{
			var lastIndex = this.PageStart + (this.Options.length % this.MaxOptions) - 1;
		}
	} else
	{
		var lastIndex = this.CurrentOptions.length - 1;
	}

	if((null == this.SelectedIndex) || (this.SelectedIndex < this.PageStart) || (this.SelectedIndex > lastIndex))
	{
		this.SelectedIndex = this.PageStart;
	} else
	{
		var id = this.getID(this.Options[this.SelectedIndex]);
		if(this.DefaultId == id)
		{
			document.getElementById(this.idPrefix + this.SelectedIndex).className = this.ClassTDdefault;
		} else
		{
			document.getElementById(this.idPrefix + this.SelectedIndex).className = this.ClassTD;
		}
		
		this.SelectedIndex ++;
		
		if(this.SelectedIndex > lastIndex)
		{
			this.SelectedIndex = this.PageStart;
		}
	}
	
	this.selectOption(this.SelectedIndex);
}

/**
* switches to the previous option
*/
inputSelector.prototype.prev = function()
{
	if(0 == this.Options.length)
	{
		return false;
	}
	
	if(this.MaxOptions < this.CurrentOptions.length)
	{
		if(0 == this.Options.length % this.MaxOptions)
		{
			var lastIndex = this.PageStart + this.MaxOptions - 1;
		} else
		{
			var lastIndex = this.PageStart + (this.Options.length % this.MaxOptions) - 1;
		}
	} else
	{
		var lastIndex = this.CurrentOptions.length - 1;
	}

	if((null == this.SelectedIndex) || (this.SelectedIndex < this.PageStart) || (this.SelectedIndex > lastIndex))
	{
		this.SelectedIndex = lastIndex;
	} else
	{
		var id = this.getID(this.Options[this.SelectedIndex]);
		if(this.DefaultId == id)
		{
			document.getElementById(this.idPrefix + this.SelectedIndex).className = this.ClassTDdefault;
		} else
		{
			document.getElementById(this.idPrefix + this.SelectedIndex).className = this.ClassTD;
		}
		
		this.SelectedIndex --;
		
		if(this.SelectedIndex < this.PageStart)
		{
			this.SelectedIndex = lastIndex;
		}
	}
	
	this.selectOption(this.SelectedIndex);
}

/**
* selects the given option based on index
*/
inputSelector.prototype.selectOption = function(index)
{
	if(!document.getElementById(this.idPrefix + index))
	{
		return false;
	}
	
	document.getElementById(this.idPrefix + index).className = this.ClassTDhover;
	document.getElementById(this.idPrefix + index).focus();
	
	if(document.getElementById(this.ContainerId))
	{
		var container = document.getElementById(this.ContainerId);
		container.scrollTop = (this.SelectedIndex - 1) * this.RowHeight;
	}
	document.getElementById(this.InputId).focus();
}



/**
* trims the selection based on input
*/
inputSelector.prototype.suggest = function(input)
{
	this.PageStart = 0;
	this.CurrentOptions = new Array();
	var count = 0;

	input = trim(input);
	
	for(var io = 0; io < this.AllOptions.length; io ++)
	{
		var option = this.getOption(this.AllOptions[io]);

		if("" == input) 
		{
			this.CurrentOptions[count++] = this.AllOptions[io];
		} else
		{
		
			if(1 == new String(input).length)
			{
				if(input.toLowerCase() == new String(option).substring(0, new String(input).length).toLowerCase())
				{
					this.CurrentOptions[count++] = this.AllOptions[io];
				}
			} else
			{
				if(-1 != new String(option).toLowerCase().indexOf(input.toLowerCase()))
				{
					this.CurrentOptions[count++] = this.AllOptions[io];
				}
			}
		}
	}

	this.getOptionsPage();
}


/**
* sets value of the parent input field
*/
inputSelector.prototype.setValue = function()
{
	if(document.getElementById(this.HiddenId) && document.getElementById(this.ParentId))
	{
		var parent = document.getElementById(this.ParentId);
		var hidden = document.getElementById(this.HiddenId);
		if(null != this.SelectedIndex)
		{
			parent.value = new String(this.getOption(this.Options[this.SelectedIndex])).replace(/&quot;/g, '"');
			hidden.value = this.getID(this.Options[this.SelectedIndex]);
		}
		
		this.close();
		parent.focus();
	}
}


/**
* gets id based on option data
*/
inputSelector.prototype.getID = function(option_data)
{
	var index_separator = new String(option_data).indexOf(this.Separator);
	if(-1 == index_separator)
	{
		return "";
	} else
	{
		return trim(new String(option_data).substring(0, index_separator));
	}
}

/**
* gets option name based on option data
*/
inputSelector.prototype.getOption = function(option_data)
{
	var index_separator = new String(option_data).indexOf(this.Separator);
	if(-1 == index_separator)
	{
		return this.Options[this.SelectedIndex];
	} else
	{
		return trim(new String(option_data).substring(index_separator + 1));
	}
}
