
if (typeof naviki == "undefined") {
	var naviki = {}
}

if (typeof naviki.util == "undefined") {
	naviki.util = {}
}

naviki.util.api = {

	isTokenRefresh: false,
	ajaxRequestStack: new Array(),
	
	setAccessToken: function(accessToken) {
		if(typeof(localStorage) !== "undefined") {	
			window.localStorage.setItem("_n_a_at", accessToken);
		}
	},
		
	getAccessToken: function() {
		if(typeof(localStorage) !== "undefined") {	
			var accessToken = window.localStorage.getItem("_n_a_at");
			if(accessToken != "undefined" && accessToken != null) {
				return accessToken;
			}
		}
		return null;
	},
		
	removeAccessToken: function() {
		if(typeof(localStorage) !== "undefined") {	
			window.localStorage.removeItem("_n_a_at");
		}
	},
		
	setRefreshToken: function(refreshToken) {
		if(typeof(localStorage) !== "undefined") {	
			window.localStorage.setItem("_n_a_rt", refreshToken);
		}
	},
		
	getRefreshToken: function() {
		if(typeof(localStorage) !== "undefined") {	
			var refreshToken = window.localStorage.getItem("_n_a_rt");
			if(refreshToken != "undefined" && refreshToken != null) {
				return refreshToken;
			}
		}
		return null;
	},
		
	removeRefreshToken: function() {
		if(typeof(localStorage) !== "undefined") {	
			window.localStorage.removeItem("_n_a_rt");
		}
	},
	
	request: function(options) {
		var parentBeforeSend = null;
		if (options.beforeSend != undefined && typeof options.beforeSend === "function") {
			parentBeforeSend = options.beforeSend;
		}
		options.beforeSend = function(xhr) {
			if (parentBeforeSend != null && typeof parentBeforeSend === "function") {
	        	parentBeforeSend();
	        }
			if (naviki.util.api.getAccessToken() != null) {
				xhr.setRequestHeader('Authorization', 'Bearer ' + naviki.util.api.getAccessToken());
			}
			if (typeof(naviki.CONSTANTS.LANGUAGE) !== "undefined") {	
				xhr.setRequestHeader('Accept-Language', naviki.CONSTANTS.LANGUAGE);
			}
	    }
		
		var parentError = null;
		if (options.error != undefined && typeof options.error === "function") {
			parentError = options.error;
		}
		options.error = function(jqXHR, textStatus, errorThrown) {
			if (jqXHR != null && jqXHR.status != null && jqXHR.status == 401) {
				naviki.util.api.ajaxRequestStack.push(options);
				if (!naviki.util.api.isTokenRefresh) {
					naviki.util.api.isTokenRefresh = true;
					naviki.util.api.refreshToken();
				}
				return;
			}
			if (parentError != null && typeof parentError === "function") {
				parentError(jqXHR);
	        }
		}
		
		return $.ajax(options);
	},
	
	refreshToken: function() {
		
		var _this = this;
		var params = "?eID=controllerDispatcher&request[format]=json&request[controller]=FeUser&request[action]=refreshToken";	
		params += "&request[arguments][refreshToken]=" + naviki.util.api.getRefreshToken();

		$.ajax({
			url: window.location.pathname + encodeURI(params),
			type: "GET",
			cache: false,
			dataType : "json",
			contentType: 'application/json; charset=utf-8',
		    processData: false,
			success : function(data) {					
				if (data.status && data.accessToken && data.refreshToken) {
					naviki.util.api.setAccessToken(data.accessToken);
					naviki.util.api.setRefreshToken(data.refreshToken);
					naviki.util.user.setUserId(data.feUserId); // could be missing, if last login long ago
					while(naviki.util.api.ajaxRequestStack.length > 0) {
						$.ajax(naviki.util.api.ajaxRequestStack.pop());
					}
					naviki.util.api.ajaxRequestStack = new Array();
					naviki.util.api.isTokenRefresh = false;
				} else {
					naviki.util.api.logoutFeUser();
				}
			},
			error: function(err) {
				naviki.util.api.logoutFeUser();
			}
		});
	},
	
	logoutFeUser: function() {
		naviki.util.api.removeAccessToken();
		naviki.util.api.removeRefreshToken();

		naviki.util.user.removeLoggedIn();
		naviki.util.user.removeUsername();
		naviki.util.user.removeUserId();
		naviki.util.user.setActivated(false);
		naviki.util.user.setUserAverageSpeed(null);
		naviki.util.user.setUserEnergyUnit(null);
		naviki.util.user.setUserWayFilters(null);
		naviki.util.user.setUserWaySort(null);
	}
}
if (typeof naviki == "undefined") {
	var naviki = {}
}

if (typeof naviki.util == "undefined") {
	naviki.util = {}
}

naviki.util.binary = {

	prepare : function(binary, length) {
		if (binary.length < length) {
			do {
				binary = "0" + binary;
			} while (binary.length < length);
		}
		return "" + binary;
	},

	getBit : function(binary, pos) {
		binary = naviki.util.prepareBinary("" + binary, pos + 1);
		tmp = binary.split("");
		return tmp[tmp.length - (pos + 1)];
	},

	setBit : function(binary, pos, value) {
		binary = naviki.util.prepareBinary("" + binary, pos + 1);
		tmp = binary.split("");
		tmp[tmp.length - (pos + 1)] = value;
		binary = "";
		for (var i = 0; i < tmp.length; i++) {
			binary += tmp[i];
		}
		return binary;
	}
}
if(typeof naviki == "undefined"){
	var naviki = {}
}

if(typeof naviki.util == "undefined"){
	naviki.util = {}
}

naviki.util.compression = {
		
		// Encodes one-dimensional and two-dimensional arrays.
		//
		// @param array decodedObject
		//
		// e.g. decodedObject = array: ((1,2,3,4),(5,6,7,8),(9,10,11,12),(13,14,15,16))
		//		result = "ACEGGGGGGGGGGGGG"
		//
		//		decodedObject = array: (1,2,3,4)
		//		result = "AAAA"
		//
		encode: function(decodedObject)
		{
		    var encodedString = "";
		    var prevRow;
		    var row;
		    
		    var delta, prevVal = 0;
		    
		    for(var i = 0; i < decodedObject.length; i++)
		    {
		        if($.isArray(decodedObject[i]))
		        {
		            row = decodedObject[i];
		            
		            // If is the first row, than
		            // generate a previous row with 0 values​​.
		            if(i == 0)
		            {
		                prevRow = new Array();
		                for(var k = 0; k < row.length; k++)
		                {
		                    prevRow.push(0);
		                }
		            }
		            
		            for(var j = 0; j < row.length; j++)
		            {
		                // Calculate the delta from the previous value.
		                delta = parseInt(row[j]) - parseInt(prevRow[j]);
		                
		                // Encode the delta value.
		                encodedString = naviki.util.compression.encodeValue(encodedString,delta);
		            }
		            // Hold the current row.
		            prevRow = row;
		        }
		        else
		        {
		            // Calculate the delta from the previous value.
		            delta = parseInt(decodedObject[i]) - parseInt(prevVal);
		            // Hold the current value.
		            prevVal = parseInt(decodedObject[i]);
		            // Encode the delta value.
		            encodedString = naviki.util.compression.encodeValue(encodedString,delta);
		        }
		    }
		    
		    return encodedString;
		},

		encodeValue: function(encodedString,delta)
		{
		    // Left-shift the value one bit.
		    // If the original decimal value is negative, invert this encoding.
		    delta = (delta < 0) ? ~(delta << 1) : (delta << 1);

		    // OR each value with 0x20 if another 5-bit chunk follows.
		    // Add 63 to each value.
		    // Convert each value to its ASCII equivalent.
		    while (delta >= 0x20) {
		    	var val = (0x20 | (delta & 0x1f)) + 63;
		        encodedString += String.fromCharCode(val);
		        delta >>= 5;
		    }
		    encodedString += String.fromCharCode(delta + 63);
		    return encodedString;
		},
		
		// Decodes an encoded string.
		//
		// @param string encodedString The encoded string.
		// @param int columnCount Number of values ​​per row.
		//
		// e.g. encodedString = "ACEGGGGGGGGGGGGG"
		//		columnCount = 4
		//		result = array: ((1,2,3,4),(5,6,7,8),(9,10,11,12),(13,14,15,16))
		//
		//		encodedString = "AAAA"
		//		columnCount = 1
		//		result = array: (1,2,3,4)
		//
		decode: function(encodedString,columnCount)
		{
		    var length = encodedString.length;
		    var idx = 0;
		    
		    var byte;
		    var shift;
		    var delta;
		    var value;
		    var res;
		    
		    var result = new Array();
		    var prevRow;
		    var row;
		    
		    while (idx < length)
		    {
		        // If is the first row, than
		        // generate a previous row with 0 values​​.
		        if(result.length == 0)
		        {
		            prevRow = new Array();
		            for(var i = 0; i < columnCount; i++)
		            {
		                prevRow.push(0);
		            }
		        }
		  
		        row = new Array();
		        for(var i = 0; i < columnCount; i++)
		        {
		            byte  = 0;
		            res   = 0;
		            shift = 0;

		            do {
		                // The statement returns the ASCII code for the character at index.
		                // Subtract 63 to get the original value.
		                // (63 was added to ensure proper ASCII characters are displayed
		                // in the encoded polyline string, which is `human` readable)
		                byte = encodedString.charCodeAt(idx++) - 63;
		                // AND the bits of the byte with 0x1f to get the original 5-bit `chunk.
		                // Then left shift the bits by the required amount, which increases
		                // by 5 bits each time.
		                // OR the value into results, which sums up the individual 5-bit chunks
		                // into the original value.  Since the 5-bit chunks were reversed in
		                // order during encoding, reading them in this way ensures proper
		                // summation.
		                res |= (byte & 0x1F) << shift;
		                shift += 5;
		                // Continue while the read byte is >= 0x20 since the last `chunk`
		                // was not OR'd with 0x20 during the conversion process. (Signals the end)
		            } while (byte >= 0x20);
		     
		            // Check if negative, and convert. (All negative values have the last bit set)
		            delta = (res & 1) ? ~(res >> 1) : (res >> 1);
		            
		            // Summing the delta to the previous value.
		            value = parseInt(prevRow[i]);
		            value += delta;
		            
		            row.push(value);
		        }
		        result.push(row);
		        // Hold the current row.
		        prevRow = row;
		    }

		    // if the column count 1, than return a one-dimensional array.
		    if(columnCount == 1)
		    {
		        var change = new Array();
		        for(var i = 0; i < result.length; i++)
		        {
		            change.push(result[i][0]);
		        }
		        result = change;
		    }

		    return result;
		}
};
if (typeof naviki == "undefined") {
	var naviki = {}
}

if (typeof naviki.util == "undefined") {
	naviki.util = {}
}

