PageSourceSearch

https://crm.mtsz.org/js/mlp/dynamicpage.js

js mtsz.org collected 2026-10-02 06:29:27 UTC 125,219 bytes, 3,280 lines download raw bytes

1/*
2 * DynamicPage MobilePage class
3 * Created by: nucleon - 2016-01-08
4 */
5if(![].forEach) {
6	Array.prototype.forEach = function(callback, thisArg) {
7		for(var i = 0; i < this.length; i++)
8			callback.call(thisArg, this[i], i, this);
9	};
10}
11jQuery.fn.outer = function() {
12	return $($('<div></div>').html(this.clone())).html();
13};
14
15function DynamicPage(properties) {
16	this.initialized = false;
17	this.initialGetContent = true;
18	var that = this;
19	var request = null;
20	var $categoryFilter = null;
21	var $tagFilter = null;
22	var $favoriteFilter = null;
23	var $difficultyFilter = null;
24	var $datasourceFilter = null;
25	var $lengthFilter = null;
26    var $priceFilter = null;
27    var $ratingFilter = null;
28	var $visitedFilter = null;
29	var $openFilter = null;
30	var $markerFilter = null;
31	var $monthFilter = null;
32	var $hiddenFilter = null;
33	var $textFilter = null;
34	var $rangeFilter = null;
35	var $clientGroupFilter = null;
36	var $geofilterBar = null;
37	var $searchForm = null;
38	var $calendar = null;
39	var $container = null;
40	var $viewSwitch = null;
41	var limitItems = false;
42	var minChars = 0;
43	var viewSwitch = true;
44	var layoutVersion = 2;
45	var ignoreViewMode = false;
46	var showElevationChart = true;
47	var dayClickCallback = function(date) { return false; };
48	var contentLoadedCallback = function(content) { return false; };
49	var initializedCallback = function(content) { return false; };
50	var $page = null;
51	var mlpObject = null;
52	var thumbnailGeneratorPath = '/image/thumb';
53	var language = 'en';
54	var initialData = null;
55	var geoFilter = false;
56	var alwaysBackToListView = false;
57	var filterInSidebar = true;
58	var infiniteScroll = true;
59    var infiniteScrollNumber = false;
60    var displayMode = 'feed';
61	var resultMode = 'list';
62	var pageID = '';
63	var defaultState = {};
64	var defaultLocation = {
65		latitude: null,
66		longitude: null
67	}
68
69	var map = {
70		obj: null,
71		mergeMarkers: 'off',
72		markerAnimation: 2, //google.maps.Animation.DROP
73		travelMode: null,
74		typeID: null,
75		type: '',
76		directionsDisplay: null,
77		directionsService: null,
78		latLngBounds: null,
79		markers: [],
80		customMarkers: [],
81		paths: [],
82		markerClusters: {},
83		currentLocation: null,
84		currentMarker: null,
85		currentInfoWindow: null,
86		destination: null,
87		locationRequestDone: false,
88		$directionInfo: null,
89		$directionDisplayButton: null,
90		directionDisplayActive: false,
91		enableCustomPoints: false,
92        disableDirectionsToHere: false,
93        tempMarker: null,
94		geocoder: null,
95		minZoom: null,
96		maxZoom: null,
97		defaultZoom: null,
98		centerLat: null,
99		centerLng: null,
100		pointViewMode: false,
101		$elevationChartDisplay: null,
102		elevationChartMarker: null,
103		disableMapAutoResize: false,
104		forceMapFullscreen: false,
105		arcgisMapServer: null,
106		defaultPosition: true
107	};
108	if (typeof google === 'object' && typeof google.maps === 'object'){
109		map.travelMode = google.maps.TravelMode.DRIVING;
110		map.typeID = google.maps.MapTypeId.TERRAIN;
111		map.directionsDisplay = new google.maps.DirectionsRenderer();
112		map.directionsService = new google.maps.DirectionsService();
113		map.currentInfoWindow = new google.maps.InfoWindow();
114	}
115
116	var currentState = {
117		qr: '',
118		card: '',
119		uuid: '',
120		start: '',
121		end: '',
122		createdStart: '',
123		createdEnd: '',
124		favorite: '',
125		hidden: '',
126		visited: '',
127		open: '',
128		marker: '',
129		difficulty: '',
130		related: '',
131        datasource: '',
132		distance: '',
133        price: '',
134        rating: '',
135		clientGroup: '',
136		month: '',
137		range: '',
138		current_page: 0,
139		tag: '',
140		category: '',
141		item: '',
142        instance: '',
143		search: '',
144		dataStoreMarkerId: '',
145		dataStoreId: '',
146		viewMode: 'auto',
147		attributes: '',
148		sort_attr: '',
149		sort_direction: true,
150		coords: {
151			latitude: null, longitude: null
152		}
153	};
154
155	setConfig(properties);
156
157	this.init = function(mlpObject, $pageObj) {
158		initDynamicPage(mlpObject, $pageObj);
159		if (displayMode == "map"){
160			initMapViewControls();
161		}
162	};
163
164	this.setDayClickCallback = function(callback) {
165		dayClickCallback = callback;
166	}
167
168	this.bounceMarkerById = function(id) {
169		$.each(map.markers, function(i, marker) {
170			if (marker.data !== undefined) {
171				if (marker.data.id == id) {
172                    marker.data.zindex = marker.getZIndex();
173                    marker.setZIndex(2000)
174                    marker.getMap().panTo(marker.getPosition());
175                    marker.setAnimation(google.maps.Animation.BOUNCE);
176                    setTimeout(function () {
177                        marker.setAnimation(null);
178                    }, 750);
179                } else {
180					if (marker.data.zindex) marker.setZIndex(marker.data.zindex);
181				}
182			}
183		});
184	}
185    this.bouncePathById = function(id,opt) {
186        $.each(map.paths, function(i, marker) {
187            if (marker.data !== undefined) {
188                if (marker.data.id == id) {
189                    marker.setOptions(opt);
190                }
191            }
192        });
193    }
194    this.setPathOptions = function(outopt,overopt) {
195        $.each(map.paths, function(i, marker) {
196            if (marker.data !== undefined) {
197                marker.setOptions(outopt);
198
199                google.maps.event.addListener(marker, 'mouseover', function () {
200                    this.setOptions(overopt);
201                });
202                google.maps.event.addListener(marker, 'mouseout', function () {
203                    this.setOptions(outopt);
204                });
205            }
206
207        });
208
209
210    }
211	this.hashChanged = function(){
212        if (location.hash.indexOf('?') > -1) {
213			getContents({});
214		} else {
215			if (currentState.item) {
216				currentState.item = '';
217				getContents({}, true);
218			} else {
219				getContents({});
220			}
221		}
222		var $p = this.getPage();
223		var data = getQueryData();
224		if ($p.data('sync')) {
225            $('div.page-block[data-datasource-id="'+$p.data('datasource-id')+'"],div.page[data-datasource-id="'+$p.data('datasource-id')+'"]').each(function(i,e){
226                if ($(e).data('sync') && ($(e).attr('id')!=$p.attr('id'))) {
227                    if ($(e).data('dynamic')!==undefined) $(e).data('dynamic').setData(data, true);
228                }
229            });
230		}
231	};
232
233	this.getCurrentState = function(){
234		return getQueryData();
235	}
236
237	this.getPage = function() {
238		return getPageObj();
239	}
240	this.fitMapBounds = function() {
241		map.obj.fitBounds(map.latLngBounds);
242	}
243	this.viewModeChanged = function(mode){
244		if (filterInSidebar && (displayMode == "text" || displayMode == "calendar" || displayMode == "map")){
245			var $filter = $page.find(".result-filter");
246			if ($filter.length) {
247				if (mode == "desktop") {
248					if (!$page.is('.fullscreen')) {
249						var $title = $('<h4 class="section-title"><i class="fa fa-filter fa-fw""></i> ' + mlpLanguage.filter + '</h4>');
250						if ($filter.is(":hidden")) $title.hide();
251						$page.find('.sidebar-col').prepend($filter).prepend($title);
252					}
253				} else {
254					$filter.prev().remove();
255					$page.find('.map-tools').prepend($page.find(".result-filter"));
256				}
257			}
258		}
259	};
260
261	this.onDisplay = function(){
262		if (!$container.children().length) {
263			getContents({}, that.initialGetContent, true);
264		} else {
265			if (alwaysBackToListView){
266				var hash = cloneState();
267				hash.item = '';
268				setLocationHash(hash);
269				that.hashChanged();
270			} else {
271				var query = getQueryStringArray();
272				if (query.item !== undefined && query.item != ''){
273					currentState.item = query.item;
274					getContents({}, that.initialGetContent, true);
275				} else if (query.item !== undefined) {
276					currentState.item = null;
277					getContents({}, that.initialGetContent, true);
278				} else {
279					setLocationHash(currentState);
280				}
281			}
282		}
283		if (displayMode == "map"){
284			initMapViewControls();
285		}
286	};
287
288	this.isInited = function(){
289		return that.initialized;
290	};
291
292	this.setInitializedCallback = function (callback) {
293		initializedCallback = callback;
294	};
295
296	this.setContentLoadedCallback = function (callback) {
297		contentLoadedCallback = callback;
298	};
299
300    this.setData = function(data, without_hash) {
301
302		if (without_hash===undefined || !without_hash) {
303            setLocationHash(data);
304		} else {
305            getContents(data);
306		}
307    };
308    this.refresh = function() {
309		getContents({}, true);
310    };
311    this.hasLocation = function() {
312    	if (currentState.coords.latitude) return true;
313    	else return false;
314	}
315	this.getLocation = function(callback) {
316        determineLocation(callback);
317	}
318    function getPageObj() {
319    	return $page;
320	}
321
322	function setConfig(properties){
323		if (properties.initialGetContent !== undefined){
324			that.initialGetContent = properties.initialGetContent;
325		}
326		if (properties.map !== undefined){
327			map = $.extend({}, map, properties.map);
328		}
329		if (properties.viewMode !== undefined){
330			if (displayMode === 'feed' && properties.viewMode == 'auto'){
331				currentState.viewMode = $(window).width() < 992 ? 'table' : 'cards';
332			} else {
333				currentState.viewMode = properties.viewMode;
334			}
335		}
336		if (properties.defaultMonth !== undefined && properties.defaultMonth !== null) {
337			currentState.month = properties.defaultMonth;
338		}
339		if (properties.language !== undefined){
340			language = properties.language;
341		}
342		if (properties.initialData !== undefined){
343			initialData = properties.initialData;
344		}
345		if (properties.geoFilter !== undefined){
346			geoFilter = properties.geoFilter != "off" && properties.geoFilter != "false";
347		}
348		if (properties.displayMode !== undefined){
349			displayMode = properties.displayMode;
350		}
351        if (properties.limitItems !== undefined){
352            limitItems = properties.limitItems;
353        }
354        if (properties.minChars !== undefined){
355            minChars = properties.minChars;
356        }
357        if (properties.layoutVersion !== undefined){
358            layoutVersion = properties.layoutVersion;
359            viewSwitch = layoutVersion == 2;
360        }
361		if (properties.pageID !== undefined){
362			pageID = properties.pageID;
363		}
364		if (properties.resultMode !== undefined){
365			resultMode = properties.resultMode;
366		}
367		if (properties.alwaysBackToListView !== undefined){
368			alwaysBackToListView = properties.alwaysBackToListView;
369		}
370		if (properties.infiniteScroll !== undefined){
371			infiniteScroll = properties.infiniteScroll;
372		}
373		if(properties.infiniteScroll !== undefined){
374            infiniteScrollNumber = properties.infiniteScrollNumber;
375        }
376		if (properties.thumbnailGeneratorPath !== undefined){
377			thumbnailGeneratorPath = properties.thumbnailGeneratorPath;
378		}
379		if (properties.enableCustomPoints !== undefined){
380			map.enableCustomPoints = properties.enableCustomPoints;
381		}
382        if (properties.disableDirectionsToHere !== undefined){
383            map.disableDirectionsToHere = properties.disableDirectionsToHere;
384        }
385		if (properties.disableMapAutoResize !== undefined){
386			map.disableMapAutoResize = properties.disableMapAutoResize;
387		}
388		if (properties.forceMapFullscreen !== undefined){
389			map.forceMapFullscreen = properties.forceMapFullscreen;
390		}
391		if (properties.filterInSidebar !== undefined){
392			filterInSidebar = properties.filterInSidebar;
393		}
394		if (properties.showElevationChart !== undefined){
395            showElevationChart = properties.showElevationChart;
396		}
397		if (properties.defaultLocation !== undefined){
398			defaultLocation = properties.defaultLocation;
399		}
400		if (properties.ignoreViewMode !== undefined) {
401			ignoreViewMode = properties.ignoreViewMode;
402		}
403		if (properties.arcgisMapServer){
404			map.arcgisMapServer = properties.arcgisMapServer;
405		}
406        if (properties.defaultState){
407			setState(properties.defaultState);
408        }
409		if (properties.initializedCallback){
410			initializedCallback = properties.initializedCallback;
411		} else if (typeof mlpCallbacks !== 'undefined' && mlpCallbacks.initialized) {
412			initializedCallback = mlpCallbacks.initialized;
413		}
414		if (properties.contentLoadedCallback){
415			contentLoadedCallback = properties.contentLoadedCallback;
416		} else if (typeof mlpCallbacks !== 'undefined' && mlpCallbacks.contentLoaded) {
417			contentLoadedCallback = mlpCallbacks.contentLoaded;
418		}
419        $('#block_'+pageID+',#page_'+pageID).data('dynamic', that);
420	}
421
422	function initDynamicPage(mlpObj, $pageObj){
423		mlpObject = mlpObj;
424		$page = $pageObj;
425		if (!pageID || !$page || !$page.length) {
426			console.log("Error");
427			return false;
428		}
429		$categoryFilter = $page.find('.category-filter input, .category-filter select');
430		$tagFilter = $page.find('.tag-filter input, .tag-filter select');
431		$favoriteFilter = $page.find('.favorite-filter select, .favorite-filter input');
432		$visitedFilter = $page.find('.visited-filter select, .visited-filter input');
433		$openFilter = $page.find('.open-filter select, .open-filter input');
434		$markerFilter = $page.find('.marker-filter select, .marker-filter input');
435		$difficultyFilter = $page.find('.difficulty-filter input');
436		$datasourceFilter = $page.find('.datasource-filter select');
437		$lengthFilter = $page.find('.length-filter input');
438		$ratingFilter = $page.find('.rating-filter input');
439		$monthFilter = $page.find('.month-filter select');
440		$hiddenFilter = $page.find('.hidden-filter select');
441		$textFilter = $page.find('.text-filter input');
442		$rangeFilter = $page.find('.range-filter select');
443		$clientGroupFilter = $page.find('.client-group-filter select, .client-group-filter input');
444		$geofilterBar = $page.find('.geofilter');
445		$searchForm = $page.find('.search-form');
446		$container = $page.find(".dynamic-content");
447
448		currentState.card = mlpObject.getCard();
449		currentState.qr = mlpObject.getQr();
450		currentState.uuid = mlpObject.getUuid();
451		currentState.coords = defaultLocation;
452
453		$page.initElements();
454
455		defaultState = cloneState();
456		bindFilterEvents();
457		bindListItemEvents();
458
459		if ($geofilterBar !== null && $geofilterBar.length) {
460			$geofilterBar.find(".btn-change").click(function (e) {
461				e.preventDefault();
462				displayLocationPicker();
463			});
464		}
465		$page.on("click", ".image-overlay a", function(e){
466			//e.stopPropagation();
467		});
468		$searchForm.submit(function(e){
469			e.preventDefault();
470			var $input = $searchForm.find("input[name='search']");
471			if (minChars <= $input.val().length) setLocationHash({search: $input.val()});
472		});
473
474		if (displayMode == "map") {
475			initMap();
476		} else if (displayMode == "text"){
477			initFeed();
478		}
479        that.initialized = true;
480        if ($container.length && $container[0].innerHTML.length && displayMode == "text" && (currentState.coords.latitude === null && currentState.coords.longitude === null)){
481            if (!ignoreViewMode) {
482                var data = getQueryData({}, false);
483                if ($container.find('.cards-view').length && data.viewMode == 'table'){
484					currentState.viewMode = 'cards'
485					getContents({viewMode: 'table'});
486				}
487				if ($container.find('.table-view').length && data.viewMode == 'cards'){
488					currentState.viewMode = 'table'
489					getContents({viewMode: 'cards'});
490				}
491			}
492			feedLoaded();
493			let defaultBehavior = true;
494			if (!ignoreViewMode && !resultMode == 'item') {
495                if (properties.viewMode == "table"){
496					defaultBehavior = false;
497					setLocationHash();
498				} else if (location.hash.indexOf('?') > -1) {
499					getContents({}, that.initialGetContent);
500				}
501			}
502			if (defaultBehavior && location.hash.indexOf('?') > -1) {
503                getContents({}, that.initialGetContent);
504			}
505		} else {
506            getContents({}, that.initialGetContent, true, true);
507		}
508		if (!map.pointViewMode && geoFilter && (currentState.coords.latitude === null || currentState.coords.longitude === null) ) {
509			getLocation();
510		}
511		initializedCallback();
512	}
513
514	function initFeed(){
515		var $feed = $page.find(".content-col");
516		var switchMarkup = '<div class="btn-group pull-right">' +
517			'<button type="button" class="btn btn-default" data-view="cards"><i class="fa fa-th-large"></i></button>' +
518			'<button type="button" class="btn btn-default" data-view="table"><i class="fa fa-th-list"></i></button>' +
519			'</div>';
520		$feed.find('> .section-title').wrap('<div />');
521		$feed.find('> div > .section-title').parent().addClass('clearfix').addClass('dynamic-section-title');
522		if (viewSwitch) {
523            var $wrapper = $feed.filter(':not(.no-view-switch)').find('> div > .section-title').parent();
524            $(switchMarkup).appendTo($wrapper).find('button[data-view="' + currentState.viewMode + '"]').addClass('active');
525
526            $viewSwitch = $wrapper.find('.btn-group');
527
528            $viewSwitch.on('click', 'button', function(e){
529                e.preventDefault();
530                setLocationHash({viewMode: $(this).data('view')});
531            });
532		}
533	}
534
535	function initMap(){
536		var $map = $page.find(".dynamic-content").addClass("map-wrapper");
537		$map.parents(".container, .container-fluid").addClass("has-map");
538		var mapOptions = {
539			minZoom: map.minZoom===null ? 2 : map.minZoom,
540			zoom: map.defaultZoom!==null?map.defaultZoom:(map.maxZoom===null || map.maxZoom===null ? 8 : Math.round(map.minZoom+((map.maxZoom-map.minZoom)/2))),
541			maxZoom: map.maxZoom===null ? 18 : map.maxZoom,
542            mapTypeId: map.typeID,
543            gestureHandling: 'greedy'
544		};
545		if (map.arcgisMapServer){
546			mapOptions.mapTypeId = 'arcgis';
547			mapOptions.mapTypeControl = false;
548			/*mapOptions.mapTypeControlOptions = {
549				mapTypeIds: ['arcgis']
550			};*/
551		}
552		map.obj = new google.maps.Map($map.get(0), mapOptions);
553		if (map.arcgisMapServer){
554			var agsType = new gmaps.ags.MapType(map.arcgisMapServer, {
555				name: 'ArcGIS',
556				singleFusedMapCache: false
557			});
558			map.obj.mapTypes.set('arcgis', agsType);
559			map.obj.setMapTypeId('arcgis');
560		} else if (map.colors!==false) {
561			var customizedColors = new google.maps.StyledMapType(map.colors)
562			map.obj.mapTypes.set('custom_style', customizedColors);
563			map.obj.setMapTypeId('custom_style');
564		}
565		if (map.type == "openstreetmap"){
566			map.obj.mapTypes.set("OSM", new google.maps.ImageMapType({
567				getTileUrl: function(coord, zoom) {
568					var tilesPerGlobe = 1 << zoom;
569					var x = coord.x % tilesPerGlobe;
570					if (x < 0) {
571						x = tilesPerGlobe+x;
572					}
573					return "http://tile.openstreetmap.org/" + zoom + "/" + x + "/" + coord.y + ".png";
574				},
575				tileSize: new google.maps.Size(256, 256),
576				name: "OpenStreetMap",
577				maxZoom: map.maxZoom===null ? 18 : map.maxZoom,
578			}));
579		} else if (map.type == "opencyclemap"){
580			map.obj.mapTypes.set("OCM", new google.maps.ImageMapType({
581				getTileUrl: function(coord, zoom) {
582					var tilesPerGlobe = 1 << zoom;
583					var x = coord.x % tilesPerGlobe;
584					if (x < 0) {
585						x = tilesPerGlobe+x;
586					}
587					return "http://tile.opencyclemap.org/cycle/" + zoom + "/" + x + "/" + coord.y + ".png";
588				},
589				tileSize: new google.maps.Size(256, 256),
590				name: "OpenCycleMap",
591				maxZoom: map.maxZoom===null ? 18 : map.maxZoom,
592			}));
593		}
594
595		map.currentInfoWindow.setContent('<strong>' +
596			mlpLanguage.youAreHere +
597			'</strong><br /><a href="#" class="btn btn-primary btn-not-here">' +
598			mlpLanguage.notHere +
599			'</a>');
600
601		$page.on("click", ".btn-not-here", function(e){
602			e.preventDefault();
603			displayLocationPicker();
604		});
605        if (map.centerLat && map.centerLng) {
606            map.obj.setCenter({lat: map.centerLat, lng: map.centerLng});
607        }
608        if (map.defaultZoom) map.obj.setZoom(map.defaultZoom);
609		var center;
610		function calculateCenter() {
611			center = map.obj.getCenter();
612		}
613		google.maps.event.addDomListener(map.obj, 'idle', function() {
614            calculateCenter();
615		});
616		google.maps.event.addDomListener(window, 'resize', function() {
617			map.obj.setCenter(center);
618		});
619		google.maps.event.addListenerOnce(map.obj, 'tilesloaded', function(){
620			if (map.centerLat && map.centerLng) {
621				map.obj.setCenter({lat: map.centerLat, lng: map.centerLng});
622			}
623			if(map.latLngBounds && !map.latLngBounds.isEmpty()) {
624                map.obj.fitBounds(map.latLngBounds,0);
625			}
626			else if (map.defaultZoom) map.obj.setZoom(map.defaultZoom);
627			else map.defaultPosition
628		});
629	}
630	function hideElevationChart(){
631        var $map = $page.find(".dynamic-content");
632        var $chart = $map.find('.elevation-chart');
633        if ($chart.length) {
634        	var $ch = $chart.find('.elevation-chart-container').highcharts();
635        	if ($ch!==undefined) $ch.destroy();
636        	$chart.remove();
637        }
638	}
639	function displayElevationChart(dataStore) {
640		var $map = $page.find(".dynamic-content").addClass("map-wrapper");
641		var $chart = $map.find('.elevation-chart');
642		if (!$chart.length) {
643			var cclass = showElevationChart ? 'elevation-chart' : 'elevation-chart chart-hidden';
644			$chart = $('<div class="'+cclass+'">' +
645				'<div class="elevation-display"></div>' +
646				'<button type="button" class="btn btn-primary btn-toggle-chart" rel="tooltip" title="'+mlpLanguage.toggleElevationChart+'"><i class="fa fa-fw fa-arrow-down"></i><i class="fa fa-fw fa-line-chart"></i></button>' +
647				'<div class="elevation-chart-container"></div>' +
648				'</div>').appendTo($map);
649			map.$elevationChartDisplay = $chart.find('.elevation-display');
650
651			map.elevationChartMarker = new google.maps.Marker({
652				position: new google.maps.LatLng(0, 0),
653				icon: {
654					path: "M0-48c-9.8 0-17.7 7.8-17.7 17.4 0 15.5 17.7 30.6 17.7 30.6s17.7-15.4 17.7-30.6c0-9.6-7.9-17.4-17.7-17.4z",
655					fillColor: mlpObject.getBrandPrimaryColor(),
656					fillOpacity: 1,
657					anchor: new google.maps.Point(0,0),
658					strokeWeight: 2,
659					strokeColor: 'rgba(0,0,0,0.75)',
660					scale: 0.7
661				}
662			});
663
664			$chart.find(".btn-toggle-chart").click(function(e){
665				e.preventDefault();
666
667				if (!$chart.is(".chart-hidden")){
668					map.elevationChartMarker.setMap(null);
669				}
670				$chart.toggleClass("chart-hidden");
671			});
672
673			$.ajax({
674				url: '/publicChart/data',
675				data: {
676					chart: {
677						target: 'track',
678						representation: 'altitude',
679						type: 'elevationdistance',
680						id: dataStore.id
681					}
682				},
683				type: 'get',
684				dataType: 'json',
685				success: function (response) {
686					var series;
687					if (response && response.series !== undefined && response.series.length) {
688						for (var i = 0; i < response.series.length; i++) {
689							var ser = response.series[i];
690							for (var j = 0; j < ser.data.length; j++) {
691								ser.data[j][0] = parseInt(ser.data[j][0]);
692							}
693						}
694						$chart.find('.elevation-chart-container').highcharts({
695							title: {
696								text: ''
697							},
698							chart: {
699								zoomType: 'x',
700								backgroundColor: 'transparent'
701							},
702							navigation: {
703								buttonOptions: {
704									enabled: false
705								}
706							},
707							xAxis: {
708								gridLineColor: '#606060',
709								gridLineWidth: '1px',
710								type: 'linear',
711								title: {text: mlpLanguage.distance + ' (m)'},
712								labels: { style: { color: '#fff' }},
713								crosshair: {
714									color: '#fff',
715									width: '1px'
716								}
717							},
718							yAxis: {
719								gridLineColor: '#606060',
720								gridLineWidth: '1px',
721								type: 'linear',
722								title: {text: mlpLanguage.altitude + ' (m)'},
723								labels: { style: { color: '#fff' }}
724							},
725							labels: {
726								style: {
727									color: '#fff'
728								}
729							},
730							plotOptions: {
731								series: {
732									point: {
733										events: {
734											mouseOver: function () {
735												elevationGraphOnMouseover(this.series.data.indexOf(this), this)
736											},
737											click: function () {
738												elevationGraphOnMouseover(this.series.data.indexOf(this), this)
739											}
740										}
741									},
742									events: {
743										mouseOut: function () {
744											elevationGraphOnMouseout(this)
745										}
746									}
747								},
748								area: {
749                                    fillColor: {
750                                        linearGradient: {
751                                            x1: 0,
752                                            y1: 0,
753                                            x2: 0,
754                                            y2: 1
755                                        },
756                                        stops: [
757                                            [0, 'rgba(255,255,255,0.9)'],
758                                            [1, 'rgba(255,255,255,0.7)']
759                                        ]
760                                    },
761                                    marker: {
762                                        radius: 0,
763                                        fillColor: '#fff'
764                                    },
765                                    lineWidth: 1,
766                                    lineColor: '#fff',
767                                    states: {
768                                        hover: {
769                                            lineWidth: 1,
770                                            halo: false,
771                                            marker: {
772                                                enabled: false
773                                            }
774                                            // }
775                                        },
776                                        threshold: null
777                                    }
778                                }
779							},
780							tooltip: {
781								enabled: false
782							},
783							legend: {
784								enabled: false
785							},
786							series: response.series,
787							credits: {
788                                enabled: false
789							}
790						});
791					}
792				}
793			});
794		}
795	}
796
797	function elevationGraphOnMouseover(index, point){
798		if (map.paths && map.paths[0] !== undefined){
799			var pointObj = map.paths[0].getPath().getAt(index);
800			if (!map.elevationChartMarker.getMap())
801				map.elevationChartMarker.setMap(map.obj);
802			map.elevationChartMarker.setPosition(new google.maps.LatLng(pointObj.lat(), pointObj.lng()));
803		}
804		map.$elevationChartDisplay.html(point.y + "m").show();
805	}
806
807	function elevationGraphOnMouseout(){
808		map.$elevationChartDisplay.hide();
809		map.elevationChartMarker.setMap(null);
810	}
811
812	function displayRoutePlanner(geolocationFailed){
813		var title = mlpLanguage.routeDialogTitle;
814
815		var template =
816			'<form class="form">' +
817			'	<h3>' + mlpLanguage.setRouteStartingPoint + ':</h3>';
818		if (geolocationFailed === true){
819			template += '<div class="alert alert-danger">' + mlpLanguage.geoLocateError + '</div>';
820		}
821		template +=
822			'	<p class="text-center">' + mlpLanguage.typeInLocation + '</p>' +
823			'	<div class="form-group">' +
824			'		<input type="text" name="location" value="" placeholder="" class="form-control">' +
825			'	</div>';
826		if (geolocationFailed !== true){
827			template +=
828				'	<p class="text-center">' + mlpLanguage.or + '</p>' +
829				'	<div class="form-group">' +
830				'		<button type="submit" class="btn btn-primary btn-block btn-current"><i class="fa fa-map-marker"></i> ' + mlpLanguage.useCurrentPosition + '</button>' +
831				'	</div>';
832		}
833		template +=
834			'</form>';
835
836		BootstrapDialog.show({
837			message: template,
838			size: BootstrapDialog.SIZE_SMALL,
839			type: BootstrapDialog.TYPE_PRIMARY,
840			title: title,
841			onshown: function(obj){
842				var $input = obj.$modalBody.find("input[name='location']");
843				$input.keydown(function (e) {
844					if (e.which == 13 && $('.pac-container:visible').length) return false;
845				});
846
847				var autocomplete = new google.maps.places.Autocomplete($input.get(0));
848				autocomplete.addListener('place_changed', function() {
849					BootstrapDialog.closeAll();
850					var place = autocomplete.getPlace();
851					if (!place.geometry) {
852						BootstrapDialog.show({
853							title: mlpLanguage.locationErrorTitle,
854							message: mlpLanguage.locationErrorBody,
855							size: BootstrapDialog.SIZE_SMALL,
856							type: BootstrapDialog.TYPE_DANGER
857						});
858					} else {
859						directionsToPoint(map.destination, place.geometry.location);
860					}
861				});
862
863				obj.$modalBody.find(".btn-current").click(function(e){
864					e.preventDefault();
865					BootstrapDialog.closeAll();
866					getLocation(true);
867				});
868				setTimeout(function(){
869					$input.focus();
870				}, 100);
871			}
872		});
873	}
874
875	function bindListItemEvents(){
876		$page.on('click', '.favorite-link', function(e){
877			e.preventDefault();
878			e.stopPropagation();
879			favorite($(this));
880
881			return false;
882		});
883
884		$page.on('click', '.business-card-image', function(e){
885			e.preventDefault();
886			e.stopPropagation();
887			var $this = $(this).parents('.business-card-header');
888			var $imageCol = $this.find('.image-col');
889			var $detailsCol = $this.find('.details-col');
890			if ($imageCol.length) {
891				if ($this.is('.open')) {
892					$this.removeClass('open');
893					$imageCol.removeClass('col-xs-12').removeClass('col-sm-6').addClass('col-xs-3');
894					$detailsCol.removeClass('col-xs-12').removeClass('col-sm-6').addClass('col-xs-9');
895				} else {
896					$this.addClass('open');
897					$imageCol.addClass('col-xs-12').addClass('col-sm-6').removeClass('col-xs-3');
898					$detailsCol.addClass('col-xs-12').addClass('col-sm-6').removeClass('col-xs-9');
899				}
900			}
901			return false;
902		});
903
904		$page.on('click', '.rating .star', function(e){
905			e.preventDefault();
906			e.stopPropagation();
907			var $this = $(this);
908			var $obj = $this.closest('.rating');
909
910			rate($obj.data("id"), $this.data("rate"), $page.hasClass('page-block')||$page.hasClass('page'));
911		});
912
913		$page.on('click', '.btn-overlay, .btn-new-tab', function(e){
914			//e.stopPropagation();
915		});
916
917		$page.on('click', '.info a', function(e){
918			e.stopPropagation();
919		});
920
921		$page.on('click', '.dynamic-item, .btn-dynamic-item', function(e){
922			//e.stopPropagation();
923
924			var $this = $(this);
925			if ($this.is(".table-view")){
926				e.preventDefault();
927
928				if ($this.is('.open')){
929					$this.find('.image-col').removeClass('col-xs-12').removeClass('col-sm-5').addClass('col-xs-3');
930					$this.find('.data-col').removeClass('col-xs-12').removeClass('col-sm-7').addClass('col-xs-9');
931					$this.find('.hidden-details').collapse('hide');
932					$this.removeClass('open');
933				} else {
934					$this.find('.image-col').removeClass('col-xs-3').addClass('col-xs-12').addClass('col-sm-5');
935					$this.find('.data-col').removeClass('col-xs-9').addClass('col-xs-12').addClass('col-sm-7');
936					$this.find('.hidden-details').collapse('show');
937					$this.addClass('open');
938					$(window).trigger('scroll');
939				}
940			} else {
941				if ($this.attr('data-id') !== undefined) {
942					e.preventDefault();
943
944					setLocationHash({item: $this.attr('data-id')});
945				} else if ($this.attr('data-href') !== undefined) {
946					e.preventDefault();
947
948					location.href = $this.attr('data-href');
949				}
950			}
951		});
952
953		$page.on('click', '.btn-back-to-list', function(e) {
954			e.preventDefault();
955			setLocationHash({item: ''});
956			//window.history.back();
957		});
958
959		$page.on('click', '.pagination:not(.custom) a', function(e) {
960			var block = $(this).parent().parent().closest('.page,.page-block');
961
962			if (block.attr('id') === $page.attr('id')) {
963				e.preventDefault();
964                currentState.item = '';
965                setLocationHash({current_page: $(this).data('page')});
966				if (block.length>0)
967					$('html, body').animate({scrollTop: block.position().top}, 'slow');
968				else
969					$('html, body').animate({scrollTop: 0}, 'slow');
970			}
971		});
972	}
973	function bindFilterEvents(){
974		var $resetButton = $page.find(".result-filter .btn-reset");
975		$resetButton.click(function(e){
976			e.preventDefault();
977			var defaultState = cloneDefaultState();
978			delete defaultState.coords;
979			setLocationHash(defaultState);
980		});
981		if ($tagFilter !== null && $tagFilter.length){
982			$tagFilter.on('change', function(){
983				var value = [];
984				var $tagselect = $tagFilter.filter('select');
985				var $taginput = $tagFilter.filter('input');
986				if ($tagselect.length>0) {
987                    value = $tagselect.val();
988				} else if ($taginput.length>0){
989                    $taginput.filter(":checked").each(function(){
990						value.push($(this).val());
991					});
992				}
993				setLocationHash({tag: value});
994			});
995		}
996		if ($categoryFilter !== null && $categoryFilter.length){
997			$categoryFilter.on('change', function(){
998				var $input = $(this);
999				var $wrapper = $categoryFilter.parents('.category-filter');
1000				var $ul = $wrapper.find('ul').first();
1001
1002				processCategoryTree();
1003				var value = [];
1004				$categoryFilter.each(function(i,e){
1005					$catFilter = $(e);
1006					if ($catFilter.is("input")){
1007						if ($ul.data('mode') == 'implicit') {
1008							if ($input.is(':checked')) {
1009								$input.parent().parent().find('input').prop('checked', true);
1010							} else {
1011								$input.parent().parent().find('input').prop('checked', false);
1012							}
1013						}
1014						$catFilter.filter(":checked").each(function(){
1015							value.push($(this).val());
1016						});
1017					} else {
1018						value = $catFilter.val();
1019					}
1020				});
1021
1022				setLocationHash({category: value});
1023			});
1024			$categoryFilter.parents('.category-filter').on('hidden.bs.collapse', function (e) {
1025				$(e.target).parent().addClass('subtree-collapsed');
1026			}).on('shown.bs.collapse', function (e) {
1027				$(e.target).parent().removeClass('subtree-collapsed');
1028			});
1029		}
1030		if ($clientGroupFilter !== null && $clientGroupFilter.length){
1031			$clientGroupFilter.on('change', function(){
1032				var value = [];
1033				if ($clientGroupFilter.is("input")){
1034					$clientGroupFilter.filter(":checked").each(function(){
1035						value.push($(this).val());
1036					});
1037				} else {
1038					value = $clientGroupFilter.val();
1039				}
1040				setLocationHash({clientGroup: value});
1041			});
1042		}
1043		if ($rangeFilter !== null && $rangeFilter.length){
1044			$rangeFilter.on('change', function(){
1045				setLocationHash({range: $rangeFilter.val()});
1046			});
1047		}
1048		if ($monthFilter !== null && $monthFilter.length){
1049			$monthFilter.on('change', function(){
1050				setLocationHash({month: $monthFilter.val()});
1051			});
1052		}
1053		if ($datasourceFilter !== null && $datasourceFilter.length){
1054            $datasourceFilter.on('change', function(){
1055				setLocationHash({datasource: $datasourceFilter.val()});
1056			});
1057		}
1058		if ($favoriteFilter !== null && $favoriteFilter.length){
1059			$favoriteFilter.on('change', function(){
1060				if ($favoriteFilter.is("select")) {
1061					setLocationHash({favorite: $favoriteFilter.val() == 'all' ? '' : $favoriteFilter.val()});
1062				} else {
1063					setLocationHash({favorite: $favoriteFilter.is(":checked") ? $favoriteFilter.val() : ''});
1064				}
1065			});
1066		}
1067		if ($visitedFilter !== null && $visitedFilter.length){
1068			$visitedFilter.on('change', function(){
1069				if ($visitedFilter.is("select")) {
1070					setLocationHash({visited: $visitedFilter.val() == 'all' ? '' : $visitedFilter.val()});
1071				} else {
1072					setLocationHash({visited: $visitedFilter.is(":checked") ? $visitedFilter.val() : ''});
1073				}
1074			});
1075		}
1076		if ($openFilter !== null && $openFilter.length){
1077			$openFilter.on('change', function(){
1078				if ($openFilter.is("select")) {
1079					setLocationHash({open: $openFilter.val() == 'all' ? '' : $openFilter.val()});
1080				} else {
1081					setLocationHash({open: $openFilter.is(":checked") ? $openFilter.val() : ''});
1082				}
1083			});
1084		}
1085		if ($markerFilter !== null && $markerFilter.length){
1086			$markerFilter.on('change', function(){
1087				if ($markerFilter.is("select")) {
1088					setLocationHash({marker: $markerFilter.val() == 'all' ? '' : $markerFilter.val()});
1089				} else {
1090					setLocationHash({marker: $markerFilter.is(":checked") ? $markerFilter.val() : ''});
1091				}
1092			});
1093		}
1094		if ($hiddenFilter !== null && $hiddenFilter.length){
1095			$hiddenFilter.on('change', function(){
1096				setLocationHash({hidden: $hiddenFilter.val()});
1097			});
1098		}
1099		if ($textFilter !== null && $textFilter.length){
1100			$textFilter.on('change', function(){
1101				setLocationHash({search: $textFilter.val()});
1102			}).on("keypress", function(event){
1103				if (event.keyCode == 13){
1104					$(this).trigger("change");
1105					return false;
1106				}
1107				if (event.keyCode == 27){
1108					$(this).val('').trigger("change");
1109					return false;
1110				}
1111				return true;
1112			});
1113		}
1114		if ($difficultyFilter !== null && $difficultyFilter.length){
1115			var difficultyTimeout = null;
1116			$difficultyFilter.on('change', function(){
1117				var $this = $(this);
1118				if (difficultyTimeout != null) clearTimeout(difficultyTimeout);
1119
1120				difficultyTimeout = setTimeout(function(){
1121					setLocationHash({difficulty: $this.val()});
1122				}, 500);
1123			});
1124		}
1125		if ($lengthFilter !== null && $lengthFilter.length){
1126			var lengthTimeout = null;
1127			$lengthFilter.on('change', function(){
1128				if (lengthTimeout != null) clearTimeout(lengthTimeout);
1129
1130				lengthTimeout = setTimeout(function(){
1131					var min = $lengthFilter.filter('input[name="length-min"]').val();
1132					var max = $lengthFilter.filter('input[name="length-max"]').val();
1133					if (min || max) {
1134						if (!min) min = 0;
1135						if (!max) max = 0;
1136						setLocationHash({distance: [min, max]});
1137					} else {
1138						setLocationHash({distance: ''});
1139					}
1140				}, 500);
1141			});
1142		}
1143        if ($priceFilter !== null && $priceFilter.length){
1144            var priceTimeout = null;
1145            $priceFilter.on('change', function(){
1146                if (priceTimeout != null) clearTimeout(priceTimeout);
1147
1148                priceTimeout = setTimeout(function(){
1149                    var min = $priceFilter.filter('input[name="price-min"]').val();
1150                    var max = $priceFilter.filter('input[name="price-max"]').val();
1151                    if (min || max) {
1152                        if (!min) min = 0;
1153                        if (!max) max = 0;
1154                        setLocationHash({price: [min, max]});
1155                    } else {
1156                        setLocationHash({price: ''});
1157                    }
1158                }, 500);
1159            });
1160        }
1161		if ($ratingFilter !== null && $ratingFilter.length){
1162			var ratingTimeout = null;
1163			$ratingFilter.on('change', function(){
1164				var $this = $(this);
1165				if (ratingTimeout != null) clearTimeout(ratingTimeout);
1166
1167				ratingTimeout = setTimeout(function(){
1168					setLocationHash({rating: $this.val()});
1169				}, 500);
1170			});
1171		}
1172	}
1173	function processCategoryTree() {
1174    	if (!$categoryFilter.is("input")) return false;
1175		$page.find('.category-filter .partially-selected-tree').removeClass('partially-selected-tree');
1176
1177		$categoryFilter.each(function(){
1178			var $input = $(this);
1179			var $li = $input.parent().parent();
1180
1181			var childrenCount = $li.find('ul input').length;
1182			var selectedChildrenCount = $li.find('ul input:checked').length;
1183
1184			if (selectedChildrenCount && selectedChildrenCount < childrenCount) {
1185				$input.parent().addClass('partially-selected-tree');
1186			}
1187		});
1188	}
1189	function setFilterDisplay(data){
1190		postLocation(data);
1191		var $resultFilter = $page.find(".result-filter");
1192		$('.btn-sort').removeClass('active');
1193		if (data.sort_attr) {
1194			var $btn = $('.btn-sort[data-sort="'+data.sort_attr+'"]');
1195			if ($btn.length>0) {
1196                $btn.addClass('active').addClass(data.sort_direction?'sort-ascending':'sort-descending');
1197			}
1198        }
1199		if (data.attributes) {
1200			var attr = data.attributes.split('&');
1201			var attrs = {};
1202            $.each(attr, function(i,e){
1203                var a = urldecode(e);
1204                var x = a.split('=');
1205                if (attrs[x[0]]==undefined) {
1206                	attrs[x[0]] = x[1];
1207                } else {
1208                	if ($.isArray(attrs[x[0]])) {
1209                		if (-1===$.inArray(x[1], attrs[x[0]])) attrs[x[0]].push(x[1]);
1210                    } else if (attrs[x[0]]!=x[1]) {
1211                        attrs[x[0]] = [attrs[x[0]], x[1]];
1212                    }
1213                }
1214            });
1215            $.each(attrs, function(name,value){
1216				var $e = $('[name="'+name+'"]');
1217				if ($e.length) {
1218					$e.each(function(){
1219                        if ($(this).is("select")) {
1220                            if (!$(this).hasClass('no-auto-init')) $(this).selectpicker('val', value);
1221                            else $(this).val(value);
1222                        } else {
1223                            switch ($(this).attr('type')) {
1224                                case 'checkbox':
1225                                case 'radio':
1226                                	var checked = false;
1227                                	if ($.isArray(value)) {
1228										checked = $.inArray($(this).val(), value)>-1;
1229									} else {
1230										checked = $(this).val()==parseInt(value);
1231									}
1232                                    $(this).prop('checked', checked);
1233                                    break;
1234                                case 'text':
1235                                    if ($(this).hasClass('range')) {
1236                                        var val = value.split(',');
1237                                        var range = [];
1238                                        $.each(val, function(i,e){ range.push(parseFloat(e)); });
1239                                        $(this).slider("setValue", range);
1240                                    }
1241                                    break;
1242                                default:
1243                                    $(this).val(value);
1244                            }
1245                        }
1246					});
1247                }
1248			});
1249		}
1250		if (data.item !== undefined && data.item){
1251			$resultFilter.hide();
1252			if ($viewSwitch !== null) {
1253				$viewSwitch.hide();
1254			}
1255			if ($resultFilter.parent().is(".sidebar-col")){
1256				$resultFilter.prev().hide();
1257			}
1258		} else {
1259			$resultFilter.show();
1260			if ($viewSwitch !== null) {
1261				$viewSwitch.show();
1262			}
1263			if ($resultFilter.parent().is(".sidebar-col")){
1264				$resultFilter.prev().show();
1265			}
1266		}
1267		if ($searchForm.length){
1268			$searchForm.find("input[name='search']").val(data.search);
1269		}
1270		if ($viewSwitch !== null){
1271			$viewSwitch.find('button').removeClass('active').filter('[data-view="' + data.viewMode + '"]').addClass('active');
1272		}
1273		if (data.tag || data.month > 0 || data.range || data.distance || data.datasource || data.difficulty != '0-10' || data.related != '' || data.favorite !== "all" || data.visited !== "all" || data.open !== "all" || data.hidden !== "all") {
1274			$page.find(".btn-filter-toggle").addClass("active");
1275		} else {
1276			$page.find(".btn-filter-toggle").removeClass("active");
1277		}
1278		if ($tagFilter !== null && $tagFilter.length){
1279			if ($tagFilter.is("select")) {
1280				if (!$tagFilter.hasClass('no-auto-init')) $tagFilter.selectpicker('val', data.tag);
1281				else $tagFilter.val(data.tag);
1282			} else {
1283				var tags = data.tag;
1284				if (typeof tags != "object") {
1285					if (tags.indexOf(",") !== -1){
1286						tags = tags.split(',');
1287					} else {
1288						tags = [tags];
1289					}
1290				}
1291				$tagFilter.each(function(){
1292					$.inArray($(this).attr('value'), tags) > -1 ? $(this).prop('checked', true) : $(this).prop('checked', false);
1293				});
1294			}
1295		}
1296		if ($categoryFilter !== null && $categoryFilter.length){
1297			if ($categoryFilter.is("select")) {
1298				if (!$categoryFilter.hasClass('no-auto-init')) $categoryFilter.selectpicker('val', data.category);
1299				else $categoryFilter.val(data.category);
1300			} else {
1301				var categories = data.category;
1302				if (categories && typeof categories != "object") {
1303					if (categories.indexOf(",") !== -1){
1304						categories = categories.split(',');
1305					} else {
1306						categories = [categories];
1307					}
1308				}
1309				$categoryFilter.each(function(){
1310					$.inArray($(this).attr('value'), categories) > -1 ? $(this).prop('checked', true) : $(this).prop('checked', false);
1311				});
1312				processCategoryTree();
1313			}
1314		}
1315		if ($clientGroupFilter !== null && $clientGroupFilter.length){
1316			if ($clientGroupFilter.is("select")) {
1317				$clientGroupFilter.selectpicker('val', data.clientGroup);
1318			} else {
1319				var clientGroups = data.clientGroup;
1320				if (typeof clientGroups != "object") {
1321					if (clientGroups.indexOf(",") !== -1){
1322						clientGroups = clientGroups.split(',');
1323					} else {
1324						clientGroups = [clientGroups];
1325					}
1326				}
1327				$clientGroupFilter.each(function(){
1328					$.inArray($(this).attr('value'), clientGroups) > -1 ? $(this).prop('checked', true) : $(this).prop('checked', false);
1329				});
1330			}
1331		}
1332		if ($textFilter !== null && $textFilter.length) {
1333			$textFilter.val(data.search);
1334		}
1335		if ($favoriteFilter !== null && $favoriteFilter.length) {
1336			if ($favoriteFilter.is("select")) {
1337				$favoriteFilter.selectpicker('val', data.favorite);
1338			} else {
1339				if (data.favorite == "favorites"){
1340					$favoriteFilter.attr('checked', true);
1341				} else {
1342					$favoriteFilter.attr('checked', false);
1343				}
1344			}
1345		}
1346		if ($visitedFilter !== null && $visitedFilter.length) {
1347			if ($visitedFilter.is("select")) {
1348				$visitedFilter.selectpicker('val', data.visited);
1349			} else {
1350				if (data.visited == "notvisited"){
1351					$visitedFilter.attr('checked', true);
1352				} else {
1353					$visitedFilter.attr('checked', false);
1354				}
1355			}
1356		}
1357		if ($openFilter !== null && $openFilter.length) {
1358			if ($openFilter.is("select")) {
1359				$openFilter.selectpicker('val', data.open);
1360			} else {
1361				if (data.open == "open"){
1362					$openFilter.attr('checked', true);
1363				} else {
1364					$openFilter.attr('checked', false);
1365				}
1366			}
1367		}
1368		if ($markerFilter !== null && $markerFilter.length) {
1369			if ($markerFilter.is("select")) {
1370				$markerFilter.selectpicker('val', data.marker);
1371			} else {
1372				if (data.marker == "datastore"){
1373					$markerFilter.attr('checked', true);
1374				} else {
1375					$markerFilter.attr('checked', false);
1376				}
1377			}
1378		}
1379		if ($hiddenFilter !== null && $hiddenFilter.length) {
1380			$hiddenFilter.selectpicker('val', data.hidden);
1381		}
1382		if ($monthFilter !== null && $monthFilter.length) {
1383			$monthFilter.selectpicker('val', data.month);
1384		}
1385		if ($rangeFilter !== null && $rangeFilter.length) {
1386			$rangeFilter.selectpicker('val', data.range);
1387		}
1388		if ($datasourceFilter !== null && $datasourceFilter.length) {
1389			$datasourceFilter.selectpicker('val', data.datasource);
1390		}
1391		if ($difficultyFilter !== null && $difficultyFilter.length) {
1392			var difficulty = [0,10];
1393			if (data.difficulty !== undefined && data.difficulty){
1394				if (typeof data.difficulty == "object" && data.difficulty.length == 2){
1395					difficulty = [parseFloat(data.difficulty[0]), parseFloat(data.difficulty[1])];
1396				} else if (data.difficulty.indexOf(',') !== -1) {
1397					difficulty = data.difficulty.split(',');
1398				}
1399			}
1400			$difficultyFilter.slider("setValue", difficulty);
1401		}
1402		if ($lengthFilter !== null && $lengthFilter.length) {
1403			var length = [];
1404			if (data.distance !== undefined && data.distance){
1405				if (typeof data.distance == "object" && data.distance.length == 2){
1406					length = [parseFloat(data.distance[0]), parseFloat(data.distance[1])];
1407				} else if (data.distance.indexOf(',') !== -1) {
1408					length = data.distance.split(',');
1409				}
1410			}
1411			$lengthFilter.filter('input[name="length-min"]').val(length[0] !== undefined ? length[0] : '');
1412			$lengthFilter.filter('input[name="length-max"]').val(length[1] !== undefined ? length[1] : '');
1413		}
1414        if ($priceFilter !== null && $priceFilter.length) {
1415            var price = [];
1416            if (data.price !== undefined && data.price){
1417                if (typeof data.price == "object" && data.price.length == 2){
1418                    price = [parseFloat(data.price[0]), parseFloat(data.price[1])];
1419                } else if (data.price.indexOf(',') !== -1) {
1420                    price = data.price.split(',');
1421                }
1422            }
1423            $priceFilter.filter('input[name="price-min"]').val(price[0] !== undefined ? price[0] : '');
1424            $priceFilter.filter('input[name="price-max"]').val(price[1] !== undefined ? price[1] : '');
1425        }
1426		if ($ratingFilter !== null && $ratingFilter.length) {
1427			var rating = [0,5];
1428			if (data.rating !== undefined && data.rating){
1429				if (typeof data.rating == "object" && data.rating.length == 2){
1430					rating = [parseFloat(data.rating[0]), parseFloat(data.rating[1])];
1431				} else if (data.rating.indexOf(',') !== -1) {
1432					rating = data.rating.split(',');
1433					$.each(rating, function(i,e){ rating[i] = parseFloat(e); });
1434				}
1435			}
1436			$ratingFilter.slider("setValue", rating);
1437		}
1438	}
1439	function getQueryStringArray(){
1440        var data = cloneState();
1441        //data.item = '';
1442		var query = {};
1443		if (location.hash.indexOf('?') > -1) {
1444			var z = location.hash.split('?');
1445			if (!that.initialized || (z[0] == '#'+$page.data('friendlyId'))) {
1446                var queryString = z[z.length - 1];
1447                var x = queryString.split('&');
1448                x.forEach(function (e) {
1449                	var pos = e.indexOf('=');
1450                	if (pos>-1) {
1451                        var y = [e.substring(0, pos), e.substring(pos+1)];
1452                        if (y[0].indexOf('.') > -1){
1453                            var t = y[0].split('.');
1454                            if ((t.length == 2)) {
1455                                if (query[t[0]] === undefined) query[t[0]] = {};
1456                                query[t[0]][t[1]] = y[1].indexOf(',') > -1 ? y[1].split(',') : y[1];
1457                            }
1458                        } else {
1459                            if ((y.length >= 2)) {
1460                                query[y[0]] = y[1].indexOf(',') > -1 ? y[1].split(',') : y[1];
1461                                query[y[0]] = urldecode(query[y[0]]);
1462                            }
1463                        }
1464					}
1465                });
1466                for (var i in query){
1467                    if (data[i] !== undefined) data[i] = query[i];
1468                }
1469			}
1470		}
1471		return data;
1472	}
1473	function getQueryData(cdata, allowExtraParams){
1474    	allowExtraParams = allowExtraParams !== undefined && allowExtraParams === true;
1475		map.pointViewMode = false;
1476		var data = getQueryStringArray();
1477        console.log(data);
1478        if (allowExtraParams && data.dataStoreMarkerId !== undefined && data.dataStoreMarkerId.length && data.dataStoreId !== undefined && data.dataStoreId.length){
1479			map.pointViewMode = true;
1480		}
1481		if (cdata !== undefined) {
1482			if (cdata.coords !== undefined && cdata.coords.latitude && cdata.coords.latitude.toString().length>0 && cdata.coords.longitude.toString().length>0) {
1483				data.coords = cdata.coords;
1484			}
1485			var hasTaxonomy = false;
1486			if (cdata.category !== undefined && cdata.category.toString().length>0) {
1487				data.category = cdata.category;
1488				data.item = '';
1489				hasTaxonomy = true;
1490			}
1491			if (cdata.tag !== undefined && cdata.tag.toString().length>0) {
1492				data.tag = cdata.tag;
1493				data.item = '';
1494				hasTaxonomy = true;
1495			}
1496			if (!hasTaxonomy && cdata.item !== undefined) {
1497				data.item = cdata.item;
1498				data.tag = '';
1499				data.category = '';
1500			} else if (cdata.current_page !== undefined) {
1501				data.current_page = cdata.current_page;
1502			}
1503			if (cdata.viewMode !== undefined && cdata.viewMode.toString().length>0) data.viewMode = cdata.viewMode;
1504			if (cdata.rating !== undefined && cdata.rating.toString().length>0) data.rating = cdata.rating;
1505			if (cdata.clientGroup !== undefined && cdata.rating.toString().length>0) data.clientGroup = cdata.clientGroup;
1506			if (cdata.range !== undefined && cdata.range.toString().length>0) data.range = cdata.range;
1507			if (cdata.marker !== undefined && cdata.marker.toString().length>0) data.marker = cdata.marker;
1508			if (cdata.favorite !== undefined && cdata.favorite.toString().length>0) data.favorite = cdata.favorite;
1509			if (cdata.visited !== undefined && cdata.visited.toString().length>0) data.visited = cdata.visited;
1510			if (cdata.open !== undefined && cdata.open.toString().length>0) data.open = cdata.open;
1511			if (cdata.difficulty !== undefined && cdata.difficulty.toString().length>0) data.difficulty = cdata.difficulty;
1512			if (cdata.related !== undefined && cdata.related.toString().length>0) data.related = cdata.related;
1513			if (cdata.datasource !== undefined && cdata.datasource.toString().length>0) data.datasource = cdata.datasource;
1514			if (cdata.distance !== undefined && cdata.distance.toString().length>0) data.distance = cdata.distance;
1515            if (cdata.price !== undefined && cdata.price.toString().length>0) data.price = cdata.price;
1516            if (cdata.month !== undefined && cdata.month.toString().length>0) data.month = cdata.month;
1517			if (cdata.start !== undefined && cdata.start.toString().length>0) data.start = cdata.start;
1518			if (cdata.end !== undefined && cdata.end.toString().length>0) data.end = cdata.end;
1519			if (cdata.createdStart !== undefined && cdata.createdStart.toString().length>0) data.createdStart = cdata.createdStart;
1520			if (cdata.createdEnd !== undefined && cdata.createdEnd.toString().length>0) data.createdEnd = cdata.createdEnd;
1521			if (cdata.search !== undefined) data.search = cdata.search;
1522			if (cdata.hidden !== undefined && cdata.hidden.toString().length>0) data.hidden = cdata.hidden;
1523			if (cdata.dataStoreMarkerId !== undefined && parseInt(cdata.dataStoreMarkerId)>0) data.dataStoreMarkerId = cdata.dataStoreMarkerId;
1524			if (cdata.dataStoreId !== undefined && parseInt(cdata.dataStoreId)>0) data.dataStoreId = cdata.dataStoreId;
1525			if (cdata.attributes !== undefined && cdata.attributes.toString().length>0) data.attributes = cdata.attributes;
1526			if (cdata.sort_attr !== undefined && cdata.sort_attr.toString().length>0) data.sort_attr = cdata.sort_attr;
1527			if (cdata.sort_direction !== undefined) data.sort_direction = cdata.sort_direction;
1528		}
1529		if (!allowExtraParams){
1530			data.dataStoreMarkerId = '';
1531			data.dataStoreId = '';
1532		}
1533		return data;
1534	}
1535
1536	function setLocationHash(cdata){
1537    	var data = getQueryData(cdata);
1538		location.hash = getHash(data);
1539	}
1540
1541	function initMapViewControls(){
1542        var $viewControl = $page.find(".view-control");
1543		var $tools = $page.find(".map-tools:not(.map-tools-bottom)");
1544		var $filter = $page.find(".result-filter");
1545		var controls = !$page.find('.content-col').hasClass('no-view-switch');
1546
1547		if (controls && !$viewControl.length){
1548			var viewControlMarkup = '<div class="view-control">';
1549			if ($page.find('.result-filter').length) {
1550				viewControlMarkup += '<button class="btn btn-default btn-search" type="button"><i class="fa fa-fw fa-search"></i> <span class="hidden-xs">' + mlpLanguage.toggleFilterTitle + '</span></button>';
1551			}
1552			if (map.enableCustomPoints) {
1553				viewControlMarkup += '<button class="btn btn-default btn-add-point" type="button"><i class="fa fa-fw fa-plus"></i> <span class="hidden-xs">' + mlpLanguage.customPointAdd + '</span></button>';
1554			}
1555			viewControlMarkup += '<button class="btn btn-default btn-menu" type="button"><i class="fa fa-fw fa-bars"></i><i class="fa fa-fw fa-arrows-alt"></i> <span class="hidden-xs">' +
1556				'<span class="fullscreen-title">' + mlpLanguage.toggleFullscreenOffTitle + '</span>' +
1557				'<span class="normal-title">' + mlpLanguage.toggleFullscreenTitle + '</span>' +
1558				'</span>' +
1559				'</button>' +
1560				'</div>';
1561			if ($tools.length==0) {
1562				viewControlMarkup = '<div class="map-tools">'+viewControlMarkup+'</div>';
1563				$page.find('.dynamic-content').before(viewControlMarkup);
1564            } else {
1565                $(viewControlMarkup).initElements().appendTo($tools);
1566            }
1567			$viewControl = $page.find(".view-control");
1568
1569			$viewControl.find(".btn-add-point").click(function(e){
1570				e.preventDefault();
1571
1572				initCustomMarkerPicker();
1573			});
1574
1575			$viewControl.find(".btn-search").click(function(e){
1576				e.preventDefault();
1577				if (parseInt($filter.parent().css("top")) < 0){
1578					$filter.parent().animate({top: 0}, 300);
1579				} else {
1580					$filter.parent().animate({top: -1 * $filter.parent().outerHeight()}, 300);
1581				}
1582			});
1583
1584			$viewControl.find(".btn-menu").click(function(e){
1585				e.preventDefault();
1586				var center = map.obj.getCenter();
1587				if ($page.is(".fullscreen")){
1588					$page.removeClass("fullscreen");
1589					$filter.parent().data('status', 'visible').css({top: 0});
1590					if (filterInSidebar && $(window).width() >= 768){
1591					//if (filterInSidebar){
1592						var $title = $('<h4 class="section-title"><i class="fa fa-filter fa-fw""></i> ' + mlpLanguage.filter + '</h4>');
1593						if ($filter.is(":hidden")) $title.hide();
1594						$page.find('.sidebar-col').prepend($filter).prepend($title);
1595					}
1596				} else {
1597					if ($filter.parents('.sidebar-col').length){
1598						$filter.prev().remove();
1599						$page.find('.map-tools').prepend($filter);
1600					}
1601
1602					$page.addClass("fullscreen");
1603					$filter.parent().data('status', 'hidden').animate({top: -1 * $filter.parent().outerHeight()}, 300);
1604				}
1605				google.maps.event.trigger(map.obj, 'resize');
1606				$(window).resize();
1607				map.obj.setCenter(center);
1608			});
1609		}
1610		$(window).on('resize', function(){
1611
1612			if ($page.is('.fullscreen')){
1613				var $filterWrapper = $filter.parent();
1614				if ($filterWrapper.data('status') == 'hidden' && parseInt($filterWrapper.css('top')) != -1 * $filterWrapper.outerHeight()) {
1615					$filterWrapper.css({top: -1 * $filterWrapper.outerHeight()});
1616				}
1617			}
1618		});
1619        if (map.forceMapFullscreen || ($(window).width() < 992 && !map.disableMapAutoResize)) {
1620
1621			var center = map.obj.getCenter();
1622
1623			$page.addClass("fullscreen");
1624			google.maps.event.trigger(map.obj, 'resize');
1625			map.obj.setCenter(center);
1626
1627			$filter.parent().data('status', 'hidden').animate({top: -1 * $filter.parent().outerHeight()}, 300);
1628		}
1629	}
1630
1631	function initCustomMarkerPicker(ID){
1632		var data = [];
1633		var i;
1634		if (ID !== undefined && ID > 0){
1635			for (i in map.customMarkers){
1636				if (map.customMarkers[i].data.customPointId == ID){
1637					data = map.customMarkers[i].data;
1638					map.customMarkers[i].setMap(null);
1639				}
1640			}
1641		}
1642		var title = mlpLanguage.customPointAdd;
1643		var markerChanged = false;
1644
1645		var iconsTemplate = '';
1646		var icons = ['Media/0000ff/star-3.png', 'Media/128e4d/star-3.png', 'Media/2863c1/star-3.png', 'Media/49bedb/star-3.png',
1647			'Media/684997/star-3.png', 'Media/858585/star-3.png', 'Media/946d37/star-3.png', 'Media/9ab83a/star-3.png', 'Media/c03638/star-3.png',
1648			'Media/c259b5/star-3.png', 'Media/e5301f/star-3.png', 'Media/ef8304/star-3.png', 'Media/ffc11f/star-3.png'];
1649		for (i in icons){
1650			iconsTemplate +=
1651				'		<div class="icon-radio"><input type="radio" value="/images/mapicons/' + icons[i] + '" name="icon" id="customPointIcon' + i + '" />' +
1652				'		<label for="customPointIcon' + i + '"><img src="/images/mapicons/' + icons[i] + '" /></label></div>';
1653		}
1654		var template =
1655			'<form class="form">' +
1656			'	<div class="form-group">' +
1657			'		<label>' + mlpLanguage.name + ':</label>' +
1658			'		<input type="text" name="name" value="" placeholder="" class="form-control" required>' +
1659			'	</div>' +
1660			'	<div class="form-group">' +
1661			'		<label>' + mlpLanguage.icon + ':</label>' +
1662			'		<div class="icons">' + iconsTemplate + '</div>' +
1663			'	</div>' +
1664			'	<div class="form-group">' +
1665			'		<label>' + mlpLanguage.address + ':</label>' +
1666			'		<input type="text" name="address" value="" placeholder="" class="form-control" required>' +
1667			'	</div>' +
1668			'	<p class="text-center">' + mlpLanguage.or + '</p>' +
1669			'	<div class="form-group">' +
1670			'		<button type="button" class="btn btn-default btn-block btn-picker"><i class="fa fa-map-marker"></i> ' + mlpLanguage.pickLocation + '</button>' +
1671			'	</div>' +
1672			'	<div class="form-group hidden form-submit-group">' +
1673			'		<button type="submit" class="btn btn-primary btn-block"><i class="fa fa-save"></i> ' + mlpLanguage.save + '</button>' +
1674			'	</div>' +
1675			'	<input type="hidden" name="latitude" />' +
1676			'	<input type="hidden" name="longitude" />' +
1677			'	<input type="hidden" name="id" />' +
1678			'</form>';
1679
1680		BootstrapDialog.show({
1681			message: template,
1682			size: BootstrapDialog.SIZE_SMALL,
1683			type: BootstrapDialog.TYPE_PRIMARY,
1684			title: title,
1685			onhidden: function() {
1686				if (map.tempMarker !== null) {
1687					map.tempMarker.setMap(null);
1688					map.tempMarker = null;
1689				}
1690				if (map.pointViewMode) {
1691					map.pointViewMode = false;
1692					getContents({dataStoreMarkerId: '', dataStoreId: ''});
1693				} else if (markerChanged) {
1694					getContents({dataStoreMarkerId: '', dataStoreId: ''}, true);
1695				}
1696				google.maps.event.clearListeners(map.obj, 'click');
1697			},
1698			onshown: function(obj){
1699				obj.$modalBody.find(".icons input").prop("checked", false);
1700				if (data.customPointId !== undefined && data.customPointId){
1701					setTemporaryPointMarker(data.latitude, data.longitude, data.icon)
1702					obj.$modalBody.find(".form-submit-group").removeClass("hidden");
1703
1704					obj.$modalBody.find(".icons input[value='" + data.icon + "']").prop("checked", true);
1705					obj.$modalBody.find("input[name='name']").val(data.name);
1706					obj.$modalBody.find("input[name='address']").val(data.address);
1707					obj.$modalBody.find("input[name='latitude']").val(data.latitude);
1708					obj.$modalBody.find("input[name='longitude']").val(data.longitude);
1709					obj.$modalBody.find("input[name='id']").val(data.customPointId);
1710				} else {
1711					obj.$modalBody.find("input[type='text']").val('');
1712					obj.$modalBody.find(".icons input").first().prop("checked", true);
1713				}
1714
1715				obj.$modalBody.find("form").validate({
1716					submitHandler: function(form){
1717						var $form = $(form);
1718						markerChanged = true;
1719						$.ajax({
1720							type: 'post',
1721							data: $form.serialize(),
1722							url: "/public/customMarker/" + $page.data("id"),
1723							success: function(d){
1724								BootstrapDialog.closeAll();
1725							}
1726						});
1727					}
1728				});
1729
1730				var $input = obj.$modalBody.find("input[name='address']");
1731				$input.keydown(function (e) {
1732					if (e.which == 13 && $('.pac-container:visible').length) return false;
1733				});
1734
1735				var autocomplete = new google.maps.places.Autocomplete($input.get(0));
1736				autocomplete.addListener('place_changed', function() {
1737					var place = autocomplete.getPlace();
1738					if (!place.geometry) {
1739						BootstrapDialog.show({
1740							title: mlpLanguage.locationErrorTitle,
1741							message: mlpLanguage.locationErrorBody,
1742							size: BootstrapDialog.SIZE_SMALL,
1743							type: BootstrapDialog.TYPE_DANGER
1744						});
1745
1746						obj.$modalBody.find(".form-submit-group").addClass("hidden");
1747					} else {
1748						obj.$modalBody.find("input[name='latitude']").val(place.geometry.location.lat());
1749						obj.$modalBody.find("input[name='longitude']").val(place.geometry.location.lng());
1750
1751						obj.$modalBody.find(".form-submit-group").removeClass("hidden");
1752					}
1753				});
1754
1755				obj.$modalBody.find(".btn-picker").click(function(e){
1756					e.preventDefault();
1757
1758					obj.$modal.hide();
1759					$page.addClass("hide-controls");
1760					if (obj.$modal.find("input[name='latitude']").val() && obj.$modal.find("input[name='longitude']").val()){
1761						setTemporaryPointMarker(
1762							obj.$modal.find("input[name='latitude']").val(),
1763							obj.$modal.find("input[name='longitude']").val(),
1764							obj.$modalBody.find("input[name='icon']:checked").val());
1765					}
1766
1767					$('<div class="map-message">' +
1768						'<strong>' + mlpLanguage.clickOnTheMapToSelect + '</strong>' +
1769						'<button type="button" class="btn btn-primary btn-save"><i class="fa fa-save"></i> ' + mlpLanguage.save + '</button>' +
1770						'</div>').appendTo($page.find(".map-wrapper"));
1771
1772					$page.find(".map-message .btn-save").click(function(e){
1773						e.preventDefault();
1774						if (map.geocoder === null){
1775							map.geocoder = new google.maps.Geocoder();
1776						}
1777						map.geocoder.geocode({latLng: new google.maps.LatLng(
1778							obj.$modal.find("input[name='latitude']").val(),
1779							obj.$modal.find("input[name='longitude']").val()
1780						)}, function (results, status) {
1781							if (status == google.maps.GeocoderStatus.OK && results.length > 0) {
1782								var address = processGeocoderResult(results[0]);
1783								obj.$modal.find("input[name='address']").val(address.formattedAddress);
1784							}
1785						});
1786						$page.removeClass("hide-controls");
1787						obj.$modal.show();
1788						$page.find(".map-message").remove();
1789					});
1790
1791					google.maps.event.addListener(map.obj, 'click', function (point) {
1792						setTemporaryPointMarker(point.latLng.lat(), point.latLng.lng(), obj.$modalBody.find("input[name='icon']:checked").val());
1793					});
1794				});
1795			}
1796		});
1797	}
1798
1799
1800	function processGeocoderResult(address){
1801		var result = {};
1802
1803		result.formattedAddress = address.formatted_address;
1804		for (var i = address.address_components.length-1; i>=0; i--) {
1805			var component = address.address_components[i];
1806			// Postal code
1807			if (component.types.indexOf('postal_code') >= 0) {
1808				result.postalCode = component.short_name;
1809			}
1810			// Street number
1811			else if (component.types.indexOf('street_number') >= 0) {
1812				result.streetNumber = component.long_name;
1813			}
1814			// Street name
1815			else if (component.types.indexOf('route') >= 0) {
1816				result.streetName = component.short_name;
1817			}
1818			// City
1819			else if (component.types.indexOf('locality') >= 0) {
1820				result.city = component.long_name;
1821			}
1822			// District
1823			else if (component.types.indexOf('sublocality') >= 0) {
1824				result.district = component.short_name;
1825			}
1826			// State \ Province
1827			else if (component.types.indexOf('administrative_area_level_1') >= 0) {
1828				result.county = component.short_name;
1829			}
1830			// State \ Province
1831			else if (component.types.indexOf('country') >= 0) {
1832				result.country = component.short_name;
1833			}
1834		}
1835		result.addressLine1 = [result.streetNumber, result.streetName].join(' ').trim();
1836		result.addressLine2 = '';
1837
1838		return result;
1839	}
1840
1841	function setTemporaryPointMarker(lat, lng, icon){
1842		if (map.tempMarker === null) {
1843			map.tempMarker = new google.maps.Marker({
1844				position: new google.maps.LatLng(lat, lng),
1845				icon: icon,
1846				draggable: true,
1847				map: map.obj
1848			});
1849			google.maps.event.addListener(map.tempMarker, 'dragend', function (event) {
1850				$(".bootstrap-dialog input[name='latitude']").val(event.latLng.lat());
1851				$(".bootstrap-dialog input[name='longitude']").val(event.latLng.lng());
1852			});
1853		} else {
1854			map.tempMarker.setPosition(new google.maps.LatLng(lat, lng));
1855			map.tempMarker.setIcon(icon);
1856		}
1857		$(".bootstrap-dialog input[name='latitude']").val(lat);
1858		$(".bootstrap-dialog input[name='longitude']").val(lng);
1859
1860		$(".bootstrap-dialog .form-submit-group").removeClass("hidden");
1861	}
1862
1863	function getContents(cdata, refresh, allowExtraParams, forceLoadFeed) {
1864        if (!that.initialized) return false;
1865		var data = getQueryData(cdata, allowExtraParams);
1866		if (forceLoadFeed===true || refresh || changes(data, displayMode != 'feed' && displayMode != 'text')) {
1867            if (that.initialized && !that.initialGetContent && $.isEmptyObject(data)) {
1868                if(forceLoadFeed===true) loadFeed({viewMode: 'cards'},true);
1869				else return;
1870            }
1871            currentData = data;
1872			setFilterDisplay(data);
1873
1874			if (request && (request.readyState != 4)) {
1875				console.debug('aborting request');
1876				request.abort();
1877				request = false;
1878			}
1879
1880			if (displayMode == "calendar") {
1881                initCalendar(data);
1882			} else if (displayMode == "map") {
1883				if (!changes(data, true) && initialData) {
1884					map.markerAnimation = null;
1885					displayMarkers(initialData)
1886					initialData = null;
1887					map.markerAnimation = google.maps.Animation.DROP;
1888                } else {
1889                    loadMap(data)
1890                }
1891			} else if (displayMode == "search") {
1892				loadFeed(data, refresh)
1893			} else {
1894				loadFeed(data, refresh);
1895			}
1896		} else {
1897            contentLoadedCallback(null);
1898		}
1899	}
1900	function loadFeed(data, refresh){
1901        if (((currentState.item == '' && data.item != '') || (currentState.item != '' && data.item == '')) && $('body').find('.page-block[data-type="dataentry"]').length<=1){
1902            $('html, body').animate({scrollTop: 0}, 'slow');
1903        }
1904        if (refresh === undefined) refresh = false;
1905        data.refresh = refresh;
1906		request = $.ajax({
1907			type: 'post',
1908			data: data,
1909			beforeSend: function() {
1910				var $content = $page.find(".dynamic-content");
1911				if ($content.data('infinite')!==undefined) {
1912                    $content.data('infinite').destroy();
1913                    $content.data("infinite-inited", false);
1914				}
1915			},
1916			url: '/public/dynamic/' + pageID + '?src=loadFeed',
1917			success: function(d){
1918				var $content = $page.find(".dynamic-content");
1919				$content.html(d).data("inited", false).initElements();
1920				setState(data);
1921				if (data.item != '') {
1922					if (typeof mlpCallbackViewData !== 'undefined') mlpCallbackViewData([data.item]);
1923				}
1924				feedLoaded();
1925				if ($.lazyLoadXT !== undefined) $(window).lazyLoadXT();
1926				contentLoadedCallback(d);
1927			}
1928		});
1929	}
1930	function feedLoaded(){
1931
1932		var $swipeImages = $page.find(".photoswipe");
1933		if ($swipeImages.length) {
1934			$swipeImages.photoSwipe({enableMouseWheel: false, enableKeyboard: true});
1935		}
1936		var $content = $page.find(".dynamic-content");
1937		if ($page.hasClass('page')) {
1938            if (($content.find(".dynamic-details").length || $content.find(".business-card").length) && $viewSwitch !== null && $viewSwitch.length) {
1939                $viewSwitch.hide();
1940            } else if ($viewSwitch !== null && $viewSwitch.length) {
1941                $viewSwitch.show();
1942            }
1943        }
1944        var $pageTitle = $content.find('.page-title');
1945        if ($pageTitle.length && ($pageTitle.data('title') !== undefined)) {
1946            if ($page.hasClass('page')) document.title = $pageTitle.data('title');
1947			var $cr = $('.breadcrumb>li:last-child:not(.final-crumb)');
1948			if ($cr.length) {
1949				$cr.addClass('final-crumb').append(' '+$pageTitle.data('title'));
1950			}
1951        }
1952		var $addresses = $content.find('address[data-address]');
1953		if ($addresses.length){
1954			var md = mlpObject.getMobileDetect();
1955			var url = '';
1956			var isOsx = navigator.platform.indexOf('Mac') > -1;
1957			if (md.is('ios') || isOsx){
1958				if (md.version('iOS') >= 6){
1959					url = 'maps://maps.apple.com/maps?address='
1960				} else {
1961					url = 'http://maps.apple.com/maps?address='
1962				}
1963			} else {
1964				url = 'http://maps.google.com?q=';
1965			}
1966			$addresses.each(function(){
1967				var $this = $(this);
1968				var $div = $this.find('> div');
1969				if ($div.length){
1970					var $link = $('<a href="' + url + $this.data('address') + '" target="_blank"></a>');
1971					$link.html($div.html());
1972					$div.replaceWith($link);
1973				}
1974				$this.removeAttr('data-address');
1975			});
1976		}
1977
1978		if (infiniteScroll==1){
1979            var $content = $page.find(".dynamic-content");
1980            if ($content.data('infinite')!==undefined) {
1981                $content.data('infinite').destroy();
1982                $content.data("infinite-inited", false);
1983            }
1984            $content.on('click', ".infinite" + $page.data("id") + "-next", function(e){
1985            	e.preventDefault();
1986            });
1987			if (!$content.find("img").length) {
1988				feedImagesLoaded($content);
1989			} else {
1990				$content.imagesLoadedComp().progress(function(instance, image) {
1991					feedImagesLoaded($content);
1992				});
1993			}
1994		} else if (infiniteScroll==2) {
1995			$content.on('click', ".infinite" + $page.data("id") + "-next", function(e){
1996                e.preventDefault();
1997                $(this).off('click');
1998                Waypoint.refreshAll();
1999                if (!$content.find("img").length) {
2000                    feedImagesLoaded($content);
2001                } else {
2002					$content.imagesLoadedComp().progress(function(instance, image) {
2003						feedImagesLoaded($content);
2004					});
2005                }
2006            });
2007        }
2008	}
2009	function feedImagesLoaded($content){
2010		if (($content.data("infinite-inited") === undefined) || !$content.data("infinite-inited")) {
2011			if ($page.hasClass('page-block') || $page.hasClass('page')) {
2012                var element = $content.find('.infinity-container')[0];
2013                if (element === undefined) element = $content.closest('.infinity-container').parent()[0];
2014                if (element === undefined) element = $content[0];
2015                if ($(element).find('.infinity-items').length>0) {
2016					var icont = '.infinity-items';
2017				} else {
2018					var icont = $content.find('.row-fixed').length>0 ? '.row-fixed' : '.row:first-child'
2019				}
2020                if ($(element).find(icont).length==0) icont = '.dynamic-content';
2021                var infinite = new Waypoint.Infinite({
2022                    element: element,
2023                    itemContainer: icont,
2024                    items: ".infinite" + $page.data("id") + "-item,.infinite-item",
2025                    more: ".infinite" + $page.data("id") + "-next",
2026                    loadingClass: "loading",
2027                    dynamicPageObject: that,
2028                    onAfterPageLoad: function() {
2029						if ($.lazyLoadXT !== undefined) $(window).lazyLoadXT();
2030                        $content.data('inited', false).initElements();
2031                        if (infiniteScroll==2) {
2032                            $content.data('infinite').destroy();
2033                            $content.data("infinite-inited", false);
2034                        }
2035                        contentLoadedCallback();
2036                    }
2037                });
2038			} else {
2039                var icont = $content.find('.dynamic-content>.row').length>0 ? '.dynamic-content>.row' : '.row:first-child';
2040                var infinite = new Waypoint.Infinite({
2041                    element: $content.parent()[0],
2042                    itemContainer: icont,
2043                    items: ".infinite" + $page.data("id") + "-item",
2044                    more: ".infinite" + $page.data("id") + "-next",
2045                    loadingClass: "loading",
2046                    dynamicPageObject: that,
2047                    onAfterPageLoad: function() {
2048                        $(window).lazyLoadXT();
2049                        $content.data('inited', false).initElements();
2050                        if (infiniteScroll==2) {
2051                            $content.data('infinite').destroy();
2052                            $content.data("infinite-inited", false);
2053                        }
2054                    }
2055                });
2056			}
2057			$content.data("infinite-inited", true).data('infinite', infinite);
2058		} else {
2059			$content.data('infinite').updateInfinite();
2060		}
2061	}
2062	function displayMarkers(data){
2063		map.markers.forEach(function (m) {
2064			m.setMap(null);
2065		});
2066		map.markers = [];
2067
2068		map.customMarkers.forEach(function (m) {
2069			m.setMap(null);
2070		});
2071		map.customMarkers = [];
2072
2073		if (map.paths.length) hideElevationChart();
2074		map.paths.forEach(function (p) {
2075			p.setMap(null);
2076		});
2077		map.paths = [];
2078
2079		if (map.mergeMarkers != 'off') {
2080			$.each(map.markerClusters, function (i, mc){
2081				mc.clearMarkers();
2082				mc.setMap(null);
2083			});
2084		}
2085
2086		map.latLngBounds = new google.maps.LatLngBounds();
2087		var markertypes = [];
2088		var boundPointsCnt = 0;
2089		var fitboundpadding = null;
2090
2091		if (data && data !== null && data.points !== null && data.points.length) {
2092			$page.find(".map-error").remove();
2093
2094			data.points.forEach(function (m) {
2095
2096				if ((m.latitude !== null && m.longitude !== null) || ((m.path != false) && $.isArray(m.path) && (m.path.length > 0))) {
2097                    //console.log(m.latitude +','+m.longitude+','+m.path);
2098					var pos = new google.maps.LatLng(parseFloat(m.latitude), parseFloat(m.longitude));
2099					if ((m.icon !== false) && ($.inArray(m.icon, markertypes) === -1)) markertypes.push(m.icon);
2100					if ((m.path != false) && $.isArray(m.path) && (m.path.length > 0)) {
2101						var llbounds = new google.maps.LatLngBounds();
2102						var path, path2;
2103						if (m.trackType !== undefined && m.trackType === 'polygon') {
2104							path = new google.maps.Polygon({
2105								map: map.obj,
2106								strokeWeight: 3,
2107								paths: [m.path],
2108								fillColor: (m.color !== null) ? m.color : '#000000',
2109								strokeColor: (m.color !== null) ? m.color : '#000000'
2110							});
2111							path2 = false;
2112						} else {
2113							path2 = new google.maps.Polyline({
2114								map: map.obj,
2115								strokeWeight: 7,
2116								path: m.path,
2117								strokeOpacity: 0.6,
2118								strokeColor: '#000000'
2119							});
2120							path = new google.maps.Polyline({
2121								map: map.obj,
2122								strokeWeight: 4,
2123								path: m.path,
2124								strokeColor: (m.color !== null) ? m.color : '#000000'
2125							});
2126						}
2127
2128						$.each(m.path, function (i, e) {
2129							var latLng = new google.maps.LatLng(e.lat, e.lng);
2130							map.latLngBounds.extend(latLng);
2131							llbounds.extend(latLng);
2132							boundPointsCnt++;
2133
2134							if (e.symbol) {
2135								var trackPointMarker = new google.maps.Marker({
2136									position: latLng,
2137									title: e.name !== null ? e.name : '',
2138									icon: e.symbol,
2139									shadow: null,
2140									map: map.obj
2141								});
2142								if (e.name !== null) {
2143									google.maps.event.addListener(trackPointMarker, 'click', function () {
2144										var markup = '';
2145										if ((e.heading !== undefined && e.heading !== null) ||
2146											(e.speed !== undefined && e.speed !== null) ||
2147											(e.alt !== undefined && e.alt !== null && e.alt != 0)) {
2148											markup += '<div class="details">';
2149											if (e.heading !== undefined && e.heading !== null) {
2150												markup += '<div class="info"><div><i class="fa fa-compass"></i><strong>' + mlpLanguage.heading + ':</strong> ' + e.heading + '&deg;</div></div>';
2151											}
2152											if (e.speed !== undefined && e.speed !== null) {
2153												markup += '<div class="info"><div><i class="fa fa-tachometer"></i><strong>' + mlpLanguage.speed + ':</strong> ' + e.speed + ' km/h</div></div>';
2154											}
2155											if (e.alt !== undefined && e.alt !== null && e.alt != 0) {
2156												markup += '<div class="info"><div><i class="fa fa-long-arrow-up"></i><strong>' + mlpLanguage.altitude + ':</strong> ' + e.alt + ' m</div></div>';
2157											}
2158											markup += '</div>';
2159										}
2160										if (e.description !== undefined && e.description !== null) {
2161											markup += '<p>' + e.description + '</p>';
2162										}
2163
2164										showInfoWindow(markup, 'html', e.name);
2165									});
2166								}
2167							}
2168						});
2169
2170						path.startPoint = new google.maps.LatLng(m.path[0].lat, m.path[0].lng);
2171						path.endPoint = new google.maps.LatLng(m.path[m.path.length - 1].lat, m.path[m.path.length - 1].lng);
2172						path.data = m;
2173						path.centerPoint = llbounds.getCenter();
2174
2175						google.maps.event.addListener(path, 'mouseover', function () {
2176							this.setOptions({strokeWeight: 6, strokeOpacity: 0.6});
2177						});
2178						google.maps.event.addListener(path, 'mouseout', function () {
2179							this.setOptions({strokeWeight: 4, strokeOpacity: 1});
2180						});
2181						map.paths.push(path);
2182						if (path2) map.paths.push(path2);
2183						google.maps.event.addListener(path, 'click', function () {
2184							map.destination = this.startPoint;
2185							showInfoWindow(this.data, 'path');
2186						});
2187					} else {
2188						map.latLngBounds.extend(pos);
2189						boundPointsCnt++;
2190						var marker;
2191						if (map.mergeMarkers == 'off') {
2192							if (m.icon === false) {
2193								marker = new google.maps.Marker({
2194									position: pos,
2195									map: map.obj,
2196									title: m.name,
2197									animation: map.markerAnimation
2198								});
2199							} else {
2200								marker = new google.maps.Marker({
2201									position: pos,
2202									map: map.obj,
2203									title: m.name,
2204									icon: m.icon,
2205									animation: map.markerAnimation
2206								});
2207							}
2208						} else {
2209							if (m.icon === false) {
2210								marker = new google.maps.Marker({
2211									position: pos,
2212									title: m.name,
2213									animation: map.markerAnimation
2214								});
2215							} else {
2216								marker = new google.maps.Marker({
2217									position: pos,
2218									title: m.name,
2219									icon: m.icon,
2220									animation: map.markerAnimation
2221								});
2222							}
2223						}
2224
2225						marker.data = m;
2226						google.maps.event.addListener(marker, 'click', function () {
2227							map.destination = this.getPosition();
2228							showInfoWindow(this.data);
2229						});
2230						map.markers.push(marker);
2231					}
2232				}
2233
2234				if (data.points.length == 1 && map.pointViewMode){
2235					google.maps.event.trigger(marker, 'click');
2236				}
2237
2238                if(m.boundcoordinates){
2239                    //map.latLngBounds.extend(latLng);
2240                    //map.obj.fitBounds(map.latLngBounds);
2241
2242                    boundcoordinates = JSON.parse(m.boundcoordinates);
2243                    if (boundcoordinates.nelat) {
2244                        var sw = new google.maps.LatLng(boundcoordinates.swlat,boundcoordinates.swlng);
2245                        var ne = new google.maps.LatLng(boundcoordinates.nelat,boun
2245dcoordinates.nelng);
2246                        //var bounds = new google.maps.LatLngBounds();
2247
2248                        map.latLngBounds.extend(sw);
2249                        map.latLngBounds.extend(ne);
2250                        //map.obj.fitBounds(map.latLngBounds,0);
2251						fitboundpadding = 0;
2252                    }
2253                }
2254			});
2255			if (map.paths.length==2 && data.points[0].path && data.points[0].path.length){
2256				displayElevationChart(data.points[0]);
2257			}
2258		}
2259
2260		if (data !== null && data.customPoints !== null && data.customPoints.length) {
2261			data.customPoints.forEach(function (m) {
2262				var pos = new google.maps.LatLng(parseFloat(m.latitude), parseFloat(m.longitude));
2263
2264				map.latLngBounds.extend(pos);
2265				boundPointsCnt++;
2266				var marker;
2267				marker = new google.maps.Marker({
2268					position: pos,
2269					map: map.obj,
2270					title: m.name,
2271					icon: m.icon,
2272					animation: google.maps.Animation.DROP
2273				});
2274
2275				marker.data = m;
2276				google.maps.event.addListener(marker, 'click', function () {
2277					map.destination = this.getPosition();
2278					showInfoWindow(this.data);
2279				});
2280				map.customMarkers.push(marker);
2281
2282				if (data.customPoints.length == 1 && map.pointViewMode){
2283					google.maps.event.trigger(marker, 'click');
2284				}
2285			});
2286		}
2287		if (!boundPointsCnt && map.currentLocation) map.latLngBounds.extend(map.currentLocation);
2288		switch (map.mergeMarkers) {
2289			case 'all':
2290				map.markerClusters['default'] = new MarkerClusterer(map.obj, map.markers);
2291				break;
2292			case 'same':
2293				var markers = {};
2294				$.each(markertypes, function(i, e){
2295					markers[e] = []
2296				});
2297				$.each(map.markers, function(i, marker) {
2298					if (marker.data !== undefined) markers[marker.data.icon].push(marker);
2299				});
2300				$.each(markertypes, function(i, e){
2301					map.markerClusters[e] = new MarkerClusterer(map.obj, markers[e], {styles: [{url: e, textColor: 'black', anchorText: [-20, 0], anchorIcon: [-16,0], textSize: 13, width: 32, height: 37}]});
2302				});
2303				break;
2304		}
2305		if (map.latLngBounds.isEmpty()) {
2306			var $map = $page.find(".dynamic-content");
2307			$('<div class="map-error"><h5>' + mlpLanguage.notFound + '</h5></div>').appendTo($map);
2308		} else if (map.defaultPosition && ((map.centerLng && map.centerLat) || map.defaultZoom)) {
2309            if (map.centerLng && map.centerLat) map.obj.setCenter({lat: map.centerLat, lng: map.centerLng});
2310            if (map.defaultZoom) map.obj.setZoom(map.defaultZoom);
2311            map.defaultPosition = false;
2312        } else if (!map.directionDisplayActive) {
2313			map.obj.fitBounds(map.latLngBounds,fitboundpadding);
2314		}
2315
2316		contentLoadedCallback(data);
2317	}
2318
2319	function showInfoWindow(data, type){
2320		var cont = '';
2321		var dialogTitle = '';
2322		if (type == "html"){
2323			cont = data;
2324		} else {
2325			if (data.info && (data.info.length > 0)) {
2326				cont = data.info;
2327			} else {
2328				if (data.image && (data.image.length > 0)) cont = cont + '<img src="' + thumbnailGeneratorPath + '?src=' + encodeURIComponent(data.image) + '&w=400&h=150" class="img-responsive" />';
2329				if (data.name && (data.name.length > 0)) {
2330					dialogTitle = data.name;
2331				}
2332				if (data.company && (data.company.length > 0)) {
2333					dialogTitle = dialogTitle ? dialogTitle + " <small>" + data.company + "</small>" : data.company;
2334				}
2335				if ((data.infoRow_valid_from !== undefined && data.infoRow_valid_from) ||
2336                    (data.infoRow_address !== undefined && data.infoRow_address) ||
2337					(data.infoRow_telephone !== undefined && data.infoRow_telephone) ||
2338					(data.infoRow_cellular !== undefined && data.infoRow_cellular) ||
2339					(data.infoRow_length !== undefined && data.infoRow_length) ||
2340					(data.infoRow_tags !== undefined && data.infoRow_tags)) {
2341					cont += '<div class="details">';
2342					if (data.infoRow_valid_from !== undefined && data.infoRow_valid_from) cont = cont + data.infoRow_valid_from;
2343					if (data.infoRow_address !== undefined && data.infoRow_address) cont = cont + data.infoRow_address;
2344					if (data.infoRow_telephone !== undefined && data.infoRow_telephone) cont = cont + data.infoRow_telephone;
2345					if (data.infoRow_cellular !== undefined && data.infoRow_cellular) cont = cont + data.infoRow_cellular;
2346					if (data.infoRow_length !== undefined && data.infoRow_length) cont = cont + data.infoRow_length;
2347					if (data.infoRow_tags !== undefined && data.infoRow_tags) cont = cont + data.infoRow_tags;
2348					cont += '</div>';
2349				}
2350				if (data.short_text !== undefined && data.short_text) cont = cont + data.short_text;
2351			}
2352			cont = cont + '<div class="btn-toolbar">';
2353
2354			if (data.links && (data.links.length > 0)) {
2355				data.links.forEach(function (e) {
2356					var $tmp = $(e).addClass("btn").addClass("btn-primary").attr('target','_blank');
2357					$tmp.html('<i class="fa fa-external-link"></i> ' + $tmp.text());
2358					cont += $tmp.outer();
2359				});
2360			}
2361			if (type == 'path' && !map.disableDirectionsToHere) {
2362				cont = cont + '<a href="#mapdialog_' + pageID + '" data-rel="popup" data-refrsh="" class="directions-to-here btn btn-primary" data-longitude="' + data.longitude + '" data-latitude="' + data.latitude + '">' +
2363					'<i class="fa fa-compass"></i> ' + mlpLanguage.routeToStart +
2364					'</a>';
2365			} else if(!map.disableDirectionsToHere) {
2366				cont = cont + '<a href="#mapdialog_' + pageID + '" data-rel="popup" data-refrsh="" class="btn btn-primary directions-to-here" data-longitude="' + data.longitude + '" data-latitude="' + data.latitude + '">' +
2367					'<i class="fa fa-compass"></i> ' + mlpLanguage.routeHere + '</a>';
2368			}
2369			if (data.customPointId !== undefined && data.customPointId){
2370				cont = cont + '<button class="btn btn-primary btn-edit" data-id="' + data.customPointId + '">' +
2371					'<i class="fa fa-edit"></i> ' + mlpLanguage.edit + '</button>';
2372				cont = cont + '<button class="btn btn-danger btn-delete" data-id="' + data.customPointId + '">' +
2373					'<i class="fa fa-trash"></i> ' + mlpLanguage.delete + '</button>';
2374			}
2375			cont += '<div class="btn-group pull-right">' +
2376				'<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">' +
2377				(type == 'path'?mlpLanguage.download:mlpLanguage.extra) + ' <span class="caret"></span>' +
2378				'</button>' +
2379				'<ul class="dropdown-menu dropdown-menu-right">';
2380			if (type != 'path') {
2381				if (mlpObject.isIos()) {
2382					cont = cont + '<li><a href="//maps.apple.com/?q=' + data.latitude + ',' + data.longitude + '" target="_blank"><i class="fa fa-external-link"></i> ' + mlpLanguage.openInNavApp + '</a></li>';
2383				} else {
2384					cont = cont + '<li><a href="//maps.google.com/?q=' + data.latitude + ',' + data.longitude + '" target="_blank"><i class="fa fa-external-link"></i> ' + mlpLanguage.openInNavApp + '</a></li>';
2385				}
2386			} else {
2387				cont += '<li><a data-ajax="false" class="btn btn-default" href="/public/downloadTrack/' + pageID + '?format=gpx&track_id=' + data.id + '"><i class="fa fa-download"></i> ' + mlpLanguage.download + ': GPX</a></li>';
2388				cont += '<li><a data-ajax="false" class="btn btn-default" href="/public/downloadTrack/' + pageID + '?format=kml&track_id=' + data.id + '"><i class="fa fa-download"></i> ' + mlpLanguage.download + ': KML</a></li>';
2389			}
2390			cont += '</ul></div>';
2391			cont = cont + '</div>';
2392		}
2393
2394		BootstrapDialog.show({
2395			title: dialogTitle ? dialogTitle : mlpLanguage.info,
2396			message: cont,
2397			type: BootstrapDialog.TYPE_PRIMARY,
2398			onshown: function(obj){
2399				obj.$modalBody.on('click', '.directions-to-here', function (e) {
2400					e.preventDefault();
2401					displayRoutePlanner();
2402				});
2403				obj.$modalBody.on('click', '.btn-edit', function (e) {
2404					e.preventDefault();
2405					initCustomMarkerPicker($(this).data("id"));
2406
2407					obj.close();
2408				});
2409				obj.$modalBody.on('click', '.btn-delete', function (e) {
2410					e.preventDefault();
2411					var $btn = $(this);
2412
2413					BootstrapDialog.confirm({
2414						title: mlpLanguage.question,
2415						message: mlpLanguage.areYouSure,
2416						type: BootstrapDialog.TYPE_DANGER,
2417						btnCancelLabel: mlpLanguage.cancel,
2418						btnOKLabel: mlpLanguage.ok,
2419						callback: function(result) {
2420							if (result) {
2421								$.ajax({
2422									type: 'post',
2423									data: { action: 'delete', id: $btn.data('id') },
2424									url: "/public/customMarker/" + $page.data('id'),
2425									success: function(d){
2426										getContents({}, true);
2427										BootstrapDialog.closeAll();
2428									}
2429								});
2430
2431								obj.close();
2432							}
2433						}
2434					});
2435				});
2436			}
2437		});
2438	}
2439	function loadMap(data){
2440        request = $.ajax({
2441			type: 'post',
2442			data: data,
2443			dataType: 'json',
2444			url: '/public/dynamic/' + pageID + '?src=loadMap',
2445			success: function(d){
2446				displayMarkers(d);
2447				setState(data);
2448				contentLoadedCallback(d);
2449			}
2450		});
2451	}
2452	function initCalendar(data){
2453        var defaultView = "calendar";
2454
2455        $container.html('<div>' +
2456            '<div id="calendar' + pageID + '"></div>' +
2457            '</div>');
2458
2459
2460        var events = {
2461            url: '/public/events/' + pageID,
2462            type: 'post',
2463            data: data,
2464            error: function () {
2465            }
2466        };
2467        var limit = limitItems !== null ? limitItems : 5;
2468
2469
2470        var today = new Date();
2471        var dd = today.getDate();
2472        var mm = today.getMonth()+1;
2473        var yyyy = today.getFullYear();
2474        if(dd<10)
2475        {
2476            dd='0'+dd;
2477        }
2478        if(mm<10)
2479        {
2480            mm='0'+mm;
2481        }
2482        today = yyyy+'-'+mm+'-'+dd;
2483
2484        var calendarEl = document.getElementById('calendar' + pageID);
2485
2486        var calendar = new FullCalendar.Calendar(calendarEl, {
2487            locale: language,
2488            initialView: 'dayGridMonth',
2489            initialDate: today,
2490            headerToolbar: {
2491                left: 'prev,next today',
2492                center: 'title',
2493                right: 'dayGridMonth,timeGridWeek,timeGridDay'
2494            },
2495            eventSources: [{
2496                url: '/public/events/' + pageID,
2497                //type: 'post',
2498                method: 'POST',
2499                //data: data,
2500                extraParams: data,
2501                failure: function() {
2502                    alert('there was an error while fetching events!');
2503                },
2504            }],
2505			eventTimeFormat:{
2506                hour: 'numeric',
2507                minute: '2-digit',
2508                meridiem: false
2509            },
2510            /*eventRender: function (event, element, view) {
2511                $(element).each(function () {
2512                    $(this).attr('date-num', event.start.format('YYYY-MM-DD'));
2513                });
2514            },
2515            eventAfterAllRender: (limit===0 ? function(view){
2516                for( cDay = view.start.clone(); cDay.isBefore(view.end) ; cDay.add(1, 'day') ){
2517                    var dateNum = cDay.format('YYYY-MM-DD');
2518                    var dayEl = $('.fc-day[data-date="' + dateNum + '"]');
2519                    var day = $('.fc-day-number[data-date="' + dateNum + '"]');
2520                    var eventCount = $('.fc-event[date-num="' + dateNum + '"]').length;
2521                    if(eventCount){
2522                        dayEl.addClass('fc-has-events');
2523                        day.html('<span>'+day.text()+'</span>').addClass('fc-has-events');
2524                        dayEl.attr({"data-toggle" : "tooltip", "data-container" : 'body', "title" : mlpLanguage.clickForMore});
2525                        var html = '<span class="event-count">' +
2526                            eventCount + ' ' + (eventCount>1 ? mlpLanguage.events : mlpLanguage.event) +
2527                            '</span>';
2528                        dayEl.append(html);
2529                    }
2530                }
2531                $('[data-toggle="tooltip"]').tooltip();
2532            } : null),
2533
2534            dayClick: function(date, jsEvent, view) {
2535                if (dayClickCallback(date)) {
2536                    $(this).closest('.calendar').find('.fc-state-active').removeClass('fc-state-active');
2537                    $(this).addClass('fc-state-active');
2538                }
2539            },*/
2540            eventClick: function (info) {
2541                info.jsEvent.preventDefault();
2542                displayEventDialog(info.event.id, info.event.title);
2543            },
2544
2545        });
2546
2547        calendar.render();
2548
2549/*
2550		if (properties.viewMode=='auto') {
2551            var defaultView = $(window).width() < 768 ? "agenda" : "calendar";
2552		} else if (currentState.viewMode=='table') {
2553            var defaultView = "calendar";
2554		} else {
2555            var defaultView = "agenda";
2556		}
2557        var switchable = !$container.parent().hasClass('no-view-switch');
2558        if (switchable) {
2559            var headerOptions = {
2560                left: 'prev,next',
2561                center: 'title',
2562                right: 'month,basicWeek,basicDay'
2563            };
2564            if (defaultView == "agenda") {
2565                $container.html('<div>' +
2566                    '<ul class="nav nav-tabs nav-pills nav-justified" role="tablist">' +
2567                    '<li role="presentation"><a href="#calendar' + pageID + '" aria-controls="calendar' + pageID + '" role="tab" data-toggle="tab"><i class="fa fa-fw fa-calendar"></i> ' + mlpLanguage.calendar + '</a></li>' +
2568                    '<li role="presentation" class="active"><a href="#agenda' + pageID + '" aria-controls="agenda' + pageID + '" role="tab" data-toggle="tab"><i class="fa fa-fw fa-list"></i> ' + mlpLanguage.agenda + '</a></li>' +
2569                    '</ul>' +
2570                    '<div class="tab-content">' +
2571                    '<div role="tabpanel" class="tab-pane tab-calendar" id="calendar' + pageID + '"><div class="calendar"></div></div>' +
2572                    '<div role="tabpanel" class="tab-pane active" id="agenda' + pageID + '"><div class="agenda"></div></div>' +
2573                    '</div>' +
2574                    '</div>');
2575            } else {
2576                $container.html('<div>' +
2577                    '<ul class="nav nav-tabs nav-pills nav-justified" role="tablist">' +
2578                    '<li role="presentation" class="active"><a href="#calendar' + pageID + '" aria-controls="calendar' + pageID + '" role="tab" data-toggle="tab"><i class="fa fa-fw fa-calendar"></i> ' + mlpLanguage.calendar + '</a></li>' +
2579                    '<li role="presentation"><a href="#agenda' + pageID + '" aria-controls="agenda' + pageID + '" role="tab" data-toggle="tab"><i class="fa fa-fw fa-list"></i> ' + mlpLanguage.agenda + '</a></li>' +
2580                    '</ul>' +
2581                    '<div class="tab-content">' +
2582                    '<div role="tabpanel" class="tab-pane tab-calendar active" id="calendar' + pageID + '"><div class="calendar"></div></div>' +
2583                    '<div role="tabpanel" class="tab-pane" id="agenda' + pageID + '"><div class="agenda"></div></div>' +
2584                    '</div>' +
2585                    '</div>');
2586            }
2587		} else {
2588            var headerOptions = {
2589                left: 'prev',
2590                center: 'title',
2591                right: 'next'
2592            };
2593            if (defaultView == "agenda") {
2594                $container.html('<div>' +
2595                    '<div class="agenda"></div>' +
2596                    '</div>');
2597            } else {
2598                $container.html('<div>' +
2599                    '<div class="calendar"></div>' +
2600                    '</div>');
2601            }
2602		}*/
2603
2604
2605
2606        /*
2607		$calendar = $container.find(".calendar").fullCalendar({
2608			lang: language,
2609			header: headerOptions,
2610			eventLimit: limit,
2611			contentHeight: 'auto',
2612            eventRender: function (event, element, view) {
2613                $(element).each(function () {
2614                    $(this).attr('date-num', event.start.format('YYYY-MM-DD'));
2615                });
2616            },
2617            eventAfterAllRender: (limit===0 ? function(view){
2618                for( cDay = view.start.clone(); cDay.isBefore(view.end) ; cDay.add(1, 'day') ){
2619                    var dateNum = cDay.format('YYYY-MM-DD');
2620                    var dayEl = $('.fc-day[data-date="' + dateNum + '"]');
2621                    var day = $('.fc-day-number[data-date="' + dateNum + '"]');
2622                    var eventCount = $('.fc-event[date-num="' + dateNum + '"]').length;
2623                    if(eventCount){
2624                        dayEl.addClass('fc-has-events');
2625                        day.html('<span>'+day.text()+'</span>').addClass('fc-has-events');
2626						dayEl.attr({"data-toggle" : "tooltip", "data-container" : 'body', "title" : mlpLanguage.clickForMore});
2627                        var html = '<span class="event-count">' +
2628                            eventCount + ' ' + (eventCount>1 ? mlpLanguage.events : mlpLanguage.event) +
2629                            '</span>';
2630                        dayEl.append(html);
2631                    }
2632                }
2633                $('[data-toggle="tooltip"]').tooltip();
2634            } : null),
2635			loading: function(isLoading, view){
2636				if (!isLoading){
2637					displayAgenda(view);
2638				}
2639			},
2640            dayClick: function(date, jsEvent, view) {
2641				if (dayClickCallback(date)) {
2642                    $(this).closest('.calendar').find('.fc-state-active').removeClass('fc-state-active');
2643                    $(this).addClass('fc-state-active');
2644				}
2645            },
2646			eventClick: function (calEvent) {
2647				displayEventDialog(calEvent.id, calEvent.title);
2648			},
2649			eventSources: [events]
2650		});
2651		*/
2652	}
2653	function displayAgenda(view){
2654		var $agendaWrapper = $container.find(".agenda");
2655		var i, j, event, dayRange, dayString, startString, endString, dayTmp, eventTmp, dayMarkup;
2656		var events = $calendar.fullCalendar('clientEvents');
2657		var title = view.title;
2658		var start = view.intervalStart;
2659		var end = view.intervalEnd;
2660
2661		var currDate = start.clone().startOf('day').add(-1, 'days');
2662		var lastDate = end.clone().startOf('day').add(-1, 'days');
2663
2664		for (i = 0; i < events.length; i++){
2665			if (events[i].end === null) events[i].end = events[i].start;
2666			events[i].eventRange = moment.range(events[i].start, events[i].end);
2667		}
2668		var agenda = [];
2669		var hasEvents = false;
2670		var today = moment();
2671		while (currDate.add(1, 'days').diff(lastDate) < 0) {
2672			dayString = currDate.format("YYYY-MM-DD");
2673			dayTmp = {
2674				date: dayString,
2675				day: currDate.format("DD"),
2676				weekday: currDate.format("dddd"),
2677				events: []
2678			};
2679			dayRange = moment(dayString);
2680			for (i = 0; i < events.length; i++){
2681				event = events[i];
2682				if (event.start !== null && event.end !== null) {
2683					eventTmp = {};
2684					startString = event.eventRange.start.format("YYYY-MM-DD");
2685					endString = event.eventRange.end.format("YYYY-MM-DD");
2686					if (event.eventRange.contains(dayRange) || dayString == startString || dayString == endString) {
2687						if (dayString == startString) {
2688							eventTmp.startTime = event.eventRange.start.format("HH:mm");
2689						} else {
2690							eventTmp.startTime = "00:00";
2691						}
2692						eventTmp.title = event.title;
2693						eventTmp.id = event.id;
2694						eventTmp.description = event.description;
2695						eventTmp.past = event.end.isBefore(today);
2696						dayTmp.events.push(eventTmp);
2697
2698						hasEvents = true;
2699					}
2700				}
2701			}
2702			agenda.push(dayTmp);
2703		}
2704		$agendaWrapper.html("");
2705		var $agendaHeader = $('<div class="agenda-header">' +
2706			'<div class="btn-toolbar">' +
2707			'<div class="btn-group">' +
2708			'<button type="button" class="btn btn-primary btn-prev"><i class="fa fa-angle-left"></i></button>' +
2709			'<button type="button" class="btn btn-primary btn-next"><i class="fa fa-angle-right"></i></button>' +
2710			'</div>' +
2711			'</div>' +
2712			title + '</div>').appendTo($agendaWrapper);
2713		if (hasEvents){
2714			for (i = 0; i < agenda.length; i++){
2715				dayTmp = agenda[i];
2716				if (dayTmp.events.length){
2717					dayMarkup = '<article>' +
2718						'<div class="date row">' +
2719						'<div class="col-xs-2 day-number">' + dayTmp.day + '</div>' +
2720						'<div class="col-xs-10 day-name">' + dayTmp.weekday + '</div>' +
2721						'</div>' +
2722						'<div class="day-events">';
2723					for (j = 0; j < dayTmp.events.length; j++){
2724						dayMarkup += '<div class="row">' +
2725							'<div class="col-xs-2 time">' + dayTmp.events[j].startTime + '</div>' +
2726							'<div class="col-xs-10 event-name">' +
2727							'<button type="button" class="btn ' + (dayTmp.events[j].past ? "btn-default" : "btn-primary") + ' btn-block" data-id="' + dayTmp.events[j].id + '">' + dayTmp.events[j].title + '</button>' +
2728							'</div>' +
2729							'</div>';
2730					}
2731					dayMarkup += '</div>' +
2732						'</article>';
2733					$(dayMarkup).appendTo($agendaWrapper);
2734				}
2735			}
2736		} else {
2737			$('<div class="alert alert-info">' + mlpLanguage.notFound + '</div>').appendTo($agendaWrapper);
2738		}
2739		$agendaHeader.find(".btn-prev").click(function(e){
2740			e.preventDefault();
2741			$calendar.fullCalendar('prev');
2742		});
2743		$agendaHeader.find(".btn-next").click(function(e){
2744			e.preventDefault();
2745			$calendar.fullCalendar('next');
2746		});
2747		$agendaWrapper.find("article .btn").click(function(e){
2748			e.preventDefault();
2749			displayEventDialog($(this).data("id"), $(this).text());
2750		});
2751
2752	}
2753	function displayEventDialog(id, title){
2754		$.ajax({
2755			url: '/public/eventInfo/' + pageID,
2756			type: 'post',
2757			dataType: 'json',
2758			data: {qr: mlpObject.getQr(), uuid: mlpObject.getUuid(), event: id},
2759			success: function (d) {
2760				BootstrapDialog.show({
2761					title: title,
2762					message: d.text,
2763					type: BootstrapDialog.TYPE_PRIMARY
2764				});
2765			}
2766		})
2767	}
2768	function setRangeValue($obj, value) {
2769		if (value)
2770		var x = value.split('-');
2771		if (x.length == 2) {
2772			$obj.first().val(Math.min.apply(Math, x));
2773			$obj.last().val(Math.max.apply(Math, x))
2774		}
2775	}
2776	function getHash(data) {
2777		function addToHash(data, current, prop) {
2778			return data[prop] != undefined && (current[prop].toString().length>0 || data[prop].toString().length>0); // && current[prop] != data[prop];
2779		}
2780		var hash = '';
2781		if (addToHash(data, currentState, 'item')) hash = hash+'item='+data.item;
2782        if (addToHash(data, currentState, 'range')) hash = hash + (hash.length > 0 ? '&' : '') + 'range=' + data.range;
2783        if (!ignoreViewMode && addToHash(data, currentState, 'viewMode')) hash = hash + (hash.length > 0 ? '&' : '') + 'viewMode=' + data.viewMode;
2784        if (addToHash(data, currentState, 'rating')) hash = hash + (hash.length > 0 ? '&' : '') + 'rating=' + data.rating;
2785        if (addToHash(data, currentState, 'clientGroup')) hash = hash + (hash.length > 0 ? '&' : '') + 'clientGroup=' + data.clientGroup;
2786        if (addToHash(data, currentState, 'search')) hash = hash + (hash.length > 0 ? '&' : '') + 'search=' + data.search;
2787        if (addToHash(data, currentState, 'start')) hash = hash + (hash.length > 0 ? '&' : '') + 'start=' + data.start;
2788        if (addToHash(data, currentState, 'end')) hash = hash + (hash.length > 0 ? '&' : '') + 'end=' + data.end;
2789        if (addToHash(data, currentState, 'createdStart')) hash = hash + (hash.length > 0 ? '&' : '') + 'createdStart=' + data.createdStart;
2790        if (addToHash(data, currentState, 'createdEnd')) hash = hash + (hash.length > 0 ? '&' : '') + 'createdEnd=' + data.createdEnd;
2791        if (addToHash(data, currentState, 'hidden')) hash = hash + (hash.length > 0 ? '&' : '') + 'hidden=' + data.hidden;
2792        if (addToHash(data, currentState, 'marker')) hash = hash + (hash.length > 0 ? '&' : '') + 'marker=' + data.marker;
2793        if (addToHash(data, currentState, 'favorite')) hash = hash + (hash.length > 0 ? '&' : '') + 'favorite=' + data.favorite;
2794        if (addToHash(data, currentState, 'visited')) hash = hash + (hash.length > 0 ? '&' : '') + 'visited=' + data.visited;
2795        if (addToHash(data, currentState, 'open')) hash = hash + (hash.length > 0 ? '&' : '') + 'open=' + data.open;
2796        if (addToHash(data, currentState, 'month')) hash = hash + (hash.length > 0 ? '&' : '') + 'month=' + data.month;
2797        if (addToHash(data, currentState, 'difficulty')) hash = hash + (hash.length > 0 ? '&' : '') + 'difficulty=' + data.difficulty;
2798        if (addToHash(data, currentState, 'related')) hash = hash + (hash.length > 0 ? '&' : '') + 'related=' + data.related;
2799        if (addToHash(data, currentState, 'datasource')) hash = hash + (hash.length > 0 ? '&' : '') + 'datasource=' + data.datasource;
2800        if (addToHash(data, currentState, 'attributes')) hash = hash + (hash.length > 0 ? '&' : '') + 'attributes=' + urlencode(data.attributes);
2801        if (addToHash(data, currentState, 'sort_attr')) hash = hash + (hash.length > 0 ? '&' : '') + 'sort_attr=' + data.sort_attr;
2802        if (addToHash(data, currentState, 'sort_direction')) hash = hash + (hash.length > 0 ? '&' : '') + 'sort_direction=' + (data.sort_direction && data.sort_direction!='false' ?true:false);
2803        if (addToHash(data, currentState, 'distance') && data.distance != '0,0') hash = hash + (hash.length > 0 ? '&' : '') + 'distance=' + urlencode(data.distance);
2804        if (addToHash(data, currentState, 'price') && data.price != '0,0') hash = hash + (hash.length > 0 ? '&' : '') + 'price=' + urlencode(data.price);
2805        if (addToHash(data, currentState, 'current_page')) hash = hash + (hash.length > 0 ? '&' : '') + 'current_page=' + data.current_page;
2806        if (addToHash(data, currentState, 'dataStoreMarkerId')) hash = hash + (hash.length > 0 ? '&' : '') + 'dataStoreMarkerId=' + data.dataStoreMarkerId;
2807        if (addToHash(data, currentState, 'dataStoreId')) hash = hash + (hash.length > 0 ? '&' : '') + 'dataStoreId=' + data.dataStoreId;
2808		if (data.coords !== undefined && ((data.coords.latitude && data.coords.latitude != '' && data.coords.longitude && data.coords.longitude != '') || (currentState.coords.latitude && currentState.coords.latitude != '' && currentState.coords.longitude && currentState.coords.longitude != ''))){
2809			hash = hash + (hash.length >
2809 0 ? '&' : '') + 'coords.latitude=' + data.coords.latitude + '&coords.longitude=' + data.coords.longitude;
2810		}
2811		var tmp;
2812		if (addToHash(data, currentState, 'tag')) {
2813			if (typeof data.tag === 'string') {
2814				tmp = data.tag;
2815			} else {
2816				tmp = data.tag.join(',');
2817			}
2818			hash = hash+(hash.length>0 ? '&' : '')+'tag='+tmp;
2819		}
2820		if (addToHash(data, currentState, 'category')) {
2821			if (typeof data.category === 'string') {
2822				tmp = data.category;
2823			} else {
2824				tmp = data.category.join(',');
2825			}
2826			hash = hash+(hash.length>0 ? '&' : '')+'category='+tmp;
2827		}
2828		var pageHash = $page && $page.data('friendly-id') !== undefined ? '#' + $page.data('friendly-id') : '#block_' + pageID;
2829		return pageHash + (hash.length > 0 ? '?' + hash : '');
2830	}
2831	function changes(d, ignore_page) {
2832		if (ignore_page===undefined) ignore_page = false;
2833		return !that.initialized || (d.item !== undefined && d.item != currentState.item) ||
2834			(!ignore_page && d.current_page !== undefined && (d.current_page != currentState.current_page)) ||
2835			(d.tag !== undefined && d.tag != currentState.tag) ||
2836			(d.category !== undefined && d.category != currentState.category) ||
2837			(!ignoreViewMode && displayMode === 'feed' && d.viewMode !== undefined && d.viewMode != currentState.viewMode) ||
2838			(d.range !== undefined && d.range != currentState.range) ||
2839			(d.rating !== undefined && d.rating != currentState.rating) ||
2840			(d.clientGroup !== undefined && d.clientGroup != currentState.clientGroup) ||
2841			(d.favorite !== undefined && d.favorite != currentState.favorite) ||
2842			(d.marker !== undefined && d.marker != currentState.marker) ||
2843			(d.visited !== undefined && d.visited != currentState.visited) ||
2844			(d.open !== undefined && d.open != currentState.open) ||
2845			(d.difficulty !== undefined && d.difficulty != currentState.difficulty) ||
2846			(d.related !== undefined && d.related != currentState.related) ||
2847			(d.datasource !== undefined && d.datasource != currentState.datasource) ||
2848			(d.distance !== undefined && d.distance != currentState.distance) ||
2849            (d.price !== undefined && d.price != currentState.price) ||
2850            (d.month !== undefined && d.month != currentState.month) ||
2851			(d.hidden !== undefined && d.hidden != currentState.hidden) ||
2852			(d.search !== undefined && d.search != currentState.search) ||
2853			(d.start !== undefined && d.start != currentState.start) ||
2854			(d.end !== undefined && d.end != currentState.end) ||
2855			(d.createdStart !== undefined && d.createdStart != currentState.createdStart) ||
2856			(d.createdEnd !== undefined && d.createdEnd != currentState.createdEnd) ||
2857			(d.attributes !== undefined && d.attributes != currentState.attributes) ||
2858			(d.sort_attr !== undefined && d.sort_attr != currentState.sort_attr) ||
2859			(d.sort_direction !== undefined && !!d.sort_direction != !!currentState.sort_direction) ||
2860			(d.dataStoreMarkerId !== undefined && d.dataStoreMarkerId != currentState.dataStoreMarkerId) ||
2861			(d.dataStoreId !== undefined && d.dataStoreId != currentState.dataStoreId) ||
2862			(d.coords !== undefined && d.coords.latitude != currentState.coords.latitude) ||
2863			(d.coords !== undefined && d.coords.longitude != currentState.coords.longitude);
2864	}
2865	function setState(d) {
2866		if (d.item !== undefined) currentState.item = d.item;
2867		if (d.current_page !== undefined) currentState.current_page = d.current_page;
2868		if (d.tag !== undefined) currentState.tag = d.tag;
2869		if (d.category !== undefined) currentState.category = d.category;
2870		if (d.viewMode !== undefined) currentState.viewMode = d.viewMode;
2871		if (d.range !== undefined) currentState.range = d.range;
2872		if (d.rating !== undefined) currentState.rating = d.rating;
2873		if (d.clientGroup !== undefined) currentState.clientGroup = d.clientGroup;
2874		if (d.favorite !== undefined) currentState.favorite = d.favorite;
2875		if (d.marker !== undefined) currentState.marker = d.marker;
2876		if (d.visited !== undefined) currentState.visited = d.visited;
2877		if (d.open !== undefined) currentState.open = d.open;
2878		if (d.difficulty !== undefined) currentState.difficulty = d.difficulty;
2879		if (d.related !== undefined) currentState.related = d.related;
2880		if (d.datasource !== undefined) currentState.datasource = d.datasource;
2881		if (d.distance !== undefined) currentState.distance = d.distance;
2882        if (d.price !== undefined) currentState.price = d.price;
2883        if (d.month !== undefined) currentState.month = d.month;
2884		if (d.hidden !== undefined) currentState.hidden = d.hidden;
2885		if (d.search !== undefined) currentState.search = d.search;
2886		if (d.start !== undefined) currentState.start = d.start;
2887		if (d.end !== undefined) currentState.end = d.end;
2888		if (d.createdStart !== undefined) currentState.createdStart = d.createdStart;
2889		if (d.createdEnd !== undefined) currentState.createdEnd = d.createdEnd;
2890		if (d.attributes !== undefined) currentState.attributes = d.attributes;
2891		if (d.sort_attr !== undefined) currentState.sort_attr = d.sort_attr;
2892		if (d.sort_direction !== undefined) currentState.sort_direction = !!d.sort_direction;
2893		if (d.dataStoreMarkerId !== undefined) currentState.dataStoreMarkerId = d.dataStoreMarkerId;
2894		if (d.dataStoreId !== undefined) currentState.dataStoreId = d.dataStoreId;
2895        if (d.coords !== undefined) {
2896            if (d.coords.latitude !== undefined) currentState.coords.latitude = d.coords.latitude;
2897            if (d.coords.longitude !== undefined) currentState.coords.longitude = d.coords.longitude;
2898		}
2899	}
2900	function cloneState() {
2901		return {
2902			qr: currentState.qr,
2903			card: currentState.card,
2904			uuid: currentState.uuid,
2905			item: currentState.item,
2906            instance: currentState.instance,
2907            tag: currentState.tag,
2908			category: currentState.category,
2909			viewMode: currentState.viewMode,
2910			range: currentState.range,
2911			rating: currentState.rating,
2912			clientGroup: currentState.clientGroup,
2913			marker: currentState.marker,
2914			favorite: currentState.favorite,
2915			visited: currentState.visited,
2916			open: currentState.open,
2917			difficulty: currentState.difficulty,
2918			related: currentState.related,
2919            datasource: currentState.datasource,
2920			distance: currentState.distance,
2921            price: currentState.price,
2922            month: currentState.month,
2923			search: currentState.search,
2924			start: currentState.start,
2925			end: currentState.end,
2926			createdStart: currentState.createdStart,
2927			createdEnd: currentState.createdEnd,
2928			dataStoreMarkerId: currentState.dataStoreMarkerId,
2929			dataStoreId: currentState.dataStoreId,
2930			hidden: currentState.hidden,
2931            attributes: currentState.attributes,
2932            sort_attr: currentState.sort_attr,
2933            sort_direction: currentState.sort_direction,
2934			coords: {
2935				latitude: currentState.coords.latitude,
2936				longitude: currentState.coords.longitude
2937			},
2938			current_page: currentState.current_page
2939		};
2940	}
2941	function cloneDefaultState() {
2942		return {
2943			qr: defaultState.qr,
2944			card: defaultState.card,
2945			uuid: defaultState.uuid,
2946			item: defaultState.item,
2947            instance: defaultState.instance,
2948			tag: defaultState.tag,
2949			category: defaultState.category,
2950			viewMode: defaultState.viewMode,
2951			range: defaultState.range,
2952			rating: defaultState.rating,
2953			clientGroup: defaultState.clientGroup,
2954			marker: defaultState.marker,
2955			favorite: defaultState.favorite,
2956			visited: defaultState.visited,
2957			open: defaultState.open,
2958			difficulty: defaultState.difficulty,
2959			related: defaultState.related,
2960            datasource: defaultState.datasource,
2961			distance: defaultState.distance,
2962            price: defaultState.price,
2963            month: defaultState.month,
2964			search: defaultState.search,
2965			start: defaultState.start,
2966			end: defaultState.end,
2967			createdStart: defaultState.createdStart,
2968			createdEnd: defaultState.createdEnd,
2969			dataStoreMarkerId: defaultState.dataStoreMarkerId,
2970			dataStoreId: defaultState.dataStoreId,
2971			hidden: defaultState.hidden,
2972            attributes: defaultState.attributes,
2973            sort_attr: defaultState.sort_attr,
2974            sort_direction: defaultState.sort_direction,
2975			coords: {
2976				latitude: defaultState.coords.latitude,
2977				longitude: defaultState.coords.longitude
2978			},
2979			current_page: defaultState.current_page
2980		};
2981	}
2982	function getLocation(isRouteplanner){
2983		$page.addClass("loading");
2984		if (navigator.geolocation) {
2985			var gotAnswer = false;
2986			navigator.geolocation.getCurrentPosition(function(pos){
2987				gotAnswer = true;
2988				map.currentLocation = new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude);
2989				setLocationHash({coords: {latitude: pos.coords.latitude, longitude: pos.coords.longitude}});
2990				if (isRouteplanner === true || map.directionDisplayActive){
2991					directionsToPoint(map.destination);
2992				}
2993				$page.removeClass("loading");
2994			}, function() {
2995				$page.removeClass("loading");
2996				gotAnswer = true;
2997				if (isRouteplanner === true){
2998					displayRoutePlanner(true)
2999				} else {
3000					displayLocationPicker(true);
3001				}
3002			}, {enableHighAccuracy: true, timeout: 10000});
3003			setTimeout(function(){
3004				$page.removeClass("loading");
3005				if (!gotAnswer){
3006					if (isRouteplanner === true){
3007						displayRoutePlanner(true)
3008					} else {
3009						displayLocationPicker(true);
3010					}
3011				}
3012			}, 10000);
3013		} else {
3014			if (isRouteplanner === true){
3015				displayRoutePlanner()
3016			} else {
3017				displayLocationPicker();
3018			}
3019		}
3020	}
3021    function determineLocation(callback){
3022        $page.addClass("loading");
3023        if (navigator.geolocation) {
3024            var gotAnswer = false;
3025            navigator.geolocation.getCurrentPosition(function(pos){
3026                gotAnswer = true;
3027                currentState.coords = {latitude: pos.coords.latitude, longitude: pos.coords.longitude};
3028                if (callback!==undefined) callback(pos.coords);
3029                $page.removeClass("loading");
3030            }, function() {
3031                $page.removeClass("loading");
3032                gotAnswer = true;
3033                displayLocationPicker(true);
3034            }, {enableHighAccuracy: true, timeout: 10000});
3035            setTimeout(function(){
3036                $page.removeClass("loading");
3037                if (!gotAnswer){
3038                    displayLocationPicker(true);
3039                }
3040            }, 10000);
3041        } else {
3042            displayLocationPicker();
3043        }
3044    }
3045	function displayLocationPicker(geolocationFailed) {
3046    	if($('body').hasClass('external-location-picker')) return;
3047		var title = mlpLanguage.locationPickerTitle;
3048		var template =
3049			'<form class="form">';
3050		if (geolocationFailed === true){
3051			template += '<div class="alert alert-danger">' + mlpLanguage.geoLocateError + '</div>';
3052		}
3053		template +=
3054			'	<p class="text-center">' + mlpLanguage.typeInLocation + '</p>' +
3055			'	<div class="form-group">' +
3056			'		<input type="text" name="location" value="" placeholder="" class="form-control">' +
3057			'	</div>';
3058		if (geolocationFailed !== true){
3059			template +=
3060				'	<p class="text-center">' + mlpLanguage.or + '</p>' +
3061				'	<div class="form-group">' +
3062				'		<button type="submit" class="btn btn-primary btn-block btn-current"><i class="fa fa-map-marker"></i> ' + mlpLanguage.useCurrentPosition + '</button>' +
3063				'	</div>';
3064		}
3065		template +=
3066			'</form>';
3067
3068		BootstrapDialog.show({
3069			message: template,
3070			size: BootstrapDialog.SIZE_SMALL,
3071			type: BootstrapDialog.TYPE_PRIMARY,
3072			title: title,
3073			onshown: function(obj){
3074				var $input = obj.$modalBody.find("input[name='location']");
3075				$input.keydown(function (e) {
3076					if (e.which == 13 && $('.pac-container:visible').length) return false;
3077				});
3078
3079				var autocomplete = new google.maps.places.Autocomplete($input.get(0));
3080				autocomplete.addListener('place_changed', function() {
3081					var place = autocomplete.getPlace();
3082					BootstrapDialog.closeAll();
3083					if (!place.geometry) {
3084						BootstrapDialog.show({
3085							title: mlpLanguage.locationErrorTitle,
3086							message: mlpLanguage.locationErrorBody,
3087							size: BootstrapDialog.SIZE_SMALL,
3088							type: BootstrapDialog.TYPE_DANGER
3089						});
3090					} else {
3091						setLocationHash({coords: {latitude: place.geometry.location.lat(), longitude: place.geometry.location.lng()}});
3092						/*
3093						If the route planner is active, set the new point as start location
3094						 */
3095						if (map.directionDisplayActive){
3096							directionsToPoint(map.destination, {lat: place.geometry.location.lat(), lng: place.geometry.location.lng()});
3097						}
3098					}
3099				});
3100
3101				obj.$modalBody.find(".btn-current").click(function(e){
3102					e.preventDefault();
3103					BootstrapDialog.closeAll();
3104					getLocation();
3105				});
3106				setTimeout(function(){
3107					$input.focus();
3108				}, 100);
3109			}
3110		});
3111	}
3112	function directionsToPoint(dest, orig){
3113		var directionsRequest = {};
3114		if (orig === undefined || orig === null) {
3115			orig = map.currentLocation;
3116		}
3117		if (orig !== undefined) {
3118			if (dest !== undefined) {
3119				map.directionDisplayActive = true;
3120				directionsRequest = {
3121					origin: orig,
3122					destination: dest,
3123					travelMode: map.travelMode
3124				};
3125				$page.addClass("loading");
3126				map.directionsService.route(directionsRequest, function (response, status) {
3127					if (status == google.maps.DirectionsStatus.OK) {
3128						if (map.$directionInfo === null){
3129							map.$directionInfo = $('<div class="hidden" />').appendTo($page);
3130						}
3131						map.directionsDisplay.setDirections(response);
3132						map.directionsDisplay.setPanel(map.$directionInfo[0]);
3133						map.directionsDisplay.setMap(map.obj);
3134
3135						if (map.$directionDisplayButton === null){
3136							map.$directionDisplayButton = e = $('<div style="padding: 5px;"><div draggable="false" title="' + mlpLanguage.showRouteDetails + '" style="direction: ltr; cursor: pointer; overflow: hidden; text-align: center; position: relative; color: rgb(255, 255, 255); margin-top: 5px; font-family: Roboto, Arial, sans-serif; -webkit-user-select: none; font-size: 12px; background-color: ' +mlpObject.getBrandPrimaryColor()+ '; padding: 8px; border-bottom-left-radius: 2px; border-top-left-radius: 2px; -webkit-background-clip: padding-box; background-clip: padding-box; -webkit-box-shadow: rgba(0, 0, 0, 0.298039) 0px 1px 4px -1px; box-shadow: rgba(0, 0, 0, 0.298039) 0px 1px 4px -1px; min-width: 34px; font-weight: 500;">' + mlpLanguage.showRouteDetails + '</div></div>');
3137							map.obj.controls[google.maps.ControlPosition.TOP_RIGHT].push(map.$directionDisplayButton[0]);
3138							google.maps.event.addDomListener(map.$directionDisplayButton[0], 'click', function() {
3139                                var template = map.$directionInfo.clone().removeClass("hidden");
3140                                $(template).append(
3141                                        '	<div class="form-group">' +
3142                                        '		<button type="submit" class="btn btn-primary btn-close"><i class="fa fa-close"></i> ' + mlpLanguage.close + '</button>' +
3143                                    	'		<button type="submit" class="btn btn-primary btn-clear-close"><i class="fa fa-close"></i> ' + mlpLanguage.removeTrack + '</button>' +
3144                                    	'	</div>');
3145
3146                                BootstrapDialog.show({
3147									title: mlpLanguage.showRouteDetails,
3148									message: template,
3149									size: BootstrapDialog.SIZE_NORMAL,
3150									type: BootstrapDialog.TYPE_PRIMARY,
3151                                    onshown: function(obj) {
3152                                        obj.$modalBody.find(".btn-close").click(function (e) {
3153                                            e.preventDefault();
3154                                            BootstrapDialog.closeAll();
3155                                        });
3156                                        obj.$modalBody.find(".btn-clear-close").click(function (e) {
3157                                            e.preventDefault();
3158                                            BootstrapDialog.closeAll();
3159                                            map.directionDisplayActive = false;
3160                                            map.directionsDisplay.setMap(null);
3161                                            map.$directionDisplayButton[0].remove();
3162                                            map.$directionDisplayButton = null;
3163                                        });
3164                                    }
3165								});
3166							});
3167
3168						}
3169
3170
3171					} else {
3172						map.directionDisplayActive = false;
3173						map.directionsDisplay.setMap(null);
3174
3175						BootstrapDialog.show({
3176							title: mlpLanguage.routeErrorTitle,
3177							message: mlpLanguage.routeErrorBody,
3178							size: BootstrapDialog.SIZE_SMALL,
3179							type: BootstrapDialog.TYPE_DANGER
3180						});
3181					}
3182					$page.removeClass("loading");
3183				});
3184
3185                //google.maps.event.addListener(ds, 'click', function(evt) {console.log('route clicked')});
3186			}
3187		}
3188	}
3189
3190	function postLocation(pos) {
3191		if (pos.coords !== undefined && pos.coords.latitude !== null && pos.coords.latitude != '' && pos.coords.longitude !== null && pos.coords.longitude != '') {
3192			currentState.coords = pos.coords;
3193			if (typeof google === 'undefined') return;
3194			var geocoder = new google.maps.Geocoder();
3195			geocoder.geocode({'latLng': new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude)}, function (results, status) {
3196				if (status == google.maps.GeocoderStatus.OK) {
3197					if (results[0]) {
3198						$geofilterBar.find("h3").html(results[0].formatted_address);
3199					} else {
3200						$geofilterBar.find("h3").html(mlpLanguage.locationErrorBody);
3201					}
3202				}
3203			});
3204			if (displayMode == "map") {
3205				map.currentLocation = new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude);
3206				if (map.currentMarker == null) {
3207					map.currentMarker = new google.maps.Marker({
3208						position: map.currentLocation,
3209						map: map.obj,
3210						title: mlpLanguage.youAreHere,
3211						icon: new google.maps.MarkerImage('//maps.gstatic.com/mapfiles/mobile/mobileimgs2.png', new google.maps.Size(22, 22), new google.maps.Point(0, 18), new google.maps.Point(11, 11)),
3212						shadow: null,
3213						zIndex: 999
3214					});
3215					map.currentInfoWindow.setPosition(map.currentLocation);
3216					/*map.currentInfoWindow.open(map.obj, map.currentMarker);
3217					setTimeout(function () {
3218						map.currentInfoWindow.close();
3219					}, 3000);*/
3220					google.maps.event.addListener(map.currentMarker, 'mouseover', function () {
3221						map.currentInfoWindow.open(map.obj, map.currentMarker);
3222					});
3223					google.maps.event.addListener(map.currentMarker, 'mouseout', function () {
3224						setTimeout(function () {
3225							map.currentInfoWindow.close();
3226						}, 3000);
3227					});
3228					google.maps.event.addListener(map.currentMarker, 'click', function () {
3229						map.currentInfoWindow.open(map.obj, map.currentMarker);
3230					});
3231				} else {
3232					map.currentMarker.setPosition(map.currentLocation);
3233					map.currentInfoWindow.setPosition(map.currentLocation);
3234				}
3235			}
3236		} else {
3237			$geofilterBar.find("h3").html(mlpLanguage.unknownLocation);
3238			if (map.currentMarker != null) {
3239				map.currentMarker.setPosition(map.currentLocation);
3240				map.currentInfoWindow.setPosition(map.currentLocation);
3241			}
3242		}
3243	}
3244
3245	function rate(dataStoreId, rating, reload) {
3246		$.ajax({
3247			beforeSend: function() {
3248				$('.rating .star').hide();
3249				$('.rating').html('<i class="fa fa-cog fa-spin fa-fw"></i>');
3250			},
3251			url: '/public/rate/' + pageID,
3252			data: {rate: rating, id: dataStoreId},
3253			type: 'post',
3254			complete: function () {
3255				if (reload)
3256					window.location.reload();
3257				else
3258					getContents({}, true);
3259			}
3260		})
3261	}
3262
3263	function favorite($e) {
3264		$.ajax({
3265			url: '/public/favorite/' + pageID,
3266			data: {id: $e.data('id')},
3267			type: 'post',
3268			success: function () {
3269				if ($e.hasClass('not-favorite')) {
3270					$e.removeClass('not-favorite').addClass('favorite');
3271					$e.find('.fa').removeClass('fa-heart-o').addClass('fa-heart')
3272				} else if ($e.hasClass('favorite')) {
3273					$e.removeClass('favorite').addClass('not-favorite');
3274					$e.find('.fa').removeClass('fa-heart').addClass('fa-heart-o')
3275				}
3276				getContents({}, true);
3277			}
3278		})
3279	}
3280}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.