var MapController = Backbone.Model.extend({ options: { drawPois: true, isMarkerClickable: true, highlightExperience: null, hoverTour: false, clickTour: false, autoInit: true, createMapOnInit: true, containerId: 'abs-map-container', trackMode : 'underground', forceTourMarker: false, experienceMode: 'full', autoSaveTime: 5, //in seconds disableMarker: false, symbolizer: { track: { outer: {color: '#000000', opacity: 1.0, weight: 5}, inner: {color: '#ff9900', opacity: 1.0, weight: 3}, hover: {color: '#ff9900'}, character: {color: '#ff0000', weight: 9} }, net: { outer: {color: '#000000', opacity: 0.2, weight: 5}, inner: {color: '#ff9900', opacity: 0.2, weight: 3}, hover: {color: '#ff9900'} }, height: { max: { r: 255, g: 0, b: 0 }, min: { r: 255, g: 255, b: 0 } }, icon: { start: new L.DivIcon({ iconSize: new L.Point(14, 14), className: 'abs-div-icon-outer', html: '
' }), end: new L.DivIcon({ iconSize: new L.Point(14, 14), className: 'abs-div-icon-outer', html: '
' }), routingpoint: { icon: new L.DivIcon({ iconSize: new L.Point(10, 10), className: 'abs-trackpoint-icon routing' }) }, routing: { icon: new L.DivIcon({ iconSize: new L.Point(50, 60), iconAnchor: new L.Point(25, 60), className: 'abs-routing-icon routing', html: '
' }), riseOnHover: true }, trackinfopoint: new L.DivIcon({ iconSize: new L.Point(10, 10), className: 'abs-trackpoint-icon info' }), image: { icon: new L.DivIcon({ iconSize: new L.Point(50, 60), iconAnchor: new L.Point(25, 60), className: 'abs-image-icon image', html: '
' }) }, marker: { tour: { icon: new L.DivIcon({ iconSize: new L.Point(33, 45), iconAnchor: new L.Point(17, 45), className: 'abs-marker tour', html: '
' + '
' + '
' + '[[Distanz]]:' + '[[Anstieg]]:
' + '[[Schwierigkeit]]:' + '
' + '
' + '
' }) }, netTour: { icon: new L.DivIcon({ iconSize: new L.Point(33, 45), iconAnchor: new L.Point(17, 45), className: 'abs-marker tour', html: '
' + '
' + '
' + '[[Distanz]]:' + '[[Anstieg]]:
' + '[[Schwierigkeit]]:' + '
' + '
' + '
' }) }, cache: { icon: new L.DivIcon({ iconSize: new L.Point(33, 45), iconAnchor: new L.Point(17, 45), className: 'abs-marker cache', html: '
' + '
' + '' + '' + '
' + '
' + '
' }) }, fakepoint: { icon: new L.DivIcon({ iconSize: new L.Point(14, 14), className: 'abs-marker fakepoint', html: '
' + '
' + '' + '
' + '
' + '
' }) }, cacheTour: { icon: new L.DivIcon({ iconSize: new L.Point(33, 45), iconAnchor: new L.Point(17, 45), className: 'abs-marker cache', html: '
' + '
' + '' + '
' + '
' + '
' }) }, poi: { icon: new L.DivIcon({ iconSize: new L.Point(34, 47), iconAnchor: new L.Point(17, 47), className: 'abs-marker poi', html: '
' + '
' + '
' + '
' }) } } } }, events: { resize: true, autoSave: false, addTrackpoints: false } }, isInit: false, isIdEditor: false, showUserOpacity: false, userId: null, editing: false, edit: { element: null, enable: false, init: false, underground: { ug: null, startLatLng: null, rectangle: null }, characters: { id: null, startLatLng: null, rectangle: null } }, drawControl: null, layers : { tracks : null, net: null, marker: null, tiles: { active: null, source: null }, localFiles: null, draw: null, routing: null, media: null, characters: null, routingCircles: null }, experiences : {}, map : null, nextFitBounds: true, showRouting: false, editRouting: false, showMedia: false, trackInfoOnMap: null, // Initialisierung initialize: function(options) { // Karte erzeugen var that = this; $.extend(true, that.options, options); that.options.trackMode = application.controller.cookie.getStorage('map.track.mode', that.options.trackMode); if (that.options.autoInit) { that.init(); } }, init: function() { var that = this; if (that.options.createMapOnInit) { that.createMap(that.options.containerId); } if (that.options.events.resize) { $(window).resize(function() { that.toggleFullscreen(true); }); } }, createMap: function(container) { var that = this; if($('#' + container).length == 1) { var lat = ($.getUrlVar('lat') !== undefined) ? $.getUrlVar('lat') : 51; var lon = ($.getUrlVar('lon') !== undefined) ? $.getUrlVar('lon') : 10.35; var zoom = ($.getUrlVar('zoom') !== undefined) ? $.getUrlVar('zoom') : 8; var view = [lat, lon, zoom]; if (application.options.mapView) { view = application.options.mapView; } that.map = L.map(container, { zoomControl: false } ).setView([view[0], view[1]], view[2]); that.map.attributionControl.setPosition('bottomleft'); that.toggleLayerSource('bing', false); that.setMapLayer(application.controller.cookie.getStorage('map.layer', 'terrain')); that.setTrackMode(application.controller.cookie.getStorage('map.track.mode', 'underground')); that.layers.characters = L.featureGroup().addTo(that.map); that.layers.tracks = L.featureGroup().addTo(that.map); that.layers.net = L.featureGroup().addTo(that.map); that.layers.marker = L.featureGroup().addTo(that.map); that.layers.routing = L.featureGroup().addTo(that.map); that.layers.media = L.featureGroup().addTo(that.map); that.layers.draw = L.featureGroup().addTo(that.map); that.layers.localFiles = L.featureGroup().addTo(that.map); that.layers.routingCircles = L.featureGroup().addTo(that.map); /*that.drawControl = new L.Control.Draw({ draw: false, edit: { featureGroup: that.layers.draw } });*/ //Messagecontainer init application.controller.message.addContainer('map', $('#' + container)); that.isInit = true; } }, toggleLayerSource: function(type, setLayer) { var that = this; if (that.layers.tiles.source !== type) { if (type == 'google') { that.layers.tiles.satellite = new L.Google('SATELLITE'); that.layers.tiles.hybrid = new L.Google('HYBRID'); that.layers.tiles.roadmap = new L.Google('ROADMAP'); that.layers.tiles.terrain = new L.Google('TERRAIN'); } else if (type == 'bing') { var token = 'pk.eyJ1IjoiYWJzb2x1dGdwcyIsImEiOiJjaWpvNDQyMXYwMDUydmxtNzdsY3g0Mnh3In0.9IRw4qv2awNQZSPjMWo5BA'; that.layers.tiles.satellite = L.tileLayer('https://api.mapbox.com/styles/v1/mapbox/satellite-v9/tiles/256/{z}/{x}/{y}?access_token=' + token, {maxZoom: 19}); that.layers.tiles.hybrid = L.tileLayer('https://api.mapbox.com/styles/v1/mapbox/satellite-streets-v11/tiles/256/{z}/{x}/{y}?access_token=' + token, {maxZoom: 19}); that.layers.tiles.roadmap = L.tileLayer('https://api.mapbox.com/styles/v1/mapbox/streets-v11/tiles/256/{z}/{x}/{y}?access_token=' + token, {maxZoom: 19}); that.layers.tiles.terrain = L.tileLayer('https://api.mapbox.com/styles/v1/mapbox/outdoors-v11/tiles/256/{z}/{x}/{y}?access_token=' + token, {maxZoom: 19}); } that.layers.tiles.source = type; $('.js-layer-source').show(); $('.js-layer-source-' + type).hide(); if (setLayer !== false) { var type = that.layers.tiles.activeType; that.layers.tiles.activeType = null; that.setMapLayer(type); } } }, setStrava: function() { var that = this; if (that.layers.tiles.strava == undefined) { that.layers.tiles.strava = L.tileLayer('http://mapdesigner.map-wizard.com/strava.php?z={z}&x={x}&y={y}'); } that.setMapLayer('strava'); }, setMapLayer: function(type) { var that = this; if (that.layers.tiles.activeType !== type) { if (that.layers.tiles.active !== null) { that.map.removeLayer(that.layers.tiles.active); } $('.js-layer-select').removeClass('active'); $('.js-layer-select-' + type).addClass('active'); that.layers.tiles.active = that.layers.tiles[type]; that.map.addLayer(that.layers.tiles.active); if (that.layers.tiles.active.options.maxZoom < that.map.getZoom()) { that.map.setZoom(that.layers.tiles.active.options.maxZoom); } application.controller.cookie.setStorage('map.layer', type); that.layers.tiles.activeType = type; } }, setTrackMode : function(mode) { var that = this; if (mode != that.options.trackMode) { that.options.trackMode = mode; if (_.size(that.experiences) > 0) { that.nextFitBounds = false; that.drawExperiences(); } } $('.js-track-mode-select').removeClass('active'); $('.js-track-mode-select-' + mode).addClass('active'); application.controller.cookie.setStorage('map.track.mode', mode); }, setExperienceMode: function(mode) { var that = this; that.options.experienceMode = mode; }, scrollToMap: function() { var that = this; $('html, body').animate({ scrollTop: $('body').offset().top }, 200); }, fitTrackBounds: function() { var that = this; that.fitLayerBounds('tracks'); }, fitLayerBounds: function(layer) { var that = this; var bounds = that.layers[layer].getBounds(); that.fitBounds(bounds); }, fitBounds: function(bounds) { var that = this; if ($.getUrlVar('fit') !== undefined) { return; } if (this.nextFitBounds !== false && bounds.isValid()) { var overlays = ['top', 'left', 'bottom', 'right']; $.each(overlays, function() { var sel = $('.js-map-overlay-' + this + ':visible'); if (sel.length == 1) { if (this == 'bottom' || this == 'top') { var overlaySize = $(sel).height() * 1.1; var diff = bounds.getNorthEast().lat - bounds.getSouthWest().lat; var mapRel = that.map.getSize().y / (that.map.getSize().y - overlaySize); if (this == 'bottom') { bounds.getSouthWest().lat = bounds.getNorthEast().lat - mapRel * diff; } else { bounds.getNorthEast().lat = bounds.getSouthWest().lat + mapRel * diff; } } if (this == 'left' || this == 'right') { var overlaySize = $(sel).width() * 1.1; var diff = bounds.getNorthEast().lng - bounds.getSouthWest().lng; var mapRel = that.map.getSize().x / (that.map.getSize().x - overlaySize); if (this == 'left') { bounds.getSouthWest().lng = bounds.getNorthEast().lng - mapRel * diff; } else { bounds.getNorthEast().lng = bounds.getSouthWest().lng + mapRel * diff; } } } }); this.map.fitBounds(bounds); } this.nextFitBounds = true; }, highlightExperience: function(experience) { var that = this; that.options.highlightExperience = (experience) ? experience : null; $.each(that.experiences, function() { if (this.mapElement && this.mapElement.tour) { if (this == experience || !experience) { this.mapElement.setOpacity(1); this.mapElement.tour.polyOut.setStyle({opacity: 1}); this.mapElement.tour.polyOut.bringToFront(); $.each(this.mapElement.tour.polyIn, function () { this.setStyle({opacity: 1}); this.bringToFront(); }) } else { this.mapElement.setOpacity(0.5); this.mapElement.tour.polyOut.setStyle({opacity: 0}); $.each(this.mapElement.tour.polyIn, function () { this.setStyle({opacity: 0.5}); }) } } }); }, drawExperiences: function(experiences, clear) { var that = this; var rt = []; if (that.layers.tracks !== null && that.map !== null && clear !== false) { that.layers.tracks.clearLayers(); that.edit.element = []; if (that.layers.marker.blocked !== undefined && that.layers.marker.blocked !== true) { that.layers.marker.clearLayers(); } that.layers.routing.clearLayers(); that.layers.media.clearLayers(); } if (experiences == undefined) { experiences = that.experiences; that.edit.element = []; } $.each(experiences, function(i, experience) { rt.push(that.drawExperience(experience, that.options.experienceMode, clear)); }); var bounds = that.layers.tracks.getBounds(); if (_.size(that.layers.marker._layers) > 0) { bounds.extend(that.layers.marker.getBounds()); } that.fitBounds(bounds); if (experiences.length > 0 && experiences[0].hasNetTour) { that.addRoutingpoints(experiences[0].netTour); } if (that.options.highlightExperience) { that.highlightExperience(that.options.highlightExperience); } return rt; }, drawExperience : function(experience, mode, clear) { var that = application.controller.map; var modeBack = null; var rt = null; if (mode !== undefined && mode != null) { modeBack = that.options.experienceMode; that.options.experienceMode = mode; } if (!that.isInit) { that.createMap(that.options.containerId); } switch (that.options.experienceMode) { case 'full': if (experience.class == 'AbsTour' || experience.class == 'AbsNetTour') { rt = that.drawTour(experience); } else if ((that.options.drawPois && experience.class == 'AbsPoi') || experience.class == 'AbsCache') { rt = that.drawExperienceMarker(experience); } break; case 'marker': rt = that.drawExperienceMarker(experience); break; } if (modeBack != null) { that.options.experienceMode = modeBack; } that.addMedia(experience); experience.mapElement = rt; if (clear !== false) { that.experiences[experience.id] = experience; } return rt; }, drawExperienceMarker: function(experience) { var that = this; var pos = experience.position; var latlng = new L.LatLng(pos.lat, pos.lon); var icon = jQuery.extend({}, that.options.symbolizer.icon.marker[that.dashToCamelCase(experience.type)]); icon.riseOnHover = true; icon.icon.options.html = application.translate(icon.icon.options.html); var marker = new L.Marker(latlng, icon).addTo(that.layers.marker); $('.experience-icon', marker._icon).addClass('experience-type-' + experience.mainType.id); $(marker._icon).addClass('experience-' + experience.id); if (experience.mainType.id == 1101 && experience.extra && experience.extra['geocaching-board-number']) { $('.experience-icon', marker._icon).text(experience.extra['geocaching-board-number']) } if (that.showUserOpacity) { if (experience.user.id !== that.userId) { $(marker._icon).css('opacity', 0.7); $(marker._icon).mouseover(function() { $(this).css('opacity', 1.0); }); $(marker._icon).mouseout(function() { $(this).css('opacity', 0.7); }); } } if (!marker.options.draggable) { $(marker._icon).click(function () { if (that.options.isMarkerClickable) { application.goToRoute('showExperience', {id: experience.id}); } application.controller.event.trigger('map.marker.click', {marker: marker, experience: experience}); }); $(marker._icon).mouseover(function() { $('.abs-marker-hover .name', this).text(experience.name); var positionText = ''; if (experience.position.region !== null && experience.position.region !== null) { positionText = experience.position.region + ', ' + experience.position.city; } else { positionText = experience.position.city; } $('.abs-marker-hover .position', this).text(positionText); if (experience.type == 'tour') { var distance = Math.round(experience.tourData.distance * 10) / 10; if (Math.round(distance) == distance) { distance = distance + ',' + 0; } else { distance = distance.toString().replace('.', ','); } $('.abs-marker-hover .distance', this).text(distance + ' km'); $('.abs-marker-hover .climb', this).text(experience.tourData.climb + ' Hm'); $('.abs-marker-hover .difficulty', this).text(application.translate('[[' + experience.difficulty.name + ']]')); } application.controller.event.trigger('map.marker.hover', {marker: marker, experience: experience}); }); } else { $('.abs-marker-hover', marker._icon).remove(); } return marker; }, drawTour : function(experience) { var that = this; switch (that.options.trackMode) { case 'simple': var marker = that.addStartEndMarker(experience.track); var tour = that.drawTourSimple(experience.track, marker); if (marker) { marker.tour = tour; } break; case 'underground': var marker = that.addStartEndMarker(experience.track); var tour = that.drawTourUnderground(experience.track, marker); if (marker) { marker.tour = tour; } break; case 'height': var marker = that.addStartEndMarker(experience.track); var tour = that.drawTourHeight(experience.track, marker); if (marker) { marker.tour = tour; } break; case 'net': that.drawTourNet(experience.track); break; case 'updown': that.drawTourUpDown(experience.track); break; } if (experience.hasNetTour !== true) { that.addRoutingpoints(experience); } that.layers.tracks.addTo(that.map); if (that.editRouting) { that.layers.tracks.on('click', function(e) { that.chooseRoutingpoint(e.latlng); }); } application.controller.event.trigger('map.tour.draw', {marker: marker, experience: experience}); //checkMapZoomforTrackpoints(); return marker; }, setHover: function(polyIn, polyOut, marker) { var that = this; if (that.options.hoverTour) { if (marker) { $(polyIn).on('mouseover', function() { $(marker._icon).trigger('mouseover'); $(marker._icon).addClass('hover'); polyOut._path.classList.add('polyOut'); polyOut._path.classList.add('hover'); }); $(polyIn).on('mouseout', function () { $(marker._icon).removeClass('hover'); polyOut._path.classList.remove('polyOut'); polyOut._path.classList.remove('hover'); }); } else { $(polyIn).on('mouseover', function() { console.log(polyOut.experience.id + ': ' + polyOut.experience.name); }); } } }, setClick: function(polyIn, polyOut, track) { var that = this; if (that.options.clickTour) { $(polyIn).on('click', function() { application.controller.event.trigger('map.tour.click', track); }); $(polyOut).on('click', function() { application.controller.event.trigger('map.tour.click', track); }); } }, drawTourSimple: function(track, marker) { var that = this; var latlngs = []; var length = track.getTrackpoints().length; for(var n = 0; n < length; n++) { var tp = track.getTPat(n); var latlng = new L.LatLng(tp.lat, tp.lon); latlngs.push(latlng); } var polyOut = L.polyline(latlngs, that.options.symbolizer.track.outer).addTo(that.layers.tracks); if (that.showDirection) { } var polyIn = L.polyline(latlngs, that.options.symbolizer.track.inner).addTo(that.layers.tracks); that.setHover(polyIn, polyOut, marker); that.setClick(polyIn, polyOut, track); return {polyOut: polyOut, polyIn: [polyIn]}; }, drawTourNet: function(track) { var that = this; var latlngs = []; var length = track.getTrackpoints().length; for(var n = 0; n < length; n++) { var tp = track.getTPat(n); var latlng = new L.LatLng(tp.lat, tp.lon); latlngs.push(latlng); } track.experience.layer = {}; track.experience.layer.polyOut = L.polyline(latlngs, that.options.symbolizer.net.outer).addTo(that.layers.net); track.experience.layer.polyIn = L.polyline(latlngs, that.options.symbolizer.net.inner).addTo(that.layers.net); }, drawTourUnderground: function(track, marker) { var that = this; var latlngs = []; var path = null; var currentUg = null; var parts = []; var length = track.getTrackpoints().length; for(var n = 0; n < length; n++) { var tp = track.getTPat(n); var latlng= new L.LatLng(tp.lat, tp.lon); latlng.ugChange = tp.ugChange; latlng.ele = tp.ele; latlng.ug = tp.ug; latlngs.push(latlng); if (currentUg == null || currentUg != tp.ug || n == length - 1 ) { if(path !== null) { path.push(latlng); parts.push(that.drawTourUndergroundPart(path, track.colors[currentUg], that.layers.tracks)); } path = []; } path.push(latlng); currentUg = tp.ug; } var polyOut = L.polyline(latlngs, that.options.symbolizer.track.outer).addTo(that.layers.tracks); polyOut.experience = track.experience; that.edit.element.push(polyOut); polyOut.polyIn = []; if (that.editing) { polyOut.edit = true; polyOut.editing.enable(); polyOut.on('edit', function(e) { application.controller.experience.savePolygonToTrack(e.target); }); } $.each(parts, function(i, part) { part.addTo(that.layers.tracks); polyOut.polyIn.push(part); that.setHover(part, polyOut, marker); that.setClick(part, polyOut, track); }); return {polyOut: polyOut, polyIn: parts}; }, drawTourUpDown: function(track, marker) { var that = this; var latlngs = []; var path = null; var currentUD = null; var parts = []; var dir = 'up'; var colors = {up: 'red', down: 'blue'}; var trackpoints = track.getTrackpoints(); trackpoints = track.profilGlatten(trackpoints); var length = trackpoints.length; for(var n = 0; n < length; n++) { var tp = track.getTPat(n); var latlng= new L.LatLng(tp.lat, tp.lon); latlngs.push(latlng); dir = (tp.ele > track.getTPat(n-1).ele) ? 'up' : 'down'; if (currentUD == null || currentUD != dir || n == length - 1 ) { if(path !== null) { path.push(latlng); parts.push(that.drawTourUndergroundPart(path, colors[currentUD], that.layers.tracks)); } path = []; } path.push(latlng); currentUD = dir; } var polyOut = L.polyline(latlngs, that.options.symbolizer.track.outer).addTo(that.layers.tracks); polyOut.experience = track.experience; that.edit.element.push(polyOut); polyOut.polyIn = []; if (that.editing) { polyOut.edit = true; polyOut.editing.enable(); polyOut.on('edit', function(e) { application.controller.experience.savePolygonToTrack(e.target); }); } $.each(parts, function(i, part) { part.addTo(that.layers.tracks); polyOut.polyIn.push(part); that.setHover(part, polyOut, marker); that.setClick(part, polyOut, track); }); return {polyOut: polyOut, polyIn: parts}; }, drawTourHeight: function(track, marker) { var that = this; var latlngs = []; var path = []; var curPart = null; var maxEle = track.getMaxEle(); var minEle = track.getMinEle(); var q = 10; var eleDiff = (maxEle-minEle); var eleDiffPart = eleDiff / q; var ele = null; var parts = []; var length = track.getTrackpoints().length; for(var n = 0; n < length; n++) { var tp = track.getTPat(n); var latlng = new L.LatLng(tp.lat, tp.lon); latlngs.push(latlng); isEle = false; if (tp.ele > ele - (eleDiffPart / 2) && tp.ele < ele + (eleDiffPart / 2)) isEle = true; if (ele != null && !isEle || n == length - 1) { if(path !== null) { var r = Math.round((that.options.symbolizer.height.max.r - (that.options.symbolizer.height.max.r - that.options.symbolizer.height.min.r) / eleDiff * (ele - minEle) )); var g = Math.round((that.options.symbolizer.height.max.g + (that.options.symbolizer.height.min.g - that.options.symbolizer.height.max.g) / eleDiff * (maxEle - ele) )); var b = Math.round((that.options.symbolizer.height.max.b + (that.options.symbolizer.height.min.b) / eleDiff * (ele - minEle) )); var color = "rgb("+r+","+g+","+b+")"; path.push(latlng); ele = tp.ele; parts.push(that.drawTourUndergroundPart(path, color)); } path = []; } if (ele == null) ele = tp.ele; path.push(latlng); } var polyOut = L.polyline(latlngs, that.options.symbolizer.track.outer).addTo(that.layers.tracks); $.each(parts, function(i, part) { part.addTo(that.layers.tracks); that.setHover(part, polyOut, marker); that.setClick(part, polyOut, track); }); return {polyOut: polyOut, polyIn: parts}; }, drawTourUndergroundPart: function(part, color, layer) { var symbolizer = jQuery.extend({}, this.options.symbolizer.track.inner); symbolizer.color = color; return L.polyline(part, symbolizer); }, toggleProfile: function() { $('#abs-map-profile').toggleClass('toggle'); application.controller.profile.resizeAll(); }, toggleFullscreen: function(resize) { var that = this; if (resize !== true) { $('body').toggleClass('fullscreen'); } if ($('body').hasClass('fullscreen')) { if (resize !== true) { that.mapHeightBak = $('#abs-map').height(); } height = $(window).height() - 10; $('#abs-map').height(height + 'px'); $('#abs-map-container').height(height + 'px'); $('#abs-map-profile').show(); } else { $('#abs-map').height(that.mapHeightBak); $('#abs-map-container').height(that.mapHeightBak); $('#abs-map-profile').hide(); } this.map.resize(); if (resize !== true) { $(window).trigger('resize'); } application.controller.cookie.setStorage('map.fullscreen', $('body').hasClass('fullscreen')); }, openMapModal: function(id) { var that = this; $('#' + id).show(); var mapSize = that.map.getSize(); var modalHeight = $('#' + id).height(); var top = 30; $('#' + id).css('top', ((mapSize.y - top - modalHeight) / 2 + top) + 'px'); }, closeMapModal: function(id) { $('#' + id).hide(); application.controller.event.trigger('map.modal.' + id + '.close'); }, chooseTrackVersions: function() { var that = this; application.controller.experience.getTrackVersions(that.edit.element[0].experience.id, function(html) { $('#editor-trackversion-choose .map-modal-body').html(html); $('#editor-trackversion-choose .map-modal-body li').click(function() { var revId = $(this).attr('data'); application.controller.experience.loadTrackVersion(revId, that.edit.element[0].experience); that.closeMapModal('editor-trackversion-choose'); }); that.openMapModal('editor-trackversion-choose'); }); }, chooseUnderground: function() { var that = this; that.openMapModal('editor-underground-choose'); }, drawUnderground: function(ug) { var that = application.controller.map; that.closeMapModal('editor-underground-choose'); // set mouse $('#abs-map-container').addClass('mouse-crosshair'); var onMousemove = function(e) { if (that.edit.underground.enable !== true) { return; } if (that.edit.underground.startLatLng == null) { return; } var bounds = [that.edit.underground.startLatLng, e.latlng]; if (that.edit.underground.rectangle == null) { that.edit.underground.rectangle = new L.rectangle(bounds, { color: that.edit.element[0].experience.track.colors[that.edit.underground.ug] }).addTo(that.map); } else { that.edit.underground.rectangle.setBounds(bounds); } }; var onClick = function(e) { if (that.edit.underground.enable !== true) { return; } if (that.edit.underground.startLatLng == null) { that.edit.underground.startLatLng = e.latlng; } else { if (that.edit.underground.rectangle) { var bounds = that.edit.underground.rectangle.getBounds(); application.controller.experience.setUgInBoundsOfExperiences(that.edit.element, that.edit.underground.ug, bounds); application.controller.event.trigger('map.underground.draw.success'); } that.drawUnderground(false); } }; var onTrackClick = function(e) { if (that.edit.underground.enable !== true) { return; } e.originalEvent.preventDefault(); var d = 0.00001; var bounds = new L.LatLngBounds(new L.LatLng(e.latlng.lat - d, e.latlng.lng - d), new L.LatLng(e.latlng.lat + d, e.latlng.lng + d)); application.controller.experience.setUgInBoundsOfExperiences(that.edit.element, that.edit.underground.ug, bounds, true); application.controller.event.trigger('map.underground.draw.success'); that.drawUnderground(false); return false; } if (!that.edit.underground.init) { that.edit.underground.enable = true; that.map.on('click', onClick); that.map.on('mousemove', onMousemove); that.edit.underground.init = true; that.layers.tracks.on('click', onTrackClick); } if (ug === false) { application.controller.event.trigger('map.underground.draw.end'); if (that.edit.underground.rectangle) { that.map.removeLayer(that.edit.underground.rectangle); } that.edit.underground.rectangle = null; that.edit.underground.startLatLng = null; that.edit.underground.enable = false; that.edit.underground.ug = null; $('#abs-map-container').removeClass('mouse-crosshair'); } else { that.edit.underground.ug = ug; that.edit.underground.enable = true; } }, addStartEndMarker: function(track) { var that = this; if (that.options.forceTourMarker) { return that.drawExperienceMarker(track.experience); } if (that.options.disableMarker) { return; } var tp = track.getTPat(0); var latlng = new L.LatLng(tp.lat, tp.lon); var startMarker = new L.Marker(latlng, { icon: that.options.symbolizer.icon.start }).addTo(that.layers.tracks); var tp = track.getTPat(track.trackpoints.length - 1); var latlng = new L.LatLng(tp.lat, tp.lon); var endMarker = new L.Marker(latlng, { icon: that.options.symbolizer.icon.end }).addTo(that.layers.tracks); track.startMarker = startMarker; track.endMarker = endMarker; var _onZoom = function() { if (track.isEditing) { return; } var difLat = track.getTPat(1).lat - track.getTPat(0).lat; var difLon = track.getTPat(0).lon - track.getTPat(1).lon; var deg = Math.atan((difLat) / (difLon)) * 180 / Math.PI; if (track.getTPat(1).lon < track.getTPat(0).lon) { deg -= 180; } $(startMarker._icon).find('div').rotate(deg) var startPoint = that.map.latLngToLayerPoint(startMarker.getLatLng()); var endPoint = that.map.latLngToLayerPoint(endMarker.getLatLng()); if (Math.abs(startPoint.x - endPoint.x) < (startMarker.options.icon.options.iconSize.x) || Math.abs(startPoint.y - endPoint.y) < (startMarker.options.icon.options.iconSize.y)) { $(endMarker._icon).hide(); } else { $(endMarker._icon).show(); } } that.map.on('zoomend', _onZoom); _onZoom(); }, refreshRoutingpoints: function(experience) { var that = this; that.layers.routing.clearLayers(); that.addRoutingpoints(experience); }, addRoutingpoints: function(experience) { var that = this; var remove = []; if (experience.routingpoints && that.showRouting) { that.layers.routingCircles.clearLayers(); experience.routingpoints.reverse(); $.each(experience.routingpoints, function(i, rp) { var isRoutingCreated = that._createRoutingIcon(rp, experience, new L.LatLng(rp.lat, rp.lon)); if (isRoutingCreated && that.editRouting) { L.circle([rp.lat, rp.lon], 15, {opacity: 0.3, stroke: false}).addTo(that.layers.routingCircles); L.circle([rp.lat, rp.lon], 5, {opacity: 0.5, stroke: false}).addTo(that.layers.routingCircles); L.circle([rp.lat, rp.lon], 2, {opacity: 1, stroke: false}).addTo(that.layers.routingCircles); } }); experience.routingpoints.reverse(); } }, _createRoutingIcon: function(rp, experience, latlng, options) { var that = this; var defaults = { move: true, drawRoutingPoint: true, }; var options = $.extend({}, defaults, options); var crossoverTps = []; var minDis = null; if (experience !== null) { var trackpoints = experience.track.getTrackpoints(); $.each (trackpoints, function(i, tp) { if (i == 0 || i == trackpoints.length - 1) { return true; } var latlngTp = new L.LatLng(tp.lat, tp.lon); var dis = latlng.distanceTo(latlngTp); if (minDis == null || dis < minDis) { minDis = dis; } if (dis < 2) { tp.index = i; tp.dis = dis; crossoverTps.push(tp); } }); } if (minDis !== null && minDis > 10) { return false; } if (options.drawRoutingPoint !== false) { new L.Marker(latlng, that.options.symbolizer.icon.routingpoint).addTo(that.layers.routing); } var routingMarker = new L.Marker(latlng, that.options.symbolizer.icon.routing).addTo(that.layers.routing); rp.experience = experience; routingMarker.crossover = rp; if (that.editRouting) { routingMarker.on('click', function(e) { application.controller.routing.editRoutingpoint(routingMarker.crossover, experience); }); } if (Math.floor(rp.type / 100) == 1) { rp.angleIn = 0; } $(routingMarker._icon).attr('c', rp.id); that.checkCrossover(routingMarker, rp, experience, crossoverTps); return routingMarker; }, getAngleOfTrackpoint: function(tpIn, tpOut) { var lat1 = tpIn.lat; var lon1 = tpIn.lon; var lat2 = tpOut.lat; var lon2 = tpOut.lon; var R = 6371; // km var dLat = (lat2-lat1).toRad(); var dLon = (lon2-lon1).toRad(); var lat1 = lat1.toRad(); var lat2 = lat2.toRad(); var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); var y = Math.sin(dLon) * Math.cos(lat2); var x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon); var brng = Math.atan2(y, x).toDeg(); return brng; }, getAnglesOfTrackpoint: function(track, index) { var that = this; var difLat = track.getTPat(index).lat - track.getTPat(index-1).lat; var difLon = track.getTPat(index-1).lon - track.getTPat(index).lon; var deg = Math.atan((difLat) / (difLon)) * 180 / Math.PI; if (track.getTPat(index).lon < track.getTPat(index-1).lon) { deg -= 180; } var angleIn = 90 + deg; var angleOut = null; if (index + 1 < track.getTrackpoints().length) { var difLat = track.getTPat(index+1).lat - track.getTPat(index).lat; var difLon = track.getTPat(index).lon - track.getTPat(index+1).lon; var deg = Math.atan((difLat) / (difLon)) * 180 / Math.PI; if (track.getTPat(index+1).lon <= track.getTPat(index).lon) { deg -= 180; } angleOut = 90 + deg; } angleIn = that.getAngleOfTrackpoint(track.getTPat(index-1), track.getTPat(index)); angleOut = that.getAngleOfTrackpoint(track.getTPat(index), track.getTPat(index+1)); return {angleIn: angleIn, angleOut: angleOut}; }, checkCrossover: function(marker, co, experience, crossoverTps) { var that = this; if (experience !== null) { if (co.type < 256) { var founds = 0; $.each(crossoverTps, function(i, cotp) { var angles = that.getAnglesOfTrackpoint(experience.track, cotp.index); $.each(co.routingpoints, function(ii, rp) { var type = rp.type; if (type == undefined) { type == 0; } var tangle = angles.angleOut - angles.angleIn; if (tangle > 180) { tangle -= 360; } if (tangle < -180) { tangle += 360; } if (Math.abs((rp.angleIn) - (angles.angleIn)) < 15 && Math.abs(tangle - application.controller.routing.crossovers.angles[type].angle) < application.controller.routing.crossovers.angles[type].tolerance ) { founds++; cotp.found = true; rp.found = true; rp.tp = cotp; marker.rp = rp; var rpCode = application.controller.routing.getCodeOfRoutingpoint(rp, co); if (founds == 1) { $(marker._icon).find('div').css('background-image', 'url("/img/global/routing/system/' + rpCode + '-' + rp.type + '.png")'); if (rp.type < 8) { $(marker._icon).find('div').rotate(parseFloat(rp.angleIn)); } } } }); }); if (founds < crossoverTps.length) { $(marker._icon).find('div').parent().addClass('none'); } if (founds == 0) { marker.rp = co.routingpoints[0]; } co.tps = crossoverTps; } else { $(marker._icon).find('div').css('background-image', 'url("/img/global/routing/system/' + co.type + '.png")') } } else { $(marker._icon).find('div').css('background-image', 'url("/img/global/routing/absGPS_RS_' + co.routingpoints[0].type + '.png")') } }, refreshMedia: function(experience) { var that = this; that.layers.media.clearLayers(); that.addMedia(experience); }, addMedia: function(experience) { var that = this; if (experience.images && that.showMedia) { $.each(experience.images, function(i, image) { if (image.position == null || image.position.id == experience.position.id) { return; } var latlng = new L.LatLng(image.position.lat, image.position.lon); var imageOptions = that.options.symbolizer.icon.image; var imageMarker = new L.Marker(latlng, imageOptions).addTo(that.layers.media); var src = image.src; src = src.replace('.jpg', '_72x72.jpg'); $(imageMarker._icon).find('div').css('background-image', 'url("' + src + '")'); $(imageMarker).on('moveend', function() { application.controller.experience.savePositionOfObject(image, imageMarker.getLatLng(), 'experience.image'); }); }); } }, chooseRoutingpoint: function(latlng, rp) { var that = this; application.router.editor.initEdit('routing') that.closeMapModal('editor-routing-choose'); that.closeMapModal('editor-routing-edit'); var _onIconClick = function() { var that = application.controller.map; var id = $(this).attr('data'); if (rp) { rp.type = id; application.controller.experience.saveRoutingpoint(rp, application.controller.routing.currentCrossover, function() {application.controller.routing.reloadRoadbook(rp.experience);}); that.addRoutingpoints(rp.experience); } else { that.drawRouting(id, latlng); } }; }, drawRouting: function(id, latlng) { var that = this; if (id == undefined) { id = null; } var marker = that._createRoutingIcon({type: id, angleIn: 0, routingpoints: [{type: id}]}, null, that.map.getCenter(), {move: false, drawRoutingPoint: false}); var _onMouseMove = function(e) { marker.setLatLng(e.latlng); }; var _onKeyPress = function (e) { if (e.keyCode == 27) { _removeListeners(); that.refreshRoutingpoints(that.edit.element[0].experience); } }; var _removeListeners = function() { that.map.off('mousemove', _onMouseMove); that.map.off('click', _onClick); $('#' + that.options.containerId).removeClass('pointer-none'); $(document).unbind('keydown', _onKeyPress); }; var _onClick = function(e, setMarker) { _removeListeners(); var track = that.edit.element[0].experience.track; var routings = that.edit.element[0].experience.routingpoints; if (that.edit.element[0].experience.hasNetTour) { track = that.edit.element[0].experience.netTour.track; routings = that.edit.element[0].experience.netTour.routingpoints; } var found = false; var minDis = null; var latlng; $.each (track.getTrackpoints(), function(i, tp) { var tplatlng = new L.LatLng(tp.lat, tp.lon); dis = tplatlng.distanceTo(e.latlng); if (minDis == null || dis < minDis) { minDis = dis; latlng = tplatlng; } }); if (setMarker !== false) { marker.setLatLng(latlng); } var rp = {lat: latlng.lat, lon: latlng.lng, type: id}; application.controller.map.map.setView(latlng, 19); if (id == null || id == undefined) { $.each(track.getTrackpoints(), function (i, tp) { if (!found && tp.lat == rp.lat && tp.lon == rp.lon && i !== 0) { found = true; var angles = that.getAnglesOfTrackpoint(track, i); rp.angleIn = angles.angleIn; application.controller.routing.selectNewCrossOfAngles(angles, function(crossoverType, angleType) { rp.type = angleType; var co = {id: null, type: crossoverType}; application.controller.experience.saveRoutingpoint(rp, co, function(data) { co = data.crossover; rp = data.routing; co.routingpoints = [rp]; routings.push(co); if (that.edit.element[0].experience.hasNetTour !== true) { that.refreshRoutingpoints(that.edit.element[0].experience); application.controller.routing.reloadRoadbook(that.edit.element[0].experience); } else { that.refreshRoutingpoints(that.edit.element[0].experience.netTour); application.controller.routing.reloadRoadbook(that.edit.element[0].experience.netTour); } application.controller.event.trigger('map.routing.draw.success'); }); }); } }); } else { rp.angleIn = 0; var co = {id: null, type: id}; application.controller.experience.saveRoutingpoint(rp, co, function(data) { co = data.crossover; rp = data.routing; co.routingpoints = [rp]; routings.push(co); if (that.edit.element[0].experience.hasNetTour !== true) { that.refreshRoutingpoints(that.edit.element[0].experience); application.controller.routing.reloadRoadbook(that.edit.element[0].experience); } else { that.refreshRoutingpoints(that.edit.element[0].experience.netTour); application.controller.routing.reloadRoadbook(that.edit.element[0].experience.netTour); } application.controller.event.trigger('map.routing.draw.success'); }); } }; $('#' + that.options.containerId).addClass('pointer-none'); that.map.on('mousemove', _onMouseMove); that.map.on('click', _onClick); $(document).keydown(_onKeyPress); if (latlng !== null && latlng !== undefined) { that.map.removeLayer(marker); _onClick({latlng: latlng}, false); } }, setTrackInfoOnMapFromTp: function(tp, dis) { var that = this; if (tp !== null) { if (that.trackInfoOnMap == null) { that.trackInfoOnMap = new L.Marker([tp.lat, tp.lon], { icon: that.options.symbolizer.icon.trackinfopoint }).addTo(that.map); that.trackInfoOnMap.bindPopup('
', { closeButton: false, autoPan: false }).openPopup(); $('#track-info-on-map').parents('.leaflet-popup').html('
'); } if (that.trackInfoOnMap !== null) { var experience = that.edit.element[0].experience; var track = experience.track; var trackpoints = track.getTrackpoints(); var hmAll = 0; var lastHm = null; var found = false; $.each(trackpoints, function() { if (!found && lastHm !== null) { var diff = (this.ele - lastHm); if (diff > 0) hmAll += diff; } lastHm = this.ele; if (this.dis >= tp.dis) found = true; }) that.trackInfoOnMap.setLatLng([tp.lat, tp.lon]); var dis = ((Math.round(dis*10)/10) + '').replace('.', ','); var h = Math.round(tp.ele); var hmAll = Math.round(hmAll); var html = application.translate('

[[Distanz]]: ' + dis + ' km

[[Höhe]]: ' + h + ' Hm

[[Anstieg]]: ' + hmAll + '

'); $('#track-info-on-map').html(html); } } else { if (that.trackInfoOnMap !== null) { that.map.removeLayer(that.trackInfoOnMap); that.trackInfoOnMap = null; } } }, reverse: function() { var that = this; var experience = that.edit.element[0].experience; var track = experience.track; var trackpoints = track.getTrackpoints(); var routingpoints = experience.routingpoints; var m = application.controller.message.addMessage('map', 'Streckenverlauf wird umgekehrt.', 'loading'); for (var i=trackpoints.length-1; i>0;i--) { trackpoints[i].ug = trackpoints[i-1].ug; } trackpoints.reverse(); experience.track.readTrackpoints(trackpoints); that.nextFitBounds = false; that.drawExperiences([experience]); if (experience.track.profile !== null) { experience.track.profile.draw(); } application.controller.experience.updateTrackInfos([experience]); application.controller.message.changeMessage(m, 'Der Streckenverlauf wurde erfolgreich umgekehrt.', 'info', 3000); }, simplify: function() { var that = this; that.openMapModal('editor-simplify'); }, srtmAlign: function() { var that = this; $.each(that.edit.element, function(i, element) { application.controller.experience.srtmAlign(element.experience); }); }, snapToRoad: function() { var that = this; $.each(that.edit.element, function(i, element) { application.controller.experience.snapToRoad(element.experience); }); }, getOsmUnderground: function() { var that = this; $.each(that.edit.element, function(i, element) { application.controller.experience.getOsmUnderground(element.experience); }); }, getTrackpointsFromSourceNet: function(id) { var that = this; application.controller.experience.getTrackpointsFromSourceNet(id, that.edit.element[0].experience); }, saveTrack: function() { var that = this; var experiences = []; $.each(that.edit.element, function(i, element) { experiences.push(element.experience); }); application.controller.experience.saveExperiencesToApi(experiences); experiences = null; }, toggleSaveTrack: function(element) { var that = this; if (!that.options.events.autoSave) { that.options.events.autoSave = true; var mText = 'Automatisches speichern wurde aktiviert (' + that.options.autoSaveTime + 's).'; $('span', element).text(application.translate('[[an]]')); application.controller.message.addMessage('map', mText, 'info', 3000); that.options.events.autoSaveTimer = window.setInterval( function(){that.saveTrack();}, that.options.autoSaveTime*1000 ); } else { that.options.events.autoSave = false; var mText = 'Automatisches speichern wurde deaktiviert.'; $('span', element).text(application.translate('[[aus]]')); application.controller.message.addMessage('map', mText, 'info', 3000); window.clearInterval(that.options.events.autoSaveTimer); } }, startLoading: function() { $('#abs-map-loader').show(); }, endLoading: function() { $('#abs-map-loader').hide(); }, toggleIdEditor: function(naviItem) { var that = this; if (!that.options.isIdEditorisIdEditor) { that.options.isIdEditorisIdEditor = true; var center = that.map.getCenter(); var lat = center.lat; var lon = center.lng; var zoom = that.map.getZoom(); $('#abs-map-nav .navi').hide(); $(naviItem).addClass('active').parent().show(); $('.control-fullscreen').parent().show(); $('#abs-map-nav').show(); $('
').appendTo('body').hide(); $('#abs-map').children().not('#abs-map-container').appendTo('#abs-map-temp'); $('#abs-map-container').hide(); $('#abs-map-temp').appendTo('#abs-map'); $('#abs-map-nav').appendTo('#abs-map'); $('