/**
 * Ten plik jest częścią pakietu SOWA-WWW. Ten plik jest częścią pakietu SOWA-WWW.
 *
 * Plik JavaScript obsługujący formularze z kryteriami
 *
 * @package SOWA-WWW 
 * @author Michał Fryska
 * @copyright SOKRATES-Software (http://www.sokrates.pl)
 * 
 * $Id: formz.js 138 2009-04-29 07:35:33Z szumek $
 */

function memoKeyPress(event) {
	var ns = ((document.layers || document.getElementById) && (!document.all));
	var ie = document.all;
	event || (event = window.event);
	var keyCode = (ie) ? event.keyCode : event.which;
	
	if (keyCode == 13) {
		if (ns)	obj = document.getElementById('ff');
		else obj = f;
		if ( CheckAndSubmit() )
			obj.submit();
		return false;
	}
}

/**
 * Konstruktor.
 * @param formName Nazwę formularza HTML w którym się znajduuje nasz form.
 * @param advpos Pozycja kryteriów zaawansowanych (tab lub bottom)
 */
function SowwwaFormz(formName, advpos) {
	/** Nazwa obiektu */
	this.selfName;
	/** Nazwa formularza */
	this.formName = formName;
	/** Lokalizacja kryteriów zaawansowanych */
	this.advpos = advpos;
	/** Referencya do obiektu formularza HTML */
	this.formObject;
	/** nazwa bazy danych [dość potrzebne w jednym krytycznym momencie] */
	this.baseName;
	/** Tablica dostępnych kryteriów [każdy element to tablica array(nazwa_kryterium, tytuł_kryterium, czy_włączone, czy_zaawansowane, human_alg) */
	this.crittab;
	/** Tablica dobrych indeksów [KHW] */
	this.kwhIndexes;
	/** Nazwa elementu zawierającego podsumowanie [opis] */
	this.summarySpanName;
	/** Referencya do owego obiektu */
	this.summarySpanObject;
	/** Tablica do odpowiedniej obsługi zdarzenia onChange dla combosów. */
	this.onChangeTab;
	/** Tablica z maskami, które trzeba skontrolowac [fieldy] przed wysłaniem. */
	this.maskFieldsTab;

	this.init();
}

/**
 * Inicjalizuje nasz obiekt.
 */
SowwwaFormz.prototype.init = function() {
	this.formObject = document.getElementById(this.formName);
	this.crittab = new Array();
	this.khwIndexes = new Array();
	this.onChangeTab = new Array();
	this.maskFieldsTab = new Array();
}

/**
 * Rejestruje siebie samego - swoją nazwę w swoich strukturach.
 * @param String selfName Nazwa siebie samego
 */
SowwwaFormz.prototype.registerSelf = function(selfName) {
	this.selfName = selfName;
}

/**
 * Ustawia nazwę bazy danych. Dość istotna operacja, polecam robić to od razu po selfrejestracji.
 * @param String baseName Nazwa bazy SOWY [np. SOWA1, SOWA2, SOWA3]
 */
SowwwaFormz.prototype.setBaseName = function(baseName) {
	this.baseName = baseName;
}

/**
 * Ustawia nazwę elementu [span'a], który ma zawierać opis "human form" podsumowania.
 * @param String spanName Nazwa spanu
 */
SowwwaFormz.prototype.setSummaryItem = function(spanName) {
	this.summarySpanName = spanName;
	this.summarySpanObject = document.getElementById(this.summarySpanName);
}

/**
 * Rejestruje kryterium. Nazwę i tytuł kryterium, oraz boolean czy ma ono być od razu
 * domyślnie oznaczone jako używane, czy tez nie.
 * @param String critName Nazwa kryterium
 * @param String critTitle Tytuł [opis] kryterium
 * @param Bool used Informacja, czy kryterium jest w użyciu, czy nie :)
 */
SowwwaFormz.prototype.registerCriterium = function(critName, critTitle, used) {
	this.crittab.push( new Array(critName, critTitle, used, (this.crittab.length > 0), new Array()) );
}

/**
 * Rejestruje "dobry" indkes KHW - dla takiego indeksu będzie wyświetlany button [o ile się pojawi na formularzyku]
 * @param String indexName Nazwa indeksu
 * @param String khw Symbol KHW
 */
