/* 
biblioteka funkcji obsługi formularzy
autor: Andrzej Cuber
wersja 0.5 prace rozpoczęto Listopad 2003
ostatnia aktualizacja Pa?dziernik 12, 2006 roku

uwaga:
1. Funkcje obsługi pól o warto¶ciach rzeczywistych bazuj± na separatorach 
tysięcznych w postaci ".", a separatorach dziesiętnych w postaci ",".
2. Mimo sparametryzowania warto¶ci dokładno¶ci czyli formatowania 
do okre¶lonej ilo¶ci miejsc dziesiętnych to funkcje były tak pisane,
że miejsc dziesiętnych jest 2.

todo:
dopracować wypełnianie liczb rzeczywistych zgodnie z zadan± precyzj±
opracować przetwarzanie liczb ujemnych
sparametryzować rodzaje znaków separatorów tysięcznych i dziesiętnych

historia zmian:

2006-10-12: dodano funkcje get_value_type oraz format_float

2004-03-29:	poprawka błędu polegaj±ca na dodawaniu 1900 do roku daty
			pod windowsami

2004-01-21:	dodano funkcje: 
			get_text_as_numeric_value: która zamienia warto¶ć tekstow± pola
			na jej numeryczny odpowiednik potrzebny podczas obliczeń 
			na formularzu
			get_numeric_value_as_text: która przygowouje warto¶ć numeryczn±
			pola do warto¶ci tekstowej, która może zostać poddana daleszemu
			formatowaniu jako poprawna warto¶ć pola
			get_selected_value: zwraca wybran± warto¶ć z pola select 
		
			dodano obsługę pól typu "select"
		
2004-01-20:	do funkcji validate_keystrokes dodano zmienn± theForm,
			która reprezentuje formularz, na którym umieszczone jest 
			dane pole.

*/

var dt_any = 0 // dt - data type
var dt_text = 1
var dt_integer = 2
var dt_signed_integer = 3
var dt_float = 4
var dt_signed_float = 5
var dt_date = 6
var decimal_precission = 2 

function find_next_field_index (theFormName, theField) {
// funkcja zwraca index następnego elementu w kolekcji form.elements
// w stosunku do nazwy bieżšcego pola

var i=0
var found = false
var fieldIndex = i

//	alert ("formularz: "+ theFormName + " pole: " + theField.name)

	while (!found) {
		if (document.forms[theFormName].elements[i].name == theField.name) {
			found = true
			
			// czy nie osiagnieto końca listy elementów
			// jezeli tak, to focus należy postawić na pierwszym,
			// który nie jest ukryty

			if (i != (document.forms[theFormName].elements.length - 1))
				fieldIndex = i+1
			else {
				// aby nie postawić focusu na elemencie ukrytym
				// to należy przej¶ć listę elementów formularza
				// od pocz±tku i znaleĽć takie pole, którego 
				// typ nie jest hidden
				i = 0
				while (document.forms[theFormName].elements[i].type == "hidden") i++
				fieldIndex = i
			} // if (i == (theForm.elements.length - 1))

		} // if (theForm.elements[i].name == theField.name)
		i++
	} // while (!found)
	
	return fieldIndex

} // function find_next_field_index (theField) 

