/**
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
* 
* © Copyright 2005 Richard Heyes
*/





   

/* URL to the PHP page called for receiving suggestions for a keyword*/
//var getFunctionsUrl = "http://dev.dagbladet.no/blink/proxy/proxy.php?proxy_url=http://www.dagbladet.no/ajax/geo/suggestions.php&name="; 

var getFunctionsUrl = "http://blink.dagbladet.no/proxy/proxy2.php?proxy_url=http://www.dagbladet.no/ajax/geo/suggestions.php5[var]name="; 

//var getFunctionsUrl = "http://dev.dagbladet.no/blink/proxy/proxy.php?proxy_url=http://www.dagbladet.no/ajax/geo/suggestions.php&name="; 

var getTagsFunctionsUrl = "http://blink.dagbladet.no/gallery/?op=TagSuggest&name="; 

/* URL for seeing the results for the selected suggestion */
var phpHelpUrl="http://www.php.net/manual/en/function.";
/* the keyword for which an HTTP request has been initiated */ 
var httpRequestKeyword = "";
/* the last keyword for which suggests have been requested */
var userKeyword = "";
/* number of suggestions received as results for the keyword */
var suggestions = 0;
/* the maximum number of characters to be displayed for a suggestion */
var suggestionMaxLength = 35;
/* flag that indicates if the up or down arrow keys were pressed
   the last time a keyup event occurred  */
var isKeyUpDownPressed = false;
/* the last suggestion that has been used for autocompleting the keyword */
var autocompletedKeyword = "";
/* flag that indicates if there are results for the current requested keyword*/
var hasResults = false;
/* the identifier used to cancel the evaluation with the clearTimeout method. */
var timeoutId = -1;
/* the currently selected suggestion (by arrow keys or mouse)*/
var position = -1;
/* cache object containing the retrieved suggestions for different keywords */
var oCache = new Object();
/* the minimum and maximum position of the visible suggestions */
var minVisiblePosition = 0;
var maxVisiblePosition = 9;
// when set to true, display detailed error messages
var debugMode = true;
/* the XMLHttp object for communicating with the server */
var xmlHttpGetSuggestions = createXmlHttpRequestObject();
/* the onload event is handled by our init function */


/* params to send after search */
var params=new Array('long','lat','uni','name','name_nd','adm','country','adm1','description');

var tagParam = 'name'; 

// initialize the new array of functions' names
dataArray = new Array();
timer = new timeObject();	

