﻿//-------------------------------- Common WebRouteFinder js lib ---------------------------------------//

// DOM

function $() {
var els = new Array();
for (var i = 0; i < arguments.length; i++) {
var el = arguments[i];
if (typeof el == 'string')
el = document.getElementById(el);
if (arguments.length == 1)
return el;
els.push(el);
}
return els;
}

// sets the caret position to l in the object
function setCaret(obj,l){
	obj.focus();
	if (obj.setSelectionRange){
		obj.setSelectionRange(l,l);
	}else if(obj.createTextRange){
		m = obj.createTextRange();		
		m.moveStart('character',l);
		m.collapse();
		m.select();
	}
}

// total top offset
function posTop(el){	
	var r = 0;
	while(el){
		r += el.offsetTop;
		el = el.offsetParent;
	}
	return r;
}

// total left offset
function posLeft(el){	
	var r = 0;
	while(el){
		r += el.offsetLeft;
		el = el.offsetParent;
	}
	return r;
}


// Events

function addEvent(obj,event_name,func_name){
if (obj.attachEvent){ obj.attachEvent("on"+event_name, func_name); }
else if(obj.addEventListener){ obj.addEventListener(event_name,func_name,false); }
else{ obj["on"+event_name] = func_name; }
}

function removeEvent(obj,event_name,func_name){
if (obj.detachEvent){
obj.detachEvent("on"+event_name,func_name);
}else if(obj.removeEventListener){
obj.removeEventListener(event_name,func_name,true);
}else{
obj["on"+event_name] = null;
}
}

// Stop an event from bubbling up the event DOM
function stopEvent(e){
	if (!e) var e = window.event;
	if (e.stopPropagation){ e.stopPropagation(); e.preventDefault(); }
	else { e.cancelBubble = true; e.returnValue = false; }
	return false;
}

// AJAX