function validate_keystrokes (theForm, theField, e, dataType) {
// funkcja ogranicza zakres znaków, jakie mog± zostać wpisane w pole
// w zależno¶ci od typu danej, jakie to pole może przechowywać
// funkcja zwraca true jeżeli znak jest poprawny lub false jeżeli nie jest
// e - event
// theForm - formularz, do którego należy dane pole theField

// var ctrlKey = (navigator.appName == "Netscape") ? theEvent.modifiers & Event.CONTROL_MASK : theEvent.ctrlKey
var charCode = (navigator.appName == "Netscape") ? e.which : e.keyCode
var typedChar = String.fromCharCode (charCode) // klaiwsz jako znak

// analiza naci¶niętych klawiszy 

//	window.status = theForm // debug do skasowania

	// alert (theForm)

	// tabulator 
	if (charCode == 9) 
		if (format_field (theField, dataType)) {
			return true
		}
		else {
			theField.select()
			return false
		} // of else of if (format_field (theField, dataType))
	
	// enter
	if (charCode == 13) 
		if (format_field (theField, dataType)) {
			next_field_index = find_next_field_index (theForm.name, theField) 
		 	document.forms[theForm.name].elements[next_field_index].focus()
			return true
		} // if (format_field (theField, dataType))
		else {
			theField.select()
			return false
		} // of else of if (format_field (theField, dataType))

	// esc 
	if (charCode == 27) {
		// przywrócenie pocz±tkowej warto¶ci pola
		theField.value = theField.defaultValue
		theField.select()
		return true 
	} //  
    
	// pozostałe znaki sterujšce, strzałki, backspace, del 
	if (charCode < 31) return true 
		
	// badanie typu pola
	// i okre¶lenie zakresu znaków jakie mog± zostać użyte podczas
	// wprowadzania danych
	// oczywi¶cie wszystkie poniższe działania maj± sens tylko w przypadku
	// pól typu "text"

	if ((dataType == dt_any) || (theField.type != "text"))
		
		return true
		
	else {

		switch (dataType) {
			
			case dt_integer:
				var re = /[0-9]/
				break
				
			case dt_signed_integer:

				// todo: dopisać obsługę podwójnego minusa
			
				if ((typedChar == "-") && (theField.value.indexOf ("-") != -1))
					var re = /[0-9\-]/
				
				break
				
			case dt_float:
				var re = /[0-9,]/

				// zapobieganie podwójnemu minusowi
				if ((typedChar == ",") && (theField.value.indexOf (",") != -1))
					var re = /[0-9]/
				break
				
			case dt_signed_float:

				// todo: dopisać obsługę podwójnego minusa i przecinka
				var re = /[0-9,\-]/
			
				if ((typedChar == "-") && (theField.value.indexOf ("-") != -1))
					var re = /[0-9,]/
					
				if ((typedChar == ",") && (theField.value.indexOf (",") != -1))
					var re = /[0-9\-]/
					
				break
				
			case dt_date:
				var re = /[0-9\-]/
				break 
				
			default:
				break
		} // switch (fld_type) 

		// test czy wpisany znak spełnia podany zakres okre¶lony przez re
		
		if (re.test(typedChar)) 
			return true
		else
			return false  

	} // if (dataType == dt_any)
	
} // function validate_keystrokes (theField, theEvent, dataType) 

function add_1000_separator (number_as_text) {
// funkcja dodaje separatory tysięczne do liczby podanej jako tekst 
// np. #######,00 -> #.###.###,00

var re=/(-?\d+)(\d{3})/

	while (re.test(number_as_text)) {
			number_as_text = number_as_text.replace (re, "$1\.$2")
    } // while (re.test(field_value))

	return number_as_text

} // function format_as_number (theNumber) 

function remove_1000_separator (number_as_text) {
// funkcja usuwa separatory tysięczne z tekstu podanego jako numer
var re=/\./g
 	number_as_text = number_as_text.replace(re, "")

	return number_as_text

} // function Remove_1000_separator (theNumber)

function unformat_field (theField) {
// funkcja deformatuje zawarto¶ć pola któr± stanowi liczba

	theField.value = remove_1000_separator (theField.value)
	theField.select()
} // function unformat_field (theField)

function set_text_as_float_number (number_as_text) {
// funkcja analizuje tre¶ć numeryczn± pola tekstowego
// wzbogacaj±c go o wszelkie elementy czyni±cego z niego
// liczbę zmienno przecinkow± 
	
	// okre¶lenie pozycji miejsca dziesiętnego - przecinka w warto¶ci
	decimal_pos = number_as_text.indexOf(",")
	
	// test na podanie jakiej kolwiek warto¶ci do pola
	// jeżeli nie to zwrócić 0,00
	if (number_as_text == "")
		number_as_text = "0,00"
	else {
		
		// test na istnienie przecinka w zawarto¶ci pola 
		if (decimal_pos == -1) // nie ma przecinka
			number_as_text = number_as_text + ",00" // uzupełnienie 
		else {
			
			// test na istnienie przecinka na 0 (pierwszym) miejscu w
			// warto¶ci, co należy uzupełnić zerem
			if (decimal_pos == 0) {
				number_as_text = "0" + number_as_text

				// okre¶l now± pozycję decimal_pos
				decimal_pos = number_as_text.indexOf(",")
			} // if (decimal_pos == 0)
			
			// obliczenie miejsca, na którym znajduje się separator
			// dziesiętyny, co pozwoli dopisać odpowiedni± ilo¶ć zer
			decimal_length = (number_as_text.length - 1) - decimal_pos

			if (decimal_length < decimal_precission) 
				for (i=decimal_length + 1; i<=decimal_precission; i++)
					number_as_text = number_as_text + "0"

		} // of else of if (decimal_pos == -1)

	} // of else if (number_as_text == "")

	return number_as_text

} // function set_text_as_float_number (number_as_text)

