 /*
 * Name: formtool.js
 * Author: thko
 * Description: Umfasst saemtliche JS-Funktion rund um das Formulartool.
 *
 * Date: 25.08.2010
 juhu
 * LastModified: 27.01.2012 Tile 
 * Packed: <yes|no> <bei no - Name des Packers - Methode>
 * jQuery: yes
 * use CSS: ???
 */

/** auszufuehrende Events bei Laden der Seite **/
jQuery(document).ready(function () {
  try { formtool.init(); } catch(ex) {alert(ex);}
});

/****** Konstantendefinitionen ******/
var formtoolConstants = {
	
	//Elements
	ELEMENT_INPUT: "input",  
	ELEMENT_TEXTAREA: "textarea",
	ELEMENT_SELECT: "select",
	
	//Element-Types
	ELEMENT_INPUT_TYPE_SELECT: "select",
	ELEMENT_INPUT_TYPE_TEXTAREA: "textarea",
	ELEMENT_INPUT_TYPE_TEXT: "text",
	ELEMENT_INPUT_TYPE_PASSWORD: "password",
	ELEMENT_INPUT_TYPE_HIDDEN: "hidden",
	ELEMENT_INPUT_TYPE_file: "file",
	ELEMENT_INPUT_TYPE_RADIO: "radio",
	ELEMENT_INPUT_TYPE_CHECKBOX: "checkbox",
	ELEMENT_INPUT_TYPE_BUTTON: "button",
	ELEMENT_INPUT_TYPE_RESET: "reset",
	ELEMENT_INPUT_TYPE_SUBMIT: "submit",
	ELEMENT_INPUT_TYPE_IMAGE: "image",
	
	//Element-Environment
	ELEMENT_ENV_WRAP_P: "p-",
	ELEMENT_ENV_WRAP_DIV: "d-",
	
	//Elementattributes
	ELEMENT_ATTRIBUTE_NAME_IDENTIFIER_BEGIN: "data[",
	ELEMENT_ATTRIBUTE_NAME_IDENTIFIER_END: "]",
	ELEMENT_ATTRIBUTE_ID_IDENTIFIER: "id",
	
	ELEMENT_ATTRIBUTE_NAME: "name",
	ELEMENT_ATTRIBUTE_ID: "id",
	
	//CSS
	CSS_SELECTOR_ERROR_MSG: "errM",
	CSS_SELECTOR_ERROR_MSG2: "eMsg",
	CSS_SELECTOR_RVL_ELEMENT: "rv",
	
	//AJAX
	AJX_ACTION: "action",
	
	//Events
	EVENT_CHANGE: "change",
	EVENT_CLICK: "click",
	EVENT_KEY_UP: "keyup",
	EVENT_BLUR: "blur",
	
	// Searchterms, wird durch Redaktion erweitert
	SEARCHTERMS: new Array("Suchbegriff eingeben...","Media Center durchsuchen",
	                        "Stichwort eingeben","Enter a search term...",
							"Searchterm","Zoekterm")

	
};