naviki.util.cookie = {

	read : function(key) {
		var c_value = document.cookie;
		var c_start = c_value.indexOf(" " + key + "=");
		if (c_start == -1) {
			c_start = c_value.indexOf(key + "=");
		}
		if (c_start == -1) {
			c_value = null;
		} else {
			c_start = c_value.indexOf("=", c_start) + 1;
			var c_end = c_value.indexOf(";", c_start);
			if (c_end == -1) {
				c_end = c_value.length;
			}
			c_value = unescape(c_value.substring(c_start, c_end));
		}
		return c_value;
	},

	write : function(key, value) {
		var e = 1000 * 60 * 60 * 24 * 365;
		var a = new Date();
		a = new Date(a.getTime() + e);
		document.cookie = key + '=' + value + ';expires=' + a.toGMTString()
				+ ';path=/';
	},

	remove : function(key) {
		document.cookie = key + '=;expires=Thu, 01-Jan-70 00:00:01 GMT;path=/';
	}
}
if (typeof naviki == "undefined") {
	var naviki = {}
}

if (typeof naviki.util == "undefined") {
	naviki.util = {}
}

naviki.util.geo = {

	/**
	 * Calculates the distance between two points.
	 * 
	 * @param p1 Object that contains the geo-coordinates.
	 * @param p2 Object that contains the geo-coordinates.
	 * @return integer The distance in km.
	 */
	calculateDistance : function(p1, p2) {
		var radlat1 = Math.PI * p1.lat / 180;
		var radlat2 = Math.PI * p2.lat / 180;
		var radlon1 = Math.PI * p1.lng / 180;
		var radlon2 = Math.PI * p2.lng / 180;
		var theta = p1.lng - p2.lng;
		var radtheta = Math.PI * theta / 180;
		var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1)
				* Math.cos(radlat2) * Math.cos(radtheta);
		dist = Math.acos(dist);
		dist = dist * 180 / Math.PI;
		dist = dist * 60 * 1.1515;
		dist = dist * 1.609344;

		if (!isNaN(dist)) {
			return dist;
		}

		return 0;
	},

	/**
	 * Calculate the bearing between two positions as a value from 0-360
	 *
	 * @param lat1 - The latitude of the first position
	 * @param lng1 - The longitude of the first position
	 * @param lat2 - The latitude of the second position
	 * @param lng2 - The longitude of the second position
	 *
	 * @return int - The bearing between 0 and 360
	 */
	calculateBearing : function(lat1, lng1, lat2, lng2) {
		var dLon = (lng2 - lng1);
		var y = Math.sin(dLon) * Math.cos(lat2);
		var x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
				* Math.cos(lat2) * Math.cos(dLon);
		var brng = Math.atan2(y, x) * 180 / Math.PI;
		return 360 - ((brng + 360) % 360);
	}
}
if(typeof naviki == "undefined"){
	var naviki = {}
}

if(typeof naviki.util == "undefined"){
	naviki.util = {}
}

naviki.util.googlepolyline = {
		
		/**
		 * Decodes a polyline that was encoded using the Google Maps method.
		 *
		 * The encoding algorithm is detailed here:
		 * http://code.google.com/apis/maps/documentation/polylinealgorithm.html
		 *
		 * This function is based off of Mark McClure's JavaScript polyline decoder
		 * (http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/decode.js)
		 * which was in turn based off Google's own implementation.
		 *
		 * This function assumes a validly encoded polyline.  The behaviour of this
		 * function is not specified when an invalid expression is supplied.
		 *
		 * @param String encoded the encoded polyline.
		 * 
		 * @return Array an Nx2 array with the first element of each entry containing
		 *  the latitude and the second containing the longitude of the
		 *  corresponding point.
		 */
		decode : function(encoded, precision) {

			if (typeof precision == "undefined" || precision == null) {
				precision = 5;
			}
			
			var precisionMultiplier = Math.pow(10, -precision);
			var index = 0, lat = 0, lng = 0, array = [];
			var b, shift, result;
			var dlat,dlng;
			
			while (index < encoded.length) {
				// The encoded polyline consists of a latitude value followed by a
				// longitude value.  They should always come in pairs.  Read the
				// latitude value first.
				shift  = 0;
				result = 0;
				do {
					// The statement returns the ASCII code for the character at index.  
					// Subtract 63 to get the original value.
					// (63 was added to ensure proper ASCII characters are displayed
					// in the encoded polyline string, which is `human` readable)
					b = encoded.charCodeAt(index++) - 63;
					// AND the bits of the byte with 0x1f to get the original 5-bit `chunk.
					// Then left shift the bits by the required amount, which increases
					// by 5 bits each time.
					// OR the value into results, which sums up the individual 5-bit chunks
					// into the original value.  Since the 5-bit chunks were reversed in
					// order during encoding, reading them in this way ensures proper
					// summation.
					result |= (b & 0x1f) << shift;
					shift += 5;
					// Continue while the read byte is >= 0x20 since the last `chunk`
					// was not OR'd with 0x20 during the conversion process. (Signals the end)
				} while (b >= 0x20);
				// Check if negative, and convert. (All negative values have the last bit set)	
				dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
				// Compute actual latitude since value is offset from previous value.
				lat += dlat;
				
				// The next values will correspond to the longitude for this point.
				shift  = 0;
				result = 0;
				do {
					b = encoded.charCodeAt(index++) - 63;
					result |= (b & 0x1f) << shift;
					shift += 5;
				} while (b >= 0x20);
				dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
				lng += dlng;
				
				var latVal = (lat * precisionMultiplier).toFixed(precision);
				var lngVal = (lng * precisionMultiplier).toFixed(precision);
				array.push([latVal, lngVal]);
			}
			
			return array;
		},

		/**
		 * Encodes a polyline that was decoded using the Google Maps method.
		 * (https://developers.google.com/maps/documentation/utilities/polylinealgorithm?hl=de&csw=1)
		 */
		encode : function(points, precision){
			
			precision = Math.pow(10, precision);
			
			var dlat, dlng;
			var latE5,lngE5;
			var nextValue;
			var plat = 0, plng = 0;
			var encodedPoints = "";
			
			for(var i = 0; i < points.length; i++){	
				// Take the decimal value and multiply it by 1e5.
				latE5 =  parseInt(points[i][0] * precision);    
			    // Calculate the delta from the previous value.
			    dlat = latE5 - plat;	    
			    // Hold the current value.
			    plat = latE5;    
			    // Left-shift the value one bit.
			    dlat = dlat << 1;    
			    // If the original decimal value is negative, invert this encoding.
			    if (dlat < 0) {
			    	dlat = ~(dlat);
			    }    
			    // OR each value with 0x20 if another 5-bit chunk follows.
			    // Add 63 to each value.
			    // Convert each value to its ASCII equivalent.
				while (dlat >= 0x20) {
					nextValue = (0x20 | (dlat & 0x1f)) + 63;
					encodedPoints += String.fromCharCode(nextValue);
					dlat >>= 5;
				}
				encodedPoints += String.fromCharCode(dlat + 63);
				
				// The next values will correspond to the longitude for this point.
			    lngE5 = parseInt(points[i][1] * precision);
			    dlng = lngE5 - plng;
			    plng = lngE5;
			    dlng = dlng << 1;
			    
			    if (dlng < 0) {
			    	dlng = ~(dlng);
			    }
			    
			    while (dlng >= 0x20) {
					nextValue = (0x20 | (dlng & 0x1f)) + 63;
					encodedPoints += String.fromCharCode(nextValue);
					dlng >>= 5;
				}
				encodedPoints += String.fromCharCode(dlng + 63);
			}
			return encodedPoints;
		},
		
		mergeTracks : function(geom) {
			if(geom == null) {
				console.log("geom was null!");
				return [];
			}
			
			var points = new Array();
			for (var i = 0; i < geom.length; i++) {
				const pointList = naviki.util.googlepolyline.decode(geom[i], 5);
				for (var counter = 0; counter < pointList.length; counter++) {
					points.push([parseFloat(pointList[counter][0]), parseFloat(pointList[counter][1])]);
				}
			}
			return points;
		},
		
		reverseTrack: function(geom) {
			if(geom == null) {
				console.log("geom was null!");
				return;
			}
			const mergedTracks = naviki.util.googlepolyline.mergeTracks(geom);	
			return mergedTracks.reverse();
		},
		
		/**
		 * 
		 * @param encoded
		 * @param max
		 * @returns string encoded the encoded polyline
		 */
		reduceToMaxPoints : function(encoded, max){		
			var points = naviki.util.googlepolyline.decode(encoded, 5);
			if(points.length > max){
				var newArray = new Array();
				var m = parseInt((points.length / max) + 1);
				
				for(var i = 0; i < points.length; i++){
					if(parseInt((i % m)) == 0){
						newArray.push(points[i]);
					}
				}
				return naviki.util.googlepolyline.encode(newArray, 5);
			}
			return encoded;
		},
		
		
		turnDirection: function(encoded){
			var points = naviki.util.googlepolyline.decode(encoded, 5);
			var newArray = new Array();
			for(var i = (points.length - 1); i >= 0; i--){
				newArray.push(points[i]);
			}
			return naviki.util.googlepolyline.encode(newArray, 5);
		}
};
if (typeof naviki == "undefined") {
	var naviki = {}
}

if (typeof naviki.util == "undefined") {
	naviki.util = {}
}

naviki.util.html = {

	/**
	 * The normal bring to top function does not work correctly 
	 * because of the nui- classes. So i must implement ower own.
	 * @returns {Number}
	 */
	bringToTop : function() {
		var aDivs = new Array();
		// get all div elements.
		aDivs = document.getElementsByTagName("div");
		if (aDivs.length == 0) {
			return 10;
		}
		var maxIndex = -9999;
		var count = aDivs.length;
		for (var i = 1; i < count; i++) {
			var div = aDivs[i];
			var sZIndex = Ext.get(div).getStyle("zIndex");
			var nZIndex = (!sZIndex || isNaN(sZIndex)) ? 0 : parseInt(sZIndex,
					10);
			if (nZIndex > maxIndex) {
				maxIndex = nZIndex;
			}
		}
		return maxIndex;
	},

	/**
	 * Strip HTML and PHP tags from a string.
	 * @param str
	 * @returns
	 */
	stripTags : function(str) {
		str = str.toString();
		return str.replace(/<\/?[^>]+>/gi, '');
	},

	/**
	 * Rreplace P tag with Br tag.
	 * @param str
	 * @returns
	 */
	replaceParagraphWithBreak : function(str) {
		str = str.toString();
		str = str.replace(/<p[^>]*?>/gi, "");
		return str.replace("</p>", "<br />");
	},

	/**
	 * Substring not in HTLM tags.
	 * @param str
	 * @param len
	 * @returns
	 */
	substr : function(str, len) {
		var temp = str.substr(0, len);
		if (temp.lastIndexOf('<') > temp.lastIndexOf('>')) {
			temp = str.substr(0, 1 + str.indexOf('>', temp.lastIndexOf('<')));
		}
		return temp;
	}
}
if (typeof naviki == "undefined") {
	var naviki = {}
}

if (typeof naviki.util == "undefined") {
	naviki.util = {}
}

naviki.util.number = {

	/**
	 * Formats a number into a string, also the "." to a ",".
	 */
	formatNumber: function(number) {
		return number.toString().replace(/\./, ","); 
	},

	/**
	 * Rounds a value with <digits> of numbers after the point ,
	 * attention: Safari doesn't support "Number.toLocaleString".
	 */
	round: function(number, digits) {
		var factor = Math.pow(10, digits);
		number = (Math.round(number*factor)) / factor;
		try {
			var roundedNumber = Number(number).toLocaleString(naviki.CONSTANTS.LOCALE_ALL.replace("_","-"), { maximumFractionDigits: digits });
			if (!isNaN(roundedNumber)) {
				return roundedNumber;
			}
		} catch (e) {
			console.log("Can not format number: " + number);
		}
		return number;
	}
};
if (typeof naviki == "undefined") {
	var naviki = {}
}

