﻿if (typeof(bsn) == "undefined")
	_b = bsn = {};



// /////////////////////////////////////////////////////////////
// DOM PROTOTYPE ______________________________________________
// /////////////////////////////////////////////////////////////

if (typeof(_b.DOM) == "undefined")
	_b.DOM = {};

// create element
_b.DOM.cE = function ( type, attr, cont, html )
{
	var ne = document.createElement( type );
	if (!ne)
		return 0;
		
	for (var a in attr)
		ne[a] = attr[a];
	
	var t = typeof(cont);
	
	if (t == "string" && !html)
		ne.appendChild( document.createTextNode(cont) );
	else if (t == "string" && html)
		ne.innerHTML = cont;
	else if (t == "object")
		ne.appendChild( cont );

	return ne;
};

// get element 
_b.DOM.gE = function ( e )
{
	var t=typeof(e);
	if (t == "undefined")
		return 0;
	else if (t == "string")
	{
		var re = document.getElementById( e );
		if (!re)
			return 0;
		else if (typeof(re.appendChild) != "undefined" )
			return re;
		else
			return 0;
	}
	else if (typeof(e.appendChild) != "undefined")
		return e;
	else
		return 0;
};

// remove element 
_b.DOM.remE = function ( ele )
{
    var e = null;
    if ( typeof(ele) == "string" ) {
	    e = this.gE(ele);
    } else {
        e = ele;
    }
    
    if (!e)
		return 0;
	else if (e.parentNode.removeChild(e))
		return true;
	else
		return 0;
};

// get position 
_b.DOM.getPos = function ( e )
{
	var e = this.gE(e);
	var obj = e;

	var curleft = 0;
	var curtop = 0;
	
	if (obj.offsetParent)
	{
		do {
		    curleft += obj.offsetLeft;
			curtop += obj.offsetTop;
		} while (obj = obj.offsetParent);
	} else {
	    if (obj.x) {
		    curleft += obj.x;
        } if (obj.y) {
            curtop += obj.y;
        }
	}
	
	return {x:curleft, y:curtop};
};

_b.DOM.clickInside =  function(e, obj) {
    e?evt=e:evt=event;
    CSE=evt.target?evt.target:evt.srcElement;
    if (obj) {
	    if (!this.isChild(CSE,obj)){
		    return false;
        }
    }
    return true;
};

_b.DOM.EvtObj = function(e){
    if(!e)
        e=window.event;
    return e;
}; 

_b.DOM.evtTgt =  function(e)
{
    var el;
    if(e.target)
        el=e.target;
    else if(e.srcElement)
        el=e.srcElement;
    if(el.nodeType==3)
        el=el.parentNode; // defeat Safari bug
    return el;
}; 

_b.DOM.isChild = function(s,d) {
    while(s) {
	    if (s==d) 
		    return true;
	    s=s.parentNode;
    }
    return false;
};

_b.DOM.cancelBubble = function(e) {
    if (!e) 
        var e = window.event;
	
	e.cancelBubble = true;
	
	if (e.stopPropagation) 
	    e.stopPropagation();
};

_b.DOM.getSelectedRadio = function(buttonGroup) {
   // returns the array number of the selected radio button or -1 if no button is selected
   if (buttonGroup[0]) { // if the button group is an array (one button is not an array)
      for (var i=0; i<buttonGroup.length; i++) {
         if (buttonGroup[i].checked) {
            return i;
         }
      }
   } else {
      if (buttonGroup.checked) { return 0; } // if the one button is checked, return zero
   }
   return -1;   // if we get to this point, no radio button is selected
};

_b.DOM.getSelectedRadioValue = function(buttonGroup) {
   // returns the value of the selected radio button or "" if no button is selected
   var i = _b.DOM.getSelectedRadio(buttonGroup);
   if (i == -1) {
      return "";
   } else {
      if (buttonGroup[i]) { // Make sure the button group is an array (not just one button)
         return buttonGroup[i].value;
      } else { // The button group is just the one button, and it is checked
         return buttonGroup.value;
      }
   }
};

_b.DOM.getSelectedCheckbox = function(buttonGroup) {
   // Go through all the check boxes. return an array of all the ones
   // that are selected (their position numbers). if no boxes were checked,
   // returned array will be empty (length will be zero)
   var retArr = new Array();
   var lastElement = 0;
   if (buttonGroup[0]) { // if the button group is an array (one check box is not an array)
      for (var i=0; i<buttonGroup.length; i++) {
         if (buttonGroup[i].checked) {
            retArr.length = lastElement;
            retArr[lastElement] = i;
            lastElement++;
         }
      }
   } else { // There is only one check box (it's not an array)
      if (buttonGroup.checked) { // if the one check box is checked
         retArr.length = lastElement;
         retArr[lastElement] = 0; // return zero as the only array value
      }
   }
   return retArr;
};

