window.org=window.org||{};org.apache=org.apache||{};org.apache.myfaces=org.apache.myfaces||{};if(!org.apache.myfaces.Popup){org.apache.myfaces.popupFrameUnder=null;org.apache.myfaces.popupCurrentlyOpenedPopup=null;org.apache.myfaces.Popup=function(A,C,B){this.popupId=A;this.displayAtDistanceX=C;this.displayAtDistanceY=B;this.isIE6=document.all&&!window.opera&&!window.XMLHttpRequest;};org.apache.myfaces.Popup.prototype.display=function(B){if(org.apache.myfaces.popupCurrentlyOpenedPopup!=null){org.apache.myfaces.popupCurrentlyOpenedPopup.style.display="none";}var A;var D;if(window.event){if(org.apache.myfaces.popupFrameUnder!=null){org.apache.myfaces.popupFrameUnder.style.display="none";}A=window.event.clientX;A+=this.popupGetScrollingX();D=window.event.clientY;D+=this.popupGetScrollingY();}else{A=B.pageX;D=B.pageY;}A+=this.displayAtDistanceX;D+=this.displayAtDistanceY;var C=document.getElementById(this.popupId);if(C.style.display!="block"){C.style.display="block";C.style.left=""+A+"px";C.style.top=""+D+"px";org.apache.myfaces.popupCurrentlyOpenedPopup=C;}this.ieIFrameFix();};org.apache.myfaces.Popup.prototype.hide=function(){var A=document.getElementById(this.popupId);A.style.display="none";if(document.all&&(org.apache.myfaces.popupFrameUnder!=null)){org.apache.myfaces.popupFrameUnder.style.display="none";}this.ieIFrameFix();};org.apache.myfaces.Popup.prototype.redisplay=function(){var A=document.getElementById(this.popupId);A.style.display="block";org.apache.myfaces.popupCurrentlyOpenedPopup=A;this.ieIFrameFix();};org.apache.myfaces.Popup.prototype.popupGetScrollingX=function(){if(self.pageXOffset){return self.pageXOffset;}else{if(document.documentElement&&document.documentElement.scrollLeft){return document.documentElement.scrollLeft;}else{if(document.body){return document.body.scrollLeft;}else{return 0;}}}};org.apache.myfaces.Popup.prototype.popupGetScrollingY=function(){if(self.pageYOffset){return self.pageYOffset;}else{if(document.documentElement&&document.documentElement.scrollTop){return document.documentElement.scrollTop;}else{if(document.body){return document.body.scrollTop;}else{return 0;}}}};org.apache.myfaces.Popup.prototype.ieIFrameFix=function(){if(this.isIE6){if(org.apache.myfaces.popupCurrentlyOpenedPopup==null){return false;}var B=document.getElementById(org.apache.myfaces.popupCurrentlyOpenedPopup.id+"_IFRAME");if(B==null){org.apache.myfaces.popupFrameUnder=document.createElement("<iframe src='javascript:false;' id='"+org.apache.myfaces.popupCurrentlyOpenedPopup.id+"_IFRAME' style='visibility:hidden; position: absolute; top:0px;left:0px; filter:alpha(Opacity=0);' frameborder='0' scroll='none' />");document.body.insertBefore(org.apache.myfaces.popupFrameUnder);}else{org.apache.myfaces.popupFrameUnder=B;}var A=org.apache.myfaces.popupCurrentlyOpenedPopup;B=org.apache.myfaces.popupFrameUnder;if(A!=null&&(A.style.display=="block")){A.style.zIndex=99;B.style.zIndex=A.style.zIndex-1;B.style.width=A.offsetWidth;B.style.height=A.offsetHeight;B.style.top=A.style.top;B.style.left=A.style.left;B.style.marginTop=A.style.marginTop;B.style.marginLeft=A.style.marginLeft;B.style.marginRight=A.style.marginRight;B.style.marginBottem=A.style.marginBottom;B.style.display="block";B.style.visibility="visible";}else{B.style.display="none";}}return false;};}(!window.myfaces)?window.myfaces={}:null;if(!myfaces.oam){myfaces.oam=new function(){this.setHiddenInput=function(E,B,D){var C=document.forms[E];if(typeof C=="undefined"){C=document.getElementById(E);}if(typeof C.elements[B]!="undefined"&&(C.elements[B].nodeName=="INPUT"||C.elements[B].nodeName=="input")){C.elements[B].value=D;}else{var A=document.createElement("input");A.setAttribute("type","hidden");A.setAttribute("id",B);A.setAttribute("name",B);A.setAttribute("value",D);C.appendChild(A);}};this.clearHiddenInput=function(E,A,D){var C=document.forms[E];if(typeof C=="undefined"){C=document.getElementById(E);}var B=C.elements[A];if(typeof B!="undefined"){C.removeChild(B);}};this.submitForm=function(L,K,I,C){var F="clearFormHiddenParams_"+L.replace(/-/g,"$:").replace(/:/g,"_");if(typeof window[F]=="function"){window[F](L);}var A=document.forms[L];if(typeof A=="undefined"){A=document.getElementById(L);}if(myfaces.core.config.autoScroll&&typeof window.getScrolling!="undefined"){myfaces.oam.setHiddenInput(L,"autoScroll",getScrolling());}if(myfaces.core.config.ieAutoSave){var E=navigator.userAgent.toLowerCase();var J=navigator.appVersion;if(E.indexOf("msie")!=-1){if(!(E.indexOf("ppc")!=-1&&E.indexOf("windows ce")!=-1&&J>=4)){window.external.AutoCompleteSaveForm(A);}}}var H=A.target;if(I!=null){A.target=I;}if((typeof C!="undefined")&&C!=null){for(var D=0,B;(B=C[D]);D++){myfaces.oam.setHiddenInput(L,B[0],B[1]);}}myfaces.oam.setHiddenInput(L,L+":"+"_idcl",K);if(A.onsubmit){var M=A.onsubmit();if((typeof M=="undefined")||M){try{A.submit();}catch(G){}}}else{try{A.submit();}catch(G){}}A.target=H;if((typeof C!="undefined")&&C!=null){for(var D=0,B;(B=C[D]);D++){myfaces.oam.clearHiddenInput(L,B[0],B[1]);}}myfaces.oam.clearHiddenInput(L,L+":"+"_idcl",K);return false;};};}(!myfaces.core)?myfaces.core={}:null;(!myfaces.core.config)?myfaces.core.config={}:null;
/**
 * Helper to 'declare' packages.
 * @param packageName
 */
function use_package(packageName) {
	if (typeof (packageName) != "string") {
		throw new Error("Can only declare packages in string format!")
	}
	var packageParts = packageName.split(".")
	    currentPackage = window,
	    i = 0,
	    len = packageParts.length;
	for (; i < len; i++) {
		if (!currentPackage[packageParts[i]]) {
			currentPackage[packageParts[i]] = {};
		}
		currentPackage = currentPackage[packageParts[i]];
	}
}
use_package("de.his.common");

/**
 * Some common utils.
 */
de.his.common.Util = new function() {
    /**
     * Translates exceptions to a string.
     */
    this.toExceptionMessage = function(e) {
        if (typeof e === "string") {
            return e;
        }
        return "Exception '" + e.message + "' at line " + e.lineNumber;
    };

    /**
     * Converts the given JSF client id so that it could be used within jQuery selectors.
     */
    this.toJQueryId = function(jsfClientId) {
    	return jsfClientId.replace(/:/g, '\\:');
    };
    
    this.escapeHtml = function (text) {
        return text
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#039;");
    };
    
    this.getQueryParam = function(param) {
        var found,
            items = window.location.search.substr(1).split("&"),
            it;
        //http://jsperf.com/url-query-search
        for(var i = 0, l = items.length; i<l; i++){
            it = items[i].split( "=" );
            if (param === it[0]) {
                found = it[1];
                break;
            }
        }
        
        return found;
    };



    /**
     * Erzeugt ein neues Popup-Fenster für die URL
     * @param url
     */
    this.openPopupWindow = function(url) {
        var left = (screen.width/2)-(screen.width/3);
        var top = (screen.height/2)-(screen.height/3);
        var params = 'width=' + (screen.width*2/3) + ', height=' + (screen.height*2/3) + ', resizeable, scrollbars, top=' + top + ', left=' + left;
        if (typeof(popupWindowRef) == 'undefined' || popupWindowRef.closed) {
            popupWindowRef = window.open(url, 'popupWindowRef', params); // neues Popup
        } else {
            popupWindowRef.location.href = url; // Erneuere die URL und hole Popup in Focus
            popupWindowRef.focus();
        }
    };
    
    var alreadyLoadedFiles = {};
    /**
	 * Filepath of js files to load. String or an Array of Strings
	 */
	this.loadFile = function (filepath, callback, async){
		
		if(filepath){
			
			//if filepath is just a string - then convert to array with 1 entry
			if(!jQuery.isArray(filepath)){
				filepath = [filepath];
			}
			
			var filesLoaded = 0, //fileloaded counter
				file,
				callbackFunction = function(){
					//if all the files have loaded
					if(filesLoaded === filepath.length){
						//check to see if there is a callback function to call
						if(jQuery.isFunction(callback)){
							callback.call();
						}
					}
				};
				
			for(var i = 0, l = filepath.length; i<l; i++){
				file = filepath[i];
				if(!alreadyLoadedFiles[file]){
					//file hasn't been loaded before - so load it now
					jQuery.ajax({
						async:typeof async === "boolean" ? async : true,
						dataType:'script',
					 	url:file,
					    success:function(){
					    	filesLoaded++;	//increment counter
					    	alreadyLoadedFiles[file] = true; //mark file as loaded
					    	callbackFunction();
					    },
					    error:function(){
					    	console.error("error whilst loading file:", file);
					    }
				    });
				}else{
					filesLoaded++;	//increment counter
					callbackFunction();
				}
				
			}
			
		}else{
			console.error("no filepath defined, nothing is loaded");
		}
	}
	
	this.sleep = function (milliseconds) {
		console.log("Sleeping for "+milliseconds+" ms. DO NOT USE IN PRODUCTION!")
		var start = new Date().getTime();
		for (var i = 0; i < 1e7; i++) {
			if ((new Date().getTime() - start) > milliseconds){
				break;
			}
		}
	}
    
};

/**
 * Context information / metadata of the server / from JSF to be used in Javascript.
 * The metadata is stored with a DOM-element rendered by '<his:globalJavascriptContextInformation />'.
 * This compoent must be included in every layout where global metadata is used in javascript.
 *
 * Additional metadata have to be declared in the xhtml-file named above.
 *
 * TODO: Automatisch durch PreRenderListener von JSF inkludieren lassen?
 *
 */
de.his.common.ContextInformation = new function() {

    var context;

    this.get = function(property) {
    	context = jQuery("#contextInformation");
    	return context.data(property);
    };

    this.set = function(property, value) {
    	context = jQuery("#contextInformation");
    	return context.data(property, value);
    };

    this.isEditUITexts = function() {
        return this.get('is-edit-ui-texts') == true;
    };
};

/**
 * Ermittelt die aktuelle System-Sprache
 */
de.his.common.LanguageHelper = new function() {
    var language;

    this.currentLanguage = function() {
        if (!language) {
            language = jQuery('html').attr('lang');
            if (!language) {
                language = 'de';
            }
        }
        return language;
    };
};

de.his.common.browser = new function(){
	
	var checkForString =  function(name){
		return navigator.userAgent.toLowerCase().indexOf(name.toLowerCase()) > -1 ? true : false;
	}
	
	this.isChrome = function(){
		return checkForString("chrome") && !checkForString("opr");
	}
	
	this.isFirefox = function(){
		return checkForString("firefox");
	}
	
	this.isIE = function(){
		return checkForString("msie") || checkForString("trident");
	}
	
	
/**
 * Add Class for IE
 */
	var ua = navigator.userAgent,
	doc = document.documentElement;
	if ((ua.match(/MSIE 10.0/i))) {
		doc.className = doc.className + " ie_old";
	} else if((ua.match(/rv:11.0/i))){
		doc.className = doc.className + " ie_old";
	}
	
}

/**
 * @param cursor - string (css value) - optional - defaults to "auto" 
 */
de.his.common.chromeCursorFix = function(cursor){
	var wkch = document.createElement("div");
    wkch.style.overflow = "hidden";
    wkch.style.position = "absolute";
    wkch.style.left = "0px";
    wkch.style.top = "0px";
    wkch.style.width = "100%";
    wkch.style.height = "100%";
    var wkch2 = document.createElement("div");
    wkch2.style.width = "200%";
    wkch2.style.height = "200%";
    wkch.appendChild(wkch2);
    document.body.appendChild(wkch);
    document.body.style.cursor = cursor || "auto";
    wkch.scrollLeft = 1;
    wkch.scrollLeft = 0;
    document.body.removeChild(wkch);
}

/**
 * IE bug fix - no contains method
 */
if ( !String.prototype.contains ) {
    String.prototype.contains = function() {
        return String.prototype.indexOf.apply( this, arguments ) !== -1;
    };
}

de.his.common.langSelected = function(select){
	var select = jQuery(select),
		option = select.find(":selected");
	//fire language change
	window.location = option.attr("data-value");
}


de.his.common.getAlreadyLoadedResources = function() {
	var list = performance.getEntriesByType("resource");
	if (list === undefined) {
		return[];
	}

  	var names = [];

  	for (var i=0; i < list.length; i++) {
		names.push(list[i].name);
	}

   	return names;	
}/**
 * Auf Cookies zugreifen
 */
de.his.common.Cookie = new function() {
	
	this.areCookiesEnabled = function (){
	    // Quick test if browser has cookieEnabled host property
	    if (navigator.cookieEnabled) return true;
	    // Create cookie
	    document.cookie = "cookietest=1; SameSite=Lax; Secure";
	    var ret = document.cookie.indexOf("cookietest=") != -1;
	    // Delete cookie
	    document.cookie = "cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT";
	    return ret;
	}

    this.create = function(name, value) {
        this.createWithPath(name, value, de.his.common.ContextInformation.get('context-path'));
    };

    this.createWithPath = function(name, value, path) {
    	var cookie = name + '=' + value + '; path=' + path +"; SameSite=Lax;Secure";  
    	
    	// Der Path soll immer nur den Servernamen enthalten.
    	if (name == "lastRefresh" && (path.lastIndexOf("/") > path.indexOf("/"))) {
	    	alert("Setting cookie with bad path. Report to SYS (JOL): " + cookie);
    	}
        document.cookie = cookie;
    };

    this.read = function(name) {
        var nameEQ = name + '=',
            ca = document.cookie.split(';'),
            i = 0;
        for (; i < ca.length; i++) {
            var c = ca[i];
            while (c && c.charAt(0) == ' ') {
                c = c.substring(1, c.length);
            }
            if (c.indexOf(nameEQ) == 0) {
                return c.substring(nameEQ.length, c.length);
            }
        }
        return null;
    };
    
    this.erase = function(name) {
        this.eraseWithPath(name, de.his.common.ContextInformation.get('context-path'));
    };

    this.eraseWithPath = function(name, path) {
    	var cookie = name + '=0; path=' + path +"; SameSite=Lax; expires=Thu, 01-Jan-1970 00:00:01 GMT";  
    	document.cookie = cookie;
    };
    
    // common function aliases
    this.get = this.read;
	this.set = this.create;
	this.del = this.erase;
};/**
 * Initializes some HISinOne JS functionality.
 * 
 * Modules to be initialized need a method 'init'. Modules to be refreshed after AJAX requests need a 'refresh' method.
 */

/**
 * sets console loglevel
 */
jQuery("#contextInformation").ready(function(){
	
	// # LOG, DEBUG, INFO, WARN, ERROR
var jsLoglevel = de.his.common.ContextInformation.get('jsconsoleLoglevel');
	window = window['hisJsLoglevel'] = jsLoglevel;
	
	var setLogLevel = function( methods ) {
		for (var i = 0; methods.length > i; i++) {
    		window.console[ methods[ i ] ] = function() {};
        }
    };
    
    // debug a single page without JS debugging enabled globally.
    if(window.location.href.endsWith("jsdebug")){
    	jsLoglevel = 'LOG';
    	console.info("JS-Console loglevel set to '", jsLoglevel, "' for one request.");
    } else {
    	console.info("JS-Console loglevel set to '", jsLoglevel, "'. Set loglevel in DispatcherProperties with HIS_JS_CONSOLE_LOGLEVEL=LOG/DEBUG/INFO/WARN/ERROR.");
    }
    
	if(jsLoglevel === "DEBUG"){
		setLogLevel( ["log"] );
	}else if(jsLoglevel === "INFO"){
	    setLogLevel( ["log", "debug"] );
	}else if(jsLoglevel === "WARN"){
	    setLogLevel( ["log", "debug", "info"] );
	}else if(jsLoglevel === "ERROR"){
	    setLogLevel( ["log", "debug", "info", "warn"] );
	}
});


/**
 * initializes all modules by calling init() on document.ready
 */
jQuery(document).ready(function() {
    de.his.modules.ModuleRegistry.initializeAll();
	window.allHISinOneModulesInitialized = true;
});

use_package("de.his.modules");

de.his.modules.eventRegistry = new function(){
	var eventReg = {};
	var eventCounter = 0;	// increased with each event registered
	
	/**
	 * @param eventName - string
	 * @param func - function to be called when eventName is fired
	 * @param scope - object - optional
	 * @param destoryWhenFired - boolean - optional - default false : when the listener is fired once then it is destroyed
	 */
	this.addListener = function(eventName, func, scope, destoryWhenFired){
		if(!eventReg[eventName]){
			eventReg[eventName] = [];
		}
		
		if(func){
			console.log("registering event: ", eventName);
			func.eventId = eventCounter++;	// give the function an eventId
			func.eventName = eventName;	// register eventName too
			console.log("listener registered for event", func.eventName, "with Id", func.eventId);
			eventReg[eventName].push({
						func:func, 
						scope:scope,
						destoryWhenFired:destoryWhenFired
					});
		}else{
			console.warn("no function defined when adding a listener", eventName);
		}
	};

	// fire events by name across the application
	this.fireEvent = function(eventName){
		console.log("fired event: ", eventName);
		var events = eventReg[eventName] || [], 
			value;
		for(var i = 0, l = events.length; i<l; i++){
			value = events[i];
			if(value && value.func){
				if(value.scope){
					value.func.apply(value.scope);
				}else{
					value.func.call();
				}
				
				if(value.destoryWhenFired === true){
					this.destroyListener(value.func);
				}
			}
			
		}
	};
	
	/**
	 * @param func = function itself
	 */
	this.destroyListener = function(func){
		// TODO: allow func to be an array of listeners
		if(func){
			var eventName = func.eventName, 
			events = eventReg[eventName],	//array of objects {} see addListener for more details
			eventId = func.eventId;
			console.log("destroy listener registered for event", eventName, "with Id", eventId);
			// iterate all events for given eventName;
			for(var i = 0, l = events.length; i<l; i++){
				//check to see if the iterated event has the same eventId as the parameter func
				if(events[i].func.eventId == eventId){
					eventReg[eventName].splice(i, 1);
					break;
				}
			}
		}
	};
	
	/**
	 * @param - eventName (string), destroys all listeners for the given eventName
	 * beware! this could destroy system based events - use destroyListener() instead and destroy each listener at a time
	 */
	this.destroyEvent = function(eventName){
		delete eventReg[eventName];
	};
	
	
	
};

/**
 * Registry of modules that want to be initialized on startup and / or refreshed after ajax requests.
 */
de.his.modules.ModuleRegistry = new function() {
    var initModules = [];
    var ajaxRefreshModules = [];
    var ajaxStartModules = [];
    var asyncScripts = [];
    /**
	 * check if initialized, see bug:109744
	 */
    var hasModuleIntialized = function(module){
    	return module.moduleIntialized;
    };
    
    this.registerModule = function(module) {
        initModules.push(module);
        return this;
    };
    
    this.registerAjaxRefreshModule = function(module) {
        ajaxRefreshModules.push(module);
        return this;
    };

    this.registerAjaxStartModule = function(module) {
        ajaxStartModules.push(module);
        return this;
    };

    this.initializeAll = function() {
    	
        callModules(initModules, 'init', "Error initialising HISinOne-JS-Module!");
    };
    
    this.refreshAll = function(data) {
    	// check if initialised, see bug:109744
    	
    	if(initModules.length == 0){
    		console.warn("attempting refresh when no modules where initalized.... initalizing all modules");
    		this.initializeAll();
    	}
    	
    	de.his.modules.ModuleRegistry.loadScriptsFromSpan();
    	
    	if(ajaxRefreshModules.length > 0){
    		// double check to see if any module hasn't loaded yet
    		for(var i = 0, l = ajaxRefreshModules.length; i<l; i++){
    			if(!hasModuleIntialized(ajaxRefreshModules[i])){
    				console.warn("trying to refresh un-initialized module... init attempt first", ajaxRefreshModules[i]);
    				callModules([ajaxRefreshModules[i]], 'init', "Error initialising HISinOne-JS-Module!");
    			}
    		}
    	}
    	
    	callModules(ajaxRefreshModules, 'refresh', "Error refreshing HISinOne-JS-Module after AJAX request!", data);
    };

    this.indicateAjaxRequestStart = function() {
        callModules(ajaxStartModules, 'indicateAjaxRequestStart', "Error indicating ajax start to HISinOne-JS-Module!");
    };
    
    var executeFunctionByName = function(functionName, context /*, args */) {
		console.log("execute function: "+functionName+ " on: ",context);
	    var args = Array.prototype.slice.call(arguments, 2);
	    var namespaces = functionName.split(".");
	    var func = namespaces.pop();
	    try{
	    	for (var i = 0; i < namespaces.length; i++) {
		        context = context[namespaces[i]];
		    }
		    return context[func].apply(context, args);
	    } catch (e){
	    	console.log("Could not init script. This might be ok. ", e);
	    	return false;
	    }
	}
    
	var getCallbackFunction = function(callbackObject){
		var callback = function(response){
			executeFunctionByName(callbackObject+".init", window);
		};
		return callback;
	}
    
    this.loadScript = function (url, callbackObject) {
    	if(asyncScripts.indexOf(url) > -1){
			// do not load script if it already has been loaded dynamically
			console.log("%s already loaded ", src);
			return;
		}
		loadScript(url,getCallbackFunction(callbackObject));
		asyncScripts.push(url);
	};
	
	var loadScript = function (url, callback) {
		console.log("Async loading Script: "+ url);
		 jQuery.ajax({
			 url: url,
			 dataType: 'script',
			 success: callback,
			 async: true
		 });
	};
    /**
	 * DOES: 
	 * - searches for span.loadScript [data-library] [data-script] [data-callback-object]
	 * - load them damn scripts dynamically into the site 
	 * - initialize them damn scripts on successful load by calling [data-callback-object].init()
	 * - refresh and ajaxStart functions are working magically, those register automatically when the Module gets initialized.
	 */
	this.loadScriptsFromSpan = function(){
		jQuery("span.loadScript[data-library][data-script][data-callback-object]").each(function(index, elem){
			//console.log("initModules",initModules);
			
			var library = jQuery(elem).data('library');
			var script = jQuery(elem).data('script');
			var refresh = jQuery(elem).data('refresh');
			var callbackObject = jQuery(elem).data('callback-object');
			var qisserverUrl = de.his.common.ContextInformation.get('context-path');
			var url = qisserverUrl+"/javax.faces.resource/"+script+".xhtml?ln="+library;
			
			var initModulesContain = function(moduleName){
				// check if any loaded JS has the given module name
				var val = false;
				 for ( var i = 0, length = initModules.length; i < length; i++) {
					 if(initModules[i].moduleName === moduleName){
						 val = true;
					 }
				 }
				 console.log("initModulesContain: "+ moduleName+" ? "+val);
				 return val;
			}
			console.log("trying to load script dynamically: "+ script, callbackObject);
			
			if(asyncScripts.indexOf(script) > -1){
				// do not load script if it already has been loaded dynamically
				console.log("script already loaded "+ script);
				return;
			}
			asyncScripts.push(script);
			
			if(initModulesContain(callbackObject)){
				// Do not load module if JSF already included it
				console.log("script already loaded by JSF: "+ script);
				return;
			}
			
			loadScript(url,getCallbackFunction(callbackObject));
		});
	};
	
    var callModules = function(modules, method, errorBaseMessage, data) {   	
        for ( var i = 0, length = modules.length; i < length; i++) {
            try {
            	console.log('', method, ' on: ', modules[i].moduleName);
                modules[i][method](data);
                if(method == "init"){
                	modules[i].moduleIntialized = true;
                }
            } catch (e) {
            	console.error(errorBaseMessage + " Src: "+modules[i].moduleName+"."+method+" (" + de.his.common.Util.toExceptionMessage(e) + ")");
            }
        }
    };
    
};
//Current workaround to warn users using android browser or other (not chrome) on a mobile device, that the browser is not supported
// Eventually to be removed
de.his.modules.mobile = new function(){
	var me = this;
	de.his.modules.ModuleRegistry.registerModule(this);
	
	this.moduleName = "de.his.modules.mobile";
	
	this.mobile = {
			/**
			 * @property warnDelay
			 * @type {Integer} days
			 * @default 30
			 */
			warnDelay: 30,
			/**
			 * @property _cacheKey
			 * @private
			 * @type {String}
			 * @default "_his.mobile.browser.warning"
			 */
			_cacheKey: "_his.mobile.browser.warning",
			/**
			 * check whether the user has been warned
			 * @method hasBeenWarned
			 * @return {Boolean}
			 */
			hasBeenWarned: function(){
				var me = this;
				return !!me.getCacheValue( me._cacheKey );	//convert to boolean
			},
			/**
			 * @method getCacheValue
			 * @returns
			 */
			getCacheValue: function(){
				var me = this;
				if(typeof window.localStorage !== 'undefined'){
					return window.localStorage.getItem( me._cacheKey );
				} else {
				    return 0;
				}
				
			},
			/**
			 * checks whether the warn message is due to show itself again
			 * @method hasWarningExpired
			 * @return {Boolean}
			 */
			hasWarningExpired: function(){
				var me = this,
					currentTime = new Date().getTime();
				if(!me.hasBeenWarned() || (currentTime > me.getCacheValue()) ){
					return true;
				}
				return false;
			},
			/**
			 * sets the cache key that the user has been warned
			 * @method setWarning
			 */
			setWarning: function(){
				var me = this,
					timestamp = new Date().getTime() + (me.warnDelay * 24 * 60 * 60 * 1000);	//30 days from now
				return window.localStorage.setItem( me._cacheKey,  timestamp );
			},
			/**
			 * @method init
			 */
			init: function(){
				var me = this,
		       		device = window.device;

				if(typeof localStorage !== "undefined" && device){
					var storage = window.localStorage;
					if(device.android() && !de.his.common.browser.isChrome()){
						if( me.hasWarningExpired() ){
							me.setWarning();
		   					alert("Bitte verwenden Sie Google Chrome als Standardbrowser für diese Webseite. <br /> Please use Google Chrome as standard browser for this webpage.");
	    	   			}
					}
				}
			}
	};
	
	this.init = function(){
		return me.mobile.init();
	};
	
};/**
 * @Author: masala, wahrendorff
 * This is for non-module specific fixes/features etc
 * TODO: 
 */
use_package("de.his.modules");
de.his.modules.GeneralFixes = new function() {
	de.his.modules.ModuleRegistry.registerModule(this).registerAjaxRefreshModule(this);
	
    this.moduleName = "de.his.modules.GeneralFixes";
    
    this.init = function() {
    	de.his.modules.GeneralFixes.fixTablePagerMaxValidation();
    	de.his.modules.GeneralFixes.fixCheckboxesWithLeftLabels();
    	de.his.modules.GeneralFixes.showCheckboxesWithoutLabelsWorkaround();
    	fixTomahawkJSPopupPosition();
    	handleInfoboxHide();
    }
    this.refresh = function() {
    	de.his.modules.GeneralFixes.init();
    }
    
    var handleInfoboxHide = function () {
	    var handleClicksAndPropagation = function(e,infoboxCloseBtn){
	    	// stop bubbling and propagation, cause burgermenu would close again when infobox is opened and automatically closed upon menu call.
	    	infoboxCloseBtn.on('click', function(){
	    		e.stopPropagation();
	    		return false;
	    	});
	    	infoboxCloseBtn.click();
	    	infoboxCloseBtn.off('click');
	    }
        // hide infobox when user clicks somewhere else in the page
        // caveeat: does not work when user clicks on iframes.
        // does not propagade click events on closing infoboxes (due to problems with burgermenu)
        //jQuery(document).off('click');
        if(jQuery("html").data('infoboxHandlerInitialized') === 'true'){
        	return;
        }
        jQuery(document).on("click", function (e) {
        	jQuery("html").data('infoboxHandlerInitialized','true');

			if(jQuery(e.target).hasClass("loadContent-behavior")){
				// do not close Infobox on automated loading Button clicks.
				return;
			}
			//console.log("clicked somewhere, target is: ", jQuery(e.target));
			//console.log("clicked somewhere, find collapsibleHeaderActionFrom: ", jQuery(e.target).closest('#collapsibleHeaderActionFrom'));
			// close all visible portalinfoboxes of service Header on elsewhere click            
            if (!jQuery(e.target).closest("[id$='collapsibleHeaderActionFrom']").length && !jQuery(e.target).closest('.confirm_infobox').length) {
            	//[id$='txtTitle']
            	if (jQuery('#infoboxElement') && jQuery('#infoboxElement').find(".infoboxContainer").html()) {
	            	//console.log("close infoboxElement:visible");
	            	handleClicksAndPropagation(e,jQuery("[id$='collapsibleHeaderActionFrom\\:infobox\\:close']"));
	            }
                if (jQuery('#userInformationCenterElement') && jQuery('#userInformationCenterElement').find(".infoboxContainer").html()) {
	            	//console.log("close userInformationCenterElement:visible");
	            	handleClicksAndPropagation(e,jQuery("[id$='collapsibleHeaderActionFrom\\:userInformationCenter\\:close']"));
	            }
	            if (jQuery('#systemInformationCenterElement') && jQuery('#systemInformationCenterElement').find(".infoboxContainer").html()) {
	            	//console.log("close systemInformationCenterElement:visible");
	            	handleClicksAndPropagation(e,jQuery("[id$='collapsibleHeaderActionFrom\\:systemInformationCenter\\:close']"));
	            }
	            if (jQuery('#myJobs') && jQuery('#myJobs').find(".infoboxContainer").html()) {
	            	//console.log("close myJobs:visible");
	            	handleClicksAndPropagation(e,jQuery("[id$='collapsibleHeaderActionFrom\\:myJobsInfobox\\:myJobsInfoBox\\:close']"));
	            }
            }
            
            var clickedLink = jQuery(e.target).closest('a');
            //close all other portalinfoboxes on portalinfobox open click
            if(clickedLink && typeof jQuery(clickedLink).attr("id") !== 'undefined' && jQuery(clickedLink).attr("id").endsWith("open") && jQuery(clickedLink).attr("id").startsWith("collapsibleHeaderActionFrom")){
            	console.log("click portalinfobox open", clickedLink);
            	if (jQuery('#infoboxElement') && jQuery('#infoboxElement').find(".infoboxContainer").html() && !jQuery(clickedLink).attr("id").includes("infobox")) {
	            	//console.log("close infoboxElement:visible");
                	handleClicksAndPropagation(e,jQuery("[id$='collapsibleHeaderActionFrom\\:infobox\\:close']"));
	            }
                if (jQuery('#userInformationCenterElement') && jQuery('#userInformationCenterElement').find(".infoboxContainer").html() && !jQuery(clickedLink).attr("id").includes("userInformationCenter")) {
	            	//console.log("close userInformationCenterElement:visible");
	            	handleClicksAndPropagation(e,jQuery("[id$='collapsibleHeaderActionFrom\\:userInformationCenter\\:close']"));
	            }
	            if (jQuery('#systemInformationCenterElement') && jQuery('#systemInformationCenterElement').find(".infoboxContainer").html() && !jQuery(clickedLink).attr("id").includes("systemInformationCenter")) {
	            	//console.log("close systemInformationCenterElement:visible");
	            	handleClicksAndPropagation(e,jQuery("[id$='collapsibleHeaderActionFrom\\:systemInformationCenter\\:close']"));
	            }
	            if (jQuery('#myJobs') && jQuery('#myJobs').find(".infoboxContainer").html() && !jQuery(clickedLink).attr("id").includes("myJobsInfobox")) {
	            	//console.log("close myJobs:visible");
	            	handleClicksAndPropagation(e,jQuery("[id$='collapsibleHeaderActionFrom\\:myJobsInfobox\\:myJobsInfoBox\\:close']"));
	            }
            }
        });
    };
    
    var fixTomahawkJSPopupPosition = function(){
    	// we do not want to fix the tomahawk directly
    	// so we do it here
    	var popupElems = jQuery('.metadata_popup');
    	if(popupElems.length>0){
    		var observer = new MutationObserver(function(mutations) {
    			
        	    mutations.forEach(function(mutationRecord) {
        	        var popupElem = mutationRecord.target;
        	        var x = popupElem.style.left.replace('px','');
        	        // correct outer document limits.
        	        if (Number(popupElem.offsetWidth) + Number(x) > document.body.clientWidth){
        	        	console.log("Correct position of datdaDictPopup");
        	        	x = document.body.clientWidth - popupElem.offsetWidth;
        	        	popupElem.style.left = "" + x + "px";
        	        }
        	    });    
        	});
        	
        	popupElems.each(function(index, elem){
        		observer.observe(elem, { attributes : true, attributeFilter : ['style'] });
        	});
    	}
    }
    
    /**
     * TODO:
     * - should be removed when Umstellung is finished
     * Otherwise combine loops from here and fixCheckboxesWithLeftLabels for better performance
     */
    this.showCheckboxesWithoutLabelsWorkaround = function(){
    	jQuery('input[type="checkbox"]').each(function(){
    		if(typeof jQuery(this).attr('id') === 'undefined'){
    			return;
    		}
    		var checkboxId = de.his.common.Util.toJQueryId(jQuery(this).attr('id'));
    		if(!jQuery('label[for="'+checkboxId+'"]').length){
    			jQuery(this).css('opacity','1');
    			jQuery(this).wrap("<div class='thisCheckboxHasNoLabelError' title='Aufgrund der Umstellung auf grafische Checkboxen bitte die Checkbox per id/for mit einem Label verknüpfen. Bei Bedarf an einem unsichtbaren Label bitte an Team Styleguide wenden.'></div>");
    		}
    		
    		jQuery(this).on('focus',function(e){
				jQuery(this).addClass("checkbox-focus");
			});
    		jQuery(this).on('blur',function(e){
				jQuery(this).removeClass("checkbox-focus");
			});
    		
    	});
    };
    
    this.fixCheckboxesWithLeftLabels = function(){
    	/*
    	 * DONE:
    	 * select checkboxes with prev label and id = for
    	 * apply style
    	 * add change handler
    	 */
    	// select checkboxes
    	jQuery('input[type="checkbox"]').each(function(){
    		if(jQuery(this).data('checkboxified') == 'true'){
    			return true;
    		} else{
    			jQuery(this).data('checkboxified', 'true');
    		}
    		
    		// check if previous element is a label and belongs to the checkbox
    		var checkboxId = jQuery(this).attr('id');
    		var labelElem = jQuery(this).prev();
    		if(labelElem.hasClass("labelrequired")){
    			labelElem = labelElem.find('label');
    		}
    		console.log("labelElem:", labelElem)
    		if(labelElem.is('label') && labelElem.attr('for') == checkboxId){
    			// apply magic
    			if(typeof jQuery(this).attr('checked') === 'undefined'){
    				labelElem.addClass("checkbox-unchecked");
    			}else{
    				labelElem.addClass("checkbox-checked");
    			}
    			if(typeof jQuery(this).attr('disabled') !== 'undefined'){
    				labelElem.addClass("checkbox-disabled");
    			}
    			
    			jQuery(this).on('focus',function(e){
    				labelElem.addClass("checkbox-focus");
    			});
        		jQuery(this).on('blur',function(e){
        			labelElem.removeClass("checkbox-focus");
    			});
    			
    			// add changehandler to update checkbox image
    			jQuery(this).on('change',function(e){
    				if(e.target.checked){
    					labelElem.removeClass("checkbox-unchecked").addClass("checkbox-checked");
        			}else{
        				labelElem.removeClass("checkbox-checked").addClass("checkbox-unchecked");
        			}
    			});
    		}
    		
    	});
    };
    
    this.fixTablePagerMaxValidation = function(){
    	//Temp Fix for: #114282
    	//Stop the user from entering a number higher than 300 in the pager (tables)
    	jQuery("input.pagerInput_behaviour").keyup(function(){
    		var input = jQuery(this),
    			val = parseInt(input.val()),
    			maxInt = 300; //TODO: make 300 variable/configurable
    		
    			console.log("val:"+val);
    		var err = function(){
    			//TODO: get the text from messages (i18n texts)
    			//console.log("set input to 300");
    			//alert("Max: 0-300"); // creates Problems on second execution (alert box is out of pageview, Background curtain cannot be removed)
    			input.val(maxInt);
    		};
    		
    		if(val != NaN){
    			if(val > maxInt || val < 0){
    				//console.log("if call err");
    				err();
    			}
    		}else{
    			//console.log("else call err");
    			err();
    		}
    	});
    }
    
};use_package("de.his.portal");

/**
 * injects userinformation for autologin login
 */
de.his.portal.AutoLogin = new function() {
	de.his.modules.ModuleRegistry.registerModule(this); //	.registerAjaxRefreshModule(this);
		
	this.moduleName = "de.his.portal.AutoLogin";

	this.init = function() {
		console.log("autologinAllowed: " + de.his.common.ContextInformation.get('autologinAllowed'));
		console.log("userLoggedIn: " + de.his.common.ContextInformation.get('userLoggedIn'));
		
		if(de.his.common.ContextInformation.get('autologinAllowed') && !de.his.common.ContextInformation.get('userLoggedIn')){
			injectUserInfoIntoLoginForm();
		}
	};
	
	var injectUserInfoIntoLoginForm = function (){
		console.log("injectUserInfoIntoLoginForm start");
		jQuery("input[name='userInfo']").val(JSON.stringify(getUserInformations()));
	}
	
	var getTimeZone = function(){
		
		var d = new Date();
		return d.getTimezoneOffset();
	}

	var getScreenInfos = function() {
		//Unter FF kann das Screen-Objekt nicht direkt weiter gegeben werden
		var screen = {};
		screen["height"] = window.screen.height;
		screen["width"] = window.screen.width;
		screen["pixelDepth"] = window.screen.pixelDepth;
		return screen;
	};
	
	var getClientInformation = function() {
		var clientInformation = {};
		if (window) {
			if (window.clientInformation) {
				if (window.clientInformation.appCodeName) {
					clientInformation["appCodeName"] = window.clientInformation.appCodeName;
				}
				if (window.clientInformation.appName) {
					clientInformation["appName"] = window.clientInformation.appName;
				}
				if (window.clientInformation.cpuClass) {
					clientInformation["cpuClass"] = window.clientInformation.cpuClass;
				}
				if (window.clientInformation.platform) {
					clientInformation["platform"] = window.clientInformation.platform;
				}
			}
			if (window.navigator) {
				if (window.navigator.oscpu) {
					clientInformation["oscpu"] = window.navigator.oscpu;
				}
			}
		}
		return clientInformation;

	}

	var getUserInformations = function() {
		var userInfo = {};
		userInfo["test"] = "test";
		userInfo["screen"] = getScreenInfos();
		userInfo["timeZone"] = getTimeZone();
		userInfo["clientInformation"] = getClientInformation();
		return userInfo;

	};

//	this.refresh = function() {
//		this.init();
//	};
};
use_package("de.his.serviceworker");
/**
 * Handles ServiceWorker registration
 */
de.his.serviceworker.registration = new function() {
    de.his.modules.ModuleRegistry
        .registerModule(this);
    this.moduleName = "de.his.serviceworker.registration";
    
    this.serviceWorkerRegistered = false;
    this.swRegistration = null;
    
    
    // map class instance to self, since the context of "this" can change.
    var self = this;
    
    this.init = function() {
    	// disable Buttons if push is not configured or serviceWorkers are not supported
    	if(!('serviceWorker' in navigator)){
    		if(!('serviceWorker' in navigator)){
    			console.error('Service workers aren\'t supported in this browser.');  
    		}
    		return;
    	}
    	
    	// check if the service worker is registered
    	self.serviceWorkerRegistered = self.isServiceWorkerRegistered();
    	
    	//console.log("sw: ", navigator);
    	if(self.serviceWorkerRegistered){
//     		console.log("sw: ", navigator.serviceWorker);
//         	console.log("sw: ", navigator.serviceWorker.controller);
    	} else {
    		self.registerServiceWorker();
    	}
    };
    
	this.registerServiceWorker = function(){
		if(self.serviceWorkerRegistered && self.swRegistration != null){
    		console.log('ServiceWorker already registered');
    		de.his.modules.eventRegistry.fireEvent("serviceWorkerRegistered");
    		return self.swRegistration;
    	}
    	
		return navigator.serviceWorker.register(de.his.common.ContextInformation.get('context-path') + "/serviceworker.js",
		 { scope: de.his.common.ContextInformation.get('context-path') + "/", updateViaCache: 'all'})
		.then(function(registration) {
			self.swRegistration = registration;
			de.his.modules.eventRegistry.fireEvent("serviceWorkerRegistered");
			console.log('Service worker successfully registered.');
			return registration;
		}, function(err) {
				// registration failed :(
				console.log('ServiceWorker registration failed: ', err);
		}).catch(function(err) {
			console.error('Unable to register service worker.', err);
		});
    };
    
    this.unregisterServiceWorker = function(){
		navigator.serviceWorker.getRegistrations().then(function(r) {
			console.log('Removing ServiceWorker.');
			self.swRegistration = null;
			return Promise.all(r.map(function(reg){reg.unregister()}));
		}).catch(function(err){
			console.log('Removing ServiceWorker failed with error: ', err);
		});
    };
    
    this.isServiceWorkerRegistered = function(){
	    if ('serviceWorker' in navigator && navigator.serviceWorker !== null && typeof navigator.serviceWorker !== 'undefined') {
	    	if('controller' in navigator.serviceWorker && navigator.serviceWorker.controller !== null && typeof navigator.serviceWorker.controller !== 'undefined'){
	    		if( navigator.serviceWorker.controller.state === 'activated'){
	    			return true;
	    		}
	    	}else{
	    		return false;
	    	}
		} else{
			return false;
		}
    };
};
use_package("de.his.pwa");
/**
 * Handles ServiceWorker registration
 */
de.his.pwa.install = new function() {
    de.his.modules.ModuleRegistry
        .registerModule(this);
        
    this.moduleName = "de.his.pwa.install";
    
    // map class instance to self, since the context of "this" can change.
    var self = this;
    var deferredPrompt;
    var btnContainer = jQuery("#pwaInstallContainer");
    var installBtn = jQuery("#pwaInstallBtn");
    var dismissBtn = jQuery("#dismissPwaInstallBtn");
    
    this.init = function() {
		window.addEventListener('beforeinstallprompt', (e) => {
			console.log("beforeinstallprompt event triggered");
			// Prevent Chrome 67 and earlier from automatically showing the prompt
			e.preventDefault();
			
			if(typeof localStorage.getItem("pwa_install_dismissed") === 'undefined'
				|| localStorage.getItem("pwa_install_dismissed") === null
				|| (Date.now() - localStorage.getItem("pwa_install_dismissed")) > 2592000000 ){ // 30 Tage
				console.log("show install prompt");
				// Stash the event so it can be triggered later.
				deferredPrompt = e;
				// show the install button Container
				btnContainer.css("display","");
			} else {
				// day in ms: 86400000
				var time2NextInstall = (2592000000 - (Date.now() - localStorage.getItem("pwa_install_dismissed")))/86400000;
				console.log("time to new install prompt: "+time2NextInstall +" days.");
			}
			
		});
		
		installBtn.on('click', (e) => {
			// hide user interface that shows install button
			btnContainer.css("display","none");
			// Show the prompt
			deferredPrompt.prompt();
			deferredPrompt.userChoice.then((choiceResult) => {
				if (choiceResult.outcome === 'accepted') {
				  console.log('User accepted the A2HS prompt');
				} else {
				  console.log('User dismissed the A2HS prompt');
				}
				deferredPrompt = null;
			});
		});
		dismissBtn.on('click', (e) => {
			// hide user interface that shows install button
			btnContainer.css("display","none");
			
			deferredPrompt = null;
			
			// Set curretn timestamp to show dialog again in 30 days
			localStorage.setItem("pwa_install_dismissed", Date.now());
			
		});


    };
    
    
    
};
/**
 * Setzt den Focus auf das erste Element im content frame, das mit der Style-Klasse 'autofocus-behavior' gekennzeichnet ist.
 */
de.his.modules.Autofocus = new function() {
    de.his.modules.ModuleRegistry.registerModule(this).registerAjaxRefreshModule(this);
    
    this.moduleName = "de.his.modules.Autofocus";

    this.init = function() {
    	console.log("autofocus start");
    	manageFocus();
    	leftMenuClickHandler();
		manageFormStepFocus();
    };
    this.refresh = function() {
		// Nur neu initialisiren, wenn es sich um eine User-Query handelt.
		if( jQuery('.messages-infobox').data('infobox-type') == 'Query') {
	        this.init();		
		}
    };
    
	this.ajaxCallback = function(data) {
		console.log("AjaxCallback: " + data.status); //while ,data.status can be 1)"begin" 2)"complete" 3)"success"
		if (data.status === 'success') {
			manageFocus();
		}
    	
	};
    
    var leftMenuClickHandler = function(){
    	// Werden Untermenüpunkte im linken Navigationsmenü geklickt, soll auf der neuen Seite die Überschrift fokussiert werden.
        jQuery('a.linkNavigationSecond').click(function(e) {
        	if (window.localStorage) {
        		localStorage.setItem("leftMenuActivePageElementId", this.id);
        	}
        });

        // Wenn ein SubMenu Link geklickt wurde, soll der Link nach dem Öffnen wieder fokussiert werden.
        jQuery('a.linkNavigationFirst').click(function(e) {
        	if (window.localStorage) {
        		localStorage.setItem("leftSubMenuActivePageElementId", this.id);
        	}
        });
    };
    
    var manageFocus = function(){
    	// wenn overlay offen setze den focus auf jeden Fall im overlay
    	var parentSelector = "#contentFrame";
    	if(jQuery("div.overlay.modal").length > 0){
    		console.log("overlay found, *overlay.js calls setFocusAutomatically...")
    		parentSelector = "div.overlay.modal";
    		
    		// no left menu with overlay
    		//manageLeftMenuFocus();
    		return;
    	}

    	if (jQuery(parentSelector+" .autofocus-behavior").filter(':visible').length || jQuery(parentSelector+" .autofocus-behavior-focused").filter(':visible').length) {
    		de.his.modules.Autofocus.setFocusAutomatically(parentSelector);
    		
    	} else {
    		manageLeftMenuFocus();
    	}
    };
    
    /**
     * Set focus on first element with autofocus-behavior or first focusable element in container element
     */
    this.setFocusAutomatically = function(containerElementSelector){
    	
    		var element = jQuery(containerElementSelector);
		
    		if (jQuery(containerElementSelector+" .autofocus-behavior").filter(':visible').length) {
				element = jQuery(containerElementSelector+" .autofocus-behavior").filter(':visible').first();
			}
			
			// wenn klasse autofocus-behavior-focused gesetzt
			if (jQuery(containerElementSelector+" .autofocus-behavior-focused").filter(':visible').length) {
				// Zum fokussierbaren Element scrollen
				element = jQuery(containerElementSelector+" .autofocus-behavior-focused");
				// letzte geänderte Element wenn vorhanden und localstorage gesetzt ist
				if (localStorage.lastChangedField !== undefined && jQuery('*[id="'+localStorage.getItem('lastChangedField')+'"]').length !== 0 ) {
					element = jQuery('*[id="'+localStorage.getItem('lastChangedField')+'"]').filter(':visible');
				} else if(localStorage.lastChangedField) {
		 			localStorage.removeItem('lastChangedField');
				}
			}

    		console.log("autofocus found autofocus-behavior class. Element:",element);
    		
    		// Styleklasse könnte auf einem Div liegen, deshalb suchen wir in diesem nach relevanten Elementen. Das ist bspw. bei selectOneMenu der Fall!
	    	var getFocusableElement = function(element){
                //beachten, dass fokussierbare elemente einen noAutofocus parent haben können.
                var focusableElements = jQuery(element).find('a[href], area[href], input, select, textarea, button, iframe, object, embed, *[tabindex], *[contenteditable]').not('[tabindex=-1], [disabled], :hidden, .titleCollapseArea,.fieldsetHeadlineCollapseButton,.collapsableFieldsetHelpButton,.noAutofocus');
                console.log("focusableElements",focusableElements);
                var elemntToFocus;
                focusableElements.each(function(index,elem){
                    
                    if(!jQuery(elem).parents('.noAutofocus').length){
                        elemntToFocus = jQuery(elem);
                        return false;
                    }
                });
                console.log("elemntToFocus",elemntToFocus);
                return elemntToFocus;
            };
            var focusableElement = getFocusableElement(element);
            
	    	//var focusableElement = jQuery(element).find('a[href], area[href], input, select, textarea, button, iframe, object, embed, *[tabindex], *[contenteditable]').not('[tabindex=-1], [disabled], :hidden, .titleCollapseArea,.fieldsetHeadlineCollapseButton,.collapsableFieldsetHelpButton,.noAutofocus');
	    	
	    	if (focusableElement && focusableElement.length) {
	    		console.log("autofocus for focusable "+focusableElement.attr('id'));
	    		
	    		/**
	    		 * PRIMEFACES PATCH START
	    		 */
	    		// element is correct for this, its a div which has the autofocus behaviour class, focus is getting set to included input.
	    		if(element.hasClass("ui-selectonemenu") || focusableElement.parent().hasClass("ui-helper-hidden-accessible")){
	    			setTimeout(function(){
	    				focusableElement.focus();
					},100);
	    		} else {
	    			focusableElement.focus();
	    		}
	    		/**
	    		 * PRIMEFACES PATCH ENDE
	    		 */
	    		jQuery('input[name="activePageElementId"]').attr('value', focusableElement.first().attr('id'));
	            de.his.common.ContextInformation.set("active-page-element-id", focusableElement.first().attr('id'));
	    	} else {
	    		console.log("autofocus for "+element.attr('id'));
	    		/**
	    		 * PRIMEFACES PATCH START
	    		 */
	    		if(element.hasClass("ui-selectonemenu") || element.hasClass("callBackButton")){
	    			setTimeout(function(){
						element.focus();
					},100);
	    		} else {
	    			element.focus();
	    		}
	    		/**
	    		 * PRIMEFACES PATCH ENDE
	    		 */
				
	    		jQuery('input[name="activePageElementId"]').attr('value', element.attr('id'));
	            de.his.common.ContextInformation.set("active-page-element-id", element.attr('id'));
	    	}	    	
	    	// scroll to autofocus object if needed
	    	var scrollTop = jQuery(document).scrollTop();
	    	var windowHeight = jQuery(window).height();
	    	var elementOffset = element.offset().top;
            
	    	if ((scrollTop == 0 && elementOffset < windowHeight) || jQuery("div.overlay.modal").length || element.hasClass("callBackButton")) {
	    		// Element ist sehr weit oben und daher sichtbar oder overlay. scrollen nicht notwendig
	    		return;
	    	}	    	

	    	// Beim scrollen einen evtl. vorhandenen ScrollWithMe Container beachten.
	    	var scrollWithMe = jQuery('.scrollWithMe');
			if (scrollWithMe.length > 0) {
				var newOffsetTop = elementOffset - scrollWithMe.offset().top;
				if (newOffsetTop < 0) {
					newOffsetTop = 0;
				}
				elementOffset = newOffsetTop;
			}
	    	
	    	//Scrollen mit einer Animation zum Element.
	        jQuery('html, body').animate({
	        	scrollTop: elementOffset
	        }, 1000);

    };
    
    /**
     * Wird im linken Navigationsmenü ein Link geklickt, wird dessen Id in die LocalStorage geschrieben. Nach dem öffnen des Links
     * wird diese id wieder ausgelesen und der Fokus entsprechend gesetzt.
     * Wenn ein SubMenu Link geklickt wurde, soll der Fokus auf dem geklickten Link bleiben.
     * Wenn ein Untermenü Link geklickt wurde, soll der Fokus auf die Überschrift der Seite gesetzt werden.
     * 
     */
    var manageLeftMenuFocus = function() {
    	console.log("autofocus manage left menu.");
    	if (window.localStorage) {
    		var leftMenuActivePageElementId = localStorage.getItem("leftMenuActivePageElementId");
    		var leftSubMenuActivePageElementId = localStorage.getItem("leftSubMenuActivePageElementId");
//    		console.log("leftMenuActivePageElementId "+leftMenuActivePageElementId );
//    		console.log("leftSubMenuActivePageElementId "+leftSubMenuActivePageElementId );
    		if (leftSubMenuActivePageElementId) {
    			var subMenuLink = document.getElementById(leftSubMenuActivePageElementId);
    			if (subMenuLink) {
    				subMenuLink.focus();
    			}
    		}

    		if (leftMenuActivePageElementId) {
    			jQuery("#hisinoneTitle").attr("tabindex", "0").focus();
    		}

    		localStorage.removeItem("leftMenuActivePageElementId");
    		localStorage.removeItem("leftSubMenuActivePageElementId");
    	}
    };
    
    /**
	 * PRIMEFACES PATCH START
	 */
	var manageFormStepFocus = function() {
		// id von letzte geänderte Element in localStorage speichern
		jQuery('.autofocus-behavior-focused').on('click', '.ui-selectonemenu-item', function(e) {
			$this = jQuery(this).closest('.autofocus-behavior-focused');
			if(window.localStorage) {
				localStorage.setItem('lastChangedField', $this.attr('id'));
			}
		});
		// Tabnavigation bestätigung mit Enter
		jQuery('.autofocus-behavior-focused').on('keyup', function(e) {
			// bei enter
			if(e.which == 13) {
				$this = jQuery(this);
				if(window.localStorage) {
					localStorage.setItem('lastChangedField', $this.attr('id'));
				}
			}
		});
		
		// Für mobile Android-Geräte, diese setzen sonst den Focus auf die Startseite des Browsers.
		jQuery('.ui-selectonemenu').on('click', '.ui-selectonemenu-item', function(){
			if( jQuery('html').hasClass('android mobile') ) {
				$this = jQuery(this);
				$this.closest('.ui-selectonemenu').find('input').blur();
				setTimeout(function(){
					$this.closest('.ui-selectonemenu').find('input').focus();
				}, 100);
			}
		});
		
	};
	/**
	 * PRIMEFACES PATCH EDNE
	 */
};
/**
 * Hilfsobjekt zur Behandlung der Default-Buttons.
 * Author: Hoersch, Wahrendorff
 */
de.his.modules.DefaultButton = new function() {
    de.his.modules.ModuleRegistry
        .registerModule(this)
        .registerAjaxRefreshModule(this);
    
    this.moduleName = "de.his.modules.DefaultButton";

    var buttonClicked = false;
    var registeredButtons = [];
    var registeredForms = [];

    this.init = function() {
    	console.log("default Button init");

        jQuery('form').each(function() {
            var form = jQuery(this);
            handleSelfDeclaredDefaultButton(form);
        });
        buttonClicked = false;
    };

    this.refresh = function() {
    	console.log("default Button refresh");
    	resetRegistry();
        this.init();
    };
    
    var resetRegistry = function(){
    	console.log("reset defaultButton Registry");
    	registeredButtons = [];
        registeredForms = [];
    }
    
    var handleSelfDeclaredDefaultButton = function(form){
    	/**
         * Button declares itself as default via JSF default=true
         * 
         * in this case a button is written as first element into the form to act as default when no js is active.
         */
        form.children("button[class='defaultbutton']").each(function(){
        	if(jQuery(this).is(":visible") === true){
        		var id = jQuery(this).attr('name');
                
            	console.log("add "+id+" to default-button-behavior (JSF)");
                register(form, id);
        	}
    	});
        /**
         * or styleClass
         */
        form.find('.default-button-behavior').each(function() {
        	if(jQuery(this).is(":visible") === true){
        		var id = jQuery(this).attr('id');
                
            	console.log("add "+id+" to default-button-behavior");
                register(form, id);
        	}
        	
        });
    };
    
    var register = function(form, buttonId) {
        if (alreadyRegistered(buttonId)) {
            return;
        }
        console.log("register button:"+buttonId);
        registeredButtons.push(buttonId);
        
        if (alreadyRegisteredForm(form.attr('id'))) {
            return;
        } else {
        	console.log("register form:"+form.attr('id'));
            registeredForms.push(form.attr('id'));
            handleFormSubmit(form);
        }
        
    };
    
    var handleFormSubmit = function(form){
    	form.off('keydown');
    	form.keydown(function(event) {
        	var keycode = event.keyCode;
        	if(keycode != 13){
        		return;
        	}
        	//console.log("Enter target: " , jQuery(event.target));
            // Für selects geht das nicht, denn hier verhalten sich die Browser unterschiedlich:
            // Firefox: nix bei Enter
            // Chrome: menü aufklappen bei Enter
            // Keiner schickt hierbei das Formular ab
            if (jQuery(event.target).is('select')) {
            	console.log("item selected, no form submit on enter.");
                return false;
            }
            
            if (jQuery(event.target).parent().hasClass('ui-selectonemenu-items-wrapper')) {
            	//maybe unnecessary, Prime fetches event from items. 
            	console.log("PrimeSelect item selected, no form submit on enter.");
                return false;
            }
            
            /** Elemente die kein input sind, sollen keine default form submit on Enter auslösen können */
            if (!jQuery(event.target).is('input')) {
            	console.log(jQuery(event.target)+" no default form submit on enter allowed.");
                return true;
            }
             
            if(keycode == 13 && jQuery(event.target).is('input') && jQuery(event.target).is('[defaultbutton]')){
            	console.log("input has declared default submit button");
				var defaultButtonId = jQuery(event.target).attr('defaultbutton');
				if(jQuery("button[id$='"+de.his.common.Util.toJQueryId(defaultButtonId)+"']").length > 0){
					jQuery("button[id$='"+de.his.common.Util.toJQueryId(defaultButtonId)+"']").click();
                    return false;
				} else {
					console.warn("DefaultButton with id ending '"+defaultButtonId+"' does not exist. It has been ignored.");
				}
            }
            
            if (keycode == 13 ) {
            	// Suche letztes overlay
            	var overlay = jQuery('div.overlay.modal').filter(':visible').last();
            	if (overlay && overlay.length) {
            		console.log("search for generic Search with defaultbutton in overlay");
            		
            		// Ausnahme: Generische Untersuchmaske zur Auswahl im Overlay
            		/**
            		 * Schauen ob suchmaske vorhanden, wenn ja , clicke ersten defaultbutton
            		 */
            		 if(overlay.find("#genericSearchMask").length > 0){
            			var gsFirstDefaultBtn = jQuery(event.target).parents("#genericSearchMask").first().parent().find(".default-button-behavior").first();
                 		
						if(gsFirstDefaultBtn.length > 0){
							console.log("found generic search in overlay");
							gsFirstDefaultBtn.addClass("noAutofocus").click();
							return false;
						}
						
            		 } else {
            			 // JS defaultbutton behavior ist wegen Anfrage 199654 in overlays abgeschaltet. 
            			 // ^^ Vermutlich wegen unsichtbarer overlays die das Verhalten gestört haben, optimierter selektor sollte das Problem beheben.
            		 	
            			var defaultBtn = jQuery(event.target).parents(".overlayContainer").first().find(".default-button-behavior").first();
						var refreshBtn = jQuery(event.target).parents().children('label').parent().children('.refreshButtonNoDisplay');

            		 	if(defaultBtn.length > 0 && refreshBtn.length == 0){
							console.log("found defaultButton in overlay");
							defaultBtn.click();
							return false;
						}
            		 }
            		
            		console.log("nothing found");
            		return true;
            	}
            }
            
            
            console.log("nothing happened for defaultbutton from JS");
            
            return true;
        });
    };

    var alreadyRegistered = function(buttonId) {
    	console.log(buttonId + " indexOf: " + registeredButtons.indexOf(buttonId));
        return registeredButtons.indexOf(buttonId) > -1;
    };
    var alreadyRegisteredForm = function(formId) {
    	console.log(formId + " indexOf: " + registeredButtons.indexOf(formId));
        return registeredForms.indexOf(formId) > -1;
    };

    this.submitEnter = function (buttonId, e) {
        var keycode;
        if (window.event) {
            keycode = window.event.keyCode;
        } else if (e) {
            keycode = e.which;
        } else {
            return true;
        }
        if (keycode == 13) {
            clickButton(buttonId);
            return false;
        }
        return true;
    };

    var clickButton = function(buttonId) {
        if (buttonClicked) {
            return;
        }
        console.log("try to click:"+buttonId);
        if (document.getElementById(buttonId) != null) {
        	document.getElementById(buttonId).click();
        }
		if (document.getElementById(buttonId+':add_button') != null) {
        	document.getElementById(buttonId+':add_button').click();
        }
        buttonClicked = true;
    };
};/**
 * HISinOne HTML-Textfeld (hier mit CK-Editor).
 */

var CKEDITOR_BASEPATH;

de.his.modules.HtmlEditor = new function() {
    de.his.modules.ModuleRegistry.registerModule(this).registerAjaxRefreshModule(this).registerAjaxStartModule(this);

    this.moduleName = "de.his.modules.HtmlEditor";
    
    var textareaSelector = 'textarea.fckEditor,textarea.fckeditor'; // ,textarea.ckeditor<-- class ckeditor is recognised by ckeditor.js and replaces textareas with default ckeditor
    var contextPath = de.his.common.ContextInformation.get('context-path');
    var getParam = function(key){
    	
    	return jQuery('span#ckeditorParams').data(key);
    }

    this.init = function() {
    	// DONE: new approach: each editor can be configured individually
    	// so we begin with iterating potential textareas 
    	// and look out for data attributes for configuration
    	// before falling back to global configuration for legacy reasons
    	
    	var textareas = jQuery(textareaSelector);
    	if(textareas.length==0){
    		// return if no textareas match.
    		return;
    	}
    	
    	if (typeof CKEDITOR!=='undefined') {
        	textareas.each(function(e, i){
        		
        		var ta = jQuery(this);
        		console.log("editor:",ta);
        		if(ta.data("loadonstart")){
        			// new approach
        			createCkeditors(ta);
        		} else {
        			// legacy
        			if (getParam("loadonstart")) {
        				if (!jQuery.fn.ckeditor) {
        		            return;
        		        }
        				ta.data(toolbar)
        				createCkeditors(ta);
        			}
        		}
        		
        	});
    	} else {
    		// we need to set CKEDITOR_BASEPATH when loading ckeditor dynamically or ckeditor thinks the current url is it's actual path
        	CKEDITOR_BASEPATH = de.his.common.ContextInformation.get('context-path')+'/pub/ckeditor/';
    		console.log("init ckeditor Basepath: %s",CKEDITOR_BASEPATH);
			de.his.modules.ModuleRegistry.loadScript(CKEDITOR_BASEPATH+"ckeditor.js", "de.his.modules.HtmlEditor");
    	}
    	
    };

    this.indicateAjaxRequestStart = function(){
        /**
         * Updating Textarea for potential ajax submit
         */
        if (typeof CKEDITOR!=='undefined') {
        	
            // update all instances of CKEDITOR that are not disabled
        	var textareas = jQuery(textareaSelector);
        	textareas.each(function() {
    			var instanceKey = this.name;
				var $instance = jQuery(this);
				 
				if(!$instance.is(':disabled')){
					try{
						CKEDITOR.instances[instanceKey].updateElement();
					} catch(e){
						// log error
				 		console.log(e);
				 	}
				}
        	});
        } 

    };

    this.debugSettings = function() {
    	//TODO: needs something else all these params are deprecated and unused in new approach
        //alert("loadOnStart = " + loadOnStart + "\r\n" + "replaceNewlines = " + replaceNewlines + "\r\n" + "customConfigFile = " + customConfigFile);
    };

    this.triggerElementUpdate = function() {
    	for ( var instance in CKEDITOR.instances ) {
    	    if( CKEDITOR.instances.hasOwnProperty( instance ) ){
    	        CKEDITOR.instances[instance].updateElement();    
    	    }
    	}
    }
    
    this.replace = function(){
    	this.init();
    };
    
    this.toggle = function(selector){
    	if(typeof selector === 'undefined'){
    		selector = textareaSelector;
    	}
    	
    	var textareas = jQuery(selector);
    	console.log("CKEDITOR.instances: "+selector ,CKEDITOR.instances);
    	if(textareas.length == 0){
    		return;
    	}
    	// we replace all findings or nothing, so simply check if the first selected textarea is ckeditorfied
    	if(!CKEDITOR.instances[textareas[0].id]){
    		createCkeditors(textareas);
    	} else{
    		destroyCkeditors(textareas);
    	}
    };
    
    var destroyCkeditors = function(textareas){
    	for (var i = 0; textareas.length > i; i++){
    		jQuery("#"+de.his.common.Util.toJQueryId(textareas[i].id)).data('already-ckeditorified', false);
        	CKEDITOR.instances[textareas[i].id].destroy();
    	}
    }
    
    var createCkeditors = function(textareas){
    	if (textareas.length == 0) {
            return;
        }
        
        var customConfigFile = contextPath+'/pub/ckeditor_his/hisconfiguration.js?20220520';

        textareas.ckeditor(customConfigFile);
    }
    
    this.refresh = function() {
    	if (!jQuery.fn.ckeditor) {
            return;
        }
    	
    	this.init();
    };

	this.getAllowedContent = function(mode, allowedHtmlTags, allowedHtmlAttributes){
        var allowedContent;
        switch (mode){
        case 'extendedHtml':
            allowedContent = {
                $1: {
                    // Use the ability to specify elements as an object.
                    elements: allowedHtmlTags,
                    attributes: allowedHtmlAttributes,
                    styles: true,
                    classes: true
                }
            }        
		break;
		case 'tagsOnly':
			allowedContent = {
		    	$1: {
			        // Use the ability to specify elements as an object.
					// Tags only
			        elements: { h1: false, h2: true, h3: true, h4: true, h5: true, h6: true, a: true, b: true, i: true, u: true, sub: true, sup: true, ul: true, ol: true, li: true, dl: true, dt: true, dd: true, p: true, span: true, em: true, s: true, strike: true, strong: true, table: true, tbody: true, thead: true, tfoot: true, tr: true, th: true, td: true, colgroup: true, col: true, caption: true, div: true, small: true, pre: true, code: true,br: true, hr: true, img: true, col: true, style: true},
			        attributes: false,
					styles: false,
			        classes: false
			    }
			};
		break;
		default:
			allowedContent = {
			    $1: {
			        // Use the ability to specify elements as an object.
					// allowed tags, attributes and styles, from HTMLUtil.java, keep in sync!
					// font and font-family is allowed in HTMLUtil.java, but ' and " in style attribute aren't.
					// therefore filter font and font-family, since there is no value in getting the font-family from a Word Document, because the texts are always within a font-family setting context (Portal, FOP-Report, LO-Report) 
			        elements: { h1: false, h2: true, h3: true, h4: true, h5: true, h6: true, a: true, b: true, i: true, u: true, sub: true, sup: true, ul: true, ol: true, li: true, dl: true, dt: true, dd: true, p: true, span: true, em: true, s: true, strike: true, strong: true, table: true, tbody: true, thead: true, tfoot: true, tr: true, th: true, td: true, colgroup: true, col: true, caption: true, div: true, small: true, pre: true, code: true,br: true, hr: true, img: true, col: true, style: true},
			        attributes: [ 'title', 'alt', 'src', 'target', 'style', 'class', 'align', 'valign', 'bgcolor', 'colspan', 'rowspan', 'height', 'nowrap', 'width', 'cellpadding', 'cellspacing', 'border', 'id', 'scope', 'summary', 'href', 'lang', 'data-delayedsrc' ],
					styles: ['width', 'height', 'direction', 'line-height', 'vertical-align', 'list-style-type', 'list-style-position', 'color', 'background-color', 'background-repeat', 'font-style', 'font-variant', 'font-weight', 'font-size', 'text-indent', 'text-align', 'text-decoration', 'letter-spacing', 'word-spacing', 'text-transform', 'white-space', 'border', 'border-top', 'border-right', 'border-bottom', 'border-left', 'border-width', 'border-style', 'border-color'],
	        		classes: true
			    }
			};
		}
		return allowedContent;
	}
    
    /**
     * return array with toolbarGroups and removeButtons
     */
    this.getToolbarConfig = function(toolbar){
    	var array = []
    	switch (toolbar){
    	case 'full':
    		array['toolbarGroups'] = [
    			{ name: 'document', groups: [ 'mode', 'document', 'doctools' ] },
    			{ name: 'clipboard', groups: [ 'clipboard', 'undo' ] },
    			{ name: 'editing', groups: [ 'find', 'selection', 'spellchecker', 'editing' ] },
    			{ name: 'links', groups: [ 'links' ] },
    			{ name: 'insert', groups: [ 'insert' ] },
    			{ name: 'forms', groups: [ 'forms' ] },
    			{ name: 'others', groups: [ 'others' ] },
    			{ name: 'tools', groups: [ 'tools' ] },
    			'/',
    			{ name: 'styles', groups: [ 'styles' ] },
    			{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
    			{ name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi', 'paragraph' ] },
    			{ name: 'colors', groups: [ 'colors' ] },
    			
    			{ name: 'about', groups: [ 'about' ] }
    			
    		];
    		array['removeButtons'] = 'About,Format,AutoComplete,UncommentSelectedRange,CommentSelectedRange,autoFormat,searchCode,Indent,Outdent';

    	break;
    	case 'basic':
    		array['toolbarGroups'] = [
    			{ name: 'document', groups: [ 'mode', 'document', 'doctools' ] },
    			{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
    			{ name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi', 'paragraph' ] },
    			{ name: 'colors', groups: [ 'colors' ] },
    			{ name: 'links', groups: [ 'links' ] },
    			{ name: 'others', groups: [ 'others' ] },
    			{ name: 'tools', groups: [ 'tools' ] },
    			{ name: 'about', groups: [ 'about' ] }
    			
    		];
    		
    		array['removeButtons'] = 'About,Format,AutoComplete,UncommentSelectedRange,CommentSelectedRange,autoFormat,searchCode,Indent,Outdent,Blockquote';

    	break;
    	case 'slim':
    		array['toolbarGroups'] = [
    			{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
    			{ name: 'colors', groups: [ 'colors' ] },
    			{ name: 'links', groups: [ 'links' ] },
    			{ name: 'others', groups: [ 'others' ] },
    			{ name: 'about', groups: [ 'about' ] }
    		];
    		
    		array['removeButtons'] = 'About,Format,AutoComplete,UncommentSelectedRange,CommentSelectedRange,autoFormat,searchCode,Indent,Outdent,Blockquote,Subscript,Superscript';

    	break;
    	default:
    		array['toolbarGroups'] = [
    			{ name: 'document', groups: [ 'mode', 'document', 'doctools' ] },
    			{ name: 'clipboard', groups: [ 'clipboard', 'undo' ] },
    			{ name: 'editing', groups: [ 'find', 'selection', 'spellchecker', 'editing' ] },
    			{ name: 'links', groups: [ 'links' ] },
    			{ name: 'insert', groups: [ 'insert' ] },
    			{ name: 'forms', groups: [ 'forms' ] },
    			{ name: 'others', groups: [ 'others' ] },
    			{ name: 'tools', groups: [ 'tools' ] },
    			'/',
    			{ name: 'styles', groups: [ 'styles' ] },
    			{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
    			{ name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi', 'paragraph' ] },
    			{ name: 'colors', groups: [ 'colors' ] },
    			
    			{ name: 'about', groups: [ 'about' ] }
    			
    		];
    		array['removeButtons'] = 'About,Format,AutoComplete,UncommentSelectedRange,CommentSelectedRange,autoFormat,searchCode,Indent,Outdent';
    		
    	
    	}
    	
    	return array;
    }
};/**
 * Kapselt Methoden, die für den Refresh-Button in Kombination mit Eingabefeldern benötigt werden.
 *
 * NOTE: in situations where focusing the next input element is undesireable the focus behavior
 *       can be disabled via the style class "disable-input-focus-behavior". 
 */
de.his.modules.InputRefresh = new function() {
    de.his.modules.ModuleRegistry
    	.registerModule(this)
    	.registerAjaxRefreshModule(this);

    this.moduleName = "de.his.modules.InputRefresh";
    var self = this;
    
    var lastActiveElements = [];
    
    this.init = function() {
        /**
         * jQuery-Funktion, welche den Focus in das nächste Eingabefeld setzt.
         * reverse - boolean - optional - set to true to focus previous input field
         */
        jQuery.fn.focusNextInputField = function(reverse) {
        	// durch select:not(.langSelector) wird die Auswahlliste der Sprachumsschaltung nicht betrachtet.
            var fields = jQuery("body").find('input[type!="submit"][type!="image"][type!="hidden"][type!="file"][data-exclude!="true"][tabindex!="-1"]:not(.ui-selectonemenu-filter),textarea,select[tabindex!="-1"]:not(.langSelector),button:not(.helpButton)');
            
            var index = fields.index(this);
            
            if(jQuery(this).hasClass("refreshButtonNoDisplay") && reverse){
            	console.log("refresh Button did it!");
            	index = index-1;
            }
           
            console.log("activeElementIndex: "+index);
            
            // ein bischen Magie zum bestimmen des Focus.
            if (index > -1 && (index + 1) < fields.length) {
            	var i = reverse === true ? index - 1 : index + 1;
            	
            	// search for the next input that is NOT disabled nor a refresh, a hidden or a help -button.
            	for(var n=i;i<=fields.length; n++){
            		var jQueryField = jQuery(fields.eq(i));
            		
            		if(!jQueryField.is(":disabled") 
        				//&& !jQueryField.is("[readonly]") 
        				&& !jQueryField.hasClass("refreshButtonNoDisplay") 
        				&& !jQueryField.hasClass("unsichtbar") 
        				//&& !jQueryField.hasClass("submit_image") 
						//&& !jQueryField.hasClass("helpButton")
						){
            			console.log("Set Focus on : "+jQueryField.attr('id'));
            			jQueryField.focus().select();
            			break;
            		}
            		i = reverse === true ? i - 1 : i + 1;
            	}
            }
            
            // Falls es keine Tabelle gibt, kann es vorkommen, dass es nach dem letzten Input noch einen Button gibt 
            // (um bspws. das Formular abzusenden siehe #166658). Ohne isTablePresent würde der viewPort aber wieder 
            // nach oben gesetzt werden. In Tabellen ist genau das aber gewünscht, deshalb an dieser Stelle die Prüfung. 
            var isTablePresent = jQuery(".datascroller");
            if (index > -1 && (index + 1) == fields.length && isTablePresent[0]) {
            	console.log("Set Focus on : "+ fields.eq(0));
                fields.eq(0).focus();
                window.scrollTo(0,0);
            }
            return this;
        };
        
        initIntern();
    };

    this.refresh = function() {
        initIntern();
    };

    var initIntern = function() {
    	// reset flag for radiobutton Patch
    	if(typeof window.sessionStorage !== 'undefined'){
    		sessionStorage.removeItem("his_refreshButtonClicked");
    	}
    	
    	// Focus Behaviour beim klicken mit Maus für einen Refresh abschalten. 
        jQuery('input[type!="submit"][type!="image"][type!="hidden"][type!="file"],textarea,select').click(function(){
        	if(!jQuery(this).hasClass('noAutofocus')){
        		var id = jQuery(this).attr('id');
            	console.log("click focus set on: "+id);
            	sessionStorage.setItem("his_lastClickedPageElementId",id);
            	setActivePageElement(id);
        	}
        });
    	
        jQuery('input[type!="submit"][type!="image"][type!="hidden"][type!="file"],textarea,select,a').focus(function() {
        	if(!jQuery(this).hasClass('noAutofocus')){
        		var id = jQuery(this).attr('id');
            	setActivePageElement(id);
        	}
        });

        //Buttons sollen Fokus nach Bedienung behalten
        jQuery('button[type=submit]').click(function() {
        	var activePageElementFocusId = jQuery(this).data('focusid');
        	if(typeof activePageElementFocusId !== 'undefined'){
        		sessionStorage.setItem("his_manualFocusByDataFocusId", activePageElementFocusId);
        	}
        	if(!jQuery(this).hasClass('noAutofocus') && !jQuery(this).hasClass('refreshButtonNoDisplay')){
        		setActivePageElement(this.id);
        	}
        });
        
        // Shift key pressed on tab Erkennung für Primefaces Select.
        jQuery('.ui-selectonemenu-filter,ui-selectonemenu-label').keydown(function(event){
        	var keyCode;
            if (event) {
            	var input = jQuery(this);
            	keyCode = event.keyCode || event.which;
            	if(keyCode === 9 || (jQuery(this).hasClass("_refreshOnEnter") && keyCode === 13)){
            		if(event.shiftKey){
            			console.log("shiftKEy pressed!");
                		//TODO: don't use globals!
                		de.his.common.ContextInformation.set("refresh-shift-key", true);
                	}else{
                		// reset if tab without shift is pressed
                		de.his.common.ContextInformation.set("refresh-shift-key", false);
                	}
            	}else{
            		// reset on any other key
            		de.his.common.ContextInformation.set("refresh-shift-key", false);
            	}
            }
        });
        
        jQuery('button[class="refreshButtonNoDisplay"]').click(function() {
            var id = jQuery(this).attr('id');
            refreshBtnClicked(id);
        });

        var activePageElementId = de.his.common.ContextInformation.get("active-page-element-id");
        
        if (activePageElementId) {
            
            var pollButtonClicked = de.his.common.ContextInformation.get("poll-button-clicked");
            var refreshButtonClicked = de.his.common.ContextInformation.get("refresh-button-clicked");
            var activePageElement = jQuery('#' + de.his.common.Util.toJQueryId(activePageElementId));

            var hasActivePageElementDisabledFocusBehavior = activePageElement.hasClass("disable-input-focus-behavior");
            var hasParentWithDisabledFocusBehavior = activePageElement.parents(".disable-input-focus-behavior").length > 0;
            var focusInputBehaviorEnabled = ! hasActivePageElementDisabledFocusBehavior && ! hasParentWithDisabledFocusBehavior;
            
            var fieldsetHelpButtonClicked = false;
            var popupButtonClicked = false;
            var tableFilterButtonClicked = false;
            var captchaRefreshButtonClicked = false;
            var tableConfigButtonClicked = false;
            var portalInfoBoxLinkClicked = false;
            
            

            //Es kann vorkommen, dass das ursprüngliche Element nicht mehr da ist, obwohl die Id noch gesetzt ist. Deshalb prüfen...
        	if (document.getElementById(activePageElementId)) {
            	fieldsetHelpButtonClicked = document.getElementById(activePageElementId).parentElement.classList.contains('fieldsetHelpButton');
            	popupButtonClicked = document.getElementById(activePageElementId).dataset.popupbutton;
            	tableFilterButtonClicked = document.getElementById(activePageElementId).dataset.tablefilterbutton;
            	captchaRefreshButtonClicked =  document.getElementById(activePageElementId).classList.contains('refreshCaptcha');
            	tableConfigButtonClicked = document.getElementById(activePageElementId).classList.contains('configTableButton');
            	portalInfoBoxLinkClicked = document.getElementById(activePageElementId).classList.contains('portalInfoBoxLink');
        	}
        	
        	// keep focus manually with data-attribute on active element, used in ui repeats to keep focus on moving element
        	var manualFocusByDataFocusId = sessionStorage.getItem("his_manualFocusByDataFocusId");
        	if(manualFocusByDataFocusId !== null){
        		manualFocusByDataFocusId = de.his.common.Util.toJQueryId(manualFocusByDataFocusId);
        		if(jQuery('[data-focusid="' + manualFocusByDataFocusId + '"]').length>0){
        			jQuery('[data-focusid="' + manualFocusByDataFocusId + '"]').focus().select();
        		} else{
        			if(manualFocusByDataFocusId.indexOf('up')>-1){
        				manualFocusByDataFocusId = manualFocusByDataFocusId.replace('up','down');
        			} else {
        				manualFocusByDataFocusId = manualFocusByDataFocusId.replace('down','up');
        			}
        			jQuery('[data-focusid="' + manualFocusByDataFocusId + '"]').focus().select();
        		}
        		console.log("focus set manually, data-focusId: %s",manualFocusByDataFocusId);
        		sessionStorage.removeItem("his_manualFocusByDataFocusId");
        		return;
        	}

            // disable focus on refresh after mouse click select
            var radioButtonClickedId = sessionStorage.getItem("his_radioButtonClickedId");
            var lastClickedPageElementId = sessionStorage.getItem("his_lastClickedPageElementId");
            console.log("lastClickedPageElementId: %s",lastClickedPageElementId);
            console.log("activePageElement: %s",activePageElementId);
           
            console.log("radioButtonClickedId: %s",radioButtonClickedId);
            
            // Wenn eine Nutzer Rückfrage (IssueQuery) eingeblendet wird, soll die Überschrift bzw. der Text fokussiert werden
        	var query = jQuery('.infobox.confirm_infobox.messages-infobox');
        	if (query && query.length) {
        		query.find('h2').attr("tabindex", "0").focus();
        		return;
        	}
            
            if(lastClickedPageElementId === activePageElementId || (radioButtonClickedId === lastClickedPageElementId && lastClickedPageElementId !== null && radioButtonClickedId!== null)) {
            	console.log("disabled Focus behaviour cause a radio button or input was clicked.. ");
            	focusInputBehaviorEnabled = false;
            	if(!jQuery(this).hasClass('noAutofocus')){
                    // TODO:
                    // - wenn geklicktes Element hat noAutofocus, behalte id des vorherigen Elements als geklicktes Element
                    sessionStorage.removeItem("his_lastClickedPageElementId");
                }
            	sessionStorage.removeItem("his_radioButtonClickedId");
            	jQuery("#"+de.his.common.Util.toJQueryId(lastClickedPageElementId)).focus();
                return;
                
            }
            
            
            
            if (focusInputBehaviorEnabled) {
            	
            	if(pollButtonClicked) {
	            	de.his.common.ContextInformation.set("poll-button-clicked", false);
	            	return;
	            }

            	
            	// wenn overlay geschlosse wurde, wurde Fokus bereits gesetzt, also ist hier nichts mehr zu tun.
//    	    	var overlayOpeningElementId = sessionStorage.getItem('overlayOpeningElementId');
//    	    	var overlayOpeningElement = document.getElementById(overlayOpeningElementId);
//    	    	if (overlayOpeningElement) {
//    	    		setOpenig element
//    	    		overlayOpeningElement.focus();
//    	    		sessionStorage.removeItem('overlayOpeningElementId');
//    	    		return;
//    	    	}
            	
            	//Wenn der HelpButton eines Fieldsets gedrückt wurde, soll der Fokus auf die überschrift des Hilfetextes gesetzt werden.
            	if (fieldsetHelpButtonClicked && activePageElement.length) {
            		//Finde zunächst den ancestor mit der Klasse, das sollte der Container mit der Überschrift des fieldsets sein.
            		var parents = activePageElement.parents('.box_title');
            		if (parents.length) {
            			// das nächste Sibling Element dieses Ancestors enthält die Überschrift des Hilfetextes.
            			// Die Überschrift wird mit Tabindex=0" gesucht, weil das h2 nicht direkt fokussiert werden kann, sondern nur der parent.
            			var parentBox = parents[0];
            			var parentBoxSibling = parentBox.nextSibling;
            			if (parentBoxSibling) {
							// Die erste H2 soll fokussiert werden 
            				jQuery(parentBoxSibling).find('h2').attr("tabindex", "0").first().focus();
                			return;
            			}
            		}
            	}

            	//Wenn ein Popup geöffnet wird, soll hier nichts mehr gemacht werden, weil das popup Skript den Fokus selbst setzt.
            	if (popupButtonClicked) {
            		return;
            	}

            	// Wenn der Filter Button in einer Tabelle geklickt wird, soll der Fokus auf das erste Filter Input gesetzt werdenn.
            	if (tableFilterButtonClicked == "false") {
            		// erst den Container indem die Tabelle enthalten ist holen
            		var tableParent = document.getElementById(activePageElementId).parentElement.parentElement;
            		var tableInputs = jQuery(tableParent).find('table').find('input');
            		tableInputs[0].focus();
            		return;
            	}

            	//Tabellen Konfiguration wurde geöffnet
            	if (tableConfigButtonClicked) {
            		var tableConfigH2 = jQuery('.curtainTableConfig').find('h2').first();
            		if (tableConfigH2.length > 0) {
            			tableConfigH2.attr("tabindex", "0");
            			tableConfigH2.focus();
            		}
            		return;
            	}
            	
            	//Portal Infobox soll nach dem Öffnen den Fokus erhatlen
            	if (portalInfoBoxLinkClicked) {
            		jQuery('.infoboxContainer').find("h2").first().focus();
            		bindFocus(jQuery('.infoboxContainer'));
            		return;
            	}

            	// Bei Captcha Eingaben soll der Fokus nach dem Klick auf den RefreshButton auf das Captcha Input gesetzt werden
            	if (captchaRefreshButtonClicked && activePageElement) {
            		var previousSibling = jQuery('.refreshCaptcha').get()[0].previousSibling;
            		if (previousSibling) {
            			previousSibling.focus();
            			return;
            		}
            	}
            	
            	// Wenn auf der Seite ein Fehler aufgetreten ist, soll der Fokus in das erste fehlerhafte Eingabeelement gesetzt werden
            	var firstErrorText = jQuery('.error').first();
            	if (firstErrorText.length) {
            		if (firstErrorText.find("input[type!=hidden]").length) {
            			firstErrorText.find("input[type!=hidden]").focus().select();
                		return;
            		}
            	}

	            if (refreshButtonClicked) {
	            	
	            	if(!de.his.common.ContextInformation.get("refresh-shift-key")) {
	            		//normal tab
	            		console.log("Focus next input: ",activePageElement);
	            		activePageElement.focusNextInputField();
	            	}else{
	            		//backwards - shift-tab
	            		console.log("Focus prev input: ",activePageElement);
	            		de.his.common.ContextInformation.set("refresh-shift-key", false);
	            		activePageElement.focusNextInputField(true);
	            	}
	            } else{
	            	console.log("Focus input: ",activePageElement);
					if(activePageElement.length){
                        if(activePageElement.hasClass('his-autocomplete-select-input')){
                            // do not select input on autocomplete, or user will erase input accedentilly upon ajax update.
                            activePageElement.focus();
                        } else {
                            activePageElement.focus().select();
                        }
					} else {
                        console.log("lastActive Element vanished.. :( ");
                        lastActiveElements.forEach(function(value,index){
                            let previousActiveElem = jQuery('#' + de.his.common.Util.toJQueryId(value));
                            if(previousActiveElem.length>0){
                                console.log("Focus previousActiveElem: ",previousActiveElem);
                                if(previousActiveElem.hasClass('his-autocomplete-select-input')){
                                    // do not select input on autocomplete, or user will erase input accedentilly upon ajax update.
                                    previousActiveElem.focus();
                                } else {
                                    previousActiveElem.focus().select();
                                }
                            }
                        });
                    }
	            }
            }else{
            	// keep selection when input focus behaviour is disabled.
            	if(activePageElement.is(':disabled')){
            		console.log("Focus next input 2: "+activePageElement.attr('id'));
            		activePageElement.focusNextInputField();
            	}else{
            		console.log("Focus input 2: "+activePageElement.attr('id'));
            		//Das soll nur für Inputs relevant sein. KEINE Buttons.
            		if(activePageElement.length && jQuery(activePageElement).is('input')){
						activePageElement.focus().select();
					}
            	}
            	
            }
        }
    };
    
    this.pollButtonClicked = function(event){
    	de.his.common.ContextInformation.set("poll-button-clicked", true);
    }

    this.refreshSelectedValues = function (event, element, hiddenFieldCliendId, hiddenInputClientId) {
        var hiddenField = document.getElementById(hiddenFieldCliendId);
        var hiddenInput = document.getElementById(hiddenInputClientId);
        if (hiddenField && hiddenInput) {
//        	if (element) {
//        		beforeAjax(element);
//        	}
        	console.log("selectManyPicklist changed: "+hiddenField.value);
        	hiddenInput.value = hiddenField.value;
        	hiddenInput.change();
        }
    };

    this.refreshBtnClick = function(event, element, btnId) {
        var btn = document.getElementById(btnId);
        if (btn) {
        	beforeAjax(element);
            refreshBtnClicked(btnId);
            // set flag for radiobutton
            sessionStorage.setItem("his_refreshButtonClicked", "true");
            btn.click();
        }
    };
    
    this.radioBtnClick = function(event, element, btnId) {
    	
        sessionStorage.setItem("his_radioButtonClickedId", jQuery(element).attr('id'));
        console.log("radioButtonClickedId: "+jQuery(element).attr('id'));
    };

    var setActivePageElement = function(activePageElementId) {
        if (activePageElementId) {
            jQuery('input[name="activePageElementId"]').attr('value', activePageElementId);
            de.his.common.ContextInformation.set("active-page-element-id", activePageElementId);
            console.log("lastActiveElements", lastActiveElements);
            lastActiveElements.unshift(activePageElementId);
            if(lastActiveElements.length >10){
                lastActiveElements.pop();
                console.log("lastActiveElements popped", lastActiveElements);
            }
        }
    };
    

    var refreshBtnClicked = function(btnId) {
        if (btnId) {
        	setActivePageElement(btnId);
            de.his.common.ContextInformation.set("refresh-button-clicked-id", btnId);
            de.his.common.ContextInformation.set("refresh-button-clicked", true);
            de.his.common.ContextInformation.set("refresh-button-clicked-for-tree", true);
        }
    };

    var beforeAjax = function(input){
    	var claz = "waitingAnimation";
    	input = jQuery(input);
    	if(input.length > 0){

    		var p = input.parent();
    		if(p.find("." +claz).length <= 0){
    			//show mask
        		//p.append(de.his.modules.Waiting.getWaitingAnimationHtml(2));
        		//de.his.modules.Waiting.executeNormalWaiting();
            	de.his.modules.eventRegistry.addListener("refresherComplete", function(){
            		//hide mask
            		//de.his.modules.Waiting.refresh();
            		//jQuery("." + claz).remove();
            		//de.his.modules.Waiting.removeWaitingAnimationHtml();
            	}, this, true);
    		}

    	}
    };

    this.inputBlur = function(event, element, btnId) {
        if (element._changed) {
        	//beforeAjax(element);
            this.refreshBtnClick(event, element, btnId);
            var btn = document.getElementById(btnId);
            if (btn) {
                btn.alreadyClicked = true;
            }
        }
    };

    this.inputKeydown = function(event, element, btnId) {
    	var keyCode;
        if (event) {
        	keyCode = event.keyCode || event.which;
        	console.log("keycode: "+keyCode);
        	if(keyCode === 9 || (jQuery(element).hasClass("_refreshOnEnter") && keyCode === 13)){
        		sessionStorage.removeItem("his_lastClickedPageElementId");
        		if(event.shiftKey){
            		//TODO: don't use globals!
            		de.his.common.ContextInformation.set("refresh-shift-key", true);
            	} else {
            		de.his.common.ContextInformation.set("refresh-shift-key", false);
            	}
        		// only refresh if element has changed
        		if (element._changed) {
        			console.log("element changed! REFRESH!");
	            	//beforeAjax(event.originalTarget);
	                this.refreshBtnClick(event, element, btnId);
	                var btn = document.getElementById(btnId);
	                if (btn) {
	                    btn.alreadyClicked = true;
	                }
	                return false;
        		}
        	}else{
        		// do not mark element as changed if only shift is pressed, it might be Shift+Tab action
        		if(keyCode!==16){
        			console.log("element changed!");
        			element._changed = true;
        		}
        		// reset on any other key
        		de.his.common.ContextInformation.set("refresh-shift-key", false);
        	}
        	// workaround für ajax Fehler in Datumsfeldern bei Return siehe #166480
        	if(jQuery(element).hasClass("input_date") || jQuery(element).hasClass('input_standard')){
        		if(keyCode === 13){
        			// refresh vor dem Absenden des Formulars
        			event.preventDefault();
        			this.refreshBtnClick(event, element, btnId);
	                var btn = document.getElementById(btnId);
	                if (btn) {
	                    btn.alreadyClicked = true;
	                }
	                if(!jQuery(element).hasClass("_refreshOnEnter")){
	                	jQuery(element).parent("form").submit();
	                }
        		}
        	}
        }
        return true;
    },
    
    this.inputRadioKeydown = function(event,element,btnId){
    	if (sessionStorage.getItem("his_refreshButtonClicked") === "true") {
    		event.preventDefault();
     		console.log("preventDefault while AJAX refreshing");
     		
     		return false;
    	}
    }

    this.inputChange = function(event, element, btnId) {
    	console.log("element changed!");
        element._changed = true;
    };

    this.checkBtnAlreadyClicked = function(event, element, btnId) {
        if (element.alreadyClicked) {
            return false;
        }
        refreshBtnClicked(element.id);
        return true;
    };
    
    var bindFocus = function(infoboxcontainer){
		jQuery("[class='focusTrapFirst']").on("focus", function(){
			console.log("FocusTrap");
			infoboxcontainer.find("[id$='close1']").focus();
		})
		jQuery("[class='focusTrapEnd']").on("focus", function(){
			console.log("FocusTrap");
			infoboxcontainer.find("h2").focus();
		})
	}
};
/**
 * Whenever the session runs out the logged-in User will see a Popup window with
 * the possibility to re-login. Pressing the ESC-Button will close this window
 * 
 * For Mobile Users the site is reloaded, what causes an autologin and leads to the startpage in any case. 
 */
de.his.modules.SessionTimeout = new function() {
	de.his.modules.ModuleRegistry.registerModule(this);
    this.moduleName = "de.his.modules.SessionTimeout";
	this.init = function() {
		window.onkeydown = function(e) {
			var key = e.keyCode ? e.keyCode : e.which;
			if (key == 27) {
				de.his.modules.SessionTimeout.closeLoginForm();
			}
		}
	};

	this.showLoginForm = function() {
		this.closeAlertMessage();
		
		var loginDiv = document.getElementById("sessionTimeoutLoginDiv");
		if (loginDiv) {
			loginDiv.className = "curtainBoxCallBackBackground";
			//cas logout fix ticket #122889
			var cas = jQuery("#casLogouts img[data-value]");
			if(cas.length){
				var a;
				jQuery.each(cas, function(i,v){
					a = jQuery(v);
					a.attr("src", a.attr("data-value"));
				});
			}
		}
	};
	
	this.closeAlertMessage = function() {
		var alertElement = document.getElementById("alert")
		if (alertElement) {
			alertElement.parentNode.removeChild(alertElement);
			
			var alertModal = document.getElementById("alert-modal");
			alertModal.parentNode.removeChild(alertModal);
		}
	};

	this.closeLoginForm = function() {
		var loginDiv = document.getElementById('sessionTimeoutLoginDiv');
		if (loginDiv) {
			loginDiv.className = "noDisplay";
			//cas logout fix ticket #122889
			var cas = jQuery("#casLogouts img[data-value]");
			if(cas.length){
				jQuery.each(cas, function(i,v){
					jQuery(v).removeAttr("src");
				});
			}
			
		}
	};
	
};/**
 * Das ablaufen der Nutzer-Session verhindern, in dem Requests an den Server
 * geschickt werden
 * 
 * 
 */
// alert(navigator.userAgent);
de.his.modules.SessionRefresh = new function() {
	de.his.modules.ModuleRegistry.registerModule(this)
			.registerAjaxRefreshModule(this);

	var refreshSec = undefined;
	var refreshActive = false;
	var lastRefresh = new Date().getTime();
	var resfreshTimer = undefined;
	var resfreshViewTimer = undefined;
	var timedOut = false;
	var loginFormShown = false;
	var autoLoginEnabled = false;
	this.moduleName = "de.his.modules.SessionRefresh";
	var self = this;
	this.init = function() {
		autoLoginEnabled = de.his.common.Cookie.get('cs.sys.hisinoneAutoLoginEnabled') == 'true' ? true : false;
		var globalSessionRefreshAllowed = de.his.common.ContextInformation.get("global-session-refresh-allowed");
		var isLoggedIn = de.his.common.ContextInformation.get("user-logged-in");
		
		console.log("loggedIN",isLoggedIn);
		if(!isLoggedIn){
			// behebt Probleme
			timedOut = true;
			de.his.common.Cookie.erase('lastRefresh');
			de.his.common.Cookie.erase('sessionRefresh');
		}
		console.log("timedOut",timedOut);
		//console.log("refresh Counter isLoggedIn",isLoggedIn);
		// Ist immer erlaubt, nur wenn das Setup aktiv ist nicht
		if (typeof globalSessionRefreshAllowed != 'undefined'
				&& globalSessionRefreshAllowed 
				&& isLoggedIn) {
			var globalSessionTimeout = de.his.common.ContextInformation.get("global-session-timeout");
			var globalRefreshSession = de.his.common.ContextInformation.get("global-refresh-session");
// 			console.log('always refresh Session? ' + globalRefreshSession);
// 			console.log('session timeout ' + globalSessionTimeout);
			de.his.common.Cookie.create('lastRefresh', lastRefresh);
			refreshSec = Math.max(globalSessionTimeout - 120,
					globalSessionTimeout / 2); // 2 Min. vor Ablauf
												// aktualisieren
// 			console.log("globalRefreshSession:",globalRefreshSession);

			// activate refresh for autologin
			if (globalRefreshSession || autoLoginEnabled) {
				this.activateRefresh();
			} else {
				this.deactivateRefresh();
			}
			resfreshViewTimer = window.setInterval(function(){de.his.modules.SessionRefresh.refreshCounter()}, 1000);
			
		};
		if(isLoggedIn){
			// run on focus, fixes sleepy problems of session timeouts on mobiles 
			jQuery(window).add(document.body);  //necessary for mobile browsers
			jQuery(window).focus(function(){
				console.log("window gained focus.");
				de.his.modules.SessionRefresh.refreshCounter();
			});
		}
	};

	this.refresh = function() {
		lastRefresh = new Date().getTime();
	};

	this.activateRefresh = function() {
		if (!timedOut) {
			de.his.common.Cookie.create('sessionRefresh', '1');
			refreshActive = true;
			this.setRefreshServerSessionTimeout( false );
			jQuery('.sessionTimeout').hide();
			jQuery('#sessionNoTimeoutText').show();
		}
	};

	this.deactivateRefresh = function() {
		if (!timedOut) {
			de.his.common.Cookie.create('sessionRefresh', '0');
			refreshActive = false;
			if (resfreshTimer) {
				window.clearTimeout(resfreshTimer);
			}
			jQuery('.sessionTimeout').show();
			jQuery('#sessionNoTimeoutText').hide();
		}
	};

	this.refreshCounter = function() {
		if (!timedOut) {
			var tmp = de.his.common.Cookie.read('lastRefresh');
			if (tmp) {
				lastRefresh = tmp;
			}
			tmp = de.his.common.Cookie.read('sessionRefresh');
			if (tmp === '1' && !refreshActive) {
				jQuery('#refreshSession').attr("checked", true);
				return this.activateRefresh();
			} else if (tmp === '0' && refreshActive) {
				jQuery('#refreshSession').attr("checked", false);
				return this.deactivateRefresh();
			}
			// tmp = null: Keine Cookies im Browser aktiviert..

			if (refreshActive) {
				return;
			}
		}

		var diff = (new Date().getTime() - lastRefresh) / 1000;
		var globalSessionTimeout = de.his.common.ContextInformation
				.get("global-session-timeout");
		var diffSeconds = (globalSessionTimeout - diff);
		if (diffSeconds > 0) {
			var min = Math.floor(diffSeconds / 60);
			var sec = Math.floor(diffSeconds % 60);
			if (min > 0) {
				jQuery('#sessionCounter').html(min + 1);
			} else {
				jQuery('#sessionCounter').html('00:' + (sec < 10 ? '0' + sec : sec));
			}

			// Prüfen ob Nutzer eingeloggt ist.
			// Klicken auf "OK" ruft eine Funktion auf, welche die Session
			// zurücksetzen und verlängern kann.
			var loginForm = document.getElementById("sessionTimeoutLoginForm");
			
			//console.log("Cookie cs.sys.hisinoneAutoLoginEnabled: ", autoLoginEnabled);
			if (min == 5 && (sec >= 0 && sec < 2) && !autoLoginEnabled) {
				// Prüfen ob bereits Alert Meldungen ausgegeben wurde
				var alertMessage = document.getElementById("alert");
				if (!alertMessage) {
					var language = de.his.common.LanguageHelper.currentLanguage();
					var alertTitle = null;
					var alertText = null;
					var alertButton = null;
					if (language == "de") {
						// Deutsche Meldung
						alertTitle = "<div class='alertWarningTitle'><span class='iconfont-time'></span><h1>Warnung</h1></div>";
						alertText = "<div class='alertWarningBody'><p>Zu Ihrer eigenen Sicherheit werden Sie in 5 Minuten automatisch vom System abgemeldet.<br />Bitte klicken Sie auf  'Anmeldung verlängern', um Ihre Sitzung zu verlängern.</p></div>";
						alertButton = "Anmeldung verlängern";
					} else {
						// Englische Meldung
						alertTitle = "<div class='alertWarningTitle'><span class='iconfont-time'></span><h1>Warning</h1></div>";
						alertText = "<div class='alertWarningBody'><p>You will be automatically logged out in 5 minutes  for security reasons.<br />Please choose 'Stay logged in' to renew your session.</p></div>";
						alertButton = "Stay logged in";
					}
					alert(alertTitle, alertText, {
						button_title : alertButton,
						callback : function() {
							de.his.modules.SessionRefresh.refreshSession();
						}
					});
				}
			}
		} else {
			jQuery('#sessionCounter').html('--');
			timedOut = true;
			if (resfreshViewTimer) {
				window.clearInterval(resfreshViewTimer);
			}

			if (!loginFormShown) {
				de.his.modules.SessionTimeout.showLoginForm();
				loginFormShown = true;
			}
		}
	};

	// Wenn nur noch 0 bis 5 Minuten der Sessionzeit eines eingeloggten
	// Benutzers übrig sind, kann dieser die Session mit klicken auf "ok"
	// zurücksetzen und verlängern.
	this.refreshSession = function() {
		if (!timedOut) {
			this.refreshServerSession();
			this.refresh();
			this.init();
		}
	};
	
	this.lastRefresh = function() {
	    lastRefresh = new Date().getTime();
        de.his.common.Cookie.create('lastRefresh', lastRefresh);
	}
	
	this.setRefreshServerSessionTimeout = function( ajax ){
		if (!timedOut) {
			console.log("Running refresh Session Timeout.")
		    this.refreshServerSession( ajax );
			resfreshTimer = window.setTimeout( function() {
		        de.his.modules.SessionRefresh.setRefreshServerSessionTimeout();
		    }, refreshSec*1000);
		}
	}

	/**
	 * refreshes the session one time
	 */
	this.refreshServerSession = function( ajax ) {
	    var me = this;
		console.log("refreshing Server Session");
		if( ajax !== false ){ //ajax can be undefined, null or boolean - only interesting if its false
		    jQuery.ajax({
		    	global: false,
	            url : de.his.common.ContextInformation.get('context-path') + '/pages/common/setSessionTimeout.faces',
	            success : function() {
	                me.lastRefresh();
	            },
	            error :  function() {
	            	de.his.ajax.Refresher.onError('Fehler beim aktuallisieren der Server Session.');
	            },
	            complete : function(){
	            	self.refresh();
	            }
	        });
		}else{
		    me.lastRefresh();
		}
		
	};

	/**
	 * sets global refresh flag on server session
	 */
	this.setRefresh = function(value) {
		console.log("set Server Refresh Session Cookie to "+value);
		jQuery.ajax({
			global: false,
			url : de.his.common.ContextInformation.get('context-path')
					+ '/pages/common/setSessionTimeout.faces?refreshSession='
					+ value,
			success : function() {
				lastRefresh = new Date().getTime();
				de.his.common.Cookie.create('lastRefresh', lastRefresh);
				de.his.common.ContextInformation.set("global-refresh-session", value);
			},
			 error :  function() {
				 de.his.ajax.Refresher.onError('Fehler beim setzen des globalen Refresh flags.');
			 },
            complete : function(){
            	self.refresh();
            }
		});
	};
};/**
 * Definiert einige Tastenkombinationen, die Funktionen in HISinOne ausführen
 */
de.his.modules.Shortcuts = new function() {
    de.his.modules.ModuleRegistry
	    .registerModule(this);
    this.moduleName = "de.his.modules.Shortcuts";
    this.init = function() {
        /** bei Nachfragen (callBack.xhtml) kann der Abbrechen/Nein-Button per Escape-Taste bedient werden. */
        jQuery(document).keyup(function(e) {
            if (e.keyCode == 13) { // enter
                jQuery('input[type="submit"].ok-button-behavior').first().click();
            }
            if (e.keyCode == 27) { // esc
                // Wenn ein cancelButton vorhanden ist, dann soll nur dieser ausgelöst werden
                var cancelButton = jQuery('input[type="submit"].cancel-button-behavior').first();
                if (cancelButton.length > 0) {
                    cancelButton.click();
                } else {
                    jQuery('.simple-close-button-behavior').click();
                }
            } 
        });
    };
};/**
 * Objekt das Funktionalitäten zum 'Warten' bereitstellt.
 * - Graut den Bildschirm (kurz) aus, wenn
 *   - eine Form submitted wird
 *   - markierte Links geklickt werden
 *     - markierung erfolgt mit der Styleklasse 'waiting-behavior'
 *     - mit der Styleklasse 'short-waiting-behavior' markierte Links bewirken nur einen "warten"-Cursor
 *   - links, buttons und inputs innerhalb
 * - Verhindert bspw. auch Doppelklicks.
 *
 * Bei Downloads:
 * Die Download-Ausgabe-Komponente muss ein Cookie 'download-complete=true' mitschicken, damit das JS erkennt, das der Doownload fertig ist.
 */
de.his.modules.Waiting = new function() {
    de.his.modules.ModuleRegistry
        .registerModule(this)
        .registerAjaxRefreshModule(this);
    this.moduleName = "de.his.modules.Waiting";
    this.init = function() {
    	console.log('[.waiting] init');
        initIntern(this, false);
        jQuery(window).on("unload", function() {    	
            // dummy unload, forces Firefox to re-run the on-ready code if the user pressed the back button. 
        });
        
        jQuery(window).on("beforeunload", function() {
            console.log("[.waiting] beforeunload");            
            jsf.ajax.cancel(); // Laufende und ausstehende Ajax-Requests entfernen
            // PrimeFaces.ajax.Queue.abortAll(); // wird vielleicht mal interessant
        });
        
    };

    this.refresh = function(data) {
    	console.log('[.waiting] refresh');    
    	var doResetWaiting = (data == null) || hasWaitingBehavior(data); 
		initIntern(this, doResetWaiting);
    };

    var initIntern = function(self, doResetWaiting) {
    	if (doResetWaiting) {
    		resetNormalWaiting();    		
    	}
        console.log("waiting start");
        /** bei jedem submit den Screen ausgrauen. */
        jQuery( "form:not(.no-waiting-behavior, .full-screen-waiting-behavior)" ).each( function(index, elem) {
        	if( typeof jQuery(elem).data("waitingBehaviorSet") !== 'undefined'){
				return;
			}
			jQuery(elem).data("waitingBehaviorSet", true);
        	// schaltet das Script bei Angular o.ä. eingebetteten Anwendungen aus.
        	if(jQuery(".noHisJsModule").length > 0 && jQuery(elem).closest(".noHisJsModule").length > 0){
        		// Angular Formulare ausnehmen.
        		console.log(".noHisJsModule found on parent... Do not register waiting handlers.");
        		return;
        	}
        	
            // JSF führt direkt form.submit aus, wenn kein form.onsubmit gesetzt ist.
            // Und wider erwarten schreibt sich jQuery hier nicht rein, wenn man .submit(function(){}) benutzt
            var prevOnsubmit = this.onsubmit;
            this.onsubmit = function( event ) {
            	
                var $form = jQuery( this );
                if ( $form.attr("target") !== "_blank" && $form[0].tagName){
                	console.log("form: "+this.id);
                    self.executeNormalWaiting(this.id);
                }
                if (prevOnsubmit) {
                    prevOnsubmit(event);
                }
            };
        } );
        
        /** bei speziell ausgezeichneten Buttons ein 'full screen waiting' durchführen. */
        jQuery('form.full-screen-waiting-behavior').submit(function(e) {
			if( typeof jQuery(this).data("waitingBehaviorSet") !== 'undefined'){
				return;
			}
			jQuery(this).data("waitingBehaviorSet", true);
            if (de.his.common.ContextInformation.isEditUITexts()) {
                return;
            }
            

            // den eigentlichen Text über data-Attribut holen
            // TODO JSF2 Dazu muss die JSF-Komponenten diese Attribute rendern
            // TODO JSF2 Für die Anmeldemaske ginge es schon so, da hier eh html-Input-Tags benutzt werden
            // SOLUTION: <f:passThroughAttribute name="data-waiting-text" value="Bitte warten..." />
            var text = jQuery(this).data('waiting-text') || "";
            self.executeFullScreenWaiting(text);
            
        });
        
        jQuery('input.full-screen-waiting-behavior, a.full-screen-waiting-behavior, button.full-screen-waiting-behavior').not(".no-waiting-behavior").click(function(e) {
			if( typeof jQuery(this).data("waitingBehaviorSet") !== 'undefined'){
				return;
			}
			jQuery(this).data("waitingBehaviorSet", true);
        	if (this.tagName == 'a' && (e.ctrlKey || e.shiftKey)) {
        		return;
        	}
        	console.log("execute Full Screen Waiting");
        	var text = jQuery(this).data('waiting-text') || "";
            self.executeFullScreenWaiting(text);
            setWaitingBehaviorMarker(this);
            
        });

        
        /**
         * only allow interactive elements (input, a, button) to have an waiting behaviour. Otherwise non active elements can block the UI upon accidental clicks
         */
        jQuery('input.waiting-behavior, a.waiting-behavior, button.waiting-behavior, .waiting-behavior input, .waiting-behavior a, .waiting-behavior button').click(function(e) {
			if( typeof jQuery(this).data("waitingBehaviorSet") !== 'undefined'){
				return;
			}
			jQuery(this).data("waitingBehaviorSet", true);
        	if ((this.tagName.toLowerCase() === 'a' && (e.ctrlKey || e.shiftKey))
        			|| (this.tagName.toLowerCase() === 'a' && jQuery(this).attr("target") === "_blank")){
        		return;
        	}
        	console.log("tagName:" + this.tagName == 'a');
        	console.log("execute Normal Waiting");
            self.executeNormalWaiting(this.id);
            setWaitingBehaviorMarker(this);            
        });
        
        jQuery('input.short-waiting-behavior:not(.rf-sel, [onchange]), a.short-waiting-behavior:not(.rf-sel), button.short-waiting-behavior:not(.rf-sel), .short-waiting-behavior:not(.rf-sel, .radio-buttons, .ui-selectonemenu) input:not([onchange]), .short-waiting-behavior:not(.rf-sel) button, .short-waiting-behavior:not(.rf-sel) a, .scroller a').not(".waiting-behavior, .no-waiting-behavior, .full-screen-waiting-behavior").click(function(e) {
        	if( typeof jQuery(this).data("waitingBehaviorSet") !== 'undefined'){
				return;
			}
			jQuery(this).data("waitingBehaviorSet", true);
			if ((this.tagName.toLowerCase() === 'a' && (e.ctrlKey || e.shiftKey))
        			|| (this.tagName.toLowerCase() === 'a' && jQuery(this).attr("target") === "_blank")) {
        		return;
        	}
        	console.log("execute Short Waiting (not .rd-sel)");
            self.executeShortWaiting(this.id);
            setWaitingBehaviorMarker(this);
        });

        
        // Radiobuttons benötigen 'change'-Event
        jQuery('.short-waiting-behavior.radio-buttons:not(.no-waiting-behavior, .full-screen-waiting-behavior)').on("change", function(e){
        	if( typeof jQuery(this).data("waitingBehaviorSet") !== 'undefined'){
				return;
			}
			jQuery(this).data("waitingBehaviorSet", true);
			console.log("execute Short Waiting (radio-buttons)");
            self.executeShortWaiting(this.id);
            setWaitingBehaviorMarker(this);            
        });       

        // Sonstige Inputs mit 'change'-Event
        jQuery('input.short-waiting-behavior[onchange]:not(.no-waiting-behavior)').on("change", function(e){
			if( typeof jQuery(this).data("waitingBehaviorSet") !== 'undefined'){
				return;
			}
			jQuery(this).data("waitingBehaviorSet", true);
        	console.log("execute Short Waiting (input with 'onchange' e.g. checkboxes)");
            self.executeShortWaiting(this.id);
            setWaitingBehaviorMarker(this);            
        });

		// Inputs mit 'change'-Event innerhalb einer Tabelle - z.B. selectManyCheckbox -
        jQuery('table.short-waiting-behavior:not(.no-waiting-behavior)').on("change", 'input[onchange]', function(e){
			if( typeof jQuery(this).data("waitingBehaviorSet") !== 'undefined'){
				return;
			}
			jQuery(this).data("waitingBehaviorSet", true);
			console.log("execute Short Waiting (input with 'onchange' e.g. checkboxes in selectManyCheckbox component)");
			jQuery(this).addClass('short-waiting-behavior');
            self.executeShortWaiting(this.id);
            setWaitingBehaviorMarker(this);            
        });    
        
        // Primefaces SelectOneMenu benötigt 'selectitem'-Event
        jQuery('.short-waiting-behavior.ui-selectonemenu').on("selectitem", function(e){
			if( typeof jQuery(this).data("waitingBehaviorSet") !== 'undefined'){
				return;
			}
			jQuery(this).data("waitingBehaviorSet", true);
        	console.log("execute Short Waiting (.ui-selectonemenu)");
            self.executeShortWaiting(this.id);
            setWaitingBehaviorMarker(this);            
        });
        
    };   
    
    var setWaitingBehaviorMarker = function(source) {
        source.setAttribute("data-startsWaiting", "true");        	
    }
    
    var hasWaitingBehavior = function(data) {
    	
    	// Workaround für manipulierte checkboxes ('checkboxified')
    	if (data.source.type == "checkbox") {
    		return data.source.classList.contains("short-waiting-behavior");
    	}
    	
    	return data.source.getAttribute("data-startsWaiting") == "true";
    }
    
    this.executeFullScreenWaiting = function(waitingText){
		if (jQuery("#full-screen-waiting").length > 0) {
        	console.log('[.waiting] full-screen-waiting already exists');
            return;
        }  
        // normal waitings are needed by automated tests. 
    	executeWaiting('curtainBackgroundTransparent', this.id
    	);
    	
	 	jQuery('body').append(''+
                 '<div id="full-screen-waiting" class="curtainBoxCallBackBackground waitingCursor">'+
                 '    <center><div class="curtainBoxCallBack">'+
                 '        <div class="infobox confirm_infobox" style="background-color: rgba(255, 255, 255, 0.9) !important;">'+
                 '            <center>'+
                 '                <div class="imageContainer imageContainerWaitingPadding">'+
                 
                 // Variant 1
             	'<div class="floatBarsGContainer" >'+
	         	'	<div id="" class="floatBarsG floatBarsG_1"></div>'+
	         	'	<div id="" class="floatBarsG floatBarsG_2"></div>'+
	         	'	<div id="" class="floatBarsG floatBarsG_3"></div>'+
	         	'	<div id="" class="floatBarsG floatBarsG_4"></div>'+
	         	'	<div id="" class="floatBarsG floatBarsG_5"></div>'+
	         	'	<div id="" class="floatBarsG floatBarsG_6"></div>'+
	         	'	<div id="" class="floatBarsG floatBarsG_7"></div>'+
	         	'	<div id="" class="floatBarsG floatBarsG_8"></div>'+
         		'</div>'+
                 
					// original
                 //'                    <img src="/HISinOne/images/loader/loader_33.gif" title=" " alt=" " />'+
                 '                </div>'+
                 '                ' + waitingText + ''+
                 '            </center>'+
                 '        </div>'+
                 '        <div class="clearer"></div>'+
                 '    </div></center>'+
                 '</div>');
    }
        
    this.executeShortWaiting = function(sourceId) {
        executeWaiting('curtainBackgroundTransparent loadingTopAnimation', sourceId);
    };

    this.executeNormalWaiting = function(sourceId) {
        executeWaiting('curtainBoxCallBackBackground loadingTopAnimation', sourceId);
    };

    var executeWaiting = function(styleClass, sourceId) {
        if (de.his.common.ContextInformation.isEditUITexts()) {
            return;
        }
        if (jQuery("#global-waiting").length > 0) {
        	console.log('[.waiting] global-waiting already exists - skipping: %s from %s', styleClass, sourceId);
            return;
        }        
        
    	console.log('[.waiting] setting global-waiting with style: %s from %s', styleClass, sourceId);        
        jQuery('body').append(''+
        		'    <div id="global-waiting" class="' + styleClass + ' waitingCursor">'+
                '        <div></div>'+ // do not remove. is used for the "flicker" effekt on waiting click
                '    </div>');
        
        // Warn when user tries to click while waiting to complete the request
        jQuery("#global-waiting").click(function() {
            var childs = jQuery(this).children();
            childs.fadeIn(50, function() {
                childs.fadeOut(30);
            });
        });
        
        // Bei Download-Links wird die Seite nicht neugerendert.
        // Deswegen wird wird hier ein Cookie ausgelesen, dass durch die Download-Ausgabe-Komponente gesetzt werden muss.
        resetOnComplete('global-waiting', sourceId);
    };

    var resetOnComplete = function(elementId, sourceId) {
        setTimeout(function () {
            reset(elementId, sourceId);
        }, 100);
    };

    var reset = function(elementId, sourceId) {
        if (de.his.common.Cookie.read("download-complete") == 'true') {
        	de.his.common.Cookie.erase("download-complete");
			console.log('[.waiting] download-complete; resetting: %s from %s', elementId, sourceId);
			
        	jQuery('#'+elementId).css("animation", "fadeout 0.5s");
 			setTimeout(function () {
                jQuery('#' + elementId).remove();
            }, 500);
            
        } else {
            setTimeout(function () {
            	// console.log('[.waiting] reset step: %s from %s', elementId, sourceId);            	
                    reset(elementId, sourceId);
                }, 100);
        }
    };

    var resetNormalWaiting = function() {
		jQuery('#global-waiting').css("animation", "fadeout 0.5s");
    	jQuery('#global-waiting').css("cursor", "initial");
        setTimeout(function(){
        	if(de.his.common.browser.isChrome()){
        		de.his.common.chromeCursorFix();
        	}
        	console.log('[.waiting] resetting global-waiting');        	
        	jQuery('#global-waiting').remove();
        }, 500);
        
		if (jQuery("#full-screen-waiting").length > 0) {
        	jQuery('#full-screen-waiting').css("animation", "fadeout 0.5s");
	        setTimeout(function(){
	        	if(de.his.common.browser.isChrome()){
	        		de.his.common.chromeCursorFix();
	        	}
	        	console.log('[.waiting] resetting global-waiting');        	
	        	jQuery('#full-screen-waiting').remove();
	        }, 500);
        }
		de.his.common.Cookie.erase("download-complete");
    };
    
    this.resetWaitingBehaviour = function(){
    	resetNormalWaiting();
    }
    /**
     * small or big
     * 2 or 1
     */
    this.getWaitingAnimationHtml = function (variant){
    	if(variant === 'big' || variant === 1){
    		var html = '<div class="floatBarsGContainer waitingAnimation">'+
				'<div class="floatBarsG floatBarsG_1"></div>'+
				'<div class="floatBarsG floatBarsG_2"></div>'+
				'<div class="floatBarsG floatBarsG_3"></div>'+
				'<div class="floatBarsG floatBarsG_4"></div>'+
				'<div class="floatBarsG floatBarsG_5"></div>'+
				'<div class="floatBarsG floatBarsG_6"></div>'+
				'<div class="floatBarsG floatBarsG_7"></div>'+
				'<div class="floatBarsG floatBarsG_8"></div>'+
			'</div>';
    	}
    	if(variant === 'small' || variant === 2){
    		var html = '<div class="theySeeMeLoading" >'+
		    '<div class="cssload-loader waitingAnimation" >'+
				'<div class="cssload-flipper">'+
					'<div class="cssload-front"></div>'+
					'<div class="cssload-back"></div>'+
				'</div>'+
			'</div>'+
		'</div>';
    	}
    	return html;
    };
    /**
     * removes all objects with .waitingAnimation
     */
    this.removeWaitingAnimationHtml = function (){
    	console.log('[.waiting] removing waitingAnimation');        	    	
    	jQuery(".waitingAnimation").remove();
    };
    

    this.isShortWaitingActive = function () {
    	var globalWaiting = jQuery('#global-waiting.curtainBackgroundTransparent');
		return globalWaiting.length > 0;
    }
    
    this.isFullWaitingActive = function () {
    	var globalWaiting = jQuery('#global-waiting.curtainBoxCallBackBackground');
    	if (globalWaiting.length > 0) {
    		return true;
    	}
    	
    	var fullScreenWaiting = jQuery('#full-screen-waiting');
    	if (fullScreenWaiting.length > 0) {
    		return true;
    	}
    	
    	return false;
    }
};/**
 * fügt Links mit der Klasse js_outputLink_newWindow eine popup funktionalität hinzu und zentriert das popup automatisch.
 */
de.his.modules.Window = new function() {
    de.his.modules.ModuleRegistry.registerModule(this);
    this.moduleName = "de.his.modules.Window";
    this.init = function() {
        jQuery(".outputLink-newWindow-behavior").click(function(event) {
            var width,
                height;
            
            event.preventDefault();
            
            // get Width and Height, otherwise use default
            if (jQuery(this).attr('data-popupWidth') !== undefined) {
                width = jQuery(this).attr('data-popupWidth');
            } else {
                width = 800; // default Width
            }
            if (jQuery(this).attr('data-popupHeight') !== undefined) {
                height = jQuery(this).attr('data-popupHeight');
            } else {
                height = 400; // default Height
            }
            // center popup window automatically
            var top = (document.body.clientHeight / 2) - (height / 2);
            var left = (document.body.clientWidth / 2) - (width / 2);

            window.open(jQuery(this).attr("href"), 'newwindow', 'menubar=no,resizable=yes,scrollbars=yes,status=no,width=' + width + ',height=' + height + ',top=' + top + ',left=' + left + '');
        });
    };
};/**
 * Zweck:
 * - linkes Menü per JS ein-/ausklappen. Der Zustand wird per f:ajax an den Server übertragen.
 * - mobiles menü im mobile modus
 * - Änderungen am menü für desktop ansicht auf mobilen Geräten
 */

de.his.modules.NavigationMenu = new function() {

	de.his.modules.ModuleRegistry.registerModule(this);
    this.moduleName = "de.his.modules.NavigationMenu";
	var navigation = {
			/**
			 * used to determine whether the navigation is currently open - only for mobile
			 * @property navOpen
			 * @private
			 * @type {Boolean}
			 * @default false
			 */
			navOpen: false,
			/**
			 * @property topNav
			 * @type {jQuery Object}
			 * @private
			 * @default null
			 */
			topNav: null,
			/**
			 * @property leftMenu
			 * @type {jQuery Object}
			 * @private
			 * @default null
			 */
			leftMenu: null,
			/**
			 * @property minNav
			 * @type {jQuery Object}
			 * @private
			 * @default null
			 */
			minNav: null,
			/**
			 * @property touchMoved
			 * @type {Boolean}
			 * @private
			 * @default null
			 */
			touchMoved: null,
			/**
			 * @property childULClass
			 * @type String}
			 * @default "smartphoneNavigation"
			 */
			childULClass: "smartphoneNavigation",
			/**
			 * stop the height resize event being set more than once - memory leak
			 * @property winheightResize
			 * @private
			 * @type {Boolean}
			 * @default false
			 */
			winheightResize: false,
			/**
			 * used on smartphones for showing menus on top of each other
			 * @property globalZindex
			 * @type {Integer}
			 * @default 10
			 */
			globalZindex: 10,
			/**
			 * attached to the body element to indicate that the navigation is open and apply certain styles
			 * @property navigationOpenClass
			 * @type {String}
			 * @private
			 * @default "navigationOpen"
			 */
			navigationOpenClass: "navigationOpen",
			/**
			 * @property mobileNav
			 * @private
			 * @type {jQuery Object}
			 * @default null
			 */
			mobileNav: null,
			/**
			 * @property mobileNavSelector
			 * @private
			 * @type {String}
			 * @default ".topMenuContainer"
			 */
			mobileNavSelector: ".topMenuContainer",
			/**
			 * 
			 */
			getNavForMobile: function(){
				var me = this;
				if(!me.mobileNav){
					me.mobileNav = jQuery( me.mobileNavSelector );
				}
				
				return me.mobileNav;
			},
			/**
			 * @method getTopNav
			 * @return {jQuery Object}
			 */
			getTopNav: function(){
				var me = this;
				if(!me.topNav){
					me.topNav = jQuery(".topMenuContainer");
				}
				return me.topNav;
			},
			/**
			 * @method getLeftMenu
			 * @return {jQuery Object}
			 */
			getLeftMenu: function(){
				var me = this;
				if(!me.leftMenu){
					me.leftMenu = jQuery("#leftMenu");
				}
				return me.leftMenu;
			},
			/**
			 * @method getMinNav
			 * @return {jQuery Object}
			 */
			getMinNav: function(){
				var me = this;
				if(!me.minNav){
					me.minNav = jQuery("#min_navigation");
				}
				return me.minNav;
			},
			/**
			 * @method removeMenu
			 */
			removeMenu:  function() {
		    	var me = this,
		    		leftMenu = me.getLeftMenu();
		    	if(!leftMenu.hasClass("_ignoreForTablet")){
		    		leftMenu.hide();
		    		me.getMinNav().show();
		            
		            // CSS Klassen ersetzen
		            jQuery(".content_navi_on").removeClass('content_navi_on').addClass('content_max_navi_off');
		            jQuery("#wrapper").attr("id", "wrapper_no_navigation");  
		    	}
		              
		    },
		    /**
		     * redirect to removeMenu
		     * @method hideMenu
		     */
		    hideMenu: function(){
		    	var me = this;
		    	return me.removeMenu.apply(me, arguments)
		    },
		    /**
			 * @method showMenu
			 */
		    showMenu: function() {
		    	var me = this,
	    			leftMenu = me.getLeftMenu();
		    	
		    	if(!leftMenu.hasClass("_ignoreForTablet")){
		    		leftMenu.show();
		    		me.getMinNav().hide();
			        
			        jQuery('.content_max_navi_off').removeClass('content_max_navi_off').addClass('content_navi_on');
			        jQuery('#wrapper_no_navigation').attr('id', 'wrapper');       
		    	}
		    },
		    /**
		     * override the behaviour of the current top navigation for smartphones - i.e the submenus in particular
			 * @method overrideNavigationForMenu
			 */
		    overrideNavigationForMenu: function(doParentLinkClick){
		    	var me = this,
		    		top = me.getTopNav(),
		    		nav = jQuery("> ul.nav", top),
		    		links;
		    	console.log('overrideNavigationForMenu');
		    	if(nav.length){
		    		links = jQuery("li.parentListItem > a", nav);
		    		console.log('we have links in nav.');
		    		if(links.length){
		    			links.click(function(event){
		    				console.log('navlink Clicked');
		    				if(jQuery(this).hasClass('subMenuLink')){
		    					// another submenu in desktop view
		    					// leave the link clickable, do nothing.
		    					console.log('subMenuLink Clicked');
		    				}else{
		    					console.log('try parentLinkClick');
		    					
		    					event.preventDefault();
		    					if(doParentLinkClick){
		    						// indicates mobile menu on mobile
		    						me.parentLinkClickMobile(this);
		    					}else{
		    						// indicates desktop menu on mobile
		    						me.parentLinkClickDesktop(this);
		    					}
		    				}
		    			});
		    		}
		    	}
		    },
		    /**
		     * called by link.click in overrideNavigationForMenu
		     * @method parentLinkClick
		     * @private
		     * @param el {HTMLElement} click events "this" property
		     */
			parentLinkClickDesktop : function(el) {
				window.console.log('parentLinkClick');
				var me = this, $this = jQuery(el), child = $this.siblings("ul"), $window = jQuery(window), orientationchange;
	
				if (child.length) {
					console.log('childs are there..');
					orientationchange = function() {
						var $thisOffset = $this.parent().offset();
	
						if ($thisOffset.left + child.width() > $window.width()) {
							child.css("left", $window.innerWidth() - child.width());
						} else {
							child.css("left", $thisOffset.left);
						}
						child.css("margin", 0); // disable margin on orientation change, easier than to compute them and take them into account
						// child.css("top", $thisOffset.top + ($this.outerHeight()));
						console.log('orientation computed!');
					};
					child.addClass(me.childULClass);
					// orientation change event
					$window.on("orientationchange, resize", orientationchange);
	
					document.ontouchend = function(e) {
						if (!$(e.target).closest('.smartphoneNavigation')) {
							jQuery(child).css('display', 'none');
							document.activeElement.blur();
						}
					};
				}
			},
		    parentLinkClickMobile: function(el){
				var me = this,
					$this = jQuery(el),
					child = $this.siblings("ul"),
					top = me.getTopNav(),
					topOffset = top.offset(),
					$window = jQuery(window),
					$document = jQuery(document),
		    		windowHeight = $document.height(),
					zIndex = $this.css("z-index"),
					orientationchange,
					backButton;
				
				if(typeof zIndex === "number"){
					zIndex += 1;
				}else{
					me.globalZindex += 1;
					zIndex = me.globalZindex
				}
				
				if(child.length){
					
					orientationchange = function(){
						
						if( jQuery('body').hasClass('navigationOpen') ){
							jQuery('.navbar-toggle').trigger('click');
						}
						
						var _top = top.offset().top,
							_windowHeight = $window.height();
						child.css("top", _top);
						child.css("bottom", "0px");
						child.css("height", jQuery('.topMenuContainer').height());	
						console.log("orientation/resize computed.")
					};
					
					child.addClass(me.childULClass);
					child.css({
						top: topOffset.top,
						bottom: "0px",
						height: jQuery('.topMenuContainer').height(),
						zIndex: zIndex
					});
					
					//orientation change
					$window.on("orientationchange", orientationchange);
					
					backButton = jQuery("> li.mobileOnly > a.backButton", child);
					if(backButton.length){
						backButton.on("click", function(){
							me.globalZindex -= 1;
							child.removeClass(me.childULClass);
							$window.off("orientationchange", orientationchange);
						});
					}
					
				}
				
	    },
		    /**
		     * this method sets the height of target to that of the (device height - it's y position)
			 * @method resizeHeight
			 * @param target {jQuery Object}
			 */
		    resizeHeight: function(target){
		    	var height = window.innerHeight ? window.innerHeight : $(window).height();
		    	target.css({
					height: (height - target.offset().top),
					overflow: "auto"
				});
		    },
		    
		    /**
		     * @method toggle
		     */
		    toggle: function(data){
		    	var me = this;
		    	return de.his.ajax.Helper.callHandlerIfPhase(data, "begin", me.toggleMenu, me);
			},
			/**
			  * used to toggle the left navigation
		     * @method toggleMenu
		     */
			toggleMenu: function(){
				var me = this,
					leftMenu = me.getLeftMenu(), 
					minNav = me.getMinNav();
				
				if(leftMenu.length && minNav.length){
					if(leftMenu.is(":visible")){
						me.removeMenu(); 
					}else{
						me.showMenu();
					}
				}
				
			},
			/**
		     * @method remove
		     */
			remove: function(data) {
				var me = this;
		        return de.his.ajax.Helper.callHandlerIfPhase(data, "begin", mw.removeMenu, me);
		    },
		    /**
		     * @method show
		     */
		    show: function(data) {
		    	var me = this;
		        return de.his.ajax.Helper.callHandlerIfPhase(data, "begin", me.showMenu, me);
		    },
		    
		    /**
		     * @method initDesktop
		     */
		    initDesktop: function() {
		        jQuery( document ).on( "click", ".topMenuLink, .subMenuLink, .bookmarkPopupMenuLink", function(e) {
		        	// Kein waiting behaviour auslösen, wenn auf einen Eintrag mit Strg+Click oder Shift+Click geklickt wird.
		        	if (e.ctrlKey || e.shiftKey) {
		        		return;
		        	}
		        	if ( jQuery(this).attr("target") !== "_blank" ){
		        		de.his.modules.Waiting.executeNormalWaiting();
		        	}
		        } );
		    },
		    
		    /**
		     * set up an initial conditions when viewed on a tablet
		     * @method initTablet
		     */
		    initTablet: function(){
		    	var me = this;
		    	
		    	jQuery(document).bind("touchstart", function(e){
	    			me.touchMoved = false;
	    		});
	    		
	    		jQuery(document).bind("touchmove", function(e){
	    			me.touchMoved = true;
	    		});
	    		
		    	jQuery(document).bind("touchend", function(e){
					var nav = me.getLeftMenu();
					
					if(nav.is(":visible")){
						
						//check if the coordinates are the same -- i.e if the use is not scrolling
						if(!me.touchMoved){
							
							if(!nav.is(e.target) && nav.has(e.target).length == 0){
								me.hideMenu();
							}	
							
						}
						
									
					}
					
				});
		    },
		    /**
		     * set up an initial conditions when viewed on a mobile
		     * @method initMobile
		     */
		    initMobile: function(){
		    	var me = this;
		    	
		    	me.overrideNavigationForMenu(true);
		    	me.initMobileNavToggle();
		    	
		    },
		    /**
		     * call the widgetPanelIconClick outside of this scope if calling this function from JSF
		     * - de.his.modules.NavigationMenu.widgetPanelIconClick
		     * @method widgetPanelIconClick
		     * this function is called by JSF in 
		     */
		    widgetPanelIconClick: function(data){
		    	var me = this,
		    		body = jQuery("body"),
		    		css = navigation.navigationOpenClass;
		    		
		    	//only for mobile
		    	if(window.device && window.device.mobile()){
		    		body.addClass( navigation.navigationOpenClass );
			    	
			    	if(me.navOpen){
		    			me.mobileHideNavigation();
		    		}else{
		    			//if the icon was clicked again to close it - if the container has no longer
		    			//any content and is no longer visible
		    			if( !jQuery(".infoboxContainer").children().length ){
		    				//remove class
		    				body.removeClass( navigation.navigationOpenClass );
		    			}
		    		}
		    	}	
		    	if (window.localStorage) {
					localStorage.setItem('wpanellsource', jQuery(data.source).attr('id'));
				}
		    },
			widgetPanelClose: function(){
				if (window.localStorage) {
					jQuery(document.getElementById(localStorage.getItem('wpanellsource'))).focus();
				}
			},
		    /**
		     * registers the events when using the ||| toggle menu button found on the mobile version of the site
		     * - imitate that of Bootstrap navigation when browser is scaled.
		     * @method initMobileNavToggle
		     */
		    initMobileNavToggle: function(){
		    	var me = this;
		    	
		    	if ( jQuery(".infoboxContainer > *").length ) {
		    	    //has children means a widget it currently open
		    	    jQuery("body").addClass( navigation.navigationOpenClass );
		    	}
		    	
		    	jQuery(".navbar-toggle").on("click", function(event){
		    		return me.toggleMobileNavigation();
		    	});
		    },
		    /**
		     * @method toggleMobileNavigation
		     */
		    toggleMobileNavigation: function(){
		    	var me = this,
		    		target = me.getNavForMobile(),
		    		widget = jQuery(".closeWidgetPanelButtonLayout > a");

	    		if(target.length){
	    			if(target.is(":visible")){
	    				me.mobileHideNavigation();
	    			}else{
	    				me.mobileShowNavigation();
	    				if(widget.length){
	        				//TODO: is there has to be a better way of closing the infoboxes!?
	    		    		//TODO: ajax request?
	        				//mimic click event
	        				widget[0].click();
	        			}
	    			}
	    		}
		    },
		    /**
		     * @method mobileHideNavigation
		     */
		    mobileHideNavigation: function(target){
		    	var me = this,
		    		target = me.getNavForMobile();
		    	
		    	jQuery("li.parentListItem > ul", target).scrollTop(0).removeClass(me.childULClass);
				jQuery("body").removeClass( me.navigationOpenClass );
				
		    	target.scrollTop(0);
				target.hide();
		    	me.navOpen = false;
		    },
		    /**
		     * @method mobileHideNavigation
		     */
		    mobileShowNavigation: function(){
		    	var me = this,
		    		target = me.getNavForMobile();
		    	
		    	jQuery("body").addClass( me.navigationOpenClass );
		    	
		    	if(!me.winheightResize){
		    		me.winheightResize = true;
		    		jQuery(window).on("resize", function(){
		    			if(me.navOpen){
		    				return me.resizeHeight(target);
		    			}
		    		});
		    	}
				
		    	target.show();
		    	me.resizeHeight(target);
				me.navOpen = true;
		    },
		    
		    /**
		     * set up event listeners etc to toggle the top navigation (usually desktop mode) by clicking on the collapse/expand button 
		     * @method initToggleTopNav
		     */
		    initToggleTopNav: function(){
		    	var me = this,
		    		closeNav,
		    		navigation,
		    		toggleBtn,
		    		closeTheNav,
		    		showTheNav;
		    	
		    	if(navigator.cookieEnabled){
	    			closeNav = window.localStorage.getItem("his_topnavigation_closed") === "true";
			    	navigation = me.getTopNav();
			    	toggleBtn = jQuery("#hisinoneHeader .toggleNavigation");
			    	closeTheNav = function () {
				    		navigation.addClass("topNavClosed");
				    		navigation.hide();
				    		toggleBtn.addClass("iconfont-arrow_right_v");
				    		toggleBtn.removeClass("iconfont-arrow_up_v");
				    };
				    showTheNav = function () {
			    		navigation.removeClass("topNavClosed");
			    		navigation.show();
			    		toggleBtn.removeClass("iconfont-arrow_right_v");
			    		toggleBtn.addClass("iconfont-arrow_up_v");
			    	};
			    	
			    	if(closeNav){
			    		closeTheNav();
			    	}
			    	
			    	toggleBtn.click(function(event, element){
			    		closeNav = !closeNav;
			    		window.localStorage.setItem("his_topnavigation_closed", closeNav);
			    		if(closeNav){
			    			closeTheNav();
			        	}else{
			        		showTheNav();
			        	}
			    		//his global function
			    		window.resizeHeader();
			    		//window.resizeIframesIfAvailable();
			    	});
		    	}
		    },
		    /**
		     * general init method, this is called when the module is loaded
		     * @method init
		     */
		    init: function(){
		    	var me = this,
		    		device = window.device,	//stop any errors if global doesn't exist
		    		minNav = me.getMinNav();

		    	if ( device && jQuery(".notBurgernavigation").length ){
		    	    if ( !jQuery("._isDesktopMode").length && !jQuery(".currentDevice_desktop").length) { //todo with left menu on tablet/mobile
		    	        if(device.tablet()){
	                        me.initTablet();
	                    }else if(device.mobile()){
	                        me.initMobile();
	                    }
		    	    }
		    	    
		    	    if(jQuery(".currentDevice_desktop").length && jQuery(".originDevice_mobile").length){
		    	    	me.overrideNavigationForMenu(false);
		    	    }
		    	    
		    	    if ( device.desktop() ) {
		    	        me.initDesktop();
		    	    }
		    	    
		    		
		    	}
		    	
		    	if(jQuery("form.hide_navigation_onready").length > 0  || (device && device.tablet())){
		    		minNav.hide();
		    		me.hideMenu();
		    	}

		    	// me.initDesktop();
				if ( jQuery(".notBurgernavigation").length ){
		    		me.initToggleTopNav();
				} else {
					me.initDesktop();
				}
		    	
		    }
			
	};
	
	this.navigation = navigation;
	
	//map old functions in case they are used elsewhere
	//TODO: remove and change any calls to these functions and not .navigation
    this.toggle = function(){
    	// this scope in this context is changed at some point and cannot see this.navigation 
    	// hence the navigation variable
    	return navigation.toggle.apply(navigation, arguments);
    };
    this.toggleMenu = function(){
    	return navigation.toggleMenu.apply(navigation, arguments);
    };
    this.hideMenu = function(){
    	return navigation.hideMenu.apply(navigation, arguments);
    };
    this.remove = function(){
    	return navigation.remove.apply(navigation, arguments);
    };
    this.show = function(){
    	return navigation.show.apply(navigation, arguments);
    };
    // ********** //
    
    this.init = function(){
    	return navigation.init.apply(navigation, arguments);
    };
    this.widgetPanelIconClick = function(){
    	return navigation.widgetPanelIconClick.apply(navigation, arguments);
    };
this.widgetPanelClose = function(){
    	return navigation.widgetPanelClose.apply(navigation, arguments);
    };
 
    
};

/**
 * Author: Daniel Dziegielewski
 * 
 */

de.his.modules.sys = new function() {
    de.his.modules.ModuleRegistry.registerModule(this)
    .registerAjaxRefreshModule(this);
    
    this.moduleName = "de.his.modules.sys";

    this.init = function() {
    	this.stopHoverWhenScrolling();
    };
    
    this.initWithAjax = function() {
    };
    
    // Stoppt jegliche Hover-Effekte wenn der User scrollt. (#170492)
    this.stopHoverWhenScrolling = function(){    	
    	
    	if(jQuery(".originDevice_mobile")[0]){
    		// do not do this on mobile devices, it is very annoying
    		return;
    	}
    	
    	var body = document.body,
        timer;
	
	    window.addEventListener('scroll', function() {
	      clearTimeout(timer);
	      if(!body.classList.contains('disable-hover')) {
	        body.classList.add('disable-hover');
	      }
	      
	      timer = setTimeout(function(){
	        body.classList.remove('disable-hover');
	      },200);
	    }, false);
	    
	    jQuery(".rf-sel-lst-scrl").on('scroll', function() {
		      clearTimeout(timer);
		      if(!body.classList.contains('disable-hover')) {
		        body.classList.add('disable-hover');
		      }
		      
		      timer = setTimeout(function(){
		        body.classList.remove('disable-hover');
		      },50);
		    });
    };
    
    this.refresh = function() {
        this.initWithAjax();
    };
};/* Placeholders.js v3.0.2 */
/*!
 * The MIT License
 *
 * Copyright (c) 2012 James Allardice
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */
!function(a){"use strict";function b(){}function c(){try{return document.activeElement}catch(a){}}function d(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return!0;return!1}function e(a,b,c){return a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent?a.attachEvent("on"+b,c):void 0}function f(a,b){var c;a.createTextRange?(c=a.createTextRange(),c.move("character",b),c.select()):a.selectionStart&&(a.focus(),a.setSelectionRange(b,b))}function g(a,b){try{return a.type=b,!0}catch(c){return!1}}function h(a,b){if(a&&a.getAttribute(B))b(a);else for(var c,d=a?a.getElementsByTagName("input"):N,e=a?a.getElementsByTagName("textarea"):O,f=d?d.length:0,g=e?e.length:0,h=f+g,i=0;h>i;i++)c=f>i?d[i]:e[i-f],b(c)}function i(a){h(a,k)}function j(a){h(a,l)}function k(a,b){var c=!!b&&a.value!==b,d=a.value===a.getAttribute(B);if((c||d)&&"true"===a.getAttribute(C)){a.removeAttribute(C),a.value=a.value.replace(a.getAttribute(B),""),a.className=a.className.replace(A,"");var e=a.getAttribute(I);parseInt(e,10)>=0&&(a.setAttribute("maxLength",e),a.removeAttribute(I));var f=a.getAttribute(D);return f&&(a.type=f),!0}return!1}function l(a){var b=a.getAttribute(B);if(""===a.value&&b){a.setAttribute(C,"true"),a.value=b,a.className+=" "+z;var c=a.getAttribute(I);c||(a.setAttribute(I,a.maxLength),a.removeAttribute("maxLength"));var d=a.getAttribute(D);return d?a.type="text":"password"===a.type&&g(a,"text")&&a.setAttribute(D,"password"),!0}return!1}function m(a){return function(){P&&a.value===a.getAttribute(B)&&"true"===a.getAttribute(C)?f(a,0):k(a)}}function n(a){return function(){l(a)}}function o(a){return function(){i(a)}}function p(a){return function(b){return v=a.value,"true"===a.getAttribute(C)&&v===a.getAttribute(B)&&d(x,b.keyCode)?(b.preventDefault&&b.preventDefault(),!1):void 0}}function q(a){return function(){k(a,v),""===a.value&&(a.blur(),f(a,0))}}function r(a){return function(){a===c()&&a.value===a.getAttribute(B)&&"true"===a.getAttribute(C)&&f(a,0)}}function s(a){var b=a.form;b&&"string"==typeof b&&(b=document.getElementById(b),b.getAttribute(E)||(e(b,"submit",o(b)),b.setAttribute(E,"true"))),e(a,"focus",m(a)),e(a,"blur",n(a)),P&&(e(a,"keydown",p(a)),e(a,"keyup",q(a)),e(a,"click",r(a))),a.setAttribute(F,"true"),a.setAttribute(B,T),(P||a!==c())&&l(a)}var t=document.createElement("input"),u=void 0!==t.placeholder;if(a.Placeholders={nativeSupport:u,disable:u?b:i,enable:u?b:j},!u){var v,w=["text","search","url","tel","email","password","number","textarea"],x=[27,33,34,35,36,37,38,39,40,8,46],y="#ccc",z="placeholdersjs",A=new RegExp("(?:^|\\s)"+z+"(?!\\S)"),B="data-placeholder-value",C="data-placeholder-active",D="data-placeholder-type",E="data-placeholder-submit",F="data-placeholder-bound",G="data-placeholder-focus",H="data-placeholder-live",I="data-placeholder-maxlength",J=100,K=document.getElementsByTagName("head")[0],L=document.documentElement,M=a.Placeholders,N=document.getElementsByTagName("input"),O=document.getElementsByTagName("textarea"),P="false"===L.getAttribute(G),Q="false"!==L.getAttribute(H),R=document.createElement("style");R.type="text/css";var S=document.createTextNode("."+z+" {color:"+y+";}");R.styleSheet?R.styleSheet.cssText=S.nodeValue:R.appendChild(S),K.insertBefore(R,K.firstChild);for(var T,U,V=0,W=N.length+O.length;W>V;V++)U=V<N.length?N[V]:O[V-N.length],T=U.attributes.placeholder,T&&(T=T.nodeValue,T&&d(w,U.type)&&s(U));var X=setInterval(function(){for(var a=0,b=N.length+O.length;b>a;a++)U=a<N.length?N[a]:O[a-N.length],T=U.attributes.placeholder,T?(T=T.nodeValue,T&&d(w,U.type)&&(U.getAttribute(F)||s(U),(T!==U.getAttribute(B)||"password"===U.type&&!U.getAttribute(D))&&("password"===U.type&&!U.getAttribute(D)&&g(U,"text")&&U.setAttribute(D,"password"),U.value===U.getAttribute(B)&&(U.value=T),U.setAttribute(B,T)))):U.getAttribute(C)&&(k(U),U.removeAttribute(B));Q||clearInterval(X)},J);e(a,"beforeunload",function(){M.disable()})}}(this),function(a,b){"use strict";var c=a.fn.val,d=a.fn.prop;b.Placeholders.nativeSupport||(a.fn.val=function(a){var b=c.apply(this,arguments),d=this.eq(0).data("placeholder-value");return void 0===a&&this.eq(0).data("placeholder-active")&&b===d?"":b},a.fn.prop=function(a,b){return void 0===b&&this.eq(0).data("placeholder-active")&&"value"===a?"":d.apply(this,arguments)})}(jQuery,this);de.his.modules.CustomizePortalNotification = new function() {
	de.his.modules.ModuleRegistry.registerModule(this);
	
    this.moduleName = "de.his.modules.CustomizePortalNotification";
    
	this.init = function() {
    }

	this.closeCustomizePortalNotification = function() {
		var loginDiv = document.getElementById('portalCustomizationNotification');
		if (loginDiv) {
			loginDiv.className = "noDisplay";
		}
		return false;
	};
	
};use_package( "de.his.modules" );

de.his.modules.ScrollWithMe = new function() {
    var cssSelector = ".scrollWithMe",
        cssClassKeepSize = "scrollWithMe-keepSize",
        cssClass = "scrollWithMe-active";

    de.his.modules.ModuleRegistry.registerModule( this ).registerAjaxRefreshModule( this );
    this.moduleName = "de.his.modules.ScrollWithMe";
    
    this.init = function(containers) {
    	var containers = jQuery( cssSelector );
        for ( var i = 0; i < containers.length; i++ ) {
        	scrollWithMe(containers[i]);
        }
    };
    
    this.refresh = function() {
        de.his.modules.ScrollWithMe.init();
    };

    this.refresSingleContainer = function(selector) {
		let single_element = jQuery(selector);
		scrollWithMe(single_element);
	};

    var scrollWithMe = function( element ) {
    	//console.log("scroll : ", element);
        var container = jQuery( element ),
            containerLeft,
            ovContainerTop,
            containerWidth,
            cssConfig,
            scrollFunction,
            limitInt;
	        //console.log("container scroll : ", container);
	        if ( container.length > 0 ) {
	            // containerLeft = container.offset().left;
	            // containerWidth = container.width();
				if( jQuery('.scrollWithMe-active').length ) {
					jQuery('.scrollWithMe-active').removeClass('scrollWithMe-active');
					ovContainerTop = parseInt( container.offset().top );  
					jQuery('.scrollWithMe').addClass('scrollWithMe-active');
					 	
				} 
				else {
	            ovContainerTop = parseInt( container.offset().top );  //parseInt to get whole number
				}
	            
	            scrollFunction = function(){
	            	var win = jQuery( window ),
	                scrollTop = win.scrollTop(),
	                scrollLeft = win.scrollLeft(),
	                containerTop = parseInt( container.offset().top ),
	                newContainerLeft;  //parseInt to get whole number
	            	
	            	if ( de.his.component.overlay && de.his.component.overlay.modalMode ) {
	                	//do nothing when overlay is open
	                	return;
	           		}
	
	            if ( !container.hasClass( cssClass ) ) {
	                //scroller not active

					if ( scrollTop > containerTop ) {
						// set var if container on top of window
						containerWidth = container.width();
						containerLeft = container.offset().left;
	                	container.parent().css("padding-top", container.outerHeight(true)+2+"px");
	                    container.addClass( cssClass );
	                
	
		                //calculate the left PX when scrolling right in the browser
		                newContainerLeft = containerLeft - scrollLeft
		                newContainerLeft = newContainerLeft < 0 ? 0 : newContainerLeft; //don't let it go below 0
		
		                cssConfig = {
		                    left: newContainerLeft + "px"   //apply new calculation
		                };
						
		                if ( container.hasClass( cssClassKeepSize ) ) {
		                    cssConfig.maxWidth = containerWidth;
		                }
						container.css( cssConfig );
					}
					
	            } else {
	                //scroller is active
	                if ( window.device && window.device.mobile() ) {
	                    //smartphone
	                    limitInt = ovContainerTop + 0;
	                } else {
	                    limitInt = ovContainerTop - 20; //-20 to stop jumping when the browser size hits the boundary of the scroll trigger
	                }
	                //console.log("ovContainerTop scrollTop "+ovContainerTop+":"+scrollTop);
	                limitInt = limitInt >= 0 ? limitInt : 0; //can be minus so set to 0
	                if ( scrollTop <= ovContainerTop ) {
	                    container.removeClass( cssClass );
	                    container.parent().css("padding-top", "");

						// Reset container values
						cssConfig = {
		                    left: '',
							maxWidth: ''
		                };
 						container.css(cssConfig);
	                }
	            }			
            };
            
            //find any containers with the selector
            var containers = jQuery( cssSelector );
            //console.log("scrollWithMe: ", containers);

            de.his.modules.eventRegistry.addListener( "overlayOpen", function() {
                jQuery( containers ).each( function() {
                    //jQuery( this ).removeClass( cssClass );
                	jQuery( this ).css('z-index','998');
                } );
            } );

            de.his.modules.eventRegistry.addListener( "overlayClose", function() {
            	jQuery( containers ).each( function() {
                    //jQuery( this ).removeClass( cssClass );
            		jQuery( this ).css('z-index','999');
                } );
            	
            } );

            //listener for scroll event
            jQuery( window ).off('scroll');
            jQuery( window ).scroll( scrollFunction );

        }
    };
};/**
 * RF Picklist
 */
de.his.modules.HisinoneSelectBox = new function() {
    de.his.modules.ModuleRegistry
        .registerModule(this)
        .registerAjaxRefreshModule(this);
    this.moduleName = "de.his.modules.HisinoneSelectBox";
    this.init = function() {
    	//#113538 bugfix
        jQuery(".picklistShuttle, .picklistShuttleButtons").show();
    };

    this.refresh = function() {
        this.init();
    };
};use_package("de.his.modules.iFrameCommunication");

/**
 * Author: wahrendorff Date: 08.06.2015 Zweck: ermöglicht der im iframe
 * eingebetteten untrusted Domain der HISinOne Hauptanwendung zu antworten.
 * 
 */

de.his.modules.iFrameCommunication = new function() {
	de.his.modules.ModuleRegistry.registerModule(this)
			.registerAjaxRefreshModule(this);
	
    this.moduleName = "de.his.modules.iFrameCommunication";

	var currentHost;
	var untrustedHost;
	
	if (typeof String.prototype.startsWith !== "function") {
        // see below for better implementation!
        String.prototype.startsWith = function(str) {
            return this.indexOf(str) === 0;
        };
    }
	
	
	var getMessages = function(type) {
		var messages = [];

		jQuery("." + type + "_infobox ul.listMessages > li:not([postedtoparent])").each(function(index, elem) {
			var message = new Object();
			message.text = jQuery(elem).text();
			message.type = type;
			if (message.text !== "") {
				messages.push(message);
			}
			jQuery(elem).attr('postedtoparent', 'true');
		});
		
		var title = "";
		jQuery("." + type + "_infobox span.messages_infobox_header:not([postedtoparent])").each(function(index, elem) {
			title = jQuery(elem).text();
			jQuery(elem).attr('postedtoparent', 'true');
		});
		
		title = title.trim();
		if(title.charAt(title.length - 1) === ':'){
			title = title.slice(0, -1);
		}
		
		for(var message of messages){
			message.title = title;
		}
		
		console.log("getting " + type + " in iFrame: ", messages);
		return JSON.stringify(messages);
	};
	
	var receiveMessageInIframe = function(event) {
        // check is not needed because H1 can only be iframed by H1
        // also a check is not possible,
        // because there is no possibility to determine on which domain H1 is running

        // if (event.origin !== "https://localhost:8443") {
        // return;
        // }
        if (event.data === "Hello") {
            event.source.postMessage("Hi, there!", event.origin);
        }
        if (event.data === "showMessages") {
			for(var type of ["error", "success", "info", "warning"]){
				var messages = getMessages(type);
            	if(typeof messages !== 'undefined' && messages.trim() !== "[]"){
               		event.source.postMessage(messages, event.origin);
            	}
			}

			event.source.postMessage("resizeMe");
        }
        console.log("receiving messages in iFrame: " + event.data);
    };
    
    var receiveMessageInParent = function(event) {

        if (event.origin !== currentHost && event.origin !== untrustedHost
                || typeof event.data !== 'string' || event.data.trim() === "") {
            // do not receive Messages if IFrame is neither untrusted domain nor
            // current host
            // this is an important security measure!
            // Do never remove!
            // console.log(event.origin+" !== "+ currentHost, event);
            return;
        }

        console.log("receiving messages in Parent: '" + event.data + "' type: "+(typeof event.data), event);

		if(event.data == "resizeMe"){
			de.his.modules.IframePortletResize.handleResizeWithPortalHelper();
			return;
		}
        
        if(event.data.startsWith("[") && event.data.endsWith("]")){
            var messages = JSON.parse(event.data);
            messages.forEach(function(message, index) {
              console.log(message, index);
            });
            
            var messageTexts = [];
            if(messages.length > 0){
				messages.forEach(message => messageTexts.push(message.text));
            	de.his.component.MessagesInfobox.showMessagesInfoboxWithTitle(messageTexts, messages[0].type, messages[0].title);
            }
            return;
        }
        
		// do not show messages that do not comply with what we expect.
        console.log("message was not from this file and therefore ignored...");
        return;
       
    };
    
    var requestMessagesFromIframe = function(iFrameElement, iFrameHost) {
        console.log("request message from iframe: ",iFrameHost);
        iFrameElement.prop("contentWindow").postMessage("showMessages", iFrameHost);
    };

	this.init = function() {
        
		if (self != top && jQuery("#hisinoneHeader").length == 0) {
			// Site is loaded in an iFrame
			console.log("init postMessages on iFrame...");
			window.addEventListener("message", receiveMessageInIframe, false);
		} else {
			// Site is NOT loaded in an iFrame
			currentHost = window.location.origin;//de.his.common.ContextInformation.get("host");
			untrustedHost = de.his.common.ContextInformation.get("untrustedHost");
            console.log("currentHost: %s",currentHost);
            console.log("untrustedHost: %s",untrustedHost);
			jQuery("iframe").each(
					function() {
						var iFrameElement = jQuery(this);
						iFrameElement.on("load", function() {
							// check if an iFrame is loaded with Host or
							// UntrustedHost content
							var url = iFrameElement.attr("src");
							if (typeof url == 'undefined' || url == "") {
                                console.log("iframe url is not valid: ",url);
								return;
							} else if(url.startsWith("http")){
								console.log("iFrame URL: %s", url);
								var urlArray = url.split("://");
								var iFrameHostArray = urlArray[1].split("/");
								// enthält den Port, wenn auch die url den Port enthält
	                            // Das Script im iFrame check die event.origin, in dieser werden Defaultports entfernt,
	                            // daher müssen wir die Defaultports beim message request auch entfernen
	                            // bei "Custom" Ports wie 8080, 8008 oder 8443 müssen die Ports beibehalten werden!
	                            var iFrameHost = urlArray[0];
								var iFrameOriginPortArray = iFrameHostArray[0].split(":");
	                            if(iFrameOriginPortArray[1] == "443" || iFrameOriginPortArray[1] == "80"){
	                                console.log("remove default port(443||80) for iFrame Communication.");
	                                iFrameHost += "://" +  iFrameOriginPortArray[0];
	                            } else {
	                                // keep Port
	                                iFrameHost += "://" + iFrameHostArray[0]; 
	                            }
                            } else{ //in case "url" is a relative url
								iFrameHost = currentHost;
							}
                            console.log("iFrameHost %s",iFrameHost);
							if (iFrameHost == currentHost
									|| iFrameHost == untrustedHost) {

								console.log("init iFrame postMessages on parent...");
								window.addEventListener("message", receiveMessageInParent, false);
								setTimeout(function(){
									requestMessagesFromIframe(iFrameElement, iFrameHost);
								});
							}
							de.his.modules.eventRegistry.fireEvent( "iframe_loaded_" + iFrameElement.attr( "id" ) );
						});
					});
		}
	}

	this.refresh = function() {
		this.init();
		this.resizeInParent();
	}
	
	this.resizeInParent = function(){
		if(typeof parent !== "undefined"){
			console.log("init resize in iframe on parent...");
			try{
				parent.de.his.modules.IframePortletResize.init();
			} catch (e){
				console.error(e);
			}
			
		}
	}

};
/**
 * Author: Daniel Dziegielewski
 * Removes css class singleblock from divs with css classes roomconflict or personconflict
 */
de.his.modules.removeSingleblock = new function() {
    de.his.modules.ModuleRegistry.registerModule(this).registerAjaxRefreshModule(this);
    
    this.moduleName = "de.his.modules.removeSingleblock";

    this.init = function() {
    	jQuery(".singleblock.roomconflict").removeClass("singleblock");
    	jQuery(".singleblock.personconflict").removeClass("singleblock");
    	jQuery(".terminStyleClass.roomconflict").removeClass("roomconflict");
    	jQuery(".terminStyleClass.personconflict").removeClass("personconflict");
    }
    
    this.refresh = function() {
        this.init();
    }
};/*!
 * jQuery Mousewheel 3.1.13
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license
 * http://jquery.org/license
 */

(function (factory) {
    if ( typeof define === 'function' && define.amd ) {
        // AMD. Register as an anonymous module.
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        // Node/CommonJS style for Browserify
        module.exports = factory;
    } else {
        // Browser globals
        factory(jQuery);
    }
}(function ($) {

    var toFix  = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
        toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ?
                    ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
        slice  = Array.prototype.slice,
        nullLowestDeltaTimeout, lowestDelta;

    if ( $.event.fixHooks ) {
        for ( var i = toFix.length; i; ) {
            $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
        }
    }

    var special = $.event.special.mousewheel = {
        version: '3.1.12',

        setup: function() {
            if ( this.addEventListener ) {
                for ( var i = toBind.length; i; ) {
                    this.addEventListener( toBind[--i], handler, false );
                }
            } else {
                this.onmousewheel = handler;
            }
            // Store the line height and page height for this particular element
            $.data(this, 'mousewheel-line-height', special.getLineHeight(this));
            $.data(this, 'mousewheel-page-height', special.getPageHeight(this));
        },

        teardown: function() {
            if ( this.removeEventListener ) {
                for ( var i = toBind.length; i; ) {
                    this.removeEventListener( toBind[--i], handler, false );
                }
            } else {
                this.onmousewheel = null;
            }
            // Clean up the data we added to the element
            $.removeData(this, 'mousewheel-line-height');
            $.removeData(this, 'mousewheel-page-height');
        },

        getLineHeight: function(elem) {
            var $elem = $(elem),
                $parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent']();
            if (!$parent.length) {
                $parent = $('body');
            }
            return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16;
        },

        getPageHeight: function(elem) {
            return $(elem).height();
        },

        settings: {
            adjustOldDeltas: true, // see shouldAdjustOldDeltas() below
            normalizeOffset: true  // calls getBoundingClientRect for each event
        }
    };

    $.fn.extend({
        mousewheel: function(fn) {
            return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');
        },

        unmousewheel: function(fn) {
            return this.unbind('mousewheel', fn);
        }
    });


    function handler(event) {
        var orgEvent   = event || window.event,
            args       = slice.call(arguments, 1),
            delta      = 0,
            deltaX     = 0,
            deltaY     = 0,
            absDelta   = 0,
            offsetX    = 0,
            offsetY    = 0;
        event = $.event.fix(orgEvent);
        event.type = 'mousewheel';

        // Old school scrollwheel delta
        if ( 'detail'      in orgEvent ) { deltaY = orgEvent.detail * -1;      }
        if ( 'wheelDelta'  in orgEvent ) { deltaY = orgEvent.wheelDelta;       }
        if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY;      }
        if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; }

        // Firefox < 17 horizontal scrolling related to DOMMouseScroll event
        if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
            deltaX = deltaY * -1;
            deltaY = 0;
        }

        // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
        delta = deltaY === 0 ? deltaX : deltaY;

        // New school wheel delta (wheel event)
        if ( 'deltaY' in orgEvent ) {
            deltaY = orgEvent.deltaY * -1;
            delta  = deltaY;
        }
        if ( 'deltaX' in orgEvent ) {
            deltaX = orgEvent.deltaX;
            if ( deltaY === 0 ) { delta  = deltaX * -1; }
        }

        // No change actually happened, no reason to go any further
        if ( deltaY === 0 && deltaX === 0 ) { return; }

        // Need to convert lines and pages to pixels if we aren't already in pixels
        // There are three delta modes:
        //   * deltaMode 0 is by pixels, nothing to do
        //   * deltaMode 1 is by lines
        //   * deltaMode 2 is by pages
        if ( orgEvent.deltaMode === 1 ) {
            var lineHeight = $.data(this, 'mousewheel-line-height');
            delta  *= lineHeight;
            deltaY *= lineHeight;
            deltaX *= lineHeight;
        } else if ( orgEvent.deltaMode === 2 ) {
            var pageHeight = $.data(this, 'mousewheel-page-height');
            delta  *= pageHeight;
            deltaY *= pageHeight;
            deltaX *= pageHeight;
        }

        // Store lowest absolute delta to normalize the delta values
        absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) );

        if ( !lowestDelta || absDelta < lowestDelta ) {
            lowestDelta = absDelta;

            // Adjust older deltas if necessary
            if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
                lowestDelta /= 40;
            }
        }

        // Adjust older deltas if necessary
        if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
            // Divide all the things by 40!
            delta  /= 40;
            deltaX /= 40;
            deltaY /= 40;
        }

        // Get a whole, normalized value for the deltas
        delta  = Math[ delta  >= 1 ? 'floor' : 'ceil' ](delta  / lowestDelta);
        deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta);
        deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta);

        // Normalise offsetX and offsetY properties
        if ( special.settings.normalizeOffset && this.getBoundingClientRect ) {
            var boundingRect = this.getBoundingClientRect();
            offsetX = event.clientX - boundingRect.left;
            offsetY = event.clientY - boundingRect.top;
        }

        // Add information to the event object
        event.deltaX = deltaX;
        event.deltaY = deltaY;
        event.deltaFactor = lowestDelta;
        event.offsetX = offsetX;
        event.offsetY = offsetY;
        // Go ahead and set deltaMode to 0 since we converted to pixels
        // Although this is a little odd since we overwrite the deltaX/Y
        // properties with normalized deltas.
        event.deltaMode = 0;

        // Add event and delta to the front of the arguments
        args.unshift(event, delta, deltaX, deltaY);

        // Clearout lowestDelta after sometime to better
        // handle multiple device types that give different
        // a different lowestDelta
        // Ex: trackpad = 3 and mouse wheel = 120
        if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
        nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);

        return ($.event.dispatch || $.event.handle).apply(this, args);
    }

    function nullLowestDelta() {
        lowestDelta = null;
    }

    function shouldAdjustOldDeltas(orgEvent, absDelta) {
        // If this is an older event and the delta is divisable by 120,
        // then we are assuming that the browser is treating this as an
        // older mouse wheel event and that we should divide the deltas
        // by 40 to try and get a more usable deltaFactor.
        // Side note, this actually impacts the reported scroll distance
        // in older browsers and can cause scrolling to be slower than native.
        // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
        return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
    }

}));
use_package("de.his.component");

de.his.component.Swipegesture = new function() {
    de.his.modules.ModuleRegistry.registerModule(this).registerAjaxRefreshModule(this);
    this.moduleName = "de.his.component.Swipegesture";
    this.init = function() { this.swipe(); };

	this.swipe = function(e) {
		let touchstartX = 0;
		let touchstartY = 0;
		let touchendX = 0;
		let touchendY = 0;
		let gestureZone = document.querySelectorAll('.menuItem');
		let deleteStatus = false;

		for (let i = 0; i < gestureZone.length; i++) {
						
			gestureZone[i].addEventListener('touchstart', function(event) {
			    touchstartX = event.changedTouches[0].screenX;
			    touchstartY = event.changedTouches[0].screenY;
			}, false);
			
			gestureZone[i].addEventListener('touchend', function(event) {
			    touchendX = event.changedTouches[0].screenX;
			    touchendY = event.changedTouches[0].screenY;
			    handleGesture(this.querySelector('.menuWrap'));
			}, false); 

			gestureZone[i].addEventListener('touchmove', function(event) {
				if( deleteStatus == true ) {
					return false;
				}
				let touchMoveX = event.changedTouches[0].screenX;
				let newPosX = touchstartX - touchMoveX;
				if(newPosX <= 500 && newPosX >= 0) {
					jQuery(this).children('.menuWrap').css({transform: 'translateX('+-newPosX+'px)', opacity: 1-(newPosX/200)});
				} else if ( newPosX <= 0 )  {
					jQuery(this).children('.menuWrap').css({transform: 'translateX(0px)', opacity: 1});
				}
			}, false);

		}
	
		function handleGesture(item) {

		    if (touchendX < touchstartX && deleteStatus == false) {
				if(touchendX - touchstartX <= -100) {
					deleteStatus = true; 
					jQuery(item).css({transform: '', opacity: ''});
					item.classList.add('deleted');
					jQuery(item).parent().animate({opacity: 0}, 1000);
					item.deleteTimer = setTimeout(function(){
						deleteStatus = false;
						item.querySelector('.iconfont-delete').click();
					}, 1000);	
				}
				else {
					jQuery(item).css({transform: '', opacity: ''});
					deleteStatus = false; 
					item.classList.remove('deleted');
				}
		    }
					    
		    if (touchendX > touchstartX || touchendY === touchstartY) {
				deleteStatus = false; 
				jQuery(item).parent().stop().css({opacity: ''});
				jQuery(item).css({transform: '', opacity: ''});
				item.classList.remove('deleted');
				clearTimeout(item.deleteTimer);
		    }
		    
		    /*if (touchendY <= touchstartY) {
		        console.log('Swiped up');
		    }
		    
		    if (touchendY >= touchstartY) {
		        console.log('Swiped down');
		    }
		    
		    if (touchendY === touchstartY) {
		        console.log('Tap');
		    }*/
		}
	}


    this.refresh = function() {
        this.init();
    };
};use_package( "de.his.common" );

de.his.common.mainnavigation = new function() {

    de.his.modules.ModuleRegistry.registerModule( this ).registerAjaxRefreshModule( this );
    this.moduleName = "de.his.common.mainnavigation";
    
    this.init = function() {
		mainnavigation();
    };

	this.refresh = function() {
		if(!jQuery('.js-opennavoverlay').length){
			de.his.common.mainnavigation.init();
		}
    };
    
	/**  
	* Höhe des Headers erst nach window.load berechenbar
	*/
	jQuery(window).on('load', function(){
		jQuery('#hisinoneHeader').addClass('js-fixed').parent().css({paddingTop:jQuery('#hisinoneHeader').outerHeight()});
	});

    var mainnavigation = function() {	
		var position = 0;
		var resizeTimer;
		
		clickEvent = "click";
		/*if($html.hasClass('touch')) {
			clickEvent = 'touchstart';
		}*/
		
		var $header = jQuery('#hisinoneHeader');
		var $navToggle = jQuery('.navbar-toggle');
		var $body = jQuery('body');
		var $html = jQuery('html');
		var $nav = jQuery('.topMenuContainer .nav');
		var $window = jQuery(window);
		var $navLink = jQuery('.topMenuContainer .parentListItem > a');
		var $navContainer = jQuery('.topMenuContainer');
		var $closeBtn = jQuery('.closeButtonNavigationESC');
		
		$window.on('resize', function() {
		  clearTimeout(resizeTimer);
		  resizeTimer = setTimeout(function() {
			
			checkScrollnav();
			
		    if( $navToggle.css('display') == 'none' ) {
				position = 0;
				$nav.css('transform', '');
				jQuery('.js-opennavoverlay').remove();
				$body.removeClass('js-navOpen js-navOpenFooter');
				$nav.find('.js-visible').removeClass('js-visible');
				$nav.find('.js-hidden').removeClass('js-hidden');
				$navContainer.css({minHeight:'', height:'', display:''});
				$header.removeClass('js-fixed').parent().css({paddingTop:''});
			} else {
				$header.addClass('js-fixed').parent().css({paddingTop:$header.outerHeight()});
			}
			if( jQuery('#loginLinkElement').css('display') == 'none' && jQuery('.headerRightTop .loginStartPage').css('display') == 'none' ) {
				jQuery('.headerRightTop .loginStartPage').css({display:''});				
			}
		  }, 250);
		});

		let navigationShown = true;
		let scrollPosition = 0;
		var oldTitle = '';		
		
		function showNavigation() {
		    scrollPosition = window.pageYOffset;
		  	$body.css({top:-scrollPosition + 'px'});
	
			if( $navToggle.parents('#hisinoneFooter').length ) {
				$html.addClass('js-navOpen js-navOpenFooter');
			} else {
				$html.addClass('js-navOpen');	
			}		  	
			jQuery('<div class="js-opennavoverlay" />').appendTo('body');
			this.oldTitle = $navToggle.attr('title');
			var newTitle = $navToggle.data('titletoggle');
			$navToggle.attr('title', newTitle).attr('id', 'mobileOnlyNavBar_open').attr('aria-expanded', 'true');
			$navToggle.data('titletoggle');
			outerClicksCloseMenuHandler();
		}
		
		function removeNavigation() {
			$html.removeClass('js-navOpen js-navOpenFooter');
		  	window.scrollTo(0, scrollPosition);
		    $body.css({top:''});
			jQuery('.js-opennavoverlay').remove();
			$navToggle.attr('title', this.oldTitle).attr('id', 'mobileOnlyNavBar').attr('aria-expanded', 'false');
			position = 0;
			$nav.css('transform', 'translateX(0%)').find('li').removeClass('js-visible js-active js-hidden');
			setTimeout(function(){
				$header.removeClass('js-hide');
				if( jQuery('.scrollWithMe').length || jQuery('[appscrollwithme]').length ) {
					var $scrollWithMe = jQuery('.scrollWithMe, [appscrollwithme]');
					if( $scrollWithMe.hasClass('scrollWithMe-active') ) {
						var headerHeight = $header.outerHeight();
						$scrollWithMe.css({top:headerHeight});			
					}
				}
			});
			
		}
		
		function outerClicksCloseMenuHandler(){
	    	// hide slidedown menues when user clicks somewhere else in the page
			jQuery('.js-opennavoverlay,#hisinoneHeader,#hisinoneFooter').off(clickEvent).on(clickEvent, function (e) {
//				console.log('clicked somewhere..', jQuery(e.target));
				
				if ( jQuery('html').hasClass('js-navOpen') && jQuery(e.target).closest('#topMenuContainerId').length == 0
				    && !jQuery(e.target).hasClass("navbar-toggle")
            		&& !jQuery(e.target).hasClass("burger_navigation")
            		&& jQuery(e.target).is(':visible') ) {
		            		
	            	$navToggle.trigger(clickEvent);
	            	
	            }
	        });
	    }
		
		$navToggle.off(clickEvent).on(clickEvent, function(){
			navInit();
			checkScrollbar();
			var $this = jQuery(this);
			$navContainer.toggle('slide', 200);
			$this.toggleClass('js-open');
			if (navigationShown) {
				showNavigation();
			} else {
				removeNavigation();
			}
			closeNavigationButton();
			navigationShown = !navigationShown;
		});
		
		$navLink.off(clickEvent).on(clickEvent, function(){
			if( $navToggle.css('display') == 'block' ) {
				var $this = jQuery(this);
				$navContainer.find('.js-active').removeClass('js-active');
				$this.closest('li').addClass('js-visible js-active');
				$this.closest('li').parent().children('li:not(.js-visible)').addClass('js-hidden');
				var activeHeight = $this.closest('li').children('ul').height();
				if( jQuery('#searchMenuExtContainer_inNav').css('display') == 'block' ) {
					var mobileNavSearchHeight = jQuery('#searchMenuExtContainer_inNav').outerHeight();
					activeHeight= activeHeight+mobileNavSearchHeight;
				}
				$closeBtn.css('top', activeHeight);
				$navContainer.scrollTop(0);
				position = position-100;
				$nav.css('transform', 'translateX('+position+'%)');
				setTimeout(function(){
					jQuery($this.next('ul').children('.navitem-headline').children()).focus();
				},100);
				return false;
			}
		});
		jQuery('.backButton').off(clickEvent).on(clickEvent, function(){ 
			var $this = jQuery(this);
			$this.closest('.js-visible').parent().children('.js-hidden').removeClass('js-hidden');
			$this.closest('.js-visible').removeClass('js-visible js-active');
			$this.closest('.js-visible').addClass('js-active');
			position = position+100;
			$nav.css('transform', 'translateX('+position+'%)');
			if( $this.closest('.parentListItem').closest('ul').children('.navitem-headline').children().length ) {
				$this.closest('.parentListItem').closest('ul').children('.navitem-headline').children().focus();
				var activeHeight = $this.closest('.js-visible').children('ul').height();
			}
			else {				
				$this.closest('.parentListItem').children('a').focus();
				var activeHeight = $nav.height();
			}
			if( jQuery('#searchMenuExtContainer_inNav').css('display') == 'block' ) {
					var mobileNavSearchHeight = jQuery('#searchMenuExtContainer_inNav').outerHeight();
					activeHeight= activeHeight+mobileNavSearchHeight;
				}
			$closeBtn.css('top', activeHeight);
			return false;	
		});
//		$body.off(clickEvent).on(clickEvent, '.js-opennavoverlay', function(){
//			$navToggle.trigger(clickEvent);
//		});
						
		function navInit() {
			$navContainer.css({minHeight: '', height: ''});
			var headerHeight = $header.outerHeight();
			var footerHeight = jQuery('#hisinoneFooter').outerHeight();
			var winHeight = window.innerHeight;
			
			if( $navToggle.parents('#hisinoneFooter').length ) {
				var newNavHeight = winHeight - headerHeight-footerHeight;	
			} else {
				var newNavHeight = winHeight - headerHeight;
			}			
			$navContainer.css({height: newNavHeight + 'px', top:headerHeight});
		}
		function checkScrollbar(){
		    var $body = jQuery("body");
		    var previousWidth = null;
		    var currentWidth = $body.width();
		    if (currentWidth != previousWidth) {
		        previousWidth = currentWidth;        
		        $body.css("overflow", "hidden");
		        var scrollBarWidth = $body.width() - currentWidth;
		        $body.css("overflow", "auto");
		        $body.css("padding-right", scrollBarWidth + "px");     
				jQuery('#logoAndServicesHeader').css("padding-right", scrollBarWidth + "px");
		        $body.css("overflow", "");
		    }
		
		};
		
		var old_scroll_top = 0, delta = 5;
		$window.on('scroll', function(e){
			
			var current_scroll_top = jQuery(document).scrollTop();
			if( current_scroll_top == 0 ) {
				$header.removeClass('js-hide');
			}
			if(Math.abs(old_scroll_top - current_scroll_top) <= delta) {
	        	return;
			}
			if( $navToggle.css('display') == 'block' ) {
				var scroll_delta = current_scroll_top - old_scroll_top;
				if( !$html.hasClass('js-navOpen') ){
					if( scroll_delta <=0 ){						
						$header.removeClass('js-hide');
						if( jQuery('.scrollWithMe').length || jQuery('[appscrollwithme]').length ) {
							var $scrollWithMe = jQuery('.scrollWithMe, [appscrollwithme]');
							if( $scrollWithMe.hasClass('scrollWithMe-active') ) {
								var headerHeight = $header.outerHeight();
								$scrollWithMe.css({top:headerHeight});
							} else {
								$scrollWithMe.css({top:''});
							}
						}						
					}
					else { 
						if( navigator.webdriver != true && current_scroll_top > 100  && !$header.find('.widgetPanelDiv').length && $header.find('.popoverContainer').css('display') != 'block' ) {
							$header.addClass('js-hide');
						}
						if( jQuery('.scrollWithMe-active').length ) {
							if( navigator.webdriver == true ) {
								var headerHeight = $header.outerHeight();
								jQuery('.scrollWithMe-active').css({top:headerHeight});
							} else {
								jQuery('.scrollWithMe-active').css({top:''});
							}
						}
					}					
				}
								
				old_scroll_top = current_scroll_top;
			}
		});	
		
		window.addEventListener("orientationchange", function(){
			if($navToggle.hasClass('js-open')) {
				setTimeout(function(){
					navInit();
				}, 100);
			}
		});
		
		
		// LOGIN TOGGLE HEADER
		jQuery('.loginToggle').off(clickEvent).on(clickEvent, function(e){
			e.preventDefault();
			jQuery('.loginStartPage').slideToggle();
		});
				
		function checkScrollnav() {
			if( jQuery('.navband').length != 0 ) {
				var initContainerWidth = jQuery('.navband')[0].scrollWidth;
				var initWrapWidth = jQuery('.navbandWrap').outerWidth()+10;
				if( initContainerWidth < initWrapWidth ) {
					jQuery('.navbandArrow').hide();
				} else {
					jQuery('.navbandRight').show();
				}
			}
		}checkScrollnav();
		num = 1;
		jQuery('.navbandArrow').off('mouseenter').on('mouseenter', function(){
			var $this = jQuery(this);
			incInterval= setInterval(function(){
				if( $this.hasClass('navbandRight') ) {
    				var pos = jQuery('.navband').scrollLeft() + num;
				} else {
					var pos = jQuery('.navband').scrollLeft() - num;
				}
    			jQuery('.navband').scrollLeft(pos);
				var curPos = jQuery('.navband').scrollLeft();
				var containerWidth = jQuery('.navband')[0].scrollWidth;
				var wrapWidth = jQuery('.navbandWrap').outerWidth();
				var scrollWidth = containerWidth - wrapWidth;
				if( curPos > 0 ) {
					jQuery('.navbandLeft').show();
				} 
				if( curPos == 0 ) {
					jQuery('.navbandLeft').hide();
				} 
				if( curPos+5 >= scrollWidth ) {
					jQuery('.navbandRight').hide();
				}
				if( curPos+5 < scrollWidth ) {
					jQuery('.navbandRight').show();
				}
		      	num++;	
			},50);
		}).mouseleave( function(){ 
			clearInterval(incInterval); 
		});
		
		function closeNavigationButton(){
			if( navigationShown ) {								
				var activeHeight = $nav.height();
				if( jQuery('#searchMenuExtContainer_inNav').css('display') == 'block' ) {
					var mobileNavSearchHeight = jQuery('#searchMenuExtContainer_inNav').outerHeight();
					activeHeight= activeHeight+mobileNavSearchHeight;
				}
				$closeBtn.css('top', activeHeight);
				$closeBtn.addClass('simple-close-button-behavior');
			} else {
				$closeBtn.removeClass('simple-close-button-behavior');
				$navToggle.focus();
			}
			$closeBtn.off('click').on('click', function(e){
				e.preventDefault();
				$navToggle.trigger('click');
			});
		}
		
		function navigationLoopEvent(){
			$closeBtn.off('keydown').on('keydown', function(e) {
				if (e.key === 'Tab' || e.keyCode === 9) {
					if( !$navContainer.find('.topMenuList').hasClass('js-hidden') ) {					
						var $firstVisibleLink = $navContainer.find('.topMenuList a').first();
					} else {
						var $firstVisibleLink = $navContainer.find('li.js-active').children('ul').find('a').first();
					}
					$firstVisibleLink.focus();
					e.preventDefault();
				}
			});
		}navigationLoopEvent();
		
	}
	

};



/*****************************************************************************/
// Provides a jQuery plugin for a simple sticky component.
// The component scolls with the window until a given margin to the op is reached, then it is fixed.
// Author: Dennis Hörsch
//
// The component must have an Id!
// OPTIONS (required):
//  - start: The distance from the top the effect should start
//  - margin: The distance to the top in case the effect is 'on'
/** *************************************************************************** */
(function(jQuery) {
	var stickyScrollables = [];
    
    jQuery.fn.stickyScrollable = function(options) {
        var component = jQuery(this),

            componentId = component.attr('id'),
        
            // Store initial values
            top = component.css('top'),
            left = component.css('left'),
            right = component.css('right'),

            scrollingBase = jQuery(options.scrollingBase ? options.scrollingBase : window),

            componentScrollingCss = {
	            position : 'absolute',
	            top : options.start,
	            left : left,
	            right : right
            },
            componentFixedCss = {
	            position : 'fixed',
	            top : options.margin,
	            left : left,
	            right : right
           	},
           	
            scrollingHandler = function() {
                var scroll = scrollingBase.scrollTop() + options.margin;

                // Wenn das Scrolling kleiner als die gewünschte Abstand zum top, dann ist die component fixiert.
                // Ansonsten ist sie absolut positioniert, so dass sie mitscrollt.
                if (scroll < options.start) {
                    component.css(componentScrollingCss);
                } else {
                    component.css(componentFixedCss);
                }
            };

        unStickyScrollable(component, componentId, scrollingBase);
            
        // First call to initialize position
        scrollingHandler();

        scrollingBase.scroll(scrollingHandler);

        stickyScrollables[componentId] = {
        	handler: scrollingHandler
        };
        
        return component;
    };

    var unStickyScrollable = function(component, componentId, scrollingBase) {
        var stickyScrollableData = stickyScrollables[componentId]; 
        
        if (stickyScrollableData) {
        	scrollingBase.unbind('scroll', stickyScrollableData.handler);
	        delete stickyScrollables[componentId];
    	}
    };
}(jQuery));/*****************************************************************************/
// Provides a jQuery plugin to 'auto close' a component.
// After a timeout the component fades out. If the mouse enters the component the fadings stops and the component is shown. On leaving the timeout starts again.
// Author: Dennis Hörsch
//
// The component must have an Id!
// OPTIONS (optiona):
//  - timeout: default is 4000 ms
//  - fadeOutTime: default is 2500 ms
//  - fadeInTime: default is 500 ms
//  - callbackOnHidden: no default
/** *************************************************************************** */
(function(jQuery) {
    var defaultOptions = {
            timeout:          4000,
            fadeOutTime:      2500,
            fadeInTime:       500,
            callbackOnHidden: undefined
    };

    jQuery.fn.autoClosing = function(params) {
    	if(jQuery('.messages-infobox-behavior.occassionalUser').length == 0){
	        var component = jQuery(this),
	            options = jQuery.extend({}, defaultOptions, params),
	
	            createTimeout = function() {
	                return setTimeout(function() {
	//                    component.fadeOut(options.fadeOutTime, fadeOutComplete);
	                    component.css({
	                    	marginRight: "-300px",
	                    	opacity: 0,
	                    	transition: "all 1s ease-in"
	                    }).addClass('hideWhenClosed');
	                    setTimeout(fadeOutComplete, 1000);
	                }, options.timeout)
	            },
	            
	            fadeOutComplete = function() {
	                component.unbind('mouseenter', mouseEnterHandler);
	                component.unbind('mouseleave', mouseLeaveHandler);
	            	options.callbackOnHidden();
	            },
	            resetAutoClosing = function() {
	                clearTimeout(autoClosingHandle);
	                component.unbind('mouseenter', mouseEnterHandler);
	                component.unbind('mouseleave', mouseLeaveHandler);  
	                
	                component.data('__autoClosing', null);
	                component.data('__resetAutoClosing', null);
	            },
	            
	            mouseEnterHandler = function() {
	                clearTimeout(autoClosingHandle);
	                component.stop().show().animate({'opacity': '1.0'}, options.fadeInTime);
	            },
	            mouseLeaveHandler = function() {
	                autoClosingHandle = createTimeout();
	            },
	            autoClosingHandle = createTimeout();
	            
			options.timeout /= 2.0;
			options.fadeOutTime /= 2.0;    
	
	        component.mouseenter(mouseEnterHandler);
	        component.mouseleave(mouseLeaveHandler);
	
	        component.data('__autoClosing', true);
	        component.data('__resetAutoClosing', resetAutoClosing);
	        
	        return component;
    	}
    };

    jQuery.fn.unAutoClosing = function() {
        var component = jQuery(this);
        if (component.data('__autoClosing')) {
        	component.data('__resetAutoClosing')();
        }
    	return component;
    };
}(jQuery));use_package("de.his.ajax");

/**
 * Re-initializes some modules after an AJAX request.
 * Usage: f:ajax onevent="de.his.ajax.Refresher.onEvent" onerror="de.his.ajax.Refresher.onError"
 * Is added automatically to all ajax-Behaviors, manually created or automatically, i.e. for refresh buttons.
 *
 * Modules to be refreshed need a method 'refresh'.
 *
 */
de.his.ajax.Refresher = new function() {

    this.onEvent = function(data) {   	
        switch (data.status) {
            /* status (JSF 2.1 spec, 14.4.1):
             * begin     Occurs immediately before the request is sent.
             * complete  Occurs immediately after the request has completed.
             *           For successful requests, this is immediately before javax.faces.response is called.
             *           For unsuccessful requests, this is immediately before the error handling callback is invoked.
             * success   Occurs immediately after jsf.ajax.response has completed.
             */
            case "begin":
            	console.log("[.ajax] begin: %s", data.source.id);            	
                ajaxBegin();
                break;
            case "complete":
               	console.log("[.ajax] complete: %s", data.source.id);
            	de.his.modules.eventRegistry.fireEvent("refresherComplete");
            	// hiermit werden fertige AJAX Calls global "sichtbar", sodass auf dieses Event reagiert werden kann
            	// Dies ist beispielsweise beim messen der clientseitigen Performanz notwendig.
            	jQuery(document).trigger('ajaxComplete');
                break;
            case "success":
            	if (isAjaxRedirect(data)) {
                	console.log("[.ajax] success redirect: %s", data.source.id);
            		break;
            	}
            	
            	console.log("[.ajax] success: %s", data.source.id);
	            ajaxEnd(data);
	            de.his.modules.eventRegistry.fireEvent("refresherSuccess");        		
               	break;
        }
    };

    var ajaxBegin = function() {
		de.his.modules.ModuleRegistry.indicateAjaxRequestStart();
    };

    var ajaxEnd = function(data) {
    	if (data.responseCode == 403) { // Access denied: force redirect, as a result the access-denied page is shown
    		window.location = window.location;
        }
        de.his.modules.ModuleRegistry.refreshAll(data);
    };

    this.onError = function(data) {
        /* status (JSF 2.1 spec, 14.4.2):
         * httpError     request status==null or request.status==undefined or request.status<200 or request.status >=300
         * serverError   The Ajax response contains an “error” element.
         * malformedXML  The Ajax response does not follow the proper format. See Section 1.4 "XML Schema Definition for Partial Responses"
         * emptyResponse There was no Ajax response from the server.
         */

        // TODO: Refresh, ansonsten ist die Oberfläche / Serverzustand evtl. inkonsistent.
        //
        // Die JavaScript-Fehlermeldung wird per AJAX verschickt und serverseitig protokolliert.
        // Weil die Fehlermeldung sehr lang werden kann (z. B. kann ajax.responseText enthalten
        // sein), muss POST verwendet werden.
        
        
        // Fehler, die beim Verlassen der Seite auftreten unterdrücken
		if (isPageUnloading == true) {
			return;
		}
	
    	console.log("[.ajax] error: %s", data.source.id);
    	var url = de.his.common.ContextInformation.get('context-path') + '/pages/cs/sys/error/error.faces?code=500&ajax=true';
        var form = new FormData();
        form.append('ajaxerror', JSON.stringify(data));
        jQuery.ajax({
            type : "POST",
            url : url,
            cache : false,
            contentType : false,
            processData : false,
            data : form,
            async : true,
            success : function(html) {
        	// alert(JSON.stringify(data));
            }
        });       
        disableWaitingBahaviour();
        showErrorToUser(data);
    };
    
    this.onErrorIgnore = function(data) {
    	console.log("[.ajax] errorignore: %s", data.source.id);    
    	disableWaitingBahaviour();
    };

    this.wrapOnEvent = function(onevent) {
        return wrapInternal(this.onEvent, onevent);
    };

    this.wrapOnError = function(onevent) {
        return wrapInternal(this.onError, onevent);
    };
    
    var disableWaitingBahaviour = function(){
    	de.his.modules.Waiting.resetWaitingBehaviour();
    }
    
    var showErrorToUser = function(data){
    	var errorMessage = getErrorText(data.status);
    	
    	if(data.status === "serverError"){
    		errorMessage += data.serverErrorMessage + " " + data.serverErrorMessage;
    	}
    	
    	de.his.component.MessagesInfobox.showMessagesInfobox(errorMessage,'error');
    }

    var wrapInternal = function(handler, onevent) {
        return function(data) {
            onevent(data);
            handler(data);
        };
    };
    
    
    var isAjaxRedirect = function(data) {
    	return (data.responseCode == 200) && (data.responseText.contains("<redirect url="));
    }
    
    var errorTexts = {
        de:{
            _title: "AJAX-Fehler:",
            malformedXML: "Das zurückgelieferte XML-Response-Objekt ist fehlerhaft aufgebaut.",
            serverError: "Auf dem Server ist ein Fehler aufgetreten.",
            clientError: "Das Javascript ist fehlerhaft.",
            httpError: "Ein unerwarteter Netzwerkfehler ist aufgetreten.",
            emptyResponse: "Die Antwort des Servers war leer.",
            _error: "Der Server antwortet nicht.",
            offline: "<div class='offlineContainer'>Ihre Internetverbindung ist unterbrochen, die Anwendung kann möglicherweise nicht vollständig genutzt werden.</div>"
        },
        en: {
            _title: "AJAX-Error:",
            malformedXML: "XML response is malformed.",
            serverError: "Server returned an error.",
            clientError: "The Javascript has errors.",
            httpError: "An unexpected network failure occured.",
            emptyResponse: "Server response was empty.",
            _error: "The Server does not answer requests.",
            offline: "<div class='offlineContainer'>Your internet connection seems to be down, this application may not respond properly if no connection is established.</div>"
        }
    };
    
    var getErrorText = function(status){
    	var lang = de.his.common.LanguageHelper.currentLanguage();
    	
    	if( !errorTexts[lang] ){
    	    //default language
    	    lang = "de";
    	}
    	
    	return (errorTexts[lang][status] || errorTexts[lang]._error);
    };

    window.addEventListener("offline", function(e) {
            alert( getErrorText( "offline" ) );
    }, false);
};

/**
 * Used i.e. in HIS_DEVELOPMENT-Modus to show a detailed error message.
 * @param data
 */
de.his.ajax.Helper = new function() {
    this.callHandlerIfPhase = function(data, phase, handler, scope) {
        console.log("AJAX status: " + data.status);
        if (data.status === phase) {
        	if(scope){
        		handler.apply(scope, data);
        	}else{
        		handler(data);	
        	}
        }
    };

    this.debugAjaxRequest = function(data) {
        if (data.responseCode == 403) { // Access denied: Handled in refresh above
            return;
        }
        var debugText = "";
        debugText += "<b>source.id:</b> " + data.source.id + "<br/>";
        debugText += "<b>responseCode:</b> " + data.responseCode + "<br/>";
        debugText += "<b>status:</b> " + data.status + "<br/>";
        debugText += "<b>serverErrorName:</b> " + data.serverErrorName + "<br/>";
        debugText += "<b>serverErrorMessage:</b> " + data.serverErrorMessage + "<br/>";

        debugText += "<b>responseText:</b><br/>" + data.responseText + "<br/>";
        
        alert("<h1>AJAX Error occured</h1>","Server is in HIS_DEVELOPMENT Mode and AJAX Error occured.<br/>You can ignore this message if you are not developing new AJAX features and just clicked any navigation link.<br/><br/>Here is your AJAX Error object:<br/><br/> "+debugText);
    };
};


/*
Die Möglichkeit schaffen, Verarbeitung zu unterdrücken, wenn die Seite gerade verlassen wird.
*/

var isPageUnloading = false;

jQuery(window).on("beforeunload",
	function() {
		isPageUnloading = true;
	}
);

use_package("de.his.ajax");

/**
 * JS-Funktionen zur Ajax-Funktion: Header einklappen
 */
de.his.ajax.ToggleHeader = new function() {
	
	var newValue, oldValue;
	
	//Wenn das togglen des Header abgeschlossen ist
    this.processEvent = function(data) {
    	
    	if (data.status == "success") {
    		jQuery('#wrapper_no_background').toggleClass('reducedHeader');
    		
    		//This ugly hack is required as styleClass is not always refreshed when using an #{} EL to define the value
    		//also: when it does change the value using the #{} EL it only does it once!
    		//TODO: is this needed in versions > JSF 2.0
    		var btn = jQuery('li.plusIconElement input.toggleIcon');
    		if(btn.length > 0 ){
    			if(!newValue && !oldValue){
    				if(btn.hasClass("minusIcon")){
    					oldValue = "minusIcon";
        				newValue = "plusIcon";
        				btn.removeClass(oldValue);
        				btn.addClass(newValue);
        			}else if(btn.hasClass("plusIcon")){
        				oldValue = "plusIcon";
        				newValue = "minusIcon";
        				btn.removeClass(oldValue);
        				btn.addClass(newValue);
        			}
    			}else{
    				btn.removeClass(newValue);
    				btn.addClass(oldValue);
    				var a = oldValue;
    				oldValue = newValue;
    				newValue = a;
    			}
    			
    		}
			
			setTimeout(function(){
				jQuery('#hisinoneHeader').parent().css({paddingTop:jQuery('#hisinoneHeader').outerHeight()});
			});			
			
    	}
    	try {
    		var fix = jQuery(".content_portal_hisinone_fixed");
    		if (fix && fix.length > 0) {
    			resizeHeader();
    		}
    	} catch (e) {
    		//Nur bei fixem Layout vorhanden
    	}
    };
};
use_package("de.his.common");

de.his.common.embedded = new function() {
	de.his.modules.ModuleRegistry.registerModule(this)
	.registerAjaxRefreshModule(this);
	this.moduleName = "de.his.common.embedded";
	
	this.init = function() {
		this.setCssClassIfHisinoneIsEmbedded();
	};
	
	this.refresh = function() {
		this.setCssClassIfHisinoneIsEmbedded();
	};
	
	/**
	 * Setzt eine CSS-Klasse, wenn HISinOne in einem IFrame läuft
	 */
	this.setCssClassIfHisinoneIsEmbedded = function() {
		var body = jQuery("body");
	    try {
	        if (window.self !== window.top) {
	        	body.addClass("embedded");
	        }
	    } catch (e) {
	    	//Auch im Fehlerfall läuft HISinOne in einem IFrame
	    	body.addClass("embedded");
	    }
	};
};use_package("de.his.common");

de.his.common.embedded = new function() {
	de.his.modules.ModuleRegistry.registerModule(this)
	.registerAjaxRefreshModule(this);
	this.moduleName = "de.his.common.linkAsOverlay";
	
	this.init = function() {
		this.setLinkTargetAsOverlayOnClick();
	};
	
	this.refresh = function() {
		this.setLinkTargetAsOverlayOnClick();
	};
	
	/**
	 * Setzt eine CSS-Klasse, wenn HISinOne in einem IFrame lÃ¤uft
	 */
	this.setLinkTargetAsOverlayOnClick = function() {
		 try {
			jQuery(document).ready(function () {
				jQuery('a.targetAsOverlay').click(function(){
					console.log("linkAsOverlay: Klick");
					var iframeSrc = jQuery(this).attr('href');
					var iframeTitle = jQuery(this).text();
					console.log("iframeSrc: " + iframeSrc);
//				    console.log(jQuery('#logoForm\:linkTargetAsOverlayPlaceholder\:overlayShowButton'));
//				    console.log("#logoForm:linkTargetAsOverlayPlaceholder:overlayShowButton");
					console.log("iframeTitle: " + iframeTitle);
					
					jQuery('#linkTargetAsOverlayForm').append('<input type="hidden" id="overlayTitle" name="overlayTitle" value="' + iframeTitle + '" />');
					
					jQuery('#linkTargetAsOverlaySrc').attr('value',iframeSrc)
					jQuery('#linkTargetAsOverlayForm').show();
					jQuery('#linkTargetAsOverlayForm\\:linkTargetAsOverlayPlaceholder\\:overlayShowButton').hide();
				    jQuery('#linkTargetAsOverlayForm\\:linkTargetAsOverlayPlaceholder\\:overlayShowButton').click();
				    return false;
				    //  jQuery('#myiFrame iframe').attr('src',iframeSrc);
				    
//				    jQuery('#myiFrame').fadeOut(1000,function(){
//				    	jQuery('#myiFrame iframe').attr('src',iframeSrc);
//				    	jQuery('#myiFrame').fadeIn(1000);
//				    });
				    //return false;
				});
			});
			
			//Wurde das Overlay aktiviert?
			if (jQuery('#iframePlaceholder').length) {
				//Nur weiter machen, wenn es noch kein Iframe im Overlay gibt
				if (!jQuery('#linkTargetAsOverlayPlaceholderIframe').length) {
					//Title setzen
					var overlayTitle = jQuery('#overlayTitle').attr('value');
					console.log("overlayTitle: " + overlayTitle);
					jQuery('#linkTargetAsOverlayForm\\:linkTargetAsOverlayPlaceholder\\:overlayPlaceholder .box_title h2').text(overlayTitle);
					
					//Ziel-URL extrahieren
					var iframeSrc = jQuery('#linkTargetAsOverlaySrc').attr('value');
					console.log("linkTargetAsOverlaySrc: " + iframeSrc);
					
					//Höhe für Inhalt holen
					var overlayContentHeight = Math.floor(window.innerHeight * 0.80) - 181;
					console.log("overlayContentHeight: " + overlayContentHeight);
					
					//IFrame hinzufügen
					var iframePlaceholder = jQuery('#iframePlaceholder');
					iframePlaceholder.append('<iframe style="border:0px;width:100%;height:'+overlayContentHeight+'px" class="frame" id="linkTargetAsOverlayPlaceholderIframe" src="#" title="Overlay">Iframe</iframe>');
					
					//URL setzten
					jQuery('iframe#linkTargetAsOverlayPlaceholderIframe').attr('src', iframeSrc);
					
					//Laden
					jQuery('iframe#linkTargetAsOverlayPlaceholderIframe').ready(function() {
				    	console.log("resizeIt");
				    	//resizeIt(jQuery("#linkTargetAsOverlayPlaceholderIframe"));
				    });
				} 
			}
	   
	    } catch (e) {
	    	console.log(e)
	    }
	};
};/**
 * Author: Evelyn Elsner
 * 
 */
de.his.modules.Menutabs = new function() {
    de.his.modules.ModuleRegistry
		.registerModule(this)
		.registerAjaxRefreshModule(this);
    
    this.moduleName = "de.his.modules.Menutabs";

    this.init = function() {
		this.activeTabHandling();
		jQuery('.tabButton.active').css('cursor','pointer');
    };
    
    this.refresh = function() {	
		this.activeTabHandling();
    };
	
	this.activeTabHandling = function(){
		if(!jQuery('.responsive_tab.mikronavi_submit > ul > li:first-child button.tabButton').hasClass('active') && jQuery(window).width() <= 768 || window.localStorage.getItem("firstLinkActivationCount") == 1){
			window.localStorage.setItem("firstLinkActivationCount", 0);
			jQuery('.responsive_tab.mikronavi_submit + div').css('display', 'block');
			jQuery('.responsive_tab.mikronavi_submit').css('display', 'none');
			
			jQuery('.backButtonTabSmallView').css('display', 'inline');
			//jQuery('button.backButtonResponsive:not(.backButtonTabSmallView)').attr('onclick', "return false");
			
			if(jQuery('.backButtonTabSmallView').is(":visible")){
				jQuery('.backButtonResponsive.submit.immediate').css('display', 'none');
			} 
		}
		if(window.localStorage.getItem("firstLinkActivationCount") == 0 && jQuery(window).width() > 768){
			jQuery('.responsive_tab.mikronavi_submit').css('display', 'block');
			jQuery('.backButtonTabSmallView').css('display', 'none');
			jQuery('.backButtonResponsive.submit.immediate').css('display', 'inline-block');
		}
		
	}
	
	// Klick auf den ersten Tab, der standardmäßig aktiv ist -> Nach Request soll noch bekannt sein, dass dieser geklickt wurde, deshalb Klick im Storage speichern
	jQuery('.responsive_tab.mikronavi_submit > ul > li:first-child button.tabButton').on("click", function(){
		var firstLinkActivationCount = parseInt(window.localStorage.getItem("firstLinkActivationCount")) + 1;
	  	window.localStorage.setItem("firstLinkActivationCount", firstLinkActivationCount);
	});
		
	this.disableBackButton = function(){
		if(jQuery('.responsive_tab.mikronavi_submit').is(":visible")){
			jQuery('.backButtonTabSmallView').css('display', 'none');
		}
	}
};

jQuery(window).resize(function() {
	if(jQuery(window).width() > 768){
		jQuery('.responsive_tab.mikronavi_submit + div').css('display', 'block');
		jQuery('.responsive_tab.mikronavi_submit').css('display', 'block');
		
		//jQuery('.backButtonTabSmallView').css('display', 'none');
	}
	else if(jQuery(window).width() <= 768 && jQuery('.responsive_tab.mikronavi_submit').css('display') == 'none'){
		jQuery('.responsive_tab.mikronavi_submit + div').css('display', 'block');
	}
	else{
		jQuery('.responsive_tab.mikronavi_submit + div').css('display', 'none');
	}
});/**
 * Author: Evelyn Elsner
 * 
 */
de.his.modules.LoginPassword = new function() {
    de.his.modules.ModuleRegistry.registerModule(this)
		.registerAjaxRefreshModule(this);
    
    this.moduleName = "de.his.modules.LoginPassword";

	var showPasswordBtn = "";
	var showPasswordBtnImg = "";
	var lang = "de";
	var newTitleDe = "Passwort verbergen";	
	var newTitleEn = "Hide password"
	var oldTitle = "";
	
	// Login-Portlet
	var pShowPasswordBtn = "";
	var pShowPasswordBtnImg = "";
	var pNewTitleDe = "Passwort verbergen";	
	var pNewTitleEn = "Hide password"
	var pOldTitle = "";
	
	// Access Denied Form
	var dShowPasswordBtn = "";
	var dShowPasswordBtnImg = "";
	var dNewTitleDe = "Passwort verbergen";	
	var dNewTitleEn = "Hide password"
	var dOldTitle = "";
	
	// Self Registration first Password
	var s1ShowPasswordBtn = "";
	var s1ShowPasswordBtnImg = "";
	var s1NewTitleDe = "Passwort verbergen";	
	var s1NewTitleEn = "Hide password"
	var s1OldTitle = "";
	
	// Self Registration second/repeated Password
	var s2ShowPasswordBtn = "";
	var s2ShowPasswordBtnImg = "";
	var s2NewTitleDe = "Passwort verbergen";	
	var s2NewTitleEn = "Hide password"
	var s2OldTitle = "";
	
	
    this.init = function() {
		showPasswordBtn = jQuery('button[id$="showPassword"]');
		showPasswordBtnImg = jQuery('button[id$="showPassword"] > img');
		oldTitle = jQuery('button[id$="showPassword"]').attr("title");
		
		pShowPasswordBtn = jQuery('button[id$="showPasswordPortlet"]');
		pShowPasswordBtnImg = jQuery('button[id$="showPasswordPortlet"] > img');
		pOldTitle = jQuery('button[id$="showPasswordPortlet"]').attr("title");
		
		dShowPasswordBtn = jQuery('button[id$="showPasswordAccessDenied"]');
		dShowPasswordBtnImg = jQuery('button[id$="showPasswordAccessDenied"] > img');
		dOldTitle = jQuery('button[id$="showPasswordAccessDenied"]').attr("title");
		
		s1ShowPasswordBtn = jQuery('button[id$="showPassword1SelfRegistration"]');
		s1ShowPasswordBtnImg = jQuery('button[id$="showPassword1SelfRegistration"] > img');
		s1OldTitle = jQuery('button[id$="showPassword1SelfRegistration"]').attr("title");
		
		s2ShowPasswordBtn = jQuery('button[id$="showPassword2SelfRegistration"]');
		s2ShowPasswordBtnImg = jQuery('button[id$="showPassword2SelfRegistration"] > img');
		s2OldTitle = jQuery('button[id$="showPassword2SelfRegistration"]').attr("title");
		
		if(jQuery('select[id$=langselectbox]').attr("class") === "langSelector language_en"){
			lang = "en";
		}
    };

    this.refresh = function() {
        this.init();
    };
  		
	function getPassword(passwordId){
		var password = document.querySelector(passwordId);
		return password;
	}
	
	// toggle the type attribute
	function setType(password){
		var type = password.getAttribute("type") === "password" ? "text" : "password";
		password.setAttribute('type', type);
		return type;
	}
	
	// toggle title and alt attributes
	function setBtnImgAttributes(button, buttonImg, titleDe, titleEn){
		if(lang === "de"){
			button.attr("title", titleDe);
			buttonImg.attr("alt", titleDe);
		}
		else if(lang === "en"){
			button.attr("title", titleEn);
			buttonImg.attr("alt", titleEn);
		}
	}
	
	function setOldAttributes(button, buttonImg, oldAttribute){
		button.attr("title", oldAttribute);
		buttonImg.attr("alt", oldAttribute);
		//this.classList.toggle('iconfont-eye_blocked'); --> TODO: Iconfont iconfont-eye_blocked in HISinOne einbauen und image damit ersetzen
		buttonImg.attr("src", "/HISinOne/images/icons/eye.svg");
	}
	
	jQuery('button[id$="showPassword"]').on("click", function(){
		var password = getPassword('#fdsa');
	  	var type = setType(password);

		if(type === "text"){
			showPasswordBtnImg.attr("src", "/HISinOne/images/icons/eye_blocked.svg");
			setBtnImgAttributes(showPasswordBtn, showPasswordBtnImg, newTitleDe, newTitleEn);
		}
		else{
			setOldAttributes(showPasswordBtn, showPasswordBtnImg, oldTitle);
		}
	});
	
	// Eye in Login-Portlet (mobile-login-form.xhtml)
	jQuery('button[id$="showPasswordPortlet"]').on("click", function(){
		var password = getPassword('input[id$="mobileLoginSubForm:fdsa"]');
		var type = setType(password);

		if(type === "text"){
			pShowPasswordBtnImg.attr("src", "/HISinOne/images/icons/eye_blocked.svg");
			setBtnImgAttributes(pShowPasswordBtn, pShowPasswordBtnImg, pNewTitleDe, pNewTitleEn);
		}
		else{
			setOldAttributes(pShowPasswordBtn, pShowPasswordBtnImg, pOldTitle);
		}
	});
	
	// Eye in Access Denied (login-form.xhtml)
	jQuery('button[id$="showPasswordAccessDenied"]').on("click", function(){
		var password = getPassword('#accessDeniedForm > div > div > input[id$="fdsa"]');
		var type = setType(password);

		if(type === "text"){
			dShowPasswordBtnImg.attr("src", "/HISinOne/images/icons/eye_blocked.svg");
			setBtnImgAttributes(dShowPasswordBtn, dShowPasswordBtnImg, dNewTitleDe, dNewTitleEn);		}
		else{
			setOldAttributes(dShowPasswordBtn, dShowPasswordBtnImg, dOldTitle);
		}
	});
	
	// Eye in self Registration Form (selfRegistrationForm.xhtml)
	jQuery('button[id$="showPassword1SelfRegistration"]').on("click", function(){
		var password = getPassword('#selbstregistrierung > div > div > div > fieldset > div > div > input[id$="passwort1"]');
		var type = setType(password);

		if(type === "text"){
			s1ShowPasswordBtnImg.attr("src", "/HISinOne/images/icons/eye_blocked.svg");
			setBtnImgAttributes(s1ShowPasswordBtn, s1ShowPasswordBtnImg, s1NewTitleDe, s1NewTitleEn);		}
		else{
			setOldAttributes(s1ShowPasswordBtn, s1ShowPasswordBtnImg, s1OldTitle);
		}
	});
	
	// Second eye in self Registration Form (selfRegistrationForm.xhtml)
	jQuery('button[id$="showPassword2SelfRegistration"]').on("click", function(){
		var password = getPassword('#selbstregistrierung > div > div > div > fieldset > div > div > input[id$="passwort2"]');
		var type = setType(password);

		if(type === "text"){
			s2ShowPasswordBtnImg.attr("src", "/HISinOne/images/icons/eye_blocked.svg");
			setBtnImgAttributes(s2ShowPasswordBtn, s2ShowPasswordBtnImg, s2NewTitleDe, s2NewTitleEn);		}
		else{
			setOldAttributes(s2ShowPasswordBtn, s2ShowPasswordBtnImg, s2OldTitle);
		}
	});
};window.org=window.org||{};org.apache=org.apache||{};org.apache.myfaces=org.apache.myfaces||{};org.apache.myfaces.dateformat=org.apache.myfaces.dateformat||{};if(!org.apache.myfaces.dateformat.DateFormatSymbols){org.apache.myfaces.dateformat.DateFormatSymbols=function(){this.eras=new Array("BC","AD");this.months=new Array("January","February","March","April","May","June","July","August","September","October","November","December","Undecimber");this.shortMonths=new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","Und");this.weekdays=new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday");this.shortWeekdays=new Array("Sun","Mon","Tue","Wed","Thu","Fri","Sat");this.ampms=new Array("AM","PM");this.zoneStrings=new Array(new Array(0,"long-name","short-name"));var A=new Date();A.setYear(A.getYear()-80);this.twoDigitYearStart=A;};org.apache.myfaces.dateformat.ParserContext=function(A){this.newIndex=0;this.invalid=false;this.firstDayOfWeek=A;this.ambigousYear=false;this.ambigousWeekYear=false;this.year=0;this.month=0;this.day=1;this.dayOfWeek=0;this.hour=0;this.hourAmpm;this.min=0;this.sec=0;this.ampm=0;this.weekYear=0;this.weekOfWeekYear=0;};org.apache.myfaces.dateformat.WeekDate=function(B,A){this.year=B;this.week=A;};org.apache.myfaces.dateformat.StringBuffer=function(A){if(A==null){this.str="";}else{this.str=A;}var B=org.apache.myfaces.dateformat.StringBuffer.prototype;B.append=function(C){this.str=this.str+C;};B.toString=function(){return this.str;};};org.apache.myfaces.dateformat.SimpleDateFormatter=function(C,B,A){this._construct(C,B,A);};var proto=org.apache.myfaces.dateformat.SimpleDateFormatter.prototype;proto.MSECS_PER_SEC=1000;proto.MSECS_PER_MIN=60*proto.MSECS_PER_SEC;proto.MSECS_PER_HOUR=60*proto.MSECS_PER_MIN;proto.MSECS_PER_DAY=24*proto.MSECS_PER_HOUR;proto.MSECS_PER_WEEK=7*proto.MSECS_PER_DAY;proto.MONTH_LEN=[0,31,59,90,120,151,181,212,243,273,304,334];proto._getIsoWeekDate=function(B){var I=B.getFullYear();var F=B.getMonth()+1;var J=B.getDate();var L,K,H,G,E,D,C,N,A;if(F<=2){L=I-1;K=Math.floor(L/4)-Math.floor(L/100)+Math.floor(L/400);H=Math.floor((L-1)/4)-Math.floor((L-1)/100)+Math.floor((L-1)/400);N=K-H;E=0;D=J-1+31*(F-1);}else{L=I;K=Math.floor(L/4)-Math.floor(L/100)+Math.floor(L/400);H=Math.floor((L-1)/4)-Math.floor((L-1)/100)+Math.floor((L-1)/400);N=K-H;E=N+1;D=J+Math.floor((153*(F-3)+2)/5)+58+N;}C=(L+K)%7;G=(D+C-E)%7;A=D+3-G;if(A<0){var M=53-Math.floor((C-N)/5);return new org.apache.myfaces.dateformat.WeekDate(I-1,M);}else{if(A>(364+N)){var M=1;return new org.apache.myfaces.dateformat.WeekDate(I+1,M);}else{var M=Math.floor(A/7)+1;return new org.apache.myfaces.dateformat.WeekDate(I,M);}}};proto._isLeapYear=function(A){return((A%4==0)&&(A%100!=0))||(A%400==0);};proto._dayOfWeek=function(B,E,A){E-=2;if(E<1){E+=12;--B;}var D=Math.floor(B/100);B%=100;var C=Math.floor((26*E-2)/10)+A+B+Math.floor(B/4)+Math.floor(D/4)+(5*D);var F=C%7;return F;};proto._getWeekDate=function(D,B){var I=D.getFullYear();var G=D.getMonth()+1;var J=D.getDate();var E=this._isLeapYear(I);var K=J+this.MONTH_LEN[G-1];if(E&&(G>2)){++K;}var M=this._dayOfWeek(I,1,1);var F=B-M;if(F>3){F-=7;}else{if(F<-3){F+=7;}}var L=K-1;if(L<F){var H=this._isLeapYear(I-1);if((F==3)||((F==2)&&H)){return new org.apache.myfaces.dateformat.WeekDate(I-1,53);}return new org.apache.myfaces.dateformat.WeekDate(I-1,52);}var C=(K-1-F);var A=Math.floor(C/7)+1;if((A<53)||(F==-3)||(F==-2&&E)){return new org.apache.myfaces.dateformat.WeekDate(I,A);}else{return new org.apache.myfaces.dateformat.WeekDate(I+1,1);}};proto._getStartOfWeekYear=function(E,A){var F=new Date(E,0,1,0,0,0);var C=F.getDay();var D=A-C;var B;if(D>=4){B=7-B;}else{if(D>=0){B=D;}else{if(D>=-3){B=D;}else{B=7+D;}}}var G=F.getTime()+(B*this.MSECS_PER_DAY);return G;};proto._getDateForWeekDate=function(H,C,I,D,E,F,A){var B=this._getStartOfWeekYear(H,A);var G=(C-1)*this.MSECS_PER_WEEK;G+=(I-1)*this.MSECS_PER_DAY;G+=D*this.MSECS_PER_HOUR;G+=E*this.MSECS_PER_MIN;G+=F*this.MSECS_PER_SEC;var J=new Date();J.setTime(B+G);return J;};proto._fullYearFromDate=function(A){if(A<1900){return A+1900;}else{return A;}};proto._createDateFromContext=function(B){var A;if(B.weekOfWeekYear!=0){A=this._getDateForWeekDate(B.weekYear,B.weekOfWeekYear,B.day,B.hour,B.min,B.sec,B.firstDayOfWeek);}else{A=new Date(B.year,B.month,B.day,B.hour,B.min,B.sec);}return A;};proto._substr=function(C,D,A){var B=C.substring(D);if(B.length<=A){return B;}else{return B.substring(0,A);}};proto._parseOps=function(C,J,A,D,E){var B=new org.apache.myfaces.dateformat.ParserContext(A);var N=0;var F=E.length;for(var H=0;(H<D.length)&&(N<F);++H){var I=D[H];var M=I.substring(0,2);var G=I.substring(2);if(M=="f:"){this._parsePattern(C,J,B,G,E,N);if((B.newIndex<0)||B.invalid){break;}N=B.newIndex;}else{if(M=="q:"||M=="l:"){var K=G.length;var L=this._substr(E,N,K);if(G!=L){B.invalid=true;break;}N+=K;}}}return B;};proto._parsePattern=function(B,H,A,E,D,K){var J=E.charAt(0);var C=E.length;if(J=="y"){var I=this._parseNum(A,D,4,K);if((A.newIndex-K)<4){A.year=I;A.ambiguousYear=true;}else{A.year=I;A.ambiguousYear=false;}if(H){A.weekYear=A.year;A.ambiguousWeekYear=A.ambiguousYear;}}else{if(J=="x"){var I=this._parseNum(A,D,4,K);if((A.newIndex-K)<4){A.weekYear=I;A.ambiguousWeekYear=true;}else{A.weekYear=I;A.ambiguousWeekYear=false;}}else{if(J=="M"){if(C==3){var G=this._substr(D,K,3);var F=this._parseIndexOf(A,B.shortMonths,G);if(F!=-1){A.month=F;}}else{if(C>=4){var G=D.substring(K);var F=this._parsePrefixOf(A,B.months,G);if(F!=-1){A.month=F;}}else{A.month=this._parseNum(A,D,2,K)-1;}}}else{if(J=="d"){A.day=this._parseNum(A,D,2,K);}else{if(J=="E"){if(C<=3){var G=D.substring(K,K+3);var F=this._parseIndexOf(A,B.shortWeekdays,G);if(F!=-1){A.dayOfWeek=F;}}else{var G=D.substring(K);var F=this._parsePrefixOf(A,B.weekdays,G);if(F!=-1){A.dayOfWeek=F;}}}else{if(J=="H"){A.hour=this._parseNum(A,D,2,K);}else{if(J=="h"){A.hourAmpm=this._parseNum(A,D,2,K);}else{if(J=="m"){A.min=this._parseNum(A,D,2,K);}else{if(J=="s"){A.sec=this._parseNum(A,D,2,K);}else{if(J=="a"){A.ampm=this._parseString(A,D,K,B.ampms);}else{if(J=="w"){A.weekOfWeekYear=this._parseNum(A,D,2,K);}else{A.invalid=true;}}}}}}}}}}}};proto._parseInt=function(C){var B=0;for(var A=0;A<C.length;A++){var D=C.charAt(A);if(D<"0"||D>"9"){return -1;}B=B*10+(D-"0");}return B;};proto._parseNum=function(F,B,D,A){var C=Math.min(D,B.length-A);for(var E=C;E>0;E--){var H=B.substring(A,A+E);var G=this._parseInt(H);if(G==-1){continue;}F.newIndex=A+E;return G;}F.newIndex=-1;F.invalid=true;return -1;};proto._parseIndexOf=function(B,E,D){for(var A=0;A<E.length;++A){var C=E[A];if(D==C){B.newIndex+=C.length;return A;}}B.invalid=true;B.newIndex=-1;return -1;};proto._parsePrefixOf=function(B,E,D){for(var A=0;A<E.length;++A){var C=E[A];if(D.indexOf(C)==0){B.newIndex+=C.length;return A;}}B.invalid=true;B.newIndex=-1;return -1;};proto._parseString=function(E,C,B,A){var D=C.substr(B);return this._parsePrefixOf(E,A,D);};proto._parsePostProcess=function(C,D){if(D.ambiguousYear){D.year+=1900;var B=this._createDateFromContext(D);var A=C.twoDigitYearStart;if(B.getTime()<A.getTime()){D.year+=100;}}if(D.year<=0){D.year=new Date().getFullYear();}if(D.hourAmpm>0){if(D.ampm==1){D.hour=D.hourAmpm+12;if(D.hour==24){D.hour=0;}}else{D.hour=D.hourAmpm;}}};proto._formatOps=function(C,I,A,D,E){var B=new org.apache.myfaces.dateformat.ParserContext(A);B.year=E.getFullYear();B.month=E.getMonth();B.day=E.getDate();B.dayOfWeek=E.getDay();B.hour=E.getHours();B.min=E.getMinutes();B.sec=E.getSeconds();B.ampm=(B.hour<12)?0:1;var J=this._getWeekDate(E,A);B.weekYear=J.year;B.weekOfWeekYear=J.week;var K=new org.apache.myfaces.dateformat.StringBuffer();for(var G=0;G<D.length;++G){var H=D[G];var L=H.substring(0,2);var F=H.substring(2);if(L=="f:"){this._formatPattern(C,B,F,I,K);if(B.invalid){break;}}else{if(L=="l:"){K.append(F);}else{if(L=="q:"){K.append(F);}}}}if(B.invalid){return null;}else{return K.toString();}};proto._formatPattern=function(E,G,F,B,D){var H=F.charAt(0);var C=F.length;if(H=="y"){if(!B){this._formatNum(G.year,C<=3?2:4,true,D);}else{this._formatNum(G.weekYear,C<=3?2:4,true,D);}}else{if(H=="x"){this._formatNum(G.weekYear,C<=3?2:4,true,D);}else{if(H=="M"){if(C==3){D.append(E.shortMonths[G.month]);}else{if(C>=4){D.append(E.months[G.month]);}else{this._formatNum(G.month+1,C,false,D);}}}else{if(H=="d"){this._formatNum(G.day,C,false,D);}else{if(H=="E"){if(C<=3){D.append(E.shortWeekdays[G.dayOfWeek]);}else{D.append(E.weekdays[G.dayOfWeek]);}}else{if(H=="H"){this._formatNum(G.hour,C,false,D);}else{if(H=="h"){var A=G.hour;if(A==0){A=12;}else{if(A>12){A=A-12;}}this._formatNum(A,C,false,D);}else{if(H=="m"){this._formatNum(G.min,C,false,D);}else{if(H=="s"){this._formatNum(G.sec,C,false,D);}else{if(H=="a"){D.append(E.ampms[G.ampm]);}else{if(H=="w"){this._formatNum(G.weekOfWeekYear,C,false,D);}else{G.invalid=true;}}}}}}}}}}}};proto._formatNum=function(B,C,E,A){var D=""+B;while(D.length<C){D="0"+D;}if(E&&D.length>C){D=D.substr(D.length-C);}A.append(D);};proto._appendToArray=function(B,A){B[B.length]=A;};proto._isLetter=function(A){if((A>="a")&&(A<="z")){return true;}if((A>="A")&&(A<="Z")){return true;}return false;};proto._analysePattern=function(F){var D=0;var A=F.length;var H=0;var E=null;var G=false;var C=new Array();while(D<A){var I=F.charAt(D);var B;if(D<A-1){B=F.charAt(D+1);}else{B=0;}if(I=="'"&&H!="\\"){if(E!=null){this._appendToArray(C,E.toString());E=null;}G=!G;}else{if(G){if(E==null){E=new org.apache.myfaces.dateformat.StringBuffer("q:");}E.append(I);}else{if(I=="\\"&&H!="\\"){}else{if(E==null){if(this._isLetter(I)){E=new org.apache.myfaces.dateformat.StringBuffer("f:");}else{E=new org.apache.myfaces.dateformat.StringBuffer("l:");}}E.append(I);if(I!=B){this._appendToArray(C,E.toString());E=null;}}}}D++;H=I;}if(E!=null){this._appendToArray(C,E.toString());}return C;};proto._hasWeekPattern=function(E){var C=false;var A=false;for(var B=0;B<E.length;++B){var D=E[B];C=C||(D.indexOf("f:ww")==0);A=A||(D.indexOf("f:xx")==0);}return C&&!A;};proto._construct=function(C,B,A){if(B==null){this.symbols=new org.apache.myfaces.dateformat.DateFormatSymbols();}else{this.symbols=B;}this.ops=this._analysePattern(C);this.yearIsWeekYear=this._hasWeekPattern(this.ops);if(A!=null){this.firstDayOfWeek=A;}else{this.firstDayOfWeek=1;}};proto.setFirstDayOfWeek=function(A){this.firstDayOfWeek=A;};proto.parse=function(A){if((A==null)||(A.length==0)){return null;}var B=this._parseOps(this.symbols,this.yearIsWeekYear,this.firstDayOfWeek,this.ops,A);if(B.invalid){return null;}this._parsePostProcess(this.symbols,B);return this._createDateFromContext(B);};proto.format=function(A){return this._formatOps(this.symbols,this.yearIsWeekYear,this.firstDayOfWeek,this.ops,A);};proto.getWeekDate=function(A){return this._getWeekDate(A,this.firstDayOfWeek);};proto.getDateForWeekDate=function(A){return this._getDateForWeekDate(A.year,A.week,1,0,0,0,this.firstDayOfWeek);};}//	based on code written by Tan Ling Wee on 2 Dec 2001
//	last updated 20 June 2003
//	email :	fuushikaden@yahoo.com
//
// Modified to be completely object-oriented, CSS based and using proper DOM-access functions
// @author Martin Marinschek
// @author Sylvain Vieujot

//we reserve the namespace correctly
window.org = window.org || {};
org.apache = org.apache || {};
org.apache.myfaces = org.apache.myfaces || {};

if (!org.apache.myfaces.PopupCalendar) {
    org.apache.myfaces.CalendarInitData = function () {
        // x position (-1 if to appear below control)
        this.fixedX = -1;

        // y position (-1 if to appear below control)
        this.fixedY = -1;

        // 0 - sunday ; 1 - monday (aka firstDayOfWeek)
        this.startAt = 1;

        // 0 - don't show; 1 - show
        this.showWeekNumber = 1;

        // 0 - don't show; 1 - show
        this.showToday = 1;

        // directory for images ... e.g. this.imgDir="/img/"
        this.imgDir = "images/";

        this.imgDirSuffix = "";

        this.themePrefix = "jscalendar-DB";

        this.gotoString = "Go To Current Month";
        this.todayString = "Today is";
        this.todayDateFormat = null;
        this.weekString = "Wk";
        this.scrollLeftMessage = "Click to scroll to previous month. Hold mouse button to scroll automatically.";
        this.scrollRightMessage = "Click to scroll to next month. Hold mouse button to scroll automatically.";
        this.selectMonthMessage = "Click to select a month.";
        this.selectYearMessage = "Click to select a year.";
        this.selectDateMessage = "Select [date] as date."; // do not replace [date], it will be replaced by date.

        this.popupLeft = false;

        this.monthName = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");
        this.dayName = this.startAt == 0 ? new Array("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat") : new Array("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun");

        this.selectMode = "day";

    };

    org.apache.myfaces.DateParts = function (sec, min, hour, date, month, year) {
        this.sec = sec;
        this.min = min;
        this.hour = hour;
        this.date = date;
        this.month = month;
        this.year = year;
    };

    org.apache.myfaces.HolidayRec = function (d, m, y, desc) {
        this.d = d;
        this.m = m;
        this.y = y;
        this.desc = desc;
    };

    org.apache.myfaces.PopupCalendar = function () {
        this.idPrefix = "org.apache.myfaces.PopupCalendar";

        this.selectedDate = new org.apache.myfaces.DateParts(0, 0, 0, 0, 0, 0);
        this.saveSelectedDate = new org.apache.myfaces.DateParts(0, 0, 0, 0, 0, 0);

        this.monthConstructed = false;
        this.yearConstructed = false;
        this.intervalID1 = null;
        this.intervalID2 = null;
        this.timeoutID1 = null;
        this.timeoutID2 = null;
        this.ctlToPlaceValue = null;
        this.ctlNow = null;
        this.containerCtl = null;
        this.dateFormat = "MM/dd/yyyy";
        this.nStartingYear = null;
        this.bPageLoaded = false;

        // Detect whether the browser is Microsoft Internet Explorer.
        // Testing for the presence of document.all is not sufficient, as Opera provides that.
        // However hopefully nothing but IE implements ActiveX..
        // it is only needed to test for ie6 and before ie7 and quirks mode
        // do not expose the bleed through bug anymore
        this.ieVersion = this.getInternetExplorerVersion();
        this.ie6 = this.ieVersion != -1 && this.ieVersion < 7;

        this.dom = document.getElementById;
        this.ns4 = document.layers;
        this.dateFormatSymbols = new org.apache.myfaces.dateformat.DateFormatSymbols();
        this.initData = new org.apache.myfaces.CalendarInitData();
        this.today = new Date();
        this.dateNow = this.today.getDate();
        this.monthNow = this.today.getMonth();
        this.yearNow = this.today.getFullYear();

        // list of images to be preloaded from the server
        this.imgSrc = new Array("drop1.gif", "drop2.gif", "left1.gif", "left2.gif", "right1.gif", "right2.gif");
        this.img = new Array();

        //elements which need to change their dynamical
        //representation over time
        this.calendarDiv;
        this.selectMonthDiv;
        this.selectYearDiv;
        this.todaySpan = null;
        this.captionSpan = null;
        this.contentSpan = null;
        this.acceptMonthSpan = null;
        this.closeCalendarSpan = null;
        this.monthSpan = null;
        this.yearSpan = null
        this.changeMonthImg = null;
        this.changeYearImg = null;

        this.holidaysCounter = 0;
        this.holidays = new Array();

        this.bClickOnCalendar = false;
        this.bCalendarHidden = true;

        this.myFacesCtlType = "x:inputCalendar";
        this.inputDateClientId;
    };

//http://msdn.microsoft.com/en-us/library/ms537509%28v=vs.85%29.aspx
    org.apache.myfaces.PopupCalendar.prototype.getInternetExplorerVersion = function ()
        // Returns the version of Internet Explorer or a -1
        // (indicating the use of another browser).
    {
        var rv = -1; // Return value assumes failure.
        if (navigator.appName == 'Microsoft Internet Explorer') {
            var ua = navigator.userAgent;
            var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
            if (re.exec(ua) != null)
                rv = parseFloat(RegExp.$1);
        }
        return rv;
    };

    org.apache.myfaces.PopupCalendar.prototype._MSECS_PER_DAY = 24 * 60 * 60 * 1000;

    /**
     popups always have to be
     at the dom level nowhere else
     */
    org.apache.myfaces.PopupCalendar.prototype._fixPopupDomOrder = function (overDiv) {
        if (document.body != overDiv.parentNode) {
            overDiv.parentNode.removeChild(overDiv);
            document.body.appendChild(overDiv);
        }
    };

// IE bug workaround: hide background controls under the specified div.
    org.apache.myfaces.PopupCalendar.prototype._showPopupPostProcess = function (overDiv) {

        //ie6 detection over object inspections
        if (this.ie6) {
            // The iframe created here is a hack to work around an IE bug. In IE,
            // "windowed controls" (esp selectboxes) do not respect the z-index
            // setting of "non-windowed controls", meaning they will be drawn on
            // top of components that they should theoretically be underneath.
            // However a selectbox will NOT be drawn on top of an iframe, so the
            // workaround is to create an iframe with no content, then in function
            // _recalculateElement position the iframe under the "popup" div to
            // "mask out" the unwanted elements. 
            var iframe = document.getElementById(overDiv.id + "_IFRAME");

            if (iframe == null) {
                // the source attribute is to avoid a IE error message about non secure content on https connections
                iframe = document.createElement("iframe");
                iframe.setAttribute("id", overDiv.id + "_IFRAME");
                iframe.setAttribute("src", "javascript:false;");
                
                //HIS_FIX_BEGIN
                jQuery(iframe).css({
                	"visibility": "hidden",
                	"position": "absolute",
                	"top": "0px",
                	"left": "0px"
                });
//                Element.setStyle(iframe, "visibility:hidden; position: absolute; top:0px;left:0px;");

                //we can append it lazily since we are late here anyway and everything is rendered
                document.body.appendChild(iframe);
            }

            // now put the iframe at the appropriate location, and make it visible.
            this._recalculateElement(overDiv);
        }
    };

// IE bug workaround: hide background controls under the specified div; see _showPopupPostProcess.
// This should be called whenever a popup div is moved.
    org.apache.myfaces.PopupCalendar.prototype._recalculateElement = function (overDiv) {
        if (this.ie6) {
            var iframe = document.getElementById(overDiv.id + "_IFRAME");

            if (iframe) {
                // ok, there is a "masking iframe" associated with this div, so make its
                // size and position match the div exactly, and set its z-index to just
                // below the div. This hack blocks IE selectboxes from being drawn on top
                // of the div. 

                overDiv.style.zIndex = 98;

                iframe.style.zIndex = overDiv.style.zIndex - 1;
                iframe.style.width = overDiv.offsetWidth;
                iframe.style.height = overDiv.offsetHeight;
                iframe.style.top = overDiv.style.top;
                iframe.style.left = overDiv.style.left;
                iframe.style.display = "block";
                iframe.style.visibility = "visible";
                /*we have to set an explicit visible otherwise it wont work*/
            }
        }
    };

// IE bug workaround: unhide background controls that are beneath the specified div; see _showPopupPostProcess.
// Note that although this is called _showeElement, it is called when the popup is being *hidden*,
// in order to *show* the underlying controls again.
// we also reallign the floating div 
    org.apache.myfaces.PopupCalendar.prototype._hidePopupPostProcess = function (overDiv) {

        if (this.ie6) {
            var iframe = document.getElementById(overDiv.id + "_IFRAME");
            if (iframe) iframe.style.display = "none";
        }
    };

    org.apache.myfaces.PopupCalendar.prototype.addHoliday = function (d, m, y, desc) {
        this.holidays[this.holidaysCounter++] = new org.apache.myfaces.HolidayRec(d, m, y, desc);
    };

    org.apache.myfaces.PopupCalendar.prototype._swapImage = function (srcImg, destImg) {

        if (srcImg)
            srcImg.setAttribute("src", this.initData.imgDir + destImg + this.initData.imgDirSuffix);
    };

    org.apache.myfaces.PopupCalendar.prototype._keypresshandler = function () {
        // This method is intended for use on IE browsers only; they are the only
        // browsers that define window.event and window.event.keyCode.
        // Q: Why is this done only for IE?
        if (window["event"] && window.event["keyCode"] && (window.event.keyCode == 27)) {
            this._hideCalendar();
        }
    };

    org.apache.myfaces.PopupCalendar.prototype._clickhandler = function () {
        if (!this.bClickOnCalendar) {
            this._hideCalendar();
        }

        this.bClickOnCalendar = false;
    };

    org.apache.myfaces.PopupCalendar.prototype._isDaySelectable = function () {
        return (this.initData.selectMode == "day");
    };

    org.apache.myfaces.PopupCalendar.prototype._isWeekSelectable = function () {
        return (this.initData.selectMode == "week");
    };

    org.apache.myfaces.PopupCalendar.prototype._isMonthSelectable = function () {
        return (this.initData.selectMode == "month");
    };

    org.apache.myfaces.PopupCalendar.prototype.init = function (containerCtl) {
        if (this.dom) {

            if (!this.calendarDiv) {
                for (var i = 0; i < this.imgSrc.length; i++) {
                    // force preload of all images, so that when DOM nodes have their src set to
                    // the name of this image, it has already been loaded from the server.
                    this.img[i] = new Image;
                    this.img[i].src = this.initData.imgDir + this.imgSrc[i] + this.initData.imgDirSuffix;
                }

                this.containerCtl = containerCtl;

                this.calendarDiv = document.createElement("div");
                this.calendarDiv.id = containerCtl.id + "_calendarDiv";
                this.calendarDiv.className = this.initData.themePrefix + "-div-style";

                //HIS_FIX_BEGIN
                var that = this;
                jQuery(this.calendarDiv).on("click", function() {
                	that.bClickOnCalendar = true;
                });
//                Event.observe(this.calendarDiv, "click", function () {
//                    this.bClickOnCalendar = true;
//                }.bind(this), false);
                //HIS_FIX_END

                this.containerCtl.appendChild(this.calendarDiv);

                var mainTable = document.createElement("table");
                
                //HIS_FIX_BEGIN
                jQuery(mainTable).css({
                	"width": ((that.initData.showWeekNumber == 1) ? 250 : 220) + "px"
                });
//                Element.setStyle(mainTable, "width:" + ((this.initData.showWeekNumber == 1) ? 250 : 220) + "px;");
                mainTable.className = this.initData.themePrefix + "-table-style";
                //HIS_FIX_END

                this.calendarDiv.appendChild(mainTable);

                //This is necessary for IE. If you don't create a tbody element, the table will never show up!
                var mainBody = document.createElement("tbody");
                mainTable.appendChild(mainBody);

                var mainRow = document.createElement("tr");
                mainRow.className = this.initData.themePrefix + "-title-background-style";

                mainBody.appendChild(mainRow);

                var mainCell = document.createElement("td");

                mainRow.appendChild(mainCell);

                var contentTable = document.createElement("table");
                
                //HIS_FIX_BEGIN
                jQuery(contentTable).css({
                	"width": ((that.initData.showWeekNumber == 1) ? 248 : 218) + "px"
                });
//                Element.setStyle(contentTable, "width:" + ((this.initData.showWeekNumber == 1) ? 248 : 218) + "px;");
                //HIS_FIX_END
                
                var contentBody = document.createElement("tbody");
                contentTable.appendChild(contentBody);

                mainCell.appendChild(contentTable);

                var headerRow = document.createElement("tr");
                contentBody.appendChild(headerRow);

                var captionCell = document.createElement("td");
                captionCell.className = this.initData.themePrefix + "-title-style";
                headerRow.appendChild(captionCell);

                this.captionSpan = document.createElement("span");
                captionCell.appendChild(this.captionSpan);

                if (this._isMonthSelectable()) {
                    var acceptMonthCell = document.createElement("td");
                    
                    //HIS_FIX_BEGIN
                    jQuery(acceptMonthCell).css("text-align", "right");
//                    Element.setStyle(acceptMonthCell, "text-align:right;");
                    //HIS_FIX_END
                    headerRow.appendChild(acceptMonthCell);

                    var acceptMonthLink = document.createElement("a");
                    acceptMonthLink.setAttribute("href", "#");
                    
                    //HIS_FIX_BEGIN
                    jQuery(acceptMonthLink).on("click", function(event){
                    	that.selectedDate.date = 1; // force first of the selected month
                    	that._closeCalendar();
                    	event.preventDefault();
                    	event.stopPropagation()
                    });
//                    Event.observe(acceptMonthLink, "click", function (event) {
//                        this.selectedDate.date = 1; // force first of the selected month
//                        this._closeCalendar();
//                        Event.stop(event);
//                    }.bindAsEventListener(this), false);
                    //HIS_FIX_END

                    acceptMonthCell.appendChild(acceptMonthLink);
                    this.acceptMonthSpan = document.createElement("span");
                    this.acceptMonthSpan.appendChild(document.createTextNode("Y"));

                    acceptMonthLink.appendChild(this.acceptMonthSpan);
                }

                var closeButtonCell = document.createElement("td");
                //HIS_FIX_BEGIN
                jQuery(closeButtonCell).css("text-align", "right");
//                Element.setStyle(closeButtonCell, "text-align:right;");
                //HIS_FIX_END
                headerRow.appendChild(closeButtonCell);

                var closeCalendarLink = document.createElement("a");
                closeCalendarLink.setAttribute("href", "#");
                
                //HIS_FIX_BEGIN
                jQuery(closeCalendarLink).on("click", function(event){
                	that._hideCalendar();
                	event.preventDefault();
                    event.stopPropagation();
                });
//                Event.observe(closeCalendarLink, "click", function (event) {
//                    this._hideCalendar();
//                    Event.stop(event);
//                }.bindAsEventListener(this), false);
                //HIS_FIX_END

                closeButtonCell.appendChild(closeCalendarLink);

                this.closeCalendarSpan = document.createElement("span");

                closeCalendarLink.appendChild(this.closeCalendarSpan);

                var contentRow = document.createElement("tr");
                mainBody.appendChild(contentRow);

                var contentCell = document.createElement("td");
                contentCell.className = this.initData.themePrefix + "-body-style";
                contentRow.appendChild(contentCell);

                this.contentSpan = document.createElement("span");
                contentCell.appendChild(this.contentSpan);

                if (this.initData.showToday == 1) {
                    var todayRow = document.createElement("tr");
                    todayRow.className = this.initData.themePrefix + "-today-style";
                    mainBody.appendChild(todayRow);

                    var todayCell = document.createElement("td");
                    todayCell.className = this.initData.themePrefix + "-today-lbl-style";
                    todayRow.appendChild(todayCell);

                    this.todaySpan = document.createElement("span");
                    todayCell.appendChild(this.todaySpan);
                }

                this.selectMonthDiv = document.createElement("div");
                this.selectMonthDiv.id = this.containerCtl.id + "_selectMonthDiv";
                this.selectMonthDiv.className = this.initData.themePrefix + "-div-style";

                this.containerCtl.appendChild(this.selectMonthDiv);

                this.selectYearDiv = document.createElement("div");
                this.selectYearDiv.id = this.containerCtl.id + "_selectYearDiv";
                this.selectYearDiv.className = this.initData.themePrefix + "-div-style";

                this.containerCtl.appendChild(this.selectYearDiv);

                // Catch global keypresses and clicks, so that entering data into any field
                // outside the calendar, or clicking anywhere outside the calendar, will
                // close it.
                //
                // This is ugly, as it's quite a load on the client to check this for every
                // keystroke/click. It would be nice to find an alternative...maybe register
                // these listeners only when a calendar is open?
                
                //HIS_FIX_BEGIN
                jQuery(document).on("keypress", function(){
                	that._keypresshandler();
                });
//                Event.observe(document, "keypress", this._keypresshandler.bind(this), false);
                jQuery(document).on("click", function(){
                	that._clickhandler();
                });
//                Event.observe(document, "click", this._clickhandler.bind(this), false);
                //HIS_FIX_END
            }
        }

        if (!this.ns4) {
            /* Instead use getFullYear() */
            /*if (!this.ie6)
             this.yearNow += 1900;*/

            this._hideCalendar();

            this.monthConstructed = false;
            this.yearConstructed = false;

            if (this.initData.showToday == 1) {
                // TODO this.dateFormatSymbols is probably never set at this point.
                this.todayDateFormatter = new org.apache.myfaces.dateformat.SimpleDateFormatter(
                        this.initData.todayDateFormat ? this.initData.todayDateFormat : this.dateFormat,
                        this.dateFormatSymbols,
                        this.initData.startAt);

                this.todaySpan.appendChild(document.createTextNode(this.initData.todayString + " "))

                var todayLink = document.createElement("a");
                todayLink.className = this.initData.themePrefix + "-today-style";
                todayLink.setAttribute("title", this.initData.gotoString);
                todayLink.setAttribute("href", "#");
                todayLink.appendChild(document.createTextNode(this._todayIsDate()));
                
                //HIS_FIX_BEGIN
                jQuery(todayLink).on("click", function(event){
                	that.selectedDate.month = that.monthNow;
                	that.selectedDate.year = that.yearNow;
                	that._constructCalendar();
                	event.preventDefault();
                    event.stopPropagation();
                });
//                Event.observe(todayLink, "click", function (event) {
//                    this.selectedDate.month = this.monthNow;
//                    this.selectedDate.year = this.yearNow;
//                    this._constructCalendar();
//                    Event.stop(event);
//                }.bindAsEventListener(this), false);
                
                jQuery(todayLink).on("mousemove", function(event){
                	window.status = that.initData.gotoString;
                });
//                Event.observe(todayLink, "mousemove", function () {
//                    window.status = this.initData.gotoString;
//                }.bind(this), false);
                
                jQuery(todayLink).on("mouseout", function(event){
                	 window.status = "";
                });
//                Event.observe(todayLink, "mouseout", function () {
//                    window.status = "";
//                }.bind(this), false);
                //HIS_FIX_END

                this.todaySpan.appendChild(todayLink);
            }

            this._appendNavToCaption("left");
            this._appendNavToCaption("right");

            this.monthSpan = document.createElement("span");
            this.monthSpan.className = this.initData.themePrefix + "-title-control-normal-style";

            //HIS_FIX_BEGIN
            jQuery(that.monthSpan).on("mouseover", function(event){
            	that._swapImage(that.changeMonthImg, "drop2.gif");
            	that.monthSpan.className = that.initData.themePrefix + "-title-control-select-style";
            	window.status = that.selectMonthMessage;
            });
//            Event.observe(this.monthSpan, "mouseover", function (event) {
//                this._swapImage(this.changeMonthImg, "drop2.gif");
//                this.monthSpan.className = this.initData.themePrefix + "-title-control-select-style";
//                window.status = this.selectMonthMessage;
//            }.bindAsEventListener(this), false);

            jQuery(that.monthSpan).on("mouseout", function(event){
            	that._swapImage(that.changeMonthImg, "drop1.gif");
            	that.monthSpan.className = that.initData.themePrefix + "-title-control-normal-style";
                window.status = "";
            });
//            Event.observe(this.monthSpan, "mouseout", function (event) {
//                this._swapImage(this.changeMonthImg, "drop1.gif");
//                this.monthSpan.className = this.initData.themePrefix + "-title-control-normal-style";
//                window.status = "";
//            }.bindAsEventListener(this), false);

            jQuery(that.monthSpan).on("click", function(event){
            	that._popUpMonth();
            	event.preventDefault();
                event.stopPropagation();
            });
//            Event.observe(this.monthSpan, "click", function (event) {
//                this._popUpMonth();
//                Event.stop(event);
//            }.bind(this), false);
            //HIS_FIX_END

            this.captionSpan.appendChild(this.monthSpan);
            this._appendNbsp(this.captionSpan);

            this.yearSpan = document.createElement("span");
            this.yearSpan.className = this.initData.themePrefix + "-title-control-normal-style";

            //HIS_FIX_BEGIN
            jQuery(that.yearSpan).on("mouseover", function(event){
            	that._swapImage(that.changeYearImg, "drop2.gif");
            	that.yearSpan.className = that.initData.themePrefix + "-title-control-select-style";
                 window.status = that.selectYearMessage;
            });
//            Event.observe(this.yearSpan, "mouseover", function (event) {
//                this._swapImage(this.changeYearImg, "drop2.gif");
//                this.yearSpan.className = this.initData.themePrefix + "-title-control-select-style";
//                window.status = this.selectYearMessage;
//            }.bindAsEventListener(this), false);

            jQuery(that.yearSpan).on("mouseout", function(event){
            	that._swapImage(that.changeYearImg, "drop1.gif");
            	that.yearSpan.className = that.initData.themePrefix + "-title-control-normal-style";
            	window.status = "";
            });
//            Event.observe(this.yearSpan, "mouseout", function (event) {
//                this._swapImage(this.changeYearImg, "drop1.gif");
//                this.yearSpan.className = this.initData.themePrefix + "-title-control-normal-style";
//                window.status = "";
//            }.bindAsEventListener(this), false);

            jQuery(that.yearSpan).on("click", function(event){
            	that._popUpYear();
            	event.preventDefault();
            	event.stopPropagation();
            });
//            Event.observe(this.yearSpan, "click", function (event) {
//                this._popUpYear();
//                Event.stop(event);
//            }.bind(this), false);
            //HIS_FIX_END

            this.captionSpan.appendChild(this.yearSpan);
            this._appendNbsp(this.captionSpan);

            this.bPageLoaded = true;

        }
    };

    org.apache.myfaces.PopupCalendar.prototype._appendNavToCaption = function (direction) {
        var imgLeft = document.createElement("img");
        imgLeft.setAttribute("src", this.initData.imgDir + direction + "1.gif" + this.initData.imgDirSuffix);
        imgLeft.setAttribute("width", "10px");
        imgLeft.setAttribute("height", "11px");
        //HIS_FIX_BEGIN
        jQuery(imgLeft).css("border", "0px");
//        Element.setStyle(imgLeft, "border:0px;");
        //HIS_FIX_END
        
        var spanLeft = document.createElement("span");

        this._createControl(direction, spanLeft, imgLeft);

        this._appendNbsp(spanLeft);
        spanLeft.appendChild(imgLeft);
        this._appendNbsp(spanLeft);
        this.captionSpan.appendChild(spanLeft);
        this._appendNbsp(spanLeft);
    };

    org.apache.myfaces.PopupCalendar.prototype._createControl = function (direction, spanLeft, imgLeft) {
        spanLeft.className = this.initData.themePrefix + "-title-control-normal-style";
        
        //HIS_FIX_BEGIN
        var that = this;
        jQuery(spanLeft).on("mouseover", function(event){
        	that._swapImage(imgLeft, direction + "2.gif");
             spanLeft.className = that.initData.themePrefix + "-title-control-select-style";
             if (direction == "left") {
                 window.status = that.scrollLeftMessage;
             }
             else {
                 window.status = that.scrollRightMessage;
             }
        });
//        Event.observe(spanLeft, "mouseover", function (event) {
//            this._swapImage(imgLeft, direction + "2.gif");
//            spanLeft.className = this.initData.themePrefix + "-title-control-select-style";
//            if (direction == "left") {
//                window.status = this.scrollLeftMessage;
//            }
//            else {
//                window.status = this.scrollRightMessage;
//            }
//        }.bindAsEventListener(this), false);
        
        jQuery(spanLeft).on("click", function(){
        	 if (direction == "left") {
        		 that._decMonth();
             }
             else {
            	 that._incMonth();
             }
        });
//        Event.observe(spanLeft, "click", function () {
//            if (direction == "left") {
//                this._decMonth();
//            }
//            else {
//                this._incMonth();
//            }
//        }.bind(this), false);
        
        
        jQuery(spanLeft).on("mouseout", function(){
        	 clearInterval(that.intervalID1);
        	 that._swapImage(imgLeft, direction + "1.gif");
             spanLeft.className = "" + that.initData.themePrefix + "-title-control-normal-style";
             window.status = "";
        });
//        Event.observe(spanLeft, "mouseout", function (event) {
//            clearInterval(this.intervalID1);
//            this._swapImage(imgLeft, direction + "1.gif");
//            spanLeft.className = "" + this.initData.themePrefix + "-title-control-normal-style";
//            window.status = "";
//        }.bindAsEventListener(this), false);
        
        jQuery(spanLeft).on("mousedown", function(){
        	 clearTimeout(that.timeoutID1);
        	 that.timeoutID1 = setTimeout((function () {
                 if (direction == "left") {
                	 that._startDecMonth();
                 }
                 else {
                	 that._startIncMonth();
                 }
             }).bind(this), 500)
        });
//        Event.observe(spanLeft, "mousedown", function () {
//            clearTimeout(this.timeoutID1);
//            this.timeoutID1 = setTimeout((function () {
//                if (direction == "left") {
//                    this._startDecMonth();
//                }
//                else {
//                    this._startIncMonth();
//                }
//            }).bind(this), 500)
//        }.bind(this), false);
        
        jQuery(spanLeft).on("mouseup", function(){
        	 clearTimeout(that.timeoutID1);
             clearInterval(that.intervalID1);
        });
//        Event.observe(spanLeft, "mouseup", function () {
//            clearTimeout(this.timeoutID1);
//            clearInterval(this.intervalID1);
//        }.bind(this), false);
        //HIS_FIX_END
    };

    org.apache.myfaces.PopupCalendar.prototype._appendNbsp = function (element) {
        if (element)
            element.appendChild(document.createTextNode(String.fromCharCode(160)));
    };

    org.apache.myfaces.PopupCalendar.prototype._todayIsDate = function () {
        return this.todayDateFormatter.format(this.today);
    };

    org.apache.myfaces.PopupCalendar.prototype._hideCalendar = function () {
        this.calendarDiv.style.visibility = "hidden"
        this.bCalendarHidden = true;
        if (this.selectMonthDiv.style != null) {
            this.selectMonthDiv.style.visibility = "hidden";
        }
        if (this.selectYearDiv.style != null) {
            this.selectYearDiv.style.visibility = "hidden";
        }

        this._hidePopupPostProcess(this.selectMonthDiv);
        this._hidePopupPostProcess(this.selectYearDiv);
        this._hidePopupPostProcess(this.calendarDiv);
    };

    org.apache.myfaces.PopupCalendar.prototype._padZero = function (num) {
        return (num < 10) ? '0' + num : num;
    };

    org.apache.myfaces.PopupCalendar.prototype._constructDate = function (d, m, y) {
        var date = new Date(y, m, d, this.selectedDate.hour, this.selectedDate.min, this.selectedDate.sec);
        return this.stdDateFormatter.format(date);
    };

    org.apache.myfaces.PopupCalendar.prototype._closeCalendar = function () {
        this._hideCalendar();

        if (this.myFacesCtlType != "x:inputDate") {
            this.ctlToPlaceValue.value = this._constructDate(this.selectedDate.date, this.selectedDate.month, this.selectedDate.year)
            var onchange = this.ctlToPlaceValue.getAttribute("onchange");
            if (onchange) {
                this.ctlToPlaceValue.onchange();
            }
        }
        else {
            document.getElementById(this.myFacesInputDateClientId + ".day").value = this.selectedDate.date;
            document.getElementById(this.myFacesInputDateClientId + ".month").value = this.selectedDate.month + 1;
            document.getElementById(this.myFacesInputDateClientId + ".year").value = this.selectedDate.year;
        }
    };

    /*** Month Pulldown ***/

    org.apache.myfaces.PopupCalendar.prototype._startDecMonth = function () {
        this.intervalID1 = setInterval((function () {
            this._decMonth();
        }).bind(this), 80);
    };

    org.apache.myfaces.PopupCalendar.prototype._startIncMonth = function () {
        this.intervalID1 = setInterval((function () {
            this._incMonth();
        }).bind(this), 80);
    };

    org.apache.myfaces.PopupCalendar.prototype._incMonth = function () {
        this.selectedDate.month = this.selectedDate.month + 1;
        if (this.selectedDate.month > 11) {
            this.selectedDate.month = 0;
            this.selectedDate.year++;
        }
        this._constructCalendar();
    };

    org.apache.myfaces.PopupCalendar.prototype._decMonth = function () {
        this.selectedDate.month = this.selectedDate.month - 1;
        if (this.selectedDate.month < 0) {
            this.selectedDate.month = 11;
            this.selectedDate.year--;
        }
        this._constructCalendar()
    };

    org.apache.myfaces.PopupCalendar.prototype._removeAllChildren = function (element) {
        while (element && element.hasChildNodes())
            element.removeChild(element.lastChild);
    };

    org.apache.myfaces.PopupCalendar.prototype._constructMonth = function () {
        this._popDownYear();
        if (!this.monthConstructed) {

            var selectMonthTable = document.createElement("table");
            //HIS_FIX_BEGIN
            jQuery(selectMonthTable).css({
            	"width": "70px",
            	"border-collapse": "collapse"
            });
//            Element.setStyle(selectMonthTable, "width:70px;border-collapse:collapse;");
            //HIS_FIX_END
            selectMonthTable.className = this.initData.themePrefix + "-dropdown-style";

            this._removeAllChildren(this.selectMonthDiv);

            this.selectMonthDiv.appendChild(selectMonthTable);

            //HIS_FIX_BEGIN
            var that = this;
            jQuery(selectMonthTable).on("mouseover", function(){
            	clearTimeout(that.timeoutID1);
            });
//            Event.observe(selectMonthTable, "mouseover", function () {
//            	clearTimeout(this.timeoutID1);
//            }.bind(this), false);
            
            jQuery(selectMonthTable).on("mouseout", function(event){
            	clearTimeout(that.timeoutID1);
            	that.timeoutID1 = setTimeout((function () {
            		that._popDownMonth()
                }).bind(this), 100);
            	event.preventDefault();
                event.stopPropagation();
            });
//            Event.observe(selectMonthTable, "mouseout", function (event) {
//                clearTimeout(this.timeoutID1);
//                this.timeoutID1 = setTimeout((function () {
//                    this._popDownMonth()
//                }).bind(this), 100);
//                Event.stop(event);
//            }.bindAsEventListener(this), false);
            //HIS_FIX_END

            var selectMonthTableBody = document.createElement("tbody");
            selectMonthTable.appendChild(selectMonthTableBody);

            for (i = 0; i < 12; i++) {
                var sName = this.initData.monthName[i];

                var sNameNode = null;

                if (i == this.selectedDate.month) {
                    sNameNode = document.createElement("span");
                    //HIS_FIX_BEGIN
                    jQuery(sNameNode).css("font-weight", "bold");
//                    Element.setStyle(sNameNode, "font-weight:bold;");
                    //HIS_FIX_END
                    sNameNode.appendChild(document.createTextNode(sName));
                    sNameNode.setAttribute("userData", i);
                }
                else {
                    sNameNode = document.createTextNode(sName);
                }

                var monthRow = document.createElement("tr");
                selectMonthTableBody.appendChild(monthRow);

                var monthCell = document.createElement("td");
                monthCell.setAttribute("userData", i);
                monthRow.appendChild(monthCell);
                
                //HIS_FIX_BEGIN
                jQuery(monthCell).on("mouseover", function(event){
                	event.target.className = that.initData.themePrefix + "-dropdown-select-style";
                });
//                Event.observe(monthCell, "mouseover", function (event) {
//                    Event.element(event).className = this.initData.themePrefix + "-dropdown-select-style";
//                }.bind(this), false);

                jQuery(monthCell).on("mouseout", function(event){
                	event.target.className = that.initData.themePrefix + "-dropdown-normal-style";
                });
//                Event.observe(monthCell, "mouseout", function (event) {
//                    Event.element(event).className = this.initData.themePrefix + "-dropdown-normal-style";
//                }.bind(this), false);

                jQuery(monthCell).on("click", function(event){
                	that.monthConstructed = false;
                	that.selectedDate.month = parseInt(event.target.getAttribute("userData"), 10);
                	that._constructCalendar();
                    that._popDownMonth();
                	event.preventDefault();
                    event.stopPropagation();
                });
//                Event.observe(monthCell, "click", function (event) {
//                    this.monthConstructed = false;
//                    this.selectedDate.month = parseInt(Event.element(event).getAttribute("userData"), 10);
//                    this._constructCalendar();
//                    this._popDownMonth();
//                    Event.stop(event);
//                }.bindAsEventListener(this), false);
                //HIS_FIX_END

                this._appendNbsp(monthCell);
                monthCell.appendChild(sNameNode);
                this._appendNbsp(monthCell);
            }

            this.monthConstructed = true;
        }
    };

    org.apache.myfaces.PopupCalendar.prototype._popUpMonth = function () {
        this._constructMonth()
        this._fixPopupDomOrder(this.selectMonthDiv);
        this.selectMonthDiv.style.visibility = (this.dom || this.ie6) ? "visible" : "show";
        this.selectMonthDiv.style.left = parseInt(this._formatInt(this.calendarDiv.style.left), 10) + 50 + "px";
        this.selectMonthDiv.style.top = parseInt(this._formatInt(this.calendarDiv.style.top), 10) + 26 + "px";

        this._showPopupPostProcess(this.selectMonthDiv);
    };

    org.apache.myfaces.PopupCalendar.prototype._popDownMonth = function () {
        this.selectMonthDiv.style.visibility = "hidden";
        this._hidePopupPostProcess(this.selectMonthDiv);
    };

    /*** Year Pulldown ***/

    org.apache.myfaces.PopupCalendar.prototype._incYear = function () {
        for (var i = 0; i < 7; i++) {
            var newYear = (i + this.nStartingYear) + 1;

            this._createAndAddYear(newYear, i);
        }
        this.nStartingYear++;
        this.bClickOnCalendar = true;
    };

    org.apache.myfaces.PopupCalendar.prototype._createAndAddYear = function (newYear, i) {
        var parentNode = document.getElementById(this.containerCtl.getAttribute("id") + "y" + i);

        this._removeAllChildren(parentNode);

        if (newYear == this.selectedDate.year) {
            this._appendNbsp(parentNode);
            var newYearSpan = document.createElement("span");
            newYearSpan.setAttribute("userData", newYear);
            newYearSpan.appendChild(document.createTextNode(newYear));
            parentNode.appendChild(newYearSpan);
            this._appendNbsp(parentNode);
        }
        else {
            this._appendNbsp(parentNode);
            parentNode.appendChild(document.createTextNode(newYear));
            this._appendNbsp(parentNode);
        }

        parentNode.setAttribute("userData", newYear);
    };

    org.apache.myfaces.PopupCalendar.prototype._decYear = function () {
        for (i = 0; i < 7; i++) {
            var newYear = (i + this.nStartingYear) - 1;

            this._createAndAddYear(newYear, i);
        }
        this.nStartingYear--;
        this.bClickOnCalendar = true;
    };

    org.apache.myfaces.PopupCalendar.prototype._constructYear = function () {
        this._popDownMonth();
        var sHTML = "";
        if (!this.yearConstructed) {

            var selectYearTable = document.createElement("table");
            //HIS_FIX_BEGIN
            jQuery(selectYearTable).css({
            	"width": "44px",
            	"border-collapse": "collapse"
            });
//            Element.setStyle(selectYearTable, "width:44px;border-collapse:collapse;");
            //HIS_FIX_END
            selectYearTable.className = this.initData.themePrefix + "-dropdown-style";

            this._removeAllChildren(this.selectYearDiv);

            this.selectYearDiv.appendChild(selectYearTable);
            
            //HIS_FIX_BEGIN
            var that = this;
            jQuery(selectYearTable).on("mouseover", function(event){
                clearTimeout(that.timeoutID2);
            });
//            Event.observe(selectYearTable, "mouseover", function (event) {
//                clearTimeout(this.timeoutID2);
//            }.bind(this), false);
            
            jQuery(selectYearTable).on("mouseout", function(event){
            	clearTimeout(that.timeoutID2);
            	that.timeoutID2 = setTimeout((function () {
            		that._popDownYear()
            	}).bind(this), 100);
            	event.preventDefault();
                event.stopPropagation();
            });
//            Event.observe(selectYearTable, "mouseout", function (event) {
//                clearTimeout(this.timeoutID2);
//                this.timeoutID2 = setTimeout((function () {
//                    this._popDownYear()
//                }).bind(this), 100);
//                Event.stop(event);
//            }.bindAsEventListener(this), false);
            //HIS_FIX_END

            var selectYearTableBody = document.createElement("tbody");
            selectYearTable.appendChild(selectYearTableBody);

            var selectYearRowMinus = document.createElement("tr");
            selectYearTableBody.appendChild(selectYearRowMinus);

            var selectYearCellMinus = document.createElement("td");
            selectYearCellMinus.setAttribute("align", "center");

            selectYearCellMinus.appendChild(document.createTextNode("-"));

            selectYearRowMinus.appendChild(selectYearCellMinus);

            //HIS_FIX_BEGIN
            jQuery(selectYearCellMinus).on("mouseover", function(event){
            	event.target.className = that.initData.themePrefix + "-dropdown-select-style";
            });
//            Event.observe(selectYearCellMinus, "mouseover", function (event) {
//                Event.element(event).className = this.initData.themePrefix + "-dropdown-select-style";
//            }.bindAsEventListener(this), false);

            jQuery(selectYearCellMinus).on("mouseout", function(event){
            	 clearInterval(that.intervalID1);
            	 event.target.className = that.initData.themePrefix + "-dropdown-normal-style";            
            });
//            Event.observe(selectYearCellMinus, "mouseout", function (event) {
//                clearInterval(this.intervalID1);
//                Event.element(event).className = this.initData.themePrefix + "-dropdown-normal-style";
//            }.bindAsEventListener(this), false);

            
            jQuery(selectYearCellMinus).on("mousedown touchstart", function(event){
            	clearInterval(that.intervalID1);
            	that.intervalID1 = setInterval((function () {
            		that._decYear();
                }).bind(this), 30);
            	event.preventDefault();
                event.stopPropagation();
            });
//            Event.observe(selectYearCellMinus, "mousedown", function (event) {
//                clearInterval(this.intervalID1);
//                this.intervalID1 = setInterval((function () {
//                    this._decYear();
//                }).bind(this), 30);
//                Event.stop(event);
//            }.bindAsEventListener(this), false);
            
            jQuery(selectYearCellMinus).on("mouseup touchend", function(event){
            	clearInterval(that.intervalID1);
            	event.preventDefault();
                event.stopPropagation();
            });
//            Event.observe(selectYearCellMinus, "mouseup", function (event) {
//                clearInterval(this.intervalID1);
//                Event.stop(event);
//            }.bindAsEventListener(this), false);
            //HIS_FIX_END

            //sHTML = "<tr><td align='center' onmouseover='this.className=\""+this.initData.themePrefix+"-dropdown-select-style\"' onmouseout='clearInterval(this.intervalID1); this.className=\""+this.initData.themePrefix+"-dropdown-normal-style\"' onmousedown='clearInterval(this.intervalID1);this.intervalID1=setInterval(\"_decYear()\",30)' onmouseup='clearInterval(this.intervalID1)'>-</td></tr>";

            this.nStartingYear = this.selectedDate.year - 3;
            var j = 0;
            for (i = this.selectedDate.year - 3; i <= (this.selectedDate.year + 3); i++) {
                var sName = i;

                var sNameNode = null;

                if (i == this.selectedDate.year) {
                    sNameNode = document.createElement("span");
                    //HIS_FIX_BEGIN
                    jQuery(sNameNode).css("font-weight", "bold");
//                    Element.setStyle(sNameNode, "font-weight:bold;");
                    //HIS_FIX_END
                    sNameNode.appendChild(document.createTextNode(sName));
                    sNameNode.setAttribute("userData", sName);
                }
                else {
                    sNameNode = document.createTextNode(sName);
                }

                var yearRow = document.createElement("tr");
                selectYearTableBody.appendChild(yearRow);

                var yearCell = document.createElement("td");
                yearCell.setAttribute("userData", sName);
                yearCell.setAttribute("id", this.containerCtl.getAttribute("id") + "y" + j);
                yearRow.appendChild(yearCell);

                //HIS_FIX_BEGIN
                jQuery(yearCell).on("mouseover", function(event){
                	event.target.className = that.initData.themePrefix + "-dropdown-select-style";
                });
//                Event.observe(yearCell, "mouseover", function (event) {
//                    Event.element(event).className = this.initData.themePrefix + "-dropdown-select-style";
//                }.bind(this), false);

                jQuery(yearCell).on("mouseout", function(event){
                	event.target.className = that.initData.themePrefix + "-dropdown-normal-style";
                });
//                Event.observe(yearCell, "mouseout", function (event) {
//                    Event.element(event).className = this.initData.themePrefix + "-dropdown-normal-style";
//                }.bind(this), false);

                jQuery(yearCell).on("click", function(event){
                	var elem = event.target;
                	var sYear = null;
                	that.selectedDate.year = parseInt(that._formatInt(elem.getAttribute("userData"), 10));
                	that.yearConstructed = false;
                	that._popDownYear();
                	that._constructCalendar();
                	event.preventDefault();
                	event.stopPropagation();
                });
//                Event.observe(yearCell, "click", function (event) {
//                    var elem = Event.element(event);
//                    var sYear = null;
//                    this.selectedDate.year = parseInt(this._formatInt(elem.getAttribute("userData"), 10));
//                    this.yearConstructed = false;
//                    this._popDownYear();
//                    this._constructCalendar();
//                    Event.stop(event);
//                }.bindAsEventListener(this), false);
                //HIS_FIX_END

                this._appendNbsp(yearCell);
                yearCell.appendChild(sNameNode);
                this._appendNbsp(yearCell);
                j++;
            }

            var selectYearRowPlus = document.createElement("tr");
            selectYearTableBody.appendChild(selectYearRowPlus);

            var selectYearCellPlus = document.createElement("td");
            selectYearCellPlus.setAttribute("align", "center");

            selectYearCellPlus.appendChild(document.createTextNode("+"));

            selectYearRowPlus.appendChild(selectYearCellPlus);
            
            //HIS_FIX_BEGIN
            jQuery(selectYearCellPlus).on("mouseover", function(event){
            	event.target.className = that.initData.themePrefix + "-dropdown-select-style";
            });
//            Event.observe(selectYearCellPlus, "mouseover", function (event) {
//                Event.element(event).className = this.initData.themePrefix + "-dropdown-select-style";
//            }.bindAsEventListener(this), false);

            jQuery(selectYearCellPlus).on("mouseout", function(event){
            	 clearInterval(that.intervalID2);
            	 event.target.className = that.initData.themePrefix + "-dropdown-normal-style";
            });
//            Event.observe(selectYearCellPlus, "mouseout", function (event) {
//                clearInterval(this.intervalID2);
//                Event.element(event).className = this.initData.themePrefix + "-dropdown-normal-style";
//            }.bindAsEventListener(this), false);

            jQuery(selectYearCellPlus).on("mousedown touchstart", function(event){
            	 clearInterval(that.intervalID2);
            	 that.intervalID2 = setInterval((function () {
            		 that._incYear();
                 }).bind(this), 30);
            });
//            Event.observe(selectYearCellPlus, "mousedown", function (event) {
//                clearInterval(this.intervalID2);
//                this.intervalID2 = setInterval((function () {
//                    this._incYear();
//                }).bind(this), 30);
//            }.bindAsEventListener(this), false);

            jQuery(selectYearCellPlus).on("mouseup touchend", function(event){
                clearInterval(that.intervalID2);
            });
//            Event.observe(selectYearCellPlus, "mouseup", function (event) {
//                clearInterval(this.intervalID2);
//            }.bindAsEventListener(this), false);
            //HIS_FIX_END

            this.yearConstructed = true;
        }
    };

    org.apache.myfaces.PopupCalendar.prototype._popDownYear = function () {
        clearInterval(this.intervalID1);
        clearTimeout(this.timeoutID1);
        clearInterval(this.intervalID2);
        clearTimeout(this.timeoutID2);
        this.selectYearDiv.style.visibility = "hidden";
        this._hidePopupPostProcess(this.selectYearDiv);
    };

    org.apache.myfaces.PopupCalendar.prototype._popUpYear = function () {
        var leftOffset;
        this._fixPopupDomOrder(this.selectYearDiv);
        this._constructYear();
        this.selectYearDiv.style.visibility = (this.dom || this.ie6) ? "visible" : "show";
        leftOffset = parseInt(this._formatInt(this.calendarDiv.style.left), 10) + this.yearSpan.offsetLeft;
        if (this.ie6)
            leftOffset += 6;
        this.selectYearDiv.style.left = leftOffset + "px";
        this.selectYearDiv.style.top = parseInt(this._formatInt(this.calendarDiv.style.top), 10) + 26 + "px";

        this._showPopupPostProcess(this.selectYearDiv);
    };

    org.apache.myfaces.PopupCalendar.prototype._appendCell = function (parentElement, value) {
        var cell = document.createElement("td");
        //HIS_FIX_BEGIN
        jQuery(cell).css("text-align", "right");
//        Element.setStyle(cell, "text-align:right;");
        //HIS_FIX_END

        if (value && value != "") {
            cell.appendChild(document.createTextNode(value));
        }
        else {
            this._appendNbsp(cell);
        }

        parentElement.appendChild(cell);
    };

    org.apache.myfaces.PopupCalendar.prototype._getDateStyle = function (datePointer) {
        var sStyle = this.initData.themePrefix + "-normal-day-style";
        //regular day

        if ((datePointer == this.dateNow) &&
                (this.selectedDate.month == this.monthNow) && (this.selectedDate.year == this.yearNow)) //today
        {
            sStyle = this.initData.themePrefix + "-current-day-style";
        }
        else if (this.dayPointer % 7 == (this.initData.startAt * -1) + 1) //end-of-the-week day
        {
            sStyle = this.initData.themePrefix + "-end-of-weekday-style";
        }

        //selected day
        if ((datePointer == this.saveSelectedDate.date) &&
                (this.selectedDate.month == this.saveSelectedDate.month) &&
                (this.selectedDate.year == this.saveSelectedDate.year)) {
            sStyle += " " + this.initData.themePrefix + "-selected-day-style";
        }

        for (k = 0; k < this.holidaysCounter; k++) {
            if ((parseInt(this._formatInt(this.holidays[k].d), 10) == datePointer) && (parseInt(this._formatInt(this.holidays[k].m), 10) == (this.selectedDate.month + 1))) {
                if ((parseInt(this._formatInt(this.holidays[k].y), 10) == 0) || ((parseInt(this._formatInt(this.holidays[k].y), 10) == this.selectedDate.year) && (parseInt(this._formatInt(this.holidays[k].y), 10) != 0))) {
                    sStyle += " " + this.initData.themePrefix + "-holiday-style";
                }
            }
        }

        return sStyle;
    };

    org.apache.myfaces.PopupCalendar.prototype._getHolidayHint = function (datePointer) {
        var sHint = "";
        for (k = 0; k < this.holidaysCounter; k++) {
            if ((parseInt(this._formatInt(this.holidays[k].d), 10) == datePointer) && (parseInt(this._formatInt(this.holidays[k].m), 10) == (this.selectedDate.month + 1))) {
                if ((parseInt(this._formatInt(this.holidays[k].y), 10) == 0) || ((parseInt(this._formatInt(this.holidays[k].y), 10) == this.selectedDate.year) && (parseInt(this._formatInt(this.holidays[k].y), 10) != 0))) {
                    sHint += sHint == "" ? this.holidays[k].desc : "\n" + this.holidays[k].desc;
                }
            }
        }

        return sHint;
    };

    org.apache.myfaces.PopupCalendar.prototype._addWeekCell = function (currentRow, startDate, weekSelectable, sNormalStyle, sSelectStyle) {
        var cell = document.createElement("td");
        //HIS_FIX_BEGIN
        jQuery(cell).css("text-align", "right");
//        Element.setStyle(cell, "text-align:right;");
        //HIS_FIX_END
        
        var weekDate = this.stdDateFormatter.getWeekDate(startDate);
        if (weekSelectable) {
            var link = document.createElement("a");
            link.className = sNormalStyle;
            link.sNormalStyle = sNormalStyle;
            link.sSelectStyle = sSelectStyle;
            link.setAttribute("href", "#");
            link.appendChild(document.createTextNode(weekDate.week + " "));

            link.dateObj = this.stdDateFormatter.getDateForWeekDate(weekDate);

            cell.appendChild(link);

            //HIS_FIX_BEGIN
            var that = this;
            jQuery(link).on("mousemove", function(event){
            	 window.status = that.initData.selectDateMessage.replace(
                         "[date]",
                         that._constructDate(link.dateObj));
            });
//            Event.observe(link, "mousemove", function (event) {
//                window.status = this.initData.selectDateMessage.replace(
//                        "[date]",
//                        this._constructDate(link.dateObj));
//            }.bindAsEventListener(this), false);

            jQuery(link).on("mouseout", function(event){
            	   var elem = event.target;
                   elem.className = elem.sNormalStyle;
                   window.status = "";
            });
//            Event.observe(link, "mouseout", function (event) {
//                var elem = Event.element(event);
//                elem.className = elem.sNormalStyle;
//                window.status = "";
//            }.bindAsEventListener(this), false);

            jQuery(link).on("click", function(event){
            	var elem = event.target;
            	that.selectedDate.year = elem.dateObj.getFullYear();
            	that.selectedDate.month = elem.dateObj.getMonth();
            	that.selectedDate.date = elem.dateObj.getDate();
            	that._closeCalendar();
            	event.preventDefault();
            	event.stopPropagation();
            });
//            Event.observe(link, "click", function (event) {
//                var elem = Event.element(event);
//                this.selectedDate.year = elem.dateObj.getFullYear();
//                this.selectedDate.month = elem.dateObj.getMonth();
//                this.selectedDate.date = elem.dateObj.getDate();
//                this._closeCalendar();
//                Event.stop(event);
//            }.bindAsEventListener(this), false);

            jQuery(link).on("mouseover", function(event){
	           	var elem = event.target;
	            elem.className = elem.sSelectStyle;
            });
//            Event.observe(link, "mouseover", function (event) {
//                var elem = Event.element(event);
//                elem.className = elem.sSelectStyle;
//            }.bindAsEventListener(this), false);
            //HIS_FIX_END
        }
        else {
            var span = document.createElement("span");
            span.className = sNormalStyle;
            span.appendChild(document.createTextNode(weekDate.week + " "));
            cell.appendChild(span);
        }

        currentRow.appendChild(cell);
    };

    org.apache.myfaces.PopupCalendar.prototype._constructCalendar = function () {
        var aNumDays = Array(31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

        var dateMessage;
        var startDate = new Date(this.selectedDate.year, this.selectedDate.month, 1);
        var numDaysInMonth = null;

        if (this.selectedDate.month == 1) {
            // to compute the number of days in february, select first day of march,
            // subtract 24 hours then query the day-of-the-month.
            var msecs = new Date(this.selectedDate.year, this.selectedDate.month + 1, 1).getTime();
            var endDate = new Date(msecs - this._MSECS_PER_DAY);
            numDaysInMonth = endDate.getDate();
        }
        else {
            numDaysInMonth = aNumDays[this.selectedDate.month];
        }

        this.datePointer = 0;
        this.dayPointer = startDate.getDay() - this.initData.startAt;

        if (this.dayPointer < 0)
            this.dayPointer = 6;

        this._removeAllChildren(this.contentSpan);

        var contentTable = document.createElement("table");
        //HIS_FIX_BEGIN
        jQuery(contentTable).css("border", "0px");
//        Element.setStyle(contentTable, "border:0px;");
        //HIS_FIX_END
        contentTable.className = this.initData.themePrefix + "-body-style";

        this.contentSpan.appendChild(contentTable);

        var contentBody = document.createElement("tbody");
        contentTable.appendChild(contentBody);

        var contentRow = document.createElement("tr");
        contentBody.appendChild(contentRow);

        if (this.initData.showWeekNumber == 1) {
            var showWeekNumberCell = document.createElement("td");
            //HIS_FIX_BEGIN
            jQuery(showWeekNumberCell).css({
            	"width": "27px",
            	"font-weight": "bold"
            });
//            Element.setStyle(showWeekNumberCell, "width:27px;font-weight:bold;");
            //HIS_FIX_END

            contentRow.appendChild(showWeekNumberCell);

            showWeekNumberCell.appendChild(document.createTextNode(this.initData.weekString));

            var dividerCell = document.createElement("td");
            //HIS_FIX_BEGIN
            jQuery(dividerCell).css("width", "1px");
//            Element.setStyle(dividerCell, "width:1px;");
            //HIS_FIX_END
            if (this.ie6) //fix for https://issues.apache.org/jira/browse/TOMAHAWK-1184
                dividerCell.setAttribute("rowSpan", "7");
            else
                dividerCell.setAttribute("rowspan", "7");
            dividerCell.className = this.initData.themePrefix + "-weeknumber-div-style";

            contentRow.appendChild(dividerCell);

            var dividerImg = document.createElement("img");
            dividerImg.setAttribute("src", this.initData.imgDir + "divider.gif" + this.initData.imgDirSuffix);
            //HIS_FIX_BEGIN
            jQuery(dividerImg).css("width", "1px");
//            Element.setStyle(dividerImg, "width:1px;");
            //HIS_FIX_END
            dividerCell.appendChild(dividerImg);
        }

        for (i = 0; i < 7; i++) {
            var dayNameCell = document.createElement("td");
            //HIS_FIX_BEGIN
            jQuery(dayNameCell).css({
            	"width": "27px",
            	"text-align": "right",
            	"font-weight": "bold"
            });
//            Element.setStyle(dayNameCell, "width:27px;text-align:right;font-weight:bold;");
            //HIS_FIX_END
            contentRow.appendChild(dayNameCell);

            dayNameCell.appendChild(document.createTextNode(this.initData.dayName[i]));
        }

        var currentRow = document.createElement("tr");
        contentBody.appendChild(currentRow);

        var weekSelectable = this._isWeekSelectable();
        var sWeekNormalStyle = this.initData.themePrefix + "-normal-week-style";
        var sWeekSelectStyle = sWeekNormalStyle + " " + this.initData.themePrefix + "-would-be-selected-week-style";

        if (this.initData.showWeekNumber == 1) {
            this._addWeekCell(currentRow, startDate, weekSelectable, sWeekNormalStyle, sWeekSelectStyle);
        }

        for (var i = 1; i <= this.dayPointer; i++) {
            this._appendCell(currentRow);
        }

        for (this.datePointer = 1; this.datePointer <= numDaysInMonth; this.datePointer++) {
            this.dayPointer++;
            var dateCell = document.createElement("td");
            //HIS_FIX_BEGIN
            jQuery(dateCell).css("text-align", "right");
//            Element.setStyle(dateCell, "text-align:right;");
            //HIS_FIX_END
            
            currentRow.appendChild(dateCell);

            var sStyle = this._getDateStyle(this.datePointer);
            var sHint = this._getHolidayHint(this.datePointer);

            var sSelectStyle = sStyle + " " + this.initData.themePrefix + "-would-be-selected-day-style";
            var sNormalStyle = sStyle;

            if (this._isDaySelectable()) {

                var dateLink = document.createElement("a");
                dateLink.className = sStyle;
                dateLink.setAttribute("href", "#");
                dateLink.setAttribute("title", sHint);

                dateLink.sNormalStyle = sNormalStyle;
                dateLink.sSelectStyle = sSelectStyle;
                dateLink.datePointer = this.datePointer;

                dateCell.appendChild(dateLink);
                
                //HIS_FIX_BEGIN
                var that = this;
                jQuery(dateLink).on("mousemove", function(event){
                    window.status = that.initData.selectDateMessage.replace("[date]", that._constructDate(this.datePointer, that.selectedDate.month, that.selectedDate.year));
                });
//                Event.observe(dateLink, "mousemove", function (event) {
//                    window.status = this.initData.selectDateMessage.replace("[date]", this._constructDate(this.datePointer, this.selectedDate.month, this.selectedDate.year));
//                }.bindAsEventListener(this), false);
                
                jQuery(dateLink).on("mouseout", function(event){
                	var elem = event.target;
                    elem.className = elem.sNormalStyle;
                    window.status = "";
                });
//                Event.observe(dateLink, "mouseout", function (event) {
//                    var elem = Event.element(event);
//                    elem.className = elem.sNormalStyle;
//                    window.status = "";
//                }.bindAsEventListener(this), false);
                
                jQuery(dateLink).on("click", function(event){
                	var elem = event.target;
                	that.selectedDate.date = elem.datePointer;
                	that._closeCalendar();
                	event.preventDefault();
                	event.stopPropagation();
                });
//                Event.observe(dateLink, "click", function (event) {
//                    var elem = Event.element(event);
//                    this.selectedDate.date = elem.datePointer;
//                    this._closeCalendar();
//                    Event.stop(event);
//                }.bindAsEventListener(this), false);
                
                jQuery(dateLink).on("mouseover", function(event){
                	var elem = event.target;
                    elem.className = elem.sSelectStyle;
                });
//                Event.observe(dateLink, "mouseover", function (event) {
//                    var elem = Event.element(event);
//                    elem.className = elem.sSelectStyle;
//                }.bindAsEventListener(this), false);
                //HIS_FIX_END

                this._appendNbsp(dateLink);
                dateLink.appendChild(document.createTextNode(this.datePointer));
                this._appendNbsp(dateLink);
            }
            else {
                var dateSpan = document.createElement("span");
                dateCell.appendChild(dateSpan);

                dateSpan.appendChild(document.createTextNode(this.datePointer));
                dateSpan.className = sStyle;
                dateSpan.setAttribute("title", sHint);
            }

            if ((this.dayPointer + this.initData.startAt) % 7 == this.initData.startAt) {
                currentRow = document.createElement("tr");
                contentBody.appendChild(currentRow);

                if ((this.initData.showWeekNumber == 1) && (this.datePointer < numDaysInMonth)) {
                    var startDate = new Date(this.selectedDate.year, this.selectedDate.month, this.datePointer + 1);
                    this._addWeekCell(currentRow, startDate, weekSelectable, sWeekNormalStyle, sWeekSelectStyle);
                }
            }
        }

        this._removeAllChildren(this.monthSpan);

        this._appendNbsp(this.monthSpan);
        this.monthSpan.appendChild(document.createTextNode(this.initData.monthName[this.selectedDate.month]));
        this._appendNbsp(this.monthSpan);

        this.changeMonthImg = document.createElement("img");
        this.changeMonthImg.setAttribute("src", this.initData.imgDir + "drop1.gif" + this.initData.imgDirSuffix);
        this.changeMonthImg.setAttribute("width", "12px");
        this.changeMonthImg.setAttribute("height", "10px");
        //HIS_FIX_BEGIN
        jQuery(that.changeMonthImg).css("border", "0px");
//        Element.setStyle(this.changeMonthImg, "border:0px;");
        //HIS_FIX_END

        this.monthSpan.appendChild(this.changeMonthImg);

        // Year dropdown list (YYYY plus dropdown icon)
        this._removeAllChildren(this.yearSpan);
        this._appendNbsp(this.yearSpan);
        this.yearSpan.appendChild(document.createTextNode(this.selectedDate.year));
        this._appendNbsp(this.yearSpan);
        this.changeYearImg = document.createElement("img");
        this.changeYearImg.setAttribute("src", this.initData.imgDir + "drop1.gif" + this.initData.imgDirSuffix);
        this.changeYearImg.setAttribute("width", "12px");
        this.changeYearImg.setAttribute("height", "10px");
        //HIS_FIX_BEGIN
        jQuery(that.changeYearImg).css("border", "0px");
//        Element.setStyle(this.changeYearImg, "border:0px;");
        //HIS_FIX_END
        this.yearSpan.appendChild(this.changeYearImg);

        // Accept Month icon
        if (this.acceptMonthSpan) {
            this._removeAllChildren(this.acceptMonthSpan);
            var acceptMonthImg = document.createElement("img");
            acceptMonthImg.setAttribute("src", this.initData.imgDir + "accept.gif" + this.initData.imgDirSuffix);
            acceptMonthImg.setAttribute("width", "15px");
            acceptMonthImg.setAttribute("height", "13px");
            //HIS_FIX_BEGIN
            jQuery(acceptMonthImg).css("border", "0px");
//            Element.setStyle(acceptMonthImg, "border:0px;");
            //HIS_FIX_END
            acceptMonthImg.setAttribute("alt", "Accept the current month selection");
            this.acceptMonthSpan.appendChild(acceptMonthImg);
        }

        // Close Popup icon
        this._removeAllChildren(this.closeCalendarSpan);
        var closeButtonImg = document.createElement("img");
        closeButtonImg.setAttribute("src", this.initData.imgDir + "close.gif" + this.initData.imgDirSuffix);
        closeButtonImg.setAttribute("width", "15px");
        closeButtonImg.setAttribute("height", "13px");
        //HIS_FIX_BEGIN
        jQuery(closeButtonImg).css("border", "0px");
//        Element.setStyle(closeButtonImg, "border:0px;");
        //HIS_FIX_END
        closeButtonImg.setAttribute("alt", "Close the calendar");
        this.closeCalendarSpan.appendChild(closeButtonImg);

        this._recalculateElement(this.calendarDiv);
    };

    org.apache.myfaces.PopupCalendar.prototype._popUpCalendar = function (ctl, ctl2, format) {
        if (!this.bPageLoaded) {
            // The user has clicked a button before the initialisation of this
            // class has completed. Just ignore the click.. 
            return;
        }

        if (this.calendarDiv.style.visibility == "hidden") {
            this.ctlToPlaceValue = ctl2;
            this.dateFormat = format;

            this.stdDateFormatter = new org.apache.myfaces.dateformat.SimpleDateFormatter(
                    this.dateFormat, this.dateFormatSymbols, this.initData.startAt);
            var dateSelected = this.stdDateFormatter.parse(ctl2.value);

            if (dateSelected) {
                this.selectedDate.sec = dateSelected.getSeconds();
                this.selectedDate.min = dateSelected.getMinutes();
                this.selectedDate.hour = dateSelected.getHours();
                this.selectedDate.date = dateSelected.getDate();
                this.selectedDate.month = dateSelected.getMonth();

                //https://issues.apache.org/jira/browse/TOMAHAWK-1595
                //http://de.selfhtml.org/javascript/objekte/date.htm#get_year
                var fullYear = dateSelected.getFullYear;
                var yearDetermined = parseInt(((fullYear) ? dateSelected.getFullYear() : dateSelected.getYear()), 10);

                if (!fullYear && yearDetermined < 1000) {
                    yearDetermined = yearDetermined + 1900;
                }

                this.selectedDate.year = yearDetermined;
            }
            else {
                this.selectedDate.date = this.dateNow;
                this.selectedDate.month = this.monthNow;
                this.selectedDate.year = this.yearNow;
            }

            this._popUpCalendar_Show(ctl);
        }
        else {
            this._hideCalendar();
            if (this.ctlNow != ctl) {
                this._popUpCalendar(ctl, ctl2, format);
            }
        }
        this.ctlNow = ctl;
    };

    org.apache.myfaces.PopupCalendar.prototype._popUpCalendarForInputDate = function (clientId, format) {
        if (this.bPageLoaded) {
            this.myFacesCtlType = "x:inputDate";
            this.myFacesInputDateClientId = clientId;
            this.dateFormat = format;

            //Init stdDateFormatter
            this.stdDateFormatter = new org.apache.myfaces.dateformat.SimpleDateFormatter(
                    this.dateFormat, this.dateFormatSymbols, this.initData.startAt);

            this.selectedDate.date = document.getElementById(clientId + ".day").value != "" ? parseInt(this._formatInt(document.getElementById(clientId + ".day").value), 10) : this.dateNow;
            this.selectedDate.month = document.getElementById(clientId + ".month").value != "-1" ? parseInt(this._formatInt(document.getElementById(clientId + ".month").value), 10) - 1 : this.monthNow;
            this.selectedDate.year = document.getElementById(clientId + ".year").value != "" ? parseInt(this._formatInt(document.getElementById(clientId + ".year").value), 10) : this.yearNow;
            this.ctlNow = document.getElementById(clientId + ".day");
            this._popUpCalendar_Show(document.getElementById(clientId + ".day"));
        }
    };

    org.apache.myfaces.PopupCalendar.prototype._getStyle = function (ctl, property) {
        var value = null;

        // local style
        if (ctl.style[property]) {
            value = ctl.style[property];
        }
        // IE syntax
        else if (ctl.currentStyle && ctl.currentStyle[property]) {
            value = ctl.currentStyle[property];
        }
        // DOM syntax
        else if (document.defaultView && document.defaultView.getComputedStyle) {
            var computed = document.defaultView.getComputedStyle(ctl, '');

            if (computed && computed.getPropertyValue(property)) {
                value = computed.getPropertyValue(property);
            }
        }
        return value;
    };

    org.apache.myfaces.PopupCalendar.prototype._popUpCalendar_Show = function (ctl) {
        this.saveSelectedDate.date = this.selectedDate.date;
        this.saveSelectedDate.month = this.selectedDate.month;
        this.saveSelectedDate.year = this.selectedDate.year;

        var leftpos = 0;
        var toppos = 0;

        var aTag = ctl;
        var aCSSPosition = null;
        var aTagPositioningisAbsolute = false;
        // Added try-catch to the next loop (MYFACES-870)
        try {

            do {
                aTag = aTag.offsetParent;
                leftpos += aTag.offsetLeft;
                toppos += aTag.offsetTop;
            }
            while ((null != aTag.offsetParent ) && ('undefined' != aTag.offsetParent ));
        }
        catch (ex) {
            // ignore
        }

        var leftScrollOffset = 0;
        var topScrollOffset = 0;

        aTag = ctl;
        // Added try-catch (MYFACES-870)
        try {
            do {
                if ('undefined' != typeof(aTag.scrollLeft) && null != aTag.scrollLeft)
                    leftScrollOffset += parseInt(aTag.scrollLeft);
                if ('undefined' != typeof(aTag.scrollTop) && null != aTag.scrollTop)
                    topScrollOffset += parseInt(aTag.scrollTop);

                aTag = aTag.parentNode;
            }
            while ((aTag.tagName.toUpperCase() != "BODY") && (aTag.tagName.toUpperCase() != "HTML"));
            //while ('undefined' != typeof(aTag) && null != aTag);
        }
        catch (ex) {
            // ignore
        }
        var bodyRect = this._getVisibleBodyRectangle();
        var cal = this.calendarDiv;

        var top = 0;
        var left = 0

        top = ctl.offsetTop + toppos - topScrollOffset + ctl.offsetHeight + 2;
        left = ctl.offsetLeft + leftpos - leftScrollOffset;

        if (this.initData.popupLeft) {
            left -= cal.offsetWidth;
        }

        if (left + cal.offsetWidth > bodyRect.right) {
            left = bodyRect.right - cal.offsetWidth;
        }
        if (top + cal.offsetHeight > bodyRect.bottom) {
            top = bodyRect.bottom - cal.offsetHeight;
        }
        if (left < bodyRect.left) {
            left = bodyRect.left;
        }
        if (top < bodyRect.top) {
            top = bodyRect.top;
        }

        /*we have to remap the popup so that we can handle the positioning in a neutral way*/
        if (this.calendarDiv.parentNode != document.body) {
            this.calendarDiv.parentNode.removeChild(this.calendarDiv);
            document.body.appendChild(this.calendarDiv);
        }

        this.calendarDiv.style.left = this.initData.fixedX == -1 ? left + "px" : this.initData.fixedX;
        this.calendarDiv.style.top = this.initData.fixedY == -1 ? top + "px" : this.initData.fixedY;
        this._constructCalendar(1, this.selectedDate.month, this.selectedDate.year);

        this.calendarDiv.style.visibility = (this.dom || this.ie6) ? "visible" : "show";
        this.bCalendarHidden = false;

        setTimeout((function () {
            this._showPopupPostProcess(this.calendarDiv);
        }).bind(this), 200);

        this._showPopupPostProcess(this.calendarDiv);

        this.bClickOnCalendar = true;
    };

    org.apache.myfaces.PopupCalendar.prototype._getVisibleBodyRectangle = function () {
        var visibleRect = new org.apache.myfaces.Rectangle();

        if (typeof window.pageYOffset != "undefined") {
            //Most non IE
            visibleRect.top = window.pageYOffset;
            visibleRect.left = window.pageXOffset;
        }
        else if (document.body && document.body.scrollTop) {
            //IE 6 strict mode
            visibleRect.top = document.body.scrollTop;
            visibleRect.left = document.body.scrollLeft;
        }
        else if (document.documentElement && document.documentElement.scrollTop) {
            //Older IE
            visibleRect.top = document.documentElement.scrollTop;
            visibleRect.left = document.documentElement.scrollLeft;
        }

        if (window.innerWidth != undefined) {
            //Most non-IE
            visibleRect.right = visibleRect.left + window.innerWidth;
            visibleRect.bottom = visibleRect.top + window.innerHeight;
        }
        else if (document.documentElement && document.documentElement.clientHeight) {
            //IE 6 strict mode
            visibleRect.right = visibleRect.left + document.documentElement.clientWidth;
            visibleRect.bottom = visibleRect.top + document.documentElement.clientHeight;
        }
        else if (document.body && document.body.clientHeight) {
            //IE 4 compatible
            visibleRect.right = visibleRect.left + document.body.clientWidth;
            visibleRect.bottom = visibleRect.top + document.body.clientHeight;
        }
        return visibleRect;
    };

    org.apache.myfaces.PopupCalendar.prototype._formatInt = function (str) {

        if (typeof str == 'string') {

            //truncate 0 for number less than 10
            if (str.charAt && str.charAt(0) == "0") { // <----- Change, added str.charAt for method availability detection (MYFACES)
                return str.charAt(1);
            }

        }
        return str;

    };

    org.apache.myfaces.Rectangle = function() {
        this.top = 0;
        this.left = 0;
        this.bottom = 0;
        this.right = 0;
    };

}    
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/**
 * @author Bruno Aranda (latest modification by $Author: dziegielewski#his.de $)
 * @version $Revision: 1.3 $ $Date: 2016/04/18 11:50:34 $
 */

window.org = window.org || {};
org.apache = org.apache || {};
org.apache.myfaces = org.apache.myfaces || {};

if (!org.apache.myfaces.Picklist) {
    org.apache.myfaces.Picklist = {};

// moves all the items to the selected list
    org.apache.myfaces.Picklist.addAllToSelected = function (availableListId, selectedListId, hiddenId) {
        var availableList = document.getElementById(availableListId);
        var selectedList = document.getElementById(selectedListId);

        org.apache.myfaces.Picklist.moveAll(availableList, selectedList, hiddenId);
        org.apache.myfaces.Picklist.updateHidden(selectedList, hiddenId);
    };

// removes all the items from the selected list
    org.apache.myfaces.Picklist.removeAllFromSelected = function (availableListId, selectedListId, hiddenId) {
        var availableList = document.getElementById(availableListId);
        var selectedList = document.getElementById(selectedListId);

        org.apache.myfaces.Picklist.moveAll(selectedList, availableList, hiddenId);
        org.apache.myfaces.Picklist.updateHidden(selectedList, hiddenId);
    };

// moves an item to the selected list
    org.apache.myfaces.Picklist.addToSelected = function (availableListId, selectedListId, hiddenId) {
        var availableList = document.getElementById(availableListId);
        var selectedList = document.getElementById(selectedListId);

        org.apache.myfaces.Picklist.move(availableList, selectedList, hiddenId);
        org.apache.myfaces.Picklist.updateHidden(selectedList, hiddenId);
    };

// removes an item from the selected list
    org.apache.myfaces.Picklist.removeFromSelected = function (availableListId, selectedListId, hiddenId) {
        var availableList = document.getElementById(availableListId);
        var selectedList = document.getElementById(selectedListId);

        org.apache.myfaces.Picklist.move(selectedList, availableList, hiddenId);
        org.apache.myfaces.Picklist.updateHidden(selectedList, hiddenId);
    };

    org.apache.myfaces.Picklist.move = function (fromList, toList, hiddenId) {
        // Return, if no items selected
        var selectedIndex = fromList.selectedIndex;
        if (selectedIndex < 0) {
            return;
        }

        var tLen = toList.options.length;
        // Decremental loop, so the index is not affected in the moves
        for (var i = fromList.options.length - 1; i >= 0; i--) {
            if (fromList.options[i].selected) {
                toList.options.add(new Option(fromList.options[i].text),tLen);
                toList.options[tLen].value = fromList.options[i].value;
                fromList.options[i] = null;
            }
        }
    };

    org.apache.myfaces.Picklist.moveAll = function (fromList, toList, hiddenId) {

    	var tLen = toList.options.length;
        // Decremental loop, so the index is not affected in the moves
        for (var i = fromList.options.length - 1; i >= 0; i--) {
            toList.options.add(new Option(fromList.options[i].text),tLen);
            toList.options[tLen].value = fromList.options[i].value;
            fromList.options[i] = null;
        }
    };

// Selection - invoked on submit
    org.apache.myfaces.Picklist.updateHidden = function(selectedList, hiddenId) {
        var hiddenField = document.getElementById(hiddenId);

        var arrValues = new Array(selectedList.options.length);
        for (var i = 0; i < selectedList.options.length; i++) {
            arrValues[i] = selectedList.options[i].value;
        }
        //https://issues.apache.org/jira/browse/TOMAHAWK-1653
        //we set a neutral divider string, which allows
        //comma and other dividiers to be used
        hiddenField.value = arrValues.join("|MFVAL_DIV|");
    };
}use_package('de.his.component');
/**
* Iframe sichtbar machen, wenn der Inhalt fertig ist.
* Bis dahin wird ein Warte-Icon angezeigt
* 
* @autor wassmann@his.de, wahrendorff@his.de
*/


/**
 * Funktionen ausführen, wenn die Seite fertig geladen ist
 */
de.his.modules.IframeVisibility = new function() {
    de.his.modules.ModuleRegistry
    	.registerModule(this)
    	.registerAjaxRefreshModule(this);
    
    this.moduleName = "de.his.modules.IframeVisibility";

    this.init = function() {
    
		jQuery('.frameWrapper-behavior > iframe').each(function(){
    		var iFrame = jQuery(this);
    		if(!iFrame.attr('initialized')){
    			
        		iFrame.attr('initialized','true');
        		//console.log("iFrame initialized.. ", iFrame);
        		
        		iFrame.on("load", function() {
        			//console.log("iFrame remove loadingAnimation event.. ", id);
        			iFrame.siblings(".loadingAnimationContainer").remove();
        			iFrame.siblings(".frameloaderBackground").remove();
        		
        			// reload portlet periodically
	        		var iframeWrapper = iFrame.parent();
	        		var reload = iframeWrapper.data("portlet-reload");
	        		if(reload !== false){
	        			setReloadTimer(reload, iFrame);
	        		}
        		});
    		} else {
    			console.log("iFrame already initialized.. ",iFrame.attr("id"));
    			
    			iFrame.on("load", function() {
    				// might need to be removed again when sitting in a lazy loaded collapesible Filedset
    				iFrame.siblings(".loadingAnimationContainer").remove();
        			iFrame.siblings(".frameloaderBackground").remove();
    			});
    		}
    		// Check if loading was complete before we set the load event 
			var iframeDoc = iFrame[0].contentDocument || iFrame[0].contentWindow.document;
		    if (  iframeDoc.readyState  == 'complete' ) {
		    	iFrame.siblings(".loadingAnimationContainer").remove();
    			iFrame.siblings(".frameloaderBackground").remove();
		    }
    	});
    	
    };
    
    var setReloadTimer = function(reload, iFrame){
    	setTimeout(function() {
    		console.log("refreshing iFrame "+iFrame.attr('id'));
    		iFrame.attr('src', iFrame.parent().data('src'));
    		setReloadTimer(reload,iFrame);
        }, reload);
    }

    this.refresh = function() {
        this.init();
    };

};
use_package('de.his.modules');
/**
* Portlets die in einem IFrame laufen sollen sich automatisch in der
* Höhe anpassen
* 
* @author wassmann@his.de
* @author wahrendorff@his.de
*/

/**
 * Funktionen ausführen, wenn die Seite fertig geladen ist
 */
de.his.modules.IframePortletResize = new function() {
	de.his.modules.ModuleRegistry
		.registerModule(this)
		.registerAjaxRefreshModule(this);
	
	this.moduleName = "de.his.modules.IframePortletResize";
	
	var self = this;
	
	this.init = function() {
		console.log("IframePortletResize init");
		this.handleEvents();
    };
    
    this.refresh = function() {
    	self.handleResizeWithPortalHelper();
    };
    
    this.handleEvents = function (){
//    	console.log("IframePortletResize handleEvents");
    	
    	this.handleResizeWithPortalHelper();
    	this.handleWindowResizeEvent();
    	
    	//this.handleAjaxLoading(); // perfect!
    	    	
    }
    
    this.handleWindowResizeEvent = function(){
    	jQuery(window).resize(function(){
    		self.handleResizeWithPortalHelper();
    	});
    }
    
    this.handleResizeWithPortalHelper = function(){
    	console.log("handleResizeWithPortalHelper");
    	jQuery("iframe").each(function(index){
    		var $iframe = jQuery(this);
    		var autoResize = $iframe.parent().data("portlet-auto-resize");
    		console.log("handleResizeWithPortalHelper Autoresize? " + autoResize);
    		
    		if($iframe.parent().hasClass('frameWrapper') && autoResize){
    			
    			
    			// keine iFramePortlets von fremden Seiten resizen
    			try{
    				var host = de.his.common.ContextInformation.get("host");
    				var urlParts = host.split(":");
    				var serverUrl = urlParts[0]+":"+urlParts[1];
    				console.log("host is: "+serverUrl);
    				if($iframe.attr('src').startsWith(serverUrl)){
    					console.log(serverUrl+" is local url...");
    					local = true;
    				}else{
    					// keine iFramePortlets von fremden Seiten resizen
    					if(!$iframe.hasClass('fullIframePage')){
    						local = false;
    						console.log("IframePortletResize "+$iframe.attr( "id" )+" wird nicht resized.");
    						return;
    					}
    				}
    			}catch(e){
    				// IE < 12
    				var host = de.his.common.ContextInformation.get("host");
    				if($iframe.attr('src').substr(0,host.length) === host){
    					local = true;
    				}else{
    					if(!$iframe.hasClass('fullIframePage')){
							local = false;
							return;
						}
    				}
    				
    			}
    			
    			console.log("IframePortletResize resize "+$iframe.attr( "id" ));
    			
    			if( $iframe.data( "his-iframe-loaded" ) ) {
    				if(autoResize){
        				$iframe.css("height","");
        			}
    				//portaHelper.js function
     	            resizeIt( $iframe );
     	        } else {
     	        	de.his.modules.eventRegistry.destroyEvent( "iframe_loaded_" + $iframe.attr( "id" ));
     	            de.his.modules.eventRegistry.addListener( "iframe_loaded_" + $iframe.attr( "id" ), function() {
     	            	if(autoResize){
     	    				$iframe.css("height","");
     	    			}
     	            	//portaHelper.js function
     	                resizeIt( $iframe );
     	                $iframe.data( "his-iframe-loaded", true );
     	            } );  
     	            // Check if loading was complete before we set the load event 
					var iframeDoc = $iframe[0].contentDocument || $iframe[0].contentWindow.document;
				    if (  iframeDoc.readyState  == 'complete' ) {
				    	if(autoResize){
     	    				$iframe.css("height","");
     	    			}
     	            	//portaHelper.js function
     	                resizeIt( $iframe );
     	                $iframe.data( "his-iframe-loaded", true );
				    }
     	        }
    		}
    	});
    };
    
    /**
     * START EXPERIMENTAL AJAX LOADING OF PORTLETS (WORKING!)
     */
    
//    this.handleAjaxLoading = function(){
//    	console.log("load iframe with ajax...");
//    	// load iFrame via AJAX.
//    	jQuery(".frameWrapper").each(function(index){
//    		
//    		var elem = jQuery(this);
//    		var autoResize = elem.data("portlet-auto-resize");
//    		var portletReload = elem.data("portlet-reload"); // data-portlet-reload="900000"
//    		
//    		if(!autoResize || typeof autoResize === 'undefined'){
//    			elem.css('height','460px');
//    			elem.css('overflow-x','auto');
//    		}
//    		self.loadPortlet(elem);
//    		
//    		// TODO: reload mechanism
//    		
//    	});
//    };
//    
//    this.loadPortlet = function(wrapperElement){
//    	var url = wrapperElement.data("src");
//    	jQuery.ajax({
//			type: 'GET',
//			url: url,
//			success : function(response){
//				// only use body content
//				var data = response.replace('<body', '<body><div id="fakebody"').replace('</body>','</div></body>');
//				var body = jQuery(data).filter('#fakebody');
//				wrapperElement.html(body);
//				console.log("Successful loaded portlet.");
//			}, 
//			error : function(response,b,c){
//				console.error("Error loading Portlet with ID "+wrapperElement.attr('id')+": " + c);
//			}
//		}); 
//    }
    
    /**
     * END EXPERIMENTAL AJAX LOADING OF PORTLETS (WORKING!)
     */
};
window.org=window.org||{};org.apache=org.apache||{};org.apache.myfaces=org.apache.myfaces||{};if(!org.apache.myfaces.Tree){org.apache.myfaces.Tree=function(){};org.apache.myfaces.Tree.treeNavClick=function(F,L,H,G,K,I,C,J,D){var E=document.getElementById(F);var M=E.style.display;if(M=="none"){M="block";org.apache.myfaces.CookieLib.setCookieAttrib(J,D,"x");}else{M="none";org.apache.myfaces.CookieLib.setCookieAttrib(J,D,"c");}E.style.display=M;if(L!=""){var B=document.getElementById(L);if(B.src.indexOf(H)>=0){B.src=G;}else{B.src=H;}}if(K!=""){var A=document.getElementById(K);if(A.src.indexOf(I)>=0){A.src=C;}else{A.src=I;}}};}window.org=window.org||{};org.apache=org.apache||{};org.apache.myfaces=org.apache.myfaces||{};if(!org.apache.myfaces.CookieLib){org.apache.myfaces.CookieLib=function(){};org.apache.myfaces.CookieLib.COOKIE_DELIM=";";org.apache.myfaces.CookieLib.COOKIE_KEYVAL="=";org.apache.myfaces.CookieLib.ATTRIB_DELIM=";";org.apache.myfaces.CookieLib.ATTRIB_KEYVAL="=";org.apache.myfaces.CookieLib.getRawCookie=function(C){var B=org.apache.myfaces.CookieLib;var D=C+B.COOKIE_KEYVAL;if(document.cookie){if(document.cookie.length>0){var E=document.cookie.indexOf(D);if(E!=-1){E+=D.length;var A=document.cookie.indexOf(B.COOKIE_DELIM,E);if(A==-1){A=document.cookie.length;}return unescape(document.cookie.substring(E,A));}}}return null;};org.apache.myfaces.CookieLib.setCookieAttrib=function(E,C,A){var B=org.apache.myfaces.CookieLib;var D=B.getCookie(E);D[C]=A;B.setCookie(E,D);};org.apache.myfaces.CookieLib.getCookieAttrib=function(D,B){var A=org.apache.myfaces.CookieLib;var C=A.getCookie(D);return C[B];};org.apache.myfaces.CookieLib.getCookie=function(H){var E=org.apache.myfaces.CookieLib;var G=new Array();var B=E.getRawCookie(H);if(typeof (B)!="undefined"&&B!=null){var C=B.split(E.ATTRIB_DELIM);for(var D=0;D<C.length;D++){var F=C[D].indexOf(E.ATTRIB_KEYVAL);var A=C[D].substring(0,F);var I=C[D].substring(F+1);G[A]=I;}}return G;};org.apache.myfaces.CookieLib.setCookie=function(F,E){var B=org.apache.myfaces.CookieLib;var D="";for(var A in E){var C=E[A];if(typeof (C)!="undefined"&&C!=null&&C!=""&&typeof (C)!="function"){if(A.indexOf(B.ATTRIB_KEYVAL)<0&&C.indexOf(B.ATTRIB_KEYVAL)<0&&A.indexOf(B.ATTRIB_DELIM)<0&&C.indexOf(B.ATTRIB_DELIM)<0){D+=((D=="")?"":B.ATTRIB_DELIM);D+=(A+B.ATTRIB_KEYVAL+C);}else{alert("Cookie attribute name and/or value contains a delimeter ("+B.ATTRIB_KEYVAL+" or "+B.ATTRIB_DELIM+").");}}}document.cookie=F+B.COOKIE_KEYVAL+escape(D);};}use_package("de.his.validation");

/**
 * Initialisiert die clientseitige Validierung via Parsley.js
 * Zu validierende Felder werden durch .parsleyValidation erkannt. Zusätzlich ist eine CSS Klasse am Feld gesetzt, welche den Namen
 * des entsprechenden Validators enthält. Dieser Name wird geparst und via dat- Attribut an das Feld geschrieben.
 * FIXME Ein setzen der data- Attribute via ApplyMetaData wäre schöner, jedoch hat das nicht überall funktioniert 
 * (wie zB klenke/klenke!, rolle: gebührenadmin, navigation Begründete Antragstypen bearbeiten, beliebiges Element bearbeiten, Auf der 
 * Detailseite in der unteren Tabelle "Absoluter Betrag, Minimal, Maximal" werden eigentlich validiert)
 * 
 * Hier werden auch die Klassen bei Fehler/Erfolg gesetzt:
 * Fehler, am Input: validation-failed inputError
 * Fehler, am Label: labelError
 * Erfolg, am Input: validation-passed
 * Erolg, am Label: keine!
 * 
 */

de.his.validation.initParsleyValidation = new function() {
    de.his.modules.ModuleRegistry
    	.registerModule(this)
    	.registerAjaxRefreshModule(this);

    this.moduleName = "de.his.validation.initParsleyValidation";

    var self = this;

    this.init = function() {
    	this.initValidation();
    	this.setParsleyLocale();
    }

    //Am refresh Modul regestrieren, damit auch Felder validiert werden, welche durch AJAX hinzukommen!
    this.refresh = function() {
    	this.init();
    }

    this.initValidation = function () {
		jQuery('.parsleyValidation').each(function() {
			var field = jQuery(this);
			var validatorId = self.getValidationIdentifier(field);
			field.attr("data-parsley-" + validatorId, "");
			var form = field.closest("form")

			if (form && form.attr('data-validataion-enabled') && !form.attr('data-initialized-parsley')) {
				// die tatsächliche technische Initialisierung des Formulars erfolgt hier. Hier kann auch die Konfiguration 
				// der Validierung erfolgen (wann soll Validierung ausgelöst werden, welche Klassen sollen gesetzt werden usw...)
				form.parsley({
					trigger: "focusout",
					triggerAfterFailure: "input",
					errorsMessagesDisabled: true,
					successClass:	"validation-passed",
					errorClass:	"validation-failed inputError",
					errorsWrapper: '<div></div>',
					errorTemplate: '<div class="errortext"></div>',
					errorsContainer: function (field) {
						//Damit sagen wir parsley, dass die Fehlermeldung an das Elternelement des Felds gehängt werden soll.
						// Sonst wird es direkt hinter das Feld gehängt, wodurch Hilfe/Info Buttons sich verschieben!
						return self.findCorrectParent(field.$element);
					}
				});
				
				// Wenn eine Validierung fehlschlägt, soll das label des Feldes eine entsprechende Klasse erhalten
				// FIXME Aktuell hat parsley.js hier noch keine Möglichkeit das direkt zu stylen, vielleicht in Zukunft?
				jQuery(form).parsley().on('field:error', function (fieldInstance) {
					var fieldId = fieldInstance.$element.attr("id");
					var label = document.getElementById(fieldId + "Label");
					if (label && !label.classList.contains('labelError')) {
						label.classList.add('labelError');
					}

					/*
					 * Fehlermeldungen werden hier manuell angezeigt. Dadurch ist es uns möglich den Namen des Labels
					 * vor die Fehlermeldung zu schreiben.
					 */
					var parent = self.findCorrectParent(fieldInstance.$element);
					var fieldErrorElement = jQuery(parent).find('.errortext');
					if (!fieldErrorElement.length) {
						var fieldMessages = fieldInstance.getErrorsMessages();
						if (fieldMessages) {
							var labelText = "";
							if (label) {
								labelText = label.innerText + ": ";
							}
							var msg = labelText + fieldMessages;
							fieldInstance.addError('fieldError', {message: msg, assert: true, updateClass: true});
						}
					}
				});
				
				// Wird ein Fehler vom Nutzer korrigiert, soll das Label keine Fehler Klasse mehr haben.
				jQuery(form).parsley().on('field:success', function (fieldInstance) {
					var fieldId = fieldInstance.$element.attr("id");
					var label = document.getElementById(fieldId + "Label");
					if (label && label.classList.contains('labelError')) {
						label.classList.remove('labelError');
					}
					// weil wir die Fehlermeldungen manuell anzeigen, müssen diese auch manuell wieder entfernt werden!
					fieldInstance.removeError("fieldError", {updateClass: true});
				});
				
				// Formular als initialisiert markieren.
				form.attr("data-initialized-parsley", "true");
			}
		});
    }

    /**
     *   Suche die in den Eltern Elementen nach einen übegreifenden Container, welcher auch Hilfe Buttons usw enthält. 
     *   Dieser wird dann genutzt um die Fehlermeldung anzuhängen. Sonst werden Hilfe Buttons usw. verschoben!
     */
    this.findCorrectParent = function(fieldInstance) {
    	var parent;
		var parentTagName;

		// Suche die in den Eltern Elementen nach einen übegreifenden Container, welcher auch 
		// Hilfe Buttons usw enthält. Dieser wird dann genutzt um die Fehlermeldung anzuhängen. Sonst
		// werden Hilfe Buttons usw. verschoben!
		for (var i = 0; i < 3; i++) {
			parent = fieldInstance.parent();
			parentTagName = parent[0].tagName;
			if (parentTagName.toLowerCase() == "div" || parentTagName.toLowerCase() == "td") {
				return parent;
			}

			fieldInstance = parent;
		}
    }

    /**
     * Parst aus den CSS Klassen des Feldes den Namen des Validators für dieses Feld. Die entsprechende CSS Klasse wurde
     * zuvor von ApplyMetadata auf dem Server gesetzt.
     */
    this.getValidationIdentifier = function(field) {
    	var classes = field.attr("class");
		var classArr = classes.split(" ");
		var arrayLength = classArr.length;
		//FIXME aktuell wird eine CSS Klasse .parsleyValidation_VALIDATORIDENTIFIER gesetzt. Mit String Operationen wird hier der 
		//Identifier bestimmt. Geht das evtl. eleganter?
		for (var i = 0; i < arrayLength; i++) {
			var currentStr = classArr[i];
			if (currentStr && currentStr.startsWith("parsleyValidation_")) {
				var currentStrArr = currentStr.split("_", 2);
				if (currentStrArr.length > 1) {
					return currentStrArr[1];
				}
			}
		}
    };

    /**
     * Setzt das aktuelle locale in Parsley. Dadurch werden dann später die korrekten Fehlermeldungen der Validierung 
     * angezeigt.
     */
    this.setParsleyLocale = function() {
    	var lang = de.his.common.LanguageHelper.currentLanguage();
    	if (lang == "de") {
    		Parsley.setLocale("de");
    	} else {
    		Parsley.setLocale("en");
    	}
    };
};
// Validation errors messages for Parsley
// Load this after Parsley

Parsley.addMessages('de', {
  defaultMessage: "Die Eingabe scheint nicht korrekt zu sein.",
  type: {
    email:        "Die Eingabe muss eine gültige E-Mail-Adresse sein.",
    url:          "Die Eingabe muss eine gültige URL sein.",
    number:       "Die Eingabe muss eine Zahl sein.",
    integer:      "Die Eingabe muss eine Zahl sein.",
    digits:       "Die Eingabe darf nur Ziffern enthalten.",
    alphanum:     "Die Eingabe muss alphanumerisch sein."
  },
  notblank:       "Die Eingabe darf nicht leer sein.",
  required:       "Dies ist ein Pflichtfeld.",
  pattern:        "Die Eingabe scheint ungültig zu sein.",
  min:            "Die Eingabe muss größer oder gleich %s sein.",
  max:            "Die Eingabe muss kleiner oder gleich %s sein.",
  range:          "Die Eingabe muss zwischen %s und %s liegen.",
  minlength:      "Die Eingabe ist zu kurz. Es müssen mindestens %s Zeichen eingegeben werden.",
  maxlength:      "Die Eingabe ist zu lang. Es dürfen höchstens %s Zeichen eingegeben werden.",
  length:         "Die Länge der Eingabe ist ungültig. Es müssen zwischen %s und %s Zeichen eingegeben werden.",
  mincheck:       "Wählen Sie mindestens %s Angaben aus.",
  maxcheck:       "Wählen Sie maximal %s Angaben aus.",
  check:          "Wählen Sie zwischen %s und %s Angaben.",
  equalto:        "Dieses Feld muss dem anderen entsprechen."
});

//FIXME das setLocale sollte wahrscheinlich eher in die initParsleyValidation.js und auch variable sein, abhängig vom aktuellem locale.
//Parsley.setLocale('de');
/**
 * Author: masala@his.de
 * 
 * device.js (below) must be included before this file
 * https://github.com/matthewhudson/device.js
 * 
 * note: 
 * 	add ?deviceDetails=true to URL in order to print device height and width
 * 
 */


(function(){
	
	if(!navigator.cookieEnabled){
		console.info("cookies must be enabled");
		return false;
	}
	
	var forceDeviceSessionName = "hisforcedevice";
	var actualDeviceSessionName = "hisactualdevice";
	
	//output the device height and width if the URL contains ?deviceDetails=true
	var urlParam = de.his.common.Util.getQueryParam("deviceDetails"),
		actualDevice = window.sessionStorage.getItem(actualDeviceSessionName),
		forcedDevice = window.sessionStorage.getItem(forceDeviceSessionName);
	
	if(urlParam == "true"){
		//print the width and height of device
		alert(window.innerWidth + " x " + window.innerHeight);
	}
	
	if(forcedDevice){
		//TODO: following replaces all classes with {mobile|tablet|desktop|etc} - what about "ios mobile portrait" etc
		jQuery("html").attr("class", forcedDevice);
	}
	
	if(!device.desktop() && forcedDevice != "desktop"){
		jQuery("a.forceDeviceLink[device-data='desktop']").css("display", "block");
	}else if(actualDevice){
		//if actual device has been set in the sessionStorage - then allow a return back to the actual device
		jQuery("a.forceDeviceLink[device-data=" + actualDevice + "]").css("display", "block");
	}
	

	//function used to disable responsive design when user clicks the desired link
	jQuery("a.forceDeviceLink").on("click", function(){
		
		//device.js
		var ad, //actual device
			url = window.location.href,
			forceDevice = jQuery(this).attr("device-data"),
			forceDeviceUrl = "wantDevice=" + forceDevice,
			currentParam = de.his.common.Util.getQueryParam( "wantDevice" );
		
		if(device.desktop()){
			ad = "desktop";
		}else if(device.mobile()){
			ad = "mobile";
		}else if(device.tablet()){
			ad = "tablet";
		}
		
		//save the device to force to - i.e. desktop
		window.sessionStorage.setItem(forceDeviceSessionName, forceDevice);
		//save the actual device - i.e mobile
		window.sessionStorage.setItem(actualDeviceSessionName, ad);
		
		
		if(currentParam){
			//replace anyting in url already
			url = url.replace("wantDevice="+currentParam, forceDeviceUrl);
		}else{
			url = url + (url.indexOf("?") >= 0 ? "&" + forceDeviceUrl : "?" + forceDeviceUrl);
			//url = url + "&device=desktop";
		}
		
		window.location = url;
	});

	
})();/**
* masala@his.de
* by setting custom or predefined (img-xs, img-l) media queries this plugin with change the image to fit the current viewport in a responsive manner.
*  
* usage: 	<img data-sizes="img-xs, img-s, img-m, img-l, img-xl" 
*				 data-srcset="http://placehold.it/60%26text=xs,
*							  http://placehold.it/60%26text=s,
*							  http://placehold.it/60%26text=m,
*							  http://placehold.it/60%26text=l,
*							  http://placehold.it/60%26text=xl" />
*
* note: if two sizes are a match then the first wins.
* 
* possible sizes:
* 	
* 	"img-xs": "(max-width:767px)",
*	"img-s": "(max-width:991px)",
*	"img-m": "(max-width:1199px)",
*	"img-l": "(max-width:1920px)",
*	"img-xl": "(min-width : 1921px)"
*
* 
*/

(function(){
	
	var presets = {
			"img-xs": "(max-width:767px)",
			"img-s": "(max-width:991px)",
			"img-m": "(max-width:1199px)",
			"img-l": "(max-width:1920px)",
			"img-xl": "(min-width : 1921px)"
	}
	
	var imgs = jQuery("img[data-srcset]");
	
	var reponsiveImages = function(){
		imgs.hide();	//hide all images
		var sizes = [], img = {}, src = [], media, size;
		//first iterate through all the image tags that were found
		for(var i = 0, l = imgs.length; i<l; i++){
			img = jQuery(imgs[i]);
			sizes = img.attr("data-sizes").split(",");
			src = img.attr("data-srcset").split(",");
			//per image tag, iterate through the sizes defined in each tag
			for(var ii = 0, ll = sizes.length;ii<ll; ii++){
				size = sizes[ii].trim();
				//if the size is defined using a preset such as img-xs or img-l - convert it to the corresponding media query
				if(size.indexOf("img-") >= 0){
					media = presets[size];
				}else{
					//preset wasn't used but a direct media query
					media = size;
				}
				console.info(media, window.matchMedia(media));
				if(window.matchMedia(media).matches){
					//set the correct src url and show the correct image
					img.attr("src", src[ii].trim());
					img.show();	
					return;
				}
			}
		}
		
	}
	
	//auto recall when windows changes size
	jQuery(window).resize(reponsiveImages);
	
	//initial call
	reponsiveImages();
	
})();/*!
 * @author Steven Masala [me@smasala.com]
 * Github: https://github.com/smasala/responsive-tables-js
 * @license MIT https://tldrlegal.com/license/mit-license
 * Responsive Tables
 * @version 0.1.5
 *
 * usage: give any table you want to work responsively, the CSS class "responsive".
 */

( function( root, factory ) {
    "use strict";
    
    if ( typeof define === "function" && define.amd ) {
        define( [ "jquery" ], function( $ ) {
            return factory( root, root.document, $ );
        } );
    } else {
        return factory( root, root.document, root.jQuery );
    }

} )( this, function( window, document, $ ) {
    "use strict";
    
    if ( window.responsiveTables ) {
        console.error( "window.responsiveTables is already defined globally", window.responsiveTables );
        return;
    }

    var responsiveTables = {

        version: "0.1.5",

        titleTpl: function( data ) {
            return "<span data-type='responsive'>" + data + "</span>";
        },

        /**
         * @method init
         * @param selector {String} optional - pass if you wish to update tables that do not meet the selector: table.responsive
         * @param force {Boolean} [default=false] - optional - set true to reiterate over previous converted tables
         */
        init: function( selector, force ) {
            var me = this,
                tables = $( selector ? selector : "table.responsive" ),
                table, ths, th, trs, tds, td, text, it; //for later

            if ( tables.length > 0 ) {

                for ( var i = 0, l = tables.length; i < l; i++ ) {
                    //iterate over each table
                    table = $( tables[ i ] );
                    if ( table.attr( "data-type" ) && !force ) {
                        //ignore this table
                        continue;
                    }
                    table.attr( "data-type", "responsive" );
                    //get all the table header for the give table
                    ths = table.find( "th" );
                    trs = table.find( "tr" );
                    //iterate over all trs
                    for ( var ii = 0, ll = trs.length; ii < ll; ii++ ) {
                        //find tds and iterate
                        tds = $( trs[ ii ] ).find( "td" );
                        for ( var iii = 0, lll = tds.length; iii < lll; iii++ ) {
                            //for each td - find the correct heading
                            th = ths[ iii ];
                            it = $( tds[ iii ] );
                            //get the text content
                            text = th.textContent || text.innerText || "";
                            if ( force ) {
                                it.find( "span[data-type='responsive']" ).remove();
                            }
                            //prepend td with the correct template
                            td = it.prepend( me.titleTpl( text ) );
                        }
                    }
                }
            }
        }

    };
    
    //define globally
    window.responsiveTables = responsiveTables;
    return responsiveTables;
} );use_package("de.his.component.ResponsiveTables");
/**
* Author:masala@his.de
* Plugin/helper for tables to make them more responsive
*/
//overlayOpen

de.his.component.ResponsiveTables = new function() {
	
    de.his.modules.ModuleRegistry
    .registerModule(this)
    .registerAjaxRefreshModule(this);
    
	this.moduleName = "de.his.component.ResponsiveTables";
 
    this.init = function(){
    	var tables = jQuery("table.table:not(.disableResponsiveLabels):not([data-responsive=true])");

    	var table, ths, trs;
    	for(var x = 0, xl = tables.length; x<xl; x++){
    		table = jQuery(tables[x]);
    		table.attr("data-responsive", true);
    		//find tableHeaders
    		ths = table.find("> thead > tr > th"); //.css("display", "none");
    		//table rows in the body of the table
    		trs = table.find("> tbody > tr");
    		
    		var tds = [], 
    			label,
    			th, td;
    		
    		for(var i = 0, l = trs.length; i<l; i++){
    			tds = jQuery(trs[i]).find("> td");
    			for(var ii = 0, ll = tds.length; ii<ll; ii++){
    				td = tds[ii];
    				th = ths[ii];
    				if(th){
    					// innerHTML damit auch HTML Elemente, wie Popup Buttons angezeigt werden können!
    					label = th.innerHTML;
    					jQuery(td).prepend("<span data-type='responsive'>" + label + "</span>").find('[id*="filterSelectOneMenu"], [id*="filterInput"], [id*="resetFilter"], [id*="filterRefresh"], [class*="headerExtSelectOneMenu"]').remove();
    					/** inline-table requires content of the td will collapse (used for responsive tables) **/ 
    					if(!jQuery(td).html()){
    						jQuery(td).html("&nbsp;");
    					}
    				}
    				
    			}
    		}
    	}
    };
    
    this.refresh = this.init;
    
};

/*
 * alert.js - javascript alert replacement v2.4
 *
 * (c) 2009-2011 Naden Badalgogtapeh - http://www.naden.de/blog/javascript-alert
 *
 */

// Datei wurde angepasst, um den Top wert nicht zu setzen, da er die Alert-box ausßerhalb des sichtbaren Bereichs anzeigt.
// Alert box wird nun anhand unseres CSS's positioniert. Zum Finden des auskommentieren Codes Suche in der Datei nach: A.style.top

window.alert=function(){var H=2.4;var D={button_title:"OK",callback:function(){},left:-1,top:-1,width:-1,height:-1,modal:true,timeout:0};if(arguments.length==2&&typeof arguments[1]=="object"){D=J(arguments[1],D)}else{if(arguments.length==3){D=J(arguments[2],D)}}window.alert_callback=D.callback;if(arguments.length==1||(arguments.length==2&&typeof arguments[1]!="string")){arguments=["",arguments[0]]}var A=document.getElementById("alert");if(A){document.body.removeChild(A)}if(D.modal){var F=document.createElement("DIV");F.id="alert-modal";F.className="alert-modal";document.body.appendChild(F)}A=document.createElement("DIV");A.id=A.className="alert";document.body.appendChild(A);A.innerHTML=(arguments[0]==""?"":'<div class="title">'+arguments[0]+"</div>")+'<div class="body">'+arguments[1]+'</div><div class="button"><a href="" onclick="var _m3423=document.getElementById(\'alert-modal\');if(_m3423)document.body.removeChild(_m3423);document.body.removeChild(document.getElementById(\'alert\'));alert_callback();return false;">'+D.button_title+"</a></div>";var B=G(),K=Math.max(I(arguments[0]),I(arguments[1]))*6,C=0,E=0;if(D.width==-1){D.width=K}else{C=D.width;K=0}if(D.left==-1){D.left=parseInt((B[0]+B[2]-K-C)/2)}A.style.display="block";if(D.top==-1){D.top=parseInt(((B[1]+B[3]-(D.height==-1?0:(D.height/2)))/2)-(A.pixelHeight||A.offsetHeight))}A.style.width=D.width+"px";if(D.height>0){A.style.height=D.height+"px"}/*A.style.left=D.left+"px";A.style.top=D.top+50+"px";*/function J(M,L){for(var N in L){if(N in M){continue}M[N]=L[N]}return M}function I(O){var P=O.split("<br />");if(P.length<=1){P=O.split("<br>")}if(P.length<=1){return O.replace(/<(?:.|\s)*?>/g,"").length}var L=0;for(var N=0;N<P.length;N++){var M=P[N].replace(/<(?:.|\s)*?>/g,"");if(M.length>L){L=M.length}}return L}function G(){var M=0,N=0,L=0,O=0;if(typeof window.innerWidth=="number"){M=window.innerWidth;N=window.innerHeight}else{if(document.documentElement&&(document.documentElement.clientWidth||document.documentElement.clientHeight)){M=document.documentElement.clientWidth;N=document.documentElement.clientHeight}else{if(document.body&&(document.body.clientWidth||document.body.clientHeight)){M=document.body.clientWidth;N=document.body.clientHeight}}}if(typeof window.pageYOffset=="number"){O=window.pageYOffset;L=window.pageXOffset}else{if(document.body&&(document.body.scrollLeft||document.body.scrollTop)){O=document.body.scrollTop;L=document.body.scrollLeft}else{if(document.documentElement&&(document.documentElement.scrollLeft||document.documentElement.scrollTop)){O=document.documentElement.scrollTop;L=document.documentElement.scrollLeft}}}return[L,O,M,N]}}; 'use strict';

use_package("de.his.component");

de.his.component.PrimeFacesSelectOneMenu = new function() {
    de.his.modules.ModuleRegistry
        .registerModule(this)
        .registerAjaxRefreshModule(this);
	this.moduleName = "de.his.component.PrimeFacesSelectOneMenu";
	const setAriaActivedescendant = true;
	const setAriaOwns = true;
	
    this.init = function() {
    	if (window.PrimeFaces) {
    	    PrimeFaces.widget.SelectOneMenu();
			PrimeFaces.animationEnabled = false;
    	}
    }
    this.refresh = function() {
        this.init();
    };
    	
    if (window.PrimeFaces) {
    	/// START PrimeFaces-Komponente ///    	
		PrimeFaces.widget.SelectOneMenu = PrimeFaces.widget.DeferredWidget.extend({
		
			/**
			 * @override
			 * @inheritdoc
		     * @param {PrimeFaces.PartialWidgetCfg<TCfg>} cfg
			 */
		    init: function(cfg) {
		        this._super(cfg);
		
		        this.panelId = this.jqId + '_panel';
		        this.input = $(this.jqId + '_input');
		        this.focusInput = $(this.jqId + '_focus');
		        this.label = this.jq.find('.ui-selectonemenu-label');
		
		        this.panel = $(this.panelId);
		        this.disabled = this.jq.hasClass('ui-state-disabled');
		        this.itemsWrapper = this.panel.children('.ui-selectonemenu-items-wrapper');
		        this.options = this.input.find('option');
		        this.cfg.effect = this.cfg.effect||'fade';
		
		        this.cfg.effectSpeed = this.cfg.effectSpeed||'normal';
		        this.cfg.autoWidth = this.cfg.autoWidth === false ? false : true;
		        this.cfg.dynamic = this.cfg.dynamic === true ? true : false;
		        this.cfg.appendTo = PrimeFaces.utils.resolveAppendTo(this, this.panel);
		        this.cfg.renderPanelContentOnClient = this.cfg.renderPanelContentOnClient === true;
		        this.isDynamicLoaded = false;
		
		        if(this.cfg.dynamic || (this.itemsWrapper.children().length === 0)) {
		            var selectedOption = this.options.filter(':selected'),
		            labelVal = this.cfg.editable ? this.label.val() : selectedOption.text();
		
		            this.setLabel(labelVal);
		        }
		        else {
		            this.initContents();
		            this.bindItemEvents();
		        }
		
		        //triggers
    	        this.triggers = this.jq.find(".ui-selectonemenu-label");
		
		        //mark trigger and descandants of trigger as a trigger for a primefaces overlay
		        this.triggers.data('primefaces-overlay-target', true).find('*').data('primefaces-overlay-target', true);
		
		        if(!this.disabled) {
		           this.bindEvents();

		           this.transition = PrimeFaces.utils.registerCSSTransition(this.panel, 'ui-connected-overlay');
		        }
		
		        // see #7602
		        if (PrimeFaces.env.isTouchable(this.cfg)) {
		            this.focusInput.attr('readonly', true);
		        }
		
		       //this.renderDeferred();
		       //this._render(); // this.renderDeferred ist eine Performancebremse (durch den Zugriff auf :visible) und bei uns scheinbar unnötig
		    },
		
		    /**
		     * Finds and initializes the DOM elements that make up this widget.
		     * @private
		     */
		    initContents: function() {
		        this.itemsContainer = this.itemsWrapper.children('.ui-selectonemenu-items');
		        this.items = this.itemsContainer.find('.ui-selectonemenu-item');
		        this.optGroupsSize = this.itemsContainer.children('li.ui-selectonemenu-item-group').length;
				this.itemsWithGroup = this.itemsContainer.find(".ui-selectonemenu-item, .ui-selectonemenu-item-group");
				
		        var $this = this,
		        selectedOption = this.options.filter(':selected'),
		        highlightedItem = this.items.eq(this.options.index(selectedOption));
		
		        //disable options
		        this.options.filter(':disabled').each(function() {
		            $this.items.eq($(this).index()).addClass('ui-state-disabled');
		        });
		
		        //activate selected
		        if(this.cfg.editable) {
		            var customInputVal = this.label.val();
		
		            //predefined input
		            if(customInputVal === selectedOption.text()) {
		                this.highlightItem(highlightedItem);
		            }
		            //custom input
		            else {
		                this.items.eq(0).addClass('ui-state-highlight');
		                this.customInput = true;
		                this.customInputVal = customInputVal;
		            }
		        }
		        else {
		            this.highlightItem(highlightedItem);
		        }
		
		        if(this.cfg.syncTooltip) {
		            this.syncTitle(selectedOption);
		        }
		
		        //pfs metadata
		        this.input.data(PrimeFaces.CLIENT_ID_DATA, this.id);
		
		        //for Screen Readers
		        for(var i = 0; i < this.items.length; i++) {
		            this.items.eq(i).attr('id', this.id + '_' + i);
		        }
		
		        var highlightedItemId = highlightedItem.attr('id');
		        this.jq.attr('aria-owns', this.itemsContainer.attr('id'));
		        this.focusInput.attr('aria-autocomplete', 'list')
		            .attr('aria-activedescendant', highlightedItemId)
		            .attr('aria-describedby', highlightedItemId)
		            .attr('aria-disabled', this.disabled);
		        this.itemsContainer.attr('aria-activedescendant', highlightedItemId);
		    },
		
		    /**
		     * @include
		     * @override
		     * @protected
		     * @inheritdoc
		     */
		    _render: function() {
		        var contentStyle = this.jq.attr('style'),
		        hasWidth = contentStyle && contentStyle.indexOf('width') != -1;
		
		        if(this.cfg.autoWidth && !hasWidth) {
		            this.jq.css('width', this.input.outerWidth() + 'px');
		        }
		    },
		
		    /**
		     * @override
		     * @inheritdoc
		     * @param {PrimeFaces.PartialWidgetCfg<TCfg>} cfg
		     */
		    refresh: function(cfg) {
		        this.panelWidthAdjusted = false;
		        this.items = null;
		
		        this._super(cfg);
		    },
		
		    /**
		     * Adjust the width of the overlay panel.
		     * @private
		     */
		    alignPanelWidth: function() {
		        //align panel and container
		        if(!this.panelWidthAdjusted) {
		            var jqWidth = this.jq.outerWidth();
		            if(this.panel.outerWidth() < jqWidth) {
		                this.panel.width(jqWidth);
		            }
		            else {
		                this.panel.width(this.panel.width());
		            }
		
		            this.panelWidthAdjusted = true;
		        }
		    },
		
		    /**
		     * Sets up all event listeners required by this widget.
		     * @private
		     */
		    bindEvents: function() {
		        var $this = this;
		
		        // Screen Reader(JAWS) hack on Chrome
		        if(PrimeFaces.env.browser.webkit) {
		            this.input.on('focus', function(){
		                setTimeout(function(){
		                    $this.focusInput.trigger('focus.ui-selectonemenu');
		                },2);
		            });
		        }
		
		        //Triggers
		        this.triggers.on("mouseenter", function() {
		            if(!$this.jq.hasClass('ui-state-focus')) {
		                $this.jq.addClass('ui-state-hover');
		            }
		        })
		        .on("mouseleave", function() {
		            $this.jq.removeClass('ui-state-hover');
		        })
		        .on("click", function(e) {
		            if($this.panel.is(":hidden")) {
		                $this.show();
		            }
		            else {
		                $this.hide();
		
		                $this.revert();
		                $this.changeAriaValue($this.getActiveItem());
		            }
		
		            $this.jq.removeClass('ui-state-hover');
		            $this.focusInput.trigger('focus.ui-selectonemenu');
		            e.preventDefault();
		        });
		
		        this.focusInput.on('focus.ui-selectonemenu', function(e) {
		            $this.jq.addClass('ui-state-focus');
		            if(!$this.cfg.dynamic && !$this.items) {
		                $this.callHandleMethod($this.handleTabKey(), e);
		            }
		        })
		        .on('blur.ui-selectonemenu', function(){
		            $this.jq.removeClass('ui-state-focus');
		
		            $this.callBehavior('blur');
		        });
		
		        //onchange handler for editable input
		        if(this.cfg.editable) {
		            this.label.on('change', function(e) {
		                $this.triggerChange(true);
		                $this.callHandleMethod($this.handleLabelChange, e);
		            });
		        }
		
    	        // fixes missing label after Chrome autofills selects or Screenreader Selection from HTML-Select
		    	this.input.off('change').on("change",function(e){
					var  value = $this.cfg.editable ? $this.label.val() : $this.getSelectedLabel(); 
	 	            $this.setLabel(value); 
	 	            
				    if($this.panel.is(":visible")){
				    	$this.hide();
				    }
				});
				
		        //key bindings
		        this.bindKeyEvents();
		    },
		
		    /**
		     * Sets up the event listeners for the selectable items.
		     * @private
		     */
		    bindItemEvents: function() {
		        var $this = this;
		        if(!this.items) {
		            return;
		        }
		
		        //Items
		        this.items.filter(':not(.ui-state-disabled)').on('mouseover.selectonemenu', function() {
		            var el = $(this);
		
		            if(!el.hasClass('ui-state-highlight'))
		                $(this).addClass('ui-state-hover');
		        })
		        .on('mouseout.selectonemenu', function() {
		            $(this).removeClass('ui-state-hover');
		        })
		        .on('click.selectonemenu', function() {
		            $this.revert();
		            $this.selectItem($(this));
		            $this.changeAriaValue($(this));
		        });
		    },
		
		    /**
		     * Sets up all panel event listeners
		     * @private
		     */
		    bindPanelEvents: function() {
		        var $this = this;
		
		        this.hideOverlayHandler = PrimeFaces.utils.registerHideOverlayHandler(this, 'mousedown.' + this.id + '_hide', this.panel,
		            function() { return  $this.label; },
		            function(e, eventTarget) {		
	    	            if(e.target.nodeName === "HTML") {
	    	            	// verhindert das einklappen bei Betätigung der Scrollbars.
	    	                return;
	    	            }     	            
		                if(!($this.panel.is(eventTarget) || $this.panel.has(eventTarget).length > 0)) {
		                    $this.panel.hide();
		                    setTimeout(function() {
		                        $this.revert();
		                        $this.changeAriaValue($this.getActiveItem());
		                    }, 2);
		                }
		            });
		
		        this.resizeHandler = PrimeFaces.utils.registerResizeHandler(this, 'resize.' + this.id + '_hide', this.panel, function() {
		            $this.handleViewportChange();
		        });
		
		        // GitHub #1173/#4609 keep panel with select while scrolling
		        this.scrollHandler = PrimeFaces.utils.registerConnectedOverlayScrollHandler(this, 'scroll.' + this.id + '_hide', this.jq, function() {
		            $this.handleViewportChange();
		        });
		    },
		
		    /**
		     * Fired when the browser viewport is resized or scrolled.  In Mobile environment we don't want to hider the overlay
		     * we want to re-align it.  This is because on some mobile browser the popup may force the browser to trigger a
		     * resize immediately and close the overlay. See GitHub #7075.
		     * @private
		     */
		    handleViewportChange: function() {
		        if (PrimeFaces.env.mobile) {
		            this.alignPanel();
		        } else {
		            this.hide();
		        }
		    },
		
		    /**
		     * Unbind all panel event listeners
		     * @private
		     */
		    unbindPanelEvents: function() {
		        if (this.hideOverlayHandler) {
		            this.hideOverlayHandler.unbind();
		        }
		
		        if (this.resizeHandler) {
		            this.resizeHandler.unbind();
		        }
		
		        if (this.scrollHandler) {
		            this.scrollHandler.unbind();
		        }
		    },
		
		    /**
		     * Removes some event listeners when this widget was disabled.
		     * @private
		     */
		    unbindEvents: function() {
		        if (this.items) {
		            this.items.off();
		        }
		        this.triggers.off();
		        this.input.off();
		        this.focusInput.off();
		        this.label.off();
		    },
		
		    /**
		     * Unselect the selected item, if any, and select the `please select` option.
		     */
		    revert: function() {
		        if(this.cfg.editable && this.customInput) {
		            this.setLabel(this.customInputVal);
		            this.items.filter('.ui-state-active').removeClass('ui-state-active');
		            this.items.eq(0).addClass('ui-state-active');
		        }
		        else {
		            this.highlightItem(this.items.eq(this.options.index(this.preShowValue)));
		        }
		    },
		
		    /**
		     * Highlight the given selectable option.
		     * @private
		     * @param {JQuery} item Option to highlight.
		     */
		    highlightItem: function(item) {
		        this.items.attr('aria-selected', false);
		        this.items.filter('.ui-state-highlight').removeClass('ui-state-highlight');
		
		        if(item.length > 0) {
		            item.addClass('ui-state-highlight');
		            item.attr('aria-selected', true);
		            this.setLabel(item.data('label'));
		        }
		    },
		
		    /**
		     * Triggers the event listeners when the value of this widget changed.
		     * @private
		     * @param {boolean} edited Whether the value was edited by the user. If it was, checks which option is now selected.
		     */
		    triggerChange: function(edited) {
		        this.changed = false;
		
		        this.input.trigger('change');
		
		        if(!edited) {
		            this.value = this.options.filter(':selected').val();
		        }
		    },
		
		    /**
		     * Callback for when the user selects an item with the mouse.
		     * @private
		     * @param {JQuery} item The option to select.
		     * @param {boolean} silent `true` to suppress triggering event listeners, or `false` otherwise.
		     */
		    selectItem: function(item, silent) {
				
				// HIS-Patch
				//index nach neuer Sortierung finden
				var newIndex;
				this.items.each(function(i, el ){
					if( item.attr('data-itemValue') == jQuery(el).attr('data-itemValue') ) {
						newIndex = i;	
					}
				});
				
		        var selectedOption = this.options.eq(newIndex),
		        currentOption = this.options.filter(':selected'),
		        sameOption = selectedOption.val() == currentOption.val(),
		        shouldChange = null;
		
		        if(this.cfg.editable) {
		            shouldChange = (!sameOption)||(selectedOption.text() != this.label.val());
		        }
		        else {
		            shouldChange = !sameOption;
		        }
		
		        if(shouldChange) {
		            this.highlightItem(item);
		            this.input.val(selectedOption.val());
		
		            if(!silent) {
		                this.triggerChange();
		            }
		
		            if(this.cfg.editable) {
		                this.customInput = false;
		            }
		
		            if(this.cfg.syncTooltip) {
		                this.syncTitle(selectedOption);
		            }
		        }
		
		        if(!silent) {
					// HIS-Patch um small-waiting-behaviour hinzubekommen, auch wenn dasselbe item wieder selektiert wird;
	           		this.input.trigger("selectitem");			
		            this.callBehavior('itemSelect');
		            this.focusInput.trigger('focus');
		        }
		
		        if(this.panel.is(':visible')) {
		            this.hide();
		        }
				
				// wenn SOM in Tableheader als Filter refresh button triggern
				if( this.id.contains('filterSelectOneMenu') && this.input.attr('onkeydown') ) {
					var refreshBtnId = this.input.attr('onkeydown').split("'")[1];
					refreshBtnId = refreshBtnId.replace( /(:|\.|\[|\]|,|=|@)/g, "\\$1" );
					jQuery('#'+refreshBtnId).trigger('click');
				}
		    },
		
		    /**
		     * Adjust the value of the title attribute to match selected option.
		     * @private
		     * @param {JQuery} option The option that was selected.
		     */
		    syncTitle: function(option) {
		        var optionTitle = this.items.eq(option.index()).attr('title');
		        if(optionTitle && optionTitle.trim().length > 0) {
		            this.jq.attr('title', optionTitle);
				}
/*		        else {
		            this.jq.removeAttr('title');
				}*/
		    },
		
		    /**
		     * Finds the index of the given selectable option.
		     * @param {JQuery} item One of the available selectable options.
		     * @return {number} The index of the given item.
		     */
		    resolveItemIndex: function(item) {
		        if(this.optGroupsSize === 0)
		            return item.index();
		        else
		            return item.index() - item.prevAll('li.ui-selectonemenu-item-group').length;
		    },
		
		    /**
		     * Sets up the event listeners for all keyboard related events other than the overlay panel, such as pressing space
		     * to bring up the overlay panel.
		     * @private
		     */
		    bindKeyEvents: function() {
		        var $this = this;
		
		        this.focusInput.on('keydown.ui-selectonemenu', function(e) {
		            var keyCode = $.ui.keyCode,
		            key = e.which;
		
		            switch(key) {
		                case keyCode.UP:
		                case keyCode.LEFT:
							if (e.altKey) {
								$this.handleEscapeKey(e);
							} else  {
								$this.callHandleMethod($this.highlightPrev, e);
							}
		                break;
		
		                case keyCode.DOWN:
							// Pfeiltaste nach unten soll Auswahlfeld öffnen
							if ($this.panel.is(":hidden")) {
								$this.show();
							} else {
								$this.callHandleMethod($this.highlightNext, e);
							}
						break;
						
						case keyCode.RIGHT:
							$this.callHandleMethod($this.highlightNext, e);
						break;
		
		                case keyCode.ENTER:
		                    $this.handleEnterKey(e);
		                break;
		
		                case keyCode.TAB:
		                    $this.handleTabKey();
		                break;
		
		                case keyCode.ESCAPE:
		                    $this.handleEscapeKey(e);
		                break;
		
		                case keyCode.SPACE:
		                    $this.handleSpaceKey(e);
		                break;

						case keyCode.BACKSPACE: 
							 $this.handleDelete(e);
							break;
						case keyCode.DELETE: 
							 $this.handleDelete(e);
							break;
		            }
		        })
		        .on('keyup.ui-selectonemenu', function(e) {
		            var keyCode = $.ui.keyCode,
		            key = e.which;
		
		            switch(key) {
		                case keyCode.UP:
		                case keyCode.LEFT:
		                case keyCode.DOWN:
		                case keyCode.RIGHT:
		                case keyCode.ENTER:
		                case keyCode.TAB:
		                case keyCode.ESCAPE:
		                case keyCode.SPACE:
		                case keyCode.HOME:
		                case keyCode.PAGE_DOWN:
		                case keyCode.PAGE_UP:
		                case keyCode.END:
		                case keyCode.DELETE:
		                case 16: //shift
		                case 17: //keyCode.CONTROL:
		                case 18: //keyCode.ALT:
		                case 19: //Pause/Break:
		                case 20: //capslock:
		                case 44: //Print Screen:
		                case 45: //Insert:
		                case 91: //left window or cmd:
		                case 92: //right window:
		                case 93: //right cmd:
		                case 144: //num lock:
		                case 145: //scroll lock:
		                break;
		
		                default:
		                    //function keys (F1,F2 etc.)
		                    if(key >= 112 && key <= 123) {
		                        break;
		                    }
		
		                    var matchedOptions = null,
		                    metaKey = e.metaKey||e.ctrlKey||e.altKey;
		
		                    if(!metaKey) {
		                        clearTimeout($this.searchTimer);
		
		                        // #4682: check for word match
		                        var text = $(this).val();
		                        matchedOptions = $this.matchOptions(text);
		                        if(matchedOptions.length) {
		                            var matchIndex = matchedOptions[0].index;
		                            var highlightItem = $this.items.eq(matchIndex);
		                            if($this.panel.is(':hidden')) {
		                                $this.selectItem(highlightItem);
		                            }
		                            else {
		                                $this.highlightItem(highlightItem);
		                                PrimeFaces.scrollInView($this.itemsWrapper, highlightItem);
		                            }
		                        } else {
		                            // #4682: check for first letter match
		                            text = String.fromCharCode(key).toLowerCase();
		                            // find all options with the same first letter
		                            matchedOptions = $this.matchOptions(text);
		                            if(matchedOptions.length) {
		                                var selectedIndex = -1;
		
		                                // is current selection one of our matches?
		                                matchedOptions.each(function() {
		                                   var option = $(this);
		                                   var currentIndex = option[0].index;
		                                   var currentItem = $this.items.eq(currentIndex);
		                                   if (currentItem.hasClass('ui-state-highlight')) {
		                                       selectedIndex = currentIndex;
		                                       return false;
		                                   }
		                                });
		
		                                matchedOptions.each(function() {
		                                    var option = $(this);
		                                    var currentIndex = option[0].index;
		                                    var currentItem = $this.items.eq(currentIndex);
		
		                                    // select next item after the current selection
		                                    if (currentIndex > selectedIndex) {
		                                         if($this.panel.is(':hidden')) {
		                                             $this.selectItem(currentItem);
		                                         }
		                                         else {
		                                             $this.highlightItem(currentItem);
		                                             PrimeFaces.scrollInView($this.itemsWrapper, currentItem);
		                                         }
		                                         return false;
		                                     }
		                                });
		                            }
		                        }
		
		                        $this.searchTimer = setTimeout(function(){
		                            $this.focusInput.val('');
		                        }, 1000);
		                    }
		                break;
		            }
		        });
		    },
		
		    /**
		     * Finds all options that match the given search string.
		     * @private
		     * @param {string} text The search string against which to match the options.
		     * @return {JQuery} All selectable options that match (contain) the given search string.
		     */
		    matchOptions: function(text) {
		        if(!text) {
		            return false;
		        }
		        return this.options.filter(function() {
		            var option = $(this);
		            if(option.is(':disabled')) {
		                return false;
		            }
		            if(option.text().toLowerCase().indexOf(text.toLowerCase()) !== 0) {
		                return false;
		            }
		            return true;
		        });
		    },
		
		    /**
		     * Sets up the event listeners for the filter input in the overlay panel.
		     * @private
		     */
		    bindFilterEvents: function() {
		        var $this = this;
		
		        this.filterInput.on('keyup.ui-selectonemenu', function(e) {
		            var keyCode = $.ui.keyCode,
		            key = e.which;
		
		            switch(key) {
		                case keyCode.UP:
		                case keyCode.LEFT:
		                case keyCode.DOWN:
		                case keyCode.RIGHT:
		                case keyCode.ENTER:
		                case keyCode.TAB:
		                case keyCode.ESCAPE:
		                case keyCode.SPACE:
		                case keyCode.HOME:
		                case keyCode.PAGE_DOWN:
		                case keyCode.PAGE_UP:
		                case keyCode.END:
		                case 16: //shift
		                case 17: //keyCode.CONTROL:
		                case 18: //keyCode.ALT:
		                case 91: //left window or cmd:
		                case 92: //right window:
		                case 93: //right cmd:
		                case 20: //capslock:
		                break;
		
		                default:
		                    //function keys (F1,F2 etc.)
		                    if(key >= 112 && key <= 123) {
		                        break;
		                    }
		
		                    var metaKey = e.metaKey||e.ctrlKey;
		
		                    if(!metaKey) {
		                        $this.filter($(this).val());
		                    }
		                break;
		            }
		        })
		        .on('keydown.ui-selectonemenu',function(e) {
		            var keyCode = $.ui.keyCode,
		            key = e.which;
		
		            switch(key) {
		                case keyCode.UP:
		                    $this.highlightPrev(e);
		                break;
		
		                case keyCode.DOWN:
								$this.highlightNext(e);
		                break;
		
		                case keyCode.ENTER:
		                    $this.handleEnterKey(e);
		                break;
		
		                case keyCode.TAB:
		                    $this.handleTabKey();
		                break;
			
		                case keyCode.ESCAPE:
		                    $this.handleEscapeKey(e);
		                break;
		
		                case keyCode.SPACE:
		                    $this.handleSpaceKey(e);
		                break;

						case keyCode.HOME:
							$this.handleHomeKey();
						break;
						case keyCode.END:
							$this.handleEndKey();
						break;
						case keyCode.PAGE_DOWN:
							$this.handlePageDownKey(e);
						break;
    	                case keyCode.PAGE_UP:
							$this.handlePageUpKey(e);
						break;
		
		                default:
		                break;
		            }
		        }).on('paste.ui-selectonemenu', function() {
		            setTimeout(function(){
		                $this.filter($this.filterInput.val());
		            },2);
				});
		    },
		
		    /**
		     * Highlights the next option after the currently highlighted option in the overlay panel.
		     * @private
		     * @param {JQuery.TriggeredEvent} event The event of the keypress.
		     */
		    highlightNext: function(event) {
		        var activeItem = this.getActiveItem(),
		        next = this.panel.is(':hidden') ? activeItem.nextAll(':not(.ui-state-disabled,.ui-selectonemenu-item-group):first')
		                                : activeItem.nextAll(':not(.ui-state-disabled,.ui-selectonemenu-item-group):visible:first');
		
		        if(event.altKey) {
		            this.show();
		        }
		        else {
		            if(next.length === 1) {
		                if(this.panel.is(':hidden')) {
		                    this.selectItem(next);
		                }
		                else {
		                    this.highlightItem(next);
		                    PrimeFaces.scrollInView(this.itemsWrapper, next);
		                    this.focusInput.focus();
		                }
		                this.changeAriaValue(next);
		            }
					else {
						this.focusInput.focus();
					}
		        }
		
		        event.preventDefault();
		    },
		
		    /**
		     * Highlights the previous option before the currently highlighted option in the overlay panel.
		     * @private
		     * @param {JQuery.TriggeredEvent} event The event of the keypress.
		     */
		    highlightPrev: function(event) {
		        var activeItem = this.getActiveItem(),
		        prev = this.panel.is(':hidden') ? activeItem.prevAll(':not(.ui-state-disabled,.ui-selectonemenu-item-group):first')
		                                : activeItem.prevAll(':not(.ui-state-disabled,.ui-selectonemenu-item-group):visible:first');
		
		        if(prev.length === 1) {
		            if(this.panel.is(':hidden')) {
		                this.selectItem(prev);
		            }
		            else {
		                this.highlightItem(prev);
		                PrimeFaces.scrollInView(this.itemsWrapper, prev);
						this.focusInput.focus();
		            }
					this.changeAriaValue(prev);
		        }
				else {
					this.filterInput.focus();
				}
		
		        event.preventDefault();
		    },
		
		    /**
		     * Callback for when the enter key was pressed. Brings up the overlay panel or accepts the highlighted option.
		     * @private
		     * @param {JQuery.TriggeredEvent} event The event of the keypress.
		     */
		    handleEnterKey: function(event) {
		        if(this.panel.is(':visible')) {
		            this.selectItem(this.getActiveItem());
			        event.preventDefault();
			        event.stopPropagation();
    	        } else {
    	        	return true;
    	        }			
		    },
		
		    /**
		     * Callback for when the space key was pressed. Brings up or hides the overlay panel.
		     * @private
		     * @param {JQuery.TriggeredEvent} event The event of the keypress.
		     */
		    handleSpaceKey: function(event) {
		        var target = $(event.target);
		
		        if(target.is('input') && target.hasClass('ui-selectonemenu-filter')) {
		            return;
		        }
		
		        if(this.panel.is(":hidden")) {
		            this.show();
		        }
		        else {
		            this.hide();
		
		            this.revert();
		            this.changeAriaValue(this.getActiveItem());
		        }
		
		        event.preventDefault();
		    },
		
		    /**
		     * Callback for when the escape key was pressed. Hides the overlay panel.
		     * @private
		     * @param {JQuery.TriggeredEvent} event The event of the keypress.
		     */
		    handleEscapeKey: function(event) {
		        if(this.panel.is(':visible')) {
		            this.revert();
		            this.hide();
		        }
		
		        event.preventDefault();
		    },
		
		    /**
		     * Callback for when the tab key was pressed. Selects the next option.
		     * @private
		     */
		    handleTabKey: function() {
		        if(this.panel.is(':visible')) {
		            this.selectItem(this.getActiveItem());
		        }
		    },
		
		    /**
		     * Callback that adjusts the label, invoked when the selected option has changed.
		     * @private
		     * @param {JQuery.TriggeredEvent} event The event that triggered the change.
		     */
		    handleLabelChange: function(event) {
		        this.customInput = true;
		        this.customInputVal = $(event.target).val();
		        this.items.filter('.ui-state-active').removeClass('ui-state-active');
		        this.items.eq(0).addClass('ui-state-active');
		    },

			handleEndKey:function() {
				var item = this.items.last();
				this.highlightItem(item); 
    	        PrimeFaces.scrollInView(this.itemsWrapper, item); 
			},
			handleHomeKey:function() {
				var item = this.items.first();
				this.highlightItem(item); 
    	        PrimeFaces.scrollInView(this.itemsWrapper, item); 
			},
			handlePageUpKey:function(b) {
				var item = this.items.filter('.ui-state-highlight').prevAll().eq(2);
				if(item.length != 1) {
					item =  this.items.first();
				}
				this.highlightItem(item); 
    	        PrimeFaces.scrollInView(this.itemsWrapper, item); 
				b.preventDefault(); 
			},
			handlePageDownKey:function(b) {
				var item = this.items.filter('.ui-state-highlight').nextAll().eq(2);
				if(item.length != 1) {
					item =  this.items.last();
				}
				this.highlightItem(item); 
    	        PrimeFaces.scrollInView(this.itemsWrapper, item);
				b.preventDefault(); 
			},
			// Event für Rück und Entf Taste bei fokus
			handleDelete:function (b) {
				this.show();
				this.setLabel('&nbsp;');
				this.filterInput.val('');
    	        b.preventDefault(); 
    	    },

		    /**
		     * Brings up the overlay panel with the available selectable options.
		     */
		    show: function() {
		        this.callHandleMethod(this._show, null);
		    },
		
		    /**
		     * Brings up the overlay panel with the available selectable options. Compared this `show`, this does not ensure
		     * the the overlay panel is loaded already (when dynamic loading is enabled).
		     * @private
		     */
		    _show: function() {
		        var $this = this;
		
		        if (this.transition) {
		            this.transition.show({
		                onEnter: function() {
		                    $this.panel.css('z-index', 100 + PrimeFaces.nextZindex());
		                    $this.alignPanel();
		                },
		                onEntered: function() {
		                    $this.bindPanelEvents();
		
		                    //value before panel is shown
		                    $this.preShowValue = $this.options.filter(':selected');
		                    $this.jq.attr('aria-expanded', true);
		
		                    PrimeFaces.scrollInView($this.itemsWrapper, $this.getActiveItem());
		
		                    if ($this.cfg.filter) {
		                        $this.focusFilter(10);
		                    }
		                }
		            });
		        }
		    },
		
		    /**
		     * Hides the overlay panel with the available selectable options.
		     */
		    hide: function() {
		        if (this.panel.is(':visible') && this.transition) {
		            var $this = this;
		
		            this.transition.hide({
		                onExit: function() {
		                    $this.unbindPanelEvents();
		                },
		                onExited: function() {
		                    $this.panel.css('z-index', '');
		                    $this.jq.attr('aria-expanded', false);
		                }
		            });
		        }
		    },
		
		    /**
		     * Puts focus on this widget.
		     */
		    focus: function() {
		        this.focusInput.trigger('focus');
		    },
		
		    /**
		     * Puts focus on the filter input in the overlay panel.
		     * @param {number} [timeout] Amount of time in milliseconds to wait before attempting to focus the input.
		     */
		    focusFilter: function(timeout) {
		        if(timeout) {
		            var $this = this;
		            setTimeout(function() {
		                $this.focusFilter();
		            }, timeout);
		        }
		        else {
		            this.filterInput.trigger('focus');
		        }
		    },
		
		    /**
		     * Removes focus from this widget.
		     */
		    blur: function() {
		        this.focusInput.trigger("blur");
		
		        this.callBehavior('blur');
		    },
		
		    /**
		     * Disables this widget so that the user cannot select any option.
		     */
		    disable: function() {
		    	if (!this.disabled) {
			        this.disabled = true;
			        this.jq.addClass('ui-state-disabled');
			        this.input.attr('disabled', 'disabled');
			        if(this.cfg.editable) {
			            this.label.attr('disabled', 'disabled');
			        }
			        this.unbindEvents();
		    	}
		    },
		
		    /**
		     * Enables this widget so that the user can select an option.
		     */
		    enable: function() {
		    	if (this.disabled) {
			        this.disabled = false;
			        this.jq.removeClass('ui-state-disabled');
			        this.input.removeAttr('disabled');
			        if(this.cfg.editable) {
			            this.label.removeAttr('disabled');
			        }
		
		            this.bindEvents();
		            this.bindItemEvents();
		    	}
		    },
		
		    /**
		     * Align the overlay panel with the available selectable options so that is is positioned next to the the button.
		     */
		    alignPanel: function() {
		        this.alignPanelWidth();
		
		        if(this.panel.parent().is(this.jq)) {
		            this.panel.css({
		                left: '0px',
		                top: this.jq.innerHeight() + 'px',
		                'transform-origin': 'center top'
		            });
		        }
		        else {
		            this.panel.css({left:'0px', top:'0px', 'transform-origin': 'center top'}).position({
		                my: 'left top'
		                ,at: 'left bottom'
		                ,of: this.jq
		                ,collision: 'flipfit'
		                ,using: function(pos, directions) {
		                    $(this).css('transform-origin', 'center ' + directions.vertical).css(pos);
		                }
		            });
		        }
		    },
		
		    /**
		     * Sets the label text that indicates the currently selected item to the item with the given value.
		     * @private
		     * @param {string} value Value of the item that was selected.
		     */
		    setLabel: function(value) {
		        var displayedLabel = this.getLabelToDisplay(value);
		
		        if (this.cfg.editable) {
		            if (value === '&nbsp;')
		                this.label.val('');
		            else
		                this.label.val(displayedLabel);
		
		            var hasPlaceholder = this.label[0].hasAttribute('placeholder');
		            this.updatePlaceholderClass((hasPlaceholder && value === '&nbsp;'));
		        }
		        else if (this.cfg.alwaysDisplayLabel && this.cfg.label) {
		            this.label.text(this.cfg.label);
		        }
		        else {
		            var labelText = this.label.data('placeholder');
		            if (labelText == null || labelText == "") {
		                labelText = '&nbsp;';
		            }
		
		            this.updatePlaceholderClass((value === '&nbsp;' && labelText !== '&nbsp;'));
		
		            if (value === '&nbsp;') {
		                if (labelText != '&nbsp;') {
		                   this.label.text(labelText);
		                } else {
		                    this.label.html(labelText);
		                }
		            }
		            else {
		                this.label.removeClass('ui-state-disabled');
		
		                var option = null;
		                if(this.items) {
		                    var selectedItem = this.items.filter('[data-label="' + $.escapeSelector(value) + '"]');
		                    option = this.options.eq(this.resolveItemIndex(selectedItem));
		                }
		                else {
		                    option = this.options.filter(':selected');
		                }
		
		                if (option && option.data('escape') === false) {
		                    this.label.html(displayedLabel);
		                } else {
		                    this.label.text(displayedLabel);
		                }
		            }
		        }
		    },
		
		    /**
		     * Selects the option with the given value.
		     * @param {string} value Value of the option to select.
		     */
		    selectValue: function(value) {
		        if(!this.items || this.items.length === 0) {
		           this.callHandleMethod(null, null);
		        }
		
		        var option = this.options.filter('[value="' + $.escapeSelector(value) + '"]');
		
		        this.selectItem(this.items.eq(option.index()), true);
		    },
		
		    /**
		     * Resets the input.
		     * @param {boolean} silent `true` to suppress triggering event listeners, or `false` otherwise.
		     */
		    resetValue: function(silent) {
		        if(!this.items || this.items.length === 0) {
		           this.callHandleMethod(null, null);
		        }
		
		        var option = this.options.filter('[value=""]');
		        if (option.length === 0) {
		            // if no empty value option found, fallback to first in list like JSF default
		            option = this.options.eq(0);
		        }
		        this.selectItem(this.items.eq(option.index()), silent);
		    },
		
		    /**
		     * Finds the element for the currently select option of this select one menu.
		     * @return {JQuery} The DOM element that represents the currently selected option.
		     */
		    getActiveItem: function() {
		        return this.items.filter('.ui-state-highlight');
		    },
		
		    /**
		     * Finds and stores the filter function which is to be used for filtering the options of this select one menu.
		     * @private
		     */
		    setupFilterMatcher: function() {
		        this.cfg.filterMatchMode = this.cfg.filterMatchMode||'startsWith';
		        this.filterMatchers = {
		            'startsWith': this.startsWithFilter
		            ,'contains': this.containsFilter
		            ,'endsWith': this.endsWithFilter
		            ,'custom': this.cfg.filterFunction
		        };
		
		        this.filterMatcher = this.filterMatchers[this.cfg.filterMatchMode];
		    },
		
		    /**
		     * Implementation of a `PrimeFaces.widget.SelectOneMenu.FilterFunction` that matches the given option when it starts
		     * with the given search text.
		     * @param {string} value Text of an option.
		     * @param {string} filter Value of the filter.
		     * @return {boolean} `true` when the text of the options starts with the filter value, or `false` otherwise.
		     */
		    startsWithFilter: function(value, filter) {
		        return value.indexOf(filter) === 0;
		    },
		
		    /**
		     * Implementation of a `PrimeFaces.widget.SelectOneMenu.FilterFunction` that matches the given option when it
		     * contains the given search text.
		     * @param {string} value Text of an option.
		     * @param {string} filter Value of the filter.
		     * @return {boolean} `true` when the text of the contains the filter value, or `false` otherwise.
		     */
		    containsFilter: function(value, filter) {
		        return value.indexOf(filter) !== -1;
		    },
		
		    /**
		     * Implementation of a `PrimeFaces.widget.SelectOneMenu.FilterFunction` that matches the given option when it ends
		     * with the given search text.
		     * @param {string} value Text of an option.
		     * @param {string} filter Value of the filter.
		     * @return {boolean} `true` when the text of the options ends with the filter value, or `false` otherwise.
		     */
		    endsWithFilter: function(value, filter) {
		        return value.indexOf(filter, value.length - filter.length) !== -1;
		    },
		
		    /**
		     * Filters the available options in the overlay panel by the given search value. Note that this does not bring up
		     * the overlay panel, use `show` for that.
		     * @param {string} value A value against which the available options are matched.
		     */
		    filter: function(value) {
			
				var filterListStart = [];
				var filterListRest = [];
				var filtered = false;
				var filterGroupResult = [];
			
		        this.cfg.initialHeight = this.cfg.initialHeight||this.itemsWrapper.height();
		        var filterValue = this.cfg.caseSensitive ? PrimeFaces.trim(value) : PrimeFaces.trim(value).toLowerCase();
		
		        if(filterValue === '') {
					
					// HIS-Patch
					// Alle Listeneinträge in vorheriger Reihenfolge ausgeben
					//Array.from(this.items).forEach(li => this.itemsContainer.append(li));
					var items = this.optGroupsSize == 0 ?  this.items : this.itemsWithGroup;
					Array.from(items).forEach(li => this.itemsContainer.append(li));

			
		            this.items.filter(':hidden').show();
		            this.itemsContainer.children('.ui-selectonemenu-item-group').show();
		        }
		        else {
		            var hide = [];
		            var show = [];
		
		            /*for(var i = 0; i < this.options.length; i++) {
		                var option = this.options.eq(i),*/
					var itemLength = this.optGroupsSize == 0 ?  this.options.length : this.itemsWithGroup.length;	
    	            for (var i = 0; i < itemLength; i++ ) {
    	                var option = this.optGroupsSize == 0 ?  this.options.eq(i) : this.itemsWithGroup.eq(i),						
		                itemLabel = this.cfg.caseSensitive ? option.text() : option.text().toLowerCase(),
		                //item = this.items.eq(i);
						item = this.optGroupsSize == 0 ?  this.items.eq(i) : this.itemsWithGroup.eq(i);
		
		                if(item.hasClass('ui-noselection-option')) {
		                    hide.push(item);
		                }
		                else {
		                    /*if(this.filterMatcher(itemLabel, filterValue)) {
								// HIS-Patch
								// Gefilterte Einträge in Arrays aufteilen, "startsWith"  und "contains"
								if(itemLabel.indexOf(filterValue) === 0) {								
									filterListStart.push(item);
								} else {
									filterListRest.push(item);
								}*/
								if(this.optGroupsSize == 0) {
			                    if (this.filterMatcher(itemLabel, filterValue)) {
									// HIS-Patch
									// Gefilterte Einträge in Arrays aufteilen, erst "startsWith" und dann "contains"
									if(itemLabel.indexOf(filterValue) === 0) {	
										filterListStart.push(item);
									} else {
										filterListRest.push(item);
								}								
										
		                        show.push(item);
							//}
		                                }
			                    else {
			                        hide.push(item); 
			                    }
							}
							else {
								// Items den Gruppen zuordnen
								if( item.hasClass('ui-selectonemenu-item-group') ) {
									var _this = this;
									
									// Wenn keiner Gruppe zugeordnet
									if( !item.prevAll().hasClass('ui-selectonemenu-item-group') ) {
										item.prevAll().each(function(){
											var $this = jQuery(this);
											var ing = _this.cfg.caseSensitive ? $this.text() : $this.text().toLowerCase();
											if (_this.filterMatcher(ing, filterValue)) {
												$this.show(); 
						                    }
						                    else {
						                    	$this.hide(); 
											}						
										});												
									}
									
									// innerhalb der Gruppen Filtern
									var itemsByGroup = item.nextUntil('.ui-selectonemenu-item-group');
									var groupResult = {group: null,items: null}; 
									var filterGroupStart = [];
									var filterGroupRest = [];
									itemsByGroup.each(function(){
										var $this = jQuery(this);
										var ibg = _this.cfg.caseSensitive ? $this.text() : $this.text().toLowerCase();
										if (_this.filterMatcher(ibg, filterValue)) {
							
											if( groupResult.group != itemLabel ) {
												groupResult = {group:itemLabel};
											}
											if(ibg.indexOf(filterValue) === 0) {
												filterGroupStart.push($this);
											} else {
												filterGroupRest.push($this);
											}
											$this.show();
							            } else {
											$this.hide();
										}
									});		
									
									if( groupResult.group == itemLabel ) {
										groupResult = {group:itemLabel, items:filterGroupStart.concat(filterGroupRest)};
										groupResult.items.unshift(item);
										filterGroupResult.push(groupResult);
									}
									
									
									if ( this.cfg.caseSensitive ? item.text() : item.text().toLowerCase() == groupResult.group ) {
										item.show();
									} else {
										item.hide();
									}
								}

							}

		                }
		            }
		
		            $.each(hide, function(i, o) { o.hide(); });
		            $.each(show, function(i, o) { o.show(); });
		            hide = [];
		            show = [];
					
					
					// HIS-Patch
					if(this.optGroupsSize == 0) {						
						var filterResult = filterListStart.concat(filterListRest);
						if( filterResult.length > 0 ) {							    
							filtered = true;					
							filterResult.forEach(li => this.itemsContainer.append(li));
							this.highlightItem(filterResult[0]);
						    PrimeFaces.scrollInView(this.itemsWrapper, filterResult[0]);
						}
					} else {
						if( filterGroupResult.length > 0 ) {
							filtered = true;
							filterGroupResult.forEach(fgr => fgr.items.forEach(li => this.itemsContainer.append(li)) );
							this.highlightItem(filterGroupResult[0].items[1]);
						    PrimeFaces.scrollInView(this.itemsWrapper, filterGroupResult[0].items[0]);
						}

					}

					
					
		            //Toggle groups
		            var groups = this.itemsContainer.children('.ui-selectonemenu-item-group');
		            for(var g = 0; g < groups.length; g++) {
		                var group = groups.eq(g);
		
		                if(g === (groups.length - 1)) {
		                    if(group.nextAll().filter(':visible').length === 0)
		                        hide.push(group);
		                    else
		                        show.push(group);
		                }
		                else {
		                    if(group.nextUntil('.ui-selectonemenu-item-group').filter(':visible').length === 0)
		                        hide.push(group);
		                    else
		                        show.push(group);
		                }
		            }
		
		            $.each(hide, function(i, o) { o.hide(); });
		            $.each(show, function(i, o) { o.show(); });
		        }
		
		        var firstVisibleItem = this.items.filter(':visible:not(.ui-state-disabled):first');
		        if(firstVisibleItem.length && !filtered) {
		            this.highlightItem(firstVisibleItem);
		        }
				filtered = false;
		        if(this.itemsContainer.height() < this.cfg.initialHeight) {
		            this.itemsWrapper.css('height', 'auto');
		        }
		        else {
		            this.itemsWrapper.height(this.cfg.initialHeight);
		        }
		
		        this.alignPanel();
		    },
		
		    /**
		     * Finds the value of the currently selected item, if any.
		     * @return {string} The value of the currently selected item. Empty string if none is selected.
		     */
		    getSelectedValue: function() {
		        return this.input.val();
		    },
		
		    /**
		     * Finds the label of the currently selected item, if any.
		     * @return {string} The label of the currently selected item. Empty string if none is selected.
		     */
		    getSelectedLabel: function() {
		        return this.options.filter(':selected').text();
		    },
		
		    /**
		     * Finds the label of the option with the given value.
		     * @private
		     * @param {string} value The value of a selectable option.
		     * @return {string} The label of the option with the given value.
		     */
		    getLabelToDisplay: function(value) {
		        if(this.cfg.labelTemplate && value !== '&nbsp;') {
		            return this.cfg.labelTemplate.replace('{0}', value);
		        }
		        return String(value);
		    },
		
		    /**
		     * Adjusts the value of the aria attributes for the given selectable option.
		     * @private
		     * @param {JQuery} item An option for which to set the aria attributes.
		     */
		    changeAriaValue: function (item) {
		        var itemId = item.attr('id');
		
		        this.focusInput.attr('aria-activedescendant', itemId)
		                .attr('aria-describedby', itemId);
		        this.itemsContainer.attr('aria-activedescendant', itemId);
		    },
		
		    /**
		     * Loads the overlay panel with the selectable options, if dynamic mode is enabled.
		     * @private
		     */
		    dynamicPanelLoad: function() {
		        var $this = this,
		        options = {
		            source: this.id,
		            process: this.id,
		            update: this.id,
		            global: false,
		            params: [{name: this.id + '_dynamicload', value: true}],
		            onsuccess: function(responseXML, status, xhr) {
		                PrimeFaces.ajax.Response.handle(responseXML, status, xhr, {
		                    widget: $this,
		                    handle: function(content) {
		                        var $content = $($.parseHTML(content));
		
		                        var $ul = $content.filter('ul');
		                        $this.itemsWrapper.empty();
		                        $this.itemsWrapper.append($ul);
		
		                        var $select = $content.filter('select');
		                        $this.input.replaceWith($select);
		                    }
		                });
		
		                return true;
		            },
		            oncomplete: function(xhr, status, args, data) {
		                $this.isDynamicLoaded = true;
		                $this.input = $($this.jqId + '_input');
		                $this.options = $this.input.children('option');
		
		                $this.renderPanelContentFromHiddenSelect(false);
		
		                $this.initContents();
		                $this.bindItemEvents();
		            }
		        };
		
		        PrimeFaces.ajax.Request.handle(options);
		    },
		
		    /**
		     * Invokes the given method after making sure that the overlay panel was loaded (in case dynamic mode is enabled).
		     * @private
		     * @param {(this: PrimeFaces.widget.SelectOneMenu, event: JQuery.TriggeredEvent) => void} handleMethod Callback method to
		     * invoke after the dynamic overlay panel was loaded.
		     * @param {JQuery.TriggeredEvent} event An event that is passed to the callback.
		     */
		    callHandleMethod: function(handleMethod, event) {
		        var $this = this;
		        if(this.cfg.dynamic && !this.isDynamicLoaded) {
		            this.dynamicPanelLoad();
		
		            var interval = setInterval(function() {
		                if($this.isDynamicLoaded) {
		                    if (handleMethod) {
		                        handleMethod.call($this, event);
		                    }
		
		                    clearInterval(interval);
		                }
		            }, 10);
		        }
		        else {
		            this.renderPanelContentFromHiddenSelect(true);
		
		            if (handleMethod) {
		                handleMethod.call(this, event);
		            }
		        }
		    },
		
		    /**
		     * Renders panel content based on hidden select.
		     * @private
		     * @param {boolean} initContentsAndBindItemEvents `true` to call {@link initContents} and {@link bindItemEvents}
		     * after rendering, `false` otherwise.
		     */
		    renderPanelContentFromHiddenSelect: function(initContentsAndBindItemEvents) {
		         if (this.cfg.renderPanelContentOnClient && this.itemsWrapper.children().length === 0) {
			
					 //filter
					 if (this.cfg.filter) {
						 this.cfg.initialHeight = this.itemsWrapper.height();
						 this.setupFilterMatcher();
						 this.filterInput = this.panel.find('> div.ui-selectonemenu-filter-container > input.ui-selectonemenu-filter');
						 PrimeFaces.skinInput(this.filterInput);

						 this.bindFilterEvents();
					 }
					 
					 PrimeFaces.utils.registerDynamicOverlay(this, this.panel, this.id + '_panel');
					 
                     var panelContent = jQuery('<ul/>').attr('id', this.id + '_items').addClass('ui-selectonemenu-items ui-selectonemenu-list ui-widget-content ui-widget ui-corner-all ui-helper-reset').attr('role', 'listbox');
                     panelContent.append(this.renderSelectItems(this.input)).html();
		             		
		             this.itemsWrapper.append(panelContent);
		
		             if (initContentsAndBindItemEvents) {
		                 this.initContents();
		                 this.bindItemEvents();
		             }
		         }
		    },
		
		    /**
		     * Renders panel HTML-code for all select items.
		     * @private
		     * @param {JQuery} parentItem A parent item (select, optgroup) for which to render HTML code.
		     * @param {boolean} [isGrouped] Indicated whether the elements of the parent item should be marked as grouped.
		     * @return {string} The rendered HTML string.
		     */
		    renderSelectItems: function(parentItem, isGrouped) {
		        var $this = this;
		        var content = new Array();
		        isGrouped = isGrouped || false;
		
		        var opts = parentItem.children("option, optgroup");
		        opts.each(function(index, element) {
		            content.push($this.renderSelectItem(element, isGrouped));
		        });
		        return content;
		    },
		
		    /**
		     * Renders panel HTML code for one select item (group).
		     * @private
		     * @param {JQuery} item An option (group) for which to render HTML code.
		     * @param {boolean} [isGrouped] Indicates whether the item is part of a group.
		     * @return {string} The rendered HTML string.
		     */
		    renderSelectItem: function(item, isGrouped) {
		        var content = "";
		        var $item = $(item);
		        var label;
		        var title = $item.data("title");
		        var escape = $item.data("escape");
		        var cssClass;
		
		        if (item.tagName === "OPTGROUP") {
		            label = $item.attr("label");
		            if (escape) {
		                label = $("<div>").text(label).html();
		            }
		            cssClass = "ui-selectonemenu-item-group ui-corner-all";
		        }
		        else { //OPTION
		            if (escape) {
		                label = $item.html();
		                if ($item.text() === "&nbsp;") {
		                    label = $item.text();
		                }
		            }
		            else {
		                label = $item.text();
		            }
		            cssClass = "ui-selectonemenu-item ui-selectonemenu-list-item ui-corner-all";
		            if (isGrouped) {
		                cssClass += " ui-selectonemenu-item-group-children";
		            }
		        }
		
		        var dataLabel = label.replace(/(<([^>]+)>)/gi, "").replaceAll('"', '&quot;');
				var dataValue = $item[0].value;
		        if ($item.data("noselection-option")) {
		            cssClass += " ui-noselection-option";
		        }
		
                var $li = jQuery('<li data-label="'+dataLabel+'">'+label+'</li>');
                $li.addClass(cssClass).attr('tabindex', '-1').attr('role', 'option').attr('title', title).attr('data-itemValue', dataValue);
                
                if ($item.is(':disabled')) {
                    $li.attr('disabled','disabled');
                }
                if (item.tagName === "OPTGROUP") {
                    var arr;
                    var li;                    
                    this.renderSelectItems($item, true).forEach(function(el){
                        arr += el.prop('outerHTML');
                    });
                    li = $li.prop('outerHTML');
                    li += arr;
                    $li = jQuery(li).filter(function(){ return this.nodeValue != 'undefined'; });
                }
                return $li;

		    },
		
		
		    /**
		     * Updates the style class of the label that indicates the currently selected item.
		     * @param {boolean} add `true` if a placeholder should be displayed, or `false` otherwise.
		     */
		    updatePlaceholderClass: function(add) {
		        if (add) {
		            this.label.addClass('ui-selectonemenu-label-placeholder');
		        }
		        else {
		            this.label.removeClass('ui-selectonemenu-label-placeholder');
		        }
		    }
		
		});
    }
};
/**
* @author masala@his.de, dziegielewski@his.de
* @usage
*  <{containerElement} 
*      class="quickmenu-container"    //must be declared
*      data-menu-taketext     //value optional, boolean, defaults to false, if true will insert text into the quickmenu items (if buttons) taken from the data-title or alt attribute
*      data-quickmenu-items   //optional, defaults to 2, specify if you wish to see more/less actions by default
*      data-quickmenu-selector //optional, defaults to "> *", value must be a valid css selector, use this to specify exactly which items within this container are quickmenu-items
*      data-quickmenu-alwaysMenu //optional, defaults to "false", specify if the menu will always be created, even if there would be only 1 element in the menu
*  >
*   <button />
*   <li></li>
*   <a></a>
*  </{containerElement}>
**/

use_package( "de.his.component" );

//IIF: $ === jQuery
( function( $ ) {
    de.his.component.Quickmenu = new function() {
        de.his.modules.ModuleRegistry
        .registerModule(this)
        .registerAjaxRefreshModule(this);
        this.moduleName = "de.his.component.Quickmenu";

        var quickmenu = {

            /**
             * change with attribute "data-quickmenu-items"
             * @private
             * @property _defaultItemNumer
             * @type {Integer}
             * @default 2
             */
            _defaultItemNumer: 2,
            /**
             * change with attribute "data-quickmenu-selector"
             * @private
             * @property _defaultItemSelector
             * @type {String}
             * @default "> *"
             */
            _defaultItemSelector: "> *",
            /**
             * change with attribute "data-quickmenu-alwaysMenu"
             * @private
             * @property _defaultAlwaysMenu
             * @type {boolean}
             * @default "false"
             */
            _defaultAlwaysMenu: false,
            /**
             * @private
             * @method _dropdownButton
             * @return {jQuery Template Element}
             */
            _dropdownButton: function(menu) {
                //get local
            	//title wählen
            	var language = de.his.common.LanguageHelper.currentLanguage();
            	if (language == "de") {
            		title = "Menü aufklappen";
            	} else {
            		title = "Open menu";
            	}
            	// Shortcut für das Aufklappen des Quickmenus soll auch im Title angezeigt werden.
            	var hotkey = jQuery( "html" ).data( "hotkey" );
            	if (hotkey && !menu.closest('table').length) {
            		title = title + "[" + hotkey.toUpperCase() + "+W]";
            	}
            	
            	
                return $( "<div tabindex='0' role='button' title='" + title + "' aria-label='" + title + "' class='quickmenu-action quickmenu-action-show iconfont-resultset_down' data-shortcut='w'>" );
            },
            /**
             * @private
             * @method _text
             * @return {jQuery Template Element}
             */
            _text: function( $item ) {
                var text = $item.data( "title" ) || $item.attr( "title" ) || "";
                return $( "<span class='quickmenu-item-text' aria-hidden='true'>" ).text( text );
            },

            /**
             * @method init
             */
            init: function() {
                var me = this, $menus = $( ".quickmenu-container" ) 
                if ( $menus.length ) {
                    me.initMenus( $menus );
                }
            },

            /**
             * @method initMenus
             * @param $menus {jQuery Object}
             **/
            initMenus: function( $menus ) {
                var me = this, $menu;
                for ( var i = 0, l = $menus.length; i < l; i++ ) {
                	$menu = $( $menus[ i ] );
                	$menuAlreadyExist = $menu.find(".quickmenu-identifier");// Search for this css class to check if the quickmenu was already created
                	if(!$menuAlreadyExist.length){
                		me.initQuickMenu( $menu );
                	}
                }
                $menus.removeClass("noDisplay");
            },

            /**
             * @initShowBtnAction
             * @param $menu {jQuery Object} container of $showBtn where ".quickmenu-container" is defined
             */
            initShowBtnAction: function( $menu ) {
                var me = this;

//                $menu.append( $showBtn );
                $menu.find("span").first().css("cursor", "pointer");
                $quickItems = $( ".quickmenu-identifier", $menu );
    			var buttons = $quickItems.children("button, a, input, span");
    			if (buttons.length) {
    				/* Wenn das letzte Elemente im Quickmenu via Tab erreicht wird und erneut Tab gedrückt wird, 
    				 * so wird ein blur Event ausgelöst. Dadurch wird das Quickmenu geschlossen und automatisch das nächste
    				 * fokussierbare Element erhält den Fokus. 
    				 * Problematisch ist hierbei, dass wenn bei fokussiertem letzten Element ein anderes Element im Quickmenu via
    				 * Maus angeklickt wird, das Menü geschlossen wird und die Aktion auf das Element nicht registriert wird. (sehr selten)
    				*/
//    				buttons.last().on("blur", function (event) {
//    					me.closeMenu($quickItems);
//    				});
    				
    				/*
    				 * Blur Variante dekativiert: wenn letztes Element im Menü ein overlay Button war. 
    				 * Wurde das Overlay geladen aber nicht angezeigt, weil dieses sich im Menü befindet 
    				 * und dieses durch das blur geschlossen wurde.
    				 */
    				buttons.last().on("keydown", function (event) {
    					if (event.keyCode == 9) {
    						if (!event.shiftKey) {
    							me.closeMenu($quickItems);
    						}
        				}
    				});
    				
    				// Beim ersten Element soll nach Shift-Tab das Menü auch geschlossen werden.
    				buttons.first().on("keydown", function (event) {
    					if (event.keyCode == 9 && event.shiftKey) {
							me.closeMenu($quickItems);
        				}
    				});
    			}

    			//ESC key will close menu.
    			$quickItems.on("keydown", function(event) {
    				if (event.keyCode == 27) {
    					me.closeMenu($quickItems);
    				}
    			});
				
    			buttons.on("keydown", function(event) {
					//Arrow DOWN
    				if (event.keyCode == 40) {
						event.preventDefault();
						if( $(this).next().hasClass('tabable-link') ) {
							$(this).next().children().focus();
						}
						else {
							$(this).next().focus();	
						}
						if( !$(this).next().length ) {
							me.closeMenu($quickItems);
						}
    				}
					//Arrow UP
					if (event.keyCode == 38) {
						event.preventDefault();
						if( $(this).prev().hasClass('tabable-link') ) {
							$(this).prev().children().focus();
						}
						else {
							$(this).prev().focus();	
						}
						if( !$(this).prev().length ) {
							me.closeMenu($quickItems);
						}
    				}
    			});
                $menu.find('.quickmenu-action, .quickmenuSpanUnderlined').on( "click keydown", function( event ) {	
                    if (event.type == "keydown" || event.type == "click") {
                    	//open menu with click or enter
                    	if (event.type == "click" || event.keyCode == 13) {
                    		$quickItems = $( ".quickmenu-identifier", $menu ), $showBtn = $menu.find(".quickmenu-action");
                    		offset = $showBtn.position();
                    		$menu.closest("tr").addClass("rowHighlightedRose");
                    
                    		if ( $quickItems.length && $quickItems.hasClass("noDisplay")) {
                    			event.preventDefault();
                    			event.stopPropagation();
                    			me.closeAnyOpenMenus();
                    			var language = de.his.common.LanguageHelper.currentLanguage();
                            	if (language == "de") {
                            		$menu.find(".quickmenu-action").attr("title", "Menü schließen");
                            	} else {
                            		$menu.find(".quickmenu-action").attr("title", "Close menu");
                            	}
                    			$menu.find(".quickmenu-action").removeClass("iconfont-resultset_down");
                    			$menu.find(".quickmenu-action").addClass("iconfont-resultset_up");
                    			$quickItems.removeClass("noDisplay");
                    			$quickItems.addClass("quickmenu-show quickmenu-container-items");
                    			
                    			// Prüfe ob das Quickmenu am rechten Bildschirm Rand ist
                    			var minWidth = parseInt(jQuery('.quickmenu-container-items.quickmenu-show').css("min-width"));
                    			var quickmenuLeftPos;
                    			// Wenn es am Rand ist, positioniere es weiter links
                    			if ($showBtn.offset().left + minWidth > window.innerWidth) {
                    				quickmenuLeftPos = $showBtn.offset().left - minWidth;
                    			} else {
                    				quickmenuLeftPos = $showBtn.offset().left;
                    			}
                    			
                    			$menu.find(".quickmenu-identifier").css( {
                    				left: quickmenuLeftPos
                    			} );
                    			
                    			// Focus first Element in Quickmenu
                    			var Elements = $quickItems.children();
                    			if(Elements.length){
                    				Elements[0].focus();
                    			}
                    			
                    			
                    			// Add blurrEvent to quickItems
                    			me.addBlurEvent( $quickItems );
                                
                    		} else {
                    			me.closeMenu($quickItems);
                    		}
                    	}
                    }
                } );
				setTimeout(function(){
					$menu.find('.quickmenu-action').trigger('click');
				});		
            },

            /**
             * @method closeAnyOpenMenus
             */
            closeAnyOpenMenus: function() {
                var me = this, $menu = $( ".quickmenu-show" );
                if ( $menu.length ) {
                    me.closeMenu( $menu );
                }
            },

            /**
             * @method addBlurEvent
             * @param $menu {jQuery Object}
             **/
            addBlurEvent: function( $menu ) {
                var me = this, 
	                f = function( event ) {
	                    var $target = $( event.target );
	                    if ( !$menu.has( $target ).length ) {
	                        me.closeMenu( $menu );
	                        $( document ).off( "click touchstart" );
	                    }
	                };
	            $( document ).off( "click touchstart" );
                $( document ).on( "click touchstart", f );
                $menu.data( "quickmenu-global-click-function", f );
            },

            /**
             * @method closeMenu
             * @param $menu{jQuery Object}
             **/
            closeMenu: function( $menu ) {
                var me = this;
                var language = de.his.common.LanguageHelper.currentLanguage();
            	if (language == "de") {
            		$menu.prev(".quickmenu-action").attr("title", "Menü aufklappen");
            	} else {
            		$menu.prev(".quickmenu-action").attr("title", "Open menu");
            	}
                $menu.prev(".quickmenu-action").removeClass("iconfont-resultset_up");
                $menu.prev(".quickmenu-action").addClass("iconfont-resultset_down");
                $menu.removeClass( "quickmenu-show quickmenu-container-items" );
                $menu.addClass("noDisplay");
                $menu.closest("tr").removeClass("rowHighlightedRose");
            },

            /**
            * @method initQuickMenu
            * @param $menu {jQuery Object}
            */
            initQuickMenu: function( $menu ) {
            	var me = this;
			
				//Quickmenu erst bei klick Initialisieren
				 items = $menu.attr( "data-quickmenu-items" ) ? $menu.data( "quickmenu-items" ) : me._defaultItemNumer;
		
				if( $menu.children().not('.ui-tooltip').length > items && !$menu.find('.quickmenu-action').length > 0 ) {
    	    		$showBtn = me._dropdownButton($menu);
    	    		$showBtn.appendTo( $menu );

					$firstElement = $menu.children(":first");
                    if($firstElement.is("span:not(.tabable-link)")) {
                    	$firstElement.addClass("quickmenuSpanUnderlined");
                    }
					$menu.find('.quickmenu-action, .quickmenuSpanUnderlined').on('click keydown', function(event){
						if (event.type == "click" || event.keyCode == 13) {
							if( !$menu.find('.quickmenu-identifier').length > 0 ) {
								if(me.initItems( $menu ) ){
									jQuery(this).off('click keydown');
									jQuery(this).parent().find('.quickmenuSpanUnderlined').off('click keydown');
			                		me.initShowBtnAction( $menu );
			                	}
							}
						}
					});
					$menu.css("display", "");
				}
				
            },

            /**
             * @method initItems
             * @param $menu {jQuery Object}
             * @return {boolean} true if items exist, false if not
             **/
            initItems: function( $menu ) {
                var me = this, 
                    takeText = ( function( $m ) {
                        var d = $m.data( "menu-taketext" );
                        return d === true || d === "";
                    } )( $menu ),
                    $quickItems = $menu.attr( "data-quickmenu-selector" ) ? $( $menu.data( "quickmenu-selector" ), $menu ) : $( me._defaultItemSelector, $menu ),
                    items = $menu.attr( "data-quickmenu-items" ) ? $menu.data( "quickmenu-items" ) : me._defaultItemNumer, $item, $box = $( "<div class='noDisplay quickmenu-identifier'>" );
                    
                    for ( var i = 0, l = $quickItems.length; i < l; i++ ) {
                        $item = $( $quickItems[ i ] );
                        /*
                         * excludeFromQuickmenu - ermöglicht es Elemente bei der Erstellung des Menus zu ignorieren.  
                         */
                        if($item.hasClass( "spacerImageTable" ) || $item.hasClass( "spacerHyphenTable" ) || $item.hasClass( "excludeFromQuickmenu" )){
                        	$item.remove();
                        	continue;
                        }
                        /*
                         * Abfrage für overlayShowButton, damit die generierten divs zu einem Overlay-Button nicht
                         * im Quickmenu angezeigt werden
                         */
						/* Lösung per CSS eingebunden #258647						
                        if($item.attr("id")){
                        	if($item.attr("id").search("overlayShowButton") != -1){
                        		// hole element des showOverlayButtons und suche das nächstgelegene Div.
                        		var nextDivItem = document.getElementById($item.attr("id")).next('div');
                        		nextDivItem.addClassName("quickmenuOverlayDiv");
                        	}
                        }
						*/
                    }
                    $quickItems = $menu.attr( "data-quickmenu-selector" ) ? $( $menu.data( "quickmenu-selector" ), $menu ) : $( me._defaultItemSelector, $menu );
                    itemSize = $quickItems.length;
                    for(var i = 0; i < itemSize; i++){
                    	$item = $( $quickItems[ i ] );
                    	if($item.attr('type') == "hidden" || $item.hasClass("noDisplay") || $item.hasClass("refreshButtonNoDisplay")){
                    		$quickItems.splice(i,1); 
                    		i--;
                    	}
                    }
                    var showAlwaysMenuString = $menu.attr( "data-quickmenu-alwaysMenu" ) ? $menu.attr( "data-quickmenu-alwaysMenu" ) : me._defaultAlwaysMenu;
                    var showAlwaysMenu = (showAlwaysMenuString == 'true');
                    // Check if more than 1 quickitem exist for bewerbung sichten to show status ( first element of quickItems ) but not the quickmenu
                    if($quickItems.length > 1)
                	{
                    	if($quickItems.length > (items+1) || showAlwaysMenu ){
    	                    for ( var i = items, l = $quickItems.length; i < l; i++ ) {
    	                    	$item = $( $quickItems[ i ] );
    	                    	if ( takeText ) {
                                    if ( $item.is( "button" ) ) {
                                        $item.append( me._text( $item ) );
                                    } else if ($item.is( "a" ) ) {
                                        $item.append( me._text( $item.find('img')));
                                    } else if ($item.is("input") && $item.attr("type") == "checkbox") {
                                    	if(!$item.hasClass("noDisplay") && !$item.attr('type') !== "hidden"){
                                    		$item.css("display", "inline-block")
                                    	}
                                    } else if ($item.is("label")) {
                                    	$item.css("display", "inline-block")
                                    }else if($item.find("button").length > 0 ){ 
                                    	// Sofern das item weder link noch button ist ( bspw span ) und taketext aktiviert ist, wird einfach der title des nächst sichtbaren Buttons oder Links genommen
                                    	var $foundButton = $item.find("button");
                                    	if(!$foundButton.hasClass("noDisplay") && !$foundButton.attr('type') !== "hidden"){
                                    		$foundButton.append( me._text( $foundButton ) ); 
                                    	}else if($item.find("a").length > 0){
                                        	var $foundLink = $item.find("a");
                                        	if(!$foundLink.hasClass("noDisplay") && !$foundLink.attr('type') !== "hidden")
                                        		$foundLink.append( "<span>" + $foundLink.attr( "title" ) + "</span>" );
                                        }
                                    }else if($item.find("a").length > 0){
                                    	var $foundLink = $item.find("a");
                                    	if(!$foundLink.hasClass("noDisplay") && !$foundLink.attr('type') !== "hidden"){
                                    		var text = $foundLink.data( "title" ) || $foundLink.attr( "title" ) || "";
                                    		$foundLink.append( me._text( text ) );
                                    	}
                                    }
    	                    	}
    	                    	if ( !$item.hasClass( "quickmenu-action" ) ) {
    	                    		$item.appendTo( $box );
    	                    	}
    	                    	/* Entfernt, siehe https://hiszilla.his.de/hiszilla/show_bug.cgi?id=283784
                                if ($item.is( "button") && $item.hasClass("submit") && !$item.hasClass("submit_linkLook")) {
    	                    		$item.addClass("submit_linkLook");
    	                    	}*/
    	                    }
    	                    if ( items < $quickItems.length || showAlwaysMenu) {
    	                    	/*//add the button here, so it has logical order in the parent div (better tab behaviour)
    	                    	$showBtn = me._dropdownButton($menu);
    	                    	$showBtn.appendTo( $menu );*/
    	                        $box.appendTo( $menu );
    	                        /*$firstElement = $menu.children(":first");
    	                        if($firstElement.is("span"))
    	                        {
    	                        	$firstElement.addClass("quickmenuSpanUnderlined");
    	                        }*/
    	                        $menu.css("display", "");
    	                        return true;
    	                    }
                        }
                	}

                    // wenn nur das "mehr..." enthalten ist, soll es nicht angezeigt werden
                    if ($quickItems.length == 1 && $menu.find('.quickMenuMoreElement').length > 0) {
                    	return false;
                    }

                    //$menu.css("display", "");
                return false;
            }

        };

        this.init = function() {
            //start
            quickmenu.init();          
        }
        
        this.refresh = function() {
            quickmenu.init();
            
        }
    };

} )( jQuery );
use_package("de.his.component");

de.his.component.SystemClipboard = new function() {
    de.his.modules.ModuleRegistry
        .registerModule(this)
        .registerAjaxRefreshModule(this);
    this.moduleName = "de.his.component.SystemClipboard";
   
    this.init = function() {
    	jQuery('.copyToSystemClipboard').click(function () {
            var clipboardContent = jQuery('#clipboardContent'); 
            var appendix=jQuery('<input>');
            jQuery('body').append(appendix);
            appendix.val(clipboardContent.text());
            appendix.select();
            document.execCommand('copy');
            appendix.remove();
        });
    	return false;
    };
    
    this.refresh = function() {
        this.init();
    };
};/* mousetrap v1.5.3 craig.is/killing/mice */
(function(C,r,g){function t(a,b,h){a.addEventListener?a.addEventListener(b,h,!1):a.attachEvent("on"+b,h)}function x(a){if("keypress"==a.type){var b=String.fromCharCode(a.which);a.shiftKey||(b=b.toLowerCase());return b}return l[a.which]?l[a.which]:p[a.which]?p[a.which]:String.fromCharCode(a.which).toLowerCase()}function D(a){var b=[];a.shiftKey&&b.push("shift");a.altKey&&b.push("alt");a.ctrlKey&&b.push("ctrl");a.metaKey&&b.push("meta");return b}function u(a){return"shift"==a||"ctrl"==a||"alt"==a||
"meta"==a}function y(a,b){var h,c,e,g=[];h=a;"+"===h?h=["+"]:(h=h.replace(/\+{2}/g,"+plus"),h=h.split("+"));for(e=0;e<h.length;++e)c=h[e],z[c]&&(c=z[c]),b&&"keypress"!=b&&A[c]&&(c=A[c],g.push("shift")),u(c)&&g.push(c);h=c;e=b;if(!e){if(!k){k={};for(var m in l)95<m&&112>m||l.hasOwnProperty(m)&&(k[l[m]]=m)}e=k[h]?"keydown":"keypress"}"keypress"==e&&g.length&&(e="keydown");return{key:c,modifiers:g,action:e}}function B(a,b){return null===a||a===r?!1:a===b?!0:B(a.parentNode,b)}function c(a){function b(a){a=
a||{};var b=!1,n;for(n in q)a[n]?b=!0:q[n]=0;b||(v=!1)}function h(a,b,n,f,c,h){var g,e,l=[],m=n.type;if(!d._callbacks[a])return[];"keyup"==m&&u(a)&&(b=[a]);for(g=0;g<d._callbacks[a].length;++g)if(e=d._callbacks[a][g],(f||!e.seq||q[e.seq]==e.level)&&m==e.action){var k;(k="keypress"==m&&!n.metaKey&&!n.ctrlKey)||(k=e.modifiers,k=b.sort().join(",")===k.sort().join(","));k&&(k=f&&e.seq==f&&e.level==h,(!f&&e.combo==c||k)&&d._callbacks[a].splice(g,1),l.push(e))}return l}function g(a,b,n,f){d.stopCallback(b,
b.target||b.srcElement,n,f)||!1!==a(b,n)||(b.preventDefault?b.preventDefault():b.returnValue=!1,b.stopPropagation?b.stopPropagation():b.cancelBubble=!0)}function e(a){"number"!==typeof a.which&&(a.which=a.keyCode);var b=x(a);b&&("keyup"==a.type&&w===b?w=!1:d.handleKey(b,D(a),a))}function l(a,c,n,f){function e(c){return function(){v=c;++q[a];clearTimeout(k);k=setTimeout(b,1E3)}}function h(c){g(n,c,a);"keyup"!==f&&(w=x(c));setTimeout(b,10)}for(var d=q[a]=0;d<c.length;++d){var p=d+1===c.length?h:e(f||
y(c[d+1]).action);m(c[d],p,f,a,d)}}function m(a,b,c,f,e){d._directMap[a+":"+c]=b;a=a.replace(/\s+/g," ");var g=a.split(" ");1<g.length?l(a,g,b,c):(c=y(a,c),d._callbacks[c.key]=d._callbacks[c.key]||[],h(c.key,c.modifiers,{type:c.action},f,a,e),d._callbacks[c.key][f?"unshift":"push"]({callback:b,modifiers:c.modifiers,action:c.action,seq:f,level:e,combo:a}))}var d=this;a=a||r;if(!(d instanceof c))return new c(a);d.target=a;d._callbacks={};d._directMap={};var q={},k,w=!1,p=!1,v=!1;d._handleKey=function(a,
c,e){var f=h(a,c,e),d;c={};var k=0,l=!1;for(d=0;d<f.length;++d)f[d].seq&&(k=Math.max(k,f[d].level));for(d=0;d<f.length;++d)f[d].seq?f[d].level==k&&(l=!0,c[f[d].seq]=1,g(f[d].callback,e,f[d].combo,f[d].seq)):l||g(f[d].callback,e,f[d].combo);f="keypress"==e.type&&p;e.type!=v||u(a)||f||b(c);p=l&&"keydown"==e.type};d._bindMultiple=function(a,b,c){for(var d=0;d<a.length;++d)m(a[d],b,c)};t(a,"keypress",e);t(a,"keydown",e);t(a,"keyup",e)}var l={8:"backspace",9:"tab",13:"enter",16:"shift",17:"ctrl",18:"alt",
20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"ins",46:"del",91:"meta",93:"meta",224:"meta"},p={106:"*",107:"+",109:"-",110:".",111:"/",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},A={"~":"`","!":"1","@":"2","#":"3",$:"4","%":"5","^":"6","&":"7","*":"8","(":"9",")":"0",_:"-","+":"=",":":";",'"':"'","<":",",">":".","?":"/","|":"\\"},z={option:"alt",command:"meta","return":"enter",
escape:"esc",plus:"+",mod:/Mac|iPod|iPhone|iPad/.test(navigator.platform)?"meta":"ctrl"},k;for(g=1;20>g;++g)l[111+g]="f"+g;for(g=0;9>=g;++g)l[g+96]=g;c.prototype.bind=function(a,b,c){a=a instanceof Array?a:[a];this._bindMultiple.call(this,a,b,c);return this};c.prototype.unbind=function(a,b){return this.bind.call(this,a,function(){},b)};c.prototype.trigger=function(a,b){if(this._directMap[a+":"+b])this._directMap[a+":"+b]({},a);return this};c.prototype.reset=function(){this._callbacks={};this._directMap=
{};return this};c.prototype.stopCallback=function(a,b){return-1<(" "+b.className+" ").indexOf(" mousetrap ")||B(b,this.target)?!1:"INPUT"==b.tagName||"SELECT"==b.tagName||"TEXTAREA"==b.tagName||b.isContentEditable};c.prototype.handleKey=function(){return this._handleKey.apply(this,arguments)};c.init=function(){var a=c(r),b;for(b in a)"_"!==b.charAt(0)&&(c[b]=function(b){return function(){return a[b].apply(a,arguments)}}(b))};c.init();C.Mousetrap=c;"undefined"!==typeof module&&module.exports&&(module.exports=
c);"function"===typeof define&&define.amd&&define(function(){return c})})(window,document);
/**
 * @author masala@his.de used with mousetrap: https://craig.is/killing/mice
 */
use_package("de.his.component");

de.his.component.HisMousetrap = new function() {
	de.his.modules.ModuleRegistry.registerModule(this).registerAjaxRefreshModule(this);
	this.moduleName = "de.his.component.HisMousetrap";

	this.init = function() {
		initIntern(this, "[data-shortcut]")
	};
	
    this.refresh = function() {
		initIntern(this, ".bookmarkPopupMenuLink[data-shortcut]");  // Lesezeichen können per Ajax umdefiniert werden   	
    };
    
    var initIntern = function(self, shortcutSelector) {
		"use strict";
		if (!window.Mousetrap) {
			throw Error("Mousetrap js library not found");
		}

		var hotkeys = jQuery("html").data("hotkey"); 
		var shortcuts = jQuery(shortcutSelector); 
		var bindTrap;

		if (shortcuts.length) {

			bindTrap = function($el) {
				var sc = $el.data("shortcut");
				var element = $el[0];
				var hk = hotkeys ? hotkeys + "+" : ""; // if hotkeys are present add a "+"
				console.log("Mousetrap hotkeys: "+hotkeys);
				
				Mousetrap.bind(hk + sc, function(event) {
					event.preventDefault();
					
					var type = element.tagName;
					
					if (type.toUpperCase() !== 'INPUT') {   
                        // wenn Angular eingebunden Anker aus URL zusammenbauen, das Routing von Angular kommt sonst nicht mit Ankern aus JSF zurecht
                        if( jQuery('app-root' ).length ) {
                            var anchor = jQuery(element).attr('href');
                            if( anchor.startsWith('#') ) {
                                jQuery(element).attr('href',window.location.pathname+window.location.search+anchor);
                            }
                        }
						element.click();
					} else {
						element.focus();
					}
					return false;
				});
			};

			for (var i = 0; i < shortcuts.length; i++) {
				var e = jQuery(shortcuts[i]);
				if(e.data("shortcut") != ""){
					bindTrap(e);
					console.log("Bind Shortcut '"+hotkeys+"+"+e.data("shortcut")+"' to '"+e[0].type+"' with id '"+e[0].id+"'");
				}
			}
		}
  	};
};/*!
 *  Flex Level Drop Down Menu v1.1
 * Created: Jan 5th, 2010 by DynamicDrive.com. This notice must stay intact for usage 
 * Author: Dynamic Drive at http://www.dynamicdrive.com/
 * Visit http://www.dynamicdrive.com/ for full source code
 */


// Achtung: Diese Version ist eine angepasste Version!
// Nicht einfach durch eine Neue ersetzen!
use_package( "de.his.portal" );

de.his.portal.Flexdropdown = new function() {

    de.his.modules.ModuleRegistry.registerModule( this ).registerAjaxRefreshModule( this );
    this.moduleName = "de.his.portal.Flexdropdown";
    
    this.init = function() {
		var reinit = false;
		flexdropdownmenuInit(reinit);
    };

	this.refresh = function() {
		var reinit = true;
		flexdropdownmenuInit(reinit);
    };

var flexdropdownmenuInit = function(reinit) { 
var flexdropdownmenu={
//	arrowpath: 'arrow.gif', //full URL or path to arrow image
	animspeed: 0, //reveal animation speed (in milliseconds)
	showhidedelay: [400, 2000], //delay before menu appears and disappears when mouse rolls out of it, in milliseconds
	defaultOffsetX: -11,
	defaultOffsetY: 1, //jQuery.browser.mozilla? 1 : (jQuery.browser.msie && parseInt(jQuery.browser.version)==8)? 3 : 5,
	minSpaceToRightEdge: 20,
	minSpaceToBottomEdge: 20,

	//***** NO NEED TO EDIT BEYOND HERE
	startzindex:1000,
	builtflexmenuids: [], //ids of flex menus already built (to prevent repeated building of same flex menu)
	menuitemsToHide: [],
	debug: false,

	positionMenu:function($, $menu, e, $anchor){
		var istoplevel=$menu.hasClass('jqflexmenu') //Bool indicating whether $menu is top level flex menu DIV
		var docrightedge=$(document).scrollLeft()+$(window).width()-this.minSpaceToRightEdge 
		var docbottomedge=$(document).scrollTop()+$(window).height()-this.minSpaceToBottomEdge
		if (istoplevel){ //if main flex menu DIV		
			var offsets=$anchor.offset()
			var anchorsetting=$anchor.data('setting')
			var x=offsets.left+this.defaultOffsetX+anchorsetting.useroffsets[0]+(anchorsetting.dir=="h"? $anchor.outerWidth() : 0) //x pos of main flex menu UL
			var y=offsets.top+this.defaultOffsetY+anchorsetting.useroffsets[1]+(anchorsetting.dir=="h"? 0 : $anchor.outerHeight())
			var menuWidth = $anchor.outerWidth()
			var subMenuWidth = $menu.data('dimensions').w
			x=(x+subMenuWidth > docrightedge)? x-(anchorsetting.useroffsets[0]*2) - subMenuWidth + menuWidth + (anchorsetting.dir=="h"? -(menuWidth*2) : 0) : x //if not enough horizontal room to the ridge of the cursor
//			y=(y+$menu.data('dimensions').h > docbottomedge)? y-(anchorsetting.useroffsets[1]*2)-$menu.data('dimensions').h-$anchor.outerHeight()+(anchorsetting.dir=="h"? ($anchor.outerHeight()*2) : 0) : y

			// Wenn Menuliste zu hoch für viewport den Header nicht fixieren
			if ($menu.parents('.navband').length) {
				var winHeight = $(window).outerHeight();
				var menuHeight = $menu.outerHeight();
				var $header = $('#hisinoneHeader');
				if( winHeight <= menuHeight ) {
					var headerTop = $header.offset().top;
					$header.addClass('js-absolute').css({top:headerTop});
				}
			}

		}
		else{ //if sub level flex menu UL
			var $parentli=$menu.data('$parentliref')
			var parentlioffset=$parentli.offset()
			var x=$menu.data('dimensions').parentliw //x pos of sub UL
			var y=0
			x=(parentlioffset.left+x+$menu.data('dimensions').w > docrightedge)? x-$menu.data('dimensions').parentliw-$menu.data('dimensions').w : x //if not enough horizontal room to the ridge parent LI
//			y=(parentlioffset.top+$menu.data('dimensions').h > docbottomedge)? y-$menu.data('dimensions').h+$menu.data('dimensions').parentlih : y
		}
		$menu.css({left:x, top:y})
	},
	
	showMenu:function($, $menu, ev){
		if ($menu.data('timers').hidetimer) {
			clearTimeout($menu.data('timers').hidetimer)
			$menu.data('timers').hidetimer = null
			this.removeFromMenuitemsToHide($menu)
		}
		this.hideOldMenuImmediate()
		$menu.data('timers').showtimer=setTimeout(function(){$menu.show(flexdropdownmenu.animspeed)}, this.showhidedelay[0])
	},

	hideMenu:function($, $menu){
		if ($menu.data('timers').showtimer) clearTimeout($menu.data('timers').showtimer) 
		$menu.data('timers').hidetimer=setTimeout(function(){
			$menu.hide(flexdropdownmenu.animspeed)
			$('#hisinoneHeader').removeClass('js-absolute').css({top:''}); // Header wieder fixieren
			}, this.showhidedelay[1]) //hide flex menu plus all of its sub ULs
		this.menuitemsToHide.push($menu)
	},
	
	hideOldMenuImmediate:function() {
		if (this.menuitemsToHide.length > 0){
			for (var i = 0; i < this.menuitemsToHide.length; i++) {
				if (this.menuitemsToHide[i].data('timers').hidetimer) {
					clearTimeout(this.menuitemsToHide[i].data('timers').hidetimer)
					this.menuitemsToHide[i].data('timers').hidetimer = null
					this.menuitemsToHide[i].hide()
					if (this.debug)
					flexdropdownmenu.writeLog('Hide Submenu of: '+this.menuitemsToHide[i].parent().find('a:eq(0)').get(0).innerHTML)
				}
			}
			this.menuitemsToHide = new Array()
		}
	},
	
	removeFromMenuitemsToHide:function($menuToShow) {
		var length_ = $menuToShow.get().length
		if (length_ == 0) {
			return
		}
		if (length_ > 1) {
			if (this.debug) this.writeLog('Fehler: Mehr als ein UL als Parameter übergeben!')
			return
		}
		if (!$menuToShow.get(0).id) {
			if (this.debug) this.writeLog('Fehler: UL hat keine id')
			return
		}
		for (var i = 0; i < this.menuitemsToHide.length; i++) {
			if (this.menuitemsToHide[i].get(0).id == $menuToShow.get(0).id) {
				this.menuitemsToHide.splice(i,1) // Element löschen
				break
			}
		}
	},

	writeLog:function(text) {
		var xx = jQuery('#debug').get(0) 
		xx.innerHTML = text + '<br>' + xx.innerHTML
	},

	buildflexmenu:function($, $menu, $anchor){ // $anchor ist Button oder Link, $menu ist ein ul (auf gleicher Ebene wie der Button/Link)
		if( $menu.hasClass('jqflexmenu') ) {
			return;	
		}
		$menu.css({display:'block', visibility:'hidden', zIndex:++this.startzindex}).addClass('jqflexmenu')//.appendTo(document.body)
		$menu.off('mouseenter').on('mouseenter', function(){
			clearTimeout($menu.data('timers').hidetimer)
			$menu.data('timers').hidetimer = null
			flexdropdownmenu.removeFromMenuitemsToHide($menu)
		})
		$menu.off('mouseleave').on('mouseleave', function(){ //hide menu when mouse moves out of it
			flexdropdownmenu.hideMenu($, $menu)
		})
		$menu.data('dimensions', {w:$menu.outerWidth(), h:$menu.outerHeight()}) //remember main menu's dimensions
		$menu.data('timers', {})
		var $lis=$menu.find("ul").parent() //find all LIs within menu with a sub UL
		$lis.each(function(i){
			var $li=$(this)
			var $subul=$li.find('ul:eq(0)').css({display:'block'}) //set sub UL to "block" so we can get dimensions
			$subul.data('dimensions', {w:$subul.outerWidth(), h:$subul.outerHeight(), parentliw:this.offsetWidth, parentlih:this.offsetHeight})
			$subul.data('$parentliref', $li) //cache parent LI of each sub UL
			$subul.data('timers', {})
			$li.data('$subulref', $subul) //cache sub UL of each parent LI
//			$li.children("input").addClass('link_next') //add arrow image
//			$li.children("a:eq(0)").append( //add arrow images
//				'<img src="'+flexdropdownmenu.arrowpath+'" class="rightarrowclass" style="border:0;" />'
//			)
			$subul.css({zIndex: ++flexdropdownmenu.startzindex})
			$li.off('mouseenter').on('mouseenter', function(ev){ //show sub UL when mouse moves over parent LI
				var $li_ = $(this)
				var $targetul=$li_.addClass("selected").data('$subulref')
				if ($targetul.queue().length<=1) { //if 1 or less queued animations
					if (flexdropdownmenu.debug)
					flexdropdownmenu.writeLog('Mouseover: ' + $li_.find('a:eq(0)').get(0).innerHTML)
					if ($targetul.data('timers').hidetimer) {
						clearTimeout($targetul.data('timers').hidetimer)
						$targetul.data('timers').hidetimer = null
						flexdropdownmenu.removeFromMenuitemsToHide($targetul)
					}
					flexdropdownmenu.removeFromMenuitemsToHide($li_.parent('ul')) // parent ul
					flexdropdownmenu.removeFromMenuitemsToHide($li_.parent('ul').parent('li').parent('ul')) // grand parent ul
					flexdropdownmenu.hideOldMenuImmediate()
					$targetul.data('timers').showtimer=setTimeout(function(){
							flexdropdownmenu.positionMenu($, $targetul, ev)
							$targetul.show(flexdropdownmenu.animspeed)
						}, flexdropdownmenu.showhidedelay[0])
				}
			})
			$li.on('mouseleave').on('mouseleave', function(ev){ //hide sub UL when mouse moves out of parent LI
				var $targetul=$(this).data('$subulref')
				clearTimeout($targetul.data('timers').showtimer)
				$targetul.data('timers').hidetimer=setTimeout(function(){$targetul.hide(flexdropdownmenu.animspeed).data('$parentliref').removeClass('selected')}, flexdropdownmenu.showhidedelay[1])
				flexdropdownmenu.menuitemsToHide.push($targetul)
				if (flexdropdownmenu.debug)
				flexdropdownmenu.writeLog('Mouseout: ' + $targetul.parent().find('a:eq(0)').get(0).innerHTML)
			})
		})
		$menu.find('ul').addBack().css({display:'none', visibility:'visible'}) //collapse all ULs again
		this.builtflexmenuids.push($menu.get(0).id) //remember id of flex menu that was just built
	},


	init:function($, $anchor, $menu){ // $anchor ist Button oder Link, $menu ist ein ul, das sich in der gleichen xml-Ebene wie $anchor befindet
	
		// Nicht in Burgernavigation ausführen
		if ($menu.parents('.topMenuContainer').length) {
			return;
		}
		if (this.builtflexmenuids.length==0 && reinit == false){ //only bind click event to document once
			$(document).on("click", function(ev){
				if (ev.button==0){ //hide all flex menus (and their sub ULs) when left mouse button is clicked
					$('.jqflexmenu').find('ul').addBack().hide()
				}
			})
		}
		if (jQuery.inArray($menu.get(0).id, this.builtflexmenuids)==-1) //if this flex menu hasn't been built yet
			this.buildflexmenu($, $menu, $anchor)
		if ($anchor.parents().filter('ul.jqflexmenu').length>0) //if $anchor matches an element within the flex menu markup, don't bind onflexmenu to that element
			return
		var useroffsets=$anchor.attr('data-offsets')? $anchor.attr('data-offsets').split(',') : [0,0] //get additional user offsets of menu
		useroffsets=[parseInt(useroffsets[0]), parseInt(useroffsets[1])]
		$anchor.data('setting', {dir: $anchor.attr('data-dir'), useroffsets: useroffsets}) //store direction (drop right or down) of menu plus user offsets
		$anchor.off("mouseenter").on("mouseenter", function(ev){
			$menu.css('zIndex', ++flexdropdownmenu.startzindex)
			flexdropdownmenu.positionMenu($, $menu, ev, $anchor)
			flexdropdownmenu.showMenu($, $menu, ev)
		})
		$anchor.off("mouseleave").on("mouseleave", function(ev){
			flexdropdownmenu.hideMenu($, $menu)
		})
	}
}

jQuery.fn.addflexmenu=function(options){
	var $=jQuery
	return this.each(function(){ //return jQuery obj
		var $anchor=$(this)
		if (typeof options=="object"){ //if options parameter defined
			if (options.dir)
				$anchor.attr('data-dir', options.dir) //set/overwrite data-dir attr with defined value
			if (options.offsets)
				$anchor.attr('data-offsets', options.offsets) //set/overwrite data-offsets attr with defined value
		}
		var $subul = $anchor.parent().find('ul:eq(0)')
		
		if ($subul.length==1) //check flex menu is defined
			flexdropdownmenu.init($, $anchor, $subul)
	})
};


	var $anchors=$('.subMenuBtn.flexdropdownmenu, .topMenuLink.flexdropdownmenu ')
	$anchors.each(function(){
		$(this).addflexmenu()
	})
	if (flexdropdownmenu.debug) {
		jQuery('body').append('<div id="debug" style="position:absolute; z-index:10000; width:100%; height:300px; left:0; bottom:0; background-color:white; overflow:auto;" />')
	}
}
}
/**
* Extend the flexdropdown menu functionality to include arrow key navigation
* author: masala@his.de
*/

window.his_flexdropdown = window.his_flexdropdown || new function(){
	
	var topLevelElement = null, openElement, originalTimers, currentFocus;
	
	
	var setTopLevelElement = function(fe){
		topLevelElement = fe;
	}

	var getTopLevelElement = function(){
		var item = jQuery(".topMenuList a:focus");
		if(item.length > 0){
			if(!item.hasClass(".topMenuLink") && !item.hasClass(".topMenuLinkHighlighted")){
				item = item.closest(".topMenuList");
				item = item.find("> a");
			}
			return item;
		}
	};
	
	var setOpenElement = function(oe){
		openElement = oe;
	}

	var getOpenElement = function(){
		return openElement;
	};
	
	var setFlexTimers = function(a,b){
		originalTimers = flexdropdownmenu.showhidedelay;
		flexdropdownmenu.showhidedelay = [a, b];	//overwrite it. so the menu shows immediately
	}

	var resetFlexTimers = function(){
		flexdropdownmenu.showhidedelay = originalTimers;
	}
	
	var focusItem = function(element, silent){
		currentFocus = element;
		//without timeout it won't always focus because of keyup event 
		if(currentFocus && !silent){
			currentFocus.focus();
		}
	}
	
	var getFocusedItem = function(){
		return currentFocus;
	}
	
	var closeOpen = function(element){
		var oe = element || getOpenElement();
		//if any open menus - then close
		if(oe){
			setFlexTimers(0, 0);	//make it immediate
			flexdropdownmenu.hideMenu(jQuery, oe);
			if(!element){
				setOpenElement(null); //clear openElement
			}
			resetFlexTimers();
		}
	};
	
	var private_showMenu = function(menu, event){
		//position and show menu - this was take from flexdropdownmenu.init() -> bind("mouseenter")
		flexdropdownmenu.positionMenu(jQuery, menu, event, menu.parent().find("> a"));
		//override the showMenu function so that the focus() doesn't need to be called delayed
		var oldShow = flexdropdownmenu.showMenu;
			flexdropdownmenu.showMenu = function($, $menu, ev){
				if ($menu.data('timers').hidetimer) {
					$menu.data('timers').hidetimer = null
					this.removeFromMenuitemsToHide($menu)
				}
				this.hideOldMenuImmediate();
				$menu.show(flexdropdownmenu.animspeed);
			};
		flexdropdownmenu.showMenu(jQuery, menu, event);
		//reset it
		flexdropdownmenu.showMenu = oldShow;
		/////////
		setOpenElement(menu);
	};
	
	var openChildMenu = function(menu, event){
		private_showMenu(menu, event);
		
		//end - boolean start from back for array
		var findLink = function(lis, end){
			if(lis.length > 0){
				if(end){
					lis = lis.toArray().reverse();
				}
				
				var link, a;
				for(var i = 0, l = lis.length; i<l; i++){
					link = jQuery(lis[i]);
					a = link.find("> a");
					if(a.length > 0){
						return a;
					}
				}
				
			}
		};
		
		
		var lis = menu.find("> li");
		if(lis.length > 0){
			var firstItem = findLink(lis);
			focusItem(firstItem);	//focus the first item in the new menu shown
		
			//if tab shift is called on the first item of the menu - close the menu as the user is leaving the menu
			var tab = function(e){
				var keyCode = e.which || e.keyCode;
				if (keyCode == 9 && e.shiftKey) {
			        closeOpen(menu);
			        firstItem.keydown(tab);
			    }
			}
			firstItem.keydown(tab);
			
			//if the menu has more than 1 LI (entry) also close the menu when the user presses the tab item on the last menu item as the user is also leaving the menu
			if(lis.length > 1){
				var lastItem = findLink(lis, true);
				if(lastItem){
					var tabDown = function(e){
						var keyCode = e.which || e.keyCode;
						if (keyCode == 9 && !e.shiftKey) {
					        closeOpen(menu);
					        lastItem.unbind("keydown");
					    }
					}
					lastItem.keydown(tabDown);
				}
			}
		}
		
	};
	
	//dir == next or prev (jQuery function)
	var topLevelMove = function(dir){
		focusItem(getTopLevelElement().parent()[dir]().find("> a"));
	};
	
	var keyActions = {
			left: function(event){
				event.preventDefault();
				//find the drop down
				var child = getTopLevelElement().parent().find("> ul.jqflexmenu");
				
				//check if exists and 
				if(child.length > 0){
					//check visibility
					if(!child.is(":visible")){
						//top menu - move across one
						topLevelMove("prev");
					}else{
						//sub menu
						var current = getFocusedItem();
						if(current){
							//find its own menu - i.e. the UL where the current LI is present
							var menu = current.closest("ul.subMenu");
							//find the parent of that menu - i.e. the LI where the sub UL is in
							var parent = menu.parent("li").find("> a");
							if(menu.length > 0 && parent.length > 0){
								//close subMenu and focus on parent Link
								closeOpen(menu);
								focusItem(parent);
							}
						}
					}
				}else{
					topLevelMove("prev");	//has no children
				}
			}, 
			right: function(event){
				event.preventDefault();
				//find the drop down
				var child = getTopLevelElement().parent().find("> ul.jqflexmenu");
				
				//check if exists and 
				if(child.length > 0){
					//check visibility
					if(!child.is(":visible")){
						//top menu - move across one
						topLevelMove("next");
					}else{
						var current = getFocusedItem();
						if(current){
							var subMenu = current.next("ul.subMenu");
							if(subMenu.length > 0){
								//open the next level (subMenu) of a menu point
								openChildMenu(subMenu, event);
							}
						}
					}
				}else{
					topLevelMove("next");//has no children
				}
			},
			up: function(event){
				event.preventDefault();
				//find the drop down
				var child = getTopLevelElement().parent().find("> ul.jqflexmenu");
				//check if exists and 
				if(child && child.length > 0){
					//check visibility
					var current = getFocusedItem();
					var li = current.closest("li");
					var prev = li.prev().find("> a");
					
					if(child.is(":visible")){
						if(prev.length > 0){
							//focus on previous entry
							focusItem(prev);
						}else{
							//only if current focus item is not inside a submenu
							var subMenu = current.closest("ul.subMenu");
							if(subMenu.length <= 0){
								//no top item - hide menu and move a level up
								closeOpen(child);
								focusItem(getTopLevelElement());
							}
						}
					}
				}
			},
			down: function(event){
				event.preventDefault();
				//find the drop down
				var child = getTopLevelElement().parent().find("> ul.jqflexmenu");
				//check if exists and 
				if(child.length > 0){
					//check visibility
					var current = getFocusedItem();
					if(!child.is(":visible")){
						openChildMenu(child, event);
					}else{
						//is visible
						var next = current.closest("li").next().find("> a");
						//focus on next entry
						if(next.length > 0){
							focusItem(current.closest("li").next().find("> a"));
						}
					}
				}
			},
			tab_up: function(event){
				var newFocus = jQuery("ul.nav a:focus");
				if(newFocus.length > 0){
					focusItem(newFocus, true);
				}
			}
	};
	
	var keyMapper = {
			onKeyDown: function(e){
				if(getTopLevelElement()){
					var keyCode = e.keyCode || e.which,
				      arrow = {left: 37, up: 38, right: 39, down: 40 }, tab = 9;
					switch (keyCode) {
					    case arrow.left:
					    	keyActions.left(e);
					    	break;
					    case arrow.up:
					    	keyActions.up(e);
					    	break;
					    case arrow.right:
					    	keyActions.right(e);
					    	break;
					    case arrow.down:
					    	keyActions.down(e);
					    	break;
					}
				}
			},
			onKeyUp: function(e){
				if(getTopLevelElement()){
					var keyCode = e.keyCode || e.which,
						tab = 9;
					switch (keyCode) {
						case tab:
					    	keyActions.tab_up(e);
					    	break;
					}
				}
			}
	};	
	
	var registerEvents = function(){
		//register events on topmenu item
		jQuery(".topMenuLink, .topMenuLinkHighlighted").focus(function(){
			closeOpen();
		});
//		jQuery(document).on("focus mouseenter", ".topMenuLink, .topMenuLinkHighlighted", function(event){
//			closeOpen();
//		});
		
		//register keydown actions
		jQuery(document).keydown(keyMapper.onKeyDown).keyup(keyMapper.onKeyUp);
	};
	
	this.init = function(){
		registerEvents();
	};
	
};


jQuery(document).ready(function(){
	
	his_flexdropdown.init();
	
});/**
 * Actions to support angular.
 * Currently the only function is deleting HTML5 SessionStorage keys
 * when clicking certain buttons and links in the JSF frame,
 * like startpage, bookmarks, menu search, menu items.
 */
use_package("de.his.modules");
de.his.modules.angularHelper = new function() {
	
    this.moduleName = "de.his.modules.angularHelper";

    /**
     * Delete all Angular keys from HTML5 SessionStorage.
     */
    this.deleteAngularSessionStorageKeys = function() {
        console.log( 'Delete angular keys from HTML5 SessionStorage...' );
        sessionStorage.removeItem( 'his_cs_sys_last_menu_item' );
        sessionStorage.removeItem( 'his_cs_sys_last_search_url' );
        sessionStorage.removeItem( 'his_cs_sys_last_searchresult_url' );
        sessionStorage.removeItem( 'his_cs_sys_last_back_url' );
    }
};
use_package("de.his.component");

de.his.component.tabsAsDropdown = new function() {
    de.his.modules.ModuleRegistry.registerModule(this).registerAjaxRefreshModule(this);
	this.moduleName = "de.his.component.tabsAsDropdown";    
    this.refresh = function() {
        this.init();
    };

	this.init = function() {
		jQuery('.tabsAsDropdown').each(function(){
		    var $this = jQuery(this);
		    if( !$this.find('.mikronavi_submit-trigger').length ) {
		        var activeText = $this.find('button.active').html();
			    jQuery('<button class="mikronavi_submit-trigger">'+activeText+'</button>').insertBefore($this.children('ul'));
		    }
		});
		
		jQuery('.tabsAsDropdown').off('click').on('click', '.mikronavi_submit-trigger', function(e){
			e.preventDefault();
			var $this = jQuery(this);
			$this.toggleClass('open');
			$this.next('ul').slideToggle(100);
		});

    };
};use_package("de.his.portal");

/**
 * Portal Grid
 */
de.his.portal.grid = new function() {
	de.his.modules.ModuleRegistry.registerModule(this).registerAjaxRefreshModule(this);
		
	this.moduleName = "de.his.portal.grid";

	this.init = function(){		
		if( jQuery('body').hasClass('editNavigationframe') ) {
			drag();
			createGrid();
			configureGrid();
			initial = true;
			if( !jQuery('.gridWrapConfiguration').hasClass('visible') ) {
				jQuery('.gridDDZoneWrap').removeClass('gridDDZone-hide');
			}
		setTimeout(function(){	
				jQuery('#hisinoneHeader').addClass('js-fixed').parent().css({paddingTop:jQuery('#hisinoneHeader').outerHeight()})				
			}, 500);
		}
	}
		
	createGrid = function(){	
		grid = [];

	    jQuery('.gridElement').each(function() {
			$this = jQuery(this);
			
			var widgetPosition = $this.attr('id');
			widgetPosition = widgetPosition.split('_')[1];
			
			$this.find('.draggableEl').each(function(i){
				$this = jQuery(this);
				var widgetType = $this.attr('id');
				widgetType = widgetType.split('_')[0];
				widgetId = $this.data('id');
				item = {}
	        	item["widgetPosition"] = Number(widgetPosition);
	        	item["widgetType"] = widgetType;
				item["widgetId"] = Number(widgetId);
				
				item["widgetSortorder"] = i;
				//item["widgetSortInPos"] = {widgetPosition: Number(widgetPosition) , widgetSortorder: i};
				
				grid.push(item);	
			});
	    });
		// Elemente aus DropZone holen 
		ddzoneIndx = 0;
		jQuery('#gridDDZone').children().each(function(){
			ddzoneIndx++;
			$this = jQuery(this);
			var widgetType = $this.attr('id');
			widgetType = widgetType.split('_')[0];
			widgetId = $this.data('id');
			item = {}
			item["widgetPosition"] = 0;
			item["widgetType"] = widgetType;
			//item["widgetSortorder"] = 999+ddzoneIndx;
			item["widgetId"] = Number(widgetId);
			
			item["widgetSortorder"] = ddzoneIndx;
			//item["widgetSortInPos"] = {widgetPosition: 0 , widgetSortorder: ddzoneIndx};
			
			grid.push(item);
		});
		
		// Reihenfolge in Array schreiben
		/*for (i = 0; i < grid.length; i++){
			if( !grid[i].widgetSortorder ) {
				grid[i].widgetSortorder = i+1;
			}
		}*/
		
		gridString = JSON.stringify(grid);
		document.getElementById('gridForm:gridData').value = gridString;
		
		//console.log(gridString);
		
	}	
	initial = true;	
	var allGridAreasSelected;
	configureGrid = function(){

		var gridAreasString = jQuery('.gridSizeHeader').val(); 
		gridAreasString = gridAreasString.replace(/'/g, '');
		var gridAreas = gridAreasString.split(" ");
		
		var gridAreasStringFooter = jQuery('.gridSizeFooter').val(); 
		gridAreasStringFooter = gridAreasStringFooter.replace(/'/g, '');
		var gridAreasFooter = gridAreasStringFooter.split(" ");
		
				
		if( initial == true ) {			
			createConfigurationGrid(gridAreas, gridAreasFooter);
		}
		// Vorhandenes Grid anzeigen
		function createConfigurationGrid(gridAreas, gridAreasFooter){			

			if( jQuery('.gridWrapConfiguration').find('.gridElementSelected').length == 0 ) {
								
				//Header									
				var gridWithCount = 1;
				for (i = 0; i < gridAreas.length; i++){			
					var pos = i+1;
					var gridElementWidth = jQuery('.gridHeader').find('.gridWrapConfiguration').find('.gridElement').width();	
					if( gridAreas[i] != gridAreas[i-1] ) {
						//console.log(gridAreas[i], pos);
						if( !jQuery('.gridHeader').find('.gridWrapConfiguration').find('.gridElement:nth-child('+pos+')').attr('data-index', gridAreas[i]).find('.gridElementSelected').length ) {
							jQuery('.gridHeader').find('.gridWrapConfiguration').find('.gridElement:nth-child('+pos+')').attr('data-index', gridAreas[i])
							.append('<div class="gridElementSelected"><a class="gridElementSelectedClose iconfont-delete" title="Rasterelement löschen" href="#" ></a><div class="gridElementDragbar"></div></div>');
							gridWithCount = 1; 
						}									
						
					} else {
						gridWithCount++; 
						gridElementWidth = gridElementWidth*gridWithCount;
						jQuery('.gridHeader').find('.gridWrapConfiguration').find('.gridElement[data-index='+gridAreas[i]+']').children('.gridElementSelected').css({width:gridWithCount*100+'%'});
					}
				}
				
				//Footer
				var gridWithCountFooter = 1;			
				for (i = 0; i < gridAreasFooter.length; i++){							
					var pos = i+1;
					var gridElementWidth = jQuery('.gridFooter').find('.gridWrapConfiguration').find('.gridElement').width();
					if( gridAreasFooter[i] != gridAreasFooter[i-1] ) {
						// console.log(gridAreas[i], pos);
						if( !jQuery('.gridFooter').find('.gridWrapConfiguration').find('.gridElement:nth-child('+pos+')').attr('data-index', gridAreasFooter[i]).find('.gridElementSelected').length ) {
							jQuery('.gridFooter').find('.gridWrapConfiguration').find('.gridElement:nth-child('+pos+')').attr('data-index', gridAreasFooter[i])
							.append('<div class="gridElementSelected"><a class="gridElementSelectedClose iconfont-delete" title="Rasterelement löschen" href="#" ></a><div class="gridElementDragbar"></div></div>');
							gridWithCountFooter = 1; 				
						}									
						
					} else {
						gridWithCountFooter++;
						gridElementWidth = gridElementWidth*gridWithCountFooter;
						jQuery('.gridFooter').find('.gridWrapConfiguration').find('.gridElement[data-index='+gridAreasFooter[i]+']').children('.gridElementSelected').css({width:gridWithCountFooter*100+'%'});
				
					}
				}
			}

		}
		
		
		// Grid Konfiguration
		var selectedElements = [];
		var selectedElements2 = [];
		var savedElements = [];
		var savedElements2 = [];		
		
		// Grid Konfiguration ein und ausblenden		
		jQuery('.toggleGridConfig').off('click').on('click', function(){
			if( jQuery('.gridWrapConfiguration').hasClass('visible') ) {
				saveGridConfig();
				// Wenn nicht jedes Gridfeld gefüllt nicht weiter machen
				if( allGridAreasSelected == false ) {
					return false;
				}
				jQuery('#gridForm\\:submitGrid').attr('disabled', false);	
			} else {
				jQuery('#gridForm\\:submitGrid').attr('disabled', true);
			}
			jQuery('.gridWrapConfiguration').toggleClass('visible');
			jQuery('.gridDDZoneWrap').toggleClass('gridDDZone-hide');
			
		});
		// Grid anwenden bei klick auf speichern
		jQuery('.saveGridConfig').off('click').on('click', function(){ 
			saveGridConfig();
		});
		
		jQuery('.toggleLoggedinView').off('click').on('click', function(){ 
			if( !jQuery('.gridWrapConfiguration').hasClass('visible') ) {
				jQuery('body').toggleClass('editNavigationframe_loggedinView');
			}
		});

		// letzten geladene Konfiguratin zurückholen
		/*jQuery('.restoreGridConfig').on('click', function(){
			restoreGridConfig();
		});*/


		// Grid Konfigurieren per Drag
		function resizableGrid() {
			jQuery('.gridElementDragbar').parent().resizable({
					handles: 'e',
					// TODO:
					//Links und rechts dragbar
					//handles: 'e, w',
					containment: "document",
					/*grid: 207,*/
					start: function(event, ui){
						// Lücke für maximale Breite berechnen					
						var $this = jQuery(this);
						var $gridElement = $this.closest('.gridElement');
						var gridElementWidth = $gridElement.outerWidth();
						
						var nextElement = $gridElement.nextAll().find('.gridElementSelected')[0];	
						var prevElement = $gridElement.prevAll().find('.gridElementSelected')[0];				
						$this.resizable( "option", "maxWidth", 0 );
						$this.resizable( "option", "minWidth", gridElementWidth );
						
						var thisTop = $this.offset().top;
						var thisLeft = $this.offset().left;
						if( nextElement ) {
							var nextLeft = jQuery(nextElement).offset().left;
							var nextTop = jQuery(nextElement).offset().top;						
							var maxWidth = nextLeft-thisLeft;
							if( nextTop == thisTop ) {
								$this.resizable( "option", "maxWidth", maxWidth );
							}
						}
						/*if( prevElement && !event.toElement.classList.contains('ui-resizable-e') ) { 
							var prevLeft = jQuery(prevElement).offset().left;
							var prevWidth = jQuery(prevElement).outerWidth();
							var prevTop = jQuery(prevElement).offset().top;						
							var maxWidth = prevLeft+prevWidth-thisLeft;						
							if( prevTop == prevTop ) {
								$this.resizable( "option", "maxWidth", maxWidth );
							}
							console.log('prevElement', prevElement)	
						}*/
						
					},				
					stop: function(){
						// neue Größe berechnen
						var $this = jQuery(this);
						var $gridElement = $this.closest('.gridElement');
						var gridElementWidth = $gridElement.outerWidth();
						var thisWidth = $this.outerWidth();
						var newWidth = (thisWidth/gridElementWidth);
						newWidth = Math.round(newWidth); 
						$this.css({width: 100*newWidth+'%'});
					},
					resize: function(){
					},				
					 
			});
		} resizableGrid();
		// Grid Konfigurieren per Click
		jQuery('.gridWrapConfiguration').find('.gridElement').off('click').on('click', function(e){
			var $this = jQuery(this);
			if(e.target.classList.contains('gridElement')) {				
				// wenn nicht vorhanden element anlegen
				if( !$this.find('.gridElementSelected').length ) {
					$this.append('<div class="gridElementSelected"><a class="gridElementSelectedClose iconfont-delete" title="Rasterelement löschen" href="#" ></a><div class="gridElementDragbar"></div></div>')
					// wenn vorhanden auswahl erweitern
				} 
				resizableGrid();
				/*if( !jQuery('.gridElementSelectedActive').length ) {
					$this.append('<div class="gridElementSelected gridElementSelectedActive"><a class="gridElementSelectedSave iconfont-save_mono" href="#" ></a><a class="gridElementSelectedClose iconfont-delete" href="#" ></a><div class="gridElementDragbar"></div></div>')
					// wenn vorhanden auswahl erweitern
				} else {
					var selectedLeft = jQuery('.gridElementSelectedActive').offset().left;
					var thisLeft = $this.offset().left;
					
					// nur positive Clicks zulassen
					if( selectedLeft <= thisLeft ) {
						var thisWidth = $this.width();
						var newWidth = thisLeft-selectedLeft + thisWidth;
						jQuery('.gridElementSelectedActive').css({width:newWidth});
					}
				}	*/						
			}
		});
		
		// Element bearbeiten
		jQuery('.gridWrapConfiguration').find('.gridElement').on('click', '.gridElementSelectedEdit', function(){
			jQuery(this).closest('.gridElementSelected').addClass('gridElementSelectedActive');
		});
		
		// Element entfernen und array leeren
		jQuery('.gridWrapConfiguration').find('.gridElement').on('click', '.gridElementSelectedClose', function(){
			jQuery(this).closest('.gridElementSelected').remove();
			// selectedElements = [];
		});
				
		function collectAllItems() {			
			/*Header*/			
			var selectedCounter = 0;
			var selectedCounterArr = [];
			jQuery('.gridHeader').find('.gridWrapConfiguration').find('.gridElementSelected').each(function(){
				var $thisSelected = jQuery(this);
				var selectedLeft = $thisSelected.offset().left;
				var selectedWidth = $thisSelected.outerWidth();
				var selectedTop = $thisSelected.offset().top;
				var activeRange = selectedLeft+selectedWidth;
				// alle gridelemente finden die überlagert werden von der Auswahl und in Array legen
				$thisSelected.closest('.gridWrapConfiguration').find('.gridElement').each(function(){
					$this = jQuery(this);
					var gridElementLeft = $this.offset().left;
					var gridElementWidth = $this.outerWidth();
					var gridElementRange = gridElementLeft+gridElementWidth;
					var gridElementTop = $this.offset().top;					
					if(Math.round(gridElementLeft) >= Math.round(selectedLeft) && Math.round(activeRange) >= Math.round(gridElementRange) && selectedTop == gridElementTop ) {
						var id = $this.attr('id').split('_')[1];
						selectedElements.push(id);
						
						// Gridfelder sammeln um zu prüfen ob alle gefüllt sind
						selectedCounter++;
						selectedCounterArr.push(selectedCounter);						
					}
				});		
				var selectedId = $thisSelected.parent().attr('id').split('_')[1];				
				savedElements.push({selectedElements, selectedId});				
		 		selectedElements = [];
			
				// Elemente in nicht definierten Areas finden
				jQuery('.gridHeader.gridWrap:not(.gridWrapConfiguration)').children('#gridElement_'+selectedId).addClass('inuse');					
			});			
							
			/*Footer*/			
			jQuery('.gridFooter').find('.gridWrapConfiguration').find('.gridElementSelected').each(function(){
				var $thisSelected = jQuery(this);
				var selectedLeft = $thisSelected.offset().left;
				var selectedWidth = $thisSelected.outerWidth();
				var selectedTop = $thisSelected.offset().top;
				var activeRange = selectedLeft+selectedWidth;
				// alle gridelemente finden die überlagert werden von der Auswahl und in Array legen
				$thisSelected.closest('.gridWrapConfiguration').find('.gridElement').each(function(){
					$this = jQuery(this);
					var gridElementLeft = $this.offset().left;
					var gridElementWidth = $this.outerWidth();
					var gridElementRange = gridElementLeft+gridElementWidth;
					var gridElementTop = $this.offset().top;
					if(Math.round(gridElementLeft) >= Math.round(selectedLeft) && Math.round(activeRange) >= Math.round(gridElementRange) && selectedTop == gridElementTop ) {
						var id = $this.attr('id').split('_')[1];
						selectedElements2.push(id);
						
						// Gridfelder sammeln um zu prüfen ob alle gefüllt sind
						selectedCounter++;
						selectedCounterArr.push(selectedCounter);
					}					
				});				
				var selectedId = $thisSelected.parent().attr('id').split('_')[1];				
				savedElements2.push({selectedElements2, selectedId});	
		 		selectedElements2 = [];
			
				// Elemente in nicht definierten Areas finden
				jQuery('.gridFooter.gridWrap:not(.gridWrapConfiguration)').children('#gridElement_'+selectedId).addClass('inuse');					
			});
			
			// Püfen ob alle Gridfelder gefüllt sind
			if( selectedCounterArr.length != 20 ) {
				allGridAreasSelected = false;
			} else {
				allGridAreasSelected = true;
			}
			
			// Wenn nicht jedes Gridfeld gefüllt nicht weiter machen
			if( allGridAreasSelected == false ) {
				return false;	
			}
			// wenn LoginForm wegkonfigurtiert			
			if( jQuery('.gridWrap:not(.gridWrapConfiguration)').find('.gridElement:not(.inuse)').find('#loginForm_DragID.draggableEl').length ) {
				document.getElementById('gridForm:isLoginFormVisible').value = false;
				jQuery('#gridForm\\:isLoginFormVisible').trigger('change');	
			}  
			// nicht in Raster positionierte Widgets in Dropzone legen
			// Productlogo darf nicht entfernt werden und wird wieder in den Footer gelegt
			jQuery('.gridWrap:not(.gridWrapConfiguration)').find('.gridElement:not(.inuse)').find('.draggableEl:not(.productLogo)').prependTo('#gridDDZone');
			jQuery('.gridWrap:not(.gridWrapConfiguration)').find('.gridElement:not(.inuse)').find('.draggableEl.productLogo').appendTo('#gridElement_11');
			jQuery('.gridWrap').find('.gridElement.inuse').removeClass('inuse');
	
		}		

		this.saveGridConfig = function() {
			// Neue Auswahl in vorhandenem Array ändern		
			collectAllItems();			
			// Wenn nicht jedes Gridfeld gefüllt nicht weiter machen
			if( allGridAreasSelected == false ) {
				jQuery('.triggerAllGridAreasSelectedMessage').trigger('click');
				return false;	
			} else {
				if( jQuery('.error_infobox').length ) {
					jQuery('.infobox_close').trigger('click');
				}
			}
			
			//Header
			for (i = 0; i < savedElements.length; i++){
				gridElement = savedElements[i].selectedId;
				elements = savedElements[i].selectedElements;
				for (i2 = 0; i2 < elements.length; i2++){
					gridAreas[elements[i2]-1] = 'grid'+ gridElement;
				}
			}		
			// Ausgabe für css Aufbereiten
			var gridAreasCss1 = [];
			var gridAreasCss2 = [];			
			for (i = 0; i < gridAreas.length; i++){
				if(i < 5) {
					gridAreasCss1.push(gridAreas[i]);
				} else {
					gridAreasCss2.push(gridAreas[i]);
				}
			}
			var gridAreasCss = "'" + gridAreasCss1.join(' ') + "' '"+ gridAreasCss2.join(' ') + "'";
			//console.log('gridAreasCss', gridAreasCss);
			jQuery('.gridSizeHeader').val(gridAreasCss);
			jQuery('.gridHeader').css({gridTemplateAreas: gridAreasCss});
			savedElements = [];
			
			//Footer
			for (i = 0; i < savedElements2.length; i++){
				gridElement = savedElements2[i].selectedId;				
				elements = savedElements2[i].selectedElements2;
				for (i2 = 0; i2 < elements.length; i2++){
					gridAreasFooter[elements[i2]-11] = 'grid'+ gridElement;
				}
			}
			var gridAreasCss1_2 = [];
			var gridAreasCss2_2 = [];			
			for (i = 0; i < gridAreasFooter.length; i++){
				if(i < 5) {
					gridAreasCss1_2.push(gridAreasFooter[i]);
				} else {
					gridAreasCss2_2.push(gridAreasFooter[i]);
				}
			}
			var gridAreasCss_2 = "'" + gridAreasCss1_2.join(' ') + "' '"+ gridAreasCss2_2.join(' ') + "'";
			jQuery('.gridSizeFooter').val(gridAreasCss_2);
			jQuery('.gridFooter').css({gridTemplateAreas: gridAreasCss_2});
			savedElements2 = [];
		};
		
	}

	this.submitGrid = function() {
		jQuery('.saveGridConfig').trigger('click');
		createGrid();
		setTimeout(function(){
			configureGrid();
		},800);
		
		initial = false;
		// Wenn nicht jedes Gridfeld gefüllt nicht weiter machen
		if( allGridAreasSelected == false ) {
			de.his.modules.Waiting.resetWaitingBehaviour();
			return false;	
		} 
    }
	
	
	var drag = function(){
		
		/*jQuery('<button type="button" class="saveGrid">ShowArray</button>').insertAfter('#hisinoneHeader');
		jQuery('.saveGrid').off('click').on('click',function(){
			createGrid();
		});*/

		var $dropZone = jQuery('.gridElement, #gridDDZone'); 
		var $dragElement = jQuery(".draggableEl");
		 $dragElement.attr('draggable', 'true');
		
		
		var originalPosX;
  		var originalPosY;
		var currPosX;
		var currPosY;
		
		jQuery('body').on('dragover', function(e){
			currPosX = e.clientX;
			currPosY = e.clientY;
			jQuery('.js-dragClone').css({left: currPosX, top: currPosY});
		});
	
		$dragElement.on('dragstart', function(e){
			
			originalPosX = jQuery(this).offset().left;
  			originalPosY = jQuery(this).offset().top;
		  				
			$dropZone.addClass('dragactive');			
			jQuery(this).addClass('onthedrag');			
			if( !jQuery('.js-dragClone').length ) {
				jQuery(this).clone().addClass('js-dragClone').css({left: originalPosX, top: originalPosY}).appendTo('body');
			}
			
			var thisId = jQuery(e.target).closest("[draggable=true]").attr('id');
			localStorage.setItem('dataTransferObject', thisId);
			
			if( jQuery(this).hasClass('productLogo') ) {
				jQuery('.gridDDZoneWrap').addClass('gridDDZone-hide');						
			}
			
		}).on('dragend', function(e){
			if( e.originalEvent.dataTransfer.dropEffect == 'none' ) {
				jQuery('.js-dragClone').animate({'top':originalPosY, 'left':originalPosX},400);
			}
			
			$dragElement.removeClass('onthedrag');
			if( jQuery('.js-dragClone').length ) {
				setTimeout(function(){
					jQuery('.js-dragClone').remove();
					jQuery('.gridDDZoneWrap').removeClass('gridDDZone-hide');
				},400);
			}
		});
		
		$dropZone.off('drop').on('drop', function(e){
			e.preventDefault();
			var ev = e;
			var data = localStorage.getItem('dataTransferObject');
			setTimeout(function(){
				$dropZone.removeClass('dragactive dragover');
				if( ev.target.classList.contains('gridElement') || ev.target.id.contains('gridDDZone') ) {
					ev.target.appendChild(document.getElementById(data));
				} 
				else {					
					var $closestDragZone = jQuery(ev.target).closest("[draggable=true]");					
					$closestDragZone[0].before(document.getElementById(data));
				}					
				
				// wenn LoginForm wegkonfigurtiert
				if( data.contains('loginForm') ) {
					if( ev.currentTarget.id.contains('gridDDZone')  ) {
						document.getElementById('gridForm:isLoginFormVisible').value = false;
						jQuery('#gridForm\\:isLoginFormVisible').trigger('change');
					} else {
						document.getElementById('gridForm:isLoginFormVisible').value = true;
						jQuery('#gridForm\\:isLoginFormVisible').trigger('change');
					}
				}
				
				localStorage.removeItem('dataTransferObject');
				jQuery('#hisinoneHeader').addClass('js-fixed').parent().css({paddingTop:jQuery('#hisinoneHeader').outerHeight()});
			},400);
			jQuery('.js-dragClone').addClass('bye');
		});
		
		
		/*$dropZone.on('dragenter', function(e){
			e.preventDefault();			
			jQuery(this).addClass('dragover');
		});*/
		
		$dropZone.on('dragleave', function(e){
			e.preventDefault();
			jQuery(this).removeClass('dragover');
		});
		
		$dropZone.on('dragover', function(e){
			jQuery(this).addClass('dragover');
			e.preventDefault();
		});
	}
	
	
	
	this.refresh = function() {
		this.init();
	};
};
/**
 * @Author: jgrimm
 */
use_package("de.his.modules");
de.his.modules.HISinOneGallery = new function() {
	de.his.modules.ModuleRegistry.registerModule(this).registerAjaxRefreshModule(this);
	
    this.moduleName = "de.his.modules.HISinOneGallery";
    var intervalId;
    
    this.init = function() {
		jQuery(".hisinone-gallery").each(function() {
			var currentGallery = jQuery(this);
			de.his.modules.HISinOneGallery.initGallery(currentGallery);
		});
    }
    
    this.refresh = function() {
    	de.his.modules.HISinOneGallery.init();
    }
    
    this.initGallery = function(gallery) {
		// init/compute image metadata
		gallery.data("imageCount", 0);
		gallery.children("img").each(function(index) {
			var galleryImage = jQuery(this);
			
			galleryImage.data("index", index);
			
			// set title to filename if not available
			var title = galleryImage.attr("title");
			if (!title) {
				var src = galleryImage.attr("src");
				var srcParts = src.split('/');
				var filename = srcParts[srcParts.length - 1];
				galleryImage.attr("title", filename);
			}
			
			// set alt to title if not available
			var alt = galleryImage.attr("alt");
			if (!alt) {
				galleryImage.attr("alt", galleryImage.attr("title"));
			}
			
			gallery.data("imageCount", gallery.data("imageCount") + 1);
		});
		
		if(!gallery.data("initialized")){
			// init gallery nav and captions
			gallery.append("<div class='hisinone-gallery-nav-caption'>" + de.his.modules.HISinOneGallery.galleryContentMarkup(null, '', null)+ "</div>");
			gallery.append("<div class='hisinone-gallery-nav'><a href='#' class='hisinone-gallery-nav-button hisinone-gallery-nav-last' title='Zurück' alt='Zurück'><span class='unsichtbar'>Zurück</span></a> <a href='#' class='hisinone-gallery-nav-button hisinone-gallery-nav-next' title='Weiter' alt='Weiter'><span class='unsichtbar'>Weiter</span></a></div>");
			
			// register click handlers for navigation
			gallery.find(".hisinone-gallery-nav-last").click(de.his.modules.HISinOneGallery.last);
			gallery.find(".hisinone-gallery-nav-next").click(de.his.modules.HISinOneGallery.next);
			
			// start with image 0
			gallery.data("currentImageIndex", 0);
			de.his.modules.HISinOneGallery.setGalleryImage(gallery, -1, 0);
			
			// start image interval
			var interval = gallery.data("interval");
			if (interval) {
				intervalId = setInterval(function() {
					de.his.modules.HISinOneGallery.changeImage(gallery, 1);
				}, interval);
			}
		}
		gallery.data("initialized", true);
	}
	
	/**
	 * show last image
	 */
	this.last = function() {
		var gallery = jQuery(this).closest(".hisinone-gallery");
		de.his.modules.HISinOneGallery.changeImage(gallery, -1);
		clearInterval(intervalId);
		return false;
	}
	
	/**
	 * show next image
	 */
	this.next = function() {
		var gallery = jQuery(this).closest(".hisinone-gallery");
		de.his.modules.HISinOneGallery.changeImage(gallery, 1);
		clearInterval(intervalId);
		return false;
	}
	
	/**
	 * change image by 'currentIndex + amount' where amount can be positive or negative
	 */
	this.changeImage = function(gallery, amount) {
		if (!amount || amount == 0) {
			return;
		}
		
		var galleryImageCount = gallery.data("imageCount");
		var currentImageIndex = gallery.data("currentImageIndex");
		var nextImageIndex = de.his.modules.HISinOneGallery.getNextImageIndex(galleryImageCount, currentImageIndex, amount);

		de.his.modules.HISinOneGallery.setGalleryImage(gallery, currentImageIndex, nextImageIndex);
	}
	
	/**
	 * compute next image index
	 * @param images number of images
	 * @param current index of current image
	 * @param change amount to change the current index 
	 */
	this.getNextImageIndex = function(images, current, change) {
		var next = current + change;
		while (next < 0) {
			next += images;
		}
		
		return next % images;
	}
	
	/**
	 * changes the image
	 */
	this.setGalleryImage = function(gallery, lastImageIndex, nextImageIndex) {
		// hide previous image
		if (lastImageIndex >= 0) {
			var lastImage = jQuery(gallery.children("img")[lastImageIndex]);
			lastImage.fadeOut();
		}
		
		// show next image
		var nextImage = jQuery(gallery.children("img")[nextImageIndex]);
		nextImage.fadeIn();
		gallery.data("currentImageIndex", nextImageIndex);
		
		// copy link from image to gallery
		var href = nextImage.data("href");
		var title = nextImage.attr("title");
		var alt = nextImage.attr("alt");
		var content = gallery.find(".hisinone-gallery-nav-content");
		content.replaceWith(de.his.modules.HISinOneGallery.galleryContentMarkup(href, title, alt));
		
		// copy image caption
		var caption = nextImage.data("caption");
		var text = gallery.find(".hisinone-gallery-nav-text");
		if (caption) {
			text.fadeIn();
			text.text(caption);
		} else {
			text.fadeOut();
			text.text("");
		}
	}
	
	this.galleryContentMarkup = function(href, title, alt) {
		if (!href) {
			return "<div title='" + title + "' class='hisinone-gallery-nav-content'><span class='hisinone-gallery-nav-text'></span></div>";
		}
		
		return "<a href='" + href + "' title='" + title + "' alt='" + alt + "' class='hisinone-gallery-nav-content' target='_blank'><span class='hisinone-gallery-nav-text'></span></a>";
	}
    
};/*****************************************************************************
* Include in diesen Datei ändern: layoutHISinOne*.xhtml
*
* portalHelper: Funktionen die von unterschiedlichen Stellen aufgerufen werden
*****************************************************************************/


/**
 * Funktion um Text zu kürzen
 * TODO hier evtl noch ein wenig optimieren
 */
function resizeText(maxLength, str ) {
	if (str == null || maxLength == null || str == "" || maxLength == "" || str.length < 1) {
		return str;
	}
	
	var dummy = document.createElement("div");
	
	dummy.innerHTML = str;
	dummy.style.whiteSpace = "nowrap";
	dummy.style.position = "absolute";
	dummy.style.top = "-100px";
	document.body.appendChild(dummy);
	var breite = dummy.scrollWidth;
	if (breite == null || breite == "" || breite < 0) {
		return str;
	}	
	document.body.removeChild(dummy);
	maxLength -= 110;
	if (breite > maxLength) {
		newbreite = breite;
		var sicherung = 0;
		while(newbreite > maxLength) {
			str = str.substr(0,str.length - 1)
			var dummy = document.createElement("div");
			dummy.innerHTML = str;
			dummy.style.whiteSpace = "nowrap";
			dummy.style.position = "absolute";
			dummy.style.top = "-100px";
			document.body.appendChild(dummy);
			newbreite = dummy.scrollWidth;
			document.body.removeChild(dummy);
			// Sicherheitsabfrage Schleife beenden
			if (sicherung > 50) {
				break;
			}
			sicherung++;
		}
		return (str + "...");
	} else {
		return	str;		
	}
};

/**
 * Entfernt ein Html-Element mit der übergeben ID aus dem DOM-Baum
 * @param clientId
 */
function removeHtmlElement(clientId) {
	if (clientId == null) {
		return;
	}
	if (document.getElementById(clientId) == null) {
		return;
	}
	document.getElementById(clientId).style.display  = 'none';
}

/**
 * Entfernt ein HTML-Element oder fügt wieder eines hinzu mit einer "coolen" Animation
 * @param clientId
 */
function toggleHtmlElementWithEffect(clientId) {
	if (clientId == null ||clientId == "") {
		return;
	}
	if (document.getElementById(clientId) == null) {
		return;
	}
	if (clientId.indexOf(':')>=0) {
		clientId = de.his.common.Util.toJQueryId(clientId);
	}
	jQuery("#"+clientId).fadeToggle("fast", "linear");
}

/**
 * Fügt ein Html-Element mit der übergeben ID wieder als Block-Element hinzu 
 * @param clientId
 */
function restoreHtmlElement(clientId) {
	if (clientId == null) {
		return;
	}
	if (document.getElementById(clientId) == null) {
		return;
	}
	document.getElementById(clientId).style.display  = 'block';
}

/**
 * Fügt ein Html-Element mit der übergeben ID wieder als Inline-Element hinzu 
 * @param clientId
 */
function restoreHtmlElementInline (clientId) {
	if (clientId == null) {
		return;
	}
	if (document.getElementById(clientId) == null) {
		return;
	}
	document.getElementById(clientId).style.display  = 'inline';
}

/**
 * Schließt die Sidebar/Infobox
 * 
 * @param contextPath
 * @param clientId
 * @param sidebarContentId
 */
function closeSidebar(contextPath, clientId, sidebarContentId) {
	toggleHtmlElementWithEffect(sidebarContentId);	
//	if (renderFixed != "true") {
//		document.getElementById('portalContent').style.width = '99%';
//	}
//	restoreHtmlElement(sidebarContentId);
	
	// Ajax ausführen
	var ajaxToken = getAjaxToken();
	jQuery.ajax( {
		type: 'POST',
		url : contextPath+'/pages/cs/sys/portal/sidebarAjaxReqest.faces',
		data: ({ 
			ajaxToken :ajaxToken, 
			clientId:clientId 
		}),
		error :  function() {
			de.his.ajax.Refresher.onError('Fehler beim Schließen der Sidebar');
		}
	}); 
}

/**
 * Öffnet die Sidebar/Infobox
 * @param contextPath
 * @param clientId
 * @param sidebarContentId
 */
function openSidebar(contextPath, clientId, sidebarContentId) {
//	removeHtmlElement('clipboardWhitoutContent');	
//	if (renderFixed != "true") {
//		document.getElementById('portalContent').style.width = '73%';
//	}
	toggleHtmlElementWithEffect(sidebarContentId);
	
	// Ajax ausführen
	var ajaxToken = getAjaxToken();
	jQuery.ajax( {
		type: 'POST',
		url : contextPath+'/pages/cs/sys/portal/sidebarAjaxReqest.faces',
		data: ({ 
			ajaxToken :ajaxToken, 
			clientId:clientId 
		}),
		error :  function() {
			de.his.ajax.Refresher.onError('Fehler beim Öffnen der Sidebar');
		}
	}); 
}

/**
 * Trigger for navigation open/close.
 * @returns
 */
//function resizeIframesIfAvailable(){
//	console.log("resizing iframe if available ");
//	jQuery("iframe").each(function(){
//		if(jQuery(this).parent().hasClass('frameWrapper')){
//			resizeContent(jQuery(this).attr('id'));
//		}
//	});
//}

/**
 * @ DEPRICATED
 * Berechnet die Größe des Inhaltsbereichs neu und setzt diese Größe
 * Dafür müssen bestimmte Id vorhanden sein: TODO Umstellen auf Klassen und einheitlicher
 * @param clientId
 */
//function resizeContent(clientId) {
//	console.log("RESIZING CONTENT FOR "+ clientId);
//    var $iframe;
//	if ( clientId ) {
//	    $iframe = jQuery( "iframe[id$=" + clientId + "]" ); //ends with client id
//	    if ( $iframe.length ) {
//	        
//	        if( $iframe.data( "his-iframe-loaded" ) ) {
//	            resizeIt( $iframe );
//	        } else {
//	            de.his.modules.eventRegistry.addListener( "iframe_loaded_" + $iframe.attr( "id" ), function() {
//	                resizeIt( $iframe );
//	                $iframe.data( "his-iframe-loaded", true );
//	            } );  
//	        }
//	    }
//	}
//}

function resizeIt( $iframe ){
	/**
	 * TODO: refactor to iFramePortletResize.
	 */
	console.log("RESIZE IT "+ $iframe.attr( "id" ));
    var winHeight = jQuery( window ).height(),
        $body,
        $footer,
        top,
        $mainContent,
        height = 0,
        $header,
        $parent = $iframe.parent();

        /**
         * Fälle:
         * 
         * Jeweils für ganzseitige iFrames und iFrame Portlets. (duh!)
         * 
         * 1. Seite auf gleicher Domain, fixierte Header und Footer deaktiviert
         * 2. Seite auf gleicher Domain, fixierte H&F aktiv
         * 3. X-Domain, fixed H&F deaktiviert
         * 4. X-Domain, fixed H&F aktiv
         */
    
    try {
    	// Bei iFrames die Seiten mit der gleichen Domain einbinden, 
    	// die volle Höhe des iFrames ermitteln und als Höhe des parents setzen.
    	// margins und paddings der Kindelemente nicht mit einbeziehen.
        var $content = jQuery( $iframe[ 0 ].contentWindow.document.body );
        if ( $content.length ) {
        	
        	/**
        	 * same-origin iframe
        	 */
        	var	contentHeight = jQuery( $iframe[ 0 ].contentWindow.document).outerHeight(true);
        	
        	if(contentHeight !== $parent.innerHeight()){
        		console.log("content Height of IFrame: "+ contentHeight + " parent:" + $parent.innerHeight());
        		// +1 removes 1px microscrollbars in infobox on mobile
        		$parent.height( 1 + contentHeight );// + childPadding); 
        	}else{
        		console.log("(no resize) content Height of IFrame: "+ contentHeight + " parent:"+ $parent.innerHeight());
        	}
            
        } else {
            //needed for safari - doesn't throw an error with cors
            throw new Error();
        }
    } catch( e ) {
    	/**
    	 * wenn fehler fliegt:  x-origin iframe
    	 */
        $footer = jQuery( "#hisinoneFooter" );
        $mainContent = jQuery( "#contentFrame" );
        $header = jQuery( "#hisinoneHeader" );
        $body = jQuery( "body" );
        $title = jQuery( "#hisinoneTitle" );
        $permissionQuery = jQuery( "#askForNotificationPermission" );
        	
        // childrens have paddings and margins that can change when the CSS is changed. 
        // Take them into account.
        childrenPadding = getChildrenPaddingAndMargin($mainContent);
        childrenPadding += getElementPaddingMarginAndBorder(jQuery( ".his_main_content" ));
        childrenPadding += getElementPaddingMarginAndBorder(jQuery( "#clearer" ));
        
    	if($permissionQuery.length && !$permissionQuery.hasClass("unsichtbar")){
    		// wenn Anfrage für push da ist und ganzseitig, höhe dazu nehmen.
    		childrenPadding += $permissionQuery.outerHeight(true)+3;
    	}
            
        childrenPadding += $title.outerHeight(true); // 
        
        bodyHeight = $body.outerHeight();
        
        headerHeight = $header.outerHeight(true);
        
        footerHeight = $footer.outerHeight(true);
        
        contentPaddingMargin = childrenPadding; 
        
        height = bodyHeight - footerHeight - headerHeight - childrenPadding;
        
        console.log("bodyHeight: "+ bodyHeight);
        console.log("headerHeight: "+ headerHeight);
        console.log("footerHeight: "+ footerHeight);
        console.log("contentPaddingMargin: "+ contentPaddingMargin);
        console.log("height: "+ height);
        
        if(height !== $parent.innerHeight()){
        	$parent.height( height );
        }
        
    }
    makeAppleScroll($iframe[ 0 ]);
}

//function resizeIframeOnXDomain(){
//	if( jQuery( "body.fixedLayout" ).length ){
//		
//	}else{
//		
//	}
//}
//
//function resizeIframeOnSameDomain(){
//	if( jQuery( "body.fixedLayout" ).length ){
//		
//	}else{
//		
//	}
//}

function getChildrenPaddingAndMargin(jQueryElement){
	 mainContentChildren = jQueryElement.find("*");
	 
	 // padding und margin vom content div mit einbeziehen.
	 childrenPadding = getElementPaddingMarginAndBorder(jQueryElement);
     mainContentChildren.each(function(){
         if(jQuery(this).is(":hidden") || jQuery(this).hasClass('unsichtbar') || jQuery(this).parents().hasClass('unsichtbar')){
             //do nothing
         }else{
             childrenPadding += getElementPaddingMarginAndBorder(jQuery(this));
         }
     });
     console.log("childrenPadding: "+ childrenPadding);
     return childrenPadding;
}

function getElementPaddingMarginAndBorder(jQueryElement){
	 var bordT = jQueryElement.outerHeight() - jQueryElement.innerHeight();
     var paddT = jQueryElement.innerHeight() - jQueryElement.height();
     var margT = jQueryElement.outerHeight(true) - jQueryElement.outerHeight();
     var paddMargBord = paddT+margT+bordT;
     
     console.log("child id: #"+ jQueryElement.attr('id'));
//     console.log("child class: ."+ jQueryElement.attr('class'));
//     console.log("padd+marg+bord: "+ paddMargBord);
     
     return paddMargBord;
}

function makeAppleScroll(element){
	// Configure for scrolling peculiarities of iPad and iPhone

	if (navigator.userAgent.indexOf('iPhone') != -1 || navigator.userAgent.indexOf('iPad') != -1){
		var iFrame = jQuery(element);
		var iframeWrapper = iFrame.parent();
		var iframeWidth = iFrame.width();
		var bodyWidth = jQuery("body").width();
		console.log("makeAppleScroll");
		console.log("iframeWrapper "+iframeWrapper);
		console.log("iframeWidth "+iframeWidth);
		
		var iframeHeight = iFrame.height();
		var bodyHeight = jQuery("body").height();
		console.log("iframeHeight "+iframeHeight);
		
		var lang = de.his.common.LanguageHelper.currentLanguage();
		
		if(jQuery("#appleLinkToIframeSrc").length === 0){
			if(lang==='en'){
				var linkText = "Open embedded site in new window.";
			}
			if(lang==='de'){
				var linkText = "Eingebettete Seite in einem neuen Fenster öffnen.";
			}
			jQuery('#hisinoneIframePage').prepend('<a id="appleLinkToIframeSrc" href="'+iFrame.attr('src')+'" target="_blank">'+linkText+'</a>');
		}
		
		/**
		 * There are no margins and padding on wrapper or iframe that could be taken into account.
		 */
//		var paddWrapper = iframeWrapper.innerWidth() - iframeWrapper.width();
//		var margWrapper = iframeWrapper.outerWidth(true) - iframeWrapper.outerWidth();
//		
//		iframeWrapper.prepend("<div>Wrapper Padding: "+paddWrapper+"px ; Wrapper Margin: "+margWrapper+"px </div>")
//		
//		var paddiFrame = iFrame.innerWidth() - iFrame.width();
//		var margiFrame = iFrame.outerWidth(true) - iFrame.outerWidth();
//		
//		iframeWrapper.prepend("<div>Frame Padding: "+paddiFrame+"px ; Frame Margin: "+margiFrame+"px </div>")
		
		// workaround for fixed Header and Footer
		if( jQuery( "body.fixedLayout" ).length ){
			jQuery(".fixedElements").css('height','auto');
			jQuery(".fixedLayout").css('overflow','auto');
			iframeWrapper.css('overflow','auto');
		}
		// NO change of width... renders iframe portlets ugly... 
		// create a responsive CSS for the child site INSTEAD.
//		if (iframeWidth > bodyWidth){
//			// not quite sure, why these addings (+90 and +120) are needed in some cases, but them do no harm in other scenarios
//			iframeWrapper.css('width',90+iframeWidth + 'px');
//			jQuery("body").css('width',120+iframeWidth + 'px');
//		}
		
		if (iframeHeight > bodyHeight){
			iframeWrapper.css('height',iframeHeight + 'px');
		}
	}
};

/**
 * Berechnet die Höhe eines Elements
 * @param elem
 * @returns Höhe
 */
function getOffsetHeight(elem) {
	if (jQuery(elem) != null && jQuery(elem)[0] != null) {
		return jQuery(elem)[0].offsetHeight;
	}
	return 0;
}

/**
 * Bei fixem Header und Footer den Header berechnen, damit das Navigationsmenü vollständig hinein passt
 */
function resizeHeader() {
//	if(jQuery('#hisinoneHeader').hasClass("header_fixed")){
//		if(jQuery("html.tablet.ios").length){
//			jQuery('.content_portal_hisinone_fixed').css('margin-top', jQuery('#hisinoneHeader').height() + 5  + "px");	
//		}else{
//			jQuery('.content_portal_hisinone_fixed').css('top', jQuery('#hisinoneHeader').height() + "px");	
//		}
//	}
}

/**
 * Hole Ajax Token
 * @returns token
 */
function getAjaxToken() {
	var ajaxToken = document.getElementById("ajaxToken").value;
	return ajaxToken;
}

/**
 * Ein Icon toggeln, also abwechselend das eine und mal das andere anzeigen
 * @param clientId
 * @param img0
 * @param img1
 */
function toggleIcon(clientId, img0, img1) {
	var img = document.getElementById(clientId).src;
	if (img == null) {
		return;
	}
	if (img.endsWith(img0)) {
		document.getElementById(clientId).src = img1;
	} else {
		document.getElementById(clientId).src = img0;
	}
}

/**
 * Icon toggeln, wenn es das Kind-Element eines Links ist
 * @param a
 * @param img0
 * @param img1
 */
function toggleIconAsChild(a, img0, img1) {
	if (a == null) {
		return;
	}
	var clientId = jQuery(a).children('img').attr('id');
	toggleIcon(clientId, img0, img1);
}

/**
 * ??
 * @param elem
 */
function toggleCCDiff(elem) {
	if (elem == null) {
		return;
	}
	jQuery(elem).parent().find(".ccDiff").fadeToggle("fast", "linear");
}

/**
 * Das Navigationsmenü, Breadcrumb, usw. deaktiveren oder aktiveren
 * EXP, wird nicht verwendet
 */
function lockOrUnlockNavigation () {
	//Linkes Menü deaktivieren
	var isLock = false;
	//Topmenü
	var menu = jQuery('.topMenuContainer .flexdropdownmenu');
	if (menu != null) {
		isLock = jQuery('.topMenuContainer').attr('title') != null;
	} else {
		return;
	}
	lockMenu(menu, isLock);
	
	//linkes Menü
	menu = jQuery('#leftTopMenu .auflistung');
	lockMenu(menu, isLock);
	
	//Krümelpfad
	menu = jQuery('.divBreadcrumb a');
	lockMenu(menu, isLock);
	
	if (isLock) {
		//Entsperren 
		unFadeMenu('.topMenuContainer');
		unFadeMenu('#leftTopMenu');
		unFadeMenu('.divBreadcrumb');
	} else {
		//Sperren
		fadeMenu('#leftTopMenu');
		fadeMenu('.topMenuContainer');
		fadeMenu('.divBreadcrumb');
	}
	//Topmenü deaktiveren
	
	//Krümelpfad deaktivieren
}

/**
 * Menü sperren oder entsperren (EXP)
 */
function lockMenu(menu, isLock) {
	if (menu == null) {
		return;
	}
	jQuery.each(menu, function() {
		if (isLock) {
			//Entsperren
			jQuery(this).attr('onclick', '');
		} else {
			//Sperren
			jQuery(this).attr('onclick', 'return false;');
		}
	});
}

/**
 * ???
 * @param clientId
 */
function unFadeMenu(clientId) {
	jQuery(clientId).fadeTo(200,1);
	jQuery(clientId).attr('title',null);
}

/**
 * ???
 * @param clientId
 */
function fadeMenu(clientId) {
	jQuery(clientId).fadeTo(400,0.4);
	jQuery(clientId).attr('title','Dieses Menü wurde gesperrt. Zum entsperren klicken Sie bitte auf den Entsperren-Button oben rechts im Kopfbereich der Seite.');
}

/**
 * Spezielle Bildergalerie in der Infobox-Verwaltung
 */
function showImageOnmouseover() {
//	jQuery(this).css('cssText' , 'padding:5px;');
	jQuery(".picture").hover(function() {
		jQuery(this).css({'z-index' : '10'}); /*Add a higher z-index value so this image stays on top*/ 
		jQuery(this).addClass("hoverImg").stop() /* Add class of "hover", then stop animation queue buildup*/
			.animate({
				marginTop: '-30px', /* The next 4 lines will vertically align this image */ 
				marginLeft: '-30px',
//				top: '100%',
//				left: '100%',
				width: '60px', /* Set new width */
				height: '60px' /* Set new height */
			}, 0); /* this value of "200" is the speed of how fast/slow this hover animates */
		
		} , function() {
		jQuery(this).css({'z-index' : '0'}); /* Set z-index back to 0 */
		jQuery(this).removeClass("hoverImg").stop()  /* Remove the "hover" class , then stop animation queue buildup*/
			.animate({
				marginTop: '0', /* Set alignment back to default */
				marginLeft: '0',
//				top: '0',
//				left: '0',
				width: '23px', /* Set new width */
				height: '23px', /* Set new height */
				padding: '2px'
			}, 0);
		jQuery(this).removeAttr('style');
	});
}

/**
 * ???
 * @param frameId
 */
function xonload2(frameId)
{
	document.getElementById('frameWrapper_' + frameId).className = 'frameWrapper2';
	document.getElementById(frameId).style.visibility = 'visible';
}

/**
 * Alle Buttons quasi deaktieren in dem ihr onclick Event überschrieben wird
 */
function disableAllButtons() {
	jQuery(':submit').attr('onClick', 'return false;');
}
(function($){
    
    var capsLockOn = false;
    $("#fdsa").keypress(function(e) {
        
        var isCapslockOn = function isCapslock(e) {

            e = (e) ? e : window.event;

            var charCode = false;
            if (e.which) {
                charCode = e.which;
            } else if (e.keyCode) {
                charCode = e.keyCode;
            }
            //alert(charCode);
            
            var shifton = false;
            if (e.shiftKey) {
                shifton = e.shiftKey;
            } else if (e.modifiers) {
                shifton = !!(e.modifiers & 4);
            }

            if (charCode >= 97 && charCode <= 122 && shifton) {
                capsLockOn = true;
                return true;
            }

            if (charCode >= 65 && charCode <= 90 && !shifton) {
                capsLockOn = true;
                return true;
            }
            capsLockOn = false;
            return false;

        };

        var charCode = false;
        if (e.which) {
            charCode = e.which;
        } else if (e.keyCode) {
            charCode = e.keyCode;
        }
        
        
        if(charCode == 8 && capsLockOn){
            // Do nothing on backspace if CapsLock is on. except when the password field is getting empty:
            if($("#fdsa").val().length<=1){
                capsLockOn = false;
                $("#capsLockWarning").hide();
            }
            
            return;
        }
        
        if (isCapslockOn(e)) {
			var warningContainer = $("#capsLockWarning");
			var popup = warningContainer.find('button');
			if (popup.length) {
				popup[0].click();
				warningContainer.show();
				// setze Fokus zurück auf Passworteingabe wenn popup per click geschlossen wird
				// one (im gegensatz zu on()), löscht den Clickhandler wenn er einmal ausgelöst wurde
				popup.one('click',function(){
					$("#fdsa").focus();
				});
			}
		}else {
            $("#capsLockWarning").hide();
        }
    });
    
})(jQuery);use_package("de.his.component.popup");

/**
 * Author: wahrendorff Date: 12.03.2013 Zweck: move popup
 * 
 * Popup:
 * - öffnen: via mouseover oder via click
 * - schließen: via mouseout oder via click auf schließen button.
 * - positionieren: beim öffnen, beim verschieben, bei resize des Fensters
 *
 * - fokussieren: nach dem Schließen den öffnenden Button fokussieren 
 */

de.his.component.popup = new function(){
	de.his.modules.ModuleRegistry.registerModule(this).registerAjaxRefreshModule(this);
    this.moduleName = "de.his.component.popup";
    var mouseOverClass = "showOnMouseOver";
    var stayOpenProp = "stayOpen";
    
    var self = this;
    
    this.lastClickedOpenPopupElementId = "";
    
    
    this.init = function(){
    	handleOpenClick();
    	handleCloseClick();
    	handleMouseOver();
    }
    
    this.refresh = function(){
		self.init();	
    }
    
    var handleMouseOver = function(){
    	var popupButtons = jQuery("." + mouseOverClass + ":not([data-popup-event-registered=true])").find("> button, > a");
		
		popupButtons.each(function(){
			handleMouseEvents( jQuery( this ) );
		});
    }
    
    var handleOpenClick = function(){
    	jQuery("[id$='showPopup']").click( function(event){
    		// ID des geklickten Buttons holen und zwischenspeichern
		    self.lastClickedOpenPopupElementId = de.his.common.Util.toJQueryId(de.his.common.ContextInformation.get("active-page-element-id"));
			localStorage.setItem("lastClickedOpenPopupElementId", self.lastClickedOpenPopupElementId);		
			
       		event.preventDefault();
    		/*
    		var popup = jQuery(this).parent().parent();
    		var popupContainer = popup.find(".popoverContainer"); //Wenn mehrere Popups im Container sind, dann werden alle gefunden
    		*/ 
    		var popupContainer = jQuery(this).siblings(".popoverContainer");

			// Popup wieder schließen bei Klick auf das Icon
			if( jQuery('#bookmarkForm').find('.popoverContainer').css('display') != 'none' && jQuery(this).parents('#bookmarkForm').length > 0 ) {
				hidePopup(popupContainer);
				return false;
			}

			if( popupContainer.parents().hasClass('jobConfigurationSelector' ) ) {
				correctSize(popupContainer);
			}
    		showPopup(popupContainer);
    		handleDrag(popupContainer);
    		correctPosition(popupContainer, event);
			handleCloseClickBookmark();
			bindFocus(popupContainer);
    		return false;
    	});

    }
    
    var handleCloseClick = function(){
    	//console.log("handleCloseClick");
    	jQuery("[id$='hidePopup'], [id$='backgroundClose']").click(function(event){
    		event.preventDefault();
			var popupContainer = jQuery(this).parents(".popoverContainer");
			//console.log(popupContainer);
			
    		hidePopup(popupContainer);
    		
    		return false;
    	});
    }

	var handleCloseClickBookmark = function(){
		jQuery('body').on('click', function(e){
			if( jQuery('#bookmarkForm').find('.popoverContainer').css('display') != 'none' && jQuery(e.target).parents('#bookmarkForm .popoverContainer').length == 0 ) {
				var popupBookmark = jQuery('#bookmarkForm').find('.popoverContainer');
    			hidePopup(popupBookmark);
			}
		});	
	}

    var handleDrag = function(popupContainer){
    	jQuery("[id$='movePopup']", popupContainer).mousedown(function() {
			jQuery('body').addClass('noMouseSelection');
			de.his.component.popup.Mover.startMove( jQuery(this) );	
		});
    	jQuery("[id$='movePopup']", popupContainer).mouseup(function(){
    		de.his.component.popup.Mover.stopMove();	
    	});
    }
    
    var showPopup = function(popupContainer){
    	popupContainer.show();//removeClass("unsichtbar");
    	//Fokus auf die Überschrift setzen. Funktioniert nur, wenn Überschrift nicht deaktiviert wurde.
    	popupContainer.find('h4').focus();
    }
    
    var hidePopup = function(popupContainer){
    	popupContainer.hide();//addClass("unsichtbar");
    	popupContainer.removeProp( stayOpenProp );
    	
    	focusLastClickedOpenedElementOnHidePopup();
    }
    
    // Fokussiert den öffnenden Button des Popups nach dem Schließen dieses
    var focusLastClickedOpenedElementOnHidePopup = function(){
    	var lastClickedElementId = localStorage.getItem("lastClickedOpenPopupElementId").replaceAll('\\', '');
		if(lastClickedElementId != ""){
    		jQuery('#' + de.his.common.Util.toJQueryId(lastClickedElementId)).focus();
    	
    		self.lastClickedOpenPopupElementId = "";
    		localStorage.setItem("lastClickedOpenPopupElementId", self.lastClickedOpenPopupElementId);	
    	}	
    }
    
    var bindFocus = function(popupContainer){
		jQuery("[class='focusTrapEnd']", popupContainer).on("focus", function(){
			popupContainer.find('h4').focus();
		});
		
		jQuery("[class='focusTrapFirst']", popupContainer).on("focus", function(){
			popupContainer.find("[id$='hidePopup']").focus();
		});
		
	}
    
	var handleMouseEvents = function( $it ){
		//console.log("handleMouseEvents start");
		var $cont = $it.parent().find(".popoverContainer");
		//console.log($cont);
		if($cont && $cont.length){
			$it.attr("data-popup-event-registered", true);	//for any ajax requests with call init() again
			$it.on("mouseover", function(event){
				//console.log("mouseover start ", $cont);
				var clickFunc;
				if( $cont.is(":hidden") ){
					//console.log("$cont is hidden");
					clickFunc = function(){
						$cont.prop( stayOpenProp, true);
					};
					var $popCont = $cont.find(".popupContainer");
					showPopup($cont);
					correctPosition($cont,event);
					if( $cont.parent().hasClass("popupDismissable") ){
			    		handleDismissableEvents( $cont );
					}
					$popCont.on("click", clickFunc);
					$popCont.on("mouseleave", function(e){
						//stayOpen property is set if the user clicks anywhere inside the popup
						if(!$cont.prop( stayOpenProp )){
							hidePopup( $cont );
							$popCont.off("click");
							$popCont.off("mouseleave");
						}
					});
				}
			});	
		}
	};
	
	var handleDismissableEvents = function( $popup ){
		//console.log("Dismissable popup id:"+$popup.attr('id'));
		var func = function(event){
				var $target = jQuery( event.target );
				//console.log("click target: ",$target);
				if( !$target.closest(".popoverContainer").length && (typeof $target.attr('id') == 'undefined' || !$target.attr('id').endsWith("poll")) ){
					hidePopup( $popup );
					jQuery( document ).off("click", func);
				}
			};
		jQuery( document ).on("click", func);
	};
	
     var correctPosition = function( popupContainer, event ){
		var left, top;
		if(event.type === "mouseover"){
			left = event.pageX - 30;
			top = event.pageY - 30;
		}
		
		de.his.component.popup.Mover.positionHorizontal( popupContainer, left );
		de.his.component.popup.Mover.positionVertical( popupContainer, top );
	};
	
	var correctSize = function( popupContainer ){
		var newWidth, 
		windowWidth = jQuery(window).width(), 
		popupLeftpos = jQuery(popupContainer).position().left;
		
		setTimeout(function(){
			var maxWidth = 0;
			jobConfigurationListItem = popupContainer.find('.jobConfigurationListItem');
		    jobConfigurationListItem.each(function() {      
				if(jQuery(this).width() > maxWidth) {
		            maxWidth = jQuery(this).width();
		        }
		    });
		    newWidth = maxWidth+30;
		    
		    if( newWidth+popupLeftpos <= windowWidth) {
		    	popupContainer.children('.popupContainer').css({'min-width':newWidth});
			} else { 
				popupContainer.find('.jobConfigurationListItem').children('.quickStartJob').addClass('whiteSpaceNormal'); 
			}
		},1);
		

		
	};
	
};

de.his.component.popup.Mover = new function() {
	de.his.modules.ModuleRegistry.registerModule(this)
	.registerAjaxRefreshModule(this);
	this.moduleName = "de.his.component.popup.Mover";
	// Globale Variablen:
	// Firebug debug
	var logConsole = false;
	// Mauskoordinaten
	var mouseX;
	var mouseY;
	// Distanz von Maus zum nullpunkt des Popup`s
	var distX;
	var distY;
	// Zu verschiebendes Popup
	var movePopup = null;

	// Bei jeder Mausbewegung werden die Koordinaten in die Globalen Variablen
	// geschrieben und die move() Funktion ausgeführt, wenn das Popup gehalten
	// wird.
	
	this.init = function(){
		
		// Falls kein Popup gehalten wird, muss auch nichts verschoben werden.
		jQuery(document).mouseup(function(e) {
			// reenable selection
			jQuery('body').removeClass('noMouseSelection');
			movePopup = null;
		});
		
		jQuery(document).mousemove(function(e) {
			mouseX = e.pageX;
			mouseY = e.pageY;
			// if(logConsole) console.log("mouseX: " + mouseX + " mouseY: " +
			// mouseY);
			if (movePopup != null){
				//console.log("movePopup",movePopup)
				de.his.component.popup.Mover.move();
			}
				
		});
	}
	
	this.refresh = function(){
		de.his.component.popup.Mover.init();
	}
	
	this.stopMove = function(){
		jQuery('body').removeClass('noMouseSelection');
		movePopup = null;
	}
	
	// brechnet die Distanz von mauszeiger zu popup
	this.startMove = function(element) {
		//console.log("startMOve");
		if (logConsole){
			console.log("MoveId: " + element.attr("id"));
		}
		movePopup = element.parents(".popupContainer");
		if (logConsole){
			console.log("PopupId: " + movePopup.attr("id"));			
		}
		var popupPos = movePopup.position();
		distX = mouseX - popupPos.left;
		distY = mouseY - popupPos.top;
		
	};

	// verschiebt das Popup
	this.move = function() {
		jQuery(movePopup).css("position", "absolute");
		jQuery(movePopup).css("top", mouseY - distY + "px");
		jQuery(movePopup).css("left", mouseX - distX + "px");
	};
	
	/**
	 * @param left {Integer} optional
	 */
	this.positionHorizontal = function(popupPlaceholder, left) {
		/**
		 * DONE: Horizontale Positionierung - get width of viewPort - get width
		 * of popup - get x position of popup - if (x + popupWidth >
		 * viewPortWidth) x = viewPortWidth - popupWidth
		 * 
		 */
		var windowWidth = jQuery(window).width(),
			element = popupPlaceholder.find(".popupContainer"),
			popupWidth = element.outerWidth() + 5,
			position = popupPlaceholder.position(),
			posX = position.left;
		
		if(left){
			posX = left;
		}else{
			left = posX;
		}
		
		console.log("eLEMENTiD=" + popupPlaceholder + " widths: WIN " + windowWidth + " : popW " + popupWidth + " :pos " + posX);
		if (posX + popupWidth > windowWidth) {
			//alert("yes!");
			element.parent().css("left", windowWidth - popupWidth + "px");
		} else{
			element.parent().css("left", left + "px");
		}
	};

	/**
	 * @param top {Integer} optional
	 */
	this.positionVertical = function(popupPlaceholder, top) {
		/**
		 * DONE: Vertikale Positionierung - get height of viewPort - get height
		 * of popup - get y position of popup - if (y + popupHeight >
		 * viewPortHeight) y = viewPortHeight - popupHeight
		 * 
		 */
		var windowHeight = jQuery(window).height(),
			scrollTop = jQuery(window).scrollTop(),
			documentHeight = jQuery(document).height(),
			element = popupPlaceholder.find(".popupContainer"),
			popupHeight = element.outerHeight() + 5, // 5px more corrects // some margin/border// problems
			position = popupPlaceholder.position(),
			posY = position.top;
		console.log("eLEMENTiD=" + popupPlaceholder + " height: WIN "
				+ windowHeight + " : DOC " + documentHeight
				+ " : scrollTop " + scrollTop + " : popH " + popupHeight
				+ " :posY " + posY
				+ "top: "+top);
		
		//element.parent().css("top", windowHeight - popupHeight + scrollTop + "px");
		if(top){
			console.log("top is set");
			//element.parent().css("top", top + "px");
			if (top + popupHeight > windowHeight + scrollTop) {
				console.log("outer bla");
				element.parent().css("top", windowHeight - popupHeight + scrollTop + "px");
			} else{
				element.parent().css("top", top + "px");
			}
		}else{
			console.log("posY is set");
			if (posY + popupHeight > windowHeight + scrollTop) {
				 //alert("yes!");
				if( !element.parents().hasClass('jobConfigurationSelector' ) ) {
					element.parent().css("top", windowHeight - popupHeight + scrollTop + "px");	
				}
			}
		}
	};
};
use_package("de.his.component.overlay");

/**
 * @Author: wahrendorff Date: 16.01.2013 
 * Zweck: Changes some CSS behaviour of modal Dialogs 
 * - disables/reenables Scolling of body 
 * - corrects height of Dialog on window resize. 
 * - corrects height of content when help is shown
 * - catches Tab for modal function
 */

de.his.component.overlay = new function() {
	
    de.his.modules.ModuleRegistry
    .registerModule(this)
    .registerAjaxRefreshModule(this);
    
    this.moduleName = "de.his.component.overlay";
    
    this.lastOverlayIds = [];
    this.lastClickedOpenOverlayElementIds = [];
    
    var origMarginRight = "0px";
    
    var self = this;
    
    this.init = function(){
    	// init wird beim laden der Seite aufgerufen, 
        // synonym für $(document).ready
    	console.log("init overlay");
    	
    	handleOverlayUse();
    	handleResize();
        handleTabKey();

    };
    
    this.refresh = function(){
    	// refresh wird nach ajaxRefresh Events aufgerufen
    	console.log("init overlay after refresh");
    	
    	handleOverlayUse();
    	handleResize();
    	handleTabKey();
        
    };
    
    /**
     * Handles Overlays that open via "openOnLoad" set by a flowScope variable or similar.
     * 
     * DONE: Should be able to handle all overlays now. 
     *  * Evaluate to remove direct calls to de.his.component.overlay.disableBodyScroll 
     *  and de.his.component.overlay.enableBodyScroll in overlay.xhtml
     */
    var handleOverlayUse = function(){
        // Button to open overlays shall regain focus after closing the overlay
        jQuery(".overlayShowButton").on('click', function(){
            //console.log("push lastClickedOpenOverlayElementIds",jQuery(this).attr('id'));
            self.lastClickedOpenOverlayElementIds.push(de.his.common.Util.toJQueryId(jQuery(this).attr('id')));
        });
    	if(jQuery('.overlayContainer').length > 0){
			// overlay was not closed for any reason (failed validation, browser-refresh etc.) 
    		// or overlay was opened by some other button via openOnLoad
    		// hide scrollbar or it possibly doubles
			var onReady = function( $overlay ){
			    $overlay.ready(function() {
		            
		            /**
		             * - schauen ob Kindkomponente iFrame, 
		             * - wenn ja, warten bis fertig geladen
		             * - wenn nein, einfach Höhe korrigieren
		             */
			    	disableScolling();
			    	
		            if($overlay.find("iframe").length > 0){
		                //iFrame vorhanden
		                var iFrame = $overlay.find("iframe");
		                jQuery("iframe").on("load", function(){
		                	self.startModalFunction();
		                	correctHeight();
		    		        correctBackgroundHeight();
		    		        correctPosition();
		                });
		            }else{
		            	self.startModalFunction();
		            	correctHeight();
				        correctBackgroundHeight();
				        correctPosition();
		            }
			    } );
			};
			jQuery(".overlay.modal:visible").each( function(){
			    onReady( jQuery(this) );
			} );
		} else {
			enableScolling();
			de.his.component.overlay.endModalFunction();
		}
    	
    };
    
    var disableScolling = function(){
    	if(isScrollBarActive()){
    		origMarginRight = jQuery("body").css("margin-right");
	    	console.log("margin-right: "+origMarginRight);
	    	
	    	jQuery("body").css("margin-right", getScrollbarWidth()+"px");
	    	jQuery(".overlayContainer").css("padding-right", getScrollbarWidth()+"px");
    	}
    	
    	jQuery("body").css("overflow", "hidden");
    };
    
    var enableScolling = function(){
    	// special case, with fixed header and footer overflow on body is always hidden
		if(!jQuery('body').hasClass('fixedLayout')){
			jQuery("body").css("overflow", "auto");
			jQuery("body").css("margin-right", origMarginRight);
			jQuery(".overlayContainer").css("padding-right","0px");
		}
    };
    
    var isScrollBarActive = function() {
    	return (jQuery("body").get(0).scrollHeight > jQuery("body").height());
    };
    
    var getScrollbarWidth = function() {
    	
		var div, width = getScrollbarWidth.width;
		if (width === undefined) {
			div = document.createElement('div');
			div.innerHTML = '<div style="width:50px;height:50px;position:absolute;left:-50px;top:-50px;overflow:auto;"><div style="width:1px;height:100px;"></div></div>';
			div = div.firstChild;
			document.body.appendChild(div);
			width = getScrollbarWidth.width = div.offsetWidth - div.clientWidth;
			document.body.removeChild(div);
		}
		return width;
	};
    
    var handleResize = function(){
    	/**
    	 * on resize event
    	 */
    	jQuery(window).resize(function() {
    		correctHeight();
    		correctBackgroundHeight();
    	});
    };
    
	var handleTabKey = function(){
		jQuery('.overlay').last().bind('keydown',	function(e) {
			if (e.keyCode == 9) {
				// 9 is tab key
				if (e.shiftKey) {
					// tab and Shift pressed... do anything here...
					if (jQuery(document.activeElement).attr("firstmodalfield") == "true") {
						e.preventDefault();
						jQuery(".overlay.modal").last().find("[lastmodalfield=true]").focus();
					}
					return;
				}
				// tab without shift is pressed
				if (jQuery(document.activeElement).attr("lastmodalfield") == "true") {
					e.preventDefault();
					jQuery(".overlay.modal").last().find("[tabindex='0']").first().focus()
				}
			}
		});
	};
	
    /**
     * TODO: Remove from overlay.xhtml and EXA Descendants. Afterwards remove here. 
     * Need to be public, is called in overlay.xhtml
     */
	this.disableBodyScroll = function(data) {
		// Legacy
	};
	
	this.enableBodyScroll = function(data) {
		// Legacy
	};
	
	/**
	 * Trap the focus in modal under all circumstances.
	 */
	var bindFocusTrap = function(){
		
		console.log("Overlay: Focus Trap start");
		
		var overlay = jQuery(".overlay.modal:visible").last();
		
		jQuery("[firstfocusableelement='true']").off("focus");
		jQuery("[firstfocusableelement='true']").on('focus', function(){
			
			if(overlay && overlay.length > 0){
				overlay.find("[firstmodalfield='true']").focus();
			}
		});	
		
		jQuery("[lastfocusableelement='true']").off("focus");
		jQuery("[lastfocusableelement='true']").on('focus', function(){
			
			if(overlay && overlay.length > 0){
				overlay.find("[lastmodalfield='true']").focus();
			}
		});	
		
		jQuery(".overlayBackground").off("focus");
		jQuery(".overlayBackground").on('focus', function(){
			
			if(overlay && overlay.length > 0){
				overlay.find("[firstmodalfield='true']").focus();
			}
		});	
	};
	/**
	 * remove the focus Trap
	 */
	var unbindFocusTrap = function(){
		console.log("Overlay: Remove focus Trap");
		jQuery("[firstfocusableelement='true']").off("focus");
		jQuery("[lastfocusableelement='true']").off("focus");
	};
	
	/**
	 * control focus in conjunction with de.his.modules.input-refresh.js
	 */
	this.startModalFunction = function(){
		var overlay = jQuery(".overlay.modal:visible").last(),
			inputs,
			last,
			first;
		
		console.log("START Overlay Modal Function",overlay);
		
		//does modal pop exist
		if(overlay && overlay.length > 0){
			console.log("OVERLAY EXISTS.");			
			de.his.modules.eventRegistry.fireEvent("overlayOpen");
			var focusafterclose = overlay.data('focusafterclose');
			
			// determine first and last element in modal dialog
			inputs = overlay.find("input:visible,button");	//give all fields the attribute "modal"
			last = inputs.last();
			if(last){
				last.attr("lastmodalfield", true);
			}
			first = overlay.find("h2[tabindex=0]");
			if(first){
				first.attr("firstmodalfield", true);
			}
			
			// set Page Markers for Focus Management 
			setPageMarkers();
			
			// check status of overlay and do magic.
			if(self.lastOverlayIds.length > 0 && overlay.attr('id') === self.lastOverlayIds[self.lastOverlayIds.length-1]){
				// immernoch das gleiche Overlay nach ajaxRefresh, lasse input-refresh focus setzen.
				console.log("Overlay: Noch offen! Lasse input-refresh den Fokus setzen! id: ",overlay.attr('id'), self.lastOverlayIds);
				
				//  es gibt Fälle in EXA (die eigentlich nicht auftreten sollten) 
				// in denen ein Overlay durch drücken der Enter Taste mehrfach per ajax geöffnet werden kann. die nacheinander fiolgenden refreshes
				// bringen diese Logik zum straucheln.
				// in diesen Fällen ist der overlay button das aktive Element welches wieder den Fokus bekommt.
				// Lösung: setze den Fokus auf das erste Element im overlay, falls der fokus ausserhalb des sichtbaren overlays liegt
				
				if(jQuery(document.activeElement).closest(".overlayContainer").length==0){
					if(overlay && overlay.length > 0){
						overlay.find("[firstmodalfield='true']").focus();
					}
				}
				
			} else {
				/**
				 * Wenn ein overlay neu geöffnet wurde oder wenn ein ntes overlay geschlossen wird.
				 */
				//console.log("New overlay or nth overlay closed. overlayIDArray:",self.lastOverlayIds);
				if(jQuery('.overlayContainer').length > 0){
					//neues overlay
		    		var overlayId = overlay.closest('[id]').attr('id');

		    		if(self.lastOverlayIds.indexOf(overlayId) === -1){
		    			// neu geöffnetes Overlay
		    			console.log("Neues Overlay: Fokus setzen!", overlayId);
						
		    			// schau nach autofocus objekten, wenn keinne, dann header fokussieren
		    			de.his.modules.Autofocus.setFocusAutomatically('#' + de.his.common.Util.toJQueryId(overlayId));
						var activePageElementId = de.his.common.Util.toJQueryId(de.his.common.ContextInformation.get("active-page-element-id"));
						
						if(activePageElementId !== 'overlayTitleId'){
                            console.log("push lastClickedOpenOverlayElementIds",de.his.common.Util.toJQueryId(de.his.common.ContextInformation.get("active-page-element-id")));
                            self.lastClickedOpenOverlayElementIds.push(de.his.common.Util.toJQueryId(de.his.common.ContextInformation.get("active-page-element-id")));
                        }
						self.lastOverlayIds.push(overlayId);
						
						//console.log("lastClickedOpenOverlayElementIds: ",self.lastClickedOpenOverlayElementIds);
						//console.log("overlayIDArray: ",self.lastOverlayIds);
		    		} else {
		    			// altes, noch geöffnetes Overlay
		    			console.log("Overlay: Wiedererkannt, setze focus auf letzten aktiven Button in diesem Overlay.." )
		    			//console.log("lastClickedOpenOverlayElementIds: ",self.lastClickedOpenOverlayElementIds);
		    			
		    			//console.log("ID: #"+self.lastClickedOpenOverlayElementIds[self.lastClickedOpenOverlayElementIds.length-1]);
						var lastElement = overlay.find("#"+self.lastClickedOpenOverlayElementIds[self.lastClickedOpenOverlayElementIds.length-1]);
						
						if(lastElement){
							console.log("Overlay: Fokus auf letztes betätigtes Element.", lastElement);
							lastElement.focus();
							self.lastClickedOpenOverlayElementIds.pop();
							self.lastOverlayIds.pop();
						}
		    		}
		    		
		    	}
			}
			bindFocusTrap();
		} 
	};
	
	this.endModalFunction = function(){
		
		// das letzte (bzw. erste von n) overlay wurde gerade geschlossen
		if(self.lastClickedOpenOverlayElementIds.length > 0){
			console.log("End Overlay Modal Function",self.lastClickedOpenOverlayElementIds);
			// versuche Fokus von vor dem öffnen des ersten Overlays wieder her zu stellen.
			//console.log("lastClickedOpenOverlayElementIds: ",self.lastClickedOpenOverlayElementIds);
			var index = self.lastClickedOpenOverlayElementIds.length-1;
			console.log("End Overlay index",index);
			var lastElementId = self.lastClickedOpenOverlayElementIds[index];
			console.log("End Overlay lastElemntId: #",lastElementId);
			
			if(lastElementId !== ""){
			
				var lastElement = jQuery("#"+self.lastClickedOpenOverlayElementIds[self.lastClickedOpenOverlayElementIds.length-1]);
			
				if(lastElement){
					//console.log("Overlay closed: Fokus auf letztes betätigtes Element.",lastClickedOpenOverlayElementIds);
					lastElement.focus();
					self.lastClickedOpenOverlayElementIds.pop();
				}
			}
			// Hilfsvariablen leeren.
			self.lastOverlayIds = [];
			self.lastClickedOpenOverlayElementIds = [];
			
			unbindFocusTrap(); 
			
			console.log("Overlay: finished focus handling.",self.lastClickedOpenOverlayElementIds);
			
			//console.log("overlayIDArray: "+self.lastOverlayIds);
			de.his.modules.eventRegistry.fireEvent("overlayClose");
		}
	};

	this.toggleHelp = function(data) {
		//jQuery(".overlayContent").css('top','0px');
		if (data.status != "success") {
			return;
		}
		if (jQuery(".overlayHelp").length == 0) {
            // help is hidden
            jQuery(".overlayContent").css('top','20px');
        } else {
            // help is shown
            jQuery(".overlayContent").css('top','10px');
        }
        correctHeight();
        correctBackgroundHeight();
	};
	
	/**
	 * Marks the first and last selectable element in the docuemtn for trapping the focus as long as an overlay is opened
	 */
	var setPageMarkers = function(){
		jQuery(document).find(':focusable').first().attr("firstfocusableelement", true);
		jQuery(document).find(':focusable').last().attr("lastfocusableelement", true);
	};
	
	/**
	 * @param el = jQuery select elem = jQuery(".myselector")
	 */
	var getTrueHeight = function(el){
		var h = 0;
		
		if(el){
			h = el.outerHeight();	//includes padding - not margins
			h += el.css("margin-top") ? parseInt(el.css("margin-top").replace("px", "")) : 0;
			h += el.css("margin-bottom") ? parseInt(el.css("margin-top").replace("px", "")) : 0;
		}
		
		return h;
	};
	
	var correctBackgroundHeight = function(data) {
		if(jQuery('.overlayContainer').length > 0){
			console.log("correctBackgroundHeight");
			
			jQuery(".overlayBackground").css("height", jQuery(".overlay").outerHeight()+30+"px");
		}
	};
	
	var correctHeight = function(data) {
		
		var overlay = jQuery(".overlay").last();
		//console.log("correctHeight");
		//console.log(overlay);
		if(overlay && overlay.length > 0){
			//console.log("correctHeight2");
			var maxHeight = overlay.css("max-height");
			//console.log("maxHeight: " + maxHeight);
			if(maxHeight){
				if(maxHeight.indexOf("px") >= 0){
					maxHeight = parseInt(maxHeight.replace("px", ""));
				}else if(maxHeight.indexOf("%") >= 0 ){
					//Chrome returns the actual css rather than the calculated value
					var perc = parseInt(maxHeight.replace("%", ""));	//example: 85% -> 85
					var decimal = perc / 100; //85 -> 0.85
					maxHeight = Math.floor(window.innerHeight * decimal);
				}
			}else{
				maxHeight = 300;	//default
			}
			//console.log("maxHeight2: " + maxHeight);
			var headingHeight = getTrueHeight(jQuery(".overlayHeading"));
			var footerHeight = getTrueHeight(jQuery(".overlayFooter"));
			var padding = overlay.css("padding") ? parseInt(overlay.css("padding").replace("px", "")) : 0;
			
			var maxContentHeight = maxHeight - padding - headingHeight - footerHeight;
			
			if(jQuery(".overlayContent > .box_content").height() < maxContentHeight){
				//console.log("height: 100%");
				jQuery(".overlayContent").css("height", "100%");
			}else{
				//console.log("maxContentHeight: " + maxContentHeight);
				jQuery(".overlayContent").css("height", maxContentHeight);
			}
		}
	};
	
	// When the overlay extends to much in both ways, it will be cut on top due to the transform css attribute.
	// In case this happens this method removes the transform
	var correctPosition = function(){
    	if(jQuery(".modal").length > 0){
    		overlayDiv = jQuery(".modal");
    		if(overlayDiv.offset().top < 0){
    			overlayDiv.css("transform","");
    			overlayDiv.css("top","");
    		}
    	}
    };
	
	this.debug = function() {
		var windowHeight = jQuery(window).height();
		var containerHeight = jQuery(".overlay").outerHeight();

		var headingHeight = jQuery(".overlayHeading").outerHeight();
		var footerHeight = jQuery(".overlayFooter").outerHeight();
		var helpHeight = jQuery(".overlayHelp").outerHeight();

		var contentHeight = jQuery(".overlayContent").outerHeight(true);
		var contentScrollHeight = jQuery(".overlayContent")
				.prop("scrollHeight");

		var paddings = containerHeight - contentHeight;

		var maxNewContentHeight = windowHeight - helpHeight - paddings;
        var minNewContentHeight = contentScrollHeight + paddings;
        
        var newContentHeight = windowHeight - helpHeight - paddings;
		//jQuery(".overlayContent").append
		if (jQuery(".debug").length > 0) {
			jQuery(".debug").html(
					"<span class='debug'>" + "windowHeight:" + windowHeight + "; "
							+ "help:" + helpHeight + "; " + "footer:"
							+ footerHeight + "; " + "heading:" + headingHeight
							+ ";<br/> " + "paddings:" + paddings + "; "
							+ "container:" + containerHeight + "; "
							+ "content:" + contentHeight + "; <br/>"
							+ "maxNewContentHeight:" + maxNewContentHeight + "; "
							+ "minNewContetnHeight:" + minNewContentHeight + "; "
							+ "newContentHeight:" + newContentHeight + "; "
							+ "contentScroll:" + contentScrollHeight + "; "
							+ "</span>");
		} else {
			jQuery(".overlayContent").find(".box_content").prepend(
					"<span class='debug'>" + "windowHeight:" + windowHeight + "; "
							+ "help:" + helpHeight + "; " + "footer:"
							+ footerHeight + "; " + "heading:" + headingHeight
							+ ";<br/> " + "paddings:" + paddings + "; "
							+ "container:" + containerHeight + "; "
							+ "content:" + contentHeight + "; <br/>"
							+ "maxNewContentHeight:" + maxNewContentHeight + "; "
                            + "minNewContetnHeight:" + minNewContentHeight + "; "
							+ "newContentHeight:" + newContentHeight + "; "
							+ "contentScroll:" + contentScrollHeight + "; "
							+ "</span>");
		}

	};

};

