/* ================================================================================================
suggestions-v1.1.js

Biblioteka Suggestions sluzy do wyswietlania podpowiedzi przy wpisywaniu danej frazy w formularzu w elemencie
'input'. Podpowiedzi pobierane sa z bazy danych na podstawie wpisywanej frazy - tzn. wybierane sa te, ktore 
zaczynaja sie od wprowadzanej frazy. Popdowiedzi pobierane sa w tle przy uzyciu technologii AJAX. 
Wybor nastepuje poprzez klikniecie myszka na dana podpowiedz lub poprzez  wcisniecie przycisku 'enter' 
z klawiatury po uprzednim wyborze za pomocą strzałek 'w górę' oraz 'w dół' z klawiatury.


Uwaga:
Biblioteka obejmuje tylko slrypty po stronie klienta. Nalezy wiec samemu napisac skrytp dzialajacy po stronie
serwera, ktory pobierze z bazy danych odpowiednie dane. 

JAK UZYWAC:

1.	Na poczatku nalezy zalaczyc te biblioteke w sekcji <head> strony:
	
	<script src="suggestions-v1.0.js" type="text/javascript"></script>

2. 	Element <input>, do ktorego maja odnosic sie podpowiedzi, nalezy umiescic w elemencie blokowym <div>, ktoremu
	nalezy nadac styl "position: relative":
	
	<div style="position: relative;">
		<input ... />
	</div>
	
3. 	Za elementem <input> nalezy wstawic element blokowy <div> i nadac mu niepowtarzalny atrybut "id":

	<div style="position: relative;">
		<input ... />
		<div id="jakis_niepowtarzalny_id"></div>
	</div>
	
	Pamietajmy o zamknieciu tego elementu!
	
4. 	W elemencie <input> musimy wstawic funkcje:  
	
	init Suggestions( in_id, suggestion_container, link, method, event )   , gdzie:	in_id - element <input> - najlepiej wpisac 'this' bez cudzyslowow;
										suggestion_container - id elementu <div>, ktoremu nadalismy
													        id "jakis_niepowtarzalny_id";
										link - sciezka do pliku se skrytpem wykonywanym po stronie
											serwera
										method - metoda przesylania danych na serwer
										event - obiekt zdarzenia, wpisujemy 'event' bez cudzyslowow;
	
	hideSuggestions ( suggestion_container )				,gdzie  suggestion_container - id elementu <div>, ktoremu nadalismy
													        id "jakis_niepowtarzalny_id";
															
	dla zdarzen:
	
	<input ...  onblur="hide Suggestions( ... );    onkeyup="initSuggestions ( ... ); "... />
	
5. 	Nalezy jeszcze w znaczniku <form ... > dopisac:

	<form ... onsubmit="checkEnter();" ... >
	
	Funkcja 'checkEnter()' ma takie dzialanie: kiedy wcisnie sie przycisk 'enter', aby zaakceptowac zaznaczona podpowiedz,
	formularz nie zostanie wyslany. Zostanie wyslany natomiast przy drugim kliknieciu przycisku 'enter'

6. 	Teraz nalezy ustalic odpowiednie style dla  tworzonych w bibiotece elementow. Nalezy po prostu zmodyfikowac
	style znajdujace sie wewnatrz nastepujacych funkcji w bibliotece:
	
	setSuggContStyles ( sc )  - 	ustawia style pola, w ktorym beda wyswietlane podpowiedzi; nalezy pamietac 
						o odpowiednim wypozycjonowaniu tego pola za pomoca stylow "top" oraz "left"
					  
	setLineStyles (  )	-		ustawia style dla pojedynczego wiersza w polu z podpowiedziami, czyli 
						dla pojedynczej podpowiedzi
						
	setHighlightLineStyles (   ) -	ustawia style dla pojedynczego wiersza, kiedy ten jest zaznaczony 
						poprzez najechanie myszka albo poprzez wciskanie klawiszy strzalek		
						'w gore' i 'w dol'.
						
	Sa to pierwsze trzy funkcje w bibliotece, dlatego latwo jest je odnalezc.
	
To wszystko. Teraz powinno dzialac.


 ================================================================================================== */