_b.DOM.getSelectedCheckboxValue = function(buttonGroup) {
   // return an array of values selected in the check box group. if no boxes
   // were checked, returned array will be empty (length will be zero)
   var retArr = new Array(); // set up empty array for the return values
   var selectedItems = _b.DOM.getSelectedCheckbox(buttonGroup);
   if (selectedItems.length != 0) { // if there was something selected
      retArr.length = selectedItems.length;
      for (var i=0; i<selectedItems.length; i++) {
         if (buttonGroup[selectedItems[i]]) { // Make sure it's an array
            retArr[i] = buttonGroup[selectedItems[i]].value;
         } else { // It's not an array (there's just one check box and it's selected)
            retArr[i] = buttonGroup.value;// return that value
         }
      }
   }
   return retArr;
};



function mrOautocomplete (Id, args) {
    var dom = _b.DOM;

    this.Id = Id;
    this.args = args;
    this.textField = null;
    this.input = null;
    this.divId = null;
    this.divObj = null;
    this.waitDivId = null;
    this.waitDivObj = null;
    this.iFrameId = null;
    this.iFrameObj = null;
    this.IATAhidden = null;
    this.listObj = null;
    this.objArr = null;
    this.timeoutId = null;
    this.pos = new Array(2);
    this.XSL = null;
    this.iHigh = null;

    this.parameters = new Array();
    this.slaves = new Array();
    
    this.lastX = null; // last event mouse pos to ignore mouseover on scroll (no mousemove)
    this.lastY = null;
    
    if (this.IATAhidden == null) {
        this.IATAhidden = document.getElementById("AC_IATA_" + this.Id);
        if (this.IATAhidden == null) {
            this.IATAhidden = dom.cE("input", {id:"AC_IATA_"+this.Id, name:"AC_IATA_"+this.Id, type:"hidden"});
            document.getElementsByTagName("form")[0].appendChild(this.IATAhidden);
        }
    }
    
    this.textField = document.getElementById(Id); //the textfield we tie the autocomplete to
    this.textField.setAttribute("autocomplete", "off");
    
    var pointer = this;
    this.textField.onkeypress 	= function(ev){ return pointer.onKeyPress(ev); };
    this.textField.onkeyup 		= function(ev){ return pointer.onKeyUp(ev); };
    this.textField.onclick 		= function(ev){
                                                pointer.getSuggestions(pointer.textField.value);
                                                _b.DOM.cancelBubble(ev);
                                            };
    this.textField.onblur = function(ev) { return pointer.looseFocus(ev); };

    // parameters object
    this.oP = this.args ? this.args : {};
    // defaults	
    var k, def = {
        //WebService:WebService.proc()  MUST BE DEFINED
        //XSLFileName:"bla.xsl"         MUST BE DEFINED
        timeout: 2500,
        delay: 650,
        minchars: 3,
        maxresults: 25,
        offsety: 0,
        height: 250,
        width: 0,
        idleText: "",
        cssLiMouseOver: "ACmouseOver",
        cssProcess: "ACProcessingTextbox",
        processStyle: "textbox"         //textbox || popup
    };

    for (k in def) {
        if (typeof (this.oP[k]) != typeof (def[k])) {
            this.oP[k] = def[k];
        }
    }

    if (this.textField.value == "") {
        this.textField.value = this.oP['idleText'];
    }
};

mrOautocomplete.prototype.looseFocus = function(ev) {
    //alert("d");
    if (this.textField.value == "") {
        this.textField.value = this.oP['idleText'];
    }
};


