/*
 * © 2008 ROBO Design
 * http://www.robodesign.ro
 */

// show some luv to IE
function myAddEvent(elem, ev, func, cap)
{
	if(!elem || !ev || !func)
		return false;

	if(!cap)
		cap = false;

	if(typeof (elem) == 'string')
		elem = document.getElementById(elem);

	if(!elem)
		return false;

	if(elem.addEventListener)
		elem.addEventListener(ev, func, cap);
	else if(elem.attachEvent)
		elem.attachEvent('on'+ev, func);
	else
		return false;

	return true;
}

// This script contains work arounds for IE 6 and IE 7 bugs. You've been warned!
// Most of them are conditioned with the RD_IE_ver variable.

var wf2_datalist = function (input)
{
	if(!input || !input.tagName)
		return false;

	var _me = this;
	_me.input = input;

	_me.load_data = function (url)
	{
		if(!url)
			return false;

		_me.xmlhttp = false;

		if(window.ActiveXObject)
		{
			try
			{
				_me.xmlhttp = new ActiveXObject('Msxml2.XMLHTTP');
			} catch (err)
			{
				try
				{
					_me.xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
				} catch (err)
				{
					return false;
				}
			}
		} else if(window.XMLHttpRequest)
		{
			try
			{
				_me.xmlhttp = new XMLHttpRequest();
			} catch (err)
			{
				return false;
			}
		} else
			return false;

		if(!_me.xmlhttp)
			return false;

		_me.xmlhttp.onreadystatechange = _me.xmlhttp_ready;

		try
		{
			_me.xmlhttp.open('GET', url);
			_me.xmlhttp.send('');
		} catch (err)
		{
			return false;
		}

		return true;
	};

	_me.xmlhttp_ready = function ()
	{
		if(_me.xmlhttp.readyState != 4)
			return false;

		if(_me.xmlhttp.status != 200)
			return false;

		// get the parsed datalist XML
		var xml_dom = _me.xmlhttp.responseXML;

		if(!xml_dom || !xml_dom.documentElement || !xml_dom.documentElement.tagName || xml_dom.documentElement.tagName != 'select' || !xml_dom.documentElement.childNodes || xml_dom.documentElement.childNodes.length < 1)
			return false;

		var i, elem, n, mem_id, mem = {},
			datalist_type = xml_dom.documentElement.getAttribute('type');

		// remove the current datalist if the type is not incremental
		if(datalist_type != 'incremental')
		{
			while(_me.datalist.hasChildNodes())
			{
				_me.datalist.removeChild(_me.datalist.firstChild);
			}
		}

		var i, y, n2, elem, elem2, n = xml_dom.documentElement.childNodes.length;
		for(i = 0; i < n; i++)
		{
			elem = xml_dom.documentElement.childNodes[i];
			if(window.RD_IE_ver && elem.nodeType != 1)
				continue;

			if(document.importNode)
				elem2 = document.importNode(elem, true);
			else
			{
				elem2 = document.createElement(elem.nodeName);
				n2 = elem.attributes.length;
				for(y = 0; y < n2; y++)
				{
					elem2.setAttribute(elem.attributes[y].name, elem.attributes[y].value);
				}
			}

			_me.datalist.appendChild(elem2);
		}

		// memory cleanup
		xml_dom = null;
		_me.xml_http = null;
		delete xml_dom;
		delete _me.xml_http;

		var options = _me.datalist.getElementsByTagName('option');

		if(!options || options.length < 1)
			return false;

		var options_arr = [];

		// specific for robodesign.ro
		var val_type, pos, showValue, shortValue, val, option, mem_label, mem_id, rem_options = [],
			re_external_link = /^[a-z0-9]+:\/\/[a-z0-9]/i;
		n = options.length;
		n2 = 0;

		for(i = 0; i < n; i++)
		{
			option = options[i];
			if(!option.value)
			{
				if(option.textContent)
					val = option.textContent;
				else if(option.innerText)
					val = option.innerText;
				else
					continue;

				option.value = val;
			} else
				val = option.value;

			if(option.getAttribute('label'))
				mem_label = option.getAttribute('label');
			else
				mem_label = '';

			mem_id = val + mem_label;
			mem_id = mem_id.toLowerCase();
			if(mem[mem_id])
			{
				rem_options[n2++] = option;
				continue;
			}

			mem[mem_id] = true;
			options_arr.push(option);

			// specific to robodesign.ro
			if(_me.list_id != 'search-data')
				continue;

			if(val.charAt(0) == '/')
				val_type = 'internal-link';
			else if(re_external_link.test(val))
				val_type = 'external-link';
			else
				val_type = false;

			showValue = val.replace(/([\/\-_])/g, ' $1 ').replace(/^[\s\/]+/, '').replace(/[\s\/]+$/, '');
			shortValue = false;

			if(val_type == 'internal-link')
			{
				pos = showValue.lastIndexOf('/');
				if(pos != -1 && pos != showValue.indexOf('/'))
				{
					pos = showValue.lastIndexOf('/', pos-1);
					shortValue = '../ ' + showValue.substr(pos+2);
				}

				showValue = '/ ' + showValue;
			} else if(val_type == 'external-link')
			{
				showValue = showValue.replace(/^https?\s*:\s*\/\s*\/\s*(www\.)?/i,'').replace(/\?.+$/,'?...');
			}

			option.wf2_showValue = showValue;
			if(shortValue)
				option.wf2_shortValue = shortValue;
		}

		for(i = 0; i < n2; i++)
		{
			elem = rem_options[i].parentNode;
			elem.removeChild(rem_options[i]);
		}

		if(options_arr.length < 1)
			return false;

		options_arr.sort(_me.options_sorter);
		n = options_arr.length;

		_me.options = {};
		for(i = 0; i < n; i++)
		{
			_me.options[i] = options_arr[i];
		}
		_me.options.length = n;

		_me.datalist.removeAttribute('data');
		_me.datalist.wf2_ready = true;
		_me.datalist.wf2_processing = false;

		rem_options = null;
		mem = null;
		delete mem;
		delete rem_options;

		return _me.prepare_input();
	};

	_me.options_sorter = function (a, b)
	{
		var arr = [a.value, b.value];
		arr.sort();
		if(arr[0] == a.value)
			return -1;
		else if(arr[0] == b.value)
			return 1;
		else
			return 0;
	};

	_me.prepare_input = function ()
	{
		if(!_me.datalist || !_me.input || !_me.event_keyup)
			return false;

		myAddEvent(_me.input, 'keyup', _me.event_keyup, false);

		if(window.RD_IE_ver)
			myAddEvent(_me.input, 'keyup', _me.event_keypress, false);
		else
			myAddEvent(_me.input, 'keypress', _me.event_keypress, false);

		myAddEvent(_me.input, 'focus', _me.event_focus, false);
		myAddEvent(_me.input, 'blur', _me.event_blur, false);

		_me.input.setAttribute('autocomplete', 'off');
		_me.input.wf2_oldValue = false;

		if(_me.input.form)
			myAddEvent(_me.input.form, 'submit', _me.event_submit, false);

		return true;
	};

	_me.options_prepare = function ()
	{
		if(_me.options)
			return true;

		var options = _me.datalist.getElementsByTagName('option');
		if(!options || options.length < 1)
			return false;

		var options_arr = [];
		var i, n = options.length;
		for(i = 0; i < n; i++)
		{
			options_arr.push(options[i]);
		}

		options_arr.sort(_me.options_sorter);

		_me.options = {};
		for(i = 0; i < n; i++)
		{
			_me.options[i] = options_arr[i];
		}
		_me.options.length = n;

		options_arr = null;
		options = null;
		delete options_arr;
		delete options;

		return true;
	};

	_me.search_prepare_str = function (str)
	{
		if(!str)
			return str;

		str = str.replace(/^\s+/, '').replace(/\s+$/, '');
		if(!str)
			return str;

		var match_url = /^([a-z0-9]+):\/\/(\1\.|www\.)?/i.exec(str);
		if(match_url && match_url[1])
		{
			var url = '^' + match_url[1] + ':\/\/';
			if(match_url[2])
				url += match_url[2];
		} else
			var url = '^https?:\/\/(www\.)?';

		var url2 = str.replace(new RegExp(url, 'i'), '');
		if(url2)
			url += wf2_datalist.regexp_escape(url2);

		url = new RegExp(url, 'i');

		var str_escaped = wf2_datalist.regexp_escape(str);

		var val = new RegExp('^' + str_escaped, 'i'),
			label = new RegExp('^(the\\s*)?' + str_escaped, 'i');

		// this is specific to robodesign.ro (sitemap)
		if(_me.list_id == 'search-data')
			val = new RegExp('^' + str_escaped + '[^\/]+\/?$', 'i');

		return {'str' : str, 'val' : val, 'label' : label, 'url' : url};
	};

	_me.search_full = function (str)
	{
		if(!str)
			return false;

		_me.searching = true;

		_me.results_clear();

		var i, label, option, n = _me.options.length, mem = {},
			re = _me.search_prepare_str(str);
		if(!re)
			return false;

		for(i = 0; i < n; i++)
		{
			option = _me.options[i];
			if(option.disabled || !option.value)
				continue;

			if(_me.input.value == option.value || mem[option.value])
				continue;

			label = option.getAttribute('label');
			if(re.val.test(option.value) || re.url.test(option.value) || re.label.test(label))
			{
				_me.results_add(re.str, i);
				mem[option.value] = true;
			}
		}

		_me.searching = false;
		mem = null;
		delete mem;

		_me.results_update();

		return true;
	};

	_me.search_incremental = function (str)
	{
		if(!str || !_me.results || !_me.input)
			return false;

		_me.searching = true;

		var i, y = 0, rem_nodes = [], option, n = _me.results.childNodes.length,
			re = _me.search_prepare_str(str);

		if(!re)
			return false;

		_me.results.scrollTop = 0;

		for(i = 0; i < n; i++)
		{
			option = _me.results.childNodes[i];
			if(option.wf2_value == _me.input.value || (!re.val.test(option.wf2_value) && !re.url.test(option.wf2_value) && !re.label.test(option.wf2_label)))
				rem_nodes[y++] = option;
		}

		if(_me.results.wf2_selected != -1)
		{
			option = _me.results.childNodes[_me.results.wf2_selected];
			if(option && option.className)
				option.className = '';

			_me.results.wf2_selected = -1;

			_me.input.wf2_suggestion_selected = false;
			if(_me.input.form)
				_me.input.form.wf2_suggestion_selected = false;
		}

		for(i = 0; i < y; i++)
			_me.results.removeChild(rem_nodes[i]);

		if(window.RD_IE_ver && window.RD_IE_ver == 6 && _me.results)
		{
			if(_me.results.offsetHeight > 300)
				_me.results.style.height = '300px';
			else
				_me.results.style.height = '';
		}

		_me.searching = false;
		_me.results_update();

		return true;
	};

	_me.results_add = function (str, i)
	{
		var option = _me.options[i];

		if(!option || !_me.results)
			return false;

		var showValue = false,
			val = option.value,
			label = option.getAttribute('label');

		if(str.charAt(0) == '/' && option.wf2_shortValue)
		{
			showValue = option.wf2_shortValue;
		} else
			showValue = option.wf2_showValue;

		if(!showValue)
			showValue = val;

		var val_elem = document.createElement('p'),
			label_elem = false;

		val_elem.className = 'wf2_suggestion_value';
		val_elem.appendChild(document.createTextNode(showValue));

		if(label)
		{
			label_elem = document.createElement('p');
			label_elem.className = 'wf2_suggestion_label';
			label_elem.appendChild(document.createTextNode(label));
		}

		var li = document.createElement('li');
		li.appendChild(val_elem);
		if(label_elem)
			li.appendChild(label_elem);

		li.wf2_value = val;
		if(label)
			li.wf2_label = label;

		myAddEvent(li, 'mousedown', _me.results_mousedown, false);
		_me.results.appendChild(li);

		return true;
	};

	_me.results_mousedown = function (ev)
	{
		if(!ev && window.event)
			var ev = window.event;

		var li = false;
		if(!ev)
			return;

		if(ev.target)
			li = ev.target;
		else if(ev.srcElement)
			li = ev.srcElement;

		if(!li)
			return;

		if(li.tagName.toLowerCase() != 'li')
			li = li.parentNode;

		if(!li || !li.wf2_value)
			return;

		_me.input.value = li.wf2_value;
		_me.results_clear();

		if(_me.input.focus)
			_me.input.focus();

		return;
	};

	_me.results_create = function ()
	{
		if(_me.results)
			return true;

		if(!_me.input)
			return false;

		var elem = document.createElement('ol');
		elem.className = 'wf2_suggestions';
		elem.style.display = 'none';

		_me.results = _me.input.parentNode.insertBefore(elem, _me.input.nextSibling);
		_me.results.wf2_selected = -1;

		_me.input.wf2_suggestion_selected = false;
		if(_me.input.form)
			_me.input.form.wf2_suggestion_selected = false;

		return true;
	};

	_me.results_show = function ()
	{
		if(!_me.results)
		{
			if(!_me.results_create())
				return false;

			if(!_me.results)
				return false;
		}

		if(!_me.input || !_me.results.style)
			return false;

		if(_me.results.style.display != 'block')
			_me.results.style.display = 'block';

		_me.input.wf2_suggestions_visible = true;
		if(_me.input.form)
			_me.input.form.wf2_suggestions_visible = true;

		if(window.RD_IE_ver && window.RD_IE_ver == 6 && _me.results.offsetHeight > 300)
			_me.results.style.height = '300px';

		return true;
	};

	_me.results_hide = function ()
	{
		if(!_me.input || !_me.results || !_me.results.style)
			return false;

		if(_me.results.style.display != 'none')
			_me.results.style.display = 'none';

		_me.input.wf2_suggestions_visible = false;
		if(_me.input.form)
			_me.input.form.wf2_suggestions_visible = false;

		if(window.RD_IE_ver && window.RD_IE_ver == 6)
			_me.results.style.height = '';

		return true;
	};

	_me.results_clear = function ()
	{
		if(!_me.results || !_me.input)
			return false;

		while(_me.results.hasChildNodes())
		{
			_me.results.removeChild(_me.results.firstChild);
		}

		_me.results.scrollTop = 0;
		_me.results.wf2_selected = -1;

		_me.input.wf2_suggestion_selected = false;
		if(_me.input.form)
			_me.input.form.wf2_suggestion_selected = false;

		return _me.results_hide();
	};

	_me.results_destroy = function ()
	{
		if(!_me.results)
			return true;

		if(!_me.input)
			return false;

		_me.input.parentNode.removeChild(_me.results);

		_me.input.wf2_suggestion_selected = false;
		_me.input.wf2_suggestions_visible = false;
		if(_me.input.form)
		{
			_me.input.form.wf2_suggestion_selected = false;
			_me.input.form.wf2_suggestions_visible = false;
		}

		return true;
	};

	_me.results_update = function (force_full)
	{
		if(!_me.results)
		{
			if(!_me.results_create())
				return false;
		} else if(_me.results.childNodes.length > 0)
			_me.results_show();
		else if(_me.results.childNodes.length == 0)
			_me.results_hide();

		if(_me.searching)
			return false;

		if(force_full && _me.results.childNodes.length < 1)
		{
			_me.input.wf2_oldValue = _me.input.value;
			return _me.search_full(_me.input.value);
		}

		if(_me.input.value == _me.input.wf2_oldValue)
			return false;

		var oldValue = _me.input.wf2_oldValue;
		_me.input.wf2_oldValue = _me.input.value;

		if(_me.input.value.length < 1 || !_me.input.value)
			return _me.results_clear();

		if(!oldValue)
			return _me.search_full(_me.input.value);

		if(_me.input.value.length <= oldValue.length)
			return _me.search_full(_me.input.value);

		var same_part = _me.input.value.substr(0, oldValue.length);
		if(same_part != oldValue)
			return _me.search_full(_me.input.value);

		// if the robodesign.ro (sitemap) regex is used, full searches need to be made (/mihai/blog doesn't have any result, but typing more adds results)
		if(_me.results.childNodes.length < 1 && _me.list_id == 'search-data')
			return _me.search_full(_me.input.value);
		else
			return _me.search_incremental(_me.input.value);
	};

	_me.event_submit = function (ev)
	{
		if(!ev && window.event)
			var ev = window.event;

		if(ev.target)
			var my_form = ev.target;
		else if(ev.srcElement)
			var my_form = ev.srcElement;
		else
			return;

		if(my_form.wf2_suggestion_selected)
		{
			if(ev.preventDefault)
				ev.preventDefault();

			return false;
		}
	};

	_me.event_focus = function (ev)
	{
		if(!_me.input)
			return;

		if(!_me.options)
			_me.options_prepare();

		_me.input.wf2_oldValue = _me.input.value;

	};

	_me.event_blur = function (ev)
	{
		_me.results_clear();
	};

	_me.event_keypress = function (ev)
	{
		if(!ev && window.event)
			var ev = window.event;

		if(!ev || !_me.results || _me.results.childNodes.length < 1)
			return;

		var key_code = false;
		if(ev.keyCode)
			key_code = ev.keyCode;
		else if(ev.which)
			key_code = ev.which;

		if(!key_code)
			return;

		var select_result = -10, elem;

		// Key DOWN: scroll the suggestions list
		if(!ev.shiftKey && key_code == 40)
			select_result = _me.results.wf2_selected+1;

		// Key UP: scroll the suggestions list
		if(!ev.shiftKey && key_code == 38)
			select_result = _me.results.wf2_selected-1;

		// Key PAGE UP: scroll the suggestions list
		if(!ev.shiftKey && key_code == 33)
			select_result = _me.results.wf2_selected-4;

		// Key PAGE DOWN: scroll the suggestions list
		if(!ev.shiftKey && key_code == 34)
			select_result = _me.results.wf2_selected+4;

		if(select_result == -10)
			return;

		if(ev.preventDefault)
			ev.preventDefault();

		// scroll the suggestions list
		if(_me.results.wf2_selected != -1)
		{
			elem = _me.results.childNodes[_me.results.wf2_selected];
			if(elem && elem.className)
				elem.className = null;
		}

		if(select_result >= _me.results.childNodes.length)
			select_result = 0;
		else if(select_result < 0)
			select_result = _me.results.childNodes.length-1;

		elem = _me.results.childNodes[select_result];
		if(elem)
			elem.className = 'wf2_suggestion_selected';

		_me.results.wf2_selected = select_result;

		_me.input.wf2_suggestion_selected = true;
		if(_me.input.form)
			_me.input.form.wf2_suggestion_selected = true;

		var calc1 = elem.offsetTop+elem.offsetHeight,
			calc2 = _me.results.scrollTop+_me.results.offsetHeight;

		if(calc1 >= calc2)
			_me.results.scrollTop += calc1-calc2+4;

		if(elem.offsetTop < _me.results.scrollTop)
			_me.results.scrollTop = elem.offsetTop+1;
	};

	_me.event_keyup = function (ev)
	{
		if(!ev && window.event)
			var ev = window.event;

		if(!ev)
			return;

		var key_code = false;
		if(ev.keyCode)
			key_code = ev.keyCode;
		else if(ev.which)
			key_code = ev.which;

		if(!key_code)
			return;

		// Key ENTER (13) and RIGHT ARROW (39): activate the selected suggestion
		if((key_code == 13 || key_code == 39) && _me.results && _me.results.wf2_selected != -1)
		{
			var elem = _me.results.childNodes[_me.results.wf2_selected];
			if(!elem || !elem.wf2_value)
				return;

			_me.input.value = elem.wf2_value;
			_me.results_clear();

			if(ev.preventDefault)
				ev.preventDefault();

			if(_me.input.focus)
				_me.input.focus();

			return;
		}

		// Key ESC (27), LEFT ARROW (37), and RIGHT ARROW (39): close the suggestions list
		if(key_code == 27 || key_code == 37 || key_code == 39)
		{
			_me.results_clear();

			if(ev.preventDefault)
				ev.preventDefault();

			return;
		}

		// Key UP (38) and DOWN (40)
		if(!ev.shiftKey && (key_code == 40 || key_code == 38))
		{
			if(ev.preventDefault)
				ev.preventDefault();

			_me.results_update(true);
			return;
		}

		_me.results_update();
	};

	_me.init = function ()
	{
		if(_me.input.tagName.toLowerCase() != 'input' || !input.type || input.type.toLowerCase() != 'text' || input.getAttribute('autocomplete') == 'off')
			return false;

		_me.list_id = _me.input.getAttribute('list');
		if(!_me.list_id)
			return false;

		_me.datalist = document.getElementById(_me.list_id);

		if(!_me.datalist || !_me.datalist.tagName || (_me.datalist.tagName.toLowerCase() != 'datalist' && _me.datalist.tagName.toLowerCase() != 'select'))
			return false;

		_me.processing = false;
		if(!_me.datalist.wf2_processing && !_me.datalist.wf2_ready)
		{
			_me.processing = true;
			_me.datalist.wf2_processing = true;

			_me.list_url = _me.datalist.getAttribute('data');
			if(_me.list_url)
				return _me.load_data(_me.list_url);
		}

		return _me.prepare_input();
	};

	if(_me.init())
		return _me;
	else
		return false;
};


