PageSourceSearch

https://doctor4africa.com/wp-content/plugins/listeo-core/assets/js/control.geocoder.js?ver=1.8.50

js doctor4africa.com collected 2026-10-02 13:02:50 UTC 48,506 bytes, 1,662 lines download raw bytes

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

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.