function autoCompleteDB()
 {
    this.aNames=new Array();
 }
 
 autoCompleteDB.prototype.assignArray=function(aList)
 {
    this.aNames=aList;
 };
 
 autoCompleteDB.prototype.getMatches=function(str,aList,maxSize)
 {
    /* debug */ //alert(maxSize+"ok getmatches");
    var ctr=0;
    for(var i in this.aNames)
    {
         if(this.aNames[i].toLowerCase().indexOf(str.toLowerCase())==0) /*looking for case insensitive matches */
       {
          aList.push(this.aNames[i]);
          ctr++;
       }
       if(ctr==(maxSize-1)) /* counter to limit no of matches to maxSize */
          break;
    }
 };
 
 function autoComplete(aNames,oText,oDiv,maxSize)
 {
 
    this.oText=oText;
    this.oDiv=oDiv;
    this.maxSize=maxSize;
    this.cur=-1;
 
    
    /*debug here */
    //alert(oText+","+this.oDiv);
    
    this.db=new autoCompleteDB();
    this.db.assignArray(aNames);
    
    oText.onkeyup=this.keyUp;
    oText.onkeydown=this.keyDown;
    oText.autoComplete=this;
    oText.onblur=this.hideSuggest;
 }
 
 autoComplete.prototype.hideSuggest=function()
 {
    this.autoComplete.oDiv.style.visibility="hidden";
 };
 
 autoComplete.prototype.selectText=function(iStart,iEnd)
 {
    if(this.oText.createTextRange) /* For IE */
    {
       var oRange=this.oText.createTextRange();
       oRange.moveStart("character",iStart);
       oRange.moveEnd("character",iEnd-this.oText.value.length);
       oRange.select();
    }
    else if(this.oText.setSelectionRange) /* For Mozilla */
    {
       this.oText.setSelectionRange(iStart,iEnd);
    }
    this.oText.focus();
 };
 
 autoComplete.prototype.textComplete=function(sFirstMatch)
 {
    if(this.oText.createTextRange || this.oText.setSelectionRange)
    {
       var iStart=this.oText.value.length;
       this.oText.value=sFirstMatch;
       this.selectText(iStart,sFirstMatch.length);
    }
 };
 
 autoComplete.prototype.keyDown=function(oEvent)
 {
    oEvent=window.event || oEvent;
    iKeyCode=oEvent.keyCode;
 
    switch(iKeyCode)
    {
       case 38: //up arrow
          this.autoComplete.moveUp();
          break;
       case 40: //down arrow
          this.autoComplete.moveDown();
          break;
       case 13: //return key
          window.focus();
          break;
    }
 };
 
 autoComplete.prototype.moveDown=function()
 {
    if(this.oDiv.childNodes.length>0 && this.cur<(this.oDiv.childNodes.length-1))
    {
       ++this.cur;
       for(var i=0;i<this.oDiv.childNodes.length;i++)
       {
          if(i==this.cur)
          {
             this.oDiv.childNodes[i].className="over";
             this.oText.value=this.oDiv.childNodes[i].innerHTML;
          }
          else
          {
             this.oDiv.childNodes[i].className="";
          }
       }
    }
 };
 
 autoComplete.prototype.moveUp=function()
 {
    if(this.oDiv.childNodes.length>0 && this.cur>0)
    {
       --this.cur;
       for(var i=0;i<this.oDiv.childNodes.length;i++)
       {
          if(i==this.cur)
          {
             this.oDiv.childNodes[i].className="over";
             this.oText.value=this.oDiv.childNodes[i].innerHTML;
          }
          else
          {
             this.oDiv.childNodes[i].className="";
          }
       }
    }
 };
 
 autoComplete.prototype.keyUp=function(oEvent)
 {
    oEvent=oEvent || window.event;
    var iKeyCode=oEvent.keyCode;
    if(iKeyCode==8 || iKeyCode==46)
    {
       this.autoComplete.onTextChange(false); /* without autocomplete */
    }
 else if (iKeyCode < 32 || (iKeyCode >= 33 && iKeyCode <= 46) || (iKeyCode >= 112 && iKeyCode <= 123))
    {
       //ignore
    }
    else
    {
       this.autoComplete.onTextChange(true); /* with autocomplete */
    }
 };
 
 autoComplete.prototype.positionSuggest=function() /* to calculate the appropriate poistion of the dropdown */
 {
    var oNode=this.oText;
    var x=0,y=oNode.offsetHeight;
 
    while(oNode.offsetParent && oNode.offsetParent.tagName.toUpperCase() != 'BODY')
    {
       x+=oNode.offsetLeft;
       y+=oNode.offsetTop;
       oNode=oNode.offsetParent;
    }
 
    x+=oNode.offsetLeft;
    y+=oNode.offsetTop;
 
    this.oDiv.style.top=y+"px";
    this.oDiv.style.left=x+"px";
 }
 
 autoComplete.prototype.onTextChange=function(bTextComplete)
 {
    var txt=this.oText.value;
    var oThis=this;
    this.cur=-1;
    
    if(txt.length>0)
    {
       while(this.oDiv.hasChildNodes())
          this.oDiv.removeChild(this.oDiv.firstChild);
       
       var aStr=new Array();
       this.db.getMatches(txt,aStr,this.maxSize);
       if(!aStr.length) {this.hideSuggest ;return}
       if(bTextComplete) this.textComplete(aStr[0]);
       this.positionSuggest();
       
       for(i in aStr)
       {
          var oNew=document.createElement('div');
          this.oDiv.appendChild(oNew);
          oNew.onmouseover=
          oNew.onmouseout=
          oNew.onmousedown=function(oEvent)
          {
             oEvent=window.event || oEvent;
             oSrcDiv=oEvent.target || oEvent.srcElement;
 
             //debug :window.status=oEvent.type;
             if(oEvent.type=="mousedown")
             {
                oThis.oText.value=this.innerHTML;
             }
             else if(oEvent.type=="mouseover")
             {
                this.className="over";
             }
             else if(oEvent.type=="mouseout")
             {
                this.className="";
             }
             else
             {
                this.oText.focus();
             }
          };
          oNew.innerHTML=aStr[i];
       }
       
       this.oDiv.style.visibility="hidden";
    }
    else
    {
       this.oDiv.innerHTML="";
       this.oDiv.style.visibility="hidden";
    }
 };
 
 function createAutoComplete()
 {
 var aNames =
    [
    "Albanvale 3021","Albion 3020","Altona 3018","Altona East","Altona Gate","Altona Meadows 3028","Altona North 3025","Ardeer 3022","Ardeer South","Braybrook 3019","Brimbank","Brookfield 3338","Brooklyn (part) 3012","Brophys Crossing","Burnside 3023","Burnside Heights 3023","Cairnlea 3023","Calder Park 3037","Caroline Springs 3023","Chartwell","Cocoroc 3030","Deer Park 3023","Delahey 3037","Derrimut 3030","Diggers Rest 3427","Exford 3338","Eynesbury 3338","Eynesbury 3338","Footscray 3011","Glengala","Hillside 3037","Hoppers Crossing 3029","Kealba 3021","Keilor 3036","Keilor Downs 3038","Keilor Lodge 3038","Keilor North 3036","Keilor Park 3042","Kings Park 3021","Kingsville 3012","Kurunjang 3337","Laverton 3028","Laverton North 3026","Laverton South","Laverton West","Little River 3211","Maidstone 3012","Mambourin 3024","Manor","Maribyrnong 3032","Melton 3337","Melton South 3338","Melton West 3337","Mount Cottrell 3024","Mount Cottrell 3024","Newport 3015","Parwan 3340","Plumpton 3335","Point Cook 3030","Quandong 3340","Ravenhall 3023","Robertson","Rockbank 3335","Sanctuary Lakes","Seabrook 3028","Seaholme 3018","Seddon 3011","South Kingsville 3015","Spotswood 3015","St Albans 3021","St Albans East","St Albans South","Sunshine 3020","Sunshine North 3020","Sunshine West 3020","Sydenham 3037","Sydenham Park","Sydenham West","Tarneit 3029","Taylors Hill 3037","Taylors Lakes 3038","The Gap","Toolern Vale 3337","Tottenham 3012","Truganina 3029","Truganina 3029","Watergardens","Werribee 3030","Werribee South 3030","West Footscray 3012","Western Gardens","Westmelton","Williams Landing 3027","Williamstown 3016","Williamstown North 3016","Wyndham Vale 3024","Yarraville 3013"
    ];
 
 new autoComplete(aNames,document.getElementById('txt'),document.getElementById('suggest'),10);
 }
 