function Suggestion (  ) {

	//	ZMIENNE GLOBALNE
	var suggestions = new Array();
	var last_id = 100;
	var id = -1;
	var max = -1;
	var input_id = "";						
	var sugg_cont = "";		
	this.not_chosen = true;
	this.if_select = false;
	this.obiekt = "";

	/**
	* Ustawienie stylow dla pola z podpowiedziami.
	*/
	function setSuggContStyles ( sc ) {
		
		// Tego lepiej nie zmieniac
		sc.style.display = "none";
		sc.style.position = "absolute";
		sc.style.zIndex = "1000";

		// To juz mozna zmieniac do woli 
		sc.style.width = "383px";
	//	sc.style.color = "#000000";
		sc.style.fontFamily = "tahoma";
		sc.style.fontSize = "12px";
		sc.style.backgroundColor = "#ffffff";
		sc.style.border = "1px solid #3b474f";	
		sc.style.top = "44px";
		sc.style.left = "172px";
		
		// Mozna tez dodawac swoje style, ktorych tutaj nie ma
		
		
	}

	/**
	* Ustawienie stylow dla jednej linii z podpowiedziami.
	*/
	function setLineStyles (  ) {
		
		var style = 'style="';
			// Tu mozna ustawiac style
			style += 'height: 25px;';
			style += 'line-height: 25px;';
			style += 'clear: both;';
			style += 'margin-left: 12px;';
			style += 'margin-right: 5px;';
			style += 'overflow: hidden;';
			style += 'cursor: pointer;';
			// koniec mozliwosci ustawiania styli
		style += '"';
		return style;
	}

	/**
	* Ustawienie stylow dla jednej linii z podpowiedziami, ktora jest aktualnie podswietlona.
	*/
	function setHighlightLineStyles ( element ) {
			
		element.style.backgroundColor = "#8095ad";
		element.style.color = "#ffffff";
	}

	/**
	* Funkcja inicjalizujaca zmienne rozpoczynajaca i dzialanie mechanizmu wyswietlania i obslugi podpowiedzi.
	*/
	this.initSuggestions = function ( in_id, suggestion_container, link, method, obj, event ) {

		// inicjalizacja zmiennych globalnych
		input_id = in_id;
		sugg_cont = document.getElementById(suggestion_container);
		url = link;
		obiekt = obj;
	
		// ustawienie opdowiednich styli
		if ( sugg_cont.style.display != "block" )
			setSuggContStyles(sugg_cont);
		
		if ( method == 'get' ) {
		
			if ( event )
				suggestGet ( url, event );
			else	 
				suggestGet ( url, window.event );
		}
		else {
		
			if ( event )
				suggestPost ( url, event );
			else	 
				suggestPost ( url, window.event );	
		}
			
	}

	/**
	* Funkcja ukrywa pole z podpowiedziami.
	*/
	this.hideSuggestions = function ( sc ) {
		if ( !this.if_select ) {
		
			document.getElementById(sc).style.display = "none";

			last_id = 100;
			id = -1;
		}
	}

	
	/**
	* Funkcja prywatna, mozliwa do wywolania tylko przez metody klasy Suggestion, 
	* ukrywa kontener z podpowiedziami.
	*/
	function privateHideSuggestions (  ) {
		
		if ( !this.if_select ) {
		
			sugg_cont.style.display = "none";
			input_id.focus();
			last_id = 100;
			id = -1;
		}
	}
	
	/**
	* Funkcja przekazuje do elementu input wybrana podpowiedz po kliknieciu myszka
	* na dana podpowiedz.
	*/
	this.selectByClickMouse = function ( chosen_div ) {
		
		input_id.value = chosen_div.innerHTML; 
		input_id.focus();
		sugg_cont.style.display = "none";
		last_id = 100;
		id = -1;
		if_select = false;
	}

	/**
	* Funkcja przekazuje do elementu input wybrana podpowiedz po wcisnieciu
	* klawisza 'enter' przy zaznaczeniu odpowiedniej podpowiedzi.
	*/
	function selectByClickEnter (  ) {
		
		if ( sugg_cont.style.display != "none" ) {
			chosen_div = document.getElementById('podp'+id);
			
			if ( chosen_div != null ) { 
				input_id.value = chosen_div.innerHTML; 
				input_id.focus();
				sugg_cont.style.display = "none";
				last_id = 100;
				id = -1;
			}
			else{
				sugg_cont.style.display = "none";
				last_id = 100;
				id = -1;
			}
		}
	}

	/**
	* Funkcja pokazuje podpowiedzi pobrane z bazy danych.
	*/
	function showSuggestions ( text ) {

		max = -1;
		var str = "";
		
		style = setLineStyles();
		
		sugg_cont.style.display = "block";
					
		suggestions = text.split("|!|");
		
		for ( var i = 0; i < suggestions.length; i++ ) 
			if ( suggestions[i].length > 0 ) {
				str += '<div id="podp'+i+'_zew" onmouseover="'+obiekt+'.highlightLine('+i+');" style="margin: 0px;">';
				str +=		'<div id="podp'+i+'" onmouseover="'+obiekt+'.if_select = true; '+obiekt+'.not_chosen = false;" onclick="'+obiekt+'.selectByClickMouse(this);" onmouseout="'+obiekt+'.if_select = false;" '+style+'>';
				str +=			suggestions[i];
				str +=		'</div>';
				str +=	'</div>';
				
				max = max+1;
			}
		sugg_cont.innerHTML = str;
	}
	
		
	/**
	* Funkcja wykorzystujaca techonologie AJAX do pobrania podpowiedzi z bazy danych.
	*/
	function suggestPost ( url, event ) {
		
		// IE
		if (event.which == null) {
			if ( event.keyCode == 38 || event.keyCode == 40 || event.keyCode == 13 || event.keyCode == 27 ) {
				movingIE(event);
				return;
			}
		}
		else if (event.which > 0) {
			if ( event.which == 38 || event.which == 40 || event.which == 13 || event.keyCode == 27 ) {
				movingOthers(event);
				return;
			}	  
		}
		
		if ( input_id.value.length > 1 ) {
			var Obj = false;
			
			if ( window.XMLHttpRequest ) {
				Obj = new XMLHttpRequest();
			}
			else if ( window.ActiveXObject ) {
				Obj = new ActiveXObject("Microsoft.XMLHTTP");
			}

			if ( Obj ) {
				Obj.open("post", url);
				Obj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
				Obj.onreadystatechange = function() {

					if ( Obj.readyState == 4 && ( Obj.status == 200 || Obj.status == 304) ) {
						if ( Obj.responseText.length > 0 ) { 
							showSuggestions(Obj.responseText);
						}
						else
							sugg_cont.style.display = "none";
					}		
				}
				Obj.send("string="+input_id.value);
			}
		}
	}

	function suggestGet ( url, event ) {
		
		// IE
		if (event.which == null) {
			if ( event.keyCode == 38 || event.keyCode == 40 || event.keyCode == 13 || event.keyCode == 27 ) {
				movingIE(event);
				return;
			}
		}
		else if (event.which > 0) {
			if ( event.which == 38 || event.which == 40 || event.which == 13 || event.keyCode == 27 ) {
				movingOthers(event);
				return;
			}	  
		}
			
		var Obj = false;
		
		if ( window.XMLHttpRequest ) {
			Obj = new XMLHttpRequest();
		}
		else if ( window.ActiveXObject ) {
			Obj = new ActiveXObject("Microsoft.XMLHTTP");
		}

		if ( Obj ) {
			Obj.open("get", url+encodeURIComponent(input_id.value));
			Obj.onreadystatechange = function() {

				if ( Obj.readyState == 4 && ( Obj.status == 200 || Obj.status == 304) ) {
					if ( Obj.responseText.length > 0 ) 
						showSuggestions(Obj.responseText); 
					else
						sugg_cont.style.display = "none";
				}		
			}
			Obj.send(null);
		}
	}
		
	/**
	* Funkcja zmienia wyglad aktualnie zaznaczonej podpowiedzi.
	*/
	this.highlightLine = function  ( curr_id ) {
		
		if ( last_id == 100 ) {
			setHighlightLineStyles(document.getElementById('podp'+curr_id+'_zew'));
		}
		else {
		
			document.getElementById('podp'+last_id+'_zew').style.backgroundColor = "#ffffff";
			document.getElementById('podp'+last_id+'_zew').style.color = "#000000";
			document.getElementById('podp'+last_id+'_zew').style.overflow = "hidden";
		
			setHighlightLineStyles(document.getElementById('podp'+curr_id+'_zew'));
		
		}
		last_id = curr_id;
	}

	/**
	* Funkcja wybiera na podstawie przechwyconego kodu wcisnietego klawisza ktora podpowiedz ma zostac zaznaczona.
	* Funkcja przeznaczona dla przegladarki IE.
	*/
	function movingOthers ( event ) {
			
		if ( event.which == 38 )
			moveUp();
		else if ( event.which == 40 )
			moveDown();
		else if ( event.which == 13 )
			selectByClickEnter();
		else if ( event.which == 27 )
			privateHideSuggestions();			
	}

	/**
	* Funkcja wybiera na podstawie przechwyconego kodu wcisnietego klawisza ktora podpowiedz ma zostac zaznaczona.
	* Funkcja przeznaczona dla przegladarek innych niz IE.
	*/
	function movingIE ( event ) {	
			
		if ( event.keyCode == 38 )
			moveUp();
		else if ( event.keyCode == 40 )
			moveDown();
		else if ( event.keyCode == 13 )
			selectByClickEnter();	
		else if ( event.keyCode == 27 )
			privateHideSuggestions();
	}

	/**
	* Funkcja zaznacza wyzsza podpowiedz  i odznaczna podpowiedz poprzednia.
	*/
	function moveUp (  ) {
		
		if ( last_id == 0 )
			id = max;
		else if ( (last_id - 1) >= 0 )
			id = last_id - 1;

		document.getElementById('podp'+last_id+'_zew').style.backgroundColor = "#ffffff";
		document.getElementById('podp'+last_id+'_zew').style.color = "#000000";
		not_chosen = false;
		setHighlightLineStyles ( document.getElementById('podp'+id+'_zew') );

		last_id = id;

	}

	/**
	* Funkcja zaznacza nizsza podpowiedz  i odznaczna podpowiedz poprzednia.
	*/
	function moveDown (  ) {
		
		if ( last_id == 100 ) {
			id = 0;
			setHighlightLineStyles ( document.getElementById('podp'+id+'_zew') );
			last_id = id;
			return;
		}
		else if ( (last_id + 1) <= max )
			id = last_id + 1;
		else
			id = 0;
			
		document.getElementById('podp'+last_id+'_zew').style.backgroundColor = "#ffffff";
		document.getElementById('podp'+last_id+'_zew').style.color = "#000000";
		not_chosen = false;
		setHighlightLineStyles ( document.getElementById('podp'+id+'_zew') );
			
		last_id = id;
		
	}

	this.checkEnter = function (  ) {

		if ( sugg_cont.style.display == "none" || not_chosen )
			return true;
		else
			return false;

	}

}
  
 
 