SowwwaFormz.prototype.registerKHWIndex = function(indexName, khw) {
	this.khwIndexes.push( new Array(indexName, khw ));
}

/**
 * Rejestruje kontrolki indkesu jako takiego
 * @param String comboName Nazwa kombo boxa obsługującego indeks
 * @param String buttonName nazwa przycisku wywzwalającego okienko z indeksem
 * @param String editName Nazwa pola, w którym edytuje się treść kryterium, celem umieszczenia tam wybranych pozycji z indeksu.
 */
SowwwaFormz.prototype.registerIndexControls = function(comboName, buttonName, editName) {
	if ( this.baseName != 'SOWA3' )
		this.onChangeTab.push( new Array( comboName, buttonName, editName ) );
}

/**
 * Rejestruje kontrolkę z maską, którą będzie trzeba skontrolować przez wysłaniem formsa.
 * @param String critName Nazwa kryterium
 * @param String controlName Nazwa kontrolki
 */
SowwwaFormz.prototype.registerMaskField = function(critName, controlName) {
	this.maskFieldsTab.push( new Array(critName, controlName) );
}

/**
 * Ustawia wpis do algorytmu obliczania human formsa, czyli czytelnego dla ludzia opisu kryterium.
 * Co to oznacza - otóż jeśli method jest 'value' to sprawdza wartość elementu i wyświetla ją.
 * Jeśli method jest 'check', to sprawdza czy element jest zaznaczony i jeśli tak - wyświetla
 * staticText. Aderłajz - wyświetla staticText.
 * @param String critName Nazwa Kryterium
 * @param String itemName Nazwa elementu formularza
 * @param String method Sposób generowania formy czytelnej dla człeka
 * @param String staticText Tekst statyczny wyświetlany gdy method tak nakazuje.
 */
SowwwaFormz.prototype.setHumanFormAlg = function(critName, itemName, method, staticText) {
	for (var i=0; i<this.crittab.length; i++)
		if (this.crittab[i][0] == critName) {
			this.crittab[i][4].push( new Array(itemName, method, staticText) );
		}
}

/**
 * Zwraca czytelny dla człowieka opis kryterium na podstawie algorytmu ustawionego wcześniej.
 * @param String critName Nazwa kryterium
 * @return String Czytelny tekst opisu kryterium
 */
SowwwaFormz.prototype.getCriteriumHumanForm = function(critName) {
	var description = '';
	for (var i=0; i<this.crittab.length; i++)
		if (this.crittab[i][0] == critName ) {
			var alg = this.crittab[i][4];
			for (var j=0; j<alg.length; j++) {
				if (alg[j][1] == 'value') {
					var item = document.getElementById(alg[j][0]);
					if (item.value == '') description += ' <i>brak</i>';
					else description += ' '+item.value.replace(/</g,"&lt;").replace(/>/g,"&gt;");
				}
				else if (alg[j][1] == 'check') {
					var item = document.getElementById(alg[j][0]);
					if (item.checked)
						description += ' '+alg[j][2];
				}
				else { // W domyśle static lub cokolwiek innego
					description += ' '+alg[j][2];
				}
			}
			break;
		}
	return description;
}

/**
 * Uaktualnia podsumowanie formularza - czytelne dla człowieka podsumowanie wprowadzonych kryteriów.
 */
SowwwaFormz.prototype.updateSummary = function() {
	if (this.summarySpanObject) {
		var innerHTML = '<b>Użyte kryteria</b><ol style="margin-top: 0px;">';
		var counter = 0;
		for (var i=0; i<this.crittab.length; i++) {
			var critname = this.crittab[i][0];
			var checkbox = document.getElementById('chk_'+critname);
			// Jeśli nie ma checkbox'a, to znaczy że kryterium jest niewyłączalne, więc zakładamy, że jest "kliknięte"
			if ( !checkbox || checkbox.checked ) {
				counter++;
				innerHTML += '<li>';
				
				if (this.crittab.length > 1) {
					innerHTML += '<a href="#" onClick="'+this.selfName+'.removeCriterium(\''+critname+'\')">';
					innerHTML += '<img src="img/usun.png" border="0" style="vertical-align:text-bottom;"/></a>';
				}
				innerHTML += '<b><a href="#" onClick="'+this.selfName+'.activateCriteriaEditor(\''+critname+'\')">'+this.crittab[i][1]+'</a>:</b> ';
				innerHTML += this.getCriteriumHumanForm(critname)+'</li>';
			}
		}
		innerHTML += '</ol>';
		if ( counter == 0 ) innerHTML = '';
		this.summarySpanObject.innerHTML = innerHTML;
	}
}


