1var isTouchSupported = "ontouchend" in document; 2var delay = (function(){ 3 var timer = 0; 4 return function(callback, ms){ 5 clearTimeout (timer); 6 timer = setTimeout(callback, ms); 7 }; 8})(); 9var currentDateRange = {min:0, max:0}; 10var map; 11var trackingdata = {}; 12function allDates() { 13 daterangebounds = $("#daterange").dateRangeSlider("bounds"); 14 $("#daterange").dateRangeSlider("values", daterangebounds.min, daterangebounds.max); 15 return false; 16} 17function zoomToFit() { 18 bounds = L.latLngBounds(); 19 points = false; 20 for (i in trackingdata) { 21 if (trackingdata[i].visible) { 22 for (p in trackingdata[i].points) { 23 bounds.extend(trackingdata[i].points[p]); 24 points = true; 25 } 26 } 27 } 28 if (points) { 29 map.fitBounds(bounds); 30 } 31 return false; 32} 33function mapOnResize() { 34 var navheight_for_map = $("#tx_dbtracking_map").height()-245; 35 var navheight_for_nav = $("#tx_dbtracking_map li").length*$("#tx_dbtracking_map li").height()*1.5+10; 36 var navheight = navheight_for_nav;
37 if (navheight_for_map<navheight) 38 navheight = navheight_for_map; 39 $("#tx_dbtracking_map .tx_dbtracking_nav").height(navheight); 40 $(".daterange").width($("#tx_dbtracking_map").width()-36); 41 $("#daterange").width($("#tx_dbtracking_map").width()-160); 42 $("#daterange").dateRangeSlider("resize"); 43 setTimeout(function(){ map.invalidateSize()}, 400); 44} 45$(document).ready(function() { 46 $(window).resize(function() { 47 mapOnResize(); 48 }); 49 function daterangeChanged(daterange) { 50 currentDateRange.min = Math.round(daterange.values.min.getTime()/1000); 51 currentDateRange.max = Math.round(daterange.values.max.getTime()/1000); 52 for (i in trackingdata) { 53 if (trackingdata[i].visible) { 54 trackingdata[i].refreshLayer(); 55 } 56 } 57 } 58 59 var currentDateRange = {min:0, max:0}; 60 function updateDaterange() { 61 var timestamp_min = false; 62 var timestamp_max = false; 63 for (i in trackingdata) { 64 animal = trackingdata[i]; 65 if (animal.visible) { 66 if (timestamp_min===false || animal.timestamp_min<timestamp_min) 67 { timestamp_min = animal.timestamp_min; } 68 if (timestamp_max===false || animal.timestamp_max>timestamp_max) 69 { timestamp_max = animal.timestamp_max; } 70 } 71 }; 72 $("#daterange").dateRangeSlider("bounds", new Date(timestamp_min*1000), new Date(timestamp_max*1000)); 73 if (toLoad==0) { 74 // all initial data has been loaded 75 $("#daterange").show(); 76 $("#daterange").bind("valuesChanged", function(e, data){ 77 daterangeChanged(data); 78 if (initializing && toLoad==0) { 79 80 allDates(); 81 setTimeout(function() { 82 if (mapPositionMode=='showall') { 83 zoomToFit(); 84 } 85 else if (mapPositionMode=='lastfix') { 86 for (key in trackingdata) break; 87 if (trackingdata[key].markers.length>0) { 88 point = trackingdata[key].markers[trackingdata[key].markers.length-1].getLatLng();
89 map.setView(point, mapZoom); 90 } 91 } 92 else if (mapPositionMode=='manual') { 93 map.setView([mapCenter[0], mapCenter[1]], mapZoom); 94 } 95 initializing = false; 96 $("#tx_dbtracking_map").css("visibility", "visible"); 97 }, 500); 98 } 99 }); 100 $("#daterange").dateRangeSlider("values", new Date(0), new Date(1)); 101 $("#daterange").dateRangeSlider("values", new Date(timestamp_min*1000), new Date(timestamp_max*1000)); 102 allDates(); 103 } 104 } 105 var year = false; 106 var toLoad = 0; 107 map = L.map("tx_dbtracking_map", { 108 center: mapCenter, 109 zoom: mapZoom, 110 minZoom: 2, 111 maxZoom: 14, 112 zoomControl: false 113 }); 114 var layerStandard = L.tileLayer('https://{s}.tile.openstreetmap.de/{z}/{x}/{y}.png', { 115 minZoom: 1, 116 maxZoom: 14, 117 attribution: '© <a href="https://openstreetmap.org/copyright">OpenStreetMap contributors</a>' 118 }).addTo(map); 119 var layerSat = L.layerGroup(); 120 // SAT needs mapbox api key 121 /* 122 var layerSat = L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', { 123 attribution: 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>', 124 minZoom: 1, 125 maxZoom: 14, 126 id: 'mapbox/satellite-streets-v11', 127 tileSize: 512, 128 zoomOffset: -1, 129 accessToken: 'mapboxapikey' 130 }); 131 */ 132 // topgraphisch 133 var layerOutdoors = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', { 134 minZoom: 1, 135 maxZoom: 14, 136 attribution: '© <a href="https://openstreetmap.org/copyright">OpenStreetMap</a>-Mitwirkende, SRTM | Kartendarstellung: © <a href="http://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)' 137 }); 138 139 var ctrlLayerSelector = L.control({position: 'topleft'}); 140 ctrlLayerSelector.onAdd = function (map) { 141 var div = L.DomUtil.create('div', 'leaflet-bar info mycontrol'); 142 div.innerHTML = '<div class="btn-group"><button id="layer-standard" class="changemaplayer btn btn-sm btn-primary active">Karte</button><!-- button id="layer-sat" class="changemaplayer btn btn-sm btn-primary">Satellit</button--><button id="layer-outdoors" class="changemaplayer btn btn-sm btn-primary">Gelände</button></div>'; 143 return div; 144 }; 145 ctrlLayerSelector.addTo(map); 146 $("#layer-sat").on("click", function() { 147 if ($(this).hasClass("active")) return; 148 map.removeLayer(layerStandard).removeLayer(layerOutdoors).addLayer(layerSat); 149 $(".changemaplayer").removeClass("active"); 150 $(this).addClass("active"); 151 }); 152 $("#layer-standard").on("click", function() { 153 if ($(this).hasClass("active")) return; 154 map.removeLayer(layerSat).removeLayer(layerOutdoors).addLayer(layerStandard); 155 $(".changemaplayer").removeClass("active"); 156 $(this).addClass("active"); 157 }); 158 $("#layer-outdoors").on("click", function() { 159 if ($(this).hasClass("active")) return; 160 map.removeLayer(layerSat).removeLayer(layerStandard).addLayer(layerOutdoors); 161 $(".changemaplayer").removeClass("active"); 162 $(this).addClass("active"); 163 }); 164 var zoomControl = L.control.zoom().addTo(map); 165 map.addControl(new L.Control.Fullscreen()); 166 map.on('fullscreenchange', function () { 167 if (map.isFullscreen()) { 168 $("#pageheader").css("zIndex", 1); 169 } 170 else { 171 $("#pageheader").css("zIndex", 11); 172 } 173 mapOnResize(); 174 175 }); 176 var loadingindicator = L.control({position: 'topright'}); 177 loadingindicator.onAdd = function () { 178 var div = L.DomUtil.create('div', 'leaflet-bar info mycontrol loadingindicator'); 179 div.innerHTML = '<div class="content">Daten werden geladen ...</div>'; 180 return div; 181 }; 182 var daterangeControl = L.control({position: 'bottomright'}); 183 daterangeControl.onAdd = function () { 184 var div = L.DomUtil.create('div', 'leaflet-bar info mycontrol daterange'); 185 div.innerHTML = '<div id="alldates"><a href="#" onclick="return allDates();" title="Unset date limit"></a></div><div id="daterange"></div>'; 186 L.DomEvent.on(div, 'click dblclick', function(ev) { 187 L.DomEvent.stopPropagation(ev); 188 }); 189 L.DomEvent.on(div, 'mouseover touchstart', function(ev) { 190 map.dragging.disable(); 191 }); 192 L.DomEvent.on(div, 'mouseout touchend', function(ev) { 193 map.dragging.enable(); 194 }); 195 return div; 196 }; 197 map.addControl(daterangeControl); 198 199 200 var selectanimalControl = L.control({position: 'topright'}); 201 selectanimalControl.onAdd = function () { 202 var div = L.DomUtil.create('div', 'leaflet-bar info mycontrol selectanimal'); 203 var html = '<ul class="tx_dbtracking_nav">'+$(".tx_dbtracking_nav").html()+'</ul>' 204 $(".tx_dbtracking_nav").remove(); 205 div.innerHTML = html; 206 L.DomEvent.on(div, 'click dblclick', function(ev) { 207 L.DomEvent.stopPropagation(ev); 208 }); 209 L.DomEvent.on(div, 'mousewheel mouseover touchstart', function(ev) { 210 map.dragging.disable(); 211 map.scrollWheelZoom.disable(); 212 }); 213 L.DomEvent.on(div, 'mousewheel mouseout touchend', function(ev) { 214 map.dragging.enable(); 215 map.scrollWheelZoom.disable(); 216 }); 217 return div; 218 }; 219 map.addControl(selectanimalControl); 220 221 var showallControl = L.control({position: 'bottomright'}); 222 showallControl.onAdd = function () { 223 var div = L.DomUtil.create('div', 'leaflet-bar info mycontrol showall'); 224 div.innerHTML = '<div id="zoomout"><a href="#" onclick="return zoomToFit();" title="Pan/Zoom to show all points"></a></div>'; 225 L.DomEvent.on(div, 'click dblclick', function(ev) { 226 L.DomEvent.stopPropagation(ev); 227 }); 228 return div; 229 }; 230 map.addControl(showallControl); 231 232 233 $(".animaltoggle").prop('checked', false); 234 $('#daterange').dateRangeSlider({ 235 arrows: true, 236 step: {"days":1}, 237 formatter: function(d) { 238 return $.datepicker.formatDate('dd.mm.yy', d); 239 } 240 }); 241 initializing = true; 242 $.each($(".animaltoggle"), function() { 243 if (toLoad!=preselect) { 244 $(this).prop('checked', true); 245 toLoad = toLoad+1; 246 toggleAnimal($(this)); 247 } 248 }); 249 mapOnResize(); 250 $(".animaltoggle").on("click", function() { 251 toggleAnimal($(this)); 252 }); 253 $("#daterange, li, #zoomout, #alldates").tooltip(); 254 // toggle animals, load trackingdata 255 function toggleAnimal(control) { 256 if (!trackingdata[$(control).attr("id")]) { 257 $(".ui-tooltip").remove(); 258 setstatus("Loading "+$(control).data("name")+" ...", false); 259 $.getJSON($(control).data("url"), '', function(data, textStatus, jqXHR) { 260 trackingdata[$(control).attr("id")] = new AnimalTrack(map, $(control).attr("id"), data); 261 setstatus(trackingdata[$(control).attr("id")].animal.name+": Loaded "+trackingdata[$(control).attr("id")].markers.length+ " points.", true); 262 toggleAnimal(control); 263 allDates(); 264 }); 265 return; 266 } 267 if ($(control).prop('checked')) { 268 trackingdata[$(control).attr("id")].show(); 269 } 270 else { 271 trackingdata[$(control).attr("id")].hide(); 272 } 273 toLoad = toLoad-1; 274 if (toLoad<0) toLoad = 0; 275 updateDaterange(map); 276 } 277 function setstatus(newStatus, fadeOut) { 278 map.addControl(loadingindicator); 279 $(".loadingindicator .content").show(); 280 $(".loadingindicator .content").html(newStatus); 281 if (fadeOut) { 282 delay(function() { 283 $(".loadingindicator .content").fadeOut(1000); 284 delay(function() { 285 loadingindicator.remove(); 286 }, 1000); 287 }, 1000); 288 } 289 } 290 291 var colors = { 292 0: "#ff0000", 293 1: "#00ff00", 294 2: "#ff00ff", 295 3: "#0000ff", 296 4: "#ffff00" 297 } 298 var circleStyle = function(color, size) { 299 if (size==1) radius = 4; 300 if (size>1) radius = 6; 301 if (size>5) radius = 8; 302 if (size>10) radius = 10; 303 304 return { 305 fillColor: color, 306 radius: radius, 307 stroke: true, 308 color: "black", 309 weight: 0.75, 310 opacity: 0.7, 311 fillOpacity: 0.75, 312 className: "marker", 313 pane: "markerPane" 314 }; 315 }; 316 function AnimalTrack(map, animal, data) { 317 var me = this; 318 this.layer = L.layerGroup().addTo(map); 319 this.polylinelayer = L.layerGroup().addTo(map); 320 this.id = animal; 321 this.animal = data.animal; 322 this.color = colors[this.animal.color]; 323 this.points = []; 324 this.markers = []; 325 this.polyline = 0; 326 this.arrowHead = 0; 327 this.visible = true; 328 this.initialized = false;
329 this.timestamp_min = Number.MAX_VALUE; 330 this.timestamp_max = 0; 331 this.info = ''; 332 if (!data) 333 return false; 334 this.uid = data.animal.uid; 335 this.initialized = true; 336 if (data.timestamp_min && data.timestamp_max) { 337 this.timestamp_min = data.timestamp_min; 338 this.timestamp_max = data.timestamp_max; 339 } 340 if (data.points.length>0) { 341 this.info = data.points.length+ " Points.<br />"+(new Date(this.timestamp_min*1000).format("d.m.Y"))+" - "+(new Date(this.timestamp_max*1000).format("d.m.Y")); 342 if (this.animal.description) 343 this.info += "<br /><hr />"+this.animal.description; 344 } 345 else { 346 this.info = "No data."; 347 } 348 $("#nav"+this.id).tooltip({content: this.info}); 349 350 this.refreshLayer = function() { 351 if (this.polyline) { 352 this.polyline.removeFrom(this.polylinelayer); 353 } 354 if (this.arrowHead) { 355 this.arrowHead.removeFrom(this.polylinelayer); 356 } 357 this.points = []; 358 for (m=0; m<this.markers.length; m++) { 359 if (this.markers[m].dbt_timestamp_end>=currentDateRange.min 360 && this.markers[m].dbt_timestamp<=currentDateRange.max+60*60*24) { 361 this.markers[m].addTo(this.layer); 362 this.points.push(this.markers[m].dbt_point); 363 } 364 else { 365 this.markers[m].removeFrom(this.layer); 366 } 367 } 368 this.polyline = L.polyline(this.points, {color: this.color, weight: 2}).addTo(this.polylinelayer); 369 this.arrowHead = L.polylineDecorator(this.polyline, { 370 patterns: [ 371 {repeat: 100, offset: 50, offsetEnd: 50, symbol: L.Symbol.arrowHead({pixelSize: 15, polygon: false, pathOptions: {color: this.color, stroke: true}})} 372 ] 373 }).addTo(this.polylinelayer); 374 } 375 376 this.addPoint = function(lat, lng, text, size, timestamp, timestamp_end, uid) { 377 if (size) { 378 var markerTooltip = document.createElement("div"); 379 markerTooltip.innerHTML = '<b>' + this.animal.name + '</b><br />' + text ; 380 var point = [lat, lng]; 381 this.points.push(point); 382 var marker = L.circleMarker(point, circleStyle(this.color, size)).addTo(this.layer); 383 marker.dbt_timestamp = timestamp; 384 marker.dbt_timestamp_end = timestamp_end; 385 marker.dbt_point = point; 386 var pop = L.popup().setContent(markerTooltip); 387 marker.bindPopup(pop); 388 this.markers.push(marker); 389 } 390 }; 391 392 var that = this; 393 $.each(data.points, function(i, point) { 394 me.addPoint ( parseFloat(point.lat), 395 parseFloat(point.lng), 396 point.text, 397 point.size, 398 point.timestamp, 399 point.timestamp_end, 400 that.uid 401 ); 402 }); 403 this.refreshLayer(); 404 405 this.show = function() { 406 if (this.visible) 407 return; 408 if (this.markers.length==0) { 409 setstatus(this.animal.name+": no data!", true); 410 return; 411 } 412 this.layer.addTo(map); 413 this.polylinelayer.addTo(map); 414 this.refreshLayer(); 415 this.visible = true; 416 } 417 this.hide = function() { 418 if (!this.visible) 419 return; 420 this.layer.removeFrom(map); 421 this.polylinelayer.removeFrom(map); 422 this.visible =false; 423 } 424 425 426 } 427}); 428
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.