/**
 * Représente le champ de recherche.
 * Envoie et affiche les résultats d'une recherche via un XHR.
 */
var SearchBox = Class.create(
{
/**
 * constructeur - prend en paramètre l'ID ou l'élément input[type=text] et les options (optionnel).
 * 
 * @param HTMLElement|string elementID élément input[type=text] de saisie de la recherche
 * @param object options options paramètrable (delay en secondes)
 * 
 * @return SearchBox
 * 
 * @access public
 * @constructor
 */
initialize:		function(elementID)
				{
					// définition des variables membres
					// noeud DOM 
					this.element = $(elementID);
					// timer de la frappe de touche
					this.timer = false;
					// requete XMLHttpRequest
					this.ajax = false;
					// resultats, de classe SearchResults
					this.results = false;
					// delai de frappe (entre 2 touches)
					this.delay = 0.4;
					// requete sans délai si return?
					this.searchOnReturn = true;
					// préchargement de l'image
					this.imagePath = 'CSS/images/ajax-loader.gif';
					// surcharge des options
					Object.extend(this,arguments[1] || {});
					// préchargement des images
					this.image = this.preloadImage(this.imagePath);
					// gestionnaire d'évènements
					this.observe();
				},

/**
 * préchargement et sauvegarde de l'image
 * 
 * @param string image_path chemin d'accès à l'image
 * 
 * @return HTMLImageElement
 */
preloadImage:	function(image_path)
				{
					var image = new Element('img',{'src':image_path});
					
					var offset = this.element.cumulativeOffset();
					var dimensions = this.element.getDimensions();
					
					image.setStyle(
						{
							'display'	: 'block',
							'position'	: 'absolute',
							'top'		: parseInt(offset.top)+'px',
							'left'		: parseInt(parseInt(offset.left) + parseInt(dimensions.width) + 5)+'px'
						}
					);
					return image;
				},
/**
 * supprime l'animation de recherche / attente à côté du champ texte
 * 
 * @access public
 */
ready:			function()
				{
					$('header').removeChild(this.image);
				},
/**
 * affiche l'animation de recherche / attente à côté du champ texte
 * 
 * @access public
 */
waiting:		function()
				{
					$('header').appendChild(this.image);
				},
				
/**
 * retourne le noeud DOM de l'objet
 * 
 * @return HTMLElement
 * 
 * @access public
 */
toElement:		function()
				{
					return this.element;
				},
/**
 * charge le(s) gestionnaire(s) d'évènements
 * 
 * @access private
 */
observe:		function()
				{
					// on écoutera le onKeyUp
					Event.observe(this.element,'keyup',this.timeout.bindAsEventListener(this));
				},
/**
 * Lance le timer. Appelé sur l'évènement onKeyUp de la SearchBox
 * 
 * @param Event event objet Event lié à l'évènement
 * 
 * @access private
 */
timeout:	function(event)
				{
					// normalisation de l'objet Event
					event = event || window.event;
					
					var word = $F(this.element);
					
					// si le timer est déjà lancé, on l'annule 
					if(this.timer !== false)
					{
						// annulation
						clearTimeout(this.timer);
					}
					
					// on lance le timer uniquement si le champ a quelque chose à soumettre
					if(word !='')
					{						
						var keyCode = event.keyCode || event.charCode;
						
						if(this.searchOnReturn && keyCode == Event.KEY_RETURN)
						{
							this.search(word);	
						}
						else
						{
							// sauvegarde du "scope" 
							var that = this;
							// lancement du timer avec le délai en paramètre (ou redéfini par les options du constructeur)
							this.timer = setTimeout(function() { that.search(word); },parseInt(this.delay)*1000);
						}
					}							
					Event.stop(event);
				},
/**
 * Lance la recherche via un appel XMLHttpRequest.
 * 
 * @param string word mot à rechercher
 * 
 * @access private
 */
search:			function(word)
				{
					// réinitialisation du timer
					this.timer = false;

					// affichage "travail en cours"
					this.waiting();

					// sauvegarde du "scope"
					var that = this;

					// nécessaire?
					if(this.ajax !== false)
					{
						this.ajax = false;
					}
										
					// lancement de l'XHR
					this.ajax = new Ajax.Request(
						'ajax.php',
						{
							method: 	'GET',
							parameters:	'search='+word,
							onSuccess:	that.searchResult.bind(that,word),
							onFailure:	that.searchError.bind(that)
						}
					);	
											
				},
/**
 * Appelé lors du succès de l'XHR.
 * 
 * @param XMLHttpRequest xhr retour de l'XHR,contenant la réponse à la requête
 * 
 * @access private
 */
searchResult:	function(word,xhr)
				{
					/*
					this.results = new SearchResult({imagePath:'CSS/images/cross.gif'});
					var offset = this.element.cumulativeOffset();
					var dims = this.element.getDimensions();
					
					this.results.setOffset(
					{
						'top':	parseInt(parseInt(offset.top)+parseInt(dims.height)+5),
						'left':	parseInt(offset.left)
					});
					
					$('header').appendChild(this.results.toElement());
					this.results.showMe();	
					*/ 
					if(!Object.isUndefined(this.results) && this.results !== false) {
						this.results.hide();
					}
					
					var offset = this.element.cumulativeOffset();
					var dims = this.element.getDimensions();
					
					UI.defaultWM.setTheme('mac_os_x');
					this.results = new UI.Window({
						shadowTheme:'mac_shadow',
						shadow:true,
						resizable:false,
						width: 350,
						top: parseInt(parseInt(offset.top)+parseInt(dims.height)+5),
						left: parseInt(offset.left),
						superflousEffects: true
					});
					this.results.element.style.zIndex = '999';
					this.results.show();
					this.results.activate();
						
					this.ready();
					
					if(word.length>15) {
						this.results.setHeader('R&eacute;sultats pour <b>'+word.truncate(15,'...')+'</b>');
						//this.results.setTitle('R&eacute;sultats pour <b>'+word.truncate(15,'...')+'</b>');
					}
					else {
						this.results.setHeader('R&eacute;sultats pour <b>'+word+'</b>');
						//this.results.setTitle('R&eacute;sultats pour <b>'+word+'</b>');	
					}
					this.results.setContent('<div style="padding:5px 10px;">'+xhr.responseText+'</div>');								
				},

/**
 * Appelé lors de l'échec de l'XHR
 * 
 * @access private
 */
searchError:	function()
				{
					this.ready();
					alert('An error occured while searching...');
				}
}
);