/**
 * Zwraca opis kryterium o podanej nazwie.
 * @param String critName Nazwa kryterium
 * @return String Opis kryterium
 */	
SowwwaFormz.prototype.getCriteriumDescription = function(critName) {
	for (var i=0; i < this.crittab.length; i++)
		if (this.crittab[i][0] == critName) return this.crittab[i][1];
	return 'Błąd: nieznane kryterium! '+critName;
}


/**
 * Czyści formularz wskazanego kryterium. [usuwa zeń wartości]
 * @param String critName Nazwa kryterium
 */
SowwwaFormz.prototype.clearForm = function(critName) {
	var prefix = critName+'-';
	for (var i=0; i < this.formObject.elements.length; i++) {
		e = this.formObject.elements[i];
		if ( e.name.substr(0,prefix.length) == prefix) {
			if (e.tagName == 'SELECT' )			e.selectedIndex = 0;
			else if (e.type == 'checkbox')		e.checked = false;
			else if (e.tagName != 'BUTTON')		e.value = '';
		}
	}
}

/**
 * Deaktywuje edytory WSZYSTKICH kryteriów.
 */
SowwwaFormz.prototype.deactivateCriteriaEditors = function() {
	for ( var i = 0; i < this.crittab.length; i++ ) {
		var div = document.getElementById('div_'+this.crittab[i][0]);
		div.style['visibility'] = 'hidden';
		this.showHideButtons(this.crittab[i][0], false);
	}
}

/**
 * Aktywuje edytor kryterium o podanej nazwie.
 * @param String critName Nazwa kryterium
 */
SowwwaFormz.prototype.activateCriteriaEditor = function(critName) {
	this.deactivateCriteriaEditors();
	var base_tab = document.getElementById('basic_tab');
	if (critName == '') {
		base_tab.style['visibility'] = 'visible';
		var div = base_tab;
	}
	else {
		base_tab.style['visibility'] = 'hidden';
		div = document.getElementById('div_'+critName);
		div.style['visibility'] = 'visible';
		this.showHideButtons(critName, true);
		
		// Nim pokażemy taba edycyjnego odhaczemy fakt włączenia kryterium.
		var checkbox = document.getElementById('chk_'+critName);
		checkbox.checked = true;
		
		// Span:
		span = document.getElementById('span_'+critName);
		span.innerHTML = '<b>'+this.getCriteriumDescription(critName)+'</b>';
	}
	// Powyższy div jest usytuowany w tabberze!
	// To jest tab pokazywany/chowany - nam zależy na divie głównym - tabberlive;
	var tabberlive = div.parentNode.parentNode;
	tabberlive.tabber.tabShow(0);
	
	this.updateSummary();
}

/**
 * Usuwa kryterium z listy aktywnych i oczywiście deaktywuje jej edytor [aktywując inny]
 * @param String critName Nazwa kryterium
 */
 SowwwaFormz.prototype.removeCriterium = function(critName) {
 	if ( confirm('Na pewno chcesz wyłączyć kryterium \''+this.getCriteriumDescription(critName)+'\'?')) {
 		// Nim pokażemy taba edycyjnego odhaczemy fakt włączenia kryterium.
 		var checkbox = document.getElementById('chk_'+critName);
 		checkbox.checked = false;
 
 		// Span:
 		var span = document.getElementById('span_'+critName);
 		span.innerHTML = this.getCriteriumDescription(critName);
 		
 		this.clearForm(critName);
 
 		// A na koniec musimy zdecydować się które kryterium aktywować - najlepiej pierwsze z brzegu!
 		var newcrit = '';
 		for (var i=0; i<this.crittab.length; i++) {
 			checkbox = document.getElementById('chk_'+this.crittab[i][0]);
 			if ( checkbox && checkbox.checked ) {
 				newcrit = this.crittab[i][0];
 				break;
 			}
 		}
 
 		this.activateCriteriaEditor(newcrit);
 	}
 }
 
 /**
  * Inicjuje edytory kryteriów na wypadek, gdyby to był reenter [trzeba odhaczyć zaznaczone],
  * tudzież aktywuje domyślny [pierwszy] jeśli to nie był reenter.
  */