var listname; 



    /**
    * Global vars
    */
    __AutoComplete = new Array();

    // Basic UA detection
    isIE = document.all ? true : false;
    isGecko = navigator.userAgent.toLowerCase().indexOf('gecko') != -1;
    isOpera = navigator.userAgent.toLowerCase().indexOf('opera') != -1;


    /**
    * Attachs the autocomplete object to a form element. Sets
    * onkeypress event on the form element.
    * 
    * @param string formElement Name of form element to attach to
    * @param array  data        Array of strings of which to use as the autocomplete data
    */
    
    function AutoComplete_Create (id, data, list)
    {
    	
    	listname = list; 
		

        __AutoComplete[id] = {'data':data,
								'data_nd':data,	
                              'isVisible':false,
                              'element':document.getElementById(id),
                              'dropdown':null,
			      				'long':null,
			      				'lat':null,
			      				'description':null,
			      				'uni':null,
			      				'hlat':null,	
			      				'name':null,
			      				'action':null,
                              'highlighted':null};
		
		
        __AutoComplete[id]['element'].setAttribute('autocomplete', 'off');
        __AutoComplete[id]['element'].onkeydown  = function(e) {return AutoComplete_KeyDown(this.getAttribute('id'), e);}
        __AutoComplete[id]['element'].onkeyup    = function(e) {return AutoComplete_KeyUp(this.getAttribute('id'), e);}
        //__AutoComplete[id]['element'].onkeypress = function(e) {if (!e) e = window.event; if (e.keyCode == 13) return false;}
        __AutoComplete[id]['element'].ondblclick = function() {AutoComplete_ShowDropdown(this.getAttribute('id'));}
        __AutoComplete[id]['element'].onclick    = function(e) {if (!e)  e = window.event; e.cancelBubble = true;  e.returnValue = false;}

        // Hides the dropdowns when document clicked
        var docClick = function()
        {
           for (id in __AutoComplete) {
               AutoComplete_HideDropdown(id);
           }
        }

        if (document.addEventListener) {
            document.addEventListener('click', docClick, false);
        } else if (document.attachEvent) {
            document.attachEvent('onclick', docClick, false);
        }


        // Max number of items shown at once
    /*    if (arguments[2] != null) {
            __AutoComplete[id]['maxitems'] = arguments[2];
            __AutoComplete[id]['firstItemShowing'] = 0;
            __AutoComplete[id]['lastItemShowing']  = arguments[2] - 1;
        }   */     

        // Max number of items shown at once

        if (arguments[2] != null) {
            __AutoComplete[id]['listname'] = arguments[2];
        }
        
        AutoComplete_CreateDropdown(id);
        
        // Prevent select dropdowns showing thru
        if (isIE) {
            __AutoComplete[id]['iframe'] = document.createElement('iframe');
            __AutoComplete[id]['iframe'].id = id +'_iframe'; 
            __AutoComplete[id]['iframe'].style.position = 'absolute'; 
            __AutoComplete[id]['iframe'].style.top = '0';
            __AutoComplete[id]['iframe'].style.left = '0';
            __AutoComplete[id]['iframe'].style.width = '0px'; 
            __AutoComplete[id]['iframe'].style.height = '0px';
            __AutoComplete[id]['iframe'].style.zIndex = '98';
            __AutoComplete[id]['iframe'].style.visibility = 'hidden';
            
            __AutoComplete[id]['element'].parentNode.insertBefore(__AutoComplete[id]['iframe'], __AutoComplete[id]['element']);
        }


            __AutoComplete[id]['hiddendiv'] = document.createElement('hiddendiv');
            __AutoComplete[id]['hiddendiv'].id = id +'_hiddendiv'; 
            __AutoComplete[id]['hiddendiv'].style.position = 'absolute'; 
            __AutoComplete[id]['hiddendiv'].style.top = '10';
            __AutoComplete[id]['hiddendiv'].style.left = '50';
            __AutoComplete[id]['hiddendiv'].style.width = '100px';
            __AutoComplete[id]['hiddendiv'].style.height = '50px';
            __AutoComplete[id]['hiddendiv'].style.zIndex = '98';	    

					  __AutoComplete[id]['hiddendiv'].innerHTML='';
					  
			if (id.toString().substring(0,7) == "geotags"){
					  
	            for(var i=0;i<params.length;i++){
	  	          __AutoComplete[id]['hiddendiv'].innerHTML=__AutoComplete[id]['hiddendiv'].innerHTML+'\n<input type=hidden name='+id+'_'+params[i]+' id='+id+'_'+params[i]+'>';;
	            }
            	
			}
			
			else {
				 __AutoComplete[id]['hiddendiv'].innerHTML=__AutoComplete[id]['hiddendiv'].innerHTML+'\n<input type=hidden name='+id+'_'+tagParam+' id='+id+'_'+tagParam+'>';;
			}
            
            __AutoComplete[id]['hiddendiv'].style.visibility = 'hidden';
            __AutoComplete[id]['element'].parentNode.insertBefore(__AutoComplete[id]['hiddendiv'], __AutoComplete[id]['element']);



    }


    /**
    * Creates the dropdown layer
    * 
    * @param string id The form elements id. Used to identify the correct dropdown.
    */
    function AutoComplete_CreateDropdown(id)
    {
    	
        var left  = AutoComplete_GetLeft(__AutoComplete[id]['element']);
        var top   = AutoComplete_GetTop(__AutoComplete[id]['element']) + __AutoComplete[id]['element'].offsetHeight;
        var width = __AutoComplete[id]['element'].offsetWidth;    	
        __AutoComplete[id]['dropdown'] = document.createElement('div');
        __AutoComplete[id]['dropdown'].className = 'autocomplete'; // Don't use setAttribute()
    
        __AutoComplete[id]['element'].parentNode.insertBefore(__AutoComplete[id]['dropdown'], __AutoComplete[id]['element']);
        
        // Position items 
        __AutoComplete[id]['dropdown'].style.left       = left + 'px';
        __AutoComplete[id]['dropdown'].style.top        = top + 'px';
        __AutoComplete[id]['dropdown'].style.width      = width + 'px';
        __AutoComplete[id]['dropdown'].style.zIndex     = '99';
        __AutoComplete[id]['dropdown'].style.visibility = 'hidden';
       
    }
    
    
    /**
    * Gets left coord of given element
    * 
    * @param object element The element to get the left coord for
    */
    function AutoComplete_GetLeft(element)
    {
        var curNode = element;
        var left    = 0;

        do {
            left += curNode.offsetLeft;
            curNode = curNode.offsetParent;

        } while(curNode.tagName.toLowerCase() != 'body');

        return left;
    }
    
    
    /**
    * Gets top coord of given element
    * 
    * @param object element The element to get the top coord for
    */
    function AutoComplete_GetTop(element)
    {
        var curNode = element;
        var top    = 0;

        do {
            top += curNode.offsetTop;
            curNode = curNode.offsetParent;

        } while(curNode.tagName.toLowerCase() != 'body');

        return top;
    }









