/*global Effect, $, $$, $R, Ajax, document, serialize, unserialize, base64_decode, rawurlencode, rawurldecode, GoogleMaps,
attachColorPicker, Control, parent, setTimeout, base64_encode, strpos, Paging, htmlspecialchars, clearTimeout,
Element, nl2br, Event, alert */

var libraries = [];
/*libraries.push('calendar.js');
libraries.push('colorpicker/yahoo.color.js');
libraries.push('colorpicker/colorPicker.js');
libraries.push('paging.js');*/

var stylesheets = [];
stylesheets.push('FormGenerator.css');
stylesheets.push('calendar.css');
stylesheets.push('colorpicker/colorPicker.css');

/**
 * constructor
 */
function FormGenerator(id)
{
	/*this.path = FormGenerator.path;*/
	this.params = FormGenerator.params;
	this.id = id;

	FormGenerator.forms[id] = this;
	$(this.id).setAttribute('onSubmit', "return FormGenerator.prototype.submit('"+this.id+"')");
	this.clear();
};

/**
 * checks if element is in array
 * 
 * @param element
 * @param arr
 * @return boolean
 */
function in_array(element,arr)
{
	for(var i=0;i<arr.length;++i)
	{
		if (arr[i] === element)
		{
			return true;
		}
	}
	return false;
};

/**
 * 
 *
 */
FormGenerator.prototype.clear = function()
{
	this.check = [];
	this.check.required = [];
	this.check.checklength = [];
	this.check.datatype = [];
	this.check.fields = [];
	this.ajax = false;
	this.ajax_info = [];
	this.error_color = "#EB6E6E";
	this.textContainerLimit = [];
	this.textContainerAutoComplete = [];
	this.selectContainerLimit = [];
	this.sliders = [];
	this.uploads = [];
	this.maps = [];
	this.searchSelects = [];
	
	FormGenerator.clockInfo = [];
	FormGenerator.clockCurrentId = null;
};

/**
 * set notification type
 *
 * @param type
 * @return
 */
FormGenerator.prototype.setNotification = function(elementid)
{
	this.notification = elementid;
};

/**
 * add a required field to form which will be checked on submit
 * 
 * @param elementid
 * @param errormsg
 * @return
 */
FormGenerator.prototype.addRequired = function(elementid,message)
{
	this.check.required.push({
		'elementid':elementid,
		'message':message
	});
};

/**
 * add a field to form. its length be checked on submit
 * 
 * @param elementid
 * @param type
 * @param num
 * @param label
 * @return
 */
FormGenerator.prototype.addLengthCheck = function(elementid,type,num,label)
{
	this.check.checklength.push({
		'elementid': elementid,
		'type': type,
		'num': num,
		'label': label 
	});
};

/**
 * add a field to be checked by a specified type
 * 
 * @param type
 * @param fields
 * @return
 */
FormGenerator.prototype.addCheckFields = function(type,fields)
{
	this.check.fields.push({
		'type': type,
		'fields': fields
	});
};

/**
 * add field to be checked by datatype
 * 
 * @param elementid
 * @param datatype
 * @param label
 * @return
 */
FormGenerator.prototype.addCheckDataType = function (elementid, datatype, label)
{
	this.check.datatype.push({
		'elementid': elementid,
		'datatype': datatype,
		'label': label
	});
};

/**
 * add AutoComplete 
 * 
 * @param id
 * @param url
 * @return
 */
FormGenerator.prototype.addAutoComplete = function(elementid,url)
{
	(new Ajax.Autocompleter(elementid, "autocomplete_choices_"+elementid, url, {
	  paramName: "value",
	  minChars: 1
	}));
};

/**
 * @param elementid
 */
FormGenerator.prototype.addMap = function(elementid)
{
	this.maps[elementid] = GoogleMaps.prototype.getMap(elementid);
};


/**
 * loads all needed files
 *
 */
FormGenerator.prototype.load = function()
{
	Element.observe(document, 'dom:loaded', function()
	{
		var path = '';
		var js = /FormGenerator\.js(\?.*)?$/;
		$$('head script[src]').findAll(function(s) 
		{
			return s.src.match(js);
		}).each(function(s) 
		{
			path = s.src.replace(js, '');
			FormGenerator.params = s.src.match(/\?.*([A-Za-z0-9]+)=([A-Za-z0-9_,.]*)/);
	
			/*if (path.match(/http:\/\//))
			{
				var p = path.substring(9);
				FormGenerator.path = p.substring(p.indexOf("/"));
			}
			else
			{
				FormGenerator.path = path;
			}*/
			
			FormGenerator.prototype.loadNextLibrary();
		});
		for(i=0;i<stylesheets.length;i++)
		{
			FormGenerator.prototype.require('css', FormGenerator.path + stylesheets[i]);
		}
	});
};

