//==================================================================================
//							AUTOCOMPLETION STYLE GOOGLE
//===================================================================================
var _documentForm=null; // le formulaire contenant notre champ texte
var _inputField=null; // le champ texte lui-meme
var _inputFieldHiddenId=null; // texte hidden id retour (c l'id du champ cache)
var _submitButton=null; // le bouton submit de notre formulaire

var _oldInputFieldValue=""; // valeur precedente du champ texte
var _currentInputFieldValue=""; // valeur actuelle du champ texte
var _oldInputFieldHiddenIdValue=""; // valeur precedente du champ id du texte
var _currentInputFieldHiddenIdValue=""; // valeur actuelle du champ id du  texte
var _resultCache=new Object(); // mecanisme de cache des requetes
var _resultCacheId=new Object(); // mecanisme de cache des requetes

var _xmlHttp = null; //l'objet xmlHttpRequest utilise pour contacter le serveur
var _adresseRecherche = "ajax/find.sociopro.php" //l'adresse à interroger pour trouver les suggestions
var _params = null ;
var _lib_resultats = null ;
var _cursorUpDownPressed = null;

var _completeDivRows = 0;
var _completeDivDivList = null;
var _highlightedSuggestionIndex = -1;
var _highlightedSuggestionDiv = null;

var _lastKeyCode=null;
var _eventKeycode = null;

var _divContainer=null // Div qui va contenir la div de resultats renvoye par l ajax

function initAutoComplete(form,field,hiddenId,submit,tablename,limit,libelle,divContainer,lib_resultats){ 
  _documentForm=form;
  _inputField=field;
  _inputFieldHiddenId=hiddenId
  _submitButton=submit;
  _inputField.autocomplete="off";
  _divContainer = divContainer;
  creeAutocompletionDiv();
  _currentInputFieldValue=_inputField.value;
  _currentInputFieldHiddenIdValue=document.getElementById(_inputFieldHiddenId).value;
  _oldInputFieldValue=_currentInputFieldValue;
  _oldInputFieldHiddenIdValue=_currentInputFieldHiddenIdValue;
  _params = '&tablename='+tablename+'&field='+libelle +'&limit='+limit;
  _lib_resultats = lib_resultats;
//  cacheResults("",new Array())
  document.onkeydown=onKeyDownHandler;  
  _inputField.onkeyup=onKeyUpHandler;  
  _inputField.onblur=onBlurHandler;
  window.onresize=onResizeHandler;         
  // Premier declenchement de la fonction dans 200 millisecondes
  setTimeout("mainLoop()",200) 	
}

// tourne en permanence pour suggerer suite à un changement du champ texte
function mainLoop(){
  if(_oldInputFieldValue!=_currentInputFieldValue){
    var valeur=escapeURI(_currentInputFieldValue);
    var suggestions=_resultCache[_currentInputFieldValue];
    var idSuggestions=_resultCacheId[_currentInputFieldValue];
    if(suggestions){ // la reponse etait encore dans le cache
      metsEnPlace(valeur,suggestions,idSuggestions)
    }else{
      callSuggestions(valeur) // appel distant
    }
    _inputField.focus()
  }
  _oldInputFieldValue=_currentInputFieldValue;
  _oldInputFieldHiddenIdValue=_currentInputFieldHiddenIdValue;
  setTimeout("mainLoop()",200); // la fonction se redeclenchera dans 200 ms
  return true
}

// echappe les caractère speciaux
function escapeURI(La){
  if(encodeURIComponent) {
    return encodeURIComponent(La);
  }
  if(escape) {
    return escape(La)
  }
}