if (typeof naviki.util == "undefined") {
	naviki.util = {}
}

naviki.util.second = {

	toDate : function(timevalue) {
		var mydate = new Date();
		mydate.setTime(timevalue * 1000);
		var month = mydate.getMonth() + 1;
		if (month < 10) {
			month = "0" + month;
		}
		var day = mydate.getDate();
		if (day < 10) {
			day = "0" + day;
		}
		return day + "." + month + "." + mydate.getFullYear();
	},

	toDateAndTime : function(timevalue) {
		var mydate = new Date();
		mydate.setTime(timevalue * 1000);
		var month = mydate.getMonth() + 1;
		if (month < 10) {
			month = "0" + month;
		}
		var day = mydate.getDate();
		if (day < 10) {
			day = "0" + day;
		}
		var minutes = mydate.getMinutes();
		if (minutes < 10) {
			minutes = "0" + minutes;
		}
		var hours = mydate.getHours();
		if (hours < 10) {
			hours = "0" + hours;
		}
		return day + "." + month + "." + mydate.getFullYear() + ", " + hours
				+ ":" + minutes;
	},

	toTime : function(seconds) {
		var hours = Math.floor(seconds / (60 * 60));
		seconds -= hours * (60 * 60);
		var minutes = Math.floor(seconds / 60);
		if (minutes < 10) {
			minutes = "0" + minutes;
		}
		return hours + ":" + minutes;
	}
}
if(typeof naviki == "undefined"){
	var naviki = {}
}

if(typeof naviki.util == "undefined"){
	naviki.util = {}
}

naviki.util.solr = function(config) {
	this.config = config;
	this.initialize();
};

naviki.util.solr.prototype.initialize = function(){
	this.url = this.config.url;
	this.mainCore = this.config.mainCore;
	this.sharedCore = null;
	if(typeof this.config.sharedCore != "undefined" && this.config.sharedCore != null && this.config.sharedCore.length > 0){
		this.sharedCore = this.config.sharedCore;
	}
};

naviki.util.solr.prototype.getSearchURL = function(){
	this.config.url = naviki.util.url.replaceProtocol(this.config.url);
	return this.config.url + "/solr/" + this.mainCore + "/select";
};

naviki.util.solr.prototype.getReverseSearchURL = function(){
	this.config.url = naviki.util.url.replaceProtocol(this.config.url);
	return this.config.url + "/solr/" + this.mainCore + "/reverse";
};

naviki.util.solr.prototype.getJsonCallback = function(){
	return "json.wrf";
};

naviki.util.solr.prototype.getSearchRequestData = function(query,language,point){
	var result = {
			"q" : query,
			"qt" : "default",
			"language" : language
	};
	if (point != null) {
		result.pt = point.lat + "," + point.lng;
	}
	if(this.sharedCore != null){
		result.collection = this.sharedCore + "," + this.mainCore;
	}
	return result;
};

naviki.util.solr.prototype.getReverseSearchRequestData = function(latitude,longitude,language){
	var pt = latitude + "," + longitude;
	var result = {
			"q": "*:*",
			"fq": "{!geofilt}",
			"pt": pt,
			"d": "5",
			"format" : "json",
			"language" : language,
			"onlyAddress" : true,
			"rows": 1
		};
	if(this.sharedCore != null){
		result.collection = this.mainCore + "," + this.sharedCore;
	}
	return result;
};

naviki.util.solr.prototype.formatSearchResponse = function(response){
	var _self = this;
	var docs = response.response;
	if(response.response.docs){
		docs = response.response.docs;
	}
	var jsonResult = $.map(docs, function(jsonItem) {
		var item = _self.formatResponseItem(jsonItem);
		if(item != null){
			return item;	
		}
	});
	return jsonResult;
};

naviki.util.solr.prototype.formatReverseSearchResponse = function(response){
	var docs = response.response;
	if(response.response.docs){
		docs = response.response.docs;
	}
	if(docs.length == 0){
		return null;
	};
	return this.formatResponseItem(docs[0]);
};

naviki.util.solr.prototype.formatResponseItem = function(item){
		
	var coordinate = item.coordinate.split(",");
	
	var point = {
		lat : coordinate[0],
		lon : coordinate[1],
		icon : null,
		label: item.label,
		subLabel : item.subLabel
	};

	return point;
};

if (typeof naviki == "undefined") {
	var naviki = {}
}

if (typeof naviki.util == "undefined") {
	naviki.util = {}
}

naviki.util.url = {

	/**
	 * This method converts a query string to a object.
	 * e.g. 
	 * source -> ?id=10&type=20
	 * target -> {id: 10,type: 20}
	 * 
	 * @param query
	 * @returns {Object}
	 */
	decodeParams : function(query) {

		if (query.indexOf("?") == 0) {
			query = query.substr(1);
		}

		if (query.indexOf("#") == 0) {
			query = query.substr(1);
		}

		var params = {};
		var pairs = query.split('&');
		for (var i = 0; i < pairs.length; i++) {

			var pair = pairs[i].split('=');

			var accessors = [];
			var name = decodeURIComponent(pair[0]), value = decodeURIComponent(pair[1]);

			if (name.length == 0) {
				continue;
			}

			var name = name.replace(/\[([^\]]*)\]/g, function(k, acc) {
				accessors.push(acc);
				return "";
			});
			accessors.unshift(name);

			var obj = null;
			for (var j = accessors.length - 1; j >= 0; j--) {
				var acc = accessors[j];
				if (obj == null) {
					obj = {};
					obj[acc] = value;
				} else {
					var tmp = {};
					tmp[acc] = obj;
					obj = $.extend({}, tmp);
				}
			}
			params = (jQuery).extend(true, {}, params, obj);
		}

		return params;
	},

	/**
	 * This method converts a object to a query string.
	 * e.g.
	 * source -> {id: 10,type: 20}
	 * target -> ?id=10&type=20
	 * 
	 * @param params
	 * @returns
	 */
	encodeParams : function(params) {

		function encodeItem(params, key) {

			var query = "";

			if (typeof params == "object") {

				for (k in params) {

					if (query.length > 0) {
						query += "&";
					}

					query += encodeItem(params[k], key + "[" + k + "]");
				}
			} else {

				query += key + "=" + params;
			}

			return query;
		}
		;

		var query = "";
		var isFirst = true;

		for (key in params) {

			if (query.length > 0) {
				query += "&";
			}

			query += encodeItem(params[key], key);
		}

		return query;
	},

	/**
	 * This method replaces the protocol from a URL.
	 * 
	 * @param url
	 * @returns {String}
	 */
	replaceProtocol : function(url) {

		var result;
		var protocol = window.location.protocol;

		if (url.search(protocol) == -1) {

			var parts = url.split("//");
			var path = parts[parts.length - 1];

			// If the protocol is http, then cut out the port.
			if (protocol == "http:" && path.search(/:/) > 0) {
				parts = path.split(":");
				result = protocol + "//" + parts[0];
				parts = path.split("/");
				for (var i = 1; i < parts.length; i++) {
					result += "/" + parts[i];
				}
			} else {
				result = protocol + "//" + path;
			}
		} else {
			result = url;
		}

		return result;
	},

	/**
	 * This method replaces a value in the url query.
	 * @param keyToReplace
	 * @param value
	 * @returns {String}
	 */
	replaceParam : function(keyToReplace, value) {

		var url = window.location.protocol + "//" + window.location.host
				+ window.location.pathname;
		var params = naviki.util.url.decodeParams(window.location.search);

		params[keyToReplace] = value;

		var query = naviki.util.url.encodeParams(params);
		if (query.length > 0) {
			url += "?" + query + window.location.hash;
		} else {
			url += window.location.hash;
		}

		return url;
	},

	/**
	 * This method removes a key from the url query.
	 * @param keyToRemove
	 * @returns {String}
	 */
	removeParam : function(keyToRemove) {

		var url = window.location.protocol + "//" + window.location.host
				+ window.location.pathname;
		var params = naviki.util.url.decodeParams(window.location.search);

		if (keyToRemove in params) {
			delete params[keyToRemove];
		}

		var query = naviki.util.url.encodeParams(params);
		if (query.length > 0) {
			url += "?" + query + window.location.hash;
		} else {
			url += window.location.hash;
		}

		return url;
	},
	
	/**
	 * This method removes keys from the url query.
	 * @param keyToRemove
	 * @returns {String}
	 */
	removeParams : function(keysToRemove) {

		var url = window.location.protocol + "//" + window.location.host
				+ window.location.pathname;
		var params = naviki.util.url.decodeParams(window.location.search);

		for (var key in params) {
			if(keysToRemove.indexOf(key) != -1) {  
				delete params[key];
			}		
		}

		var query = naviki.util.url.encodeParams(params);
		if (query.length > 0) {
			url += "?" + query + window.location.hash;
		} else {
			url += window.location.hash;
		}

		return url;
	},	

	/**
	 * This method gives back a value from the url query.
	 * @param key
	 * @returns
	 */
	extractValue : function(key) {
		var params = window.location.search, value = "";

		if (params.indexOf(key) < 0) {
			return null;
		}

		value = params.substring(params.indexOf(key), params.length);
		value = value.substring(key.length + 1,
				(value.indexOf("&") > -1) ? value.indexOf("&") : value.length);
		return value;
	},

	/**
	 * This method adds a slash to the end when it is missing.
	 * @param url
	 * @returns the formated url
	 */
	addSlash : function(url) {
		var pos = url.indexOf("/");
		if (pos != 0) {
			url = "/" + url;
		}
		return url;
	},
	
	/**
	 * This method gives back the domain from the url.
	 * @param url
	 * @returns
	 */
	extractDomain: function(url) {
	    var domain = url.replace(/(https?:\/\/)?(www.)?/i, '');
	    domain = domain.split('.');
	    domain = domain.slice(domain.length - 2).join('.');
	    if (domain.indexOf('/') !== -1) {
	        return domain.split('/')[0];
	    }
	    return domain;
	}
}
if (typeof naviki == "undefined") {
	var naviki = {}
}

if (typeof naviki.util == "undefined") {
	naviki.util = {}
}

naviki.util.localeformatter = {

	FACTOR_KCAL_KJ: 4.1868,

	ENERGY_UNIT_KCAL: 10,
	ENERGY_UNIT_KJ: 20,

	getConvertedEnergy: function(energyInKilocalories) {
		var userEnergyUnit = naviki.util.user.getUserEnergyUnit();
		if (userEnergyUnit && userEnergyUnit == this.ENERGY_UNIT_KJ) {
			return "" + Math.round(energyInKilocalories * this.FACTOR_KCAL_KJ) + " " + naviki.Lang.getLL("pi_userprofile.energy.kilojoule");
		}
		return "" + Math.round(energyInKilocalories) + " " + naviki.Lang.getLL("pi_userprofile.energy.kilocalories");
	},

}
if (typeof naviki == "undefined") {
	var naviki = {}
}

if (typeof naviki.util == "undefined") {
	naviki.util = {}
}