FormGenerator.prototype.loadNextLibrary = function()
{
	if (typeof FormGenerator.libraryLoadIterator == 'undefined')
	{
		FormGenerator.libraryLoadIterator = 0;
	}
	else
	{
		FormGenerator.libraryLoadIterator++;
	}
	if (typeof libraries[FormGenerator.libraryLoadIterator] != 'undefined')
	{
		var i = FormGenerator.libraryLoadIterator;
		var library = libraries[i];
		if (!library.match(/^http:\/\//))
		{
			library = FormGenerator.path + library;
		}
		var script = FormGenerator.prototype.require('script',library);
		Element.observe(script, 'load', function(event)
		{
			FormGenerator.prototype.loadNextLibrary();
		});
	}
};

/**
 * loads a script or css file
 * @param type
 * @param file
 * @return void
 */
FormGenerator.prototype.require = function(type,file,callback)
{
	
	var heads = $$('head');
	var head = heads[0];

	if (type=='script')
	{
		var script = document.createElement('SCRIPT');
		script.type = 'text/javascript';
		
		script.onreadystatechange = function () 
		{
	   		if (this.readyState == 'complete') 
	   		{
	   			callback();
	   		}
   		};
   		script.onload = callback;
		script.src = file;
		head.appendChild(script);
		return script;
	}	
	if (type=='css')
	{
		var css = document.createElement('LINK');
		css.href = file;
		css.type = 'text/css';
		css.rel = "stylesheet";
		head.appendChild(css);
		return css;
	}
};

/**
 * 
 * @param formid
 * @return
 */
FormGenerator.prototype.submitLink = function(formid)
{
	var form = FormGenerator.forms[formid];

	if (form.ajax)
	{
		var test = form.test();
		if (test)
		{
			form.ajax_submit();
		}
	}
	else
	{
		$(form.id).submit();
	}
};

/**
 * submits a form
 * 
 * @param form
 * @return
 */
FormGenerator.prototype.submit = function(formid,link)
{
	var form = FormGenerator.forms[formid];
	var test = form.test();
	if (form.ajax && test)
	{
		form.ajax_submit();
		return false;
	}
	else if (!form.ajax && test)
	{
		return true;
	}
	else
	{
		return false;
	}
};

/**
 * set ajax info
 * 
 * @param formid
 * @param action
 * @param resultid
 * @return
 */
FormGenerator.prototype.setAjaxInfo = function (action,resultid,resetform)
{
	this.ajax = true;
	this.ajax_info.action = action;
	this.ajax_info.resultid = resultid;
	this.ajax_info.resetform = resetform;
};

/**
 * submits a form with ajax
 * 
 * @param formid
 * @return
 */
FormGenerator.prototype.ajax_submit = function()
{
	var action = this.ajax_info.action;
	var resultid = this.ajax_info.resultid;
	var resetform = this.ajax_info.resetform;

	var form = $(this.id);
	var sdata = Form.serialize(form);
	if (resetform)
	{
		form.reset();
	}

	/* starting ajax updater */
	(new Ajax.Request(action,
	{
		method:'POST',
		parameters: { formdata: sdata },
		onSuccess: function(transport)
		{
			if (resultid)
			{
				$(resultid).innerHTML = transport.responseText;
			}
			transport.responseText.evalScripts();
			if (resultid)
			{
				$(resultid).fire('ajax:update', { 'transport':transport });	
			}
		},
		onException: function(req,exception) 
		{
			alert("The request had a fatal exception thrown.\n\n" +exception);
			alert("exception.description: "+exception.description);
			alert("exception.message: "+exception.message);
			return true;
		}
	}));

	if (typeof resultid != 'undefined')
	{
		var element = $(resultid);
		if (element && typeof element != 'undefined')
		{
			/* showing indicator */
			element.innerHTML = '<img src="'+FormGenerator.path+'images/indicator.gif" alt="Loading..." />';
		}
	}
};

/**
 * checks form data
 * @param form - object/tag
 * @return
 */
FormGenerator.prototype.test = function ()
{
	//var formid = this.id;
	var errormsg = [];
	var errorfields = [];
	var formgen = this;
	
	/* check required fields */
	this.check.required.each(function(chk) 
	{
		var element = $(chk.elementid);
		var err = chk.message;
		if (typeof formgen.maps[chk.elementid] != 'undefined')
		{
			var error = 1;
			if (element.value)
			{
				var info = unserialize(base64_decode(rawurldecode(element.value)));
				if (info.points[0].lat)
				{
					error = 0;
				}
			}
			if (error)
			{
				errorfields.push(element);
				if (err) 
				{
					errormsg.push(err);
				}
			}
				
		}
		else if (
			(element.tagName == 'INPUT') && 
			(typeof element.type == 'undefined' || element.type == 'text' || element.type == 'password') && 
			element.value == ""
		)
		{
			/* required text,password not entered */
			errorfields.push(element);
			if (err) 
			{
				errormsg.push(err);
			}
			element.style.backgroundColor = formgen.error_color;
		}
		else if (element.tagName == 'TEXTAREA' && !element.value)
		{
			/* required textarea not entered */
			errorfields.push(element);
			if (err)
			{
				errormsg.push(err);
			}
			element.style.backgroundColor = formgen.error_color;
		}
		else if (element.tagName == 'INPUT' && (element.type=='checkbox' || element.type=='radio') && !element.checked)
		{
			/* required checkbox or radio button not checked */
			errorfields.push(element);
			if (err) 
			{
				errormsg.push(err);
			}
			element.style.backgroundColor = formgen.error_color;
		}
		else if (element.tagName == 'SELECT' && !element.options[element.selectedIndex].value)
		{
			errorfields.push(element);
			if (err) 
			{
				errormsg.push(err);
			}
			element.style.backgroundColor = formgen.error_color;				
		}
		else if (!in_array(element,errorfields))
		{
			element.style.backgroundColor = "";
		}
	});
	/* required fields checked */

	/* length checks */
	this.check.checklength.each(function(chk)
	{
		var element = $(chk.elementid);
		var type = chk.type;
		var num = chk.num;
		var label = chk.label;
		if (typeof label == 'undefined') 
		{
			label = chk.elementid;
		}
		if (type == 'min' && element.value.length < num)
		{
			/* not enough characters */
			errorfields.push(element);
			errormsg.push(label + " muss mindestens " + num + " Zeichen lang sein");
			element.style.backgroundColor = formgen.error_color;
		}
		else if (type == 'max' && element.value.length > num)
		{
			/* to much characters */
			errorfields.push(element);
			errormsg.push(label + " darf maximal " + num + " Zeichen lang sein");
			element.style.backgroundColor = formgen.error_color;
		}
		else if (!in_array(element,errorfields)) 
		{
			element.style.backgroundColor = "";
		}
	});
	/* end length checks */

	/* check for datatypes */
	this.check.datatype.each(function(chk)
	{
		var element = $(chk.elementid);
		var datatype = chk.datatype;
		var label = chk.label;
		if (typeof label == 'undefined' || !label) 
		{
			label = chk.elementid; // if label not set, label = element id
		}
		switch (datatype)
		{
			case 'int':
				if (element.value && !formgen.isInt(element.value))
				{
					errorfields.push(element);
					errormsg.push(label + " muss eine Ganzzahl sein");
					element.style.backgroundColor = formgen.error_color;
				}
				break;
			case 'float':
				if (element.value && !formgen.isFloat(element.value))
				{
					errorfields.push(element);
					errormsg.push(label + " muss eine Zahl sein");
					element.style.backgroundColor = formgen.error_color;
				}
				break;
			case 'nospecials':
				if (element.value && formgen.hasSpecials(element.value))
				{
					errorfields.push(element);
					errormsg.push(label + " darf keine Sonderzeichen enthalten");
					element.style.backgroundColor = formgen.error_color;
				}
				break;
			case 'email':
				if (element.value && !formgen.isEmail(element.value))
				{
					errorfields.push(element);
					errormsg.push(label + " muss eine Email-Adresse sein");
					element.style.backgroundColor = formgen.error_color;
				}
				break;
		}
		if (!in_array(element,errorfields)) 
		{
			element.style.backgroundColor = "";
		}
	});

	/* end datatype checks */
	
	/* check for attributes */
	this.check.fields.each(function(chk)
	{
		var type = chk.type;
		var elements = chk.fields;
		var element = [];
		var i;
		for (i=0;i<elements.length;i++)	
		{
			element[i] = $(elements[i]);
		}
		switch (type)
		{
			case 'equal':
				/* checks elements on equal */
				for (i=0;i<element.length;i++)
				{
					var x=i+1;
					if (typeof element[i] != 'undefined' && typeof element[x] != 'undefined')
					{
						if (element[i].value != element[x].value)
						{
							if (element[i].type == 'password') 
							{
								errormsg.push("Passwörter stimmen nicht überein");
							}
							else 
							{
								errormsg.push(element[i].id + " != "+ element[x].id);
							}
							element[i].style.backgroundColor = formgen.error_color;
							element[x].style.backgroundColor = formgen.error_color;
						}
						else
						{
							var e1 = element[i];
							var e2 = element[x];
							if (!in_array(e1,errorfields)) 
							{
								e1.style.backgroundColor = "";
							}
							if (!in_array(e2,errorfields)) 
							{
								e2.style.backgroundColor = "";
							}
						}
					}
				}
				break;
			case 'todo':
				// other checks
				break;
		}
	});
	/* end attribute checks */

	/* printing errors */
	if (errormsg.length>0)
	{
		var tmp = [];
		tmp.errormsg = [];
		var new_errormsg = [];
		for (var i=0;i<errormsg.length;i++) // delete double errormessages
		{
			if (!tmp.errormsg[i])
			{
				tmp.errormsg[i] = i;
				new_errormsg.push(errormsg[i]);
			}
		}
		errormsg = new_errormsg;
		
		if (this.notification=="none") 
		{
			return false;
		}
		var msg = "Es sind folgende Fehler aufgetreten: \n";
		var container = $(this.notification);
		if (typeof this.notification != 'undefined' && container && typeof container != 'undefined' && typeof container.innerHTML != 'undefined') 
		{
			msg = nl2br(msg);
			$(this.notification).innerHTML = '<div class="errorMessage">'+msg+this.genHTMLErrorMessage(errormsg)+'</div>';
		}
		else 
		{
			alert(msg+this.genErrorMessage(errormsg));
		}

		/* stop submit */
		return false;
	}
	/* continue submit */
	return true;
};


/**
 * build error messages from array 
 * 
 * @param arr
 * @return
 */
FormGenerator.prototype.genErrorMessage = function (arr)
{
	var str = "";
	for(var i=0;i<arr.length;i++)
	{
		str += (i+1) + ". " + arr[i] + "\n";
	}
	return str;
};

/**
 * build error message in html style
 * 
 * @param arr
 * @return
 */
FormGenerator.prototype.genHTMLErrorMessage = function(arr)
{
	var str = "<ol>";
	for(var i=0;i<arr.length;i++)
	{
		str += "<li>" + arr[i] + "</li>\n";
	}
	str += "</ol>";
	return str;
};

/**
 * checks if str is a float
 * 
 * @param str
 * @return
 */
FormGenerator.prototype.isFloat = function(str)
{
	str = str.replace(",", ".");
	return (this.isInt(str) || (parseFloat(str)==str));
};

/**
 * checks if str is an integer
 * 
 * @param str
 * @return
 */
FormGenerator.prototype.isInt = function(str)
{
	return parseInt(str,10) == str;
};

/**
 * checks if str contains special characters
 * 
 * @param str
 * @return
 */
FormGenerator.prototype.hasSpecials = function(str)
{
	return str.match("^[a-zA-Z0-9]+$")!=str;
};

/**
 * checks if str is an email
 * 
 * @param str
 * @return
 */
FormGenerator.prototype.isEmail = function(str)
{
	/* should work but could possibly be better */
	return (str.search(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/) != -1);
};

/**
 * sets maximum number of input texts in a dynamic text container
 * 
 * @param elementid
 * @param limit
 * @return
 */
FormGenerator.prototype.setTextContainerLimit = function(elementid,limit)
{
	this.textContainerLimit[elementid] = parseInt(limit,10);
};

/**
 * autocompletion for text container
 * 
 * @param elementid
 * @param url
 * @return
 */
FormGenerator.prototype.setTextContainerAutoComplete = function(elementid, url)
{
	this.textContainerAutoComplete[elementid] = url;
};

/**
 * adds an input text field to a FormInputTextContainer
 * 
 * @param elementid
 * @param input
 * @return
 */
FormGenerator.prototype.newTextContainerItem = function(formid, elementid, input) // static 
{
	var form = FormGenerator.forms[formid];
	var textid = input.id;
	/* parse number of current input */
	var num = parseInt(textid.substring((elementid.length+1)),10);
	var newnum = num+1;

	/* stop if limit is reached */
	if (typeof form.textContainerLimit[elementid] != 'undefined' && form.textContainerLimit[elementid] <= newnum)
	{
		return;
	}
	var newid = elementid+"_"+newnum;
	var element = $(newid);
	/* if the next element doesnt exist */
	if (typeof element == 'undefined' || !element)
	{
		/* new element */
		var newElement = document.createElement("TR");
		newElement.id = 'tr_'+newid;
		newElement.style.display = "none"; /* for Effect.Appear */
		$('tbody_'+elementid).appendChild(newElement); /* add new row to table */
		
		/* setting content of row */
		var td = document.createElement('TD');
		var newInput = document.createElement('INPUT');
		newInput.setAttribute('type', input.type);
		newInput.setAttribute('id', newid);
		newInput.setAttribute('name', input.name);
		//newInput.setAttribute('onkeyup', input.getAttribute('onkeyup'));
		Event.observe(newInput, 'keyup', function (event)
		{
			FormGenerator.prototype.newTextContainerItem(formid,elementid,newInput);
		});
		td.appendChild(newInput);

		/* adding autocomplete extras if nessesary */
		
		if (typeof form.textContainerAutoComplete[elementid] != 'undefined') 
		{
			var autocomplete_span = document.createElement('SPAN');
			autocomplete_span.setAttribute('id', 'indicator_'+newid);
			autocomplete_span.style.display = 'none';
			var autocomplete_img = document.createElement('IMG');
			autocomplete_img.src = this.path+'indicator.gif';
			autocomplete_img.setAttribute('alt', 'Loading...');
			autocomplete_span.appendChild(autocomplete_img);
			
			var autocomplete_div = document.createElement('DIV');
			autocomplete_div.setAttribute('id', 'autocomplete_choices_'+newid);
			autocomplete_div.className = 'autocomplete';
			
			td.appendChild(autocomplete_span);
			td.appendChild(autocomplete_div);
		}
		newElement.appendChild(td);

		/* makes appear more sexy */
		Effect.Appear("tr_"+newid, {duration: 0.5});
		
		/* adding autocomplete handler  if nessesary */
		if (typeof form.textContainerAutoComplete[elementid] != 'undefined')
		{
			form.addAutoComplete(newid,form.textContainerAutoComplete[elementid]);
		}
	}
};

/**
 * sets maximum number of selects in a dynamic select container
 * 
 * @param elementid
 * @param limit
 * @return
 */
FormGenerator.prototype.setSelectContainerLimit = function(elementid, limit)
{
	this.selectContainerLimit[elementid] = parseInt(limit,10);
};

/**
 * adds an input text field to a FormSelectTextContainer
 * 
 * @param formid
 * @param elementid
 * @param input
 * @return
 */
FormGenerator.prototype.newSelectContainerItem = function(formid, elementid, input)
{
	var form = FormGenerator.forms[formid];
	var selectid = input.id;
	/* parse number of current input */
	var num = parseInt(selectid.substring((elementid.length+1)),10);
	var newnum = num+1;

	/* stop if limit is reached */
	if (typeof form.selectContainerLimit[elementid] != 'undefined' && form.selectContainerLimit[elementid] <= newnum) 
	{
		return;
	}
	var newid = elementid+"_"+newnum;
	var element = $(newid);
	/* if the next element doesnt exist */
	if (typeof element == 'undefined' || !element)
	{
		/* new element */
		var newElement = document.createElement("TR");
		newElement.id = 'tr_'+newid;
		newElement.style.display = "none"; /* for Effect.Appear */
		$('tbody_'+elementid).appendChild(newElement); /* add new row to table */

		var newTd = document.createElement('TD');
		var newSelect = document.createElement('SELECT');
		newSelect.setAttribute('id', newid);
		newSelect.setAttribute('name', input.name);
		
		// setup all options for the new select
		var opts = [];
		for (var i=0;i<input.options.length;i++)
		{
			opts[i] = document.createElement('OPTION');
			opts[i].value = input.options[i].value;
			opts[i].innerHTML = input.options[i].innerHTML;
			newSelect.appendChild(opts[i]);
		}

		// adds onChange event handler
		Element.observe(newSelect, 'change', function(event)
		{
			FormGenerator.prototype.newSelectContainerItem(formid,elementid,newSelect);
		});

		newTd.appendChild(newSelect);
		newElement.appendChild(newTd);
		
		/* makes appear more sexy */
		Effect.Appear("tr_"+newid, {duration: 0.5});
	}
};

/**
 * 
 * @param boxid
 * @return
 */
FormGenerator.prototype.change_box = function(boxid)
{
	var box = $(boxid);
	if (box.style.display=="none")
	{
		box.show();
	}
	else
	{
		box.hide();
	}
};

/**
 * 
 * @param input
 * @param format
 * @param buttonObj
 * @return
 */
FormGenerator.prototype.displayClock = function(inputid, format, buttonObj)
{
	if (!FormGenerator.clockInfo[inputid])
	{
		
		FormGenerator.clockInfo[inputid] = [];
		FormGenerator.clockInfo[inputid].format = format;
		FormGenerator.clockInfo[inputid].buttonObj = buttonObj;
	}

	this.initClock(inputid);
	
	if (inputid==FormGenerator.clockCurrentId)
	{
		if ($('clockDiv').style.display=='none')
		{
			$('clockDiv').show();
		}
		else
		{
			FormGenerator.prototype.hideClock();
		}
	}
	else
	{
		$('clockDiv').show();
		FormGenerator.clockCurrentId = inputid;
	}
	
	// move div to correct position
	var dimension = Element.getDimensions(buttonObj);
	$('clockDiv').clonePosition(buttonObj, {offsetTop: dimension.height});
};

/**
 * 
 * @return
 */
FormGenerator.prototype.hideClock = function()
{
	$('clockDiv').hide();
};

/**
 * 
 * @param inputid
 * @return
 */
FormGenerator.prototype.initClock = function(inputid)
{
	if (!$('clockDiv'))
	{
		var div = document.createElement('DIV');
		div.id = 'clockDiv';
		document.body.appendChild(div);	
		Element.absolutize(div);
		$('clockDiv').hide();
	}
	
	
	$('clockDiv').innerHTML = '<div id="clockDivContent"></div>';
	$('clockDivContent').innerHTML = '<div id="clockDivContentHeader"></div><div id="clockDivContentBody"></div><div id="clockDivContentFooter"></div>';
	$('clockDivContentHeader').innerHTML = '<a href="javascript:FormGenerator.prototype.hideClock()"><img src="'+FormGenerator.path+'/images/close.gif" alt="X" /></a><h2>Wähle die Uhrzeit</h2>';

	// hours
	var table = '<table cellspacing="0" cellpadding="0"><tr>';	
	var i;
	var num;
	for (i=0;i<24;i++)
	{
		num = i;
		if (num<10)
		{
			num = '0'+num;
		}
		if (i==12) 
		{
			table += '</tr><tr>';
		}
		table += '<td><a href="javascript:FormGenerator.prototype.clockSelectHour(\''+inputid+'\', \''+i+'\')" id="'+inputid+'_clock_hour_'+i+'"><span>'+num+'</span></a></td>';
	}
	table += '</tr></table>';
	$('clockDivContentBody').innerHTML = table;
	
	// minutes
	table = '<table cellspacing="0" cellpadding="0"><tr>';
	for(i=0;i<60;i+=10)
	{
		num = i;
		if (i<10) 
		{
			num = '0'+num;
		}
		num = ':'+num;
		table += '<td><a href="javascript:FormGenerator.prototype.clockSelectMinute(\''+inputid+'\', \''+i+'\')" id="'+inputid+'_clock_minute_'+i+'"><span>'+num+'</span></a></td>';		
	}
	table += '</tr></table>';
	$('clockDivContentBody').innerHTML += table;
	FormGenerator.prototype.clockSetTime(inputid);
};

/**
 * 
 * @param inputid
 * @return
 */
FormGenerator.prototype.clockSetTime = function(inputid)
{
	var hour = FormGenerator.clockInfo[inputid].hour;
	var minute = FormGenerator.clockInfo[inputid].minute;
	var i;
	for (i=0;i<24;i++)
	{
		if ($(inputid+'_clock_hour_'+i).hasClassName('active'))
		{
			$(inputid+'_clock_hour_'+i).removeClassName('active');
		}
	}

	for (i=0;i<60;i+=10)
	{
		if ($(inputid+'_clock_minute_'+i).hasClassName('active'))
		{
			$(inputid+'_clock_minute_'+i).removeClassName('active');
		}
	}	
	
	if (hour)
	{
		$(inputid+'_clock_hour_'+hour).addClassName('active');
	}
	if (minute)
	{
		$(inputid+'_clock_minute_'+minute).addClassName('active');
	}

};

/**
 * 
 * @param inputid
 * @param hour
 * @return
 */
FormGenerator.prototype.clockSelectHour = function(inputid,hour)
{
	FormGenerator.clockInfo[inputid].hour = hour;
	FormGenerator.prototype.clockSetTime(inputid);
	if (FormGenerator.clockInfo[inputid].minute)
	{
		FormGenerator.prototype.clockSelected(inputid);
	}
};

/**
 * 
 * @param inputid
 * @param minute
 * @return
 */
FormGenerator.prototype.clockSelectMinute = function(inputid,minute)
{
	FormGenerator.clockInfo[inputid].minute = minute;
	FormGenerator.prototype.clockSetTime(inputid);
	if (FormGenerator.clockInfo[inputid].hour)
	{
		FormGenerator.prototype.clockSelected(inputid);
	}
};

/**
 * 
 * @param inputid
 * @return
 */
FormGenerator.prototype.clockSelected = function(inputid)
{
	var format = FormGenerator.clockInfo[inputid].format;
	var hour = FormGenerator.clockInfo[inputid].hour;
	var minute = FormGenerator.clockInfo[inputid].minute;
	if (hour < 10) 
	{
		hour = '0'+hour;
	}
	if (minute < 10) 
	{
		minute = '0'+minute;
	}
	
	format = format.replace('hh', hour);
	format = format.replace('ii', minute);
	$(inputid).value = format;
};

/**
 * @param inputid
 */
FormGenerator.prototype.clockSelection = function(elementid)
{
	var format = 'hh:ii';
	var hourElement = $('clock_hour_'+elementid);
	var hour = hourElement.options[hourElement.selectedIndex].value;

	var minuteElement = $('clock_minute_'+elementid);
	var minute = minuteElement.options[minuteElement.selectedIndex].value;
	format = format.replace('hh', hour);
	format = format.replace('ii', minute);
	$(elementid).value = format;	
};

/**
 * 
 * @param elementid
 * @return
 */
FormGenerator.prototype.addSlider = function(elementid, min, max, value)
{
	if (this.sliders[elementid])
	{
		this.sliders[elementid] = [];
		this.sliders[elementid].min = min;
		this.sliders[elementid].max = max;
		
		var myForm = this;
		// horizontal slider control
		var slider = new Control.Slider('sliderHandle_'+elementid, 'slider_'+elementid, {
			range: $R(min,max),
			onSlide: function(v) { myForm.moveSlider(elementid,v); },
			onChange: function(v) { myForm.moveSlider(elementid,v); }
		});
		
		if (value)
		{
			slider.setValue(value);
		}
	}
};

/**
 * 
 * @param elementid
 * @param v
 * @return
 */
FormGenerator.prototype.moveSlider = function(elementid,v)
{
	v = Math.round(v * 100) / 100;
	$(elementid).value = v; 
	$('slider_result_'+elementid).innerHTML = '&nbsp;' + v;
};


// colorPicker stuff
/**
 * adds a colorpicker
 * 
 * @param elementid
 * @param value
 * @return
 */
FormGenerator.prototype.addColorPicker = function(elementid,value)
{
	Event.observe(window, "load", function() 
	{
		new Control.ColorPicker(elementid, { IMAGE_BASE : FormGenerator.path+"colorpicker/img/" });
		//attachColorPicker($('colorpicker_'+elementid),null, FormGenerator.path+'images/colorpicker', $(elementid));
	});
};

/**
 *  gets content document of a frame
 *  @param frameId
 *  
 *  return Object
 */
FormGenerator.prototype.getContentDocument = function(frameId)
{
	var iframe = $(frameId);
	var iframeDocument = null;
	if (iframe.contentDocument) {
	    iframeDocument = iframe.contentDocument;
	} else if (iframe.contentWindow) {
	    // for IE 5.5, 6 and 7:
	    iframeDocument = iframe.contentWindow.document;
	}
	if (iframeDocument) {
	    return iframeDocument;
	} else {
	    alert('use a newer browser');
	}
};

/**
 * adds upload
 * 
 * @param elementid
 * @param path
 * @param filename
 * @param filetype
 * @param preview
 * @param imagesize
 * @param previewsize
 * 
 * @return void
 */
FormGenerator.prototype.addUpload = function(elementid,path,filename,filetype,preview,imagesize,previewsize,saveOriginal,fixImageSize)
{
	this.uploads[elementid] = {
		'elementid':elementid,
		'path':path,
		'filename':filename,
		'filetype':filetype,
		'preview': preview,
		'imagesize': imagesize,
		'previewsize': previewsize,
		'saveOriginal': saveOriginal,
		'fixImageSize': fixImageSize,
		'time': (new Date()).getTime()
	};
	
	var div = $('upload_'+elementid);
	div.innerHTML = '';
	var iframe = document.createElement("IFRAME");
	iframe.id = "uploadFrame_"+elementid;
	iframe.style.width = '1px';
	iframe.style.height = '1px';
	iframe.style.border = '0';
	iframe.style.padding = '0';
	iframe.setAttribute('scrolling', "no");
	div.appendChild(iframe);

	var frameElement = $(iframe.id);
	var id = this.id;

	Element.observe(frameElement, 'load', function(event)
	{
		parent.FormGenerator.prototype.initUploadFrame(id,elementid);	
	});
};

/**
 * setup upload frame
 * 
 * @param formid
 * @param elementid
 * @return void
 */
FormGenerator.prototype.initUploadFrame = function(formid,elementid)
{
	var form = FormGenerator.forms[formid];
	var frameId = 'uploadFrame_'+elementid;
	var frameElement = $(frameId);
	if (form.uploads[elementid].sent === true)
	{
		form.uploads[elementid].sent = false;
		FormGenerator.prototype.checkUpload(formid,elementid); // frame has been reloaded
	}

	form.uploads[elementid].frame_content = this.getContentDocument(frameId);
	form.uploads[elementid].frame_head = form.uploads[elementid].frame_content.getElementsByTagName('HEAD')[0];
	form.uploads[elementid].frame_body = form.uploads[elementid].frame_content.getElementsByTagName('BODY')[0];
	form.uploads[elementid].frame_body.style.border = '0';
	var upload = form.uploads[elementid];
	if (upload.frame_body.innerHTML != "")
	{
		alert("error: "+upload.frame_body.innerHTML);
	}
	upload.frame_body.innerHTML = '';
	
	upload.frame_body.style.margin = 0;
	upload.frame_body.style.padding = 0;
	
	var formElement = upload.frame_content.createElement("FORM");
	formElement.setAttribute('enctype', 'multipart/form-data');
	formElement.setAttribute('id', 'uploadForm_'+elementid);
	formElement.setAttribute('method', 'POST');
	formElement.setAttribute('action', FormGenerator.path+'ajax.php?call=upload');
	upload.frame_body.appendChild(formElement);

	var elements = [];
	elements.push({name: 'code', value: upload.elementid});
	elements.push({name: 'time', value: upload.time});
	elements.push({name: 'filetype', value: upload.filetype});
	elements.push({name: 'filename', value: upload.filename});
	elements.push({name: 'imagesize', value: upload.imagesize});
	elements.push({name: 'previewsize', value: upload.previewsize});
	elements.push({name: 'path', value: upload.path});
	elements.push({name: 'saveOriginal', value: upload.saveOriginal});
	elements.push({name: 'fixImageSize', value: upload.fixImageSize});
	
	elements.each(function(element)
	{
		var hiddenElement = upload.frame_content.createElement("INPUT");
		hiddenElement.type = 'hidden';
		hiddenElement.name = 'uploadinfo['+element.name+']';
		hiddenElement.value = element.value;
		formElement.appendChild(hiddenElement);
	});
	
	var fileElement = upload.frame_content.createElement("INPUT");
	fileElement.type ='file';
	fileElement.name = 'file';
	fileElement.id = "uploadinput";
	Element.observe(fileElement, 'change', function(event)
	{
		parent.FormGenerator.prototype.startUpload(formid,elementid);
	});
	formElement.appendChild(fileElement);
	frameElement.style.width = fileElement.offsetWidth+'px';
	frameElement.style.height = fileElement.offsetHeight+'px';
};

/**
 * start upload
 * 
 * @param formid
 * @param elementid
 * @return void
 */
FormGenerator.prototype.startUpload = function(formid,elementid)
{
	var form = FormGenerator.forms[formid];
	var uploadForm = form.uploads[elementid].frame_content.getElementById('uploadForm_'+elementid);
	
	form.uploads[elementid].sent = true;
	var preview_element = $('preview_'+elementid);
	if (form.uploads[elementid].preview && $(form.uploads[elementid].preview))
	{
		preview_element = $(form.uploads[elementid].preview);
	}
	preview_element.innerHTML = '<img src="'+FormGenerator.path+'images/indicator.gif" alt="Loading..." />';
	uploadForm.submit();
};

/**
 * checks upload
 * 
 * @param formid
 * @param elementid
 * @return void
 */
FormGenerator.prototype.checkUpload = function(formid, elementid)
{
	var form = FormGenerator.forms[formid];
	(new Ajax.Request(FormGenerator.path+"ajax.php?call=checkUpload&time="+form.uploads[elementid].time+"&code="+elementid, {
		method: 'GET',
		onSuccess: function (transport)
		{
			var images = transport.responseText;
			images = unserialize(images);
			if (images.error == 1)
			{
				setTimeout("FormGenerator.prototype.checkUpload('"+formid+"','"+elementid+"')", 1000);
			}
			else if (images.error > 1)
			{
				alert(images.error_info);
			}
			else
			{
				$(elementid).value = base64_encode(serialize(images.files));
				var image = images.files[form.uploads[elementid].previewsize]; 
				if (!image) 
				{
					image = images.files[0]; // temporary image file
				}
				var dim = form.uploads[elementid].previewsize.split("x");
				var preview_element = $('preview_'+elementid);
				if (form.uploads[elementid].preview && $(form.uploads[elementid].preview))
				{
					preview_element = $(form.uploads[elementid].preview);
				}
				var img = '<img src="/'+image+'?'+(new Date()).getTime()+'" style="max-width:'+dim[0]+'px;max-height:'+dim[1]+'px" alt="Loading..." />';
				preview_element.innerHTML = img;
			}
		}
	}));
};

/**
 * 
 * @param resultid
 * @param url
 * @return
 */
FormGenerator.prototype.ajax_update = function (resultid, url) {
	(new Ajax.Request(url,
	{
		method:'POST',
		onSuccess: function(transport)
		{
			$(resultid).innerHTML = transport.responseText;
			transport.responseText.evalScripts();
			$(resultid).fire('ajax:update', { 'transport':transport });
		}
	}));
};

/**
 * append the result of the url to innerHTML of resultid
 * 
 * @param resultid
 * @param url
 * @param arg
 * @return
 */
FormGenerator.prototype.ajax_append = function(resultid,url,arg)
{
	if (typeof arg != 'undefined' && arg)
	{
		if (!strpos(url,'?')) 
		{
			url += '?0='+arg;
		}
		else
		{
			var i=0;
			var pos = strpos(url,'?');
			while (strpos(url,'?'+i.toString()+'=',pos) || strpos(url,'&'+i.toString()+'=',pos)) 
			{
				i++;
			}
			url+='&'+i+'='+arg;
		}
	}
	(new Ajax.Updater(resultid,url, {
		insertion: 'bottom',
		evalScripts: true
	}));
};

/**
 * 
 * @param elementid
 * @param libraryPath
 * @param request
 * @return
 */
FormGenerator.prototype.addSearchSelect = function (elementid, searchAjax, selectedAjax, selectedAjaxResult, onSearchHideResult)
{
	this.searchSelects[elementid] = {
			'elementid': elementid,
			'searchAjax': base64_decode(searchAjax),
			'selectedAjax': base64_decode(selectedAjax),
			'selectedAjaxResult': selectedAjaxResult,
			'onSearchHideResult': onSearchHideResult,
			'lastresult': ''
	};
};

/**
 * 
 * @param formid
 * @param elemetid
 * @return
 */
FormGenerator.prototype.searchSelectAjax = function(formid,elementid,page)
{
	var form = FormGenerator.forms[formid];
	var info = form.searchSelects[elementid];
	if (!page)
	{
		page = 1;
	}
	$(elementid+'_result').innerHTML = '<img src="'+FormGenerator.path+'images/indicator.gif" alt="Loading..." />';
	if (info.onSearchHideResult && info.selectedAjax)
	{
		var element = elementid+"_selectedResult";
		if (info.selectedAjaxResult)
		{
			element = info.selectedAjaxResult;
		}
		$(element).innerHTML = '';
	}
	(new Ajax.Request(info.searchAjax, {
		method: 'POST',
		postBody: 'search='+rawurlencode($(elementid+'_search').value)+"&page="+page,
		onSuccess: function (transport)
		{
			var data = transport.responseText.evalJSON(true);
			var paging = '';
			
			var results = data;
			if (data.data)
			{
				paging = new Paging(data);
				paging.setClickEvent("FormGenerator.prototype.searchSelectAjax('"+formid+"', '"+elementid+"', '%s')");
//				paging.setHref("javascript:FormGenerator.prototype.searchSelectAjax('"+formid+"', '"+elementid+"', '%s')");
				results = data.data;
			}
			form.searchSelects[elementid].lastresult = data;
			var html = paging;
			html += '<ul>';
			for (var i=0; i<results.length; i++)
			{
				html += form.searchSelectAddResult(elementid,results[i]);
			}
			html += '</ul>'+paging;
			$(elementid+'_result').innerHTML = html;
		}
	}));
};

/**
 * 
 * @param elementid
 * @param data
 * @return
 */
FormGenerator.prototype.searchSelectAddResult = function(elementid,data)
{
	return '<li id="'+elementid+'_value_'+data.value+'"><a href="javascript:FormGenerator.prototype.searchSelect(\''+this.id+'\',\''+elementid+'\', \''+data.value+'\')">'+htmlspecialchars(data.label)+'</a></li>';
};

/**
 * 
 * @param formid
 * @param elementid
 * @return
 */
FormGenerator.prototype.searchSelectAutoSearch = function(formid,elementid)
{
	if (!FormGenerator.searchSelectTimeout) 
	{
		FormGenerator.searchSelectTimeout = [];
	}
	if (FormGenerator.searchSelectTimeout[elementid]) 
	{
		clearTimeout(FormGenerator.searchSelectTimeout[elementid]);
	}
	FormGenerator.searchSelectTimeout[elementid] = setTimeout("FormGenerator.prototype.searchSelectAjax('"+formid+"','"+elementid+"')", 500);
};

/**
 * 
 * @param elementid
 * @param value
 * @return
 */
FormGenerator.prototype.searchSelect = function(formid,elementid,value)
{
	var form = FormGenerator.forms[formid];
	var info = form.searchSelects[elementid];
	
	// set the value
	$(elementid).value = value;
	
	// highlight selected
	var results  = $$('#'+elementid+'_result li');
	for (var i=0; i<results.length;i++)
	{
		results[i].style.fontWeight = "normal";
		results[i].style.textDecoration = "none";
	}
	$(elementid+'_value_'+value).style.fontWeight = "bold";
	$(elementid+'_value_'+value).style.textDecoration = "underline";
	
	// call the callback :)
	if (info.selectedAjax)
	{
		var element = elementid+"_selectedResult";
		if (info.selectedAjaxResult)
		{
			element = info.selectedAjaxResult;
		}
		$(element).innerHTML = '<img src="'+FormGenerator.path+'images/indicator.gif" alt="Loading..." />';

		(new Ajax.Updater(element, info.selectedAjax, {
			method: 'POST',
			postBody: 'value='+value,
			evalScripts: true
		}));
	}
};

FormGenerator.prototype.setPath = function(path)
{
	path += '/';
	this.path = path;
	if (!FormGenerator.path)
	{
		FormGenerator.path = path;
		FormGenerator.prototype.load();
	}
};

// load all libraries
FormGenerator.forms = [];