function callSuggestions(valeur){
  if(_xmlHttp&&_xmlHttp.readyState!=0){
    _xmlHttp.abort()
  }
  _xmlHttp=getHTTPObject();
  if(_xmlHttp){
    //appel à l'url distante
    
    //_xmlHttp.open("GET",_adresseRecherche+"?val="+valeur+_params,true); 
    _xmlHttp.open("GET",_adresseRecherche+"?val="+valeur,true);    
    _xmlHttp.onreadystatechange=function() {
      if(_xmlHttp.readyState==4&&_xmlHttp.responseText) {      	
        var liste = traiteTextSuggestions(_xmlHttp.responseText);
        var idListe = traiteTextIdSuggestions(_xmlHttp.responseText);        
//        cacheResults(valeur,liste,idListe);
        metsEnPlace(valeur,liste,idListe);
      }
    };
    // envoi de la requete
    _xmlHttp.send(null)
  }
}

// Mecanisme de caching des reponses
function cacheResults(debut,suggestions,Idsuggestions){
  _resultCache[debut]=suggestions;
  _resultCacheId[debut]=Idsuggestions;
}

// Transformation XML en tableau
function traiteXmlSuggestions(xmlDoc) {
  var options = xmlDoc.getElementsByTagName('option');
  var optionsListe = new Array();
  for (var i=0; i < options.length; ++i) {
    optionsListe.push(options[i].firstChild.data);
  }
  return optionsListe;
}

// Transformation Txt en tableau
function traiteTextSuggestions(sReponse) {  
  var aReponse = new Array();
  aReponse = sReponse.split("|");
  var optionsListe = new Array();
  
  for(i=0;i<aReponse.length;i++)
  {  	
  	if(i%2 && aReponse[i]!=0 )
  	{  		
  		optionsListe.push(aReponse[i]);  	
  	}
  }
  return optionsListe;
}

function trim(myString) 
{ 
return myString.replace(/^\s+/g,'').replace(/\s+$/g,'') ;
} 

// Transformation Txt en tableau
function traiteTextIdSuggestions(sReponse) {  
  var aReponse = new Array();
  aReponse = sReponse.split("|");  
  var idOptionsListe = new Array();
  for(i=0;i<aReponse.length;i++)
  {  	
  	if(!(i%2))
  	{  		
  		idOptionsListe.push(trimCR(trim(aReponse[i])));
  	}
  }
  
  return idOptionsListe;
}

//insère une règle avec son nom
function insereCSS(nom,regle){
  if (document.styleSheets) {
    var I=document.styleSheets[0];
    if(I.addRule){ // methode IE
      I.addRule(nom,regle)
    }else if(I.insertRule){ // methode DOM
      I.insertRule(nom+" { "+regle+" }",I.cssRules.length)
    }
  }
}

/*function initStyle(){
  var AutoCompleteDivListeStyle="font-size: 12px; font-family: arial,sans-serif; word-wrap:break-word; ";//container
  var AutoCompleteDivStyle="display: block; padding-left: 3; padding-right: 3; height: 16px; overflow: hidden; background-color: white;";//defuat
  var AutoCompleteDivActStyle="background-color: #3366cc; color: white ! important; ";//hover
  insereCSS(".AutoCompleteDivListeStyle",AutoCompleteDivListeStyle);
  insereCSS(".AutoCompleteDiv",AutoCompleteDivStyle);
  insereCSS(".AutoCompleteDivAct",AutoCompleteDivActStyle);
}*/

function setStylePourElement(c,name){
  c.className=name;
}

// calcule le decalage à gauche
function calculateOffsetLeft(r){
  return calculateOffset(r,"offsetLeft")
}

// calcule le decalage vertical
function calculateOffsetTop(r){
  return calculateOffset(r,"offsetTop")
}

function calculateOffset(r,attr){
  var kb=0;
  while(r){
    kb+=r[attr];
    r=r.offsetParent
  }
  return kb
}

// calcule la largeur du champ
function calculateWidth(){
  return _inputField.offsetWidth-2*1
}