// creates an XMLHttpRequest instance
function createXmlHttpRequestObject() 
{
  // will store the reference to the XMLHttpRequest object
  var xmlHttp;
  // this should work for all browsers except IE6 and older
  try
  {
    // try to create XMLHttpRequest object
    xmlHttp = new XMLHttpRequest();
  }
  catch(e)
  {
    // assume IE6 or older
    var XmlHttpVersions = new Array("MSXML2.XMLHTTP.6.0",
                                    "MSXML2.XMLHTTP.5.0",
                                    "MSXML2.XMLHTTP.4.0",
                                    "MSXML2.XMLHTTP.3.0",
                                    "MSXML2.XMLHTTP",
                                    "Microsoft.XMLHTTP");
    // try every prog id until one works
    for (var i=0; i<XmlHttpVersions.length && !xmlHttp; i++) 
    {
      try 
 
      { 
        // try to create XMLHttpRequest object
        xmlHttp = new ActiveXObject(XmlHttpVersions[i]);
      } 
      catch (e) {}
    }
  }
  // return the created object or display an error message
  if (!xmlHttp)
    alert("Error creating the XMLHttpRequest object.");
  else 
    return xmlHttp;
}





/* initiate HTTP request to retrieve suggestions for the current keyword */
function getSuggestions(id,keyword) 
{     

	keyword = escape(keyword.toLowerCase()); 
  /* continue if keyword isn't null and the last pressed key wasn't up or 
     down */

  //document.all['debug2'].innerText= //document.all['debug2'].innerText + '\n\nsøker ' + keyword;
	
  if(keyword != "" )
  {  	
    // check to see if the keyword is in the cache
    isInCache = checkCache(keyword);
    //document.all['debug2'].innerText= //document.all['debug2'].innerText + ' cache? ' + isInCache;
    // if keyword is in cache...
    if(isInCache == true) 
    {   
    	
      // retrieve the results from the cache          
      httpRequestKeyword=keyword;
      userKeyword=keyword;     
      // display the results in the cache
      displayResults(keyword, oCache[keyword]);                          
    }
    // if the keyword isn't in cache, make an HTTP request
    else    
    {   
    	 
      if(xmlHttpGetSuggestions)
      {       	

        try
        {
          /* if the XMLHttpRequest object isn't busy with a previous
             request... */
          
 
          if (xmlHttpGetSuggestions.readyState == 4 || xmlHttpGetSuggestions.readyState == 0){            	
            httpRequestKeyword = keyword;
            userKeyword = keyword;
            //document.all['debug2'].innerText= //document.all['debug2'].innerText + '\nhenter ' + keyword;

            
            if ( id.toString().substring(0,7) == "geotags" ){ 				           
           	 	//xmlHttpGetSuggestions.open("GET", getFunctionsUrl + encode(keyword) + '&id=' + id, true);
           	 	xmlHttpGetSuggestions.open("GET", getFunctionsUrl + encode(keyword) + '[var]id=' + id, true);           	 	
            	
            }
            else {                   	            	     	
            	xmlHttpGetSuggestions.open("GET", getTagsFunctionsUrl + encode(keyword) + '&id=' + id, true);            	
            }
            
//alert(getFunctionsUrl + encode(keyword) + '&id=' + id);
            xmlHttpGetSuggestions.onreadystatechange = handleGettingSuggestions; 
            xmlHttpGetSuggestions.send(null);
          }
          // if the XMLHttpRequest object is busy...
          else
          {
            // retain the keyword the user wanted             
            userKeyword = keyword;
            // clear any previous timeouts already set
            if(timeoutId != -1)
              clearTimeout(timeoutId);          
            // try again in 0.5 seconds     
            timeoutId = setTimeout("getSuggestions('"+id+"','"+userKeyword+"')", 100);
          }
        }
        catch(e)
 
        {
          displayError("1: Can't connect to server:\n" + e.toString());
        }
      }
    }    
  }
}


/* function that escapes a string */
function encode(uri) 
{
	
  if (encodeURIComponent) 
  {
//    return encodeURIComponent(uri);
  }

  if (escape) 
  {
    return escape(uri);
  }
}