SowwwaFormz.prototype.initCriteriaEditors = function() {
	// czyścimy - bo Firefox zachowuje niepotrzebnie zaznaczenia checkboxów.
	if (this.advpos == 'tab') {
		var critname;
		var found = false;
		for ( var i = 0; i < this.crittab.length; i++) {
			var checkbox = document.getElementById('chk_'+this.crittab[i][0]);
			if (this.crittab[i][2]) {
				checkbox.checked = true;
				if ( !found ) {
					found = true;
					critname = this.crittab[i][0];
					var div = document.getElementById('div_'+critname);
					div.style['visibility'] = 'visible';
				}
			}
			else
				checkbox.checked = false;
		}
		if ( !found ) {
			// Oznacza to zatem, że winniśmy włączyć pierwsze - domyślne kryterium.
			critname = this.crittab[0][0];
			var checkbox = document.getElementById('chk_'+critname);
			checkbox.checked = true;
			var div = document.getElementById('div_'+critname);
			div.style['visibility'] = 'visible';
		}
		var base_tab = document.getElementById('basic_tab');
		base_tab.style['visibility'] = 'hidden';
		this.showHideButtons(critname, true);
	}
	else if (this.advpos == 'bottom') {
		for (var i = 0; i < this.crittab.length; i++) {
			if (this.crittab[i][3]) { // Jeśli zaawansowane jeno.
				var checkbox = document.getElementById('chk_'+this.crittab[i][0]);
				var div = document.getElementById('epr_'+this.crittab[i][0]);
				checkbox.checked = this.crittab[i][2];
				set_display(div, this.crittab[i][2]);
			}
			this.showHideButtons(this.crittab[i][0], true);
		}
	}
	
	this.updateSummary();
}

/**
 * Przełącza kryterium (czyli włącza tudzież wyłącza)
 * @param {String} critName Nazwa kryterium
 */
SowwwaFormz.prototype.switchCriteriaEditor = function(critName) {
	for (var i = 0; i < this.crittab.length; i++ ) {
		if (this.crittab[i][0] == critName) {
			var checkbox = document.getElementById('chk_'+this.crittab[i][0]);
			if (checkbox) {
				var div = document.getElementById('epr_'+this.crittab[i][0]);
				var nval = ! this.crittab[i][2];
			
				checkbox.checked = nval;
				set_display(div, nval);
				this.crittab[i][2] = nval;
			}
			break;
		}
	}
}

/**
 * Pobiera symbol KHW dla wartości z podanego combosa. Z uwagi na to, że inaczej działa SOWA3 a inaczej inne,
 * koniecznie trzeba mieć ustawione this.baseName
 * @param String comboName Nazwa combosa
 * @return String Symbol KHW
 */
SowwwaFormz.prototype.getKHW = function(comboName) {
	var comboCtrl = document.getElementById(comboName);
	var khw = '';
	if ( this.baseName == 'SOWA3' ) {
		khw = comboCtrl.value;
	}
	else {
		for (var i=0; i< this.khwIndexes.length; i++)
			if (this.khwIndexes[i][0] == comboCtrl.value)
				khw = this.khwIndexes[i][1];
	}
	return khw;
}

/**
 * Pokazuje/chowa przycisk związany z podanym combosem, o ile wartość KHW jest niepusta, czyli że istnieje indeks.
 * @param String buttonName Nazwa przycisku
 * @param String comboName nazwa combosa
 */
SowwwaFormz.prototype.showHideButton = function(buttonName, comboName) {
	var comboObj = document.getElementById(comboName);
	var buttonObj = document.getElementById(buttonName);
	var khw = this.getKHW(comboName);
	if (khw == '')
		buttonObj.style['visibility'] = 'hidden';
	else
		buttonObj.style['visibility'] = 'visible';
}

/**
 * Wykonuje operacje takie, aby pokazać/ukryć przycisk dla indeksu w odpowiednich momentach, 
 * gdy obiekt o podanym ID zmienia swój stan.
 * @param String objectId Identyfikator obiektu
 */