naviki.util.user = {
		
	isLoggedIn: function() {
		if(typeof(localStorage) !== "undefined") {	
			var userState = window.localStorage.getItem("_n_u_s");
			if(userState != "undefined" && userState != null) {
				return userState == "in" ? true : false;
			}
		}
		return false;
	},
	
	setLoggedIn: function(status) {
		if(typeof(localStorage) !== "undefined") {	
			// saving of booleans causes problems
			window.localStorage.setItem("_n_u_s", status ? "in" : "out");
		}
	},
	
	removeLoggedIn: function() {
		if(typeof(localStorage) !== "undefined") {	
			window.localStorage.removeItem("_n_u_s");
		}
	},
	
	setUsername: function(username) {
		if(typeof(localStorage) !== "undefined") {	
			window.localStorage.setItem("_n_u_n", username);
		}
	},
	
	getUsername: function() {
		if(typeof(localStorage) !== "undefined") {	
			var username = window.localStorage.getItem("_n_u_n");
			if(username != "undefined" && username != null) {
				return username;
			}
		}
		return null;
	},
	
	removeUsername: function() {
		if(typeof(localStorage) !== "undefined") {	
			window.localStorage.removeItem("_n_u_n");
		}
	},

	setUserId: function(userId) {
		if(typeof(localStorage) !== "undefined") {
			window.localStorage.setItem("_n_u_id", userId);
		}
	},

	getUserId: function() {
		if(typeof(localStorage) !== "undefined") {
			var userId = window.localStorage.getItem("_n_u_id");
			if(userId != "undefined" && userId != null) {
				return userId;
			}
		}
		return null;
	},

	removeUserId: function() {
		if(typeof(localStorage) !== "undefined") {
			window.localStorage.removeItem("_n_u_id");
		}
	},
	
	isActivated: function() {
		if(typeof(localStorage) !== "undefined") {	
			var userState = window.localStorage.getItem("_n_u_act");
			if(userState != "undefined" && userState != null) {
				return userState == "y" ? true : false;
			}
		}
		return false;
	},
	
	setActivated: function(status) {
		if(typeof(localStorage) !== "undefined") {	
			// saving of booleans causes problems
			window.localStorage.setItem("_n_u_act", status ? "y" : "n");
		}
	},
	
	getUserAverageSpeed: function() {
		if (typeof(localStorage) !== "undefined") {	
			var avgSpeed = window.localStorage.getItem("_n_u_asp");
			if (avgSpeed != "undefined" && avgSpeed != null) {
				return avgSpeed;
			}
		}
		return 15;
	},
	
	setUserAverageSpeed: function(avgSpeed) {
		if (typeof(localStorage) !== "undefined") {
			window.localStorage.setItem("_n_u_asp", avgSpeed);
		}
	},

	getUserEnergyUnit: function() {
		if (typeof(localStorage) !== "undefined") {
			var energyUnit = window.localStorage.getItem("_n_u_ueu");
			if (energyUnit != "undefined" && energyUnit != null) {
				return energyUnit;
			}
		}
		return null;
	},

	setUserEnergyUnit: function(energyUnit) {
		if (typeof(localStorage) !== "undefined") {
			window.localStorage.setItem("_n_u_ueu", energyUnit);
		}
	},

	getUserWayFilters: function() {
		if (typeof(localStorage) !== "undefined") {
			var wayFilters = window.localStorage.getItem("_n_u_way_filters");
			if (wayFilters != "undefined" && wayFilters != null) {
				return JSON.parse(wayFilters);
			}
		}
		return null;
	},

	setUserWayFilters: function(wayFilters) {
		if (typeof(localStorage) !== "undefined") {
			window.localStorage.setItem("_n_u_way_filters", wayFilters != null ? JSON.stringify(wayFilters) : null);
		}
	},

	getUserWaySort: function() {
		if (typeof(localStorage) !== "undefined") {
			var waySort = window.localStorage.getItem("_n_u_way_sort");
			if (waySort != "undefined" && waySort != null) {
				return waySort;
			}
		}
		return null;
	},

	setUserWaySort: function(waySort) {
		if (typeof(localStorage) !== "undefined") {
			window.localStorage.setItem("_n_u_way_sort", waySort);
		}
	},
}
if (typeof naviki == "undefined") {
	var naviki = {}
}

if (typeof naviki.util == "undefined") {
	naviki.util = {}
}

naviki.util.pixel = {
	
		// distance from a point to a segment between two points
		pointToSegmentDistance:  function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2) {
			return Math.sqrt(this._sqClosestPointOnSegment(p, p1, p2, true));
		},
		
		closestPointOnSegment: function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2) {
			return this._sqClosestPointOnSegment(p, p1, p2);
		},
		
		// return closest point on segment or distance to that point
		_sqClosestPointOnSegment: function (p, p1, p2, sqDist) {
			var x = p1.x,
				y = p1.y,
				dx = p2.x - x,
				dy = p2.y - y,
				dot = dx * dx + dy * dy,
				t;

			if (dot > 0) {
				t = ((p.x - x) * dx + (p.y - y) * dy) / dot;

				if (t > 1) {
					x = p2.x;
					y = p2.y;
				} else if (t > 0) {
					x += dx * t;
					y += dy * t;
				}
			}

			dx = p.x - x;
			dy = p.y - y;

			return sqDist ? dx * dx + dy * dy : {x:x, y:y};
		},
		
		// square distance (to avoid unnecessary Math.sqrt calls)
		dist: function (p1, p2) {
			var xs = p2.x - p1.x,
				ys = p2.y - p1.y;		
		
			xs *= xs;
			ys *= ys;
		 
			return Math.sqrt( xs + ys );
		},
}
/*
 *  jQuery Boilerplate - v3.3.1
 *  A jump-start for jQuery plugins development.
 *  http://jqueryboilerplate.com
 *
 *  Made by Zeno Rocha
 *  Under MIT License
 */
// the semi-colon before function invocation is a safety net against concatenated
// scripts and/or other plugins which may not be closed properly.
;(function($, window, document, undefined) {

	var pluginName = "History";
	
	function Plugin(settings){
		
		var defaults = {
			popstate: null
		};
		
		if (settings){
			$.extend(this, defaults, settings);
		} else {
			$.extend(this, defaults);
		}
		
		this.enable = false;
		this.init();
	}
	
	Plugin.prototype = {
		
		init : function(){
			
			var _self = this;
			
			/*
	         * Note, this is the only difference when using this library,
	         * because the object window.location cannot be overriden,
	         * so library the returns generated "location" object within
	         * an object window.history, so get it out of "history.location".
	         * For browsers supporting "history.pushState" get generated
	         * object "location" with the usual "window.location".
	         */
	        var location = window.history.location || window.location;
	        
	        $(window).on('popstate', function(e) {
	        	try {
		        	if (typeof _self.popstate == "function") {
	        			_self.popstate(history.state);
	        		}
	        	} catch (e) {
	        		console.log(e);
	        	}
	       });
		},
	
		replaceState: function(state, title, url) {
			try {
				if (typeof history != "undefined") {
					if (state == null) {
						state = this.getState();
					}
					history.replaceState(state, title, url);
				}
			} catch (e) {
				console.log(e);
			}
		},
		
		pushState: function(state, title, url) {
			try {
				if (typeof history != "undefined") {
					history.pushState(state, title, url);
				}
			} catch (e) {
				console.log(e);
			}
		},
		
		updateURL: function(url) {
			try {
				if (typeof history != "undefined") {
					history.replaceState(this.getState(), "", url);
				}
			} catch (e) {
				console.log(e);
			}
		},
		
		getState: function() {
			try {
				if(typeof history != "undefined") {
					return history.state;
				}
			} catch (e) {
				console.log(e);
			}
			return null;
			
		},
		
		back: function() {
			try {
				if(typeof history != "undefined") {
					history.back();
				}
			} catch (e) {
				console.log(e);
			}
		}
	}
		
	$.fn[pluginName] = function(options) {
		return new Plugin(options);
	}

})(jQuery, window, document);
/*
 *  jQuery Boilerplate - v3.3.1
 *  A jump-start for jQuery plugins development.
 *  http://jqueryboilerplate.com
 *
 *  Made by Zeno Rocha
 *  Under MIT License
 */
// the semi-colon before function invocation is a safety net against concatenated
// scripts and/or other plugins which may not be closed properly.
;(function ( $, window, document, undefined ) {

		// undefined is used here as the undefined global variable in ECMAScript 3 is
		// mutable (ie. it can be changed by someone else). undefined isn't really being
		// passed in so we can ensure the value of it is truly undefined. In ES5, undefined
		// can no longer be modified.

		// dialog and document are passed through as local variable rather than global
		// as this (slightly) quickens the resolution process and can be more efficiently
		// minified (especially when both are regularly referenced in your plugin).

		// Create the defaults once
		var pluginName = "navikiUiDialog";
		var defaults = {
				id: "naviki-ui-dialog",
				close: true,
				content: "",
				footer: "",
				buttons: null,
				className: null,
				closeCallback: null,
				openCallback: null
		};

		// The actual plugin constructor
		function Plugin (options ) {

				// jQuery has an extend method which merges the contents of two or
				// more objects, storing the result in the first object. The first object
				// is generally empty as we don't want to alter the default options for
				// future instances of the plugin
				this.options = $.extend( {}, defaults, options );
				this._defaults = defaults;
				this._name = pluginName;
				
				this.element = null;
				this.init();
		}

		Plugin.prototype = {
				
				init: function () {
					// Place initialization logic here
					// You already have access to the DOM element and
					// the options via the instance, e.g. this.element
					// and this.options
					// you can add more functions like the one below and
					// call them like so: this.yourOtherFunction(this.element, this.options).		
					var _self = this;
					
					if ($("#" + this.options.id).length == 0) {

						this.element = $("<div/>",{id:this.options.id,"class":"naviki-ui-dialog-wrapper"});
						$('body').append(this.element);
						
						var dialog = $("<div/>",{"class":"naviki-ui-dialog"});
						this.element.append(dialog);
						
						var container = $("<div/>",{"class":"dialog-container"});
						dialog.append(container);
						
						container.append($("<div/>",{"class":"header"}));
						container.append($("<div/>",{"class":"content"}));
						container.append($("<div/>",{"class":"buttons"}));
						container.append($("<div/>",{"class":"footer"}));
						
						$(document).keyup(function (e) {
				            if (e.keyCode == 27) {
				            	_self.close();
				            }
				        });	
						
						if (this.options.className != null) {
							this.element.addClass(this.options.className);
						}
					} else {
						this.element = $("#" + this.options.id);
					}
				
					this.element.find('.header').first().empty();
					this.element.find('.buttons').first().empty();
					this.element.find('.content').first().html(this.options.content);
					this.element.find('.footer').first().html(this.options.footer);			
					
					if (this.options.footer.length == 0) {
						this.element.find('.footer').first().css("display","none");
					} else {
						this.element.find('.footer').first().css("display","");
					}
					
					if (this.options.close) {
						this.element.find('.header').first().append($("<span/>",{"class":"icon-close"}));
						this.element.find('.icon-close').first().click(function(){
							_self.close();
						});
					}
					
					if (this.options.buttons != null && $.isArray(this.options.buttons) && this.options.buttons.length > 0) {

						for (var i = 0; i < this.options.buttons.length; i++) {
							(function(button){
								btn = $("<button/>",{type:"button","class":"btn btn-default"});
								btn.text(button.text);
								btn.click(button.callback);
								_self.element.find('.buttons').first().append(btn);
							})(this.options.buttons[i]);
						}
					}
					
					$( window ).resize(function() {
						_self.resize();
					});
				},
				
				open: function() {
					this.element.addClass('visible');
					this.resize();
					if (typeof this.options.openCallback == "function") {
						this.options.openCallback();
					}
				},
			    
			    close: function() {
					this.element.removeClass('visible');
					if (typeof this.options.closeCallback == "function") {
						this.options.closeCallback();
					}
			    },
			    
			    resize: function() {
			    	var content = this.element.find('.content').first();					
					content.css("height","");
					var height = content.first().outerHeight();
					var windowHeight = $(window).outerHeight() * 0.9;
					if (height > windowHeight) {
						content.css("height",windowHeight);
					}
			    }
		
		};

		$.fn[pluginName] = function(options) {
			return new Plugin(options);
		}

})( jQuery, window, document );
/*
 *  jQuery Boilerplate - v3.3.1
 *  A jump-start for jQuery plugins development.
 *  http://jqueryboilerplate.com
 *
 *  Made by Zeno Rocha
 *  Under MIT License
 */