function setCompleteDivSize(){
  if(_completeDiv){
    _completeDiv.style.left=calculateOffsetLeft(_inputField)+"px";
    _completeDiv.style.top=calculateOffsetTop(_inputField)+_inputField.offsetHeight-1+"px";
    _completeDiv.style.width=calculateWidth()+"px"
  }
}

function creeAutocompletionDiv() {
  //initStyle();
  _completeDiv=document.createElement("DIV");
  _completeDiv.id="completeDiv";  
  var borderLeftRight=1;
  var borderTopBottom=1;
 /* _completeDiv.style.borderRight="black "+borderLeftRight+"px solid";
  _completeDiv.style.borderLeft="black "+borderLeftRight+"px solid";
  _completeDiv.style.borderTop="black "+borderTopBottom+"px solid";
  _completeDiv.style.borderBottom="black "+borderTopBottom+"px solid";*/
 /* _completeDiv.style.zIndex="1";
  _completeDiv.style.paddingRight="0";
  _completeDiv.style.paddingLeft="0";
  _completeDiv.style.paddingTop="0";
  _completeDiv.style.paddingBottom="0";
  setCompleteDivSize();
  _completeDiv.style.visibility="hidden";
  _completeDiv.style.position="absolute";
  _completeDiv.style.backgroundColor="white";
  _completeDiv.style.cursor="pointer";*/
  document.getElementById(_divContainer).appendChild(_completeDiv);
//  document.body.appendChild(_completeDiv);
  setStylePourElement(_completeDiv,"AutoCompleteDivListeStyle");
}

function metsEnPlace(valeur, liste, idListe){
  while(_completeDiv.childNodes.length>0) {
    _completeDiv.removeChild(_completeDiv.childNodes[0]);
  }
  
  // mise en place des suggestions
  for(var f=0; f<liste.length; ++f){
    var nouveauDiv=document.createElement("DIV");
    nouveauDiv.onmousedown=divOnMouseDown;
    nouveauDiv.onmouseover=divOnMouseOver;    
    nouveauDiv.onmouseout=divOnMouseOut;
    setStylePourElement(nouveauDiv,"AutoCompleteDiv");
    var nouveauSpan=document.createElement("SPAN");
    nouveauSpan.id = idListe[f]; // id du texte de la suggestion
    nouveauSpan.innerHTML=liste[f]; // le texte de la suggestion
    nouveauDiv.appendChild(nouveauSpan);
    _completeDiv.appendChild(nouveauDiv);
  }
  
  //affichage resultats
  var nouveauSpan=document.createElement("SPAN");
  nouveauSpan.id = "resListe"; // id du texte de la suggestion
  if(idListe[liste.length]!= undefined) 
  {
  	var nb_resultats = idListe[liste.length];
  }
  else
  {
  	var nb_resultats = 0;
  }
  nouveauSpan.innerHTML= nb_resultats + " " + _lib_resultats ; // le texte de la suggestion
//  nouveauDiv.appendChild(nouveauSpan);
  _completeDiv.appendChild(nouveauSpan);  
  
  PressAction();
  if(_completeDivRows>0) {
    _completeDiv.height=16*_completeDivRows+4;
  } else {
    hideCompleteDiv();
  }
  
  

}

// Handler pour le keydown du document
var onKeyDownHandler=function(event){
  // accès evenement compatible IE/Firefox
  if(!event&&window.event) {
    event=window.event;
  }
  // on enregistre la touche ayant declenche l'evenement
  if(event) {
    _lastKeyCode=event.keyCode;
  }
}