/****** Bibliotheksdefinition ******/
var formtool = {

  /****** Funktionsdefinitionen ******/

	/**
	   * Initialisierungsmethode
	   */
	init : function() {
		try { formtool.runtimeValidation.init(); } catch(ex) {/*nothing*/}
		try { formtool.paging.init(); } catch(ex) {/*nothing*/}
		try { formtool.suggestions.init(); } catch(ex) {/*nothing*/}
		try { formtool.industrysearch.init(); } catch(ex) {/*nothing*/}
		try { formtool.search.init(); } catch(ex) {/* nothing */}
		try { formtool.dynamisation.init(); } catch(ex) {/*nothing*/}
		try { formtool.pricing.init(); } catch(ex) {/*nothing*/}
	},
	
	/*****************************************************************************
	 *** Pricing
	 ****************************************************************************/
	pricing : {
		
		suitableFields: [
							formtoolConstants.ELEMENT_INPUT,
				            formtoolConstants.ELEMENT_SELECT
						],
		clickTypes: [
						formtoolConstants.ELEMENT_INPUT_TYPE_RADIO,
						formtoolConstants.ELEMENT_INPUT_TYPE_CHECKBOX
					],
		
		init : function() {
			formtool.pricing.handlePricingConfig();
		},
		
		handlePricingConfig : function() {
			if (formtool_config.priceconfig.destElements) {
				jQuery.each(formtool_config.priceconfig.destElements, function(i, elemName) {
					var triggerElement = jQuery('#id' + elemName);
					if (triggerElement.length == 0) {
						triggerElement = jQuery('input[name|="data['+ elemName +']"]');
					}
					if (triggerElement.length > 0) {
						if (triggerElement.length > 1) {
							jQuery.each(triggerElement, function(i, singleTriggerElement) {
								formtool.pricing.bindPricingEvent(jQuery(singleTriggerElement));				
							});
						} else {
							formtool.pricing.bindPricingEvent(triggerElement);
						}
					}
				});
			}
		},
		
		bindPricingEvent : function(triggerElement) {
			if(jQuery.inArray(triggerElement.attr('tagName').toLowerCase(), formtool.pricing.suitableFields) != -1) {
				if (jQuery.inArray(triggerElement.attr('type').toLowerCase(), formtool.pricing.clickTypes) != -1) {
					triggerElement.bind('click', function() {
						formtool.pricing.getPriceInformation();
					});
				}else {
					triggerElement.bind('change', function() {
						formtool.pricing.getPriceInformation();
					});
				}
			}
		},
		
		getPriceInformation : function() {
			var priceValues = {};
			jQuery.each(formtool_config.priceconfig.destElements, function(i, elemName) {
				var priceElem = jQuery('#id' + elemName);
				if (priceElem && priceElem.length == 0) {
					priceElem = jQuery('input[name|="data['+ elemName +']"]');
				}
				if (priceElem) {
					if (priceElem.length > 1) {
						jQuery.each(priceElem, function(i, elem) {
							if (jQuery(elem).attr('checked')) {
								priceValues['"' + elemName + '"'] = '"' +  jQuery(elem).val() + '"';
							}
						});
					} else {
						var priceElementType = formtool.helper.getElementType(priceElem);
						if (priceElementType == formtoolConstants.ELEMENT_INPUT_TYPE_CHECKBOX) {
							if (priceElem.attr('checked')) {
								priceValues['"' + elemName + '"'] = '"' + priceElem.val() + '"';
							}
						} else {
							priceValues['"' + elemName + '"'] = '"' + priceElem.val() + '"';
						}
					}
				}
			});
			
			priceValues = encodeURI('formData='+formtool.helper.toString(priceValues));
			
			jQuery.getJSON (
				priceConfigUrl, 
				priceValues, 
				function(json, textStatus){
					formtool.pricing.handleResponse(json, priceValues);
				}
			);
		},
		
		handleResponse : function(json, parameters) {
			if (json) {
				jQuery.each(json, function(key, value) {
					if (jQuery('#id'+key) && jQuery('#id'+key).length > 0) {
						jQuery('#id'+key).val(value);
					}
				});
			}
		}
	},
	
	/*****************************************************************************
	 *** Dynamisierung
	 ****************************************************************************/
	dynamisation : {

		suitableFields: [
							formtoolConstants.ELEMENT_INPUT,
				            formtoolConstants.ELEMENT_SELECT
						],
		clickTypes: [
						formtoolConstants.ELEMENT_INPUT_TYPE_RADIO,
						formtoolConstants.ELEMENT_INPUT_TYPE_CHECKBOX
					],
					
		/** Enthaelt die dynamischen Felder, welche versteckt werden und leergemacht werden sollen. */
    preAllocatedElements: {}, 
    /** Enthaelt die dynamischen Felder, welche sichtbar gemacht wurden. */
    handledElements: {},
		
		init : function() {
			formtool.dynamisation.handleDynamisationConfig();
		},
		
		/**
		 * Liest die JavaScript-Eventkonfiguration.
		 */
		handleDynamisationConfig : function() {
			if (formtool_config && formtool_config.events) {
				jQuery.each(formtool_config.events, function(elemKey, destElements) {
					var triggerElement = jQuery('#id' + elemKey);
					if (triggerElement.length == 0) {
						triggerElement = jQuery('input[name|="data['+ elemKey +']"]');
					}
					if (triggerElement.length > 0) {
						if (triggerElement.length > 1) {
							var match = false;
							triggerElement.sort(formtool.helper.radioSort);
							jQuery.each(triggerElement, function(i, singleTriggerElement) {
								formtool.dynamisation.bindDynamisationEvent(jQuery(singleTriggerElement));
								/* 
								 * Pruefen ob bereits abhaengige Felder eingeblendet wurden.
								 * Das verhindert das bereits eingeblendete Felder wieder ausgeblendet werden.
								 * Diese pruefung ist nur fuer Radioboxen relevant.
								 */
								if (!match) {				
									match = formtool.dynamisation.handleVisibility(jQuery(singleTriggerElement), destElements);
								}
							});
						} else {
							formtool.dynamisation.bindDynamisationEvent(triggerElement);						
							formtool.dynamisation.handleVisibility(triggerElement, destElements);
						}
					}
				});
			}
		},
		
		/**
		 * Bindet die Events fuer die Dynamisierung an das Ausloeseelement.
		 */
		bindDynamisationEvent : function(triggerElement) {
			if(jQuery.inArray(triggerElement.attr('tagName').toLowerCase(), formtool.dynamisation.suitableFields) != -1) {
				if (jQuery.inArray(triggerElement.attr('type').toLowerCase(), formtool.dynamisation.clickTypes) != -1) {
					triggerElement.bind('click', function() {
					  /* Leert die Map mit den zu leerenden Feldern, Fuehrt die benoetigten Aenderungen bzgl. des Events aus, und macht die versteckten Felder leer. */
					  formtool.dynamisation.preAllocatedElements = {};
						formtool.dynamisation.handleElementStateChange(jQuery(this));
						formtool.dynamisation.clearHiddenDynamicField();
					});
				}else {
					triggerElement.bind('change', function() {
					  /* Leert die Map mit den zu leerenden Feldern, Fuehrt die benoetigten Aenderungen bzgl. des Events aus, und macht die versteckten Felder leer. */
					  formtool.dynamisation.preAllocatedElements = {};
						formtool.dynamisation.handleElementStateChange(jQuery(this));
						formtool.dynamisation.clearHiddenDynamicField();
					});
				}
			}
		},
		
		/**
		 * Leert die Felder, welche aufgrund des geflogenen Events versteckt werden sollen.
		 */     		
		clearHiddenDynamicField : function() {
      jQuery.each(formtool.dynamisation.preAllocatedElements, function (elem, value) {        
        if (value !== true) {
    			var elemType = formtool.helper.getElementType(value);
    			switch (elemType) {
    				case formtoolConstants.ELEMENT_INPUT_TYPE_SELECT:
    					jQuery(value.attr('options')[0]).attr('selected',true);          					
    					break;
    				case formtoolConstants.ELEMENT_INPUT_TYPE_TEXT:
    				case formtoolConstants.ELEMENT_INPUT_TYPE_PASSWORD:
    				case formtoolConstants.ELEMENT_INPUT_TYPE_TEXTAREA:
    					value.val('');
    					break;
    				case formtoolConstants.ELEMENT_INPUT_TYPE_CHECKBOX:
    					value.attr('checked','false');
    					break;
    				case formtoolConstants.ELEMENT_INPUT_TYPE_RADIO:
    					jQuery.each(value, function(i, radioElem) {
  							jQuery(radioElem).attr('checked',false);
  						});
    					break;
    				default:
    					//nothing
    					break;
    			}
        }
      });
    },
		
		/**
		 * Fuehrt die notwendigen Aktionen aus, wenn ein Ausloeseelement seinen Zustand geaendert hat.
		 * Weiterhin werden alle davon betroffenen Ausloeseelemente ebenfalls behandelt. 
		 */
		handleElementStateChange : function(triggerElement) {
    formtool.dynamisation.handledElements = {};
			var destElements = formtool.dynamisation.getDestElementsForTriggerElement(triggerElement);
			formtool.dynamisation.handleVisibility(triggerElement, destElements);
			jQuery.each(destElements, function(i, options) {
				if (formtool_config.events[options.destElemName]) {
					var elem = jQuery('#id' + options.destElemName)
					if (elem.length == 0) {
						elem = jQuery('input[name|="data['+ options.destElemName +']"]');
					}
					formtool.dynamisation.handleElementStateChange(elem);
				}
			});
		},
		
		/**
		 * Prueft die initiale Sichtbarkeit der betroffenen Elemente und schaltet diese sichtbar oder unsichtbar.
		 * Anschließend wird die Elemente als Pflichtfelder markiert oder die Markierung entfernt.
		 * Folgende Ausloeseelemente werden behandelt:
		 *  - Select
		 *  - Radiobox
		 *  - Checkbox
		 */
		handleVisibility : function(triggerElement, destElements) {
			var triggerElementType = formtool.helper.getElementType(triggerElement);
			var match = false;
			
			jQuery.each(destElements, function(i, destElemAttr) {
				var destElem = jQuery('#id' + destElemAttr.destElemName);
				if (destElem.length == 0) {
					destElem = jQuery('input[name|="data['+ destElemAttr.destElemName +']"]');
				}
				var hide = true;
				switch (triggerElementType) {
					// Behandlung fuer Selectboxen
					case formtoolConstants.ELEMENT_INPUT_TYPE_SELECT:
						var selectedOpt = '';
						jQuery.each(triggerElement.attr('options'), function(i, item) {
							item = jQuery(item);
							if (item.attr("selected")) {
								selectedOpt = item.val();
							}
						});
						if (selectedOpt == destElemAttr.triggerValue) {
							hide = false;
						}
						break;
					// Behandlung fuer Radioboxen und Checkboxen
					case formtoolConstants.ELEMENT_INPUT_TYPE_RADIO:
					case formtoolConstants.ELEMENT_INPUT_TYPE_CHECKBOX:
						var chkValue = triggerElement.val();
						var elemChecked = triggerElement.attr('checked');
						if (chkValue == destElemAttr.triggerValue && elemChecked) {
							hide = false;
							/* 
							 * 'match' aktivieren, damit keine weitere Sichbarkeitspruefung 
							 * fuer diese Radiobox durchgefuehrt wird.
							 */ 
							match = true;
						}
						break;
				}
				
				if (!formtool.dynamisation.handledElements[destElemAttr.destElemName]) {
					if (hide) {
						formtool.helper.hideElement(destElem);
						formtool.dynamisation.disableMandatory(destElem, destElemAttr);
						
						/** Wenn nicht schon ermittelt wurde, dass das Element angezeigt werden soll (true), dann wird dies zum Leermachen markiert. */
            if (formtool.dynamisation.preAllocatedElements[destElemAttr.destElemName] !== true) {
              formtool.dynamisation.preAllocatedElements[destElemAttr.destElemName] = destElem;
            }
					} else {
						formtool.helper.showElement(destElem);
						formtool.dynamisation.enableMandatory(destElem, destElemAttr);
						formtool.dynamisation.handledElements[destElemAttr.destElemName] = true;
						formtool.dynamisation.handlePreallocation(destElem, destElemAttr, hide);
						
						/** Das Element soll anezeigt werden, soll also nicht geleert werden. */
						formtool.dynamisation.preAllocatedElements[destElemAttr.destElemName] = true;
					}
				}
			});
			
			return match;
		},
		
		/**
		 * Behandelt die Vorbelegung der einzublendenen Felder.
		 * Die trifft nur fuer folgende Elemente zu:
		 *  - Select
		 *  - Textfield
		 *  - Textarea
		 *  - Passwordfield 
		 */
		handlePreallocation : function(elem, destElemAttr, invisible) {
			var elemType = formtool.helper.getElementType(elem);
			switch (elemType) {
				case formtoolConstants.ELEMENT_INPUT_TYPE_SELECT:
					var preallocData = eval('(' + destElemAttr.preallocation + ')');
					var selectedOpt = null;	
					var selectedIdx = 0;

					jQuery.each(elem.attr('options'), function(i, opt) {
						if (jQuery(opt).attr('selected') == true) {
							selectedOpt = jQuery(opt).val();
							selectedIdx = i;
						}
					});
					
					if (destElemAttr.preallocation && destElemAttr.preallocation.length > 2) {
  					while(elem.attr('options').length > 0) {
  						elem.attr('options')[0] = null;
  					}
  					
  					jQuery.each(preallocData, function(key, value) {
  						if (key == '_') key = '';
  						elem.append(jQuery('<option>', { value : key }).text(value));
  					});
  					
  					var hasSelected = false;
  					jQuery.each(elem.attr('options'), function(i, opt) {
  						if (jQuery(opt).val() == selectedOpt) {
  							jQuery(opt).attr('selected', true);
  							hasSelected = true;
  						}
  					});
  					
  					if (!hasSelected) {
  						jQuery(elem.attr('options')[0]).attr('selected',true);
  					}
				  }
					break;
				case formtoolConstants.ELEMENT_INPUT_TYPE_TEXT:
				case formtoolConstants.ELEMENT_INPUT_TYPE_PASSWORD:
				case formtoolConstants.ELEMENT_INPUT_TYPE_TEXTAREA:
					if (invisible) {
						elem.val('');
					}
					if (!invisible && elem.val() == '') {
						elem.val(destElemAttr.preallocation);
					}
					break;
				case formtoolConstants.ELEMENT_INPUT_TYPE_CHECKBOX:
					if (invisible) {
						elem.attr('checked','false');
					}
					break;
				case formtoolConstants.ELEMENT_INPUT_TYPE_RADIO:
					if (invisible) {
						jQuery.each(elem, function(i, radioElem) {
							jQuery(radioElem).attr('checked',false);
						});
					}
					break;
				default:
					//nothing
					break;
			}
		},
		
		/**
		 * Markiert das uebergebene Element 'elem', anhand des Labels als Plichtfeld.
		 */
		enableMandatory : function(elem, destElemAttr) {
			if (destElemAttr.mandatory) {
				var label = formtool.helper.getElementLabel(elem);
				if (label) {
					var labelText = label.html();
					if (labelText && labelText.indexOf("*") < 0) {
						label.html(label.html() + " *");
						label.addClass('lMan');
					}
				}
			}
		},
		
		/**
		 * Entfernt die Pflichtfeldmarkierung vom Label des uebergenen Elements 'elem'.
		 */
		disableMandatory : function(elem, destElemAttr) {
			if (destElemAttr.mandatory) {
				var label = formtool.helper.getElementLabel(elem);
				if (label) {
					var labelText = label.html();
					if (labelText && labelText.indexOf("*") > 0) {
						label.html(labelText.substring(0, labelText.length-1));
						label.removeClass('lMan');
					}
				}
			}
		},
		
		/**
		 * Liefert die Zielelementkonfigurationen fuer das uebergebene Ausloeseelement 'triggerElement'.
		 */
		getDestElementsForTriggerElement: function(triggerElement) {
			var triggerElementName = formtool.helper.getElementName(triggerElement);
			if(formtool_config.events) {
				return formtool_config.events[triggerElementName];
			}
		}
		
	},
	
	/*****************************************************************************
	 *** Runtimevalidation
	 ****************************************************************************/
	
	runtimeValidation : {
		
		constants: {			
			//Runtimevalidation-Requestparameters
			REQ_ELEMENT_NAME: "elementname",
			REQ_ELEMENT_VALUE: "fieldvalue",
			RES_ERROR_MESSAGE: "ErrorMessage",
			AJX_ACTION_RUNTIME_VALIDATION: "runtimevalidation"
		},

		suitableFields: [
				            formtoolConstants.ELEMENT_INPUT,
				            formtoolConstants.ELEMENT_TEXTAREA,
				            formtoolConstants.ELEMENT_SELECT
						],
	 
		suitableInputTypes: [
							formtoolConstants.ELEMENT_INPUT_TYPE_TEXT,
							formtoolConstants.ELEMENT_INPUT_TYPE_TEXTAREA,
							formtoolConstants.ELEMENT_INPUT_TYPE_PASSWORD
							],
		
		/**
		  * Initialisierungsmethode
		  */
		init: function() {
			try { formtool.runtimeValidation.bindRuntimeValidationEvents(); } catch(ex) {/*nothing*/}
		},
			
		/**
		  * Liefert alle Formularelemente die die CSS-Klasse 'rv' besitzen und bindet
		  * abhaengig vom TYPE ein Event an das Element.
		  */
		bindRuntimeValidationEvents: function() {
		  jQuery("." + formtoolConstants.CSS_SELECTOR_RVL_ELEMENT).each(function (i, item) {
					suitable = true;
			  if (jQuery.inArray(item.tagName.toLowerCase(), formtool.runtimeValidation.suitableFields) == -1) {
						suitable = false;
					}
					if (item.type &&
							jQuery.inArray(item.type.toLowerCase(), formtool.runtimeValidation.suitableInputTypes) == -1) {
					  suitable = false;
					}		

					if (suitable) {
						jQuery(item).blur(function() { formtool.runtimeValidation.validate(jQuery(item)); });
					}
			});   
		},
			
		/**
		  * Ermittelt die Informationen fuer die RuntimeValidierung und bereitet sie
		  * fuer den Versand auf.
		  * 
		  * @param {Object} elem
		  */
		validate: function(elem) {
			elementValue = jQuery(elem).val();
			elementName = formtool.helper.getElementName(elem);
			url = runtimeValidationUrl;
			
			paremeters = [
				formtool.runtimeValidation.constants.REQ_ELEMENT_NAME, 
				elementName,
				formtool.runtimeValidation.constants.REQ_ELEMENT_VALUE, 
				elementValue
			];
			
			encodedURI = encodeURI(jQuery.serializeObject(paremeters));
			formtool.runtimeValidation._doXHR(url, encodedURI);
		},
			
		/**
		 * Fuehrt einen JSON-XMLHTTPRequest anhand der uebergebenen 
		* Parameter "url" und "parameters" aus.
		* 
		 * @param {Object} url
		 * @param {Object} parameters
		 */
		_doXHR: function(url, parameters) {
			jQuery.getJSON (
				url, 
				parameters, 
				function(json, textStatus){
				  formtool.runtimeValidation._handleResponse(json, parameters);
				}
			);
		},
			
		/**
		  * Verarbeitet den jeweiligen XMLHTTPResponse.
		  * 
		  * @param {Object} result
		  * @param {Object} parameters
		  */
		_handleResponse: function(result, parameters) {
			if (result) {
				if (jQuery.objContainsKey(formtoolConstants.AJX_ACTION, result)) {
					if (result[formtoolConstants.AJX_ACTION] == formtool.runtimeValidation.constants.AJX_ACTION_RUNTIME_VALIDATION) {
						formtool.runtimeValidation.handleRuntimeValidationResult(result);
					}
				}
			}
		},
		
		/**
		 * Behandelt das Ergebnis der Runtimevalidation.
		 * 
		 * @param {Object} result
		 */
		handleRuntimeValidationResult: function(result) {
			errorSelector = "#" + 
			                formtoolConstants.ELEMENT_ENV_WRAP_DIV + 
							result[formtool.runtimeValidation.constants.REQ_ELEMENT_NAME] + 
							" > ." + 
							formtoolConstants.CSS_SELECTOR_ERROR_MSG;
							
			if (jQuery(errorSelector) && jQuery(errorSelector).length > 0) {
				jQuery(errorSelector).remove();
			}
			
			if (result[formtool.runtimeValidation.constants.RES_ERROR_MESSAGE] != null) {
				elementEnvironmentSelector = "#" +
											 formtoolConstants.ELEMENT_ENV_WRAP_DIV +
											 result[formtool.runtimeValidation.constants.REQ_ELEMENT_NAME];
																		 
				if (jQuery(elementEnvironmentSelector) && jQuery(elementEnvironmentSelector).length > 0) {
					jQuery(elementEnvironmentSelector).prepend("<div class=\"" + formtoolConstants.CSS_SELECTOR_ERROR_MSG + "\">" +
														   result[formtool.runtimeValidation.constants.RES_ERROR_MESSAGE] +
														   "</div>");
				}
			}
		}
				
	},
	
	/*****************************************************************************
	*** AutoSuggestions
	****************************************************************************/
	
	suggestions: {
		
		init: function() {
		  if (suggestionUrl && jQuery( "input.sg" ).length > 0) {
        jQuery( "input.sg" ).focus(function() {
          jQuery.getJSON (
            suggestionUrl, 
            "suggestionType=searchsuggestions", 
            function(json, textStatus){
              formtool.suggestions._handleResponse(json, "searchsuggestions");
            }
          );
        });
		  }
		},
		
		_handleResponse: function(json, parameters) {
			if (parameters && parameters=="searchsuggestions") {
				var resultSuggestions = [];
					
				jQuery.each(json, function(key, value) {
					resultSuggestions.push(value); 
				});
				
                if (jQuery( "input.sg" ).length > 0 ) {
					jQuery( "input.sg" ).each(function(k, inp) {
						jQuery(inp).autocomplete({
							minLength: 1,
							source: function( request, response ) {
								var matcher = new RegExp( jQuery.ui.autocomplete.escapeRegex(request.term), "i" );
								response( jQuery(resultSuggestions).map(function() {
									var text = this;									
									if ( !request.term || matcher.test(this) ) {
										return {
											label: text.replace(
												new RegExp(
													"(?![^&;]+;)(?!<[^<>]*)(" +
													jQuery.ui.autocomplete.escapeRegex(request.term) +
													")(?![^<>]*>)(?![^&;]+;)", "gi"
												), "<strong>$1</strong>" ),
												value: text,
												option: this
										};
									}	
								}));
							}
						});
					});
                
                    jQuery( "input.sg" ).each(function(l, inp) {
                        jQuery(inp).data("autocomplete")._renderItem = function( ul, item ) {
                            if (ul.children().length == 0) {
                                ul.append(jQuery("<li></li>").addClass("arrow"));
                            }
                            var result = jQuery( "<li></li>" )
                                .data( "item", item )
                                .append( "<a>" + item.label + "</a>" )
                                .appendTo( ul );
                                
                            return result;
                        };
                    });
                    
				}
			}
		}
	},
	
	/*****************************************************************************
	  *** Paging per Tabs
	  ****************************************************************************/
	paging: {
		
		/**
		  * Konstantendefinitionen fuer das Paging
		  */
		constants: {			
			PAGE_TABBOX_SELECTOR: "tabBox",
			PAGE_TAB_SELECTOR: "tabCo",
			NAVI_SELECTOR: "nav",
			NAVI_BACK_SELECTOR: "bSub",
			NAVI_NEXT_SELECTOR: "nSub"			
		},
		
		errorPages: [],
		
		/**
		  * Initialisierungsmethode
		  */
		init: function() {
			try {		  	
				formtool.paging.bindNaviEvents();
				formtool.paging.getStartingPage();
			} catch(e) {/*nothing*/}
		},
		
		/**
		 * Selektiert alle Buttons mit Klassennamen "navielement" und haengt ein 
		 * onClick-Event an zum Durschschalten der Seiten
		 */ 
		bindNaviEvents: function() {
			var pages = jQuery("." + formtool.paging.constants.PAGE_TAB_SELECTOR);

			if (pages.length > 1) {
				jQuery.each(pages, function(i, page) {
					pageIdParts = page.id.split("-");
					if (pageIdParts.length == 3) {
						var pageId = parseInt(pageIdParts[2]);
						jQuery("#" + page.id + " ." + formtool.paging.constants.NAVI_SELECTOR).each(function(l, button) {
							if (jQuery(button).attr("className").indexOf(formtool.paging.constants.NAVI_BACK_SELECTOR) != -1) {
								if ((pageId) > 0) {
									jQuery(button).click(function() { formtool.paging.navigate(pageIdParts[1], pageId, false); });
									jQuery(button).css({ display: "block" });
								}
							}
							if (jQuery(button).attr("className").indexOf(formtool.paging.constants.NAVI_NEXT_SELECTOR) != -1) {
								jQuery(button).click(function() { formtool.paging.navigate(pageIdParts[1], pageId, true); });
								jQuery(button).css({ display: "block" });
							}
						});
					}
				});
			} 
		},
		
		/**
		 * ermittelt die Startseite der Formularseite. Ist abhaengig von enthaltenen
		 * Validierungs-Fehlermeldung
		 */
		getStartingPage: function() {
			var startingPageId = "0";
			var hasErrors = false;

			jQuery("." + formtool.paging.constants.PAGE_TAB_SELECTOR).each(function(i, page) { 
				pageIdParts = page.id.split("-");               
				var errors = jQuery("#" + page.id + " ." + formtoolConstants.CSS_SELECTOR_ERROR_MSG);
				if(errors != null && errors.length > 0) {
					if (!hasErrors) {
						startingPageId = pageIdParts[2];
						hasErrors = true;
					}
					formtool.paging.errorPages.push(page);
				}       
			});

			formtool.paging.showTabs(startingPageId);
		},
		
		/**
		 * Die Methode dient der Navigation per Buttons durch die einzelnen Tabs.
		 * Die Methode wird per Klick-Event, onLoad an die Navigationsbuttons gebunden.
		 * 
		 * @param {Object} formToolId ID des Formulars
		 * @param {Object} pageId ID des aktuellen Tabs
		 * @param {Object} forward true wenn forwaerfts navigiert werden soll
		 */
		navigate: function(formToolId, pageId, forward) {
			var page = jQuery("#tabCo-"+formToolId+"-"+pageId)[0];
			var idx = jQuery.inArray(page, formtool.paging.errorPages);
			var direction = forward ? 1 : -1;

			if (idx != -1) {    
				var nextIdx = idx+direction;
				if (nextIdx >= 0) {
					if (nextIdx < formtool.paging.errorPages.length) {
						var nextErrorPage = formtool.paging.errorPages[nextIdx];
						pageId = nextErrorPage.id.replace("tabCo-" + formToolId + "-", "");
						jQuery("#" + formtool.paging.constants.PAGE_TABBOX_SELECTOR + "-" + formToolId).tabs('select', pageId);
					}else {
						pageId += direction;
						jQuery("#" + formtool.paging.constants.PAGE_TABBOX_SELECTOR + "-" + formToolId).tabs('select', pageId);
					}
				}     
			}else {
				pageId += direction;
				jQuery("#" + formtool.paging.constants.PAGE_TABBOX_SELECTOR + "-" + formToolId).tabs('select', pageId);
			}     
		},
		
		/**
		 * Initialisiert das Tabobjekt.
		 * 
		 * @param {Object} idx ID des Starttabs
		 */
		showTabs: function(idx) {
			var pages = jQuery("." + formtool.paging.constants.PAGE_TAB_SELECTOR);
			if (pages.length > 1) {
				jQuery.each(pages, function(i, page) {   
					pageIdParts = page.id.split("-");      
					var tabId = "tab-" + pageIdParts[1] + "-" + pageIdParts[2];
					if (jQuery.inArray(page, formtool.paging.errorPages) != -1) {            
						jQuery("#" + tabId + " a").addClass(formtoolConstants.CSS_SELECTOR_ERROR_MSG);
					}
				});
				jQuery("." + formtool.paging.constants.PAGE_TABBOX_SELECTOR).tabs({
					selected: idx
				});
			}
		}
		
	},
	
	/*****************************************************************************
	  *** Branchensuche
	  ****************************************************************************/	
	industrysearch: {

		constants: {			
			CSS_SELECTOR_INDUSTRY_SEARCH: ".indsearch"
		},

		/**
		  * Initialisierungsmethode
		  */
		init: function() {
			try { formtool.industrysearch.bindIndustryCheckboxesEvents(); } catch(ex) {/*nothing*/}
		},

		/**
		  * Liefert alle Formularelemente die die CSS-Klasse 'indsearch' besitzen. Diesen wird ein Clickevent
		  * hinzugefuegt: Wenn geclickt, submitte die Form, die den Button enthaelt.		 
		  */
		bindIndustryCheckboxesEvents: function() {
			jQuery(formtool.industrysearch.constants.CSS_SELECTOR_INDUSTRY_SEARCH).each(function (i, item) {
				jQuery(item).click(function() {
					formtool.helper.submitParentForm(item);
				});
			});
		},

		/**
		  * Wenn geclickt, setze alle indsearch-Ckeckboxen auf checked und submitte die Form.       	    
		  */	  
		selectAll: function(selectAllBox) {
			var checkBoxes = jQuery(formtool.industrysearch.constants.CSS_SELECTOR_INDUSTRY_SEARCH);
			if (!checkBoxes) return;

			jQuery(checkBoxes).attr('checked', selectAllBox.checked);

			if (selectAllBox.checked) {
				formtool.helper.submitParentForm(selectAllBox);
			}
		}
	},
	
	search: {
		
		init: function() {
			try { formtool.search.bindSearchTermEvents(); } catch(ex) {/*nothing*/}
		},
		
		bindSearchTermEvents: function() {
			if (jQuery( "input.sg" ).length > 0 ) {
				jQuery( "input.sg" ).each(function(k, inp) {
					jQuery(inp).focus(function() {
						if (formtoolConstants.SEARCHTERMS.indexOf(jQuery(inp).val()) != -1 ) {
							jQuery(inp).val("");
						}
					});
				});
			}
		}	
	},
	
	/*****************************************************************************
	 *** Some dirty little Helpers
	 ****************************************************************************/
	helper: {
		
		getElementName: function(elem) {
			if (elem.attr(formtoolConstants.ELEMENT_ATTRIBUTE_NAME)) {
				elemName = elem.attr(formtoolConstants.ELEMENT_ATTRIBUTE_NAME);
				if (elemName.indexOf(formtoolConstants.ELEMENT_ATTRIBUTE_NAME_IDENTIFIER_BEGIN) == 0) {
					return elemName.substring(formtoolConstants.ELEMENT_ATTRIBUTE_NAME_IDENTIFIER_BEGIN.length, elemName.length-formtoolConstants.ELEMENT_ATTRIBUTE_NAME_IDENTIFIER_END.length);
				}
			}
			if (elem.attr(formtoolConstants.ELEMENT_ATTRIBUTE_ID)) {
				elemId = elem.attr(formtoolConstants.ELEMENT_ATTRIBUTE_ID);
				if (elemId.indexOf(formtoolConstants.ELEMENT_ATTRIBUTE_ID_IDENTIFIER) == 0) {
					return elemId.substring(formtoolConstants.ELEMENT_ATTRIBUTE_ID_IDENTIFIER.length, elemId.length);
				}
			}
		},
		
		getElementType : function(elem) {
			if(elem) {
				if (elem.length > 1) {
					elem = jQuery(elem[0]);
				}
				if (elem.attr('tagName').toLowerCase() == formtoolConstants.ELEMENT_INPUT) {
					return elem.attr('type').toLowerCase();
				} else {
					return elem.attr('tagName').toLowerCase();
				}
			}
		},
		
		getElementLabel: function(elem) {
			if (elem) {
				if (elem.length > 1) {
					var elemName = formtool.helper.getElementName(jQuery(elem[0]));
					if (elemName != '') {
						return jQuery('#' + formtoolConstants.ELEMENT_ENV_WRAP_DIV + elemName + ' > span');
					}
				} else {
					var elemId = elem.attr('id');
					return jQuery("label[for="+elemId+"]");
				}
			}
		},
		
		/**
		 * Submitted die Form, welche das uebergebene Element enthaelt.
		 */     		
		submitParentForm: function(elem) {
			var parent = elem.parents('form');
			if (parent) {
				jQuery(parent).submit();
			}
		},
		
		
		hideElement: function(elem) {
			if (elem) {
				if (elem.length > 1) {
					elem = jQuery(elem[0]);
				}
				var name = formtool.helper.getElementName(elem);
				if (name != '') {
					jQuery('#' + formtoolConstants.ELEMENT_ENV_WRAP_DIV + name).hide();
				}
			}
		},
		
		showElement: function(elem) {
			if (elem) {
				if (elem.length > 1) {
					elem = jQuery(elem[0]);
				}
				var name = formtool.helper.getElementName(elem);
				if (name != '') {
					jQuery('#' + formtoolConstants.ELEMENT_ENV_WRAP_DIV + name).show();
				}
			}
		},
		
		
		toString : function(val) {
			var str = '{';
			jQuery.each(val, function(key, value) {
				if (str.length > 1) str += ',';
				str += key+':'+value;
			});
			return str + "}";
		},
		
		radioSort: function(a, b) {
			if (jQuery(a).attr('checked')) {
				return -1;
			} else if (jQuery(b).attr('checked')) {
				return 1;
			} else {
				return 0;
			}
		}
	}
	
};

if (!Array.prototype.indexOf) {

	Array.prototype.indexOf = function(elt /*, from*/) {
	
		var len = this.length >>> 0;
		var from = Number(arguments[1]) || 0;
			from = (from < 0) 
				 ? Math.ceil(from) 
				 : Math.floor(from);
			
		if (from < 0) {
			from += len;
		}
		for (; from < len; from++) {
			if (from in this && this[from] === elt)			
			return from;
		}
		return -1;
	};
}

