/**
	pics.form.js
	Desc:	Framework zum Verarbeiten von Formularen

	basiert auf pics.base
	
	Author: Christian Grösswang
	
	20061227,gc - v0.01		Prototype + Test
	20071127,gc - v1.00		Bug bei RadioButtons mit convertParams behoben
	20080528,gc - v1.10		deleteFormRow erweitert
	20080712,gc - v1.11		neue funktion limitTextSize
**/




/*
	Funktionsübersicht 
	
	Form-Framework:
		pics.Form.init 			Framework initialisieren
		pics.Form.hasChanged		prüft, ob sich im Formular was geändert hat
		pics.Form.fieldHasChanged	prüft, ob das Feld geändert hat
		pics.Form.convert2Params	Erstellt aus allen Felder im Formular einen Parameter-String für die Übermittlung per POST/GET
		pics.Form.getDebugInfo		liefert Informationen zu allen Feldern eines Formulars
		pics.Form.limitTextSize		bschränkt die eingabe eines Textfelds auf X zeichen

*/


// Constructor, falls das PICS-Framework nicht geladen ist
	if (typeof pics == 'undefined') pics = {};

/* 
 *	====================================================================================
 *	===== FRAMEWORK: pics.Form 														====
 *	====================================================================================
 */

	// Constructor
	if (typeof pics.Form == 'undefined') pics.Form = {};

	// Variablen
	pics.Form.lastValue='';
	
	/**
	 * pics.Form.init()
	 *		Form-Basisobjekt initialisieren und Variablen vorbelegen
	 */
	pics.Form.init = function() 
	{
	} // pics.Form.init

	/**
	 * pics.Form.hasChanged()
	 *		prüft, ob sich der Inhalt des Formulars geändert hat
	 *	@param	string	pFormID		ID des zu prüfenden Formulars
	 *	@return	boolean	true/false
	 */
	pics.Form.hasChanged = function(pFormID)
	{
		// Formular holen
		oForm=document.getElementById(pFormID);
		if (!oForm) return false;
		aChanged=new Array();	// Array mit den geänderten Feldern
		// alle Elemente durchlaufen
		for (var i=0;i<oForm.elements.length;i++)
		{
			oElement=oForm.elements[i];
			// bei SELECT-FELDERN müssen wir die OPTION-Tags auswerten
			if (oElement.tagName=="SELECT")
			{
				lChanged=false;
				for (var j=0;j<oElement.options.length;j++)
				{	
					oOption=oElement.options[j];
					if (oOption.selected!=oOption.defaultSelected) lChanged=true;
				}
				if (lChanged) aChanged[aChanged.length]=oElement.name;
			}
			else
			{
				if ((oElement.value!=oElement.defaultValue) || (oElement.checked!=oElement.defaultChecked))
				{
					aChanged[aChanged.length]=oElement.name;
				}
			}		
		} // for
		if (aChanged.length>0) return true;
		return false;
	} // pics.Form.hasChanged
	
	
	/**
	 * pics.Form.fieldHasChanged()
	 *		prüft, ob sich der Inhalt des Formulars geändert hat
	 *	@param	object	pField		übergebenes Feld
	 *	@return	boolean	true/false
	 */
	pics.Form.fieldHasChanged = function(pField)
	{
		oElement=pField;
		lChanged=false;
		// bei SELECT-FELDERN müssen wir die OPTION-Tags auswerten
		if (oElement.tagName=="SELECT")
		{
			for (var j=0;j<oElement.options.length;j++)
			{	
				oOption=oElement.options[j];
				if (oOption.selected!=oOption.defaultSelected) lChanged=true;
			}
		}
		else
		{
			if ((oElement.value!=oElement.defaultValue) || (oElement.checked!=oElement.defaultChecked))
			{
				lChanged=true;
			}
		}
		return lChanged;
	} // pics.Form.fieldHasChanged
	
	
	/**
	 * pics.Form.markUnchanged()
	 *		setzt die aktuellen Werte als Default-Values, damit das Formular als ungeändert gilt
	 *	@param	string	pFormID		ID des zu prüfenden Formulars
	 *	@return	boolean	true/false
	 */
	pics.Form.markUnchanged = function(pFormID)
	{
		// Formular holen
		oForm=document.getElementById(pFormID);
		// alle Elemente durchlaufen
		for (var i=0;i<oForm.elements.length;i++)
		{
			oElement=oForm.elements[i];
			// bei SELECT-FELDERN müssen wir die OPTION-Tags auswerten
			if (oElement.tagName=="SELECT")
			{
				for (var j=0;j<oElement.options.length;j++)
				{	
					oOption=oElement.options[j];
					if (oOption.selected!=oOption.defaultSelected) oOption.defaultSelected=oOption.selected;
				}
			}
			else
			{
				if (oElement.value!=oElement.defaultValue) oElement.defaultValue=oElement.value;
				if (oElement.checked!=oElement.defaultChecked) oElement.defaultChecked=oElement.checked;
			}		
		} // for
		if (aChanged.length>0) return true;
		return false;
	} // pics.Form.markUnchanged
	
	
	/**
	 * pics.Form.convert2Params()
	 *		Erstellt aus allen Felder im Formular einen Parameter-String 
	 *		für die Übermittlung per POST/GET
	 *	@param	string	pFormID		ID des zu prüfenden Formulars
	 *	@param	boolean	pChangedOnly	nur geänderte Felder
	 *	@return	boolean	true/false
	 */
	pics.Form.convert2Params = function(pFormID, pChangedOnly)
	{
		if (typeof pChangedOnly == 'undefined') pChangedOnly=false;

		// Formular holen
		oForm=document.getElementById(pFormID);
		lParams="";

		// alle Elemente durchlaufen
		for (var i=0;i<oForm.elements.length;i++)
		{
			oElement=oForm.elements[i];
			// nur benannte Elemente
			if (oElement.name!='')
			{
				switch(oElement.type)
				{
					case "select-one":			// bei SELECT-FELDERN müssen wir die OPTION-Tags auswerten
					case "select-multiple":
						for (j=0;j<oElement.options.length;j++)
						{	
							oOption=oElement.options[j];
							if ((oOption.selected!=oOption.defaultSelected)  || (pChangedOnly==false)) 
							{
								if (oOption.selected) lParams+="&"+oElement.name+"="+encodeURIComponent(oOption.value);
							}
						}
						break;
					case "checkbox":			// bei CHECKBOXEN-FELDERN müssen wir die checked-Eigenschaft auswerten
					case "radio":			// bei RADIO-FELDERN müssen wir die checked-Eigenschaft auswerten
						if ((oElement.value!=oElement.defaultValue) || (oElement.checked!=oElement.defaultChecked) || (pChangedOnly==false))
						{
							if (oElement.checked) lParams+="&"+oElement.name+"="+encodeURIComponent(oElement.value);
						}
						break;
					default:
						if ((oElement.value!=oElement.defaultValue) || (oElement.checked!=oElement.defaultChecked) || (pChangedOnly==false))
						{
							lParams+="&"+oElement.name+"="+encodeURIComponent(oElement.value);
						}
				}	//switch tagName
			} // if name
		} // for
		return lParams;

	} // pics.Form.convert2Params
	

	/**
	 * pics.Form.addFormRow()
	 *		dazu wird die ausgeblendete Zeile mit pID gesucht und danach nochmal eingefügt
	 *	@param	string	pElementID	ID des Elements, in das die Debuginfo geschrieben wird
	 *	@param	string	pNewID		neue ID der Zeile
	 *	@return	
	 */
	pics.Form.addFormRow = function(pElementID, pNewID)
	{
		if (typeof pNewID == 'undefined') pNewID='';

		oElement=document.getElementById(pElementID);		// Zeile holen
		oNew = oElement.cloneNode(true);			// duplizieren
		oNew.id=pNewID;								// neue ID zuweisem
		oNew.style.display="";						// einblenden
		oElement.parentNode.insertBefore(oNew, oElement);	// vor der leeren einfügen	
	} // pics.Form.addFormRow


	/**
	 * pics.Form.addFormRowLimited()
	 *		dupliziert die angegebene Zeile, aber nur, wenn noch nicht mehr als pLimit Felder mit dem Namen pField existieren
	 *	@param	string	pElementID	ID des Elements, in das die Debuginfo geschrieben wird
	 *	@param	string	pField		Name des zu prüfenden Felds
	 *	@param	int		pLimit		Max. Anzahl der Felder
	 *	@return	string	HTML-Code mit Infos zum Formular
	 */
	pics.Form.addFormRowLimited = function(pElementID, pField, pLimit)
	{
		oField=document.getElementByName(pField);		// Feld holen
		if (oField.length<pLimit) pics.Form.addFormRow(pElementID);
	} // pics.Form.addFormRow


	/**
	 * pics.Form.deleteFormRow()
	 *		löscht die aktuelle Tabellenzeile
	 *	@param	string	pElement 	Element in der aktuellen Zeile
	 *	@param	string	pField		Feld mit dem Primary Key
	 *	@param	string	pNewValue	Wert der in das ID-Feld geschrieben wird, *-1 wenn nicht vorhanden
	 *	@param	bool	pConfirm	Fragen?
	 *	@return	bool true
	 */
	pics.Form.deleteFormRow = function(pElement, pField, pNewValue,pConfirm)
	{
		if (typeof pField == 'undefined') pField='';
		if (typeof pNewValue == 'undefined') pNewValue='--INVERT--';
		if (typeof pConfirm == 'undefined') pConfirm=true;
		
		if (pConfirm)
		{
			rc = confirm("Wollen Sie den Eintrag wirklich löschen?");
			if (rc==false) return false;
		}
	
		// 1.) übergeordnetes Zeilenelement finden
		oRow=pics.findParentID(pElement, "TR");
		oRow.style.display='none';
		// 2.) ID-Feld finden und reseten
		if (pField!='')
		{
			oField=pics.findElementsByName(oRow, pField);
			if (pNewValue=='--INVERT--')
			{
				oField.value=-oField.value;
			}
			else
			{
				oField.value=pNewValue;
			}
		}
		return true;
	} // pics.Form.deleteFormRow
	
	

	/**
	 * pics.Form.enterField()
	 *		merkt sich beim Betreten eines Feldes den aktuellen Wert, kann mit pics.Form.getOldValue abgefragt werden
	 *	@param	object	pField		Verweise auf das Feld
	 *	@return	
	 */
	pics.Form.enterField = function(pField)
	{
		pics.Form.lastValue='';
		if (pField.value) pics.Form.lastValue=pField.value;
	} // pics.Form.enterField

	/**
	 * pics.Form.getOldValue()
	 *		liefert den alten Wert des Feldes, der bei enterfield gemerkt wurde
	 *	@return	string	Wert
	 */
	pics.Form.getOldValue = function()
	{
		return pics.Form.lastValue=pField.value;
	} // pics.Form.getOldValue



	/**
	 * pics.Form.getDebugInfo()
	 *		liefert Informationen zu allen Feldern
	 *	@param	string	pFormID		ID des zu prüfenden Formulars
	 *	@param	string	pElementID	ID des Elements, in das die Debuginfo geschrieben wird
	 *	@return	string	HTML-Code mit Infos zum Formular
	 */
	pics.Form.getDebugInfo = function(pFormID, pElementID)
	{
		// durchläuft das Form und gibt alle Informationen im Layer divDebug aus
		oForm=document.getElementById(pFormID);
		lHtml="<table>";
		lHtml+='<tr bgcolor="#666666"><td>NAME</td><td>tagName / type</td><td>value / defaultValue</td><td>checked / defaultChecked</td></tr>';
	//	alert("Formular hat "+oForm.elements.length+" Elemente!");
		for (var i=0;i<oForm.elements.length;i++)
		{
			oElement=oForm.elements[i];
			// bei SELECT-Boxen geben wir auch noch die OPTIONS aus
			switch(oElement.type)
			{
				case "select-one":			// bei SELECT-FELDERN müssen wir die OPTION-Tags auswerten
				case "select-multiple":

					lStyle='';
					lHtml+='<tr'+lStyle+'><td>'+oElement.name+':'+'</td>';
					lHtml+="<td>"+"("+oElement.tagName+" / "+oElement.type+") "+"</td>";
					lHtml+="<td>"+oElement.value+" / "+oElement.defaultValue+"</td>";
					lHtml+="<td>"+oElement.checked+" / "+oElement.defaultChecked+"</td>";
					lHtml+="</tr>";
				
					for (j=0;j<oElement.options.length;j++)
					{	
						oOption=oElement.options[j];
						lStyle='';
						if (oOption.selected!=oOption.defaultSelected)  lStyle=' bgcolor="#66ffcc"';
						lHtml+='<tr'+lStyle+'><td>&nbsp;</td>';
						lHtml+="<td>&nbsp;</td>";
						lHtml+="<td>"+oOption.value+" / "+oOption.text+"</td>";
						lHtml+='<td>'+oOption.selected+" / "+oOption.defaultSelected+"</td>";
						lHtml+="</tr>";
					}
					break;
				default:
					lStyle='';
					if ((oElement.value!=oElement.defaultValue) || (oElement.checked!=oElement.defaultChecked)) lStyle=' bgcolor="#66ffcc"';
					lHtml+='<tr'+lStyle+'><td>'+oElement.name+':'+'</td>';
					lHtml+="<td>"+"("+oElement.tagName+" / "+oElement.type+") "+"</td>";
					lHtml+="<td>"+oElement.value+" / "+oElement.defaultValue+"</td>";
					lHtml+="<td>"+oElement.checked+" / "+oElement.defaultChecked+"</td>";
					lHtml+="</tr>";
				
			}	//switch tagName
		}
		lHtml+="</table>";
		// zurückgeben?
		if (typeof pElementID == 'undefined') return lHtml;
		// oder in Element ausgeben
		document.getElementById(pElementID).innerHTML=lHtml;		
	}	// pics.Form.getDebugInfo()

	
	/**
	 * pics.Form.setMarker(pField, pRowID, pMarker, pValue, pElementType)
	 *		setzt die Marker-Checkbox in der Zeile des Felds
	 *	@param	string	pElement	übergebenes Element/Feld
	 *	@param	string	pRowID		ID die gesucht wird
	 *	@param	string	pMarker		Name des Markerfelds, default ist fMarker[]
	 *	@param	mixed	pValue		zu setzender Wert. Default=true, null=wechsel
	 *	@param	string	pElementType	gesuchtes übergeordnetes Element, default = TR
	 *	@return	
	 */
	pics.Form.setMarker = function(pField, pRowID, pMarker, pValue, pElementType)
	{
		if (typeof pRowID == 'undefined') 	pRowID='';
		if (typeof pMarker == 'undefined') 	pMarker='fMarker[]';
		if (typeof pValue == 'undefined') 	pValue=true;
		if (typeof pElementType == 'undefined') 	pElementType='TR';

		// übergeordnete Zeile finden
		oParentTR=pics.findParentID(pField,pElementType,pRowID);
		// In dieser Zeile die Checkbox anhaken
		if (oParentTR) 
		{
			oMarker=pics.findElementsByName(oParentTR, pMarker);
			if (oMarker)
			{
				if (pValue==null) pValue=!oMarker.checked;
				oMarker.checked = pValue;	
			}
		}
	}	// pics.Form.setMarker


	/**
	 * pics.Form.checkAll(pForm,pField, pMarker)
	 *		setzt alle Checkboxen mit dem Namen pField auf den Wert der Box pMarker
	 *	@param	string	pForm		Name des Fomulars
	 *	@param	string	pField		Name des Fomularfelds
	 *	@param	string	pMarker		ID des Markers
	 *	@return	
	 */
	pics.Form.checkAll = function(pForm,pField, pMarker)
	{
		oForm=document.getElementById(pForm);
		lMarker=oForm.elements[pMarker].checked;
		for (var i=0;i<oForm.elements.length;i++)
		{
			oElement=oForm.elements[i];
			// bei SELECT-FELDERN müssen wir die OPTION-Tags auswerten
			if (oElement.name==pField)
			{
				oElement.checked=lMarker;
			}		
		} // for
	}	// pics.Form.checkAll


	/**
	 * pics.Form.save(pSaveHandler, pForm, pKey, pHideElement, pShowElement, pDebug)
	 *		Speichert das angegebene Form mit dem übergebenen Save-Handler und
	 *		schreibt die entsprechenden Werte zurück ins Formular
	 *	@param	string	pSaveHandler	URL zum SaveHandler
	 *	@param	string	pForm			Name des Formulars
	 *	@param	string	pKey			ID des Primary Key
	 *	@param	string	pHideElement	auszublendendes Element wenn erfolgreich
	 *	@param	string	pShowElement	einzublendendes Element wenn erfolgreich
	 *	@param	string	pDebug			Ebene für Debug-Ausgabe
	 *	@return	
	 */
	pics.Form.save = function(pSaveHandler, pForm, pKey, pHideElement, pShowElement, pDebug)
	{ 
		// wenn die Windows-Bibliothek vorhanden ist, dann zeigen wir das an
		lShowInfo=true;
		if (typeof pics.Form == 'undefined') lShowInfo=false;		
		if (typeof pHideElement == 'undefined') pHideElement='';		
		if (typeof pShowElement == 'undefined') pShowElement='';		
		if (typeof pDebug == 'undefined') pDebug='';		
		
		// Infobox ausgeben
		if (lShowInfo)
		{
	 		oSaveInfo=pics.Windows.infoBox("winInfoSave");
			oSaveInfo.create(400,100,300,0,'speichern...','Datensatz wird gespeichert',true);
			oSaveInfo.setContent("Daten werden gespeichert...");				
		}
		
		lStatus=false;
		// und bauen uns einen Speicherstring
		lParams=pics.Form.convert2Params(pForm);
	
		// und speichern das Formular
		lUrl='savedata.php?mode='+pSaveHandler;
		lResult=pics.Ajax.request_sync(lUrl, "POST", lParams);
		lMsg="";
		//	alert(lResult);
		if (pDebug!='') pics.setHTML(pDebug,lResult);
		
	// === AUSGABE auswerten
		// jetzt verarbeiten wir noch das Ergebnis
		aLines=lResult.split('\n');
		lRecordID=0;
		for (i=0;i<aLines.length;i++)
		{
			aSpalten=aLines[i].split(":");
			switch(aSpalten[0])
			{
				case "SAVE":		// Normalerweise SAVE:ID:Message wobei Message = OK oder FEHLER
					if (aSpalten[2]=="OK")
					{
						// ID merken
						if (pKey!='')
						{
							oField=document.getElementById(pKey);
							oField.value=aSpalten[1];
						}
						lRecordID=aSpalten[1];
						lStatus=true;
						lMsg="Datensatz gespeichert!";
					}
					else
					{
						lStatus=false;
						lMsg=aSpalten[2];
					}
					break;
				case "DATA":	// Normalerweise DATA:Field:ID1,ID2, ...
					if (lStatus==true)
					{
						// IDs aufsplitten und in die fAKID-Felder eintragen
						aIDs=aSpalten[2].split(",");
						aFields=document.getElementsByName(aSpalten[1]);
						// alle Elemente durchlaufen
						for (var i=0;i<aFields.length;i++)
						{
							aFields[i].value=aIDs[i];
						} // for
					}
					break;
				case "FIELD":		// Normalerweise FIELD:Field:ID
					if (lStatus==true)
					{
						oForm=document.getElementById(pForm);
						oForm.elements[aSpalten[1]].value=aSpalten[2];;
					}
					break;
			} // switch
		} // for
	// === ENDE AUSGABE auswerten
		if (lShowInfo) 
		{
			oSaveInfo.setContent(lMsg);				
			// und blenden ihn wieder aus
			if (lStatus==true) 
			{
				oSaveInfo.hide();
			}
			else
			{
				if (lMsg=="") oSaveInfo.setContent("Fehler beim Speichern!");
				oSaveInfo.addButton("OK");
			}
		}
		if (lStatus)
		{
			if (pHideElement != '') pics.showHideElement(pHideElement,false);
			if (pShowElement != '') pics.showHideElement(pShowElement,true);	
		}
		return lStatus;
	}	// pics.Form.save
	

	/**
	 * pics.Form.post2html(pSaveHandler, pForm, pDestElement,pLoadMsg)
	 *		Speichert das angegebene Form mit dem übergebenen Save-Handler und
	 *		schreibt die Ausgabe in den das pDestElement
	 *	@param	string	pSaveHandler	URL zum SaveHandler
	 *	@param	string	pForm			Name des Formulars
	 *	@param	string	pDestElement	Element für die Ausgabe vom Save-Handler
	 *	@param	string	pLoadMsg		wenn angegeben, wird vor dem Load in den Ausgabelayer geschrieben
	 *	@return	
	 */
	pics.Form.post2html = function(pSaveHandler, pForm, pDestElement,pLoadMsg)
	{ 
		// wenn die Windows-Bibliothek vorhanden ist, dann zeigen wir das an
		lShowInfo=true;
		if (typeof pDestElement == 'undefined') pDestElement='';		
		if (typeof pLoadMsg == 'undefined') pLoadMsg='';		
		
		// Load-Meldung ausgeben?
		if ((pDestElement!='') && (pLoadMsg!='')) pics.setHTML(pDestElement,pLoadMsg);
		
		// und bauen uns einen Speicherstring
		lParams=pics.Form.convert2Params(pForm);
	
		// und speichern das Formular
		lUrl='savedata.php?mode='+pSaveHandler;
		lResult=pics.Ajax.request_sync(lUrl, "POST", lParams);
		
		if (pDestElement=='')
		{
			alert(lResult);
		}
		else
		{
			pics.setHTML(pDestElement,lResult);
		}
	}	// pics.Form.post2html
	

	/**
	 * pics.Form.limitTextSize(pField, pSize)
	 *		beschränkt die Länge eines Eingabefelds auf die angegebene Anzahl zeichen
	 *	@param	object	pField		übergebenes Feld
	 *	@return	boolean	true/false
	 */
	pics.Form.limitTextSize = function(pField, pSize)
	{
		if (typeof pField == 'undefined') return false;		
		if (typeof pSize == 'undefined') pSize=50;		
		oElement=pField;
		
		if (oElement.value.length>pSize) oElement.value=oElement.value.substring(0,pSize);
	} // pics.Form.limitTextSize
	
	
/* 
 *	====================================================================================
 *	===== GLOBALE INITALISIERUNG													====
 *	====================================================================================
 */

	 
// Form-Framework-Initialisieren
	pics.Form.init();

	 
