1 2function genMarkerIcon_dot(url) { 3 return L.icon({ 4 iconUrl: url, 5 className: "marker-cafePin", 6 popupAnchor: [0, -20], 7 iconSize: [25, 25], 8 iconAnchor: [12, 25], 9 }); 10} 11 12var green_pin = genMarkerIcon_dot('leaflet/images/green-pin.png'); 13var blue_pin = genMarkerIcon_dot('leaflet/images/blue-pin.png'); 14var grey_pin = genMarkerIcon_dot('leaflet/images/grey-pin.png'); 15 16var pinMapping = { 17 "New": green_pin, 18 "default": blue_pin, 19 "Take": blue_pin, 20 "TempClosed": grey_pin, 21}; 22 23function updateMapSize() 24{ 25 var c = $(map.getContainer()); 26 var newHeight = (window.innerHeight-c.offset().top-2); 27 if (c.height()!=newHeight) 28 { 29 c.height(newHeight+ "px"); 30 map.invalidateSize(); 31 } 32} 33 34function initMap() 35{ 36 var tileLayers = { 37 "OpenStreetMap": L.tileLayer( 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { 38 attribution: ' © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>', 39 40 maxZoom: 19, 41 minZoom: 5, 42 }), 43 "OpenCycleMap": L.tileLayer('https://{s}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png?apikey={apikey}', { 44 attribution: '© <a href="http://www.thunderforest.com/">Thunderforest</a>, © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors', 45 apikey: 'f3e5c8ab7dc9440faf167ccd39c826e0', 46 bounds:[[35, -11],[62, 18]], 47 maxZoom: 22,minZoom: 6 48 }), 49 "Esri": L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}', { 50 maxZoom: 19, minZoom: 5, 51 bounds:[[35, -11],[62, 18]], 52 attribution: 'Tiles © Esri — Source: Esri, DeLorme, <br>NAVTEQ, USGS, Intermap, iPC, NRCAN, METI, TomTom', 53 }), 54 55 "CyclOSM": L.tileLayer('https://{s}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png', { 56 attribution: '<a href="https://github.com/cyclosm/cyclosm-cartocss-style/releases" title="CyclOSM - Open Bicycle render">CyclOSM</a> | Map data: © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors', 57 maxZoom: 20,minZoom: 6, 58 59 }), 60 61 "Open MTB": L.tileLayer('https://tile.mtbmap.cz/mtbmap_tiles/{z}/{x}/{y}.png', { 62 attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors & USGS', 63 maxZoom: 18, minZoom: 6, 64 bounds:[[35, -11],[62, 18]], 65 }), 66 67 "Top Plus" : L.tileLayer('https://sgx.geodatenzentrum.de/wmts_topplus_open/tile/1.0.0/web/default/WEBMERCATOR/{z}/{y}/{x}.png', { 68 maxZoom: 16, minZoom: 5, 69 attribution: 'Map data: © <a href="http://www.govdata.de/dl-de/by-2-0">dl-de/by-2-0</a>', 70 }), 71 72 "OpenTopoMap": L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', { 73 maxZoom: 17, minZoom: 5, 74 attribution: 'Map data: © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: © <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)', 75 bounds:[[35, -11],[62, 18]], 76 }), 77 78 "Satellite": L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', { 79 maxZoom: 19, minZoom: 6, 80 attribution: 'Tiles © Esri — Source: Esri, i-cubed, <br>USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, <br>IGP, UPR-EGP, and the GIS User Community' 81 }) 82 }; 83 84 85 map = new L.map('cafemap', { 86 trackResize: true, 87 }); 88 ciLayer = L.canvasIconLayer({}).addTo(map); 89 90 tileLayers["OpenStreetMap"].addTo( map ); 91 92 L.control.layers(tileLayers).addTo(map); 93 94 L.Control.FileLayerLoad.LABEL = '<i class="fa fa-route fa"></i>', 95 L.Control.fileLayerLoad({ 96 97 position: 'topright', 98 layerOptions: {style: {color:'fuchsia'}}, 99 fileSizeLimit: 4096, 100 formats: [ 101 /*'.gpx', 102 '.geojson', 103 '.json', 104 '.kml', 105 'application/gpx+xml', 106 'application/json', 107 'application/vnd.google-earth.kml+xml'*/ 108 '' 109 ] 110 }).addTo(map); 111 112 113 if (L.Browser.mobile) { 114 map.removeControl(map.zoomControl); 115 } 116 117
118 map.setView(new L.LatLng(54.4700378,-4.3945308),6); 119 120 var doneFirstLocation = false; 121 122 function onLocationFound(e) { 123 var minZoom = 11; 124 var radius = e.accuracy / 2; 125 var newZoom = map.getZoom(); 126 if (newZoom<minZoom) 127 newZoom = minZoom; 128 map.flyTo(e.latlng, newZoom, {animate:doneFirstLocation}); 129 doneFirstLocation = true; 130 } 131 map.on('locationfound', onLocationFound); 132 map.locate({timeout:60000, maximumAge:30000}); 133 134function formatJSON(rawjson) { //callback that remap fields name 135 var json = {}, 136 key, loc, disp = []; 137 138 for(var i in rawjson) 139 { 140 disp = rawjson[i].display_name.split(','); 141 key = disp[0] +', '+ disp[1]; 142 loc = L.latLng( rawjson[i].lat, rawjson[i].lon ); 143 json[ key ]= loc; //key,value format 144 } 145 146 return json; 147 } 148 149 var SearchOpts = { 150 url: 'https://nominatim.openstreetmap.org/search?format=json&countrycodes=ie%2Cgb&q={s}', 151 jsonpParam: 'json_callback', 152 formatData: formatJSON, 153 textPlaceholder: 'Town, Place, Post Code..', 154 autoType: true, 155 tipAutoSubmit: true, 156 firstTipSubmit: true, 157 //tooltipLimit: 25, 158 textErr: "Location Not Found", 159 position: "topleft", 160 autoCollapse: true, 161 //autoCollapseTime: 5, 162 zoom: 14, 163 delayType: 50, //with mobile device typing is more slow 164 marker: { 165 icon: false 166 } 167 }; 168 169 map.addControl( new L.Control.Search(SearchOpts) ); 170 171var lc = L.control.locate({ 172 position: 'bottomright', 173 strings: { 174 title: "Show Location" 175 }, 176 locateOptions: { 177 enableHighAccuracy: true 178 }, 179 keepCurrentZoomLevel : true, 180}); 181lc.addTo(map) 182 183 var legend = L.control({position: 'bottomleft'}); 184 185 legend.onAdd = function (map) { 186 var div = L.DomUtil.create('div', 'legend'); 187 div.innerHTML += '<img src="leaflet/images/blue-pin.png">' + 'Cafe' + '<br>' 188 div.innerHTML += '<img src="leaflet/images/green-pin.png">' + 'New cafe' + '<br>' 189 div.innerHTML += '<img src="leaflet/images/grey-pin.png">' + 'Temp closed' + '<br>' 190 div.innerHTML += '<u><a href="https://cafes.cyclingmaps.net/help.php#q-Legend"target="_blank">Maps Legend</a></u>' 191 return div; 192 }; 193 194 legend.addTo(map); 195 196} 197 198function genPopupContent(c) 199{ 200 var x; 201 var popupContent = document.createElement('div'); 202 203 x = document.createElement('b'); 204 var titleTxt; 205 if (typeof c.location==="string" && c.location!="") 206 titleTxt = c.name + ", " + c.location; 207 else 208 titleTxt = c.name; 209 x.appendChild(document.createTextNode(titleTxt)); 210 popupContent.appendChild(x); 211 212 popupContent.appendChild(document.createElement('br')); 213 popupContent.appendChild(document.createTextNode(c.address)); 214 popupContent.appendChild(document.createElement('br')); 215 popupContent.appendChild(document.createTextNode(c.details)); 216 popupContent.appendChild(document.createElement('br')); 217 218 if (typeof c.phone==="string" && c.phone!="") 219 { 220 popupContent.appendChild(document.createTextNode("Tel: ")); 221 x = document.createElement('a'); 222 x.appendChild(document.createTextNode(c.phone)); 223 x.setAttribute("target", "_blank"); 224 x.setAttribute("href", "tel:"+c.phone); 225 popupContent.appendChild(x); 226 popupContent.appendChild(document.createElement('br')); 227 228 } 229 if (typeof c.email==="string" && c.email!="") 230 { 231 x = document.createElement('a'); 232 x.appendChild(document.createTextNode("Email")); 233 x.setAttribute("target", "_blank"); 234 x.setAttribute("href", "mailto:"+c.email); 235 popupContent.appendChild(x); 236 popupContent.appendChild(document.createElement('br')); 237 } 238 if (typeof c.website==="string" && c.website!="") 239 { 240 x = document.createElement('a'); 241 x.appendChild(document.createTextNode("Website")); 242 x.setAttribute("target", "_blank"); 243 x.setAttribute("href", c.website); 244 x.className = "cafe-webLink"; 245 popupContent.appendChild(x); 246 popupContent.appendChild(document.createElement('br')); 247 } 248 // Streetview 249 x = document.createElement('a'); 250 x.appendChild(document.createTextNode("Street View")); 251 x.setAttribute("target", "_blank"); 252 x.setAttribute("href", "https://www.google.com/maps/@?api=1&map_action=pano&viewpoint="+c.lat+","+c.lng); 253 x.className = "cafe-webLink"; 254 popupContent.appendChild(x);
255 if (typeof c.photo==="string" && c.photo!="") 256 { 257 x = document.createElement('img'); 258 x.className = "cafe-photo"; 259 x.setAttribute("alt", "Image"); 260 x.setAttribute("src", c.photo); 261 x.setAttribute('onclick', 'this.requestFullscreen()'); 262 popupContent.appendChild(x); 263 popupContent.appendChild(document.createElement('br')); 264 } 265 266 return popupContent; 267} 268function onCafeMarkerClick() 269{ 270 var sizeLimit = map.getSize(); 271 var margin = { 272 top:50, 273 left:36, 274 bottom:70, 275 right:4, 276 } 277 278 sizeLimit.y -= margin.top+margin.bottom +50; 279 sizeLimit.x -= margin.left+margin.right +50; 280 281 var popupContent = genPopupContent(this.options.cafe); 282 var popup = L.popup({ 283 hasTip: true, 284 autoPan: true, 285 autoPanPaddingTopLeft: L.point(margin.left,margin.top), 286 autoPanPaddingBottomRight: L.point(margin.right,margin.bottom), 287 maxWidth:(sizeLimit.x<500 ? sizeLimit.x : 500), 288 minWidth:(sizeLimit.x<200 ? sizeLimit.x : 200), 289 maxHeight:(sizeLimit.y>100 ? sizeLimit.y : 100), 290 offset: this.options.icon.options.popupAnchor, 291 }) 292 .setLatLng(this.getLatLng()) 293 294 $(popupContent).find("img").on("load error", function(){ 295 setTimeout(function(){ 296 popup.update(); 297 }, 1); 298 }); 299 popup.setContent(popupContent); 300 301 popup.openOn(map); 302 popup.update(); 303} 304 305 306function addCafeMarkers(cafes) 307{ 308 var n = cafes.length; 309 var cafes_total = cafes.length; 310 var newMarkers = []; 311 document.getElementById("cafecount").innerHTML = cafes_total; 312 313 for (var i=0; i<n; i++) 314 { 315 var c = cafes[i]; 316 var cafeIcon = pinMapping["default"]; 317 if (c.status!==null && typeof pinMapping[c.status] != "undefined") 318 // if (c.status!==null && typeof pinMapping[c.status] != "Closed") 319 cafeIcon = pinMapping[c.status]; 320 var m = L.marker([c.lat,c.lng], {icon: cafeIcon}); 321 m.options.cafe = c; 322 m.on('click', L.bind(onCafeMarkerClick, m)); 323 newMarkers.push(m); 324 } 325 ciLayer.addMarkers(newMarkers); 326 var redrawFunc = function(){ 327 ciLayer._redraw(); 328 }; 329 setTimeout(redrawFunc, 1); 330 setTimeout(redrawFunc, 1000); 331} 332 333document.onclick = (event) => { 334 if (document.fullscreenElement) { 335 document 336 .exitFullscreen() 337 .catch((err) => console.error(err)); 338 } 339 }; 340 341$(document).ready(function(){ 342 $("#cafemapLoading").html("<div>Loading cafes...</div><div id=\"cafemapLoadingProgress\"></div>"); 343 initMap(); 344 $.get({ 345 type:"GET", 346 //url:"/data/cafes.json", 347 url:"/data/cafes.json?mtime="+cafeMTime, 348 dataType:"json", 349 //cache:false, 350 cache:true, 351 xhrFields:{ 352 onprogress:function(e){ 353 if (e.lengthComputable) 354 { 355 $("#cafemapLoadingProgress").text(Math.round(e.loaded/e.total *100)+"%"); 356 } 357 }, 358 }, 359 }) 360 .done(function(data){ 361 addCafeMarkers(data); 362 $("#cafemapLoading").remove(); 363 }) 364 .fail(function(){ 365 alert("Failed to load cafes data"); 366 }); 367 setTimeout(updateMapSize,1); 368 $(window).on("orientationchange resize scroll", updateMapSize); 369});
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.