wf2_datalist.regexp_escape = function (str)
{
	if(!str)
		return str;

	str = str.replace('\\', '\\\\').replace(/([\[\]^${}()|*+?\.])/g, '\\$1');

	return str;
};




myAddEvent(window, 'load',
function ()
{
	var page_path = document.location.toString();
	var pos = page_path.indexOf('/', 8);
	var site_address = page_path.substr(0, pos);
	page_path = page_path.substr(pos+1);
	pos = page_path.indexOf('?');
	if(pos != -1)
		page_path = page_path.substr(0, pos);
	pos = page_path.indexOf('#');
	if(pos != -1)
		page_path = page_path.substr(0, pos);

	page_path = page_path.replace(/\/+$/, '');
	if(page_path.length < 1 || /^index/i.test(page_path))
		page_path = 'index';

	var usearch_sdata = function ()
	{
		if(!sdata || !sdata.appendChild)
			return false;

		var new_value, new_title, new_text, new_elem, elem, elems = document.getElementsByTagName('a');
		var re_path = false, i, n = elems.length, mem_id, mem = {};
		var re_site = new RegExp('^' + wf2_datalist.regexp_escape(site_address), 'i');

		if(window.RD_IE_ver)
			re_path = new RegExp('^\/' + wf2_datalist.regexp_escape(page_path), 'i');

		var sdata_add = function (label, val)
		{
			label = label.replace(/^\s+/, '').replace(/\s+$/, '').replace(/\s+/, ' ');
			if(!label)
				return false;

			val = unescape(val);

			var mem_id = val + label;
			mem_id = mem_id.toLowerCase();
			if(mem[mem_id])
				return false;
			else
				mem[mem_id] = true;

			var option = document.createElement('option');
			option.value = val;
			option.setAttribute('label', label);

			sdata.appendChild(option);

			return true;
		};

		for(i = 0; i < n; i++)
		{
			elem = elems[i];

			if(elem.getAttribute('href'))
				new_value = elem.getAttribute('href');
			else if(elem.href)
				new_value = elem.href;
			else
				continue;

			if(elem.getAttribute('title'))
				new_title = elem.getAttribute('title');
			else
				new_title = '';

			if(elem.textContent)
				new_text = elem.textContent;
			else if(elem.innerText)
				new_text = elem.innerText;
			else
				new_text = '';

			new_value = new_value.replace(/^\s+/, '').replace(/\s+$/, '').replace(/\s+/, ' ').replace(re_site, '');

			if(re_path && new_value.indexOf('#') != -1)
			{
				if(new_value.charAt(0) == '/' && new_value.charAt(1) == '#')
					new_value = new_value.substr(1);
				else
					new_value = new_value.replace(re_path, '');
			}

			if(!new_value || new_value == '/' || new_value == '/index' || new_value == '#')
				continue;

			if(new_title)
				sdata_add(new_title, new_value);

			if(new_text)
				sdata_add(new_text, new_value);
		}

		mem = null;
		delete mem;

		return true;
	};

	var sdata = document.getElementById('search-data');

	if (window.RD_IE_ver)
	{
		if (sdata)
		{
			var tmp = sdata.parentNode;
			tmp.removeChild(sdata);
		}

		var sdata = document.createElement('datalist');
		sdata.setAttribute('id', 'search-data');
		sdata.setAttribute('data', '/search.xml');

		var tmp = document.getElementById('header');
		if (!tmp)
			return false;

		tmp.appendChild(sdata);
	}

	usearch_sdata();

	var inputs = document.getElementsByTagName('input');

	if(!inputs || inputs.length < 1)
		return false;

	var i, n = inputs.length;
	for(i = 0; i < n; i++)
	{
		new wf2_datalist(inputs[i]);
	}

}, false);