// the semi-colon before function invocation is a safety net against concatenated
// scripts and/or other plugins which may not be closed properly.
;(function ( $, window, document, undefined ) {

		// undefined is used here as the undefined global variable in ECMAScript 3 is
		// mutable (ie. it can be changed by someone else). undefined isn't really being
		// passed in so we can ensure the value of it is truly undefined. In ES5, undefined
		// can no longer be modified.

		// window and document are passed through as local variable rather than global
		// as this (slightly) quickens the resolution process and can be more efficiently
		// minified (especially when both are regularly referenced in your plugin).

		// Create the defaults once
		var pluginName = "navikiUiLoading";
		var defaults = {
				id : null,
				zindex: null
		};

		// The actual plugin constructor
		function Plugin ( element, options ) {
				
				this.calcualte = function(){				
					$("#loader-overlay-" + this.options.id).css({
						opacity : 0.15,
						top : $(this.element).position().top,
						left: $(this.element).position().left,
						width : $(this.element).outerWidth(),
						height: $(this.element).outerHeight()
					});
					$("#loader-img-" + this.options.id).css({
						top : ($(this.element).height() / 2 - 9),
						left: ($(this.element).width() / 2 - 9)
					});
				};
				
				var uniqID = {
					counter:0,
					get:function(prefix) {
						if(!prefix) {
							prefix = "uniqid";
						}
						var id =  prefix+""+uniqID.counter++;
						if (jQuery("#"+id).length == 0) {
							return id;
						} else {
							return uniqID.get()
						}
					}
				}

				this.element = element;
				// jQuery has an extend method which merges the contents of two or
				// more objects, storing the result in the first object. The first object
				// is generally empty as we don't want to alter the default options for
				// future instances of the plugin
				this.options = $.extend( {}, defaults, options );
				this.options.id = uniqID.get();
				this._defaults = defaults;
				this._name = pluginName;
				this.init();
		}

		Plugin.prototype = {
				init: function () {
					// Place initialization logic here
					// You already have access to the DOM element and
					// the options via the instance, e.g. this.element
					// and this.options
					// you can add more functions like the one below and
					// call them like so: this.yourOtherFunction(this.element, this.options).		
					//this.options.id = $(this.element).uniqueId().attr( "id" );
					var _self = this;
					var node = "<div id='loader-overlay-" + this.options.id + "' class='naviki-ui-loader-overlay'";
					if(this.options.zindex != null) {
						node += " style='z-index:" + this.options.zindex + ";'";
					}
					node += ">" +
					"<img class='naviki-ui-loader-img' src='typo3conf/ext/naviki/Resources/Public/Img/ajax-loader-2.gif' id='loader-img-" + this.options.id + "' />" +
					"</div>";		
					$(this.element).append(node);
					$(window).resize(function() {
						_self.calcualte();
					});
				},
				hide : function(args) {
					$("#loader-overlay-" + this.options.id).fadeOut(0);
				},
				show : function(args) {
					this.calcualte();
					$("#loader-overlay-" + this.options.id).fadeIn(0);
				}
		};

		// A really lightweight plugin wrapper around the constructor, 
		// preventing against multiple instantiations and allowing any
		// public function (ie. a function whose name doesn't start
		// with an underscore) to be called via the jQuery plugin,
		// e.g. $(element).defaultPluginName('functionName', arg1, arg2)
		$.fn[ pluginName ] = function ( options ) {
			var args = arguments;
			if (options === undefined || typeof options === 'object') {
				return this.each(function () {
		            if (!$.data(this, 'plugin_' + pluginName)) {
		                $.data(this, 'plugin_' + pluginName, new Plugin( this, options ));
		            }
		        });
		    } else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
		        return this.each(function () {
		            var instance = $.data(this, 'plugin_' + pluginName);
		            if (instance instanceof Plugin && typeof instance[options] === 'function') {
		                instance[options].apply( instance, Array.prototype.slice.call( args, 1 ) );
		            }
		        });
		    }
		};

})( jQuery, window, document );
/* jQuery Boilerplate - v3.3.1 */
;(function ( $, window, document, undefined ) {

		var pluginName = "navikiUiUserActivationHint";
		var defaults = {
				oauth2MicroServiceHostname: ""
		};

		function Plugin (options) {
				this.options = $.extend( {}, defaults, options );
				this._defaults = defaults;
				this._name = pluginName;
				
				this.element = null;
				this.init();
		}

		Plugin.prototype = {
				init: function () {
					if (naviki.util.user.isLoggedIn() && !naviki.util.user.isActivated()) {
						this._requestActivationStatus();
					}
				},
				
				_showUserActivationHintBar: function(email) {
					var _this = this;

					var hintText = naviki.Lang.getLL('base.deactivatedAccountHint');
					hintText = hintText.replace("{0}", email);

					var linkUrl = this.options.oauth2MicroServiceHostname + "/reactivateUser";
					if (naviki.util.user.getUsername() != null)
						linkUrl += "?emailPlaceholder=" + naviki.util.user.getUsername();

					var content = "<div class='cookie-choice-info warning'><div>";
					content += "<span>" + hintText + "</span>";
					content += "<a href='" + linkUrl + "' id='user-activation-resend-button'>" + naviki.Lang.getLL('base.deactivatedAccountResendButton') + "</a>";
					content += "<a href='" + naviki.CONSTANTS.LANGUAGE + "/naviki/intern/my-naviki-profile-and-settings/'>" + naviki.Lang.getLL('base.deactivatedAccountChangeEmailButton') + "</a>";
					content += "</div></div>";
						
					if ($('#fixedHeader').length > 0) {
						$('#fixedHeader').prepend(content);
					} else {
						$('body').prepend(content);
					}

					$("#user-activation-resend-button").click(function(event) {
						event.preventDefault();
						var url = $(this).attr("href");
						_this._openDialog(url);	
					});	
				},
		 		
		 		_requestActivationStatus: function() {
					var _this = this;
					$.ajax({
						url: this.options.oauth2MicroServiceHostname + "/api/user/activatedAccount",
						type: "POST",
						cache: false,
						dataType : "json",
						contentType: 'application/json; charset=utf-8',
					    processData: false,
					    beforeSend: function(xhr) {
							if (naviki.util.api.getAccessToken() != null) {
								xhr.setRequestHeader('Authorization', 'Bearer ' + naviki.util.api.getAccessToken());
							}
					    },
						success: function(data) {
							if (typeof data.valid !== 'undefined') {
								if (data.valid) {
									naviki.util.user.setActivated(true);
								} else {
									_this._showUserActivationHintBar(data.email);
								}
							}
						},
						error: function (request, status, error) {
							console.log("Error in jquery.naviki.ui.useractivationhint.js: " + error);
		                }
					});
				},
				
				_openDialog: function(url) {	
					this.dialog = $.colorbox({
						width: 320, 
						height: 480, 
						scrolling: false,
						iframe: true, 
						href: url
					});
				}
		};

		$.fn[pluginName] = function(options) {
			return new Plugin(options);
		}
})( jQuery, window, document );
/*
 *  jQuery Boilerplate - v3.3.1
 *  A jump-start for jQuery plugins development.
 *  http://jqueryboilerplate.com
 *
 *  Made by Zeno Rocha
 *  Under MIT License
 */
// the semi-colon before function invocation is a safety net against concatenated
// scripts and/or other plugins which may not be closed properly.
;(function ( $, window, document, undefined ) {

		// undefined is used here as the undefined global variable in ECMAScript 3 is
		// mutable (ie. it can be changed by someone else). undefined isn't really being
		// passed in so we can ensure the value of it is truly undefined. In ES5, undefined
		// can no longer be modified.

		// dialog and document are passed through as local variable rather than global
		// as this (slightly) quickens the resolution process and can be more efficiently
		// minified (especially when both are regularly referenced in your plugin).

		// Create the defaults once
		var pluginName = "navikiUiCookieChoices";
		var defaults = {
				cookieName: "displayCookieConsent",
			    cookieConsentId: "cookieChoiceInfo",
			    dismissLinkId: "cookieChoiceDismiss",
				cookieText: "Please note this website uses cookies enabling us to give you the best user experience.",
				dismissText: "OK",
				linkText: "Learn more",
				linkHref: "http://www.example.net/p/cookies.html"
		};

		// The actual plugin constructor
		function Plugin (options ) {

				// jQuery has an extend method which merges the contents of two or
				// more objects, storing the result in the first object. The first object
				// is generally empty as we don't want to alter the default options for
				// future instances of the plugin
				this.options = $.extend( {}, defaults, options );
				this._defaults = defaults;
				this._name = pluginName;
				
				this.element = null;
				this.init();
		}

		Plugin.prototype = {
				
				init: function () {
					if (this._shouldDisplayConsent()) {
						this._showCookieConsentBar();
					}
				},
				
				_showCookieConsentBar: function() {
					var content = "<div class='cookie-choice-info' id='"+this.options.cookieConsentId+"'>";
					content += "<div>"
					content += "<span>"+this.options.cookieText+"</span>";
					content += "<a id='"+this.options.dismissLinkId+"'>"+this.options.dismissText+"</a>";
					content += "<a href='"+this.options.linkHref+"' target='_blank'>"+this.options.linkText+"</a>";		
					content += "</div></div>";
						
					if ($('#fixedHeader').length > 0) {
						$('#fixedHeader').prepend(content);
					} else {
						$('body').prepend(content);
					}
					
					var _self = this;
					$("#"+this.options.dismissLinkId).click(function(){
						_self._saveUserPreference();
						_self._removeCookieConsent();
					});
				},
				
		 		_removeCookieConsent: function() {
		 			var cookieChoiceElement = document.getElementById(this.options.cookieConsentId);
		 			if (cookieChoiceElement != null) {
		 				cookieChoiceElement.parentNode.removeChild(cookieChoiceElement);
		 				$(document).trigger("cookieChoiceRemoved");
		 			}
		 		},

		 		_saveUserPreference: function() {
		 			localStorage.setItem(this.options.cookieName, 'y');
		 		},

		 		_shouldDisplayConsent: function() {
		 			const cookieValue = Cookies.get(this.options.cookieName);
		 			if (typeof cookieValue !== 'undefined' && cookieValue == 'y') {
		 				// move state from cookie to local storage
		 				this._saveUserPreference();
		 				Cookies.remove(this.options.cookieName, { path: '/' });
		 				return false;
		 			}

		 			const localStorageValue = localStorage.getItem(this.options.cookieName);
		 			return (typeof localStorageValue === null || localStorageValue != 'y');
		 		}
		};

		$.fn[pluginName] = function(options) {
			return new Plugin(options);
		}

})( jQuery, window, document );
/*
 *  jQuery Boilerplate - v3.3.1
 *  A jump-start for jQuery plugins development.
 *  http://jqueryboilerplate.com
 *
 *  Made by Zeno Rocha
 *  Under MIT License
 */