//Id: the id of the textbox to hook to
//args:
// Webservice:  function to call on the webservice
// Timeout:         timeout before the autocomplete disappears
// Delay:           delay before pollying the webservice for results
// Minchars:        min chars before pollying the webservice for results
// Offsety:         offset between textbo and dropdown
mrOautocomplete.prototype.init = function() {
    var dom = _b.DOM;
    this.divId = "AC_div_" + this.Id;
    this.divObj = dom.cE("div", { id: this.divId, display: "none" });
    this.waitDivId = "AC_waitDiv_" + this.Id;
    this.waitDivObj = dom.cE("div", { id: this.waitDivId, display: "none" });
    this.iFrameId = "AC_iFrame_" + this.Id;
    this.iFrameObj = null;

    var Obj = this.divObj;
    var pointer = this;
    var clickFunction = function(ev) {
        if (!dom.clickInside(ev, Obj)) {
            pointer.HidePopupDiv(pointer.divObj, pointer.iFrameObj);
            pointer.iFrameObj = null;
        }
    };
    document.all ? document.attachEvent("onclick", clickFunction) : document.addEventListener("click", clickFunction, false);

    document.getElementsByTagName("body")[0].appendChild(this.divObj);
    document.getElementsByTagName("body")[0].appendChild(this.waitDivObj);

    this.objArr = new Array(); //array with information about <li>s
    this.input = "";

    // OUTPUT NECESSARY HTML / JAVASCRIPT
    //document.write();
};

mrOautocomplete.prototype.registerParameter = function (name, value, template) {
    var param = new Array(3);
    param[0] = name;
    param[1] = value; 
    param[2] = template,
    this.parameters[this.parameters.length] = param;
};

mrOautocomplete.prototype.liObj = function(id, ele, title, cssClass) {
    this.id = id;
    this.ele = ele;
    this.title = title;
    this.cssClass = cssClass;
};

mrOautocomplete.prototype.onKeyPress = function(ev) {
    var key = (window.event) ? window.event.keyCode : ev.keyCode;
    var bubble = true;

    var RETURN = 13;
    var TAB = 9;
    var ESC = 27;

    switch(key)
    {
	    case RETURN:
		    this.setHighlightedValue();
		    bubble = false;
		    break;

        case TAB:
		    this.setHighlightedValue();
		    bubble = false;
		    break;
        
	    case ESC:
		    this.clearSuggestions();
		    break;
    }
    
    return bubble;
};

mrOautocomplete.prototype.onKeyUp = function(ev) {
    var key = (window.event) ? window.event.keyCode : ev.keyCode;
    var bubble = true;

    var ARRUP = 38;
    var ARRDN = 40;
	var RETURN = 13;
    var TAB = 9;
    var ESC = 27;

    switch(key)
    {
        case RETURN:
		    break;

        case TAB:
		    break;
        
	    case ESC:
		    break;
		    
	    case ARRUP:
		    this.changeHighlight(key, ev);
		    bubble = false;
		    break;

	    case ARRDN:
		    this.changeHighlight(key, ev);
		    bubble = false;
		    break;
        
	    default:
		    this.getSuggestions(this.textField.value);
    }
    
    return bubble;
};

mrOautocomplete.prototype.getSuggestions = function(input) {
    if ( this.textField.value == this.oP['idleText']) {
        this.textField.value = "";
    }

    if (this.divObj == null) {
        this.init();
    }

    if (input != this.sInp) {
        this.IATAhidden.value = "";
        this.updateSlaves();
    }
    this.sInp = input;

    // input length is less than the min required to trigger a request
    // do nothing
    if (input.length < this.oP.minchars) {
        this.objArr = new Array();
        this.nInpC = input.length;
        this.clearSuggestions();
        return 0;
    }

    var ol = this.nInpC; // old length
    this.nInpC = input.length ? input.length : 0;

    var pointer = this;
    clearTimeout(this.timeoutId);
    this.timeoutId = setTimeout(function() { pointer.doAjaxRequest(input) }, this.oP.delay);

    return false;
};

mrOautocomplete.prototype.doAjaxRequest = function(input) {
    // check that saved input is still the value of the field
    if (input != this.textField.value)
        return false;

    this.divObj.style.display = "none";
    this.waitDivObj.style.display = "none";

    if (this.oP.processStyle == 'textbox') {
        this.textField.className = this.oP.cssProcess;
    } else {
        this.waitDivObj.innerHTML = '&nbsp;';
        this.waitDivObj.className = this.oP.cssProcess;
        var pos = _b.DOM.getPos(this.textField);
        this.ShowPopupDiv(this.waitDivObj, pos.x, (pos.y + this.textField.offsetHeight + this.oP.offsety));
    }

    var pointer = this;
    var onSuccessFunc = function(req) { pointer.setSuggestions(req) };

    //this.oP.WebService(input, this.oP.maxresults, onSuccessFunc, mrOwebservice.OnTimeOut, mrOwebservice.OnError);

    var ary = this.getParameterArray();
    this.oP.WebService(input, ary, onSuccessFunc, mrOwebservice.OnTimeOut, mrOwebservice.OnError);
};

