1/* global WiGLE, require, minLat, minLon, maxLat, maxLon, round*/ 2 3WiGLE.mapControlsBusy = function(busy, message) { 4 if (busy) { 5 $('<div class="wigle-search-modal-overlay" style="display: block"><a href="/index" class="mapBar-search" id="homeplanetmodal"><img src="/images/planet-bubble.png" height="60" width="60" class="fadeBubble"></a><div class="searchInProgressMessage">'+message+'</div></div>').appendTo($("#mapBar")); 6 } else { 7 $(".wigle-search-modal-overlay").remove(); 8 /* ALIBI: ERSI's fetchTile isn't redrawing dynamically - probably a bug, but in the meantime, nudge the map on complete to force a tile redraw. */ 9 let centerLat = WiGLE.mapView.center.latitude; 10 let centerLon = WiGLE.mapView.center.longitude; 11 WiGLE.mapView.center = [centerLon, centerLat]; 12 } 13 $(".mapfilter").prop( "disabled", busy); 14} 15WiGLE.handleSuccess = function() { WiGLE.mapControlsBusy( false ); } 16WiGLE.handleFailure = function (reason) { WiGLE.mapControlsBusy( false ); } 17 18WiGLE.updateOverlays = function() { 19 require([
20 //"esri/core/watchUtils", 21 "esri/core/reactiveUtils", 22 ], function(reactiveUtils) { 23 WiGLE.requestTrailer = WiGLE.buildRequestTrailer("e1"); 24 if (WiGLE.map) { 25 try { 26 var tileLayer = WiGLE.map.findLayerById('wigle-tiles'); 27 } catch (err) { 28 //IGNORE 29 } 30 $(".mapfilter").prop( "disabled", true ); 31 WiGLE.mapControlsBusy(true, 'updating...'); 32 const refreshPromise = new Promise((resolve, reject) => { 33 tileLayer.refresh(); 34 //.then((layerView) => watchUtils.whenFalseOnce(layerView, "updating", () => resolve())) 35 WiGLE.mapView.whenLayerView(tileLayer) 36 .then((layerView) => reactiveUtils.when( 37 () => layerView.updating === false, 38 () => { 39 resolve(); 40 }, 41 { once: true })) 42 .catch((reason) => reject(reason)); 43 }); 44 refreshPromise.then(WiGLE.handleSuccess, WiGLE.handleFailure); 45 } 46 return true;}); 47} 48 49// really? this isn't a built-in? 50// what kind of clown show f'd up joke language is this? 51// copied below from: https://javascript.plainenglish.io/here-are-2-javascript-approaches-to-encode-decode-html-entities-52989bb12031 52function encodeHTMLEntities(text) { 53 let textArea = document.createElement('textarea'); 54 textArea.innerText = text; 55 let encodedOutput=textArea.innerHTML; 56 let arr=encodedOutput.split('<br>'); 57 encodedOutput=arr.join('\n'); 58 return encodedOutput; 59} 60 61WiGLE.initializeMap = function() { 62 // set configuration before loading anything else 63 require([ 64 "esri/config" 65 ], function(esriConfig) { 66 esriConfig.request.trustedServers.push("https://wigle.net"); 67 esriConfig.request.trustedServers.push("https://www.wigle.net"); 68 esriConfig.request.trustedServers.push("https://api.wigle.net"); 69 esriConfig.apiKey = "AAPTaH5TGUPNPUFaMsbJdJpK0wQ..A2FvxlDj4C84_lL4konpJ0gkw0RZqcNCyQziSQJ_JlvnaJraL6E9ffF8fJjMMmhoHKbtDPYyZ2RT8SUx1N5c-Ket_rFi8AY35w3P99xOFXj2GBBjoGBq9C6RLMaibySXC_5KMrk_fA0S3PhjTbtAjTs-lHevCieuGzYeZLv4peDJ7oJUucfaiSjUiVrqVRqiTnSo93vnyI6SC0LeNIfCRFnyvhM_OjKhcaOv4aBq1UoNplT4m2j47kprS9n33ZpY2I6BAT1_T8NqwE8o"; 70 }); 71 72 require([
73 "esri/Map", 74 "esri/views/MapView", 75 // "esri/core/watchUtils", 76 "esri/core/reactiveUtils", 77 "esri/layers/TileLayer", 78 "esri/layers/BaseTileLayer", 79 "esri/layers/support/TileInfo", 80 "esri/geometry/support/webMercatorUtils", 81 "esri/geometry/Point", 82 "esri/widgets/Search", 83 "esri/request", 84 "esri/config" 85 ], function(Map, MapView, reactiveUtils, TileLayer, BaseTileLayer, TileInfo, webMercatorUtils, Point, Search, esriRequest, esriConfig) { 86 87 var WiGLETileLayer = BaseTileLayer.createSubclass({ 88 // properties of the custom tile layer 89 constructor() { 90 this.tileInfo = TileInfo.create({ 91 size: 512, 92 spatialReference: { wkid: 102100 } 93 }); 94 }, 95 getTileUrl: function (level, row, col) { 96 return "https://"+location.host+"/tile?tileX=" + col + "&tileY=" + row + "&tileZoom=" + level + "&sizeX=512&sizeY=512" 97 + WiGLE.requestTrailer; 98 } 99 }); 100 101 var tileLayer = new WiGLETileLayer({title: "WiGLE Tiles", id: "wigle-tiles"}); 102 103 var basemapName = WiGLE.getStyleForKey(WiGLE.params['mapstyle']); 104 105 WiGLE.map = new Map({ 106 basemap: basemapName, 107 layers: [ tileLayer ] 108 }); 109 110 var initialZoom = parseInt(WiGLE.params['mapzoom']); 111 if (initialZoom < 2) { 112 initialZoom = 2; 113 } 114 if (initialZoom > 21) { 115 initialZoom = 21; 116 } 117 WiGLE.mapView = new MapView({ 118 container: "map_canvas", 119 map: WiGLE.map, 120 center: [WiGLE.params['maplon'],WiGLE.params['maplat']], 121 zoom: initialZoom, 122 constraints: { maxZoom: 21, minZoom: 2} 123 }); 124 125 if ("/mapsearch" !== document.location.pathname) { 126 try { 127 var searchWidget = new Search({ 128 view: WiGLE.mapView 129 }); 130 131 WiGLE.mapView.ui.add(searchWidget, { 132 position: "top-left", 133 index: 0 134 }); 135 } catch (err) { 136 console.log('unable to load search tool.'); 137 } 138 } 139 140 function updateCoordinates(evt) { 141 isMoving(webMercatorUtils.xyToLngLat(WiGLE.mapView.extent.xmax, WiGLE.mapView.extent.ymax), 142 webMercatorUtils.xyToLngLat(WiGLE.mapView.extent.xmin, WiGLE.mapView.extent.ymin)); 143 } 144 145 //watchUtils.whenTrue(WiGLE.mapView, "stationary", function() { 146 reactiveUtils.when( 147 () => WiGLE.mapView.stationary === true, 148 () => { 149 if (WiGLE.mapView.extent) { 150 //console.log(WiGLE.mapView.extent); 151 isMoving(webMercatorUtils.xyToLngLat(WiGLE.mapView.extent.xmax, WiGLE.mapView.extent.ymax), 152 webMercatorUtils.xyToLngLat(WiGLE.mapView.extent.xmin, WiGLE.mapView.extent.ymin)); 153 WiGLE.getMapLink(); 154 } 155 }); 156 157 WiGLE.mapView.when(function() { 158 WiGLE.mapView.on('drag',updateCoordinates); 159 WiGLE.mapView.on('resize',updateCoordinates); 160 }); 161 162 WiGLE.activateShowHideControls(); 163 WiGLE.activateFilterButtons(); 164 165 // nearest network pop-up 166 function getTitleSuffix2(inputLat, inputLon) { 167 const lat = Math.round(inputLat * 1000) / 1000; 168 const lon = Math.round(inputLon * 1000) / 1000; 169 return " (lat: " + lat + ", lon: " + lon + ")"; 170 } 171 function getTitleSuffix(event) { 172 return getTitleSuffix2(event.mapPoint.latitude, event.mapPoint.longitude); 173 } 174 175 function queryNearestNetwork(event, popup) { 176 const eventLat = event.mapPoint.latitude; 177 const eventLon = event.mapPoint.longitude; 178 const extent = WiGLE.mapView.extent; 179 const fudge = 0.5; 180 const max = webMercatorUtils.xyToLngLat(extent.xmax, extent.ymax); 181 const min = webMercatorUtils.xyToLngLat(extent.xmin, extent.ymin); 182 maxLat = max[1]; 183 minLat = min[1]; 184 maxLon = max[0]; 185 minLon = min[0]; 186 187 var lat1 = eventLat-fudge; 188 var lat2 = eventLat+fudge; 189 var lon1 = eventLon-fudge; 190 var lon2 = eventLon+fudge; 191 192 // truncate search space to current viewport 193 if (lat1 < minLat) {lat1 = minLat} 194 if (lat2 > maxLat) {lat2 = maxLat} 195 if (lon1 < minLon) {lon1 = minLon} 196 if (lon2 > maxLon) {lon2 = maxLon} 197 198 // execute the query 199 // url = "https://api.wigle.net/api/v2/stats/site" 200 const url = "https://api.wigle.net/api/v2/network/search?resultsPerPage=1" 201 + "&closestLat=" + eventLat 202 + "&closestLong=" + eventLon 203 + "&latrange1=" + lat1 204 + "&latrange2=" + lat2 205 + "&longrange1=" + lon1 206 + "&longrange2=" + lon2 207 const titleSuffix = getTitleSuffix(event); 208 return esriRequest(url, { 209 responseType: "json" 210 }).then(function(response){ 211 // Happy response 212 if (response.data['resultCount'] != 1) { 213 popup.title = "Sorry" + titleSuffix; 214 popup.content = "None found"; 215 } 216 else { 217 network = response.data['results'][0]; 218 const netLat = network['trilat']; 219 const netLon = network['trilong']; 220 // new point in web mercator 221 popup.location = new Point({ 222 latitude: netLat, 223 longitude: netLon, 224 spatialReference: { 225 wkid: 3857 226 } 227 }); 228 popup.title = "Nearest Network" + getTitleSuffix2(netLat, netLon); 229 var address = ""; 230 if (network['housenumber']) {address += network['housenumber'] + " ";} 231 if (network['road']) {address += network['road'];} 232 if (network['city']) {address += ", " + network['city'];} 233 if (network['region']) {address += ", " + network['region'];} 234 if (network['country']) {address += ", " + network['country'];} 235 if (network['postalcode']) {address += ", " + network['postalcode'];} 236 237 popup.content = "SSID: " + encodeHTMLEntities(network['ssid']) 238 + "<br>BSSID: " + network['netid'] 239 + "<br>First Time: " + network['firsttime'] 240 + "<br>Last Time: " + network['lasttime'] 241 + "<br>Channel: " + network['channel'] 242 + "<br>Encryption: " + network['encryption'] 243 + "<br>Quality of Signal: " + network['qos'] 244 + "<br>Address: " + address; 245 } 246 }).catch(function(error){ 247 // Error 248 console.log("error on request: " + error.message); 249 const httpStatus = error.details.httpStatus; 250 if (httpStatus == 401) { 251 popup.title = "Not Logged In" + titleSuffix; 252 popup.content = "Login to WiGLE to use this feature!" 253 } 254 else if (httpStatus == 429) { 255 popup.title = "Too Many Requests" + titleSuffix; 256 popup.content = "Too many requests of this type today for this account"; 257 } 258 else if (httpStatus == 412) { 259 popup.title = "Unverified Email Address" + titleSuffix; 260 popup.content = "Click on link in verification email for this account"; 261 } 262 else { 263 popup.title = "Error" + titleSuffix; 264 popup.content = "Error response: " + error.message; 265 } 266 }); 267 } 268 269 if (!WiGLE.mapView.popup) WiGLE.mapView.popup = new Popup(); 270 271 WiGLE.mapView.popup.autoOpenEnabled = false;
272 if (!WiGLE.mapView.popup.dockOptions) WiGLE.mapView.popup.dockOptions = {}; 273 WiGLE.mapView.popup.dockOptions.position = "bottom-left"; 274 275 // https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#popupEnabled 276 // Disable the popup from automatically appearing and 277 // open the popup manually using a click event. 278 WiGLE.mapView.popupEnabled = false; 279 WiGLE.mapView.on("click", (event) => { 280 WiGLE.mapView.openPopup({ 281 // Set the popup's title to the coordinates of the clicked location 282 title: "Loading..." + getTitleSuffix(event), 283 location: event.mapPoint, // Set the location of the popup to the clicked location 284 content: queryNearestNetwork(event, WiGLE.mapView.popup) 285 }); 286 }); 287 }); 288 289 if ( (navigator.geolocation) && (WiGLE.defaultloc === true) ) { 290 WiGLE.params['mapzoom'] = 13; 291 var ua = navigator.userAgent.toLowerCase(); 292 if ( (ua.indexOf('safari') != -1) && (ua.indexOf('chrome')== -1)) { 293 setTimeout(function(){ 294 navigator.geolocation.getCurrentPosition(function (position) { 295 WiGLE.params['maplon'] = position.coords.longitude; 296 WiGLE.params['maplat'] = position.coords.latitude; 297 try { 298 WiGLE.mapView.center = [position.coords.longitude, position.coords.latitude]; 299 } catch (e) { 300 // just supress 301 } 302 WiGLE.defaultloc = false; 303 }, WiGLE.mapGeoError, {timeout:10000}); 304 },1000); 305 console.log("Dear Safari Users: your browser still won't stop bouncing on location"); 306 } else { 307 navigator.geolocation.getCurrentPosition(function (position) { 308 WiGLE.params['maplon'] = position.coords.longitude; 309 WiGLE.params['maplat'] = position.coords.latitude; 310 try { 311 WiGLE.mapView.center = [position.coords.longitude, position.coords.latitude]; 312 } catch (e) { 313 // just supress 314 } 315 WiGLE.defaultloc = false; 316 }, WiGLE.mapGeoError, {timeout:10000}); 317 } 318 } else { 319 WiGLE.defaultloc = false; 320 } 321 322 WiGLE.mapFormSync(); 323 324 WiGLE.updateControlsFromRequest(); 325 326 WiGLE.requestTrailer = WiGLE.buildRequestTrailer("e2"); 327 328 //TODO: set windows size? 329 WiGLE.getMapLink(); 330} 331 332WiGLE.activateStyleSelect = function() { 333 //ALIBI: because ESRI has satellite as a basemap (not a layer) add the distinct basemap to dropdown 334 $('#mapstyle').append( new Option('Satellite','satellite') ); 335 $('#mapstyle').append( new Option('Hybrid','hybrid') ); 336 337 $('select#mapstyle').change(function () { 338 var selectedMapStyle = null; 339 $( "select#mapstyle option:selected" ).each(function() { 340 selectedMapStyle = $( this ).val(); 341 }); 342 //console.log("chose: " +WiGLE.getStyleForKey(selectedMapStyle)); 343 WiGLE.params['mapstyle'] = selectedMapStyle; 344 WiGLE.map.basemap = WiGLE.getStyleForKey(selectedMapStyle); 345 WiGLE.getMapLink(); 346 }); 347} 348 349WiGLE.getStyleForKey = function(key) { 350 if (typeof key === 'undefined') { 351 var defaultKey = WiGLE.getMapStyleKeyForDefault(); 352 if (typeof defaultKey === 'undefined' || defaultKey === key) { 353 return WiGLE.defaultMapStyle; 354 } 355 return WiGLE.getStyleForKey(defaultKey); 356 } 357 if ("night" === key) { 358 return 'streets-night-vector'; 359 } else if ("grey" === key) { 360 return 'gray-vector'; 361 } else if ("standard" === key) { 362 return 'streets-navigation-vector'; 363 } else if ("satellite" === key) { 364 return 'satellite'; 365 } else if ("hybrid" === key) { 366 return 'hybrid'; 367 } 368 return WiGLE.defaultMapStyle; 369} 370 371WiGLE.getMapLink = function () { 372 if (typeof WiGLE.mapView !== 'undefined') { 373 var linkParams = WiGLE.getMapParams(); 374 $("#savelinkhereID").attr("save-params", linkParams+'&save=on'); 375 } 376 377 var urlParams = WiGLE.getMapParams(); 378 379 var linkLocation = document.location.protocol +"//"+ document.location.hostname + document.location.pathname; 380 if (typeof urlParams !== 'undefined') { 381 linkLocation = linkLocation + "?" + urlParams; 382 //console.log(linkLocation); 383 var path = document.URL; 384 if (path.indexOf(WiGLE.mapPage) > -1) { 385 window.history.replaceState(null, null, linkLocation); 386 } 387 } 388 return linkLocation; 389} 390 391WiGLE.getMapParams = function() { 392 if (typeof WiGLE.mapView !== 'undefined') { 393 var center = WiGLE.mapView.center; 394 var lat = center.latitude; 395 var lon = center.longitude; 396 var zoom = WiGLE.mapView.zoom; 397 var mapstyle = ""; 398 if (typeof WiGLE.params['mapstyle'] !== 'undefined') { 399 mapstyle = "&mapstyle=" + WiGLE.params['mapstyle']; 400 } 401 return "maplat=" 402 + lat + "&maplon=" + lon + "&mapzoom=" + zoom 403 + mapstyle + WiGLE.buildRequestTrailer("e3"); 404 } 405} 406 407const isMoving = function(max, min) { 408 maxLat = round( max[1], 4 ); 409 minLat = round( min[1], 4 ); 410 maxLon = round( max[0], 4 ); 411 minLon = round( min[0], 4 ); 412 if ($('#displaylat').length > 0) { 413 $('#displaylat').val(minLat + " to " + maxLat); 414 $('#displaylon').val(minLon + " to " + maxLon); 415 } 416 417 var lat = WiGLE.mapView.center.latitude; 418 var lon = WiGLE.mapView.center.longitude; 419 var zoom = WiGLE.mapView.zoom; 420 if ($('#update').length > 0) { 421 document.forms["update"].maplat.value = lat; 422 document.forms["update"].maplon.value = lon; 423 document.forms["update"].mapzoom.value = zoom; 424 } else if ($('#searchForm').length > 0){ 425 $('#latrange1').val(minLat); 426 $('#latrange2').val(maxLat); 427 $('#longrange1').val(minLon); 428 $('#longrange2').val(maxLon); 429 } 430 WiGLE.params['maplat'] = lat; 431 WiGLE.params['maplon'] = lon; 432 WiGLE.params['mapzoom'] = zoom; 433} 434 435//setWindowSize(); 436//window.onresize = windowResize; 437
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.