/* 
   function that checks to see if the keyword specified as parameter is in 
   the cache or tries to find the longest matching prefixes in the cache 
   and adds them in the cache for the current keyword parameter
*/
function checkCache(keyword)
{ 

  // check to see if the keyword is already in the cache
  if(oCache[keyword])
    return true;
  // try to find the biggest prefixes
  for(i=keyword.length-2; i>=0; i--)
  {
    // compute the current prefix keyword 
    var currentKeyword = keyword.substring(0, i+1);
    // check to see if we have the current prefix keyword in the cache
    if(oCache[currentKeyword])
    {            
      // the current keyword's results already in the cache
      var cacheResults = oCache[currentKeyword];
      // the results matching the keyword in the current cache results
      var keywordResults = new Array();
      var keywordResultsSize = 0;            
      // try to find all matching results starting with the current prefix
      for(j=0;j<cacheResults.length;j++)
      {
 
        if(cacheResults[j].indexOf(keyword) == 0)               
          keywordResults[keywordResultsSize++] = cacheResults[j];
      }      
      // add all the keyword's prefix results to the cache
      addToCache(keyword, keywordResults);      
      return true;  
    }
  }
  // no match found
  return false;
}




/* transforms all the children of an xml node into an array */
function xmlToArray(resultsXml)
{
  // initiate the resultsArray
  var resultsArray= new Array();  
  // loop through all the xml nodes retrieving the content  
  for(i=0;i<resultsXml.length;i++)
    resultsArray[i]=resultsXml.item(i).firstChild.data;
  // return the node's content as an array
  return resultsArray;
}



/* handles the server's response containing the suggestions 
   for the requested keyword  */
function handleGettingSuggestions() 
{
	
	
  //if the process is completed, decide what to do with the returned data
  if (xmlHttpGetSuggestions.readyState == 4) 
  {
  	
  	
    // only if HTTP status is "OK"
    if (xmlHttpGetSuggestions.status == 200) 
    { 
    
      try
      {
        // process the server's response
        
        updateSuggestions();        
      }
      catch(e)
      {
        // display the error message
//        displayError(e.toString()); 
      }  
    } 
    else
    {
      displayError("There was a problem retrieving the data:\n" + xmlHttpGetSuggestions.statusText);
    }       
  }
}





/* function that processes the server's response */
function updateSuggestions()
{	
  // retrieve the server's response 
  var response = xmlHttpGetSuggestions.responseText;
	

  // server error?
  if (response.indexOf("ERRNO") >= 0  || response.indexOf("error:") >= 0 || response.length == 0) throw(response.length == 0 ? "Void server response." : response);
  // retrieve the document element


  response = xmlHttpGetSuggestions.responseXML.documentElement;
	


  // check to see if we have any results for the searched keyword


	//document.all['debug2'].innerText=//document.all['debug2'].innerText+' fant '+response.childNodes.length;
  
  if(response.childNodes.length)
  {  	
    /* we retrieve the new functions' names from the document element as 
       an array */

    for(var i=0;i<params.length;i++){
      dataArray[params[i]]=xmlToArray(response.getElementsByTagName(params[i]));
    }

//    nameArray= xmlToArray(response.getElementsByTagName("name"));       
//    latArray= xmlToArray(response.getElementsByTagName("lat"));       
//    longArray= xmlToArray(response.getElementsByTagName("long"));       
    moreMatches=xmlToArray(response.getElementsByTagName("searchmore"));       
    id=xmlToArray(response.getElementsByTagName("searchid"));       
  }



	//document.all['debug'].innerText='*'+httpRequestKeyword +' '+ userKeyword+' '+nameArray.join(' ');

  // check to see if other keywords are already being searched for
  if(httpRequestKeyword == userKeyword)    
  {
  	
    // display the results array
//    displayResults(httpRequestKeyword, nameArray);
////document.all['debug'].innerText=id; 
//for(i=0;i<nameArray.length;i++){ 
//  	//document.all['debug'].innerText=//document.all['debug'].innerText+"\n"+nameArray[i];
//} 

//alert(dataArray['name'].length);
////document.all['debug'].innerText=xmlHttpGetSuggestions.responseText;

//  //document.all['debug2'].innerText= //document.all['debug2'].innerText + '\nhentet ' +nameArray.join(' ');


  var tmpar=new Array();
	var tmpar_nd=new Array();
  for(i=0;i<dataArray['name'].length;i++){ 
    var tmp =new String();
//    tmpar[i]=dataArray['name'][i];

  	if((dataArray['adm1'][i]!='NULL') && (dataArray['adm1'][i]!=dataArray['name'][i])){
      tmp=tmp+', '+dataArray['adm1'][i]; 
    }

  	if((dataArray['adm'][i]!='NULL') && (dataArray['adm1'][i]!=dataArray['adm'][i]) && (dataArray['name'][i]!=dataArray['adm'][i])){
      tmp=tmp+', '+dataArray['adm'][i]; 
    }

  	if((dataArray['country'][i]!='NULL') && (dataArray['country'][i]!=dataArray['name'][i])){
      tmp=tmp+', '+dataArray['country'][i]; 
    } 
	
  	if(tmp.length>0){
  		 			  		
  		if ( id.toString().substring(0,7) == "geotags" ){
  		
	    tmpar_nd[i]=dataArray['name_nd'][i]+' '+i+' ('+tmp.substring(2,tmp.length)+')';
      tmpar[i]=dataArray['name'][i]+' ('+tmp.substring(2,tmp.length)+')';    			
      					      
		
         
  		}
  		 		
  		
  		else {
  			
  			
  		  tmpar_nd[i]=dataArray['name_nd'][i]+' '+i+' ';
      tmpar[i]=dataArray['name'][i];
  			
  		}
  		
    }else{
	    tmpar_nd[i]=dataArray['name_nd'][i];
      tmpar[i]=dataArray['name'][i];
    }
  }
   
    __AutoComplete[id]['data_nd']=tmpar_nd; 
    __AutoComplete[id]['data']=tmpar; 
    
    AutoComplete_ShowDropdown(id);       
  }
  else
  {
    // add the results to the cache
    // we don't need to display the results since they are no longer useful
    addToCache(httpRequestKeyword, dataArray['name']);              
  }

}