// Handler pour le keyup de lu champ texte
var onKeyUpHandler=function(event){
  // accès evenement compatible IE/Firefox
  if(!event&&window.event) {
    event=window.event;
  }
  _eventKeycode=event.keyCode;
  // Dans les cas touches touche haute(38) ou touche basse (40)
  if(_eventKeycode==40||_eventKeycode==38) {
    // on autorise le blur du champ (traitement dans onblur)
    blurThenGetFocus();
  }
  // taille de la selection
  var N=rangeSize(_inputField);
  // taille du texte avant la selection (selection = suggestion d'autocompletion)
  var v=beforeRangeSize(_inputField);
  // contenu du champ texte
  var V=_inputField.value;
  var VId=document.getElementById(_inputFieldHiddenId).value;
  
  if(_eventKeycode!=0){
    if(N>0&&v!=-1) {
      // on recupere uniquement le champ texte tape par l'utilisateur
      V=V.substring(0,v);
    }
    // 13 = touche entree
    if(_eventKeycode==13||_eventKeycode==3){
      var d=_inputField;
      // on mets en place l'ensemble du champ texte en repoussant la selection
      if(_inputField.createTextRange){
        var t=_inputField.createTextRange();
        t.moveStart("character",_inputField.value.length);        
        _inputField.select()
      } else if (d.setSelectionRange){      	
        _inputField.setSelectionRange(_inputField.value.length,_inputField.value.length)
      }
    } else {
      // si on a pas pu agrandir le champ non selectionne, on le mets en place violemment.
      if(_inputField.value!=V) {
        _inputField.value=V;
        document.getElementById(_inputFieldHiddenId).value=VId;
      }
    }
  }
  
  // si la touche n'est ni haut, ni bas, on stocke la valeur utilisateur du champ
  if(_eventKeycode!=40&&_eventKeycode!=38) {
    // le champ courant n est pas change si key Up ou key Down
  	_currentInputFieldValue=V;
  	_currentInputFieldHiddenIdValue=VId;
//  	document.getElementById(_inputFieldHiddenId).value=zId;
  }
    
  //si on supprime une lettre alors on vide le champ ID
  if(_eventKeycode==8||_eventKeycode==46)
  {  	
  	_currentInputFieldHiddenIdValue = "";
  	document.getElementById(_inputFieldHiddenId).value="";
  }
   
  
  if(handleCursorUpDownEnter(_eventKeycode)&&_eventKeycode!=0) 
  {
    // si on a presse une touche autre que haut/bas/enter et suppr   
    PressAction();
  }
}

// Change la suggestion selectionne.
// cette methode traite les touches haut, bas et enter
function handleCursorUpDownEnter(eventCode)
{
  if(eventCode==40)
  {
    highlightNewValue(_highlightedSuggestionIndex+1);
    return false;
  }
  else 
  {
  	if(eventCode==38)  
	{  	
	   highlightNewValue(_highlightedSuggestionIndex-1);
	   return false;
	}
	else 
	{		
    	return false;
  	}
  }
  return true;
}