function get_value_type(theValue)
// funkcja zwraca nazwŤ rodzaju wartosci przechowywan? przez dan? zmienn?
{
	return (typeof(theValue));
}

function format_float (float_value)
// funkcja formatuje wartoć? tekstow? podan? jako zmiennoprzecinkow?
// do postaci tekstowej zamieniaj?c kropki na przecinki oraz dodaje separatory 
// tysiŤczne
{
	// badanie czy podana wartoć? wymaga konwersji na text
	if (get_value_type(float_value) == "number")
		float_value = float_value.toString();

	// przygotowanie warto¶ci numerycznej pola tekstowego
	float_value = set_text_as_float_number (float_value)
	
	// zamiana przecinka na kropkę
	re = /,/
	numeric_value = float_value.replace (re, ".")
	
	// zamień warto¶ć tekstow± na zmienno przecinkow± 
	numeric_value = parseFloat (numeric_value)
	
	// przesunięcie przecinka o 2 miejsca w prawo
	numeric_value = numeric_value * Math.pow(10, decimal_precission)
	
	// zaokr±glenie otrzymanej warto¶ci
	numeric_value = Math.round (numeric_value)
	
	// przywrócenie warto¶ci pocz±tkowej
	numeric_value = numeric_value / Math.pow (10, decimal_precission)
	
	// zamiana warto¶ci numerycznej na tekstow±
	text_value = numeric_value.toString()
	
	// zamiana kropki na przecinek
	re = /\./
	text_value = text_value.replace (re, ",")
	
	text_value = set_text_as_float_number(text_value)			
	
	return add_1000_separator (text_value)
} // function format_float (float_value)

function format_field (theField, dataType) {
// funkcja formatuje zawarto¶ć pola, którego warto¶ć okre¶la dataType
// funkcja zwraca true jeżeli wprowadzone dane s± poprzwne lub false jeżeli
// nie s±

var ret_value = true;

	switch (dataType) {
	
		case dt_float: // dodatkowe formatowania pola zmienno przecinkowego
						
			theField.value = format_float (theField.value);

			// pole zostało sformatowane poprawnie i można przej¶ć do
			// nasępnego elemetu na formularzu
			
			ret_value = true	
			
			break // dt_float

		case dt_integer:
			if (theField.value == "") theField.value = "0"
			
			theField.value = add_1000_separator (theField.value)

			ret_value = true
			
			break // dt_integer

		case dt_date:
			var isValid = true
			// test czy data jest pusta
			if (theField.value == "") theField.value = "0000-00-00"

			if (theField.value != "0000-00-00") {
		
				// definicja wyrażenia regularnego, które sprawdzi 
				// czy wprowadzone dane maj± sens
				// var re = /\b(0?[1-9]|[12][0-9]|3[01])[\-\/](1[0-2]|0?[1-9])[\-\/]((19|20)\d{2})/
				var re = /\b((19|20)\d{2})[-](0[1-9]|1[012])[\-](0[1-9]|[12][0-9]|3[01])/

				/* wynik parsowania wyrażenia regularnego zapisywany jest
				w tablicy 'matchArray'
				[0] - cały ci±g = theField.value
				[1] - rok
				[2] - pocz±tek 2 cyfry roku
				[3] - miesi±c
				[4] - dzień miesi±ca
				*/

				var matchArray = re.exec(theField.value)
				if (matchArray) { // jeżeli wyrażenie regularne zadziałało

					// utworzenie obiektu date, który posłuży jako Ľródło dla
					// nowej daty
					var theDate = new Date(matchArray[1],matchArray[3]-1,matchArray[4])
					// różne przegl±darki różnie traktuj± datę, także systemy operacyjne
					if (theDate.getYear() < 2000)
						theYear = 1900 + theDate.getYear() 
					else
						theYear = theDate.getYear() 
					theMonth = theDate.getMonth() + 1 // styczeń = 0
					theDay = theDate.getDate()

					newDate = theYear
					
					if (theMonth < 10) // uwzględnienie zera 
						newDate = newDate + "-0" + theMonth
					else
						newDate = newDate + "-" + theMonth

					if (theDay < 10)
						newDate = newDate + "-0" + theDay
					else
						newDate = newDate + "-" + theDay
					
					theField.value = newDate

					ret_value = true

				} // if (matchArray)
				else {
						window.alert ("The given date is not valid!")
						
						ret_value = false 
						
					 }// of else of if (matchArray)
					
			} // if (theField.value != "0000-00-00")
			break // dt_date

		default:
			break
	
	} // switch (dataType)

	return ret_value
	
} // function format_field (theField)