/* function that displays an error message */
function displayError(message)
{
  // display error message, with more technical details if debugMode is true
  alert("Error accessing the server! "+ (debugMode ? "\n" + message : ""));
}









    
    /**
    * Shows the dropdown layer
    * 
    * @param string id The form elements id. Used to identify the correct dropdown.
    */
    function AutoComplete_ShowDropdown(id)
    {
    	
        AutoComplete_HideAll();
             
        var value = __AutoComplete[id]['element'].value;
        
        var toDisplay = new Array();
        var newDiv    = null;
        var text      = null;
        var numItems  = __AutoComplete[id]['dropdown'].childNodes.length;
		
        //alert(numItems);
        
        // Remove all child nodes from dropdown
        while (__AutoComplete[id]['dropdown'].childNodes.length > 0) {
            __AutoComplete[id]['dropdown'].removeChild(__AutoComplete[id]['dropdown'].childNodes[0]);            
        }			
		
        var tmpstr=new String();
        var tmpstr_nd=new String();
        // Go thru data searching for matches

	    try{
	    	
	    	var x = 0;
	        for (i=0; i<__AutoComplete[id]['data'].length; ++i) {
	            tmpstr=__AutoComplete[id]['data'][i].substr(0, value.length);
	            tmpstr_nd=__AutoComplete[id]['data_nd'][i].substr(0, value.length);
	          //  alert(__AutoComplete[id]['data'][i]);
	            if (tmpstr.toLowerCase() == value.toLowerCase() || tmpstr_nd.toLowerCase() == value.toLowerCase()) {            		            	
	                toDisplay[toDisplay.length] = __AutoComplete[id]['data'][i]; 
	            }
	        
        }
	      }catch(e){}		
        
        // No matches?
        if (toDisplay.length == 0) {        	        	
            AutoComplete_HideDropdown(id);
            return;
        }


        // Add data to the dropdown layer
        for (i=0; i<toDisplay.length; ++i) {
            newDiv = document.createElement('div');
            newDiv.className = 'autocomplete_item'; // Don't use setAttribute()
            newDiv.setAttribute('id', 'autocomplete_item_' + i);
            newDiv.setAttribute('title', dataArray['description'][i]);
            newDiv.setAttribute('index', i);
            newDiv.style.zIndex = '99';
            
             // Scrollbars are on display ?    
            if (toDisplay.length > __AutoComplete[id]['maxitems'] && navigator.userAgent.indexOf('MSIE') == -1) {
                newDiv.style.width = __AutoComplete[id]['element'].offsetWidth - 22 + 'px';
            }else{
                newDiv.style.width = __AutoComplete[id]['element'].offsetWidth - 5 + 'px';
            }

            newDiv.onmouseover = function() {AutoComplete_HighlightItem(__AutoComplete[id]['element'].getAttribute('id'), this.getAttribute('index'));};
            newDiv.onclick     = function() {AutoComplete_SetValue(__AutoComplete[id]['element'].getAttribute('id')); AutoComplete_HideDropdown(__AutoComplete[id]['element'].getAttribute('id'));}
            
            text   = document.createTextNode(toDisplay[i]);
            newDiv.appendChild(text);
                        
            __AutoComplete[id]['dropdown'].appendChild(newDiv);            
            
        }
        
        
        // Too many items?
        if (toDisplay.length > __AutoComplete[id]['maxitems']) {        	
            __AutoComplete[id]['dropdown'].style.height = (__AutoComplete[id]['maxitems'] * 15) + 2 + 'px';
        
        } else {
            __AutoComplete[id]['dropdown'].style.height = '';
        }

        
        /**
        * Set left/top in case of document movement/scroll/window resize etc
        */
        __AutoComplete[id]['dropdown'].style.left = AutoComplete_GetLeft(__AutoComplete[id]['element']);
        __AutoComplete[id]['dropdown'].style.top  = AutoComplete_GetTop(__AutoComplete[id]['element']) + __AutoComplete[id]['element'].offsetHeight;		
		__AutoComplete[id]['dropdown'].style.width = __AutoComplete[id]['element'].style.width;
        // Show the iframe for IE
        if (isIE) {
        	__AutoComplete[id]['iframe'].style.width = document.getElementById(id).offsetWidth;
            __AutoComplete[id]['iframe'].style.top    = __AutoComplete[id]['dropdown'].style.top;
            __AutoComplete[id]['iframe'].style.left   = __AutoComplete[id]['dropdown'].style.left;
            __AutoComplete[id]['iframe'].style.width  = __AutoComplete[id]['dropdown'].offsetWidth;
            __AutoComplete[id]['iframe'].style.height = __AutoComplete[id]['dropdown'].offsetHeight;            			
            __AutoComplete[id]['iframe'].style.visibility = 'visible';
            
        }
		
        if (isOpera){        	
	    __AutoComplete[id]['iframe'].style.width='0';
        }
		
        // Show dropdown
        if (!__AutoComplete[id]['isVisible']) {        	
        	
            __AutoComplete[id]['dropdown'].style.visibility = 'visible';            
            
            
                        
            __AutoComplete[id]['isVisible'] = true;            
        }		
        
        // If now showing less items than before, reset the highlighted value
        if (__AutoComplete[id]['dropdown'].childNodes.length != numItems) {
            __AutoComplete[id]['highlighted'] = null;
        }
    }
    
    
    /**
    * Hides the dropdown layer
    * 
    * @param string id The form elements id. Used to identify the correct dropdown.
    */
    function AutoComplete_HideDropdown(id)
    {
        if (__AutoComplete[id]['iframe']) {
            __AutoComplete[id]['iframe'].style.visibility = 'hidden';
        }


        __AutoComplete[id]['dropdown'].style.visibility = 'hidden';
        __AutoComplete[id]['highlighted'] = null;
        __AutoComplete[id]['isVisible']   = false;
    }
    
    
    /**
    * Hides all dropdowns
    */
    function AutoComplete_HideAll()
    {
        for (id in __AutoComplete) {
            AutoComplete_HideDropdown(id);
        }
    }
    
    
    /**
    * Highlights a specific item
    * 
    * @param string id    The form elements id. Used to identify the correct dropdown.
    * @param int    index The index of the element in the dropdown to highlight
    */
    function AutoComplete_HighlightItem(id, index)
    {
        if (__AutoComplete[id]['dropdown'].childNodes[index]) {
            for (var i=0; i<__AutoComplete[id]['dropdown'].childNodes.length; ++i) {
                if (__AutoComplete[id]['dropdown'].childNodes[i].className == 'autocomplete_item_highlighted') {
                    __AutoComplete[id]['dropdown'].childNodes[i].className = 'autocomplete_item';
                }
            }  
	  	try{
           // __AutoComplete[id]['dropdown'].title='test '+dataArray['long'][index]+ ' \n'+dataArray['lat'][index];
}catch(e){}
            __AutoComplete[id]['dropdown'].childNodes[index].className = 'autocomplete_item_highlighted';
            __AutoComplete[id]['highlighted'] = index;

        }
           
    }


    /**
    * Highlights the menu item with the given index
    * 
    * @param string id    The form elements id. Used to identify the correct dropdown.
    * @param int    index The index of the element in the dropdown to highlight
    */
    function AutoComplete_Highlight(id, index)
    {
        // Out of bounds checking
        if (index == 1 && __AutoComplete[id]['highlighted'] == __AutoComplete[id]['dropdown'].childNodes.length - 1) {
            __AutoComplete[id]['dropdown'].childNodes[__AutoComplete[id]['highlighted']].className = 'autocomplete_item';
            __AutoComplete[id]['highlighted'] = null;
        
        } else if (index == -1 && __AutoComplete[id]['highlighted'] == 0) {
            __AutoComplete[id]['dropdown'].childNodes[0].className = 'autocomplete_item';
            __AutoComplete[id]['highlighted'] = __AutoComplete[id]['dropdown'].childNodes.length;
        }

        // Nothing highlighted at the moment
        if (__AutoComplete[id]['highlighted'] == null) {
            __AutoComplete[id]['dropdown'].childNodes[0].className = 'autocomplete_item_highlighted';
            __AutoComplete[id]['highlighted'] = 0;

        } else {
            if (__AutoComplete[id]['dropdown'].childNodes[__AutoComplete[id]['highlighted']]) {
                __AutoComplete[id]['dropdown'].childNodes[__AutoComplete[id]['highlighted']].className = 'autocomplete_item';
            }

            var newIndex = __AutoComplete[id]['highlighted'] + index;

            if (__AutoComplete[id]['dropdown'].childNodes[newIndex]) {
                __AutoComplete[id]['dropdown'].childNodes[newIndex].className = 'autocomplete_item_highlighted';
                
                __AutoComplete[id]['highlighted'] = newIndex;
            }
        }


    }


    /**
    * Sets the input to a given value
    * 
    * @param string id    The form elements id. Used to identify the correct dropdown.
    */
    function AutoComplete_SetValue(id)
    {
    	
		__AutoComplete[id]['element'].value = __AutoComplete[id]['dropdown'].childNodes[__AutoComplete[id]['highlighted']].innerHTML;
		
		var goldfish = __AutoComplete[id]['element'].value;
		if(__AutoComplete[id]['listname']){
			addGeotag(id);
		}
		
		//	
		//	__AutoComplete[id]['long']=dataArray['long'][__AutoComplete[id]['highlighted']];
		//	__AutoComplete[id]['lat']=dataArray['lat'][__AutoComplete[id]['highlighted']];
		
		if (id.toString().substring(0,7) == 'geotags'){
			
			var pvalues=new Array();
			for(var i=0;i<params.length;i++){

				__AutoComplete[id][params[i]]=dataArray[params[i]][__AutoComplete[id]['highlighted']];
				document.getElementById(id+'_'+params[i]).value=__AutoComplete[id][params[i]];
				pvalues[params[i]]=__AutoComplete[id][params[i]]; 
			}
		
		
			//	document.getElementById(id+'_lat').value=__AutoComplete[id]['lat'];	
			if(__AutoComplete[id]['action'] != null){
				eval(__AutoComplete[id]['action']+'(pvalues)'); 
			}	
		
		}
		
		//alert(goldfish);
		
		else {
		
			//alert(goldfish);
			
			var pvalues=new Array();	
			__AutoComplete[id][tagParam]=dataArray[tagParam][__AutoComplete[id]['highlighted']];
			//document.getElementById(id+'_'+tagParam).value=__AutoComplete[id][tagParam];
			
			document.getElementById(id+'_'+tagParam).value=goldfish;
			
			pvalues[tagParam]=__AutoComplete[id][tagParam]; 
			
			if(__AutoComplete[id]['action'] != null){
				eval(__AutoComplete[id]['action']+'(pvalues)'); 
			}	
		
		}
	
    }
    
    
    /**
    * Checks if the dropdown needs scrolling
    * 
    * @param string id    The form elements id. Used to identify the correct dropdown.
    */
    function AutoComplete_ScrollCheck(id)
    {
        // Scroll down, or wrapping around from scroll up
        if (__AutoComplete[id]['highlighted'] > __AutoComplete[id]['lastItemShowing']) {
            __AutoComplete[id]['firstItemShowing'] = __AutoComplete[id]['highlighted'] - (__AutoComplete[id]['maxitems'] - 1);
            __AutoComplete[id]['lastItemShowing']  = __AutoComplete[id]['highlighted'];
        }
        
        // Scroll up, or wrapping around from scroll down
        if (__AutoComplete[id]['highlighted'] < __AutoComplete[id]['firstItemShowing']) {
            __AutoComplete[id]['firstItemShowing'] = __AutoComplete[id]['highlighted'];
            __AutoComplete[id]['lastItemShowing']  = __AutoComplete[id]['highlighted'] + (__AutoComplete[id]['maxitems'] - 1);
        }
        
        __AutoComplete[id]['dropdown'].scrollTop = __AutoComplete[id]['firstItemShowing'] * 15;
    }


    /**
    * Function which handles the keypress event
    * 
    * @param string id    The form elements id. Used to identify the correct dropdown.
    */
    function AutoComplete_KeyDown(id)
    {

        // Mozilla
        if (arguments[1] != null) {
            event = arguments[1];
        }

        var keyCode = event.keyCode;

        switch (keyCode) {

            // Return/Enter
            case 13:
                if (__AutoComplete[id]['highlighted'] != null) {                	
                    AutoComplete_SetValue(id);
                    AutoComplete_HideDropdown(id);                    
                }
                else{                	
                	//event.returnValue = false;
                }
                
                event.cancelBubble = true;
                break;

            // Escape
            case 27:
                AutoComplete_HideDropdown(id);
                event.returnValue = false;
                event.cancelBubble = true;
                break;
            
            // Up arrow
            case 38:
                if (!__AutoComplete[id]['isVisible']) {
                    AutoComplete_ShowDropdown(id);
                }
                
                AutoComplete_Highlight(id, -1);
                AutoComplete_ScrollCheck(id, -1);
                return false;
                break;
            
            // Tab
            case 9:
                if (__AutoComplete[id]['isVisible']) {
                    AutoComplete_HideDropdown(id);
                }
                return;
            
            // Down arrow
            case 40:
                if (!__AutoComplete[id]['isVisible']) {
                    AutoComplete_ShowDropdown(id);
                }
                
                AutoComplete_Highlight(id, 1);
                AutoComplete_ScrollCheck(id, 1);
                return false;
                break;
        }
        
    }
 

    /**
    * Function which handles the keyup event
    * 
    * @param string id    The form elements id. Used to identify the correct dropdown.
    */
    function AutoComplete_KeyUp(id)
    {	   	    	   	    	

        // Mozilla
        if (arguments[1] != null) {
            event = arguments[1];
        }
		if(event.srcElement){
			e = event.srcElement;
		}
		else if (event.target){
			e = event.target; 
		}

        var keyCode = event.keyCode;

        switch (keyCode) {
            case 13:            
            	//addGeotag(id);	              	                         
                event.cancelBubble = true;                     
              	//event.returnValue = false;            	             
                break;

            case 27:
                AutoComplete_HideDropdown(id);
                event.returnValue = false;
                event.cancelBubble = true;
                break;
            
            case 38:
            case 40:
                return false;
                break;

            default:
            	if(document.getElementById(id).value){
            		
            		var now = new Date(); 
            		var then = timer.then;
            		
            		if((now.valueOf() - then) < 1000){            			
            			clearTimeout(timer.taketime);            			
            		}   
            		
            		var tekst = document.getElementById(id).value;            		
            		t = setTimeout("getSuggestions('"+id+"','"+tekst+"')",1000);   
            		timer.taketime = t;             		         		            		            		
                	//AutoComplete_ShowDropdown(id);
                	timer.then = now.valueOf();                	
                	
            	}	
            	
                break;
        }
    }
    
    /**
    * Returns whether the dropdown is visible
    * 
    * @param string id    The form elements id. Used to identify the correct dropdown.
    */
    function AutoComplete_isVisible(id)
    {
        return __AutoComplete[id]['dropdown'].style.visibility == 'visible';
    }
    
    function addGeotag(id){
    	var elem = document.getElementById(id);
		var listname = __AutoComplete[id]['listname'];		
    	if((elem.id.substring(0,6) == 'geotag') && !document.getElementById(listname).innerHTML && (e == document.getElementById(id)) && document.getElementById(id).value && listname){
	            	
	            	var new_geotag = document.createElement( 'div' );
	            	new_geotag.id = 'place';
	            	new_geotag.innerHTML = document.getElementById(id).value; 	            	  	            	
	            	var delete_button = document.createElement( 'b' );				
					delete_button.innerHTML = ' (x)';											
					delete_button.onclick= function(){						
						parents = document.getElementById(listname);												
						parents.removeChild(parents.childNodes[0]);
						document.getElementById(id).value = '';
						//elem.disabled = false;
					};
					delete_button.onmouseover=function(){
						document.body.style.cursor = 'default';
					};
					new_geotag.appendChild(delete_button); 
					document.getElementById(listname).appendChild(new_geotag);
					//elem.disabled = true;									
	            }  
    }
    
    function timeObject(){
    	var then;    
    	var taketime;
    	then = 0;     	
    }    
    

    
    
    

    
    