// gere une touche pressee autre que haut/bas/enter
function PressAction(){
	
  _highlightedSuggestionIndex=-1;
  var suggestionList=_completeDiv.getElementsByTagName("div");
  var suggestionLongueur=suggestionList.length;
  // on stocke les valeurs precedentes
  // nombre de possibilites de completion
  _completeDivRows=suggestionLongueur;
  // possiblites de completion
  _completeDivDivList=suggestionList;
  // si le champ est vide, on cache les propositions de completion
  if(_currentInputFieldValue==""||suggestionLongueur==0){
    hideCompleteDiv()
  }else{
    showCompleteDiv()
  }
  var trouve=false;
  
  // si on a du texte sur lequel travailler
  if(_currentInputFieldValue.length>0){
    var indice;
    // T vaut true si on a dans la liste de suggestions un mot commencant comme l'entree utilisateur
    for(indice=0; indice<suggestionLongueur; indice++){
      if(getSuggestion(suggestionList.item(indice)) != undefined)
      {
	      if(getSuggestion(suggestionList.item(indice)).toUpperCase().indexOf(_currentInputFieldValue.toUpperCase())==0) {
	        trouve=true;
	        break
	      }
      }
    }
  }
  // on deselectionne toutes les suggestions
  for(var i=0; i<suggestionLongueur; i++) {
    setStylePourElement(suggestionList.item(i),"AutoCompleteDiv");
  }
  // si l'entree utilisateur (n) est le debut d'une suggestion (n-1) on selectionne cette suggestion avant de continuer
  if(trouve){
    _highlightedSuggestionIndex=indice;
    _highlightedSuggestionDiv=suggestionList.item(_highlightedSuggestionIndex);
  }else{
    _highlightedSuggestionIndex=-1;
    _highlightedSuggestionDiv=null
  }
  var supprSelection=false;
  switch(_eventKeycode){
    // cursor left, cursor right, page up, page down, others??
    case 8:
    case 33:
    case 34:
    case 35:
    case 35:
    case 36:
    case 37:
    case 39:
    case 45:
    case 46:
      // on supprime la suggestion du texte utilisateur
      supprSelection=true;
      break;
    default:
      break
  }
  // si on a une suggestion (n-1) selectionnee
  if(!supprSelection&&_highlightedSuggestionDiv){
    setStylePourElement(_highlightedSuggestionDiv,"AutoCompleteDivAct");
    var z; var zId;
    if(trouve) {
      z=getSuggestion(_highlightedSuggestionDiv).substr(0);
      zId=getSuggestionId(_highlightedSuggestionDiv).substr(0);
    } else {
      z=_currentInputFieldValue;
    }
    if(z!=_inputField.value){
      if(_inputField.value!=_currentInputFieldValue) {
        return;
      }
      // si on peut creer des range dans le document
      if(_inputField.createTextRange||_inputField.setSelectionRange) {      	
        _inputField.value=z;               
        document.getElementById(_inputFieldHiddenId).value=zId;
      }
      // on selectionne la fin de la suggestion
      if(_inputField.createTextRange){
        var t=_inputField.createTextRange();
        t.moveStart("character",_currentInputFieldValue.length);
        t.select()
      }else if(_inputField.setSelectionRange){
        _inputField.setSelectionRange(_currentInputFieldValue.length,_inputField.value.length)
      }
    }
  }else{
    // sinon, plus aucune suggestion de selectionnee
    _highlightedSuggestionIndex=-1;
  }
}



// permet le blur du champ texte après que la touche haut/bas ai ete presse.
// le focus est recupere après traitement (via le timeout).
function blurThenGetFocus(){
  _cursorUpDownPressed=true;
  _inputField.blur();
  setTimeout("_inputField.focus();",10);
  return
}

// taille de la selection dans le champ input
function rangeSize(n){
  var N=-1;
  if(n.createTextRange){
    var fa=document.selection.createRange().duplicate();
    N=fa.text.length
  }else if(n.setSelectionRange){
    N=n.selectionEnd-n.selectionStart
  }
  return N
}

// taille du champ input non selectionne
function beforeRangeSize(n){
  var v=0;
  if(n.createTextRange){
    var fa=document.selection.createRange().duplicate();
    fa.moveEnd("textedit",1);
    v=n.value.length-fa.text.length
  }else if(n.setSelectionRange){
    v=n.selectionStart
  }else{
    v=-1
  }
  return v
}

// Place le curseur à la fin du champ
function cursorAfterValue(n){
  if(n.createTextRange){
    var t=n.createTextRange();
    t.moveStart("character",n.value.length);
    t.select()
  } else if(n.setSelectionRange) {
    n.setSelectionRange(n.value.length,n.value.length)
  }
}


// Retourne la valeur de la possibilite (texte) contenu dans une div de possibilite
function getSuggestion(uneDiv){
  if(!uneDiv) {
    return null;
  }
  
  	if(uneDiv.getElementsByTagName('span')[0].firstChild != null)
  	{
   		return trimCR(uneDiv.getElementsByTagName('span')[0].firstChild.data);
  	}
 }

 