SowwwaFormz.prototype.processOnChangeIndex = function(objectId) {
	for (var i = 0; i < this.onChangeTab.length; i++ ) {
		if (objectId == this.onChangeTab[i][1]) {
			this.showHideButton(this.onChangeTab[i][0], this.onChangeTab[i][1]);
			break;
		}
	}
	
	// c@8-A.1 może był kliknięt, wtęczasz cza zaaktywować kryterium, jeśli jest to tryb bottomowy
	if (this.advpos == 'bottom') {
		for (var i = 0; i < this.crittab.length; i++) {
			crit_name = this.crittab[i][0];
			if (!this.crittab[i][2] && objectId.indexOf(crit_name) == 0) {
				this.switchCriteriaEditor(crit_name);
				break;
			}
		}
	}
}

/**
 * Pokazuje/ukrywa wszystkie przyciski zapodanego kryterium. Jeśli visibility jest false,
 * to chowa wszystkie, jeśli true - to pokazuje tylko te, które warto.
 * @param String critName Nazwa kryterium
 * @param Bool visibility Czy pokazać, czy schować przyciski (TRUE pokazać)
 */
SowwwaFormz.prototype.showHideButtons = function(critName, visibility) {
	for (var i = 0; i < this.onChangeTab.length; i++ ) {
		if (this.onChangeTab[i][0].substr(0,critName.length) == critName) {
			if ( visibility ) {
				this.showHideButton(this.onChangeTab[i][0], this.onChangeTab[i][1]);
			}
			else {
				var buttonObj = document.getElementById(this.onChangeTab[i][0]);
				buttonObj.style['visibility'] = 'hidden';
			}
		}
	}
}

/**
 * Sprawdza, czy choć jedno kryterium zostało właściwie wypełnione i czy można posłać formularz zapytania.
 * @return Bool TRUE jeśli jest OK.
 */
SowwwaFormz.prototype.isFormFilled = function() {
	var isOK = false;
	for (var i = 0; i < this.crittab.length; i++) {
		var checkbox = document.getElementById('chk_'+this.crittab[i][0]);
		var hidinput = document.getElementById('hid_'+this.crittab[i][0]);
		// Jeśli checkboxa nie ma, to uznajemy że to jest wiecznie włączone kryterium
		if (hidinput || (checkbox && checkbox.checked)) {
			var isvalueset = false;
			var isnonselect = false;
			// Teraz musimy dla danego kryterium sprawdzić, czy choć jeden element został zaznaczony!
			var prefix = this.crittab[i][0]+'-';
			for (var j=0; j < this.formObject.elements.length; j++) {
				e = this.formObject.elements[j];
				if ( e.name.substr(0,prefix.length) == prefix) {
					if (e.tagName) {
						if (e.tagName != 'SELECT' && e.tagName != 'BUTTON' ) {
							isnonselect = true;
							if (e.type == 'checkbox') {
								if (e.checked)
									isvalueset = true;
							}
							else if (e.type != 'hidden' && e.value.trim() != '')
								isvalueset = true;
						}
					}
				}
			}
			if (!isnonselect || isvalueset) {
				isOK = true;
				if (hidinput) hidinput.value="1";
			}
			else {
				if (checkbox && checkbox.checked) {
					checkbox.checked = false;
					this.crittab[i][2] = false;
					// Jeśli byśmy chcieli też zamknąć taba, to trzeba zrobic to.
				}
				if (hidinput) hidinput.value="0";
			}
		}
	}
	
	return isOK;
}

/**
 * Sprawdza, czy pola masek są właściwie wypełnione. Jeśli nie są to krzyczy i ustawia się na błędnej 
 * masce.
 * @return Bool TRUE jeśli maski sa OK
 */
SowwwaFormz.prototype.checkMasks = function() {
	for (var i=0; i < this.maskFieldsTab.length; i++ ) {
		var checkbox = document.getElementById('chk_'+this.maskFieldsTab[i][0]);
		if ( checkbox.checked ) {
			var control = document.getElementById(this.maskFieldsTab[i][1]);
			if ( !control.maskEdit.isValidValue() ) {
				alert('Wartość \''+control.maskEdit.getText()+'\' nie jest prawidłowa dla tego pola.');
				if (this.advpos == 'tab') {
					this.activateCriteriaEditor(this.maskFieldsTab[i][0]);
				}
				control.focus();
				return false;
			}
		}
	}
	return true;
}
