PageSourceSearch

https://www.sante-numerique-normandie.fr/theme_front/theme_front_1…/dist/Control.Geocoder.js?1789406638

js sante-numerique-normandie.fr collected 2026-10-10 00:09:34 UTC 45,678 bytes, 1,484 lines download raw bytes

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