// Retourne la valeur de la possibilite (texte) contenu dans une div de possibilite
function getSuggestionId(uneDiv){
  if(!uneDiv) {
    return null;
  }
    
  	if(uneDiv.getElementsByTagName('span')[0].firstChild != null)
  	{
   		return trimCR(uneDiv.getElementsByTagName('span')[0].id);
  	}
 }
 
// supprime les caractères retour chariot et line feed d'une chaine de caractères
function trimCR(chaine){
  for(var f=0,nChaine="",zb="\n\r"; f<chaine.length; f++) {
    if (zb.indexOf(chaine.charAt(f))==-1) {
      nChaine+=chaine.charAt(f);
    }
  }
  return nChaine
}

// Cache completement les choix de completion
function hideCompleteDiv(){
  _completeDiv.style.visibility="hidden"
}

// Rends les choix de completion visibles
function showCompleteDiv(){
  _completeDiv.style.visibility="visible";
  setCompleteDivSize()
}

// Change la suggestion en surbrillance
function highlightNewValue(C){
  if(!_completeDivDivList||_completeDivRows<=0) {
    return;
  }
  showCompleteDiv();
  if(C>=_completeDivRows){
    C=_completeDivRows-1
  }
  if(_highlightedSuggestionIndex!=-1&&C!=_highlightedSuggestionIndex){
    setStylePourElement(_highlightedSuggestionDiv,"AutoCompleteDiv");
    _highlightedSuggestionIndex=-1
  }
  if(C<0){
    _highlightedSuggestionIndex=-1;
    _inputField.focus();
    return
  }
  _highlightedSuggestionIndex=C;
  _highlightedSuggestionDiv=_completeDivDivList.item(C);
  setStylePourElement(_highlightedSuggestionDiv,"AutoCompleteDivAct");
  _inputField.value=getSuggestion(_highlightedSuggestionDiv);
  document.getElementById(_inputFieldHiddenId).value=getSuggestionId(_highlightedSuggestionDiv);
  
}

// Handler de resize de la fenetre
var onResizeHandler=function(event){
  // recalcule la taille des suggestions
  setCompleteDivSize();
}

// Handler de blur sur le champ texte
var onBlurHandler=function(event){
  if(!_cursorUpDownPressed){
    // si le blur n'est pas cause par la touche haut/bas
    hideCompleteDiv();
    // Si la dernière touche presse est tab, on passe au bouton de validation
    if(_lastKeyCode==9 || _lastKeyCode==13 ){
//      _submitButton.focus();

	//supprime les divs crees
		removeChildrenFromNode(document.getElementById(_divContainer));
      _lastKeyCode=-1
    }
  }
  _cursorUpDownPressed=false
};

// declenchee quand on clique sur une div contenant une possibilite
var divOnMouseDown=function(){
  _inputField.value=getSuggestion(this);
  _inputFieldHiddenId.value = getSuggestionId(this);    
  document.getElementById(_inputFieldHiddenId).value =  getSuggestionId(this);  
  
  //on supprime la div
  removeChildrenFromNode(document.getElementById(_divContainer));
  //document.getElementById(_documentForm).submit();
  
_documentForm.submit();
};

// declenchee quand on passe sur une div de possibilite. La div precedente est passee en style normal
var divOnMouseOver=function(){
	
  if(_highlightedSuggestionDiv) {
    setStylePourElement(_highlightedSuggestionDiv,"AutoCompleteDiv");
    
  }    
  setStylePourElement(this,"AutoCompleteDivAct");
  
};

// declenchee quand la sourie quitte une div de possiblite. La div repasse a l'etat normal
var divOnMouseOut = function(){	
  setStylePourElement(this,"AutoCompleteDiv");
	
};

function removeElement(divNum) {
  var d = document.body ;
  var olddiv = document.getElementById("completeDiv");
  d.removeChild(olddiv);
//  alert("toto");
}


function removeChildrenFromNode(node){	
 while(node.lastChild)
 {      	
 	node.removeChild(node.lastChild);
 }
}