function GetXmlHttpObject()
{
var x=null;
try { x=new XMLHttpRequest(); }
catch (e)
{        
try { x=new ActiveXObject("Msxml2.XMLHTTP"); }
catch (e) 
{ 
try { x=new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { }
}
}
return x;
}

function DownloadURL(url, onload)
{
var x=GetXmlHttpObject();
if (x==null) { alert ("Your browser does not support AJAX!"); return; }  
x.onreadystatechange=function() { 
	try { if (x.readyState==4 && x.status==200) onload(x); }
	catch(e) {}
} ;
x.open("GET",url,true);
x.send(null);
return x;
}

//-------------- Autocomplete --------------//

function autocomplete(_el,_fn,_opts){

this.IsVisible = false;        

var _self = this;
var _keywords = [ ];        
var _pos = -1;
var _count = 0;
var _ff = false; // forced focus (after mouse click)
var _kk = false; // key captured
var _to; // timeout event
var _cache = [];

if (!_opts) _opts = new Object();
if (!_opts.timeout) _opts.timeout = 500;
if (!_opts.minlength) _opts.minlength = 1;
if (!_opts.cache) _opts.cache = true;

//addEvent(_el, "focus", _generate);
addEvent(_el, "blur", _hide);
addEvent(_el, "keydown", _onkeydown);
addEvent(_el, "keypress", _onkeypress);

function _generate(){
if (!_ff) 
{
	if (_to) { clearTimeout(_to); _to = null; }
	if (_el.value.length >= _opts.minlength)
	{
		if (_opts.cache)	
		{
			var kw = _getcached(_el.value);
			if (kw) { _show(_el.value, kw); return; }
		}	
		_to = setTimeout(function() { _to = null; _fn(_el.value, _show); }, _opts.timeout);
	}	
	else
		_hide();
}
_ff = false;
}

function _getcached(s)
{
	var i;
	for (i = 0; i < _cache.length; i++)	 
		if (_cache[i][0] == s) 
			return _cache[i][1];	
	return null;
}

function _show(s,kw){
if (_opts.cache && s) _cache.push([s, kw]);

_hide();
_keywords = kw;
_pos = -1;
_count = _keywords.length;
if (_count == 0) return;

var a = document.createElement('table');
a.cellSpacing='0px';
a.style.position='absolute';
var elpos = { x:posLeft(_el), y:posTop(_el), width:_el.offsetWidth, height:_el.offsetHeight };
//var elpos = WebForm_GetElementPosition(_el);
a.style.top = (elpos.y + elpos.height) + "px";
a.style.left = elpos.x + "px";
a.style.width = elpos.width + "px";
a.className='ac_table';
a.id = 'ac_table';
document.body.appendChild(a);

var i;		 
for (i=0;i<_keywords.length;i++)
{
	var r = a.insertRow(-1);
	r.className='ac_tr'
	r.id = 'ac_tr'+(i);			    
	var c = r.insertCell(-1);
	c.className='ac_td'
	c.innerHTML = _keywords[i];
	c.id = 'ac_td'+(i);
	c.setAttribute('pos',i);
	c.style.cursor = 'default';			
	c.onmouseover = _onCellMouseOver;
	c.onmousedown = _onCellClick;		
}
_self.IsVisible = true;
}

function _hide() {
if ($('ac_table')){ document.body.removeChild($('ac_table')); } 
_self.IsVisible = false;
}

function _markRow(newPos){
try {
if (_pos >= 0 && _pos < _count) $('ac_tr'+_pos).className='ac_tr';
_pos = newPos;
$('ac_tr'+_pos).className='ac_trh';
}catch(e) { alert(_pos); }
}

function _selectRow(pos){			
_el.value = _keywords[pos];
_hide();
}	   	    

function _onkeydown(e){  
if (!e) e = event;
var a = e.keyCode;		 
_kk = false;
switch (a){
	case 38:
		if (!_self.IsVisible) return true;
		if (_pos > 0) _markRow(_pos-1);
		_kk = true;
		return false;
		break;
	case 40:
		if (!_self.IsVisible) return true;
		if (_pos < _count - 1) _markRow(_pos+1);
		_kk = true;
		return false;
		break;
	case 13: case 9:
		if (!_self.IsVisible) return true;
		if (_pos >= 0) { _selectRow(_pos); _kk = true; return false; }	
		break;	
	case 35: case 36: case 37: case 39: case 16: case 17: case 18: 
		break;
	case 27: // escape
		if (_self.IsVisible) { _hide(); _kk  = true; return false; }
		break;
	default:
		setTimeout(function() { _generate(); },50);		
		break;
}
}

function _onkeypress(e){
	if (_kk) stopEvent(e);
	var ret = !_kk;
	_kk=false;
	return ret;
}

function _onCellMouseOver(evt){
var pos=Number(this.getAttribute('pos'));
_markRow(pos);
}	   

function _onCellClick(e){
var pos=Number(this.getAttribute('pos'));
_selectRow(pos);
//_ff = true;
_el.blur();
setTimeout(function(){setCaret(_el,_el.value.length);}, 50); // hack for IE to keep textbox focused
}


}

//-------------------------- Webservice autocomplete -----------------//

// _url e.g.: /buswebservice.asmx/GetSimilarStopNames?prefixText={0}&count={1}
function wsautocomplete(_el, _url, _opts)
{	
	if (!_opts) _opts = new Object();
	if (!_opts.minlength) _opts.minlength = 2;
	if (!_opts.maxhints) _opts.maxhints = 10;
	
	var _ac, _acxml, _acs, _acfn;		
	_ac = new autocomplete(_el, _showHint, _opts);

	function _showHint(str,callback)
	{
	if (_acxml) { _acxml.abort(); _acxml = null; }
	_acs = str;
	_acfn = callback;
	var url = _url.replace("{0}", str).replace("{1}", _opts.maxhints);	
	_acxml = DownloadURL(url, _onHintLoad);
	}

	function _onHintLoad(xmlHttp)
	{
	_acxml = null;
	var xmlDoc=xmlHttp.responseXML.documentElement;
	var x=xmlDoc.getElementsByTagName('string');
	var kw = [];
	for (i=0;i<x.length;i++)
	{        				
		kw.push(x[i].firstChild.nodeValue);
	}
	_acfn(_acs, kw);
	}
}


var MUtils = new Object();  // Object to put static methods on

// Events

MUtils.AttachEvent = function(obj,event_name,func_name){
if (obj.attachEvent){ obj.attachEvent("on"+event_name, func_name); }
else if(obj.addEventListener){ obj.addEventListener(event_name,func_name,false); }
else{ obj["on"+event_name] = func_name; }
}

// Adds script to the body of document, after which it's loaded asynchronously
MUtils.LoadScript = function (id, url) {
	if ($(id)) return;	
	var s = document.createElement('script');
	s.id = id;
	s.type = 'text/javascript';
	s.src = url;
	document.body.appendChild(s);
}