mrOautocomplete.prototype.getParameterArray = function() {
    var retAr = new Array(this.parameters.length);
    for (var i = 0; i < this.parameters.length; i++) {
        if (this.parameters[i][2] == "radio") {
            var value = _b.DOM.getSelectedRadioValue(document.getElementsByName(this.parameters[i][1]));
            retAr[i] = this.parameters[i][0] + ":" + value;
        } else if (this.parameters[i][2] == "textbox") {
            var value = document.getElementById(this.parameters[i][1]).value;
            retAr[i] = this.parameters[i][0] + ":" + value;
        } else {
            retAr[i] = this.parameters[i][0] + ":" + this.parameters[i][1];
        }
    }
    //alert(" this.parameters: \n" + this.parameters + "\n\n\nretAr: \n" + retAr);
    return retAr;
};

mrOautocomplete.prototype.setSuggestions = function (result) {
    var myXML;
    myXML = mrOxml.getXMLObj(result, 2);
    this.createList(myXML);
};

mrOautocomplete.prototype.createList = function(myXML) {
    var pointer = this;
    
    if ( this.oP.processStyle == 'textbox' ) {
        this.textField.className = '';
    } else {
        this.HidePopupDiv(this.waitDivObj, this.iFrameObj);
        this.iFrameObj = null;
        this.waitDivObj.innerHTML = '&nbsp;';
        this.waitDivObj.className = '';
    }

    this.killTimeout();

    if ( this.XSL == null ) {
        this.XSL = mrOxml.getXMLObj(this.oP.XSLFileName, 1);
    }
    
    // recreate the div to force ie to redraw the ul
    _b.DOM.remE(this.divObj);
    this.divObj = _b.DOM.cE("div", {id:this.divId, display:"none"});
    document.getElementsByTagName("body")[0].appendChild(this.divObj); 

    var pos = _b.DOM.getPos(this.textField);
	this.divObj.className = "ACcontainerDiv";
    this.divObj.onmouseover 	= function(){ pointer.killTimeout() };
//    this.divObj.onmouseout 		= function(){ pointer.resetTimeout() };
    
    this.divObj.style.overflow = "auto";
    
    this.divObj.style.height = this.oP.height + 'px';
    this.divObj.style.width = (this.oP.width != 0) ? (this.oP.width + 'px') : (this.textField.offsetWidth + 'px');
    
    this.divObj.innerHTML = "";
    this.divObj.style.display = 'none';
    mrOxml.applyXSL(myXML, this.XSL, this.divObj);
    
    this.ShowPopupDiv(this.divObj, pos.x, ( pos.y + this.textField.offsetHeight + this.oP.offsety ) );

    this.iHigh = 0;
    
    // remove list after an interval
//    this.timeoutId = setTimeout(function () { pointer.clearSuggestions() }, this.oP.timeout);
    
    this.listObj = _b.DOM.gE("as_ul");
    this.listObj.id = "as_ul_"+this.Id;
    
//    this.iFrameObj.style.width = this.listObj.offsetWidth + 'px';
//    this.iFrameObj.style.height = this.listObj.offsetHeight + 'px';
    
    var listArr = this.listObj.getElementsByTagName("li");
    this.objArr = new Array(listArr.length);

    for (var i = 0; i < listArr.length; i++) {    
        var ele = listArr[i];
        
        var val = listArr[i].title.trim();
        this.objArr[i] = new this.liObj(listArr[i].id, ele, val, listArr[i].className);
 
        listArr[i].title = val;
        listArr[i].name = i+1;

	    listArr[i].onclick = function () { pointer.setHighlightedValue(); return false; };
	    listArr[i].onmouseover = function (ev) {
                                        var x = (ev||event).clientX;
                                        var y = (ev||event).clientY;
	                                    if ( ( pointer.lastX && pointer.lastY  ) &&
	                                         ( pointer.lastX != x || pointer.lastY != y ) ) {
     	                                    pointer.setHighlight(this.name, ev);
                                        } else {
                                            if (x != null) {
                                                pointer.lastX = x;
    	                                        pointer.lastY = y;
                                            }
                                        }
	                                };
    }

};

mrOautocomplete.prototype.IsIE =  function () {
    return ( navigator.appName=="Microsoft Internet Explorer" );
};

mrOautocomplete.prototype.HidePopupDiv =  function (divObj, iFrameObj) {
    divObj.style.display = 'none';
    if (iFrameObj != null) {
        document.body.removeChild(iFrameObj);
    }
};

