PageSourceSearch

https://collegelearners.org/wp-content/plugins/wp-realestate/assets/js/leaflet/Control.Geocoder.js?ver=1.5.1

js collegelearners.org collected 2026-10-02 21:22:22 UTC 48,134 bytes, 1,650 lines download raw bytes

1/* @preserve
2 * Leaflet Control Geocoder 1.8.2
3 * https://github.com/perliedman/leaflet-control-geocoder
4 *
5 * Copyright (c) 2012 sa3m (https://github.com/sa3m)
6 * Copyright (c) 2018 Per Liedman
7 * All rights reserved.
8 */
9
10this.L = this.L || {};
11this.L.Control = this.L.Control || {};
12this.L.Control.Geocoder = (function (L) {
13  'use strict';
14
15  L = L && L.hasOwnProperty('default') ? L['default'] : L;
16
17  var lastCallbackId = 0;
18
19  // Adapted from handlebars.js
20  // https://github.com/wycats/handlebars.js/
21  var badChars = /[&<>"'`]/g;
22  var possible = /[&<>"'`]/;
23  var escape = {
24    '&': '&amp;',
25    '<': '&lt;',
26    '>': '&gt;',
27    '"': '&quot;',
28    "'": '&#x27;',
29    '`': '&#x60;'
30  };
31
32  function escapeChar(chr) {
33    return escape[chr];
34  }
35
36  function htmlEscape(string) {
37    if (string == null) {
38      return '';
39    } else if (!string) {
40      return string + '';
41    }
42
43    // Force a string conversion as this will be done by the append regardless and
44    // the regex test will do this transparently behind the scenes, causing issues if
45    // an object's to string has escaped characters in it.
46    string = '' + string;
47
48    if (!possible.test(string)) {
49      return string;
50    }
51    return string.replace(badChars, escapeChar);
52  }
53
54  function jsonp(url, params, callback, context, jsonpParam) {
55    var callbackId = '_l_geocoder_' + lastCallbackId++;
56    params[jsonpParam || 'callback'] = callbackId;
57    window[callbackId] = L.Util.bind(callback, context);
58    var script = document.createElement('script');
59    script.type = 'text/javascript';
60    script.src = url + getParamString(params);
61    script.id = callbackId;
62    document.getElementsByTagName('head')[0].appendChild(script);
63  }
64
65  function getJSON(url, params, callback) {
66    var xmlHttp = new XMLHttpRequest();
67    xmlHttp.onreadystatechange = function() {
68      if (xmlHttp.readyState !== 4) {
69        return;
70      }
71      if (xmlHttp.status !== 200 && xmlHttp.status !== 304) {
72        callback('');
73        return;
74      }
75      callback(xmlHttp.response);
76    };
77    xmlHttp.open('GET', url + getParamString(params), true);
78    xmlHttp.responseType = 'json';
79    xmlHttp.setRequestHeader('Accept', 'application/json');
80    xmlHttp.send(null);
81  }
82
83  function template(str, data) {
84    return str.replace(/\{ *([\w_]+) *\}/g, function(str, key) {
85      var value = data[key];
86      if (value === undefined) {
87        value = '';
88      } else if (typeof value === 'function') {
89        value = value(data);
90      }
91      return htmlEscape(value);
92    });
93  }
94
95  function getParamString(obj, existingUrl, uppercase) {
96    var params = [];
97    for (var i in obj) {
98      var key = encodeURIComponent(uppercase ? i.toUpperCase() : i);
99      var value = obj[i];
100      if (!L.Util.isArray(value)) {
101        params.push(key + '=' + encodeURIComponent(value));
102      } else {
103        for (var j = 0; j < value.length; j++) {
104          params.push(key + '=' + encodeURIComponent(value[j]));
105        }
106      }
107    }
108    return (!existingUrl || existingUrl.indexOf('?') === -1 ? '?' : '&') + params.join('&');
109  }
110
111  var ArcGis = L.Class.extend({
112    options: {
113      service_url: 'https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer'
114    },
115
116    initialize: function(accessToken, options) {
117      L.setOptions(this, options);
118      this._accessToken = accessToken;
119    },
120
121    geocode: function(query, cb, context) {
122      var params = {
123        SingleLine: query,
124        outFields: 'Addr_Type',
125        forStorage: false,
126        maxLocations: 10,
127        f: 'json'
128      };
129
130      if (this._key && this._key.length) {
131        params.token = this._key;
132      }
133
134      getJSON(
135        this.options.service_url + '/findAddressCandidates',
136        L.extend(params, this.options.geocodingQueryParams),
137        function(data) {
138          var results = [],
139            loc,
140            latLng,
141            latLngBounds;
142
143          if (data.candidates && data.candidates.length) {
144            for (var i = 0; i <= data.candidates.length - 1; i++) {
145              loc = data.candidates[i];
146              latLng = L.latLng(loc.location.y, loc.location.x);
147              latLngBounds = L.latLngBounds(
148                L.latLng(loc.extent.ymax, loc.extent.xmax),
149                L.latLng(loc.extent.ymin, loc.extent.xmin)
150              );
151              results[i] = {
152                name: loc.address,
153                bbox: latLngBounds,
154                center: latLng
155              };
156            }
157          }
158
159          cb.call(context, results);
160        }
161      );
162    },
163
164    suggest: function(query, cb, context) {
165      return this.geocode(query, cb, context);
166    },
167
168    reverse: function(location, scale, cb, context) {
169      var params = {
170        location: encodeURIComponent(location.lng) + ',' + encodeURIComponent(location.lat),
171        distance: 100,
172        f: 'json'
173      };
174
175      getJSON(this.options.service_url + '/reverseGeocode', params, function(data) {
176        var result = [],
177          loc;
178
179        if (data && !data.error) {
180          loc = L.latLng(data.location.y, data.location.x);
181          result.push({
182            name: data.address.Match_addr,
183            center: loc,
184            bounds: L.latLngBounds(loc, loc)
185          });
186        }
187
188        cb.call(context, result);
189      });
190    }
191  });
192
193  function arcgis(accessToken, options) {
194    return new ArcGis(accessToken, options);
195  }
196
197  var Bing = L.Class.extend({
198    initialize: function(key) {
199      this.key = key;
200    },
201
202    geocode: function(query, cb, context) {
203      jsonp(
204        'https://dev.virtualearth.net/REST/v1/Locations',
205        {
206          query: query,
207          key: this.key
208        },
209        function(data) {
210          var results = [];
211          if (data.resourceSets.length > 0) {
212            for (var i = data.resourceSets[0].resources.length - 1; i >= 0; i--) {
213              var resource = data.resourceSets[0].resources[i],
214                bbox = resource.bbox;
215              results[i] = {
216                name: resource.name,
217                bbox: L.latLngBounds([bbox[0], bbox[1]], [bbox[2], bbox[3]]),
218                center: L.latLng(resource.point.coordinates)
219              };
220            }
221          }
222          cb.call(context, results);
223        },
224        this,
225        'jsonp'
226      );
227    },
228
229    reverse: function(location, scale, cb, context) {
230      jsonp(
231        '//dev.virtualearth.net/REST/v1/Locations/' + location.lat + ',' + location.lng,
232        {
233          key: this.key
234        },
235        function(data) {
236          var results = [];
237          for (var i = data.resourceSets[0].resources.length - 1; i >= 0; i--) {
238            var resource = data.resourceSets[0].resources[i],
239              bbox = resource.bbox;
240            results[i] = {
241              name: resource.name,
242              bbox: L.latLngBounds([bbox[0], bbox[1]], [bbox[2], bbox[3]]),
243              center: L.latLng(resource.point.coordinates)
244            };
245          }
246          cb.call(context, results);
247        },
248        this,
249        'jsonp'
250      );
251    }
252  });
253
254  function bing(key) {
255    return new Bing(key);
256  }
257
258  var Google = L.Class.extend({
259    options: {
260      serviceUrl: 'https://maps.googleapis.com/maps/api/geocode/json',
261      geocodingQueryParams: {},
262      reverseQueryParams: {}
263    },
264
265    initialize: function(key, options) {
266      this._key = key;
267      L.setOptions(this, options);
268      // Backwards compatibility
269      this.options.serviceUrl = this.options.service_url || this.options.serviceUrl;
270    },
271
272    geocode: function(query, cb, context) {
273      var params = {
274        address: query
275      };
276
277      if (this._key && this._key.length) {
278        params.key = this._key;
279      }
280
281      params = L.Util.extend(params, this.options.geocodingQueryParams);
282
283      getJSON(this.options.serviceUrl, params, function(data) {
284        var results = [],
285          loc,
286          latLng,
287          latLngBounds;
288        if (data.results && data.results.length) {
289          for (var i = 0; i <= data.results.length - 1; i++) {
290            loc = data.results[i];
291            latLng = L.latLng(loc.geometry.location);
292            latLngBounds = L.latLngBounds(
293              L.latLng(loc.geometry.viewport.northeast),
294              L.latLng(loc.geometry.viewport.southwest)
295            );
296            results[i] = {
297              name: loc.formatted_address,
298              bbox: latLngBounds,
299              center: latLng,
300              properties: loc.address_components
301            };
302          }
303        }
304
305        cb.call(context, results);
306      });
307    },
308
309    reverse: function(location, scale, cb, context) {
310      var params = {
311        latlng: encodeURIComponent(location.lat) + ',' + encodeURIComponent(location.lng)
312      };
313      params = L.Util.extend(params, this.options.reverseQueryParams);
314      if (this._key && this._key.length) {
315        params.key = this._key;
316      }
317
318      getJSON(this.options.serviceUrl, params, function(data) {
319        var results = [],
320          loc,
321          latLng,
322          latLngBounds;
323        if (data.results && data.results.length) {
324          for (var i = 0; i <= data.results.length - 1; i++) {
325            loc = data.results[i];
326            latLng = L.latLng(loc.geometry.location);
327            latLngBounds = L.latLngBounds(
328              L.latLng(loc.geometry.viewport.northeast),
329              L.latLng(loc.geometry.viewport.southwest)
330            );
331            results[i] = {
332              name: loc.formatted_address,
333              bbox: latLngBounds,
334              center: latLng,
335              properties: loc.address_components
336            };
337          }
338        }
339
340        cb.call(context, results);
341      });
342    }
343  });
344
345  function google(key, options) {
346    return new Google(key, options);
347  }
348
349  var HERE = L.Class.extend({
350    options: {
351      geocodeUrl: 'http://geocoder.api.here.com/6.2/geocode.json',
352      reverseGeocodeUrl: 'http://reverse.geocoder.api.here.com/6.2/reversegeocode.json',
353      app_id: '<insert your app_id here>',
354      app_code: '<insert your app_code here>',
355      geocodingQueryParams: {},
356      reverseQueryParams: {}
357    },
358
359    initialize: function(options) {
360      L.setOptions(this, options);
361    },
362
363    geocode: function(query, cb, context) {
364      var params = {
365        searchtext: query,
366        gen: 9,
367        app_id: this.options.app_id,
368        app_code: this.options.app_code,
369        jsonattributes: 1
370      };
371      params = L.Util.extend(params, this.options.geocodingQueryParams);
372      this.getJSON(this.options.geocodeUrl, params, cb, context);
373    },
374
375    reverse: function(location, scale, cb, context) {
376      var params = {
377        prox: encodeURIComponent(location.lat) + ',' + encodeURIComponent(location.lng),
378        mode: 'retrieveAddresses',
379        app_id: this.options.app_id,
380        app_code: this.options.app_code,
381        gen: 9,
382        jsonattributes: 1
383      };
384      params = L.Util.extend(params, this.options.reverseQueryParams);
385      this.getJSON(this.options.reverseGeocodeUrl, params, cb, context);
386    },
387
388    getJSON: function(url, params, cb, context) {
389      getJSON(url, params, function(data) {
390        var results = [],
391          loc,
392          latLng,
393          latLngBounds;
394        if (data.response.view && data.response.view.length) {
395          for (var i = 0; i <= data.response.view[0].result.length - 1; i++) {
396            loc = data.response.view[0].result[i].location;
397            latLng = L.latLng(loc.displayPosition.latitude, loc.displayPosition.longitude);
398            latLngBounds = L.latLngBounds(
399              L.latLng(loc.mapView.topLeft.latitude, loc.mapView.topLeft.longitude),
400              L.latLng(loc.mapView.bottomRight.latitude, loc.mapView.bottomRight.longitude)
401            );
402            results[i] = {
403              name: loc.address.label,
404              bbox: latLngBounds,
405              center: latLng
406            };
407          }
408        }
409        cb.call(context, results);
410      });
411    }
412  });
413
414  function here(options) {
415    return new HERE(options);
416  }
417
418  var LatLng = L.Class.extend({
419    options: {
420      // the next geocoder to use
421      next: undefined,
422      sizeInMeters: 10000
423    },
424
425    initialize: function(options) {
426      L.Util.setOptions(this, options);
427    },
428
429    geocode: function(query, cb, context) {
430      var match;
431      var center;
432      // regex from https://github.com/openstreetmap/openstreetmap-website/blob/master/app/controllers/geocoder_controller.rb
433      if ((match = query.match(/^([NS])\s*(\d{1,3}(?:\.\d*)?)\W*([EW])\s*(\d{1,3}(?:\.\d*)?)$/))) {
434        // [NSEW] decimal degrees
435        center = L.latLng(
436          (/N/i.test(match[1]) ? 1 : -1) * parseFloat(match[2]),
437          (/E/i.test(match[3]) ? 1 : -1) * parseFloat(match[4])
438        );
439      } else if (
440        (match = query.match(/^(\d{1,3}(?:\.\d*)?)\s*([NS])\W*(\d{1,3}(?:\.\d*)?)\s*([EW])$/))
441      ) {
442        // decimal degrees [NSEW]
443        center = L.latLng(
444          (/N/i.test(match[2]) ? 1 : -1) * parseFloat(match[1]),
445          (/E/i.test(match[4]) ? 1 : -1) * parseFloat(match[3])
446        );
447      } else if (
448        (match = query.match(
449          /^([NS])\s*(\d{1,3})°?\s*(\d{1,3}(?:\.\d*)?)?['′]?\W*([EW])\s*(\d{1,3})°?\s*(\d{1,3}(?:\.\d*)?)?['′]?$/
450        ))
451      ) {
452        // [NSEW] degrees, decimal minutes
453        center = L.latLng(
454          (/N/i.test(match[1]) ? 1 : -1) * (parseFloat(match[2]) + parseFloat(match[3] / 60)),
455          (/E/i.test(match[4]) ? 1 : -1) * (parseFloat(match[5]) + parseFloat(match[6] / 60))
456        );
457      } else if (
458        (match = query.match(
459          /^(\d{1,3})°?\s*(\d{1,3}(?:\.\d*)?)?['′]?\s*([NS])\W*(\d{1,3})°?\s*(\d{1,3}(?:\.\d*)?)?['′]?\s*([EW])$/
460        ))
461      ) {
462        // degrees, decimal minutes [NSEW]
463        center = L.latLng(
464          (/N/i.test(match[3]) ? 1 : -1) * (parseFloat(match[1]) + parseFloat(match[2] / 60)),
465          (/E/i.test(match[6]) ? 1 : -1) * (parseFloat(match[4]) + parseFloat(match[5] / 60))
466        );
467      } else if (
468        (match = query.match(
469          /^([NS])\s*(\d{1,3})°?\s*(\d{1,2})['′]?\s*(\d{1,3}(?:\.\d*)?)?["″]?\W*([EW])\s*(\d{1,3})°?\s*(\d{1,2})['′]?\s*(\d{1,3}(?:\.\d*)?)?["″]?$/
470        ))
471      ) {
472        // [NSEW] degrees, minutes, decimal seconds
473        center = L.latLng(
474          (/N/i.test(match[1]) ? 1 : -1) *
475            (parseFloat(match[2]) + parseFloat(match[3] / 60 + parseFloat(match[4] / 3600))),
476          (/E/i.test(match[5]) ? 1 : -1) *
477            (parseFloat(match[6]) + parseFloat(match[7] / 60) + parseFloat(match[8] / 3600))
478        );
479      } else if (
480        (match = query.match(
481          /^(\d{1,3})°?\s*(\d{1,2})['′]?\s*(\d{1,3}(?:\.\d*)?)?["″]\s*([NS])\W*(\d{1,3})°?\s*(\d{1,2})['′]?\s*(\d{1,3}(?:\.\d*)?)?["″]?\s*([EW])$/
482        ))
483      ) {
484        // degrees, minutes, decimal seconds [NSEW]
485        center = L.latLng(
486          (/N/i.test(match[4]) ? 1 : -1) *
487            (parseFloat(match[1]) + parseFloat(match[2] / 60 + parseFloat(match[3] / 3600))),
488          (/E/i.test(match[8]) ? 1 : -1) *
489            (parseFloat(match[5]) + parseFloat(match[6] / 60) + parseFloat(match[7] / 3600))
490        );
491      } else if (
492        (match = query.match(/^\s*([+-]?\d+(?:\.\d*)?)\s*[\s,]\s*([+-]?\d+(?:\.\d*)?)\s*$/))
493      ) {
494        center = L.latLng(parseFloat(match[1]), parseFloat(match[2]));
495      }
496      if (center) {
497        var results = [
498          {
499            name: query,
500            center: center,
501            bbox: center.toBounds(this.options.sizeInMeters)
502          }
503        ];
504        cb.call(context, results);
505      } else if (this.options.next) {
506        this.options.next.geocode(query, cb, context);
507      }
508    }
509  });
510
511  function latLng(options) {
512    return new LatLng(options);
513  }
514
515  var Mapbox = L.Class.extend({
516    options: {
517      serviceUrl: 'https://api.mapbox.com/geocoding/v5/mapbox.places/',
518      geocodingQueryParams: {},
519      reverseQueryParams: {}
520    },
521
522    initialize: function(accessToken, options) {
523      L.setOptions(this, options);
524      this.options.geocodingQueryParams.access_token = accessToken;
525      this.options.reverseQueryParams.access_token = accessToken;
526    },
527
528    geocode: function(query, cb, context) {
529      var params = this.options.geocodingQueryParams;
530      if (
531        typeof params.proximity !== 'undefined' &&
532        params.proximity.hasOwnProperty('lat') &&
533        params.proximity.hasOwnProperty('lng')
534      ) {
535        params.proximity = params.proximity.lng + ',' + params.proximity.lat;
536      }
537      getJSON(this.options.serviceUrl + encodeURIComponent(query) + '.json', params, function(data) {
538        var results = [],
539          loc,
540          latLng,
541          latLngBounds;
542        if (data.features && data.features.length) {
543          for (var i = 0; i <= data.features.length - 1; i++) {
544            loc = data.features[i];
545            latLng = L.latLng(loc.center.reverse());
546            if (loc.hasOwnProperty('bbox')) {
547              latLngBounds = L.latLngBounds(
548                L.latLng(loc.bbox.slice(0, 2).reverse()),
549                L.latLng(loc.bbox.slice(2, 4).reverse())
550              );
551            } else {
552              latLngBounds = L.latLngBounds(latLng, latLng);
553            }
554
555            var properties = {
556              text: loc.text,
557              address: loc.address
558            };
559
560            for (var j = 0; j < loc.context.length; j++) {
561              var id = loc.context[j].id.split('.')[0];
562              properties[id] = loc.context[j].text;
563            }
564
565            results[i] = {
566              name: loc.place_name,
567              bbox: latLngBounds,
568              center: latLng,
569              properties: properties
570            };
571          }
572        }
573
574        cb.call(context, results);
575      });
576    },
577
578    suggest: function(query, cb, context) {
579      return this.geocode(query, cb, context);
580    },
581
582    reverse: function(location, scale, cb, context) {
583      getJSON(
584        this.options.serviceUrl +
585          encodeURIComponent(location.lng) +
586          ',' +
587          encodeURIComponent(location.lat) +
588          '.json',
589        this.options.reverseQueryParams,
590        function(data) {
591          var results = [],
592            loc,
593            latLng,
594            latLngBounds;
595          if (data.features && data.features.length) {
596            for (var i = 0; i <= data.features.length - 1; i++) {
597              loc = data.features[i];
598              latLng = L.latLng(loc.center.reverse());
599              if (loc.hasOwnProperty('bbox')) {
600                latLngBounds = L.latLngBounds(
601                  L.latLng(loc.bbox.slice(0, 2).reverse()),
602                  L.latLng(loc.bbox.slice(2, 4).reverse())
603                );
604              } else {
605                latLngBounds = L.latLngBounds(latLng, latLng);
606              }
607              results[i] = {
608                name: loc.place_name,
609                bbox: latLngBounds,
610                center: latLng
611              };
612            }
613          }
614
615          cb.call(context, results);
616        }
617      );
618    }
619  });
620
621  function mapbox(accessToken, options) {
622    return new Mapbox(accessToken, options);
623  }
624
625  var MapQuest = L.Class.extend({
626    options: {
627      serviceUrl: 'https://www.mapquestapi.com/geocoding/v1'
628    },
629
630    initialize: function(key, options) {
631      // MapQuest seems to provide URI encoded API keys,
632      // so to avoid encoding them twice, we decode them here
633      this._key = decodeURIComponent(key);
634
635      L.Util.setOptions(this, options);
636    },
637
638    _formatName: function() {
639      var r = [],
640        i;
641      for (i = 0; i < arguments.length; i++) {
642        if (arguments[i]) {
643          r.push(arguments[i]);
644        }
645      }
646
647      return r.join(', ');
648    },
649
650    geocode: function(query, cb, context) {
651      getJSON(
652        this.options.serviceUrl + '/address',
653        {
654          key: this._key,
655          location: query,
656          limit: 5,
657          outFormat: 'json'
658        },
659        L.bind(function(data) {
660          var results = [],
661            loc,
662            latLng;
663          if (data.results && data.results[0].locations) {
664            for (var i = data.results[0].locations.length - 1; i >= 0; i--) {
665              loc = data.results[0].locations[i];
666              latLng = L.latLng(loc.latLng);
667              results[i] = {
668                name: this._formatName(loc.street, loc.adminArea4, loc.adminArea3, loc.adminArea1),
669                bbox: L.latLngBounds(latLng, latLng),
670                center: latLng
671              };
672            }
673          }
674
675          cb.call(context, results);
676        }, this)
677      );
678    },
679
680    reverse: function(location, scale, cb, context) {
681      getJSON(
682        this.options.serviceUrl + '/reverse',
683        {
684          key: this._key,
685          location: location.lat + ',' + location.lng,
686          outputFormat: 'json'
687        },
688        L.bind(function(data) {
689          var results = [],
690            loc,
691            latLng;
692          if (data.results && data.results[0].locations) {
693            for (var i = data.results[0].locations.length - 1; i >= 0; i--) {
694              loc = data.results[0].locations[i];
695              latLng = L.latLng(loc.latLng);
696              results[i] = {
697                name: this._formatName(loc.street, loc.adminArea4, loc.adminArea3, loc.adminArea1),
698                bbox: L.latLngBounds(latLng, latLng),
699                center: latLng
700              };
701            }
702          }
703
704          cb.call(context, results);
705        }, this)
706      );
707    }
708  });
709
710  function mapQuest(key, options) {
711    return new MapQuest(key, options);
712  }
713
714  var Neutrino = L.Class.extend({
715    options: {
716      userId: '<insert your userId here>',
717      apiKey: '<insert your apiKey here>',
718      serviceUrl: 'https://neutrinoapi.com/'
719    },
720
721    initialize: function(options) {
722      L.Util.setOptions(this, options);
723    },
724
725    // https://www.neutrinoapi.com/api/geocode-address/
726    geocode: function(query, cb, context) {
727      getJSON(
728        this.options.serviceUrl + 'geocode-address',
729        {
730          apiKey: this.options.apiKey,
731          userId: this.options.userId,
732          //get three words and make a dot based string
733          address: query.split(/\s+/).join('.')
734        },
735        function(data) {
736          var results = [],
737            latLng,
738            latLngBounds;
739          if (data.hasOwnProperty('locations')) {
740            data.geometry = data.locations[0];
741            latLng = L.latLng(data.geometry['latitude'], data.geometry['longitude']);
742            latLngBounds = L.latLngBounds(latLng, latLng);
743            results[0] = {
744              name: data.geometry.address,
745              bbox: latLngBounds,
746              center: latLng
747            };
748          }
749
750          cb.call(context, results);
751        }
752      );
753    },
754
755    suggest: function(query, cb, context) {
756      return this.geocode(query, cb, context);
757    },
758
759    // https://www.neutrinoapi.com/api/geocode-reverse/
760    reverse: function(location, scale, cb, context) {
761      getJSON(
762        this.options.serviceUrl + 'geocode-reverse',
763        {
764          apiKey: this.options.apiKey,
765          userId: this.options.userId,
766          latitude: location.lat,
767          longitude: location.lng
768        },
769        function(data) {
770          var results = [],
771            latLng,
772            latLngBounds;
773          if (data.status.status == 200 && data.found) {
774            latLng = L.latLng(location.lat, location.lng);
775            latLngBounds = L.latLngBounds(latLng, latLng);
776            results[0] = {
777              name: data.address,
778              bbox: latLngBounds,
779              center: latLng
780            };
781          }
782          cb.call(context, results);
783        }
784      );
785    }
786  });
787
788  function neutrino(accessToken) {
789    return new Neutrino(accessToken);
790  }
791
792  var Nominatim = L.Class.extend({
793    options: {
794      serviceUrl: 'https://nominatim.openstreetmap.org/',
795      geocodingQueryParams: {},
796      reverseQueryParams: {},
797      htmlTemplate: function(r) {
798        var a = r.address,
799          parts = [];
800        if (a.road || a.building) {
801          parts.push('{building} {road} {house_number}');
802        }
803
804        if (a.city || a.town || a.village || a.hamlet) {
805          parts.push(
806            '<span class="' +
807              (parts.length > 0 ? 'leaflet-control-geocoder-address-detail' : '') +
808              '">{postcode} {city} {town} {village} {hamlet}</span>'
809          );
810        }
811
812        if (a.state || a.country) {
813          parts.push(
814            '<span class="' +
815              (parts.length > 0 ? 'leaflet-control-geocoder-address-context' : '') +
816              '">{state} {country}</span>'
817          );
818        }
819
820        return template(parts.join('<br/>'), a, true);
821      }
822    },
823
824    initialize: function(options) {
825      L.Util.setOptions(this, options);
826    },
827
828    geocode: function(query, cb, context) {
829      getJSON(
830        this.options.serviceUrl + 'search',
831        L.extend(
832          {
833            q: query,
834            limit: 5,
835            format: 'json',
836            addressdetails: 1
837          },
838          this.options.geocodingQueryParams
839        ),
840        L.bind(function(data) {
841          var results = [];
842          for (var i = data.length - 1; i >= 0; i--) {
843            var bbox = data[i].boundingbox;
844            for (var j = 0; j < 4; j++) bbox[j] = parseFloat(bbox[j]);
845            results[i] = {
846              icon: data[i].icon,
847              name: data[i].display_name,
848              html: this.options.htmlTemplate ? this.options.htmlTemplate(data[i]) : undefined,
849              bbox: L.latLngBounds([bbox[0], bbox[2]], [bbox[1], bbox[3]]),
850              center: L.latLng(data[i].lat, data[i].lon),
851              properties: data[i]
852            };
853          }
854          cb.call(context, results);
855        }, this)
856      );
857    },
858
859    reverse: function(location, scale, cb, context) {
860      getJSON(
861        this.options.serviceUrl + 'reverse',
862        L.extend(
863          {
864            lat: location.lat,
865            lon: location.lng,
866            zoom: Math.round(Math.log(scale / 256) / Math.log(2)),
867            addressdetails: 1,
868            format: 'json'
869          },
870          this.options.reverseQueryParams
871        ),
872        L.bind(function(data) {
873          var result = [],
874            loc;
875
876          if (data && data.lat && data.lon) {
877            loc = L.latLng(data.lat, data.lon);
878            result.push({
879              name: data.display_name,
880              html: this.options.htmlTemplate ? this.options.htmlTemplate(data) : undefined,
881              center: loc,
882              bounds: L.latLngBounds(loc, loc),
883              properties: data
884            });
885          }
886
887          cb.call(context, result);
888        }, this)
889      );
890    }
891  });
892
893  function nominatim(options) {
894    return new Nominatim(options);
895  }
896
897  var OpenLocationCode = L.Class.extend({
898    options: {
899      OpenLocationCode: undefined,
900      codeLength: undefined
901    },
902
903    initialize: function(options) {
904      L.setOptions(this, options);
905    },
906
907    geocode: function(query, cb, context) {
908      try {
909        var decoded = this.options.OpenLocationCode.decode(query);
910        var result = {
911          name: query,
912          center: L.latLng(decoded.latitudeCenter, decoded.longitudeCenter),
913          bbox: L.latLngBounds(
914            L.latLng(decoded.latitudeLo, decoded.longitudeLo),
915            L.latLng(decoded.latitudeHi, decoded.longitudeHi)
916          )
917        };
918        cb.call(context, [result]);
919      } catch (e) {
920        console.warn(e); // eslint-disable-line no-console
921        cb.call(context, []);
922      }
923    },
924    reverse: function(location, scale, cb, context) {
925      try {
926        var code = this.options.OpenLocationCode.encode(
927          location.lat,
928          location.lng,
929          this.options.codeLength
930        );
931        var result = {
932          name: code,
933          center: L.latLng(location.lat, location.lng),
934          bbox: L.latLngBounds(
935            L.latLng(location.lat, location.lng),
936            L.latLng(location.lat, location.lng)
937          )
938        };
939        cb.call(context, [result]);
940      } catch (e) {
941        console.warn(e); // eslint-disable-line no-console
942        cb.call(context, []);
943      }
944    }
945  });
946
947  function openLocationCode(options) {
948    return new OpenLocationCode(options);
949  }
950
951  var Pelias = L.Class.extend({
952    options: {
953      serviceUrl: 'https://api.geocode.earth/v1',
954      geocodingQueryParams: {},
955      reverseQueryParams: {}
956    },
957
958    initialize: function(apiKey, options) {
959      L.Util.setOptions(this, options);
960      this._apiKey = apiKey;
961      this._lastSuggest = 0;
962    },
963
964    geocode: function(query, cb, context) {
965      var _this = this;
966      getJSON(
967        this.options.serviceUrl + '/search',
968        L.extend(
969          {
970            api_key: this._apiKey,
971            text: query
972          },
973          this.options.geocodingQueryParams
974        ),
975        function(data) {
976          cb.call(context, _this._parseResults(data, 'bbox'));
977        }
978      );
979    },
980
981    suggest: function(query, cb, context) {
982      var _this = this;
983      getJSON(
984        this.options.serviceUrl + '/autocomplete',
985        L.extend(
986          {
987            api_key: this._apiKey,
988            text: query
989          },
990          this.options.geocodingQueryParams
991        ),
992        L.bind(function(data) {
993          if (data.geocoding.timestamp > this._lastSuggest) {
994            this._lastSuggest = data.geocoding.timestamp;
995            cb.call(context, _this._parseResults(data, 'bbox'));
996          }
997        }, this)
998      );
999    },
1000
1001    reverse: function(location, scale, cb, context) {
1002      var _this = this;
1003      getJSON(
1004        this.options.serviceUrl + '/reverse',
1005        L.extend(
1006          {
1007            api_key: this._apiKey,
1008            'point.lat': location.lat,
1009            'point.lon': location.lng
1010          },
1011          this.options.reverseQueryParams
1012        ),
1013        function(data) {
1014          cb.call(context, _this._parseResults(data, 'bounds'));
1015        }
1016      );
1017    },
1018
1019    _parseResults: function(data, bboxname) {
1020      var results = [];
1021      L.geoJson(data, {
1022        pointToLayer: function(feature, latlng) {
1023          return L.circleMarker(latlng);
1024        },
1025        onEachFeature: function(feature, layer) {
1026          var result = {},
1027            bbox,
1028            center;
1029
1030          if (layer.getBounds) {
1031            bbox = layer.getBounds();
1032            center = bbox.getCenter();
1033          } else if (layer.feature.bbox) {
1034            center = layer.getLatLng();
1035            bbox = L.latLngBounds(
1036              L.GeoJSON.coordsToLatLng(layer.feature.bbox.slice(0, 2)),
1037              L.GeoJSON.coordsToLatLng(layer.feature.bbox.slice(2, 4))
1038            );
1039          } else {
1040            center = layer.getLatLng();
1041            bbox = L.latLngBounds(center, center);
1042          }
1043
1044          result.name = layer.feature.properties.label;
1045          result.center = center;
1046          result[bboxname] = bbox;
1047          result.properties = layer.feature.properties;
1048          results.push(result);
1049        }
1050      });
1051      return results;
1052    }
1053  });
1054
1055  function pelias(apiKey, options) {
1056    return new Pelias(apiKey, options);
1057  }
1058  var GeocodeEarth = Pelias;
1059  var geocodeEarth = pelias;
1060
1061  var Mapzen = Pelias; // r.i.p.
1062  var mapzen = pelias;
1063
1064  var Openrouteservice = Mapzen.extend({
1065    options: {
1066      serviceUrl: 'https://api.openrouteservice.org/geocode'
1067    }
1068  });
1069  function openrouteservice(apiKey, options) {
1070    return new Openrouteservice(apiKey, options);
1071  }
1072
1073  var Photon = L.Class.extend({
1074    options: {
1075      serviceUrl: 'https://photon.komoot.de/api/',
1076      reverseUrl: 'https://photon.komoot.de/reverse/',
1077      nameProperties: ['name', 'street', 'suburb', 'hamlet', 'town', 'city', 'state', 'country']
1078    },
1079
1080    initialize: function(options) {
1081      L.setOptions(this, options);
1082    },
1083
1084    geocode: function(query, cb, context) {
1085      var params = L.extend(
1086        {
1087          q: query
1088        },
1089        this.options.geocodingQueryParams
1090      );
1091
1092      getJSON(
1093        this.options.serviceUrl,
1094        params,
1095        L.bind(function(data) {
1096          cb.call(context, this._decodeFeatures(data));
1097        }, this)
1098      );
1099    },
1100
1101    suggest: function(query, cb, context) {
1102      return this.geocode(query, cb, context);
1103    },
1104
1105    reverse: function(latLng, scale, cb, context) {
1106      var params = L.extend(
1107        {
1108          lat: latLng.lat,
1109          lon: latLng.lng
1110        },
1111        this.options.reverseQueryParams
1112      );
1113
1114      getJSON(
1115        this.options.reverseUrl,
1116        params,
1117        L.bind(function(data) {
1118          cb.call(context, this._decodeFeatures(data));
1119        }, this)
1120      );
1121    },
1122
1123    _decodeFeatures: function(data) {
1124      var results = [],
1125        i,
1126        f,
1127        c,
1128        latLng,
1129        extent,
1130        bbox;
1131
1132      if (data && data.features) {
1133        for (i = 0; i < data.features.length; i++) {
1134          f = data.features[i];
1135          c = f.geometry.coordinates;
1136          latLng = L.latLng(c[1], c[0]);
1137          extent = f.properties.extent;
1138
1139          if (extent) {
1140            bbox = L.latLngBounds([extent[1], extent[0]], [extent[3], extent[2]]);
1141          } else {
1142            bbox = L.latLngBounds(latLng, latLng);
1143          }
1144
1145          results.push({
1146            name: this._decodeFeatureName(f),
1147            html: this.options.htmlTemplate ? this.options.htmlTemplate(f) : undefined,
1148            center: latLng,
1149            bbox: bbox,
1150            properties: f.properties
1151          });
1152        }
1153      }
1154
1155      return results;
1156    },
1157
1158    _decodeFeatureName: function(f) {
1159      return (this.options.nameProperties || [])
1160        .map(function(p) {
1161          return f.properties[p];
1162        })
1163        .filter(function(v) {
1164          return !!v;
1165        })
1166        .join(', ');
1167    }
1168  });
1169
1170  function photon(options) {
1171    return new Photon(options);
1172  }
1173
1174  var What3Words = L.Class.extend({
1175    options: {
1176      serviceUrl: 'https://api.what3words.com/v2/'
1177    },
1178
1179    initialize: function(accessToken) {
1180      this._accessToken = accessToken;
1181    },
1182
1183    geocode: function(query, cb, context) {
1184      //get three words and make a dot based string
1185      getJSON(
1186        this.options.serviceUrl + 'forward',
1187        {
1188          key: this._accessToken,
1189          addr: query.split(/\s+/).join('.')
1190        },
1191        function(data) {
1192          var results = [],
1193            latLng,
1194            latLngBounds;
1195          if (data.hasOwnProperty('geometry')) {
1196            latLng = L.latLng(data.geometry['lat'], data.geometry['lng']);
1197            latLngBounds = L.latLngBounds(latLng, latLng);
1198            results[0] = {
1199              name: data.words,
1200              bbox: latLngBounds,
1201              center: latLng
1202            };
1203          }
1204
1205          cb.call(context, results);
1206        }
1207      );
1208    },
1209
1210    suggest: function(query, cb, context) {
1211      return this.geocode(query, cb, context);
1212    },
1213
1214    reverse: function(location, scale, cb, context) {
1215      getJSON(
1216        this.options.serviceUrl + 'reverse',
1217        {
1218          key: this._accessToken,
1219          coords: [location.lat, location.lng].join(',')
1220        },
1221        function(data) {
1222          var results = [],
1223            latLng,
1224            latLngBounds;
1225          if (data.status.status == 200) {
1226            latLng = L.latLng(data.geometry['lat'], data.geometry['lng']);
1227            latLngBounds = L.latLngBounds(latLng, latLng);
1228            results[0] = {
1229              name: data.words,
1230              bbox: latLngBounds,
1231              center: latLng
1232            };
1233          }
1234          cb.call(context, results);
1235        }
1236      );
1237    }
1238  });
1239
1240  function what3words(accessToken) {
1241    return new What3Words(accessToken);
1242  }
1243
1244
1245
1246  var geocoders = /*#__PURE__*/Object.freeze({
1247    ArcGis: ArcGis,
1248    arcgis: arcgis,
1249    Bing: Bing,
1250    bing: bing,
1251    Google: Google,
1252    google: google,
1253    HERE: HERE,
1254    here: here,
1255    LatLng: LatLng,
1256    latLng: latLng,
1257    Mapbox: Mapbox,
1258    mapbox: mapbox,
1259    MapQuest: MapQuest,
1260    mapQuest: mapQuest,
1261    Neutrino: Neutrino,
1262    neutrino: neutrino,
1263    Nominatim: Nominatim,
1264    nominatim: nominatim,
1265    OpenLocationCode: OpenLocationCode,
1266    openLocationCode: openLocationCode,
1267    Pelias: Pelias,
1268    pelias: pelias,
1269    GeocodeEarth: GeocodeEarth,
1270    geocodeEarth: geocodeEarth,
1271    Mapzen: Mapzen,
1272    mapzen: mapzen,
1273    Openrouteservice: Openrouteservice,
1274    openrouteservice: openrouteservice,
1275    Photon: Photon,
1276    photon: photon,
1277    What3Words: What3Words,
1278    what3words: what3words
1279  });
1280
1281  var Geocoder = L.Control.extend({
1282    options: {
1283      showResultIcons: false,
1284      collapsed: true,
1285      expand: 'touch', // options: touch, click, anythingelse
1286      position: 'topright',
1287      placeholder: 'Search...',
1288      errorMessage: 'Nothing found.',
1289      queryMinLength: 1,
1290      suggestMinLength: 3,
1291      suggestTimeout: 250,
1292      defaultMarkGeocode: true
1293    },
1294
1295    includes: L.Evented.prototype || L.Mixin.Events,
1296
1297    initialize: function(options) {
1298      L.Util.setOptions(this, options);
1299      if (!this.options.geocoder) {
1300        this.options.geocoder = new Nominatim();
1301      }
1302
1303      this._requestCount = 0;
1304    },
1305
1306    addThrobberClass: function() {
1307      L.DomUtil.addClass(this._container, 'leaflet-control-geocoder-throbber');
1308    },
1309
1310    removeThrobberClass: function() {
1311      L.DomUtil.removeClass(this._container, 'leaflet-control-geocoder-throbber');
1312    },
1313
1314    onAdd: function(map) {
1315      var className = 'leaflet-control-geocoder',
1316        container = L.DomUtil.create('div', className + ' leaflet-bar'),
1317        icon = L.DomUtil.create('button', className + '-icon', container),
1318        form = (this._form = L.DomUtil.create('div', className + '-form', container)),
1319        input;
1320
1321      this._map = map;
1322      this._container = container;
1323
1324      icon.innerHTML = '&nbsp;';
1325      icon.type = 'button';
1326
1327      input = this._input = L.DomUtil.create('input', '', form);
1328      input.type = 'text';
1329      input.placeholder = this.options.placeholder;
1330      L.DomEvent.disableClickPropagation(input);
1331
1332      this._errorElement = L.DomUtil.create('div', className + '-form-no-error', container);
1333      this._errorElement.innerHTML = this.options.errorMessage;
1334
1335      this._alts = L.DomUtil.create(
1336        'ul',
1337        className + '-alternatives leaflet-control-geocoder-alternatives-minimized',
1338        container
1339      );
1340      L.DomEvent.disableClickPropagation(this._alts);
1341
1342      L.DomEvent.addListener(input, 'keydown', this._keydown, this);
1343      if (this.options.geocoder.suggest) {
1344        L.DomEvent.addListener(input, 'input', this._change, this);
1345      }
1346      L.DomEvent.addListener(
1347        input,
1348        'blur',
1349        function() {
1350          if (this.options.collapsed && !this._preventBlurCollapse) {
1351            this._collapse();
1352          }
1353          this._preventBlurCollapse = false;
1354        },
1355        this
1356      );
1357
1358      if (this.options.collapsed) {
1359        if (this.options.expand === 'click') {
1360          L.DomEvent.addListener(
1361            container,
1362            'click',
1363            function(e) {
1364              if (e.button === 0 && e.detail !== 2) {
1365                this._toggle();
1366              }
1367            },
1368            this
1369          );
1370        } else if (L.Browser.touch && this.options.expand === 'touch') {
1371          L.DomEvent.addListener(
1372            container,
1373            'touchstart mousedown',
1374            function(e) {
1375              this._toggle();
1376              e.preventDefault(); // mobile: clicking focuses the icon, so UI expands and immediately collapses
1377              e.stopPropagation();
1378            },
1379            this
1380          );
1381        } else {
1382          L.DomEvent.addListener(container, 'mouseover', this._expand, this);
1383          L.DomEvent.addListener(container, 'mouseout', this._collapse, this);
1384          this._map.on('movestart', this._collapse, this);
1385        }
1386      } else {
1387        this._expand();
1388        if (L.Browser.touch) {
1389          L.DomEvent.addListener(
1390            container,
1391            'touchstart',
1392            function() {
1393              this._geocode();
1394            },
1395            this
1396          );
1397        } else {
1398          L.DomEvent.addListener(
1399            container,
1400            'click',
1401            function() {
1402              this._geocode();
1403            },
1404            this
1405          );
1406        }
1407      }
1408
1409      if (this.options.defaultMarkGeocode) {
1410        this.on('markgeocode', this.markGeocode, this);
1411      }
1412
1413      this.on('startgeocode', this.addThrobberClass, this);
1414      this.on('finishgeocode', this.removeThrobberClass, this);
1415      this.on('startsuggest', this.addThrobberClass, this);
1416      this.on('finishsuggest', this.removeThrobberClass, this);
1417
1418      L.DomEvent.disableClickPropagation(container);
1419
1420      return container;
1421    },
1422
1423    _geocodeResult: function(results, suggest) {
1424      if (!suggest && results.length === 1) {
1425        this._geocodeResultSelected(results[0]);
1426      } else if (results.length > 0) {
1427        this._alts.innerHTML = '';
1428        this._results = results;
1429        L.DomUtil.removeClass(this._alts, 'leaflet-control-geocoder-alternatives-minimized');
1430        L.DomUtil.addClass(this._container, 'leaflet-control-geocoder-options-open');
1431        for (var i = 0; i < results.length; i++) {
1432          this._alts.appendChild(this._createAlt(results[i], i));
1433        }
1434      } else {
1435        L.DomUtil.addClass(this._container, 'leaflet-control-geocoder-options-error');
1436        L.DomUtil.addClass(this._errorElement, 'leaflet-control-geocoder-error');
1437      }
1438    },
1439
1440    markGeocode: function(result) {
1441      result = result.geocode || result;
1442
1443      this._map.fitBounds(result.bbox);
1444
1445      if (this._geocodeMarker) {
1446        this._map.removeLayer(this._geocodeMarker);
1447      }
1448
1449      this._geocodeMarker = new L.Marker(result.center)
1450        .bindPopup(result.html || result.name)
1451        .addTo(this._map)
1452        .openPopup();
1453
1454      return this;
1455    },
1456
1457    _geocode: function(suggest) {
1458      var value = this._input.value;
1459      if (!suggest && value.length < this.options.queryMinLength) {
1460        return;
1461      }
1462
1463      var requestCount = ++this._requestCount,
1464        mode = suggest ? 'suggest' : 'geocode',
1465        eventData = { input: value };
1466
1467      this._lastGeocode = value;
1468      if (!suggest) {
1469        this._clearResults();
1470      }
1471
1472      this.fire('start' + mode, eventData);
1473      this.options.geocoder[mode](
1474        value,
1475        function(results) {
1476          if (requestCount === this._requestCount) {
1477            eventData.results = results;
1478            this.fire('finish' + mode, eventData);
1479            this._geocodeResult(results, suggest);
1480          }
1481        },
1482        this
1483      );
1484    },
1485
1486    _geocodeResultSelected: function(result) {
1487      this.fire('markgeocode', { geocode: result });
1488    },
1489
1490    _toggle: function() {
1491      if (L.DomUtil.hasClass(this._container, 'leaflet-control-geocoder-expanded')) {
1492        this._collapse();
1493      } else {
1494        this._expand();
1495      }
1496    },
1497
1498    _expand: function() {
1499      L.DomUtil.addClass(this._container, 'leaflet-control-geocoder-expanded');
1500      this._input.select();
1501      this.fire('expand');
1502    },
1503
1504    _collapse: function() {
1505      L.DomUtil.removeClass(this._container, 'leaflet-control-geocoder-expanded');
1506      L.DomUtil.addClass(this._alts, 'leaflet-control-geocoder-alternatives-minimized');
1507      L.DomUtil.removeClass(this._errorElement, 'leaflet-control-geocoder-error');
1508      L.DomUtil.removeClass(this._container, 'leaflet-control-geocoder-options-open');
1509      L.DomUtil.removeClass(this._container, 'leaflet-control-geocoder-options-error');
1510      this._input.blur(); // mobile: keyboard shouldn't stay expanded
1511      this.fire('collapse');
1512    },
1513
1514    _clearResults: function() {
1515      L.DomUtil.addClass(this._alts, 'leaflet-control-geocoder-alternatives-minimized');
1516      this._selection = null;
1517      L.DomUtil.removeClass(this._errorElement, 'leaflet-control-geocoder-error');
1518      L.DomUtil.removeClass(this._container, 'leaflet-control-geocoder-options-open');
1519      L.DomUtil.removeClass(this._container, 'leaflet-control-geocoder-options-error');
1520    },
1521
1522    _createAlt: function(result, index) {
1523      var li = L.DomUtil.create('li', ''),
1524        a = L.DomUtil.create('a', '', li),
1525        icon = this.options.showResultIcons && result.icon ? L.DomUtil.create('img', '', a) : null,
1526        text = result.html ? undefined : document.createTextNode(result.name),
1527        mouseDownHandler = function mouseDownHandler(e) {
1528          // In some browsers, a click will fire on the map if the control is
1529          // collapsed directly after mousedown. To work around this, we
1530          // wait until the click is completed, and _then_ collapse the
1531          // control. Messy, but this is the workaround I could come up with
1532          // for #142.
1533          this._preventBlurCollapse = true;
1534          L.DomEvent.stop(e);
1535          this._geocodeResultSelected(result);
1536          L.DomEvent.on(
1537            li,
1538            'click',
1539            function() {
1540              if (this.options.collapsed) {
1541                this._collapse();
1542              } else {
1543                this._clearResults();
1544              }
1545            },
1546            this
1547          );
1548        };
1549
1550      if (icon) {
1551        icon.src = result.icon;
1552      }
1553
1554      li.setAttribute('data-result-index', index);
1555
1556      if (result.html) {
1557        a.innerHTML = a.innerHTML + result.html;
1558      } else {
1559        a.appendChild(text);
1560      }
1561
1562      // Use mousedown and not click, since click will fire _after_ blur,
1563      // causing the control to have collapsed and removed the items
1564      // before the click can fire.
1565      L.DomEvent.addListener(li, 'mousedown touchstart', mouseDownHandler, this);
1566
1567      return li;
1568    },
1569
1570    _keydown: function(e) {
1571      var _this = this,
1572        select = function select(dir) {
1573          if (_this._selection) {
1574            L.DomUtil.removeClass(_this._selection, 'leaflet-control-geocoder-selected');
1575            _this._selection = _this._selection[dir > 0 ? 'nextSibling' : 'previousSibling'];
1576          }
1577          if (!_this._selection) {
1578            _this._selection = _this._alts[dir > 0 ? 'firstChild' : 'lastChild'];
1579          }
1580
1581          if (_this._selection) {
1582            L.DomUtil.addClass(_this._selection, 'leaflet-control-geocoder-selected');
1583          }
1584        };
1585
1586      switch (e.keyCode) {
1587        // Escape
1588        case 27:
1589          if (this.options.collapsed) {
1590            this._collapse();
1591          } else {
1592            this._clearResults();
1593          }
1594          break;
1595        // Up
1596        case 38:
1597          select(-1);
1598          break;
1599        // Up
1600        case 40:
1601          select(1);
1602          break;
1603        // Enter
1604        case 13:
1605          if (this._selection) {
1606            var index = parseInt(this._selection.getAttribute('data-result-index'), 10);
1607            this._geocodeResultSelected(this._results[index]);
1608            this._clearResults();
1609          } else {
1610            this._geocode();
1611          }
1612          break;
1613        default:
1614          return;
1615      }
1616
1617      L.DomEvent.preventDefault(e);
1618    },
1619    _change: function() {
1620      var v = this._input.value;
1621      if (v !== this._lastGeocode) {
1622        clearTimeout(this._suggestTimeout);
1623        if (v.length >= this.options.suggestMinLength) {
1624          this._suggestTimeout = setTimeout(
1625            L.bind(function() {
1626              this._geocode(true);
1627            }, this),
1628            this.options.suggestTimeout
1629          );
1630        } else {
1631          this._clearResults();
1632        }
1633      }
1634    }
1635  });
1636
1637  function geocoder(options) {
1638    return new Geocoder(options);
1639  }
1640
1641  L.Util.extend(Geocoder, geocoders);
1642
1643  L.Util.extend(L.Control, {
1644    Geocoder: Geocoder,
1645    geocoder: geocoder
1646  });
1647
1648  return Geocoder;
1649
1650}(L));

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.