PageSourceSearch

https://wigle.net/js/esrimap.js

js wigle.net collected 2026-10-01 09:08:47 UTC 16,381 bytes, 437 lines download raw bytes

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.