mrOautocomplete.prototype.ShowPopupDiv =  function (divObj, left, top) {
    divObj.style.left = left + "px";
    divObj.style.top = top + "px";
    
    /*
    if (!this.IsIE()) {
        //Just display the div
        divObj.style.display = '';
        return;
    }*/
    
    if (this.iFrameObj) {
        this.HidePopupDiv(divObj, this.iFrameObj);
        this.iFrameObj = null;
    }

    this.iFrameObj = document.createElement("IFRAME");
    this.iFrameObj.setAttribute("src", "");
    //Match IFrame position with divPopup
    this.iFrameObj.style.position = "absolute";
    this.iFrameObj.style.left = left + 'px';
    this.iFrameObj.style.top = top + 'px';

    this.iFrameObj.style.border = '0px';
    this.iFrameObj.style.filter = 'alpha(opacity=0)';

    document.body.appendChild(this.iFrameObj);
    divObj.style.zIndex = this.iFrameObj.style.zIndex+1;
    divObj.style.display = '';
    
    this.iFrameObj.style.width = divObj.offsetWidth + 'px';
    this.iFrameObj.style.height = divObj.offsetHeight + 'px';
};

mrOautocomplete.prototype.killTimeout = function() {
    clearTimeout(this.timeoutId);
};

mrOautocomplete.prototype.resetTimeout = function() {
    clearTimeout(this.timeoutId);
    var pointer = this;
    this.timeoutId = setTimeout(function () { pointer.clearSuggestions() }, this.oP.timeout);
};

mrOautocomplete.prototype.changeHighlight =  function(key, ev)
{
    var pointer = mrOautocomplete;
    var list = this.listObj;
    if (!list)
	    return false;
	
    var n;
    if (key == 40) { //down
	    n = this.iHigh + 1;
    } else if (key == 38) { //up
	    n = this.iHigh - 1;
    }

    if (n > list.childNodes.length)
	    n = list.childNodes.length;
    if (n < 1)
	    n = 1;

//scroll that besh
    var top = list.childNodes[n-1].offsetTop;
    var bottom = (top + list.childNodes[n-1].offsetHeight); 
    var divBottom = this.divObj.scrollTop + this.divObj.offsetHeight;

    if (this.divObj.scrollTop > top) {
        this.divObj.scrollTop = top;
    } else if ( bottom > divBottom ) {
        this.divObj.scrollTop = bottom-this.divObj.offsetHeight;
    }
    
    this.setHighlight(n, ev);
};

mrOautocomplete.prototype.setHighlight = function(n, ev)
{    
    var list = this.listObj;
    if (!list)
	    return false;
    if (this.iHigh > 0)
	    this.clearHighlight();
	
    this.iHigh = Number(n);
    
    list.childNodes[this.iHigh-1].className = this.oP.cssLiMouseOver;
    this.killTimeout();

    var x = (ev||event).clientX;
    var y = (ev||event).clientY;
    this.lastX = x;
    this.lastY = y;
};

mrOautocomplete.prototype.clearHighlight = function()
{
    var list = this.listObj;
    if (!list)
	    return false;
	
    if (this.iHigh > 0)
    {
        list.childNodes[this.iHigh-1].className = this.objArr[this.iHigh-1].cssClass;
	    this.iHigh = 0;
    }
};

mrOautocomplete.prototype.setHighlightedValue = function ()
{
    if (this.iHigh)
    {
		this.input = this.textField.value = this.objArr[ this.iHigh-1 ].title;
		
        this.IATAhidden.value = document.getElementById(this.IATAhidden.id).value = this.objArr[ this.iHigh-1 ].id;
        this.updateSlaves();
        this.clearSuggestions();
	    this.iHigh = 0;

	    this.textField.blur();
    }
};

mrOautocomplete.prototype.clearSuggestions = function() {
    this.killTimeout();
    //this.sInp = "";
    this.HidePopupDiv(this.divObj, this.iFrameObj);
    this.iFrameObj = null;
};

mrOautocomplete.prototype.registerSlave = function(pointer) {
    this.slaves[this.slaves.length] = pointer;
};

mrOautocomplete.prototype.updateSlaves = function() {
    if (this.slaves.length > 0) {
        for(var i in this.slaves) {
            //alert( this.slaves[i].IATAhidden.id+"\n"+this.IATAhidden.id );
            this.slaves[i].textField.value = this.textField.value;
            this.slaves[i].IATAhidden.value = this.IATAhidden.value;
        }
    }
};