function find_first_visible_field_index_in_form (theForm) {
/*
	funkcja zwraca nazwę pierwszego widocznego pola edycyjnego 
	na formularzu okre¶lonym przez theForm
*/
	i = 0
	var ret_value = i
	found = false
	while ((i != theForm.elements.length) && !found) {
		var theField = theForm.elements[i]
		if (! ( (theField.type == "hidden") || (theField.type == "submit") || (theField.type == "reset") || (theField.type == "button")) )
			found = true
		else 
			i++
	} // while (i != theForm.elements.length)
	ret_value = i
	
	return ret_value

} // function set_focus_on_first_visible_field_in_form (theForm)

function set_focus_on_first_visible_field() {
//	var theForm = document.forms[0]	
//	var theIndex = find_first_visible_field_index_in_form (theForm)
//	theForm.elements[theIndex].focus()
//	theForm.elements[theIndex].select()
} // function set_focus_on_first_visible_field()

function get_text_as_numeric_value (value_as_text) {
/* 
funkcja zamienia poprawnie sformatowan± warto¶ć pola tekstowego
jako warto¶ć zmiennoprzecinko±, na jest odpowiednik o warto¶ci numerycznej
czyli np. "3,14" => "3.14"
celem funkcji jest wykorzystanie jej podczas walidacji formularzy
oraz przeliczania warto¶ci nunerycznych na formularzach i aktualizacji 
znajduj±cych się tam pól

todo: 	dodać typ warto¶ci jako parametr funkcji i będzie osbługa 
		dla warto¶ci całkowitych

*/
	var numeric_value = 0.00

	// zamiana przecinka na kropkę
	var re = /,/

	// usunięcie separatorów tysięcznych 
	value_as_text = remove_1000_separator (value_as_text)
	
	// zamiana przecinka na kropkę 
	value_as_text = value_as_text.replace (re, ".")
			
	// zamień warto¶ć tekstow± na zmienno przecinkow± 
	numeric_value = parseFloat (value_as_text)

	return numeric_value

} // function get_text_as_numeric_value (value_as_text)

function get_numeric_value_as_text (numeric_value) {
// funkcja zamienia warto¶ć numeryczn± na warto¶ć tekstow± 
// co dalej może zostać przekazane do warto¶ci pola
// kropka dziesiętna zamieniana jest na przecinek

	var text_value = ""
	var re = /\./
	
	text_value = numeric_value.toString()
	text_value = text_value.replace (re, ",")

	return text_value

} // function get_numeric_value_as_text (numeric_value)

function get_selected_value (theForm, fieldName) {
// funkcja zwraca wybran± warto¶ć z pola typu select

	selectedValue = theForm.elements[fieldName].options[theForm.elements[fieldName].selectedIndex].value

	return selectedValue 
} // function get_selected_value (theForm, fieldName)

function testit() {
} // 