/**
 * fenêtre interne à la page affichant les résultats.
 */
var SearchResult = Class.create
(
{
/**
 * constructeur.
 */
initialize:		function()
				{
					Object.extend(this,arguments[0] || {});
					this.createDOM();
				},
				
/**
 * créé les différents éléments DOM
 */
				
createDOM:		function()
				{
					this.outerdiv = new Element('div',{id:'searchresult_outerdiv'});
					this.styleOuterDiv();
					
					this.title = new Element('h1',{id:'searchresult_title'});
					this.styleTitle();
					
					this.innerdiv = new Element('div',{id:'searchresult_innerdiv'});
					this.styleContent();
					
					this.image = new Element('img',{id:'searchresult_image','src':this.imagePath});
					this.styleImage();
					
					this.observeImage();								
					
					this.title.appendChild(this.image);
					this.outerdiv.appendChild(this.title);
					this.outerdiv.appendChild(this.innerdiv);
				},
/**
 * définit le contenu (zone blanche) de la fenêtre de résultats
 * 
 * @param string innerHTML 
 */
setContent:		function(innerHTML)
				{
					this.innerdiv.innerHTML = innerHTML;
				},

/**
 * définit le titre de la fenêtre
 * 
 * @param string innerHTML
 */
setTitle:		function(innerHTML)
				{
					this.title.innerHTML = innerHTML;
					this.title.appendChild(this.image);
				},

/**
 * initialise les gestionnaires d'évènement sur l'image (fermeture de la fenetre principalement)
 */
observeImage:	function()
				{
					Event.observe(this.image,'click',this.closeMe.bindAsEventListener(this));				
				},
				
/**
 * stylise l'image
 */				
styleImage:		function()
				{
					this.image.setStyle({'cursor':'pointer'});
				},
				
/**
 * stylise le DIV externe
 */
styleOuterDiv:	function()
				{
					this.outerdiv.setStyle(
					{
						'border':			'1px solid #FB7D00',
						'backgroundColor':	'#FFFFFF',
						'display':			'none',
						'zIndex':			'999'
					});
				},

/**
 * stylise le titre
 */
styleTitle:		function()
				{
					this.title.setStyle(
					{
						'color':			'white',
						'backgroundColor':	'#FB7D00',
						'fontSize':			'1em',
						'margin':			'0',
						'padding':			'0'
					});
				},

/**
 * stylise le contenu
 */
styleContent:	function()
				{
					this.innerdiv.setStyle(
					{
						'overflow':			'auto',
						'backgroundColor':	'#FFFFFF',
						'height':			'150px',
						'padding':			'5px'
					});
				},

/**
 * définit la position de la fenêtre
 * 
 * @param Object offset contient les variables offset.top et offset.left (integer)
 */				
setOffset:		function(offset)
				{
					this.outerdiv.setStyle(
					{
						position: 	'absolute',
						top: 		offset.top+'px',
						left: 		offset.left+'px'
					}
					);
				},
/**
 *	retourne l'élément engloblant le "widget" 
 */
toElement:		function()
				{
					return this.outerdiv;
				},
				
/**
 * ferme la fenêtre 
 */
closeMe:		function()
				{
					new Effect.Fade(this.toElement(),{duration:0.4});
				},
/**
 * ouvre la fenêtre
 */
showMe:			function()
				{
					new Effect.Appear(this.toElement(),{duration:0.3});
				},
/**
 * vérifie si la fenêtre est visible ou non
 */	
isVisible:		function()
				{
					return this.outerdiv.style.display != 'none';
				}
}
);