// the semi-colon before function invocation is a safety net against concatenated
// scripts and/or other plugins which may not be closed properly.
;
(function($, window, document, undefined) {

	// undefined is used here as the undefined global variable in ECMAScript 3 is
	// mutable (ie. it can be changed by someone else). undefined isn't really being
	// passed in so we can ensure the value of it is truly undefined. In ES5, undefined
	// can no longer be modified.

	// window and document are passed through as local variable rather than global
	// as this (slightly) quickens the resolution process and can be more efficiently
	// minified (especially when both are regularly referenced in your plugin).

	// Create the defaults once
	var pluginName = "navikiUserAuth";
	var defaults = {};

	// The actual plugin constructor
	function Plugin(element, options) {

		this.element = element;
		// jQuery has an extend method which merges the contents of two or
		// more objects, storing the result in the first object. The first object
		// is generally empty as we don't want to alter the default options for
		// future instances of the plugin
		this.options = $.extend({}, defaults, options);
		this._defaults = defaults;
		this._name = pluginName;
		
		this.history = new $.fn.History();
		this.dialog = null;
		this.dialogWidth = 320;
		this.dialogHeight = 480;
		
		this.init();
	}

	Plugin.prototype = {

		init : function() {
			// Place initialization logic here
			// You already have access to the DOM element and
			// the options via the instance, e.g. this.element
			// and this.options
			// you can add more functions like the one below and
			// call them like so: this.yourOtherFunction(this.element, this.options).		
			var _this = this;	
			
			// remove unused item
			if(typeof(localStorage) !== "undefined") {	
				window.localStorage.removeItem("_n_um");
				window.localStorage.removeItem("_n_un");
				window.localStorage.removeItem("_n_us");
			}
			
			if (window.location != window.parent.location) { 
				// THE PAGE IS OPENED INSIDE A IFRAME
				// event listener for cross origin communication,
				window.addEventListener("message", function(event) {
					
					// Do we trust the sender of this message?
				    var domain = naviki.util.url.extractDomain(event.origin);
				    if (domain !== "localhost:18080" &&
				        domain !== "naviki.org") {
				        return;
				    }
					
					if (event.data.get == "search") {
						event.source.postMessage({search:window.location.search},  event.origin);
					}
				}, false);	
			} else {
				// THE PAGE IS OPENED INSIDE A BROWSER TAB
				// event listener for cross origin communication,
				window.addEventListener("message", function(event) {
					
					// Do we trust the sender of this message?
				    var domain = naviki.util.url.extractDomain(event.origin);
				    if (domain !== "localhost:18080" &&
				        domain !== "naviki.org") {
				        return;
				    }	
					
					if (_this.dialog != null) {
						if (event.data.height) {
							//enough height for g-recaptcha
							const newHeight = event.data.height < 522 ? 522 : event.data.height;
							_this.dialog.colorbox.resize({
								innerWidth: _this.dialogWidth,
								innerHeight: newHeight
							});
						}
						if (event.data.search) {
							var query = naviki.util.url.decodeParams(decodeURI(event.data.search.substring(1)));
							_this.initLogin(query);
							setTimeout(function(){
								_this.dialog.colorbox.close();
								_this.dialog.colorbox.remove();
							}, 3000);
						}
					}
				}, false);			

				// open the login/register page inside a iframe
				$("#header-register-container a").first().click(function(event) {
					event.preventDefault();
					var url = $(this).attr("href");
					_this.openLoginDialog(url);	
				});	
				$("#header-login-container a").first().click(function(event) {
					event.preventDefault();
					var url = $(this).attr("href");
					_this.openLoginDialog(url);				
				});	

				// catch url query parameters as object
				var query = naviki.util.url.decodeParams(decodeURI(window.location.search.substring(1)));	
				this.initLogin(query);
			}
		},
		
		initLogin: function(query) {
			if (query.login != undefined) {
				// catch typo3 sociallogin
				this.login(null);
				// remove GET params
				var url = naviki.util.url.removeParam("login");
				this.history.replaceState(null,null,url);
			} else if (query.code) {
				// catch java oauth2
				this.login(query.code);
				// remove GET params
				var url = naviki.util.url.removeParams(new Array("code","state"));
				this.history.replaceState(null,null,url);
			} else if(naviki.util.user.isLoggedIn() && naviki.util.user.getUsername() != null) {
				this.showMenuBtn();
			} else {
				this.showLoginBtn();
			}
		},
		
		login: function(code) {
			var _this = this;
			var params = "?eID=controllerDispatcher&request[format]=json&request[controller]=FeUser&request[action]=feSession";	
			params += "&request[arguments][code]=" + code;

			$.ajax({
				url: window.location.pathname + encodeURI(params),
				type: "GET",
				cache: false,
				dataType : "json",
				contentType: 'application/json; charset=utf-8',
			    processData: false,
				success : function(data) {				
					naviki.util.user.setLoggedIn(data.status);		
					if (data.status) {	
						naviki.util.api.setAccessToken(data.accessToken);
						naviki.util.api.setRefreshToken(data.refreshToken);
						naviki.util.user.setUsername(data.username);
						naviki.util.user.setUserId(data.feUserId);
						_this.showMenuBtn();
					} else {
						_this.showLoginBtn();
					}
					$(window).trigger("naviki_loginSuccess");

					// when user has successfully changed password, it comes to redirect page and this point
					// user is logged in now and tokens are set
					// in this case, wer must manually redirect to naviki start page
					if (window.location.pathname.indexOf("/naviki/single-pages/loading/mobile.html") != -1) {
						document.location.replace(location.origin);
					}
				},
				beforeSend: function() {
					_this.clear();
				},
				complete: function() {
				},
				error: function(err) {
					_this.showLoginBtn();
				}
			});
		},
		
		showLoginBtn: function() {
			this.clear();
			var _this = this;
			$("#header-dropdown-container").fadeOut("slow",function(){
				$("#header-login-container").fadeIn("slow");
				$("#header-register-container").fadeIn("slow");
			});
		},
		
		showMenuBtn: function(loadItems) {
			$("#header-register-container").fadeOut("slow");
			
			$("#header-login-container").fadeOut("slow",function() {
				$("#header-username").text(naviki.util.user.getUsername());
				$("#header-dropdown-container").fadeIn( "slow" );
			});
			
			var _this = this;
			$("#header-dropdown-btn").one("click",function(){
				_this.loadMenu();
			});
		},
		
		loadMenu: function() {
			
			var _this = this;	
			var params = "?eID=controllerDispatcher&request[format]=json&request[controller]=FeUser&request[action]=feMenu";
			
			$.ajax({
				url: window.location.pathname + encodeURI(params),
				type: "GET",
				cache: false,
				dataType : "json",
				contentType: 'application/json; charset=utf-8',
			    processData: false,
				success : function(data) {
					if (data.status) {						
						$("#header-dropdown-menu").html(data.menuItems);
						$("#header-dropdown-container ul li:last-child").one("click", function(){
							// logout was clicked
							_this.clear();
						});
					} else {					
						_this.showLoginBtn();
					}
				},
				beforeSend: function() {
					$("#header-caret").css("visibility", "hidden");
					$("#header-loading").addClass("spinning-wheel");
					$("#header-dropdown-menu").css("border-width","0");
					
				},
				complete: function() {
					$("#header-caret").css("visibility", "");
					$("#header-loading").removeClass("spinning-wheel");
					$("#header-dropdown-menu").css("border-width","1px");
				},
				error: function(jqXHR, textStatus, errorThrown) {
					// do not logout if server was too busy
					if (jqXHR != null && jqXHR.status != null && jqXHR.status == 504)
						return;
					_this.showLoginBtn();
				}
			});
		},
		
		clear: function() {
			naviki.util.api.logoutFeUser();
		},
		
		openLoginDialog: function(url) {	
			this.dialog = $.colorbox({
				width: this.dialogWidth, 
				height: this.dialogHeight, 
				scrolling: false,
				iframe: true, 
				href: url,
				onComplete : function() {
					// avoid opaque title bar
					$('#colorbox').css("background", "#ffffff");
					
					var frame = $('#colorbox iframe').get(0);
					$(frame).load(function(e) {
						frame.contentWindow.postMessage({get:"height"}, "*");
						frame.contentWindow.postMessage({get:"search"}, "*");
					});
				} 
			});
		}
	};
	
	// A really lightweight plugin wrapper around the constructor, 
	// preventing against multiple instantiations and allowing any
	// public function (ie. a function whose name doesn't start
	// with an underscore) to be called via the jQuery plugin,
	// e.g. $(element).defaultPluginName('functionName', arg1, arg2)
	$.fn[pluginName] = function(options) {
		var args = arguments;
		if (options === undefined || typeof options === 'object') {
			return this.each(function() {
				if (!$.data(this, 'plugin_' + pluginName)) {
					$.data(this, 'plugin_' + pluginName, new Plugin(this, options));
				}
			});
		} else if (typeof options === 'string' && options[0] !== '_'
				&& options !== 'init') {
			return this.each(function() {
				var instance = $.data(this, 'plugin_' + pluginName);
				if (instance instanceof Plugin && typeof instance[options] === 'function') {
					instance[options].apply(instance, Array.prototype.slice .call(args, 1));
				}
			});
		}
	};

})(jQuery, window, document);

/*!
	Colorbox 1.6.4
	license: MIT
	http://www.jacklmoore.com/colorbox
*/
(function(t,e,i){function n(i,n,o){var r=e.createElement(i);return n&&(r.id=Z+n),o&&(r.style.cssText=o),t(r)}function o(){return i.innerHeight?i.innerHeight:t(i).height()}function r(e,i){i!==Object(i)&&(i={}),this.cache={},this.el=e,this.value=function(e){var n;return void 0===this.cache[e]&&(n=t(this.el).attr("data-cbox-"+e),void 0!==n?this.cache[e]=n:void 0!==i[e]?this.cache[e]=i[e]:void 0!==X[e]&&(this.cache[e]=X[e])),this.cache[e]},this.get=function(e){var i=this.value(e);return t.isFunction(i)?i.call(this.el,this):i}}function h(t){var e=W.length,i=(A+t)%e;return 0>i?e+i:i}function a(t,e){return Math.round((/%/.test(t)?("x"===e?E.width():o())/100:1)*parseInt(t,10))}function s(t,e){return t.get("photo")||t.get("photoRegex").test(e)}function l(t,e){return t.get("retinaUrl")&&i.devicePixelRatio>1?e.replace(t.get("photoRegex"),t.get("retinaSuffix")):e}function d(t){"contains"in x[0]&&!x[0].contains(t.target)&&t.target!==v[0]&&(t.stopPropagation(),x.focus())}function c(t){c.str!==t&&(x.add(v).removeClass(c.str).addClass(t),c.str=t)}function g(e){A=0,e&&e!==!1&&"nofollow"!==e?(W=t("."+te).filter(function(){var i=t.data(this,Y),n=new r(this,i);return n.get("rel")===e}),A=W.index(_.el),-1===A&&(W=W.add(_.el),A=W.length-1)):W=t(_.el)}function u(i){t(e).trigger(i),ae.triggerHandler(i)}function f(i){var o;if(!G){if(o=t(i).data(Y),_=new r(i,o),g(_.get("rel")),!U){U=$=!0,c(_.get("className")),x.css({visibility:"hidden",display:"block",opacity:""}),I=n(se,"LoadedContent","width:0; height:0; overflow:hidden; visibility:hidden"),b.css({width:"",height:""}).append(I),j=T.height()+k.height()+b.outerHeight(!0)-b.height(),D=C.width()+H.width()+b.outerWidth(!0)-b.width(),N=I.outerHeight(!0),z=I.outerWidth(!0);var h=a(_.get("initialWidth"),"x"),s=a(_.get("initialHeight"),"y"),l=_.get("maxWidth"),f=_.get("maxHeight");_.w=Math.max((l!==!1?Math.min(h,a(l,"x")):h)-z-D,0),_.h=Math.max((f!==!1?Math.min(s,a(f,"y")):s)-N-j,0),I.css({width:"",height:_.h}),J.position(),u(ee),_.get("onOpen"),O.add(F).hide(),x.focus(),_.get("trapFocus")&&e.addEventListener&&(e.addEventListener("focus",d,!0),ae.one(re,function(){e.removeEventListener("focus",d,!0)})),_.get("returnFocus")&&ae.one(re,function(){t(_.el).focus()})}var p=parseFloat(_.get("opacity"));v.css({opacity:p===p?p:"",cursor:_.get("overlayClose")?"pointer":"",visibility:"visible"}).show(),_.get("closeButton")?B.html(_.get("close")).appendTo(b):B.appendTo("<div/>"),w()}}function p(){x||(V=!1,E=t(i),x=n(se).attr({id:Y,"class":t.support.opacity===!1?Z+"IE":"",role:"dialog",tabindex:"-1"}).hide(),v=n(se,"Overlay").hide(),L=t([n(se,"LoadingOverlay")[0],n(se,"LoadingGraphic")[0]]),y=n(se,"Wrapper"),b=n(se,"Content").append(F=n(se,"Title"),R=n(se,"Current"),P=t('<button type="button"/>').attr({id:Z+"Previous"}),K=t('<button type="button"/>').attr({id:Z+"Next"}),S=t('<button type="button"/>').attr({id:Z+"Slideshow"}),L),B=t('<button type="button"/>').attr({id:Z+"Close"}),y.append(n(se).append(n(se,"TopLeft"),T=n(se,"TopCenter"),n(se,"TopRight")),n(se,!1,"clear:left").append(C=n(se,"MiddleLeft"),b,H=n(se,"MiddleRight")),n(se,!1,"clear:left").append(n(se,"BottomLeft"),k=n(se,"BottomCenter"),n(se,"BottomRight"))).find("div div").css({"float":"left"}),M=n(se,!1,"position:absolute; width:9999px; visibility:hidden; display:none; max-width:none;"),O=K.add(P).add(R).add(S)),e.body&&!x.parent().length&&t(e.body).append(v,x.append(y,M))}function m(){function i(t){t.which>1||t.shiftKey||t.altKey||t.metaKey||t.ctrlKey||(t.preventDefault(),f(this))}return x?(V||(V=!0,K.click(function(){J.next()}),P.click(function(){J.prev()}),B.click(function(){J.close()}),v.click(function(){_.get("overlayClose")&&J.close()}),t(e).bind("keydown."+Z,function(t){var e=t.keyCode;U&&_.get("escKey")&&27===e&&(t.preventDefault(),J.close()),U&&_.get("arrowKey")&&W[1]&&!t.altKey&&(37===e?(t.preventDefault(),P.click()):39===e&&(t.preventDefault(),K.click()))}),t.isFunction(t.fn.on)?t(e).on("click."+Z,"."+te,i):t("."+te).live("click."+Z,i)),!0):!1}function w(){var e,o,r,h=J.prep,d=++le;if($=!0,q=!1,u(he),u(ie),_.get("onLoad"),_.h=_.get("height")?a(_.get("height"),"y")-N-j:_.get("innerHeight")&&a(_.get("innerHeight"),"y"),_.w=_.get("width")?a(_.get("width"),"x")-z-D:_.get("innerWidth")&&a(_.get("innerWidth"),"x"),_.mw=_.w,_.mh=_.h,_.get("maxWidth")&&(_.mw=a(_.get("maxWidth"),"x")-z-D,_.mw=_.w&&_.w<_.mw?_.w:_.mw),_.get("maxHeight")&&(_.mh=a(_.get("maxHeight"),"y")-N-j,_.mh=_.h&&_.h<_.mh?_.h:_.mh),e=_.get("href"),Q=setTimeout(function(){L.show()},100),_.get("inline")){var c=t(e).eq(0);r=t("<div>").hide().insertBefore(c),ae.one(he,function(){r.replaceWith(c)}),h(c)}else _.get("iframe")?h(" "):_.get("html")?h(_.get("html")):s(_,e)?(e=l(_,e),q=_.get("createImg"),t(q).addClass(Z+"Photo").bind("error."+Z,function(){h(n(se,"Error").html(_.get("imgError")))}).one("load",function(){d===le&&setTimeout(function(){var e;_.get("retinaImage")&&i.devicePixelRatio>1&&(q.height=q.height/i.devicePixelRatio,q.width=q.width/i.devicePixelRatio),_.get("scalePhotos")&&(o=function(){q.height-=q.height*e,q.width-=q.width*e},_.mw&&q.width>_.mw&&(e=(q.width-_.mw)/q.width,o()),_.mh&&q.height>_.mh&&(e=(q.height-_.mh)/q.height,o())),_.h&&(q.style.marginTop=Math.max(_.mh-q.height,0)/2+"px"),W[1]&&(_.get("loop")||W[A+1])&&(q.style.cursor="pointer",t(q).bind("click."+Z,function(){J.next()})),q.style.width=q.width+"px",q.style.height=q.height+"px",h(q)},1)}),q.src=e):e&&M.load(e,_.get("data"),function(e,i){d===le&&h("error"===i?n(se,"Error").html(_.get("xhrError")):t(this).contents())})}var v,x,y,b,T,C,H,k,W,E,I,M,L,F,R,S,K,P,B,O,_,j,D,N,z,A,q,U,$,G,Q,J,V,X={html:!1,photo:!1,iframe:!1,inline:!1,transition:"elastic",speed:300,fadeOut:300,width:!1,initialWidth:"600",innerWidth:!1,maxWidth:!1,height:!1,initialHeight:"450",innerHeight:!1,maxHeight:!1,scalePhotos:!0,scrolling:!0,opacity:.9,preloading:!0,className:!1,overlayClose:!0,escKey:!0,arrowKey:!0,top:!1,bottom:!1,left:!1,right:!1,fixed:!1,data:void 0,closeButton:!0,fastIframe:!0,open:!1,reposition:!0,loop:!0,slideshow:!1,slideshowAuto:!0,slideshowSpeed:2500,slideshowStart:"start slideshow",slideshowStop:"stop slideshow",photoRegex:/\.(gif|png|jp(e|g|eg)|bmp|ico|webp|jxr|svg)((#|\?).*)?$/i,retinaImage:!1,retinaUrl:!1,retinaSuffix:"@2x.$1",current:"image {current} of {total}",previous:"previous",next:"next",close:"close",xhrError:"This content failed to load.",imgError:"This image failed to load.",returnFocus:!0,trapFocus:!0,onOpen:!1,onLoad:!1,onComplete:!1,onCleanup:!1,onClosed:!1,rel:function(){return this.rel},href:function(){return t(this).attr("href")},title:function(){return this.title},createImg:function(){var e=new Image,i=t(this).data("cbox-img-attrs");return"object"==typeof i&&t.each(i,function(t,i){e[t]=i}),e},createIframe:function(){var i=e.createElement("iframe"),n=t(this).data("cbox-iframe-attrs");return"object"==typeof n&&t.each(n,function(t,e){i[t]=e}),"frameBorder"in i&&(i.frameBorder=0),"allowTransparency"in i&&(i.allowTransparency="true"),i.name=(new Date).getTime(),i.allowFullscreen=!0,i}},Y="colorbox",Z="cbox",te=Z+"Element",ee=Z+"_open",ie=Z+"_load",ne=Z+"_complete",oe=Z+"_cleanup",re=Z+"_closed",he=Z+"_purge",ae=t("<a/>"),se="div",le=0,de={},ce=function(){function t(){clearTimeout(h)}function e(){(_.get("loop")||W[A+1])&&(t(),h=setTimeout(J.next,_.get("slideshowSpeed")))}function i(){S.html(_.get("slideshowStop")).unbind(s).one(s,n),ae.bind(ne,e).bind(ie,t),x.removeClass(a+"off").addClass(a+"on")}function n(){t(),ae.unbind(ne,e).unbind(ie,t),S.html(_.get("slideshowStart")).unbind(s).one(s,function(){J.next(),i()}),x.removeClass(a+"on").addClass(a+"off")}function o(){r=!1,S.hide(),t(),ae.unbind(ne,e).unbind(ie,t),x.removeClass(a+"off "+a+"on")}var r,h,a=Z+"Slideshow_",s="click."+Z;return function(){r?_.get("slideshow")||(ae.unbind(oe,o),o()):_.get("slideshow")&&W[1]&&(r=!0,ae.one(oe,o),_.get("slideshowAuto")?i():n(),S.show())}}();t[Y]||(t(p),J=t.fn[Y]=t[Y]=function(e,i){var n,o=this;return e=e||{},t.isFunction(o)&&(o=t("<a/>"),e.open=!0),o[0]?(p(),m()&&(i&&(e.onComplete=i),o.each(function(){var i=t.data(this,Y)||{};t.data(this,Y,t.extend(i,e))}).addClass(te),n=new r(o[0],e),n.get("open")&&f(o[0])),o):o},J.position=function(e,i){function n(){T[0].style.width=k[0].style.width=b[0].style.width=parseInt(x[0].style.width,10)-D+"px",b[0].style.height=C[0].style.height=H[0].style.height=parseInt(x[0].style.height,10)-j+"px"}var r,h,s,l=0,d=0,c=x.offset();if(E.unbind("resize."+Z),x.css({top:-9e4,left:-9e4}),h=E.scrollTop(),s=E.scrollLeft(),_.get("fixed")?(c.top-=h,c.left-=s,x.css({position:"fixed"})):(l=h,d=s,x.css({position:"absolute"})),d+=_.get("right")!==!1?Math.max(E.width()-_.w-z-D-a(_.get("right"),"x"),0):_.get("left")!==!1?a(_.get("left"),"x"):Math.round(Math.max(E.width()-_.w-z-D,0)/2),l+=_.get("bottom")!==!1?Math.max(o()-_.h-N-j-a(_.get("bottom"),"y"),0):_.get("top")!==!1?a(_.get("top"),"y"):Math.round(Math.max(o()-_.h-N-j,0)/2),x.css({top:c.top,left:c.left,visibility:"visible"}),y[0].style.width=y[0].style.height="9999px",r={width:_.w+z+D,height:_.h+N+j,top:l,left:d},e){var g=0;t.each(r,function(t){return r[t]!==de[t]?(g=e,void 0):void 0}),e=g}de=r,e||x.css(r),x.dequeue().animate(r,{duration:e||0,complete:function(){n(),$=!1,y[0].style.width=_.w+z+D+"px",y[0].style.height=_.h+N+j+"px",_.get("reposition")&&setTimeout(function(){E.bind("resize."+Z,J.position)},1),t.isFunction(i)&&i()},step:n})},J.resize=function(t){var e;U&&(t=t||{},t.width&&(_.w=a(t.width,"x")-z-D),t.innerWidth&&(_.w=a(t.innerWidth,"x")),I.css({width:_.w}),t.height&&(_.h=a(t.height,"y")-N-j),t.innerHeight&&(_.h=a(t.innerHeight,"y")),t.innerHeight||t.height||(e=I.scrollTop(),I.css({height:"auto"}),_.h=I.height()),I.css({height:_.h}),e&&I.scrollTop(e),J.position("none"===_.get("transition")?0:_.get("speed")))},J.prep=function(i){function o(){return _.w=_.w||I.width(),_.w=_.mw&&_.mw<_.w?_.mw:_.w,_.w}function a(){return _.h=_.h||I.height(),_.h=_.mh&&_.mh<_.h?_.mh:_.h,_.h}if(U){var d,g="none"===_.get("transition")?0:_.get("speed");I.remove(),I=n(se,"LoadedContent").append(i),I.hide().appendTo(M.show()).css({width:o(),overflow:_.get("scrolling")?"auto":"hidden"}).css({height:a()}).prependTo(b),M.hide(),t(q).css({"float":"none"}),c(_.get("className")),d=function(){function i(){t.support.opacity===!1&&x[0].style.removeAttribute("filter")}var n,o,a=W.length;U&&(o=function(){clearTimeout(Q),L.hide(),u(ne),_.get("onComplete")},F.html(_.get("title")).show(),I.show(),a>1?("string"==typeof _.get("current")&&R.html(_.get("current").replace("{current}",A+1).replace("{total}",a)).show(),K[_.get("loop")||a-1>A?"show":"hide"]().html(_.get("next")),P[_.get("loop")||A?"show":"hide"]().html(_.get("previous")),ce(),_.get("preloading")&&t.each([h(-1),h(1)],function(){var i,n=W[this],o=new r(n,t.data(n,Y)),h=o.get("href");h&&s(o,h)&&(h=l(o,h),i=e.createElement("img"),i.src=h)})):O.hide(),_.get("iframe")?(n=_.get("createIframe"),_.get("scrolling")||(n.scrolling="no"),t(n).attr({src:_.get("href"),"class":Z+"Iframe"}).one("load",o).appendTo(I),ae.one(he,function(){n.src="//about:blank"}),_.get("fastIframe")&&t(n).trigger("load")):o(),"fade"===_.get("transition")?x.fadeTo(g,1,i):i())},"fade"===_.get("transition")?x.fadeTo(g,0,function(){J.position(0,d)}):J.position(g,d)}},J.next=function(){!$&&W[1]&&(_.get("loop")||W[A+1])&&(A=h(1),f(W[A]))},J.prev=function(){!$&&W[1]&&(_.get("loop")||A)&&(A=h(-1),f(W[A]))},J.close=function(){U&&!G&&(G=!0,U=!1,u(oe),_.get("onCleanup"),E.unbind("."+Z),v.fadeTo(_.get("fadeOut")||0,0),x.stop().fadeTo(_.get("fadeOut")||0,0,function(){x.hide(),v.hide(),u(he),I.remove(),setTimeout(function(){G=!1,u(re),_.get("onClosed")},1)}))},J.remove=function(){x&&(x.stop(),t[Y].close(),x.stop(!1,!0).remove(),v.remove(),G=!1,x=null,t("."+te).removeData(Y).removeClass(te),t(e).unbind("click."+Z).unbind("keydown."+Z))},J.element=function(){return t(_.el)},J.settings=X)})(jQuery,document,window);
/**
 * Call function if user clicked on naviki logo. Changes the window location to
 * the start of the landingpage.
 * 
 */
;(function($) {
	
	$.fn.navikiFullPage = function() {
		
		/*
		 * Setup bootstrap column definitions for content elements
		 */
		$('.csc-textpic.csc-textpic-intext-right .csc-textpic-imagewrap').addClass('col-lg-6');
		$('.csc-textpic.csc-textpic-intext-right .csc-textpic-text').addClass('col-lg-5 col-lg-offset-1');
		$('.csc-textpic.csc-textpic-intext-left .csc-textpic-imagewrap').addClass('col-lg-5 col-lg-offset-1');
		$('.csc-textpic.csc-textpic-intext-left .csc-textpic-text').addClass('col-lg-5');
		$('.csc-textpic.csc-textpic-intext-right-nowrap .csc-textpic-imagewrap').addClass('col-lg-6');
		$('.csc-textpic.csc-textpic-intext-right-nowrap .csc-textpic-text').addClass('col-lg-5 col-lg-offset-1');
		$('.csc-textpic.csc-textpic-intext-left-nowrap .csc-textpic-imagewrap').addClass('col-lg-5 col-lg-offset-1');
		$('.csc-textpic.csc-textpic-intext-left-nowrap .csc-textpic-text').addClass('col-lg-5');
	
		/*
		 * Setup full-page classes, only first level of section items
		 */
		const sectionItems = $('#fullpage > .section');
		const length = sectionItems.length;
		sectionItems.each(function(index) {		
			var container = $(this).find(".container").first();
			
			if ($(this).hasClass("wrap")) {
				$(this).addClass("section-table");	
				container.wrap( "<div class='section-table-cell'></div>" );
			}
			
			if (index < length - 1) {
				var arrow = "<div class='arrow-down-container'><span data-next='"+(index+1)+"' class='icon-arrow-down-fullscreen'></span></div>";
				container.append(arrow);
			}
			
			if (index == 0) {
				if($(".fixedHeader").length > 0) {
					$(this).addClass("first-section");
				}
			}
		});
		
		/*
		 * Scroll effects
		 */
		var transitionListener = false;
		var next, destination, next, avail, scroll, deltaScroll;
		$(".icon-arrow-down-fullscreen").bind('click',function(event){
			
			next = $(this).data("next");
			
			destination = 0;
			if ($(".fixedHeader").length > 0) {
	//			destination = - $("#fixedHeader").outerHeight();
			}
			
			$('#fullpage .section').each(function(index) {
				if (index < next) {
					destination += $(this).outerHeight();
				}
			});
			
			if (typeof document.body.style.transitionProperty === 'string') {

			    // CSS3 transitions are supported. Yay!
				avail = $(document).height() - $(window).height();

				if (avail > 0) {
					scroll = destination;
          
					if (scroll > avail) {
						scroll = avail;
					}
				} else {
					scroll = 0;
				}

				deltaScroll = $(window).scrollTop() - scroll;

				// if we don't have to scroll because we're already at the right scrolling level,
				if (!deltaScroll) {
					return; // do nothing
				}
				
				event.preventDefault();
				
			    // translate3d forces hardware acceleration, second param is 'y'
			    var translate3d = 'translate3d(0, ' + deltaScroll + 'px, 0)';
			    $("#fullpage").css({
                	'transition' : ".7s",
                    '-webkit-transform': translate3d,
                    '-moz-transform': translate3d,
                    '-ms-transform':translate3d,
                    'transform': translate3d
                }); 
			    
			    // revert back to native scrollTop
			    $("#fullpage").bind('transitionend webkitTransitionEnd msTransitionEnd oTransitionEnd', function(event) {
			    	$(document).scrollTop(destination);   	
			    	$(this).removeAttr("style");
			    	$(this).unbind(event);
			    });
              
			} else {
				
				try {
					$(document).stop(true, true) // stop potential other jQuery animation (assuming we're the only one doing it)
					$(document).animate({
				        scrollTop: destination
				    }, 1000);
				} catch (e) {
					$(document).scrollTop(destination);   
				}
			}
		});
		
		$(window).on("scroll",function() {
			clearTimeout($.data(this, 'scrollTimer'));
		    $.data(this, 'scrollTimer', setTimeout(function() {
		    	var offset = 0;
				if ($(".fixedHeader").length > 0) {
					offset += $("#fixedHeader").outerHeight();
				}
				$(".icon-arrow-down-fullscreen").each(function(index){					
					if ($(window).scrollTop() + offset > $(this).offset().top) {
						$(this).css("visibility","hidden");
					} else {
						$(this).css("visibility","visible");
					}
				});
		    }, 250));
		    
			
		});
		
		
		/*
		 * Add break for four column layout.
		 * This break is visible under 1199px.
		 */
		$('.csc-textpic-imagerow').each(function(index) {
			var n = $(this).find(".csc-textpic-imagecolumn" ).length;
			if (n == 4) {
				var e = $(this).find(".csc-textpic-imagecolumn:eq( 1 )")
				$( "<div class='four-column-break'></div>" ).insertAfter(e);
			}
		});

		/*
		 * toggle the background color between green and white
		 */
		$('#fullpage >.section').each(function(index) {
			if (index % 2 == 0) {
				$(this).css("background-color","#edeeea")
			}
		});
		
		/*
		 * pick images from content element and set the image to the background of
		 * the fullpage section
		 */
		var bgImgs = $('#fullpage .section .csc-default.csc-img-bg img, #fullpage .section .csc-frame-default.csc-img-bg img');
		$.each(bgImgs, function(i, bgImg) {
			// get the image-url
			var imageUrl = 'url(' + bgImg.src + ')';
	
			// traverse along all parents and pick the section element
			$(bgImg).parents('.section').css({
				'background-image' : imageUrl,
				'background-repeat': 'no-repeat'
			});
			
			// set full height for section with background image
			$(bgImg).parents('.section').addClass("full-height");
		});
		
		/*
		 * pick content element with layout-5 and set 
		 * vertical-align = top
		 */
		var items = $('#fullpage .section .csc-default.layout-5, #fullpage .section .csc-frame-default.layout-5');
		$.each(items, function(i, item) {
			// traverse along all parents and pick the section element
			$(item).parents('.section-table-cell').css({
				'vertical-align' : 'top'
			});
		});
		
		/*
		 * for single section, we set the height to full
		 */
		if ($('#fullpage .section').length == 1) {
			$('#fullpage .section').addClass("full-height");
		};
		
		/*
		 * set all sections with the class full-height to window height
		 */
		$(".full-height").css("height",$( window ).height());
		$( window ).resize(function() {
			$(".full-height").css("height",$( window ).height());
		});
	};
	
	$.fn.navikiFullPage();
	
})( jQuery);