gtfs-to-html 2.12.1 → 2.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/index.js +26 -21
- package/dist/app/index.js.map +1 -1
- package/dist/bin/gtfs-to-html.js +37 -58
- package/dist/bin/gtfs-to-html.js.map +1 -1
- package/dist/frontend_libraries/anchorme.min.js +1 -0
- package/dist/frontend_libraries/gtfs-realtime.browser.proto.js +0 -0
- package/dist/frontend_libraries/maplibre-gl-geocoder.css +284 -0
- package/dist/frontend_libraries/maplibre-gl-geocoder.js +2790 -0
- package/dist/frontend_libraries/maplibre-gl.css +1 -0
- package/dist/frontend_libraries/maplibre-gl.js +59 -0
- package/dist/frontend_libraries/pbf.js +1 -0
- package/dist/index.js +37 -58
- package/dist/index.js.map +1 -1
- package/package.json +14 -11
- package/scripts/postinstall.js +115 -0
|
@@ -0,0 +1,2790 @@
|
|
|
1
|
+
(function (global, factory) {
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.MaplibreGeocoder = factory());
|
|
5
|
+
})(this, (function () { 'use strict';
|
|
6
|
+
|
|
7
|
+
/******************************************************************************
|
|
8
|
+
Copyright (c) Microsoft Corporation.
|
|
9
|
+
|
|
10
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
11
|
+
purpose with or without fee is hereby granted.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
14
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
15
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
16
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
17
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
18
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
19
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
20
|
+
***************************************************************************** */
|
|
21
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
25
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
26
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
27
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
28
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
29
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
30
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
35
|
+
var e = new Error(message);
|
|
36
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
40
|
+
|
|
41
|
+
function getDefaultExportFromCjs (x) {
|
|
42
|
+
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
var immutable;
|
|
46
|
+
var hasRequiredImmutable;
|
|
47
|
+
|
|
48
|
+
function requireImmutable () {
|
|
49
|
+
if (hasRequiredImmutable) return immutable;
|
|
50
|
+
hasRequiredImmutable = 1;
|
|
51
|
+
immutable = extend;
|
|
52
|
+
|
|
53
|
+
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
54
|
+
|
|
55
|
+
function extend() {
|
|
56
|
+
var target = {};
|
|
57
|
+
|
|
58
|
+
for (var i = 0; i < arguments.length; i++) {
|
|
59
|
+
var source = arguments[i];
|
|
60
|
+
|
|
61
|
+
for (var key in source) {
|
|
62
|
+
if (hasOwnProperty.call(source, key)) {
|
|
63
|
+
target[key] = source[key];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return target
|
|
69
|
+
}
|
|
70
|
+
return immutable;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
var fuzzy = {exports: {}};
|
|
74
|
+
|
|
75
|
+
/*
|
|
76
|
+
* Fuzzy
|
|
77
|
+
* https://github.com/myork/fuzzy
|
|
78
|
+
*
|
|
79
|
+
* Copyright (c) 2012 Matt York
|
|
80
|
+
* Licensed under the MIT license.
|
|
81
|
+
*/
|
|
82
|
+
|
|
83
|
+
var hasRequiredFuzzy;
|
|
84
|
+
|
|
85
|
+
function requireFuzzy () {
|
|
86
|
+
if (hasRequiredFuzzy) return fuzzy.exports;
|
|
87
|
+
hasRequiredFuzzy = 1;
|
|
88
|
+
(function (module, exports) {
|
|
89
|
+
(function() {
|
|
90
|
+
|
|
91
|
+
var fuzzy = {};
|
|
92
|
+
|
|
93
|
+
// Use in node or in browser
|
|
94
|
+
{
|
|
95
|
+
module.exports = fuzzy;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Return all elements of `array` that have a fuzzy
|
|
99
|
+
// match against `pattern`.
|
|
100
|
+
fuzzy.simpleFilter = function(pattern, array) {
|
|
101
|
+
return array.filter(function(str) {
|
|
102
|
+
return fuzzy.test(pattern, str);
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// Does `pattern` fuzzy match `str`?
|
|
107
|
+
fuzzy.test = function(pattern, str) {
|
|
108
|
+
return fuzzy.match(pattern, str) !== null;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// If `pattern` matches `str`, wrap each matching character
|
|
112
|
+
// in `opts.pre` and `opts.post`. If no match, return null
|
|
113
|
+
fuzzy.match = function(pattern, str, opts) {
|
|
114
|
+
opts = opts || {};
|
|
115
|
+
var patternIdx = 0
|
|
116
|
+
, result = []
|
|
117
|
+
, len = str.length
|
|
118
|
+
, totalScore = 0
|
|
119
|
+
, currScore = 0
|
|
120
|
+
// prefix
|
|
121
|
+
, pre = opts.pre || ''
|
|
122
|
+
// suffix
|
|
123
|
+
, post = opts.post || ''
|
|
124
|
+
// String to compare against. This might be a lowercase version of the
|
|
125
|
+
// raw string
|
|
126
|
+
, compareString = opts.caseSensitive && str || str.toLowerCase()
|
|
127
|
+
, ch;
|
|
128
|
+
|
|
129
|
+
pattern = opts.caseSensitive && pattern || pattern.toLowerCase();
|
|
130
|
+
|
|
131
|
+
// For each character in the string, either add it to the result
|
|
132
|
+
// or wrap in template if it's the next string in the pattern
|
|
133
|
+
for(var idx = 0; idx < len; idx++) {
|
|
134
|
+
ch = str[idx];
|
|
135
|
+
if(compareString[idx] === pattern[patternIdx]) {
|
|
136
|
+
ch = pre + ch + post;
|
|
137
|
+
patternIdx += 1;
|
|
138
|
+
|
|
139
|
+
// consecutive characters should increase the score more than linearly
|
|
140
|
+
currScore += 1 + currScore;
|
|
141
|
+
} else {
|
|
142
|
+
currScore = 0;
|
|
143
|
+
}
|
|
144
|
+
totalScore += currScore;
|
|
145
|
+
result[result.length] = ch;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// return rendered string if we have a match for every char
|
|
149
|
+
if(patternIdx === pattern.length) {
|
|
150
|
+
// if the string is an exact match with pattern, totalScore should be maxed
|
|
151
|
+
totalScore = (compareString === pattern) ? Infinity : totalScore;
|
|
152
|
+
return {rendered: result.join(''), score: totalScore};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return null;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// The normal entry point. Filters `arr` for matches against `pattern`.
|
|
159
|
+
// It returns an array with matching values of the type:
|
|
160
|
+
//
|
|
161
|
+
// [{
|
|
162
|
+
// string: '<b>lah' // The rendered string
|
|
163
|
+
// , index: 2 // The index of the element in `arr`
|
|
164
|
+
// , original: 'blah' // The original element in `arr`
|
|
165
|
+
// }]
|
|
166
|
+
//
|
|
167
|
+
// `opts` is an optional argument bag. Details:
|
|
168
|
+
//
|
|
169
|
+
// opts = {
|
|
170
|
+
// // string to put before a matching character
|
|
171
|
+
// pre: '<b>'
|
|
172
|
+
//
|
|
173
|
+
// // string to put after matching character
|
|
174
|
+
// , post: '</b>'
|
|
175
|
+
//
|
|
176
|
+
// // Optional function. Input is an entry in the given arr`,
|
|
177
|
+
// // output should be the string to test `pattern` against.
|
|
178
|
+
// // In this example, if `arr = [{crying: 'koala'}]` we would return
|
|
179
|
+
// // 'koala'.
|
|
180
|
+
// , extract: function(arg) { return arg.crying; }
|
|
181
|
+
// }
|
|
182
|
+
fuzzy.filter = function(pattern, arr, opts) {
|
|
183
|
+
if(!arr || arr.length === 0) {
|
|
184
|
+
return [];
|
|
185
|
+
}
|
|
186
|
+
if (typeof pattern !== 'string') {
|
|
187
|
+
return arr;
|
|
188
|
+
}
|
|
189
|
+
opts = opts || {};
|
|
190
|
+
return arr
|
|
191
|
+
.reduce(function(prev, element, idx, arr) {
|
|
192
|
+
var str = element;
|
|
193
|
+
if(opts.extract) {
|
|
194
|
+
str = opts.extract(element);
|
|
195
|
+
}
|
|
196
|
+
var rendered = fuzzy.match(pattern, str, opts);
|
|
197
|
+
if(rendered != null) {
|
|
198
|
+
prev[prev.length] = {
|
|
199
|
+
string: rendered.rendered
|
|
200
|
+
, score: rendered.score
|
|
201
|
+
, index: idx
|
|
202
|
+
, original: element
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
return prev;
|
|
206
|
+
}, [])
|
|
207
|
+
|
|
208
|
+
// Sort by score. Browsers are inconsistent wrt stable/unstable
|
|
209
|
+
// sorting, so force stable by using the index in the case of tie.
|
|
210
|
+
// See http://ofb.net/~sethml/is-sort-stable.html
|
|
211
|
+
.sort(function(a,b) {
|
|
212
|
+
var compare = b.score - a.score;
|
|
213
|
+
if(compare) return compare;
|
|
214
|
+
return a.index - b.index;
|
|
215
|
+
});
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
}());
|
|
220
|
+
} (fuzzy));
|
|
221
|
+
return fuzzy.exports;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
var list;
|
|
225
|
+
var hasRequiredList;
|
|
226
|
+
|
|
227
|
+
function requireList () {
|
|
228
|
+
if (hasRequiredList) return list;
|
|
229
|
+
hasRequiredList = 1;
|
|
230
|
+
|
|
231
|
+
var List = function(component) {
|
|
232
|
+
this.component = component;
|
|
233
|
+
this.items = [];
|
|
234
|
+
this.active = component.options.noInitialSelection ? -1 : 0;
|
|
235
|
+
this.wrapper = document.createElement('div');
|
|
236
|
+
this.wrapper.className = 'suggestions-wrapper';
|
|
237
|
+
this.element = document.createElement('ul');
|
|
238
|
+
this.element.className = 'suggestions';
|
|
239
|
+
this.wrapper.appendChild(this.element);
|
|
240
|
+
|
|
241
|
+
// selectingListItem is set to true in the time between the mousedown and mouseup when clicking an item in the list
|
|
242
|
+
// mousedown on a list item will cause the input to blur which normally hides the list, so this flag is used to keep
|
|
243
|
+
// the list open until the mouseup
|
|
244
|
+
this.selectingListItem = false;
|
|
245
|
+
|
|
246
|
+
component.el.parentNode.insertBefore(this.wrapper, component.el.nextSibling);
|
|
247
|
+
return this;
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
List.prototype.show = function() {
|
|
251
|
+
this.element.style.display = 'block';
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
List.prototype.hide = function() {
|
|
255
|
+
this.element.style.display = 'none';
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
List.prototype.add = function(item) {
|
|
259
|
+
this.items.push(item);
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
List.prototype.clear = function() {
|
|
263
|
+
this.items = [];
|
|
264
|
+
this.active = this.component.options.noInitialSelection ? -1 : 0;
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
List.prototype.isEmpty = function() {
|
|
268
|
+
return !this.items.length;
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
List.prototype.isVisible = function() {
|
|
272
|
+
return this.element.style.display === 'block';
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
List.prototype.draw = function() {
|
|
276
|
+
this.element.innerHTML = '';
|
|
277
|
+
|
|
278
|
+
if (this.items.length === 0) {
|
|
279
|
+
this.hide();
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
for (var i = 0; i < this.items.length; i++) {
|
|
284
|
+
this.drawItem(this.items[i], this.active === i);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
this.show();
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
List.prototype.drawItem = function(item, active) {
|
|
291
|
+
var li = document.createElement('li'),
|
|
292
|
+
a = document.createElement('a');
|
|
293
|
+
|
|
294
|
+
if (active) li.className += ' active';
|
|
295
|
+
|
|
296
|
+
a.innerHTML = item.string;
|
|
297
|
+
|
|
298
|
+
li.appendChild(a);
|
|
299
|
+
this.element.appendChild(li);
|
|
300
|
+
|
|
301
|
+
li.addEventListener('mousedown', function() {
|
|
302
|
+
this.selectingListItem = true;
|
|
303
|
+
}.bind(this));
|
|
304
|
+
|
|
305
|
+
li.addEventListener('mouseup', function() {
|
|
306
|
+
this.handleMouseUp.call(this, item);
|
|
307
|
+
}.bind(this));
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
List.prototype.handleMouseUp = function(item) {
|
|
311
|
+
this.selectingListItem = false;
|
|
312
|
+
this.component.value(item.original);
|
|
313
|
+
this.clear();
|
|
314
|
+
this.draw();
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
List.prototype.move = function(index) {
|
|
318
|
+
this.active = index;
|
|
319
|
+
this.draw();
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
List.prototype.previous = function() {
|
|
323
|
+
this.move(this.active <= 0 ? this.items.length - 1 : this.active - 1);
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
List.prototype.next = function() {
|
|
327
|
+
this.move(this.active >= this.items.length - 1 ? 0 : this.active + 1);
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
List.prototype.drawError = function(msg){
|
|
331
|
+
var li = document.createElement('li');
|
|
332
|
+
|
|
333
|
+
li.innerHTML = msg;
|
|
334
|
+
|
|
335
|
+
this.element.appendChild(li);
|
|
336
|
+
this.show();
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
list = List;
|
|
340
|
+
return list;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
var suggestions;
|
|
344
|
+
var hasRequiredSuggestions;
|
|
345
|
+
|
|
346
|
+
function requireSuggestions () {
|
|
347
|
+
if (hasRequiredSuggestions) return suggestions;
|
|
348
|
+
hasRequiredSuggestions = 1;
|
|
349
|
+
|
|
350
|
+
var extend = requireImmutable();
|
|
351
|
+
var fuzzy = requireFuzzy();
|
|
352
|
+
var List = requireList();
|
|
353
|
+
|
|
354
|
+
var Suggestions = function(el, data, options) {
|
|
355
|
+
options = options || {};
|
|
356
|
+
|
|
357
|
+
this.options = extend({
|
|
358
|
+
minLength: 2,
|
|
359
|
+
limit: 5,
|
|
360
|
+
filter: true,
|
|
361
|
+
hideOnBlur: true,
|
|
362
|
+
noInitialSelection: true
|
|
363
|
+
}, options);
|
|
364
|
+
|
|
365
|
+
this.el = el;
|
|
366
|
+
this.data = data || [];
|
|
367
|
+
this.list = new List(this);
|
|
368
|
+
|
|
369
|
+
this.query = '';
|
|
370
|
+
this.selected = null;
|
|
371
|
+
|
|
372
|
+
this.list.draw();
|
|
373
|
+
|
|
374
|
+
this.el.addEventListener('keyup', function(e) {
|
|
375
|
+
this.handleKeyUp(e.keyCode, e);
|
|
376
|
+
}.bind(this), false);
|
|
377
|
+
|
|
378
|
+
this.el.addEventListener('keydown', function(e) {
|
|
379
|
+
this.handleKeyDown(e);
|
|
380
|
+
}.bind(this));
|
|
381
|
+
|
|
382
|
+
this.el.addEventListener('focus', function() {
|
|
383
|
+
this.handleFocus();
|
|
384
|
+
}.bind(this));
|
|
385
|
+
|
|
386
|
+
this.el.addEventListener('blur', function() {
|
|
387
|
+
this.handleBlur();
|
|
388
|
+
}.bind(this));
|
|
389
|
+
|
|
390
|
+
this.el.addEventListener('paste', function(e) {
|
|
391
|
+
this.handlePaste(e);
|
|
392
|
+
}.bind(this));
|
|
393
|
+
|
|
394
|
+
// use user-provided render function if given, otherwise just use the default
|
|
395
|
+
this.render = (this.options.render) ? this.options.render.bind(this) : this.render.bind(this);
|
|
396
|
+
|
|
397
|
+
this.getItemValue = (this.options.getItemValue) ? this.options.getItemValue.bind(this) : this.getItemValue.bind(this);
|
|
398
|
+
|
|
399
|
+
return this;
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
Suggestions.prototype.handleKeyUp = function(keyCode, e) {
|
|
403
|
+
// 40 - DOWN
|
|
404
|
+
// 38 - UP
|
|
405
|
+
// 27 - ESC
|
|
406
|
+
// 13 - ENTER
|
|
407
|
+
// 9 - TAB
|
|
408
|
+
|
|
409
|
+
if (keyCode === 40 ||
|
|
410
|
+
keyCode === 38 ||
|
|
411
|
+
keyCode === 27 ||
|
|
412
|
+
keyCode === 9) return;
|
|
413
|
+
|
|
414
|
+
if (keyCode === 13) {
|
|
415
|
+
if (this.list.items[this.list.active]) {
|
|
416
|
+
this.list.handleMouseUp(this.list.items[this.list.active]);
|
|
417
|
+
e.stopPropagation();
|
|
418
|
+
}
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
this.handleInputChange(this.el.value);
|
|
423
|
+
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
Suggestions.prototype.handleKeyDown = function(e) {
|
|
427
|
+
switch (e.keyCode) {
|
|
428
|
+
case 13: // ENTER
|
|
429
|
+
if (this.list.active >= 0) {
|
|
430
|
+
this.list.selectingListItem = true;
|
|
431
|
+
}
|
|
432
|
+
break;
|
|
433
|
+
case 9: // TAB
|
|
434
|
+
if (!this.list.isEmpty()) {
|
|
435
|
+
if (this.list.isVisible()) {
|
|
436
|
+
e.preventDefault();
|
|
437
|
+
}
|
|
438
|
+
this.value(this.list.active >= 0 ? this.list.items[this.list.active].original : null);
|
|
439
|
+
this.list.hide();
|
|
440
|
+
}
|
|
441
|
+
break;
|
|
442
|
+
case 27: // ESC
|
|
443
|
+
if (!this.list.isEmpty()) this.list.hide();
|
|
444
|
+
break;
|
|
445
|
+
case 38: // UP
|
|
446
|
+
this.list.previous();
|
|
447
|
+
break;
|
|
448
|
+
case 40: // DOWN
|
|
449
|
+
this.list.next();
|
|
450
|
+
break;
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
Suggestions.prototype.handleBlur = function() {
|
|
455
|
+
if (!this.list.selectingListItem && this.options.hideOnBlur) {
|
|
456
|
+
this.list.hide();
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
Suggestions.prototype.handlePaste = function(e) {
|
|
461
|
+
if (e.clipboardData) {
|
|
462
|
+
this.handleInputChange(e.clipboardData.getData('Text'));
|
|
463
|
+
} else {
|
|
464
|
+
var self = this;
|
|
465
|
+
setTimeout(function () {
|
|
466
|
+
self.handleInputChange(e.target.value);
|
|
467
|
+
}, 100);
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
Suggestions.prototype.handleInputChange = function(query) {
|
|
472
|
+
this.query = this.normalize(query);
|
|
473
|
+
|
|
474
|
+
this.list.clear();
|
|
475
|
+
|
|
476
|
+
if (this.query.length < this.options.minLength) {
|
|
477
|
+
this.list.draw();
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
this.getCandidates(function(data) {
|
|
482
|
+
for (var i = 0; i < data.length; i++) {
|
|
483
|
+
this.list.add(data[i]);
|
|
484
|
+
if (i === (this.options.limit - 1)) break;
|
|
485
|
+
}
|
|
486
|
+
this.list.draw();
|
|
487
|
+
}.bind(this));
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
Suggestions.prototype.handleFocus = function() {
|
|
491
|
+
if (!this.list.isEmpty()) this.list.show();
|
|
492
|
+
this.list.selectingListItem = false;
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Update data previously passed
|
|
497
|
+
*
|
|
498
|
+
* @param {Array} revisedData
|
|
499
|
+
*/
|
|
500
|
+
Suggestions.prototype.update = function(revisedData) {
|
|
501
|
+
this.data = revisedData;
|
|
502
|
+
this.handleKeyUp();
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Clears data
|
|
507
|
+
*/
|
|
508
|
+
Suggestions.prototype.clear = function() {
|
|
509
|
+
this.data = [];
|
|
510
|
+
this.list.clear();
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Normalize the results list and input value for matching
|
|
515
|
+
*
|
|
516
|
+
* @param {String} value
|
|
517
|
+
* @return {String}
|
|
518
|
+
*/
|
|
519
|
+
Suggestions.prototype.normalize = function(value) {
|
|
520
|
+
value = value.toLowerCase();
|
|
521
|
+
return value;
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Evaluates whether an array item qualifies as a match with the current query
|
|
526
|
+
*
|
|
527
|
+
* @param {String} candidate a possible item from the array passed
|
|
528
|
+
* @param {String} query the current query
|
|
529
|
+
* @return {Boolean}
|
|
530
|
+
*/
|
|
531
|
+
Suggestions.prototype.match = function(candidate, query) {
|
|
532
|
+
return candidate.indexOf(query) > -1;
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
Suggestions.prototype.value = function(value) {
|
|
536
|
+
this.selected = value;
|
|
537
|
+
this.el.value = this.getItemValue(value || { place_name: this.query });
|
|
538
|
+
|
|
539
|
+
if (document.createEvent) {
|
|
540
|
+
var e = document.createEvent('HTMLEvents');
|
|
541
|
+
e.initEvent('change', true, false);
|
|
542
|
+
this.el.dispatchEvent(e);
|
|
543
|
+
} else {
|
|
544
|
+
this.el.fireEvent('onchange');
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
|
|
548
|
+
Suggestions.prototype.getCandidates = function(callback) {
|
|
549
|
+
var options = {
|
|
550
|
+
pre: '<strong>',
|
|
551
|
+
post: '</strong>',
|
|
552
|
+
extract: function(d) { return this.getItemValue(d); }.bind(this)
|
|
553
|
+
};
|
|
554
|
+
var results;
|
|
555
|
+
if(this.options.filter){
|
|
556
|
+
results = fuzzy.filter(this.query, this.data, options);
|
|
557
|
+
|
|
558
|
+
results = results.map(function(item){
|
|
559
|
+
return {
|
|
560
|
+
original: item.original,
|
|
561
|
+
string: this.render(item.original, item.string)
|
|
562
|
+
};
|
|
563
|
+
}.bind(this));
|
|
564
|
+
}else {
|
|
565
|
+
results = this.data.map(function(d) {
|
|
566
|
+
var renderedString = this.render(d);
|
|
567
|
+
return {
|
|
568
|
+
original: d,
|
|
569
|
+
string: renderedString
|
|
570
|
+
};
|
|
571
|
+
}.bind(this));
|
|
572
|
+
}
|
|
573
|
+
callback(results);
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* For a given item in the data array, return what should be used as the candidate string
|
|
578
|
+
*
|
|
579
|
+
* @param {Object|String} item an item from the data array
|
|
580
|
+
* @return {String} item
|
|
581
|
+
*/
|
|
582
|
+
Suggestions.prototype.getItemValue = function(item) {
|
|
583
|
+
return item;
|
|
584
|
+
};
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* For a given item in the data array, return a string of html that should be rendered in the dropdown
|
|
588
|
+
* @param {Object|String} item an item from the data array
|
|
589
|
+
* @param {String} sourceFormatting a string that has pre-formatted html that should be passed directly through the render function
|
|
590
|
+
* @return {String} html
|
|
591
|
+
*/
|
|
592
|
+
Suggestions.prototype.render = function(item, sourceFormatting) {
|
|
593
|
+
if (sourceFormatting){
|
|
594
|
+
// use existing formatting on the source string
|
|
595
|
+
return sourceFormatting;
|
|
596
|
+
}
|
|
597
|
+
var boldString = (item.original) ? this.getItemValue(item.original) : this.getItemValue(item);
|
|
598
|
+
var indexString = this.normalize(boldString);
|
|
599
|
+
var indexOfQuery = indexString.lastIndexOf(this.query);
|
|
600
|
+
while (indexOfQuery > -1) {
|
|
601
|
+
var endIndexOfQuery = indexOfQuery + this.query.length;
|
|
602
|
+
boldString = boldString.slice(0, indexOfQuery) + '<strong>' + boldString.slice(indexOfQuery, endIndexOfQuery) + '</strong>' + boldString.slice(endIndexOfQuery);
|
|
603
|
+
indexOfQuery = indexString.slice(0, indexOfQuery).lastIndexOf(this.query);
|
|
604
|
+
}
|
|
605
|
+
return boldString
|
|
606
|
+
};
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* Render an custom error message in the suggestions list
|
|
610
|
+
* @param {String} msg An html string to render as an error message
|
|
611
|
+
*/
|
|
612
|
+
Suggestions.prototype.renderError = function(msg){
|
|
613
|
+
this.list.drawError(msg);
|
|
614
|
+
};
|
|
615
|
+
|
|
616
|
+
suggestions = Suggestions;
|
|
617
|
+
return suggestions;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
var suggestionsList;
|
|
621
|
+
var hasRequiredSuggestionsList;
|
|
622
|
+
|
|
623
|
+
function requireSuggestionsList () {
|
|
624
|
+
if (hasRequiredSuggestionsList) return suggestionsList;
|
|
625
|
+
hasRequiredSuggestionsList = 1;
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* A typeahead component for inputs
|
|
629
|
+
* @class Suggestions
|
|
630
|
+
*
|
|
631
|
+
* @param {HTMLInputElement} el A valid HTML input element
|
|
632
|
+
* @param {Array} data An array of data used for results
|
|
633
|
+
* @param {Object} options
|
|
634
|
+
* @param {Number} [options.limit=5] Max number of results to display in the auto suggest list.
|
|
635
|
+
* @param {Number} [options.minLength=2] Number of characters typed into an input to trigger suggestions.
|
|
636
|
+
* @param {Boolean} [options.hideOnBlur=true] If `true`, hides the suggestions when focus is lost.
|
|
637
|
+
* @return {Suggestions} `this`
|
|
638
|
+
* @example
|
|
639
|
+
* // in the browser
|
|
640
|
+
* var input = document.querySelector('input');
|
|
641
|
+
* var data = [
|
|
642
|
+
* 'Roy Eldridge',
|
|
643
|
+
* 'Roy Hargrove',
|
|
644
|
+
* 'Rex Stewart'
|
|
645
|
+
* ];
|
|
646
|
+
*
|
|
647
|
+
* new Suggestions(input, data);
|
|
648
|
+
*
|
|
649
|
+
* // with options
|
|
650
|
+
* var input = document.querySelector('input');
|
|
651
|
+
* var data = [{
|
|
652
|
+
* name: 'Roy Eldridge',
|
|
653
|
+
* year: 1911
|
|
654
|
+
* }, {
|
|
655
|
+
* name: 'Roy Hargrove',
|
|
656
|
+
* year: 1969
|
|
657
|
+
* }, {
|
|
658
|
+
* name: 'Rex Stewart',
|
|
659
|
+
* year: 1907
|
|
660
|
+
* }];
|
|
661
|
+
*
|
|
662
|
+
* var typeahead = new Suggestions(input, data, {
|
|
663
|
+
* filter: false, // Disable filtering
|
|
664
|
+
* minLength: 3, // Number of characters typed into an input to trigger suggestions.
|
|
665
|
+
* limit: 3, // Max number of results to display.
|
|
666
|
+
* hideOnBlur: false // Don't hide results when input loses focus
|
|
667
|
+
* });
|
|
668
|
+
*
|
|
669
|
+
* // As we're passing an object of an arrays as data, override
|
|
670
|
+
* // `getItemValue` by specifying the specific property to search on.
|
|
671
|
+
* typeahead.getItemValue = function(item) { return item.name };
|
|
672
|
+
*
|
|
673
|
+
* input.addEventListener('change', function() {
|
|
674
|
+
* console.log(typeahead.selected); // Current selected item.
|
|
675
|
+
* });
|
|
676
|
+
*
|
|
677
|
+
* // With browserify
|
|
678
|
+
* var Suggestions = require('suggestions');
|
|
679
|
+
*
|
|
680
|
+
* new Suggestions(input, data);
|
|
681
|
+
*/
|
|
682
|
+
var Suggestions = requireSuggestions();
|
|
683
|
+
suggestionsList = Suggestions;
|
|
684
|
+
|
|
685
|
+
if (typeof window !== 'undefined') {
|
|
686
|
+
window.Suggestions = Suggestions;
|
|
687
|
+
}
|
|
688
|
+
return suggestionsList;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
var suggestionsListExports = requireSuggestionsList();
|
|
692
|
+
var Typeahead = /*@__PURE__*/getDefaultExportFromCjs(suggestionsListExports);
|
|
693
|
+
|
|
694
|
+
var subtag$2 = {exports: {}};
|
|
695
|
+
|
|
696
|
+
var subtag$1 = subtag$2.exports;
|
|
697
|
+
|
|
698
|
+
var hasRequiredSubtag;
|
|
699
|
+
|
|
700
|
+
function requireSubtag () {
|
|
701
|
+
if (hasRequiredSubtag) return subtag$2.exports;
|
|
702
|
+
hasRequiredSubtag = 1;
|
|
703
|
+
(function (module) {
|
|
704
|
+
!function(root, name, make) {
|
|
705
|
+
if (module.exports) module.exports = make();
|
|
706
|
+
else root[name] = make();
|
|
707
|
+
}(subtag$1, 'subtag', function() {
|
|
708
|
+
|
|
709
|
+
var empty = '';
|
|
710
|
+
var pattern = /^([a-zA-Z]{2,3})(?:[_-]+([a-zA-Z]{3})(?=$|[_-]+))?(?:[_-]+([a-zA-Z]{4})(?=$|[_-]+))?(?:[_-]+([a-zA-Z]{2}|[0-9]{3})(?=$|[_-]+))?/;
|
|
711
|
+
|
|
712
|
+
function match(tag) {
|
|
713
|
+
return tag.match(pattern) || []
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
function split(tag) {
|
|
717
|
+
return match(tag).filter(function(v, i) { return v && i })
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
function api(tag) {
|
|
721
|
+
tag = match(tag);
|
|
722
|
+
return {
|
|
723
|
+
language: tag[1] || empty,
|
|
724
|
+
extlang: tag[2] || empty,
|
|
725
|
+
script: tag[3] || empty,
|
|
726
|
+
region: tag[4] || empty
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
function expose(target, key, value) {
|
|
731
|
+
Object.defineProperty(target, key, {
|
|
732
|
+
value: value,
|
|
733
|
+
enumerable: true
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
function part(position, pattern, type) {
|
|
738
|
+
function method(tag) {
|
|
739
|
+
return match(tag)[position] || empty
|
|
740
|
+
}
|
|
741
|
+
expose(method, 'pattern', pattern);
|
|
742
|
+
expose(api, type, method);
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
part(1, /^[a-zA-Z]{2,3}$/, 'language');
|
|
746
|
+
part(2, /^[a-zA-Z]{3}$/, 'extlang');
|
|
747
|
+
part(3, /^[a-zA-Z]{4}$/, 'script');
|
|
748
|
+
part(4, /^[a-zA-Z]{2}$|^[0-9]{3}$/, 'region');
|
|
749
|
+
|
|
750
|
+
expose(api, 'split', split);
|
|
751
|
+
|
|
752
|
+
return api
|
|
753
|
+
});
|
|
754
|
+
} (subtag$2));
|
|
755
|
+
return subtag$2.exports;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
var subtagExports = requireSubtag();
|
|
759
|
+
var subtag = /*@__PURE__*/getDefaultExportFromCjs(subtagExports);
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* lodash (Custom Build) <https://lodash.com/>
|
|
763
|
+
* Build: `lodash modularize exports="npm" -o ./`
|
|
764
|
+
* Copyright jQuery Foundation and other contributors <https://jquery.org/>
|
|
765
|
+
* Released under MIT license <https://lodash.com/license>
|
|
766
|
+
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
|
|
767
|
+
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
|
768
|
+
*/
|
|
769
|
+
|
|
770
|
+
var lodash_debounce;
|
|
771
|
+
var hasRequiredLodash_debounce;
|
|
772
|
+
|
|
773
|
+
function requireLodash_debounce () {
|
|
774
|
+
if (hasRequiredLodash_debounce) return lodash_debounce;
|
|
775
|
+
hasRequiredLodash_debounce = 1;
|
|
776
|
+
/** Used as the `TypeError` message for "Functions" methods. */
|
|
777
|
+
var FUNC_ERROR_TEXT = 'Expected a function';
|
|
778
|
+
|
|
779
|
+
/** Used as references for various `Number` constants. */
|
|
780
|
+
var NAN = 0 / 0;
|
|
781
|
+
|
|
782
|
+
/** `Object#toString` result references. */
|
|
783
|
+
var symbolTag = '[object Symbol]';
|
|
784
|
+
|
|
785
|
+
/** Used to match leading and trailing whitespace. */
|
|
786
|
+
var reTrim = /^\s+|\s+$/g;
|
|
787
|
+
|
|
788
|
+
/** Used to detect bad signed hexadecimal string values. */
|
|
789
|
+
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
|
|
790
|
+
|
|
791
|
+
/** Used to detect binary string values. */
|
|
792
|
+
var reIsBinary = /^0b[01]+$/i;
|
|
793
|
+
|
|
794
|
+
/** Used to detect octal string values. */
|
|
795
|
+
var reIsOctal = /^0o[0-7]+$/i;
|
|
796
|
+
|
|
797
|
+
/** Built-in method references without a dependency on `root`. */
|
|
798
|
+
var freeParseInt = parseInt;
|
|
799
|
+
|
|
800
|
+
/** Detect free variable `global` from Node.js. */
|
|
801
|
+
var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
|
|
802
|
+
|
|
803
|
+
/** Detect free variable `self`. */
|
|
804
|
+
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
|
|
805
|
+
|
|
806
|
+
/** Used as a reference to the global object. */
|
|
807
|
+
var root = freeGlobal || freeSelf || Function('return this')();
|
|
808
|
+
|
|
809
|
+
/** Used for built-in method references. */
|
|
810
|
+
var objectProto = Object.prototype;
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* Used to resolve the
|
|
814
|
+
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
|
|
815
|
+
* of values.
|
|
816
|
+
*/
|
|
817
|
+
var objectToString = objectProto.toString;
|
|
818
|
+
|
|
819
|
+
/* Built-in method references for those with the same name as other `lodash` methods. */
|
|
820
|
+
var nativeMax = Math.max,
|
|
821
|
+
nativeMin = Math.min;
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Gets the timestamp of the number of milliseconds that have elapsed since
|
|
825
|
+
* the Unix epoch (1 January 1970 00:00:00 UTC).
|
|
826
|
+
*
|
|
827
|
+
* @static
|
|
828
|
+
* @memberOf _
|
|
829
|
+
* @since 2.4.0
|
|
830
|
+
* @category Date
|
|
831
|
+
* @returns {number} Returns the timestamp.
|
|
832
|
+
* @example
|
|
833
|
+
*
|
|
834
|
+
* _.defer(function(stamp) {
|
|
835
|
+
* console.log(_.now() - stamp);
|
|
836
|
+
* }, _.now());
|
|
837
|
+
* // => Logs the number of milliseconds it took for the deferred invocation.
|
|
838
|
+
*/
|
|
839
|
+
var now = function() {
|
|
840
|
+
return root.Date.now();
|
|
841
|
+
};
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
* Creates a debounced function that delays invoking `func` until after `wait`
|
|
845
|
+
* milliseconds have elapsed since the last time the debounced function was
|
|
846
|
+
* invoked. The debounced function comes with a `cancel` method to cancel
|
|
847
|
+
* delayed `func` invocations and a `flush` method to immediately invoke them.
|
|
848
|
+
* Provide `options` to indicate whether `func` should be invoked on the
|
|
849
|
+
* leading and/or trailing edge of the `wait` timeout. The `func` is invoked
|
|
850
|
+
* with the last arguments provided to the debounced function. Subsequent
|
|
851
|
+
* calls to the debounced function return the result of the last `func`
|
|
852
|
+
* invocation.
|
|
853
|
+
*
|
|
854
|
+
* **Note:** If `leading` and `trailing` options are `true`, `func` is
|
|
855
|
+
* invoked on the trailing edge of the timeout only if the debounced function
|
|
856
|
+
* is invoked more than once during the `wait` timeout.
|
|
857
|
+
*
|
|
858
|
+
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
|
|
859
|
+
* until to the next tick, similar to `setTimeout` with a timeout of `0`.
|
|
860
|
+
*
|
|
861
|
+
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
|
|
862
|
+
* for details over the differences between `_.debounce` and `_.throttle`.
|
|
863
|
+
*
|
|
864
|
+
* @static
|
|
865
|
+
* @memberOf _
|
|
866
|
+
* @since 0.1.0
|
|
867
|
+
* @category Function
|
|
868
|
+
* @param {Function} func The function to debounce.
|
|
869
|
+
* @param {number} [wait=0] The number of milliseconds to delay.
|
|
870
|
+
* @param {Object} [options={}] The options object.
|
|
871
|
+
* @param {boolean} [options.leading=false]
|
|
872
|
+
* Specify invoking on the leading edge of the timeout.
|
|
873
|
+
* @param {number} [options.maxWait]
|
|
874
|
+
* The maximum time `func` is allowed to be delayed before it's invoked.
|
|
875
|
+
* @param {boolean} [options.trailing=true]
|
|
876
|
+
* Specify invoking on the trailing edge of the timeout.
|
|
877
|
+
* @returns {Function} Returns the new debounced function.
|
|
878
|
+
* @example
|
|
879
|
+
*
|
|
880
|
+
* // Avoid costly calculations while the window size is in flux.
|
|
881
|
+
* jQuery(window).on('resize', _.debounce(calculateLayout, 150));
|
|
882
|
+
*
|
|
883
|
+
* // Invoke `sendMail` when clicked, debouncing subsequent calls.
|
|
884
|
+
* jQuery(element).on('click', _.debounce(sendMail, 300, {
|
|
885
|
+
* 'leading': true,
|
|
886
|
+
* 'trailing': false
|
|
887
|
+
* }));
|
|
888
|
+
*
|
|
889
|
+
* // Ensure `batchLog` is invoked once after 1 second of debounced calls.
|
|
890
|
+
* var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
|
|
891
|
+
* var source = new EventSource('/stream');
|
|
892
|
+
* jQuery(source).on('message', debounced);
|
|
893
|
+
*
|
|
894
|
+
* // Cancel the trailing debounced invocation.
|
|
895
|
+
* jQuery(window).on('popstate', debounced.cancel);
|
|
896
|
+
*/
|
|
897
|
+
function debounce(func, wait, options) {
|
|
898
|
+
var lastArgs,
|
|
899
|
+
lastThis,
|
|
900
|
+
maxWait,
|
|
901
|
+
result,
|
|
902
|
+
timerId,
|
|
903
|
+
lastCallTime,
|
|
904
|
+
lastInvokeTime = 0,
|
|
905
|
+
leading = false,
|
|
906
|
+
maxing = false,
|
|
907
|
+
trailing = true;
|
|
908
|
+
|
|
909
|
+
if (typeof func != 'function') {
|
|
910
|
+
throw new TypeError(FUNC_ERROR_TEXT);
|
|
911
|
+
}
|
|
912
|
+
wait = toNumber(wait) || 0;
|
|
913
|
+
if (isObject(options)) {
|
|
914
|
+
leading = !!options.leading;
|
|
915
|
+
maxing = 'maxWait' in options;
|
|
916
|
+
maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
|
|
917
|
+
trailing = 'trailing' in options ? !!options.trailing : trailing;
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
function invokeFunc(time) {
|
|
921
|
+
var args = lastArgs,
|
|
922
|
+
thisArg = lastThis;
|
|
923
|
+
|
|
924
|
+
lastArgs = lastThis = undefined;
|
|
925
|
+
lastInvokeTime = time;
|
|
926
|
+
result = func.apply(thisArg, args);
|
|
927
|
+
return result;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
function leadingEdge(time) {
|
|
931
|
+
// Reset any `maxWait` timer.
|
|
932
|
+
lastInvokeTime = time;
|
|
933
|
+
// Start the timer for the trailing edge.
|
|
934
|
+
timerId = setTimeout(timerExpired, wait);
|
|
935
|
+
// Invoke the leading edge.
|
|
936
|
+
return leading ? invokeFunc(time) : result;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
function remainingWait(time) {
|
|
940
|
+
var timeSinceLastCall = time - lastCallTime,
|
|
941
|
+
timeSinceLastInvoke = time - lastInvokeTime,
|
|
942
|
+
result = wait - timeSinceLastCall;
|
|
943
|
+
|
|
944
|
+
return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
function shouldInvoke(time) {
|
|
948
|
+
var timeSinceLastCall = time - lastCallTime,
|
|
949
|
+
timeSinceLastInvoke = time - lastInvokeTime;
|
|
950
|
+
|
|
951
|
+
// Either this is the first call, activity has stopped and we're at the
|
|
952
|
+
// trailing edge, the system time has gone backwards and we're treating
|
|
953
|
+
// it as the trailing edge, or we've hit the `maxWait` limit.
|
|
954
|
+
return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
|
|
955
|
+
(timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
function timerExpired() {
|
|
959
|
+
var time = now();
|
|
960
|
+
if (shouldInvoke(time)) {
|
|
961
|
+
return trailingEdge(time);
|
|
962
|
+
}
|
|
963
|
+
// Restart the timer.
|
|
964
|
+
timerId = setTimeout(timerExpired, remainingWait(time));
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
function trailingEdge(time) {
|
|
968
|
+
timerId = undefined;
|
|
969
|
+
|
|
970
|
+
// Only invoke if we have `lastArgs` which means `func` has been
|
|
971
|
+
// debounced at least once.
|
|
972
|
+
if (trailing && lastArgs) {
|
|
973
|
+
return invokeFunc(time);
|
|
974
|
+
}
|
|
975
|
+
lastArgs = lastThis = undefined;
|
|
976
|
+
return result;
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
function cancel() {
|
|
980
|
+
if (timerId !== undefined) {
|
|
981
|
+
clearTimeout(timerId);
|
|
982
|
+
}
|
|
983
|
+
lastInvokeTime = 0;
|
|
984
|
+
lastArgs = lastCallTime = lastThis = timerId = undefined;
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
function flush() {
|
|
988
|
+
return timerId === undefined ? result : trailingEdge(now());
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
function debounced() {
|
|
992
|
+
var time = now(),
|
|
993
|
+
isInvoking = shouldInvoke(time);
|
|
994
|
+
|
|
995
|
+
lastArgs = arguments;
|
|
996
|
+
lastThis = this;
|
|
997
|
+
lastCallTime = time;
|
|
998
|
+
|
|
999
|
+
if (isInvoking) {
|
|
1000
|
+
if (timerId === undefined) {
|
|
1001
|
+
return leadingEdge(lastCallTime);
|
|
1002
|
+
}
|
|
1003
|
+
if (maxing) {
|
|
1004
|
+
// Handle invocations in a tight loop.
|
|
1005
|
+
timerId = setTimeout(timerExpired, wait);
|
|
1006
|
+
return invokeFunc(lastCallTime);
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
if (timerId === undefined) {
|
|
1010
|
+
timerId = setTimeout(timerExpired, wait);
|
|
1011
|
+
}
|
|
1012
|
+
return result;
|
|
1013
|
+
}
|
|
1014
|
+
debounced.cancel = cancel;
|
|
1015
|
+
debounced.flush = flush;
|
|
1016
|
+
return debounced;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
/**
|
|
1020
|
+
* Checks if `value` is the
|
|
1021
|
+
* [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
|
|
1022
|
+
* of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
|
|
1023
|
+
*
|
|
1024
|
+
* @static
|
|
1025
|
+
* @memberOf _
|
|
1026
|
+
* @since 0.1.0
|
|
1027
|
+
* @category Lang
|
|
1028
|
+
* @param {*} value The value to check.
|
|
1029
|
+
* @returns {boolean} Returns `true` if `value` is an object, else `false`.
|
|
1030
|
+
* @example
|
|
1031
|
+
*
|
|
1032
|
+
* _.isObject({});
|
|
1033
|
+
* // => true
|
|
1034
|
+
*
|
|
1035
|
+
* _.isObject([1, 2, 3]);
|
|
1036
|
+
* // => true
|
|
1037
|
+
*
|
|
1038
|
+
* _.isObject(_.noop);
|
|
1039
|
+
* // => true
|
|
1040
|
+
*
|
|
1041
|
+
* _.isObject(null);
|
|
1042
|
+
* // => false
|
|
1043
|
+
*/
|
|
1044
|
+
function isObject(value) {
|
|
1045
|
+
var type = typeof value;
|
|
1046
|
+
return !!value && (type == 'object' || type == 'function');
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
/**
|
|
1050
|
+
* Checks if `value` is object-like. A value is object-like if it's not `null`
|
|
1051
|
+
* and has a `typeof` result of "object".
|
|
1052
|
+
*
|
|
1053
|
+
* @static
|
|
1054
|
+
* @memberOf _
|
|
1055
|
+
* @since 4.0.0
|
|
1056
|
+
* @category Lang
|
|
1057
|
+
* @param {*} value The value to check.
|
|
1058
|
+
* @returns {boolean} Returns `true` if `value` is object-like, else `false`.
|
|
1059
|
+
* @example
|
|
1060
|
+
*
|
|
1061
|
+
* _.isObjectLike({});
|
|
1062
|
+
* // => true
|
|
1063
|
+
*
|
|
1064
|
+
* _.isObjectLike([1, 2, 3]);
|
|
1065
|
+
* // => true
|
|
1066
|
+
*
|
|
1067
|
+
* _.isObjectLike(_.noop);
|
|
1068
|
+
* // => false
|
|
1069
|
+
*
|
|
1070
|
+
* _.isObjectLike(null);
|
|
1071
|
+
* // => false
|
|
1072
|
+
*/
|
|
1073
|
+
function isObjectLike(value) {
|
|
1074
|
+
return !!value && typeof value == 'object';
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
/**
|
|
1078
|
+
* Checks if `value` is classified as a `Symbol` primitive or object.
|
|
1079
|
+
*
|
|
1080
|
+
* @static
|
|
1081
|
+
* @memberOf _
|
|
1082
|
+
* @since 4.0.0
|
|
1083
|
+
* @category Lang
|
|
1084
|
+
* @param {*} value The value to check.
|
|
1085
|
+
* @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
|
|
1086
|
+
* @example
|
|
1087
|
+
*
|
|
1088
|
+
* _.isSymbol(Symbol.iterator);
|
|
1089
|
+
* // => true
|
|
1090
|
+
*
|
|
1091
|
+
* _.isSymbol('abc');
|
|
1092
|
+
* // => false
|
|
1093
|
+
*/
|
|
1094
|
+
function isSymbol(value) {
|
|
1095
|
+
return typeof value == 'symbol' ||
|
|
1096
|
+
(isObjectLike(value) && objectToString.call(value) == symbolTag);
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
/**
|
|
1100
|
+
* Converts `value` to a number.
|
|
1101
|
+
*
|
|
1102
|
+
* @static
|
|
1103
|
+
* @memberOf _
|
|
1104
|
+
* @since 4.0.0
|
|
1105
|
+
* @category Lang
|
|
1106
|
+
* @param {*} value The value to process.
|
|
1107
|
+
* @returns {number} Returns the number.
|
|
1108
|
+
* @example
|
|
1109
|
+
*
|
|
1110
|
+
* _.toNumber(3.2);
|
|
1111
|
+
* // => 3.2
|
|
1112
|
+
*
|
|
1113
|
+
* _.toNumber(Number.MIN_VALUE);
|
|
1114
|
+
* // => 5e-324
|
|
1115
|
+
*
|
|
1116
|
+
* _.toNumber(Infinity);
|
|
1117
|
+
* // => Infinity
|
|
1118
|
+
*
|
|
1119
|
+
* _.toNumber('3.2');
|
|
1120
|
+
* // => 3.2
|
|
1121
|
+
*/
|
|
1122
|
+
function toNumber(value) {
|
|
1123
|
+
if (typeof value == 'number') {
|
|
1124
|
+
return value;
|
|
1125
|
+
}
|
|
1126
|
+
if (isSymbol(value)) {
|
|
1127
|
+
return NAN;
|
|
1128
|
+
}
|
|
1129
|
+
if (isObject(value)) {
|
|
1130
|
+
var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
|
|
1131
|
+
value = isObject(other) ? (other + '') : other;
|
|
1132
|
+
}
|
|
1133
|
+
if (typeof value != 'string') {
|
|
1134
|
+
return value === 0 ? value : +value;
|
|
1135
|
+
}
|
|
1136
|
+
value = value.replace(reTrim, '');
|
|
1137
|
+
var isBinary = reIsBinary.test(value);
|
|
1138
|
+
return (isBinary || reIsOctal.test(value))
|
|
1139
|
+
? freeParseInt(value.slice(2), isBinary ? 2 : 8)
|
|
1140
|
+
: (reIsBadHex.test(value) ? NAN : +value);
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
lodash_debounce = debounce;
|
|
1144
|
+
return lodash_debounce;
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
var lodash_debounceExports = requireLodash_debounce();
|
|
1148
|
+
var debounce = /*@__PURE__*/getDefaultExportFromCjs(lodash_debounceExports);
|
|
1149
|
+
|
|
1150
|
+
var immutableExports = requireImmutable();
|
|
1151
|
+
var extend = /*@__PURE__*/getDefaultExportFromCjs(immutableExports);
|
|
1152
|
+
|
|
1153
|
+
var events = {exports: {}};
|
|
1154
|
+
|
|
1155
|
+
var hasRequiredEvents;
|
|
1156
|
+
|
|
1157
|
+
function requireEvents () {
|
|
1158
|
+
if (hasRequiredEvents) return events.exports;
|
|
1159
|
+
hasRequiredEvents = 1;
|
|
1160
|
+
|
|
1161
|
+
var R = typeof Reflect === 'object' ? Reflect : null;
|
|
1162
|
+
var ReflectApply = R && typeof R.apply === 'function'
|
|
1163
|
+
? R.apply
|
|
1164
|
+
: function ReflectApply(target, receiver, args) {
|
|
1165
|
+
return Function.prototype.apply.call(target, receiver, args);
|
|
1166
|
+
};
|
|
1167
|
+
|
|
1168
|
+
var ReflectOwnKeys;
|
|
1169
|
+
if (R && typeof R.ownKeys === 'function') {
|
|
1170
|
+
ReflectOwnKeys = R.ownKeys;
|
|
1171
|
+
} else if (Object.getOwnPropertySymbols) {
|
|
1172
|
+
ReflectOwnKeys = function ReflectOwnKeys(target) {
|
|
1173
|
+
return Object.getOwnPropertyNames(target)
|
|
1174
|
+
.concat(Object.getOwnPropertySymbols(target));
|
|
1175
|
+
};
|
|
1176
|
+
} else {
|
|
1177
|
+
ReflectOwnKeys = function ReflectOwnKeys(target) {
|
|
1178
|
+
return Object.getOwnPropertyNames(target);
|
|
1179
|
+
};
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
function ProcessEmitWarning(warning) {
|
|
1183
|
+
if (console && console.warn) console.warn(warning);
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) {
|
|
1187
|
+
return value !== value;
|
|
1188
|
+
};
|
|
1189
|
+
|
|
1190
|
+
function EventEmitter() {
|
|
1191
|
+
EventEmitter.init.call(this);
|
|
1192
|
+
}
|
|
1193
|
+
events.exports = EventEmitter;
|
|
1194
|
+
events.exports.once = once;
|
|
1195
|
+
|
|
1196
|
+
// Backwards-compat with node 0.10.x
|
|
1197
|
+
EventEmitter.EventEmitter = EventEmitter;
|
|
1198
|
+
|
|
1199
|
+
EventEmitter.prototype._events = undefined;
|
|
1200
|
+
EventEmitter.prototype._eventsCount = 0;
|
|
1201
|
+
EventEmitter.prototype._maxListeners = undefined;
|
|
1202
|
+
|
|
1203
|
+
// By default EventEmitters will print a warning if more than 10 listeners are
|
|
1204
|
+
// added to it. This is a useful default which helps finding memory leaks.
|
|
1205
|
+
var defaultMaxListeners = 10;
|
|
1206
|
+
|
|
1207
|
+
function checkListener(listener) {
|
|
1208
|
+
if (typeof listener !== 'function') {
|
|
1209
|
+
throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener);
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
|
|
1214
|
+
enumerable: true,
|
|
1215
|
+
get: function() {
|
|
1216
|
+
return defaultMaxListeners;
|
|
1217
|
+
},
|
|
1218
|
+
set: function(arg) {
|
|
1219
|
+
if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {
|
|
1220
|
+
throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.');
|
|
1221
|
+
}
|
|
1222
|
+
defaultMaxListeners = arg;
|
|
1223
|
+
}
|
|
1224
|
+
});
|
|
1225
|
+
|
|
1226
|
+
EventEmitter.init = function() {
|
|
1227
|
+
|
|
1228
|
+
if (this._events === undefined ||
|
|
1229
|
+
this._events === Object.getPrototypeOf(this)._events) {
|
|
1230
|
+
this._events = Object.create(null);
|
|
1231
|
+
this._eventsCount = 0;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
this._maxListeners = this._maxListeners || undefined;
|
|
1235
|
+
};
|
|
1236
|
+
|
|
1237
|
+
// Obviously not all Emitters should be limited to 10. This function allows
|
|
1238
|
+
// that to be increased. Set to zero for unlimited.
|
|
1239
|
+
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
|
|
1240
|
+
if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {
|
|
1241
|
+
throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.');
|
|
1242
|
+
}
|
|
1243
|
+
this._maxListeners = n;
|
|
1244
|
+
return this;
|
|
1245
|
+
};
|
|
1246
|
+
|
|
1247
|
+
function _getMaxListeners(that) {
|
|
1248
|
+
if (that._maxListeners === undefined)
|
|
1249
|
+
return EventEmitter.defaultMaxListeners;
|
|
1250
|
+
return that._maxListeners;
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
|
|
1254
|
+
return _getMaxListeners(this);
|
|
1255
|
+
};
|
|
1256
|
+
|
|
1257
|
+
EventEmitter.prototype.emit = function emit(type) {
|
|
1258
|
+
var args = [];
|
|
1259
|
+
for (var i = 1; i < arguments.length; i++) args.push(arguments[i]);
|
|
1260
|
+
var doError = (type === 'error');
|
|
1261
|
+
|
|
1262
|
+
var events = this._events;
|
|
1263
|
+
if (events !== undefined)
|
|
1264
|
+
doError = (doError && events.error === undefined);
|
|
1265
|
+
else if (!doError)
|
|
1266
|
+
return false;
|
|
1267
|
+
|
|
1268
|
+
// If there is no 'error' event listener then throw.
|
|
1269
|
+
if (doError) {
|
|
1270
|
+
var er;
|
|
1271
|
+
if (args.length > 0)
|
|
1272
|
+
er = args[0];
|
|
1273
|
+
if (er instanceof Error) {
|
|
1274
|
+
// Note: The comments on the `throw` lines are intentional, they show
|
|
1275
|
+
// up in Node's output if this results in an unhandled exception.
|
|
1276
|
+
throw er; // Unhandled 'error' event
|
|
1277
|
+
}
|
|
1278
|
+
// At least give some kind of context to the user
|
|
1279
|
+
var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));
|
|
1280
|
+
err.context = er;
|
|
1281
|
+
throw err; // Unhandled 'error' event
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
var handler = events[type];
|
|
1285
|
+
|
|
1286
|
+
if (handler === undefined)
|
|
1287
|
+
return false;
|
|
1288
|
+
|
|
1289
|
+
if (typeof handler === 'function') {
|
|
1290
|
+
ReflectApply(handler, this, args);
|
|
1291
|
+
} else {
|
|
1292
|
+
var len = handler.length;
|
|
1293
|
+
var listeners = arrayClone(handler, len);
|
|
1294
|
+
for (var i = 0; i < len; ++i)
|
|
1295
|
+
ReflectApply(listeners[i], this, args);
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
return true;
|
|
1299
|
+
};
|
|
1300
|
+
|
|
1301
|
+
function _addListener(target, type, listener, prepend) {
|
|
1302
|
+
var m;
|
|
1303
|
+
var events;
|
|
1304
|
+
var existing;
|
|
1305
|
+
|
|
1306
|
+
checkListener(listener);
|
|
1307
|
+
|
|
1308
|
+
events = target._events;
|
|
1309
|
+
if (events === undefined) {
|
|
1310
|
+
events = target._events = Object.create(null);
|
|
1311
|
+
target._eventsCount = 0;
|
|
1312
|
+
} else {
|
|
1313
|
+
// To avoid recursion in the case that type === "newListener"! Before
|
|
1314
|
+
// adding it to the listeners, first emit "newListener".
|
|
1315
|
+
if (events.newListener !== undefined) {
|
|
1316
|
+
target.emit('newListener', type,
|
|
1317
|
+
listener.listener ? listener.listener : listener);
|
|
1318
|
+
|
|
1319
|
+
// Re-assign `events` because a newListener handler could have caused the
|
|
1320
|
+
// this._events to be assigned to a new object
|
|
1321
|
+
events = target._events;
|
|
1322
|
+
}
|
|
1323
|
+
existing = events[type];
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
if (existing === undefined) {
|
|
1327
|
+
// Optimize the case of one listener. Don't need the extra array object.
|
|
1328
|
+
existing = events[type] = listener;
|
|
1329
|
+
++target._eventsCount;
|
|
1330
|
+
} else {
|
|
1331
|
+
if (typeof existing === 'function') {
|
|
1332
|
+
// Adding the second element, need to change to array.
|
|
1333
|
+
existing = events[type] =
|
|
1334
|
+
prepend ? [listener, existing] : [existing, listener];
|
|
1335
|
+
// If we've already got an array, just append.
|
|
1336
|
+
} else if (prepend) {
|
|
1337
|
+
existing.unshift(listener);
|
|
1338
|
+
} else {
|
|
1339
|
+
existing.push(listener);
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
// Check for listener leak
|
|
1343
|
+
m = _getMaxListeners(target);
|
|
1344
|
+
if (m > 0 && existing.length > m && !existing.warned) {
|
|
1345
|
+
existing.warned = true;
|
|
1346
|
+
// No error code for this since it is a Warning
|
|
1347
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
1348
|
+
var w = new Error('Possible EventEmitter memory leak detected. ' +
|
|
1349
|
+
existing.length + ' ' + String(type) + ' listeners ' +
|
|
1350
|
+
'added. Use emitter.setMaxListeners() to ' +
|
|
1351
|
+
'increase limit');
|
|
1352
|
+
w.name = 'MaxListenersExceededWarning';
|
|
1353
|
+
w.emitter = target;
|
|
1354
|
+
w.type = type;
|
|
1355
|
+
w.count = existing.length;
|
|
1356
|
+
ProcessEmitWarning(w);
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
return target;
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
EventEmitter.prototype.addListener = function addListener(type, listener) {
|
|
1364
|
+
return _addListener(this, type, listener, false);
|
|
1365
|
+
};
|
|
1366
|
+
|
|
1367
|
+
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
|
|
1368
|
+
|
|
1369
|
+
EventEmitter.prototype.prependListener =
|
|
1370
|
+
function prependListener(type, listener) {
|
|
1371
|
+
return _addListener(this, type, listener, true);
|
|
1372
|
+
};
|
|
1373
|
+
|
|
1374
|
+
function onceWrapper() {
|
|
1375
|
+
if (!this.fired) {
|
|
1376
|
+
this.target.removeListener(this.type, this.wrapFn);
|
|
1377
|
+
this.fired = true;
|
|
1378
|
+
if (arguments.length === 0)
|
|
1379
|
+
return this.listener.call(this.target);
|
|
1380
|
+
return this.listener.apply(this.target, arguments);
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
function _onceWrap(target, type, listener) {
|
|
1385
|
+
var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
|
|
1386
|
+
var wrapped = onceWrapper.bind(state);
|
|
1387
|
+
wrapped.listener = listener;
|
|
1388
|
+
state.wrapFn = wrapped;
|
|
1389
|
+
return wrapped;
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
EventEmitter.prototype.once = function once(type, listener) {
|
|
1393
|
+
checkListener(listener);
|
|
1394
|
+
this.on(type, _onceWrap(this, type, listener));
|
|
1395
|
+
return this;
|
|
1396
|
+
};
|
|
1397
|
+
|
|
1398
|
+
EventEmitter.prototype.prependOnceListener =
|
|
1399
|
+
function prependOnceListener(type, listener) {
|
|
1400
|
+
checkListener(listener);
|
|
1401
|
+
this.prependListener(type, _onceWrap(this, type, listener));
|
|
1402
|
+
return this;
|
|
1403
|
+
};
|
|
1404
|
+
|
|
1405
|
+
// Emits a 'removeListener' event if and only if the listener was removed.
|
|
1406
|
+
EventEmitter.prototype.removeListener =
|
|
1407
|
+
function removeListener(type, listener) {
|
|
1408
|
+
var list, events, position, i, originalListener;
|
|
1409
|
+
|
|
1410
|
+
checkListener(listener);
|
|
1411
|
+
|
|
1412
|
+
events = this._events;
|
|
1413
|
+
if (events === undefined)
|
|
1414
|
+
return this;
|
|
1415
|
+
|
|
1416
|
+
list = events[type];
|
|
1417
|
+
if (list === undefined)
|
|
1418
|
+
return this;
|
|
1419
|
+
|
|
1420
|
+
if (list === listener || list.listener === listener) {
|
|
1421
|
+
if (--this._eventsCount === 0)
|
|
1422
|
+
this._events = Object.create(null);
|
|
1423
|
+
else {
|
|
1424
|
+
delete events[type];
|
|
1425
|
+
if (events.removeListener)
|
|
1426
|
+
this.emit('removeListener', type, list.listener || listener);
|
|
1427
|
+
}
|
|
1428
|
+
} else if (typeof list !== 'function') {
|
|
1429
|
+
position = -1;
|
|
1430
|
+
|
|
1431
|
+
for (i = list.length - 1; i >= 0; i--) {
|
|
1432
|
+
if (list[i] === listener || list[i].listener === listener) {
|
|
1433
|
+
originalListener = list[i].listener;
|
|
1434
|
+
position = i;
|
|
1435
|
+
break;
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
if (position < 0)
|
|
1440
|
+
return this;
|
|
1441
|
+
|
|
1442
|
+
if (position === 0)
|
|
1443
|
+
list.shift();
|
|
1444
|
+
else {
|
|
1445
|
+
spliceOne(list, position);
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
if (list.length === 1)
|
|
1449
|
+
events[type] = list[0];
|
|
1450
|
+
|
|
1451
|
+
if (events.removeListener !== undefined)
|
|
1452
|
+
this.emit('removeListener', type, originalListener || listener);
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
return this;
|
|
1456
|
+
};
|
|
1457
|
+
|
|
1458
|
+
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
|
|
1459
|
+
|
|
1460
|
+
EventEmitter.prototype.removeAllListeners =
|
|
1461
|
+
function removeAllListeners(type) {
|
|
1462
|
+
var listeners, events, i;
|
|
1463
|
+
|
|
1464
|
+
events = this._events;
|
|
1465
|
+
if (events === undefined)
|
|
1466
|
+
return this;
|
|
1467
|
+
|
|
1468
|
+
// not listening for removeListener, no need to emit
|
|
1469
|
+
if (events.removeListener === undefined) {
|
|
1470
|
+
if (arguments.length === 0) {
|
|
1471
|
+
this._events = Object.create(null);
|
|
1472
|
+
this._eventsCount = 0;
|
|
1473
|
+
} else if (events[type] !== undefined) {
|
|
1474
|
+
if (--this._eventsCount === 0)
|
|
1475
|
+
this._events = Object.create(null);
|
|
1476
|
+
else
|
|
1477
|
+
delete events[type];
|
|
1478
|
+
}
|
|
1479
|
+
return this;
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
// emit removeListener for all listeners on all events
|
|
1483
|
+
if (arguments.length === 0) {
|
|
1484
|
+
var keys = Object.keys(events);
|
|
1485
|
+
var key;
|
|
1486
|
+
for (i = 0; i < keys.length; ++i) {
|
|
1487
|
+
key = keys[i];
|
|
1488
|
+
if (key === 'removeListener') continue;
|
|
1489
|
+
this.removeAllListeners(key);
|
|
1490
|
+
}
|
|
1491
|
+
this.removeAllListeners('removeListener');
|
|
1492
|
+
this._events = Object.create(null);
|
|
1493
|
+
this._eventsCount = 0;
|
|
1494
|
+
return this;
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
listeners = events[type];
|
|
1498
|
+
|
|
1499
|
+
if (typeof listeners === 'function') {
|
|
1500
|
+
this.removeListener(type, listeners);
|
|
1501
|
+
} else if (listeners !== undefined) {
|
|
1502
|
+
// LIFO order
|
|
1503
|
+
for (i = listeners.length - 1; i >= 0; i--) {
|
|
1504
|
+
this.removeListener(type, listeners[i]);
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
return this;
|
|
1509
|
+
};
|
|
1510
|
+
|
|
1511
|
+
function _listeners(target, type, unwrap) {
|
|
1512
|
+
var events = target._events;
|
|
1513
|
+
|
|
1514
|
+
if (events === undefined)
|
|
1515
|
+
return [];
|
|
1516
|
+
|
|
1517
|
+
var evlistener = events[type];
|
|
1518
|
+
if (evlistener === undefined)
|
|
1519
|
+
return [];
|
|
1520
|
+
|
|
1521
|
+
if (typeof evlistener === 'function')
|
|
1522
|
+
return unwrap ? [evlistener.listener || evlistener] : [evlistener];
|
|
1523
|
+
|
|
1524
|
+
return unwrap ?
|
|
1525
|
+
unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
EventEmitter.prototype.listeners = function listeners(type) {
|
|
1529
|
+
return _listeners(this, type, true);
|
|
1530
|
+
};
|
|
1531
|
+
|
|
1532
|
+
EventEmitter.prototype.rawListeners = function rawListeners(type) {
|
|
1533
|
+
return _listeners(this, type, false);
|
|
1534
|
+
};
|
|
1535
|
+
|
|
1536
|
+
EventEmitter.listenerCount = function(emitter, type) {
|
|
1537
|
+
if (typeof emitter.listenerCount === 'function') {
|
|
1538
|
+
return emitter.listenerCount(type);
|
|
1539
|
+
} else {
|
|
1540
|
+
return listenerCount.call(emitter, type);
|
|
1541
|
+
}
|
|
1542
|
+
};
|
|
1543
|
+
|
|
1544
|
+
EventEmitter.prototype.listenerCount = listenerCount;
|
|
1545
|
+
function listenerCount(type) {
|
|
1546
|
+
var events = this._events;
|
|
1547
|
+
|
|
1548
|
+
if (events !== undefined) {
|
|
1549
|
+
var evlistener = events[type];
|
|
1550
|
+
|
|
1551
|
+
if (typeof evlistener === 'function') {
|
|
1552
|
+
return 1;
|
|
1553
|
+
} else if (evlistener !== undefined) {
|
|
1554
|
+
return evlistener.length;
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
return 0;
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
EventEmitter.prototype.eventNames = function eventNames() {
|
|
1562
|
+
return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
|
|
1563
|
+
};
|
|
1564
|
+
|
|
1565
|
+
function arrayClone(arr, n) {
|
|
1566
|
+
var copy = new Array(n);
|
|
1567
|
+
for (var i = 0; i < n; ++i)
|
|
1568
|
+
copy[i] = arr[i];
|
|
1569
|
+
return copy;
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
function spliceOne(list, index) {
|
|
1573
|
+
for (; index + 1 < list.length; index++)
|
|
1574
|
+
list[index] = list[index + 1];
|
|
1575
|
+
list.pop();
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
function unwrapListeners(arr) {
|
|
1579
|
+
var ret = new Array(arr.length);
|
|
1580
|
+
for (var i = 0; i < ret.length; ++i) {
|
|
1581
|
+
ret[i] = arr[i].listener || arr[i];
|
|
1582
|
+
}
|
|
1583
|
+
return ret;
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
function once(emitter, name) {
|
|
1587
|
+
return new Promise(function (resolve, reject) {
|
|
1588
|
+
function errorListener(err) {
|
|
1589
|
+
emitter.removeListener(name, resolver);
|
|
1590
|
+
reject(err);
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
function resolver() {
|
|
1594
|
+
if (typeof emitter.removeListener === 'function') {
|
|
1595
|
+
emitter.removeListener('error', errorListener);
|
|
1596
|
+
}
|
|
1597
|
+
resolve([].slice.call(arguments));
|
|
1598
|
+
}
|
|
1599
|
+
eventTargetAgnosticAddListener(emitter, name, resolver, { once: true });
|
|
1600
|
+
if (name !== 'error') {
|
|
1601
|
+
addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true });
|
|
1602
|
+
}
|
|
1603
|
+
});
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
function addErrorHandlerIfEventEmitter(emitter, handler, flags) {
|
|
1607
|
+
if (typeof emitter.on === 'function') {
|
|
1608
|
+
eventTargetAgnosticAddListener(emitter, 'error', handler, flags);
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
|
|
1613
|
+
if (typeof emitter.on === 'function') {
|
|
1614
|
+
if (flags.once) {
|
|
1615
|
+
emitter.once(name, listener);
|
|
1616
|
+
} else {
|
|
1617
|
+
emitter.on(name, listener);
|
|
1618
|
+
}
|
|
1619
|
+
} else if (typeof emitter.addEventListener === 'function') {
|
|
1620
|
+
// EventTarget does not have `error` event semantics like Node
|
|
1621
|
+
// EventEmitters, we do not listen for `error` events here.
|
|
1622
|
+
emitter.addEventListener(name, function wrapListener(arg) {
|
|
1623
|
+
// IE does not have builtin `{ once: true }` support so we
|
|
1624
|
+
// have to do it manually.
|
|
1625
|
+
if (flags.once) {
|
|
1626
|
+
emitter.removeEventListener(name, wrapListener);
|
|
1627
|
+
}
|
|
1628
|
+
listener(arg);
|
|
1629
|
+
});
|
|
1630
|
+
} else {
|
|
1631
|
+
throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter);
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
return events.exports;
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
var eventsExports = requireEvents();
|
|
1638
|
+
|
|
1639
|
+
const exceptions = {
|
|
1640
|
+
'fr': {
|
|
1641
|
+
'name': 'France',
|
|
1642
|
+
'bbox': [[-4.59235, 41.380007], [9.560016, 51.148506]]
|
|
1643
|
+
},
|
|
1644
|
+
'us': {
|
|
1645
|
+
'name': 'United States',
|
|
1646
|
+
'bbox': [[-171.791111, 18.91619], [-66.96466, 71.357764]]
|
|
1647
|
+
},
|
|
1648
|
+
'ru': {
|
|
1649
|
+
'name': 'Russia',
|
|
1650
|
+
'bbox': [[19.66064, 41.151416], [190.10042, 81.2504]]
|
|
1651
|
+
},
|
|
1652
|
+
'ca': {
|
|
1653
|
+
'name': 'Canada',
|
|
1654
|
+
'bbox': [[-140.99778, 41.675105], [-52.648099, 83.23324]]
|
|
1655
|
+
}
|
|
1656
|
+
};
|
|
1657
|
+
|
|
1658
|
+
/**
|
|
1659
|
+
* Localized values for the placeholder string
|
|
1660
|
+
*
|
|
1661
|
+
* @private
|
|
1662
|
+
*/
|
|
1663
|
+
const placeholder = {
|
|
1664
|
+
// list drawn from https://docs.mapbox.com/api/search/#language-coverage
|
|
1665
|
+
'de': 'Suche', // german
|
|
1666
|
+
'it': 'Ricerca', //italian
|
|
1667
|
+
'en': 'Search', // english
|
|
1668
|
+
'nl': 'Zoeken', //dutch
|
|
1669
|
+
'fr': 'Chercher', //french
|
|
1670
|
+
'ca': 'Cerca', //catalan
|
|
1671
|
+
'he': 'לחפש', //hebrew
|
|
1672
|
+
'ja': 'サーチ', //japanese
|
|
1673
|
+
'lv': 'Meklēt', //latvian
|
|
1674
|
+
'pt': 'Procurar', //portuguese
|
|
1675
|
+
'sr': 'Претрага', //serbian
|
|
1676
|
+
'zh': '搜索', //chinese-simplified
|
|
1677
|
+
'cs': 'Vyhledávání', //czech
|
|
1678
|
+
'hu': 'Keresés', //hungarian
|
|
1679
|
+
'ka': 'ძიება', // georgian
|
|
1680
|
+
'nb': 'Søke', //norwegian
|
|
1681
|
+
'sk': 'Vyhľadávanie', //slovak
|
|
1682
|
+
'th': 'ค้นหา', //thai
|
|
1683
|
+
'fi': 'Hae', //finnish
|
|
1684
|
+
'is': 'Leita', //icelandic
|
|
1685
|
+
'ko': '수색', //korean
|
|
1686
|
+
'pl': 'Szukaj', //polish
|
|
1687
|
+
'sl': 'Iskanje', //slovenian
|
|
1688
|
+
'fa': 'جستجو', //persian(aka farsi)
|
|
1689
|
+
'ru': 'Поиск', //russian,
|
|
1690
|
+
'es': 'Buscar' //spanish
|
|
1691
|
+
};
|
|
1692
|
+
const errorNoResults = {
|
|
1693
|
+
'en': 'No results found',
|
|
1694
|
+
'de': 'Keine Ergebnisse gefunden',
|
|
1695
|
+
'es': 'No hay resultados',
|
|
1696
|
+
'fr': 'Aucun résultat trouvé'
|
|
1697
|
+
};
|
|
1698
|
+
const errorConnectionFailed = {
|
|
1699
|
+
'en': 'There was an error reaching the server',
|
|
1700
|
+
'de': 'Verbindung fehlgeschlagen',
|
|
1701
|
+
'es': 'Error al conectarse al servidor',
|
|
1702
|
+
'fr': 'Une erreur est survenue lors de la connexion au serveur'
|
|
1703
|
+
};
|
|
1704
|
+
var localization = { placeholder, errorNoResults, errorConnectionFailed };
|
|
1705
|
+
|
|
1706
|
+
/**
|
|
1707
|
+
* A regular expression to match coordinates.
|
|
1708
|
+
*/
|
|
1709
|
+
const COORDINATES_REGEXP = /(-?\d+\.?\d*)[, ]+(-?\d+\.?\d*)[ ]*$/;
|
|
1710
|
+
/**
|
|
1711
|
+
* A geocoder component that works with maplibre
|
|
1712
|
+
*/
|
|
1713
|
+
class MaplibreGeocoder {
|
|
1714
|
+
constructor(geocoderApi, options) {
|
|
1715
|
+
this.options = {
|
|
1716
|
+
zoom: 16,
|
|
1717
|
+
flyTo: true,
|
|
1718
|
+
trackProximity: true,
|
|
1719
|
+
showResultsWhileTyping: false,
|
|
1720
|
+
minLength: 2,
|
|
1721
|
+
reverseGeocode: false,
|
|
1722
|
+
limit: 5,
|
|
1723
|
+
enableEventLogging: true,
|
|
1724
|
+
marker: true,
|
|
1725
|
+
popup: false,
|
|
1726
|
+
maplibregl: undefined,
|
|
1727
|
+
collapsed: false,
|
|
1728
|
+
clearAndBlurOnEsc: false,
|
|
1729
|
+
clearOnBlur: false,
|
|
1730
|
+
proximityMinZoom: 9,
|
|
1731
|
+
getItemValue: (item) => {
|
|
1732
|
+
return item.text !== undefined ? item.text : item.place_name;
|
|
1733
|
+
},
|
|
1734
|
+
render: function (item) {
|
|
1735
|
+
// Render as a suggestion
|
|
1736
|
+
if (!item.geometry) {
|
|
1737
|
+
const suggestionString = item.text;
|
|
1738
|
+
const indexOfMatch = suggestionString
|
|
1739
|
+
.toLowerCase()
|
|
1740
|
+
.indexOf(this.query.toLowerCase());
|
|
1741
|
+
const lengthOfMatch = this.query.length;
|
|
1742
|
+
const beforeMatch = suggestionString.substring(0, indexOfMatch);
|
|
1743
|
+
const match = suggestionString.substring(indexOfMatch, indexOfMatch + lengthOfMatch);
|
|
1744
|
+
const afterMatch = suggestionString.substring(indexOfMatch + lengthOfMatch);
|
|
1745
|
+
return ('<div class="maplibregl-ctrl-geocoder--suggestion">' +
|
|
1746
|
+
'<svg class="maplibregl-ctrl-geocoder--suggestion-icon" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><path d="M22.8702 20.1258H21.4248L20.9125 19.6318C22.7055 17.546 23.785 14.8382 23.785 11.8925C23.785 5.32419 18.4608 0 11.8925 0C5.32419 0 0 5.32419 0 11.8925C0 18.4608 5.32419 23.785 11.8925 23.785C14.8382 23.785 17.546 22.7055 19.6318 20.9125L20.1258 21.4248V22.8702L29.2739 32L32 29.2739L22.8702 20.1258ZM11.8925 20.1258C7.33676 20.1258 3.65923 16.4483 3.65923 11.8925C3.65923 7.33676 7.33676 3.65923 11.8925 3.65923C16.4483 3.65923 20.1258 7.33676 20.1258 11.8925C20.1258 16.4483 16.4483 20.1258 11.8925 20.1258Z" fill="#687078"/></svg>' +
|
|
1747
|
+
'<div class="maplibregl-ctrl-geocoder--suggestion-info">' +
|
|
1748
|
+
'<div class="maplibregl-ctrl-geocoder--suggestion-title">' +
|
|
1749
|
+
beforeMatch +
|
|
1750
|
+
'<span class="maplibregl-ctrl-geocoder--suggestion-match">' +
|
|
1751
|
+
match +
|
|
1752
|
+
"</span>" +
|
|
1753
|
+
afterMatch +
|
|
1754
|
+
"</div>" +
|
|
1755
|
+
"</div>" +
|
|
1756
|
+
"</div>");
|
|
1757
|
+
}
|
|
1758
|
+
// render as a search result
|
|
1759
|
+
const placeName = item.place_name.split(",");
|
|
1760
|
+
return ('<div class="maplibregl-ctrl-geocoder--result">' +
|
|
1761
|
+
'<svg class="maplibregl-ctrl-geocoder--result-icon" viewBox="0 0 24 32" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 0C5.36571 0 0 5.38676 0 12.0471C0 21.0824 12 32 12 32C12 32 24 21.0824 24 12.0471C24 5.38676 18.6343 0 12 0ZM12 16.3496C9.63428 16.3496 7.71429 14.4221 7.71429 12.0471C7.71429 9.67207 9.63428 7.74454 12 7.74454C14.3657 7.74454 16.2857 9.67207 16.2857 12.0471C16.2857 14.4221 14.3657 16.3496 12 16.3496Z" fill="#687078"/></svg>' +
|
|
1762
|
+
"<div>" +
|
|
1763
|
+
'<div class="maplibregl-ctrl-geocoder--result-title">' +
|
|
1764
|
+
placeName[0] +
|
|
1765
|
+
"</div>" +
|
|
1766
|
+
'<div class="maplibregl-ctrl-geocoder--result-address">' +
|
|
1767
|
+
placeName.splice(1, placeName.length).join(",") +
|
|
1768
|
+
"</div>" +
|
|
1769
|
+
"</div>" +
|
|
1770
|
+
"</div>");
|
|
1771
|
+
},
|
|
1772
|
+
popupRender: (item) => {
|
|
1773
|
+
const placeName = item.place_name.split(",");
|
|
1774
|
+
return ('<div class="maplibregl-ctrl-geocoder--suggestion popup-suggestion"><div class="maplibregl-ctrl-geocoder--suggestion-title popup-suggestion-title">' +
|
|
1775
|
+
placeName[0] +
|
|
1776
|
+
'</div><div class="maplibregl-ctrl-geocoder--suggestion-address popup-suggestion-address">' +
|
|
1777
|
+
placeName.splice(1, placeName.length).join(",") +
|
|
1778
|
+
"</div></div>");
|
|
1779
|
+
},
|
|
1780
|
+
showResultMarkers: true,
|
|
1781
|
+
debounceSearch: 200,
|
|
1782
|
+
};
|
|
1783
|
+
this._eventEmitter = new eventsExports.EventEmitter();
|
|
1784
|
+
this.options = extend({}, this.options, options);
|
|
1785
|
+
this.fresh = true;
|
|
1786
|
+
this.lastSelected = null;
|
|
1787
|
+
this.geocoderApi = geocoderApi;
|
|
1788
|
+
}
|
|
1789
|
+
/**
|
|
1790
|
+
* Add the geocoder to a container. The container can be either a `Map`, an `HTMLElement` or a CSS selector string.
|
|
1791
|
+
*
|
|
1792
|
+
* If the container is a [`Map`](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map), this function will behave identically to [`Map.addControl(geocoder)`](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map#addcontrol).
|
|
1793
|
+
* If the container is an instance of [`HTMLElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement), then the geocoder will be appended as a child of that [`HTMLElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement).
|
|
1794
|
+
* If the container is a [CSS selector string](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors), the geocoder will be appended to the element returned from the query.
|
|
1795
|
+
*
|
|
1796
|
+
* This function will throw an error if the container is none of the above.
|
|
1797
|
+
* It will also throw an error if the referenced HTML element cannot be found in the `document.body`.
|
|
1798
|
+
*
|
|
1799
|
+
* For example, if the HTML body contains the element `<div id='geocoder-container'></div>`, the following script will append the geocoder to `#geocoder-container`:
|
|
1800
|
+
* @example
|
|
1801
|
+
* ```js
|
|
1802
|
+
* const GeoApi = {
|
|
1803
|
+
* forwardGeocode: (config) => { return { features: [] } },
|
|
1804
|
+
* reverseGeocode: (config) => { return { features: [] } }
|
|
1805
|
+
* }
|
|
1806
|
+
* const geocoder = new MaplibreGeocoder(GeoAPI, {});
|
|
1807
|
+
* geocoder.addTo('#geocoder-container');
|
|
1808
|
+
* ```
|
|
1809
|
+
* @param container - A reference to the container to which to add the geocoder
|
|
1810
|
+
*/
|
|
1811
|
+
addTo(container) {
|
|
1812
|
+
function addToExistingContainer(geocoder, container) {
|
|
1813
|
+
if (!document.body.contains(container)) {
|
|
1814
|
+
throw new Error("Element provided to #addTo() exists, but is not in the DOM");
|
|
1815
|
+
}
|
|
1816
|
+
const el = geocoder.onAdd(); //returns the input elements, which are then added to the requested html container
|
|
1817
|
+
container.appendChild(el);
|
|
1818
|
+
}
|
|
1819
|
+
// if the container is an HTMLElement, then set the parent to be that element
|
|
1820
|
+
if (container instanceof HTMLElement) {
|
|
1821
|
+
addToExistingContainer(this, container);
|
|
1822
|
+
}
|
|
1823
|
+
// if the container is a string, treat it as a CSS query
|
|
1824
|
+
else if (typeof container == "string") {
|
|
1825
|
+
const parent = document.querySelectorAll(container);
|
|
1826
|
+
if (parent.length === 0) {
|
|
1827
|
+
throw new Error("Element " + container + "not found.");
|
|
1828
|
+
}
|
|
1829
|
+
if (parent.length > 1) {
|
|
1830
|
+
throw new Error("Geocoder can only be added to a single html element");
|
|
1831
|
+
}
|
|
1832
|
+
addToExistingContainer(this, parent[0]);
|
|
1833
|
+
}
|
|
1834
|
+
// if the container is a map, add the control like normal
|
|
1835
|
+
else if ('addControl' in container) {
|
|
1836
|
+
// it's a maplibre-gl map, add like normal
|
|
1837
|
+
container.addControl(this);
|
|
1838
|
+
}
|
|
1839
|
+
else {
|
|
1840
|
+
throw new Error("Error: addTo must be a maplibre-gl-js map, an html element, or a CSS selector query for a single html element");
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1843
|
+
onAdd(map) {
|
|
1844
|
+
if (map && typeof map != "string") {
|
|
1845
|
+
this._map = map;
|
|
1846
|
+
}
|
|
1847
|
+
this.setLanguage();
|
|
1848
|
+
if (this.options.localGeocoderOnly && !this.options.localGeocoder) {
|
|
1849
|
+
throw new Error("A localGeocoder function must be specified to use localGeocoderOnly mode");
|
|
1850
|
+
}
|
|
1851
|
+
this._onChange = this._onChange.bind(this);
|
|
1852
|
+
this._onKeyDown = this._onKeyDown.bind(this);
|
|
1853
|
+
this._onPaste = this._onPaste.bind(this);
|
|
1854
|
+
this._onBlur = this._onBlur.bind(this);
|
|
1855
|
+
this._showButton = this._showButton.bind(this);
|
|
1856
|
+
this._hideButton = this._hideButton.bind(this);
|
|
1857
|
+
this._onQueryResult = this._onQueryResult.bind(this);
|
|
1858
|
+
this.clear = this.clear.bind(this);
|
|
1859
|
+
this._updateProximity = this._updateProximity.bind(this);
|
|
1860
|
+
this._collapse = this._collapse.bind(this);
|
|
1861
|
+
this._unCollapse = this._unCollapse.bind(this);
|
|
1862
|
+
this._clear = this._clear.bind(this);
|
|
1863
|
+
this._clearOnBlur = this._clearOnBlur.bind(this);
|
|
1864
|
+
const el = (this.container = document.createElement("div"));
|
|
1865
|
+
el.className =
|
|
1866
|
+
"maplibregl-ctrl-geocoder maplibregl-ctrl maplibregl-ctrl-geocoder maplibregl-ctrl";
|
|
1867
|
+
const searchIcon = this.createIcon("search", '<path d="M7.4 2.5c-2.7 0-4.9 2.2-4.9 4.9s2.2 4.9 4.9 4.9c1 0 1.8-.2 2.5-.8l3.7 3.7c.2.2.4.3.8.3.7 0 1.1-.4 1.1-1.1 0-.3-.1-.5-.3-.8L11.4 10c.4-.8.8-1.6.8-2.5.1-2.8-2.1-5-4.8-5zm0 1.6c1.8 0 3.2 1.4 3.2 3.2s-1.4 3.2-3.2 3.2-3.3-1.3-3.3-3.1 1.4-3.3 3.3-3.3z"/>');
|
|
1868
|
+
this._inputEl = document.createElement("input");
|
|
1869
|
+
this._inputEl.type = "search";
|
|
1870
|
+
this._inputEl.className =
|
|
1871
|
+
"maplibregl-ctrl-geocoder--input";
|
|
1872
|
+
this.setPlaceholder();
|
|
1873
|
+
if (this.options.collapsed) {
|
|
1874
|
+
this._collapse();
|
|
1875
|
+
this.container.addEventListener("mouseenter", this._unCollapse);
|
|
1876
|
+
this.container.addEventListener("mouseleave", this._collapse);
|
|
1877
|
+
this._inputEl.addEventListener("focus", this._unCollapse);
|
|
1878
|
+
}
|
|
1879
|
+
if (this.options.collapsed || this.options.clearOnBlur) {
|
|
1880
|
+
this._inputEl.addEventListener("blur", this._onBlur);
|
|
1881
|
+
}
|
|
1882
|
+
this._inputEl.addEventListener("keydown", debounce(this._onKeyDown, this.options.debounceSearch));
|
|
1883
|
+
this._inputEl.addEventListener("paste", this._onPaste);
|
|
1884
|
+
this._inputEl.addEventListener("change", this._onChange);
|
|
1885
|
+
this.container.addEventListener("mouseenter", this._showButton);
|
|
1886
|
+
this.container.addEventListener("mouseleave", this._hideButton);
|
|
1887
|
+
const actions = document.createElement("div");
|
|
1888
|
+
actions.classList.add("maplibregl-ctrl-geocoder--pin-right");
|
|
1889
|
+
this._clearEl = document.createElement("button");
|
|
1890
|
+
this._clearEl.setAttribute("type", "button");
|
|
1891
|
+
this._clearEl.setAttribute("aria-label", "Clear");
|
|
1892
|
+
this._clearEl.addEventListener("click", this.clear);
|
|
1893
|
+
this._clearEl.className = "maplibregl-ctrl-geocoder--button";
|
|
1894
|
+
const buttonIcon = this.createIcon("close", '<path d="M3.8 2.5c-.6 0-1.3.7-1.3 1.3 0 .3.2.7.5.8L7.2 9 3 13.2c-.3.3-.5.7-.5 1 0 .6.7 1.3 1.3 1.3.3 0 .7-.2 1-.5L9 10.8l4.2 4.2c.2.3.7.3 1 .3.6 0 1.3-.7 1.3-1.3 0-.3-.2-.7-.3-1l-4.4-4L15 4.6c.3-.2.5-.5.5-.8 0-.7-.7-1.3-1.3-1.3-.3 0-.7.2-1 .3L9 7.1 4.8 2.8c-.3-.1-.7-.3-1-.3z"/>');
|
|
1895
|
+
this._clearEl.appendChild(buttonIcon);
|
|
1896
|
+
this._loadingEl = this.createIcon("loading", '<path fill="#333" d="M4.4 4.4l.8.8c2.1-2.1 5.5-2.1 7.6 0l.8-.8c-2.5-2.5-6.7-2.5-9.2 0z"/><path opacity=".1" d="M12.8 12.9c-2.1 2.1-5.5 2.1-7.6 0-2.1-2.1-2.1-5.5 0-7.7l-.8-.8c-2.5 2.5-2.5 6.7 0 9.2s6.6 2.5 9.2 0 2.5-6.6 0-9.2l-.8.8c2.2 2.1 2.2 5.6 0 7.7z"/>');
|
|
1897
|
+
actions.appendChild(this._clearEl);
|
|
1898
|
+
actions.appendChild(this._loadingEl);
|
|
1899
|
+
el.appendChild(searchIcon);
|
|
1900
|
+
el.appendChild(this._inputEl);
|
|
1901
|
+
el.appendChild(actions);
|
|
1902
|
+
this._typeahead = new Typeahead(this._inputEl, [], {
|
|
1903
|
+
filter: false,
|
|
1904
|
+
minLength: this.options.minLength,
|
|
1905
|
+
limit: this.options.limit,
|
|
1906
|
+
noInitialSelection: true,
|
|
1907
|
+
});
|
|
1908
|
+
this.container.addEventListener("click", () => {
|
|
1909
|
+
this._typeahead.update(this._typeahead.data);
|
|
1910
|
+
});
|
|
1911
|
+
this.setRenderFunction(this.options.render);
|
|
1912
|
+
this._typeahead.getItemValue = this.options.getItemValue;
|
|
1913
|
+
this.mapMarker = null;
|
|
1914
|
+
this.resultMarkers = [];
|
|
1915
|
+
this._handleMarker = this._handleMarker.bind(this);
|
|
1916
|
+
this._handleResultMarkers = this._handleResultMarkers.bind(this);
|
|
1917
|
+
if (this._map) {
|
|
1918
|
+
if (this.options.trackProximity) {
|
|
1919
|
+
this._updateProximity();
|
|
1920
|
+
this._map.on("moveend", this._updateProximity);
|
|
1921
|
+
}
|
|
1922
|
+
this._maplibregl = this.options.maplibregl;
|
|
1923
|
+
if (!this._maplibregl && this.options.marker) {
|
|
1924
|
+
console.error("No maplibregl detected in options. Map markers are disabled. Please set options.maplibregl.");
|
|
1925
|
+
this.options.marker = false;
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1928
|
+
return el;
|
|
1929
|
+
}
|
|
1930
|
+
createIcon(name, path) {
|
|
1931
|
+
const icon = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
1932
|
+
icon.setAttribute("class", "maplibregl-ctrl-geocoder--icon maplibregl-ctrl-geocoder--icon-" + name);
|
|
1933
|
+
icon.setAttribute("viewBox", "0 0 18 18");
|
|
1934
|
+
icon.setAttribute("xml:space", "preserve");
|
|
1935
|
+
icon.setAttribute("width", "18");
|
|
1936
|
+
icon.setAttribute("height", "18");
|
|
1937
|
+
// IE does not have innerHTML for SVG nodes
|
|
1938
|
+
if (!("innerHTML" in icon)) {
|
|
1939
|
+
const SVGNodeContainer = document.createElement("div");
|
|
1940
|
+
SVGNodeContainer.innerHTML =
|
|
1941
|
+
"<svg>" + path.valueOf().toString() + "</svg>";
|
|
1942
|
+
const SVGNode = SVGNodeContainer.firstChild, SVGPath = SVGNode.firstChild;
|
|
1943
|
+
icon.appendChild(SVGPath);
|
|
1944
|
+
}
|
|
1945
|
+
else {
|
|
1946
|
+
icon.innerHTML = path;
|
|
1947
|
+
}
|
|
1948
|
+
return icon;
|
|
1949
|
+
}
|
|
1950
|
+
onRemove() {
|
|
1951
|
+
this.container.remove();
|
|
1952
|
+
if (this.options.trackProximity && this._map) {
|
|
1953
|
+
this._map.off("moveend", this._updateProximity);
|
|
1954
|
+
}
|
|
1955
|
+
this._removeMarker();
|
|
1956
|
+
this._map = null;
|
|
1957
|
+
return this;
|
|
1958
|
+
}
|
|
1959
|
+
_onPaste(e) {
|
|
1960
|
+
const value = (e.clipboardData || window.clipboardData).getData("text");
|
|
1961
|
+
if (value.length >= this.options.minLength &&
|
|
1962
|
+
this.options.showResultsWhileTyping) {
|
|
1963
|
+
this._geocode(value);
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
_onKeyDown(e) {
|
|
1967
|
+
const ESC_KEY_CODE = 27;
|
|
1968
|
+
const TAB_KEY_CODE = 9;
|
|
1969
|
+
const ENTER_KEY_CODE = 13;
|
|
1970
|
+
if (e.keyCode === ESC_KEY_CODE && this.options.clearAndBlurOnEsc) {
|
|
1971
|
+
this._clear(e);
|
|
1972
|
+
return this._inputEl.blur();
|
|
1973
|
+
}
|
|
1974
|
+
const value = this._inputEl.value;
|
|
1975
|
+
if (!value) {
|
|
1976
|
+
this.fresh = true;
|
|
1977
|
+
// the user has removed all the text
|
|
1978
|
+
if (e.keyCode !== TAB_KEY_CODE)
|
|
1979
|
+
this.clear(e);
|
|
1980
|
+
return (this._clearEl.style.display = "none");
|
|
1981
|
+
}
|
|
1982
|
+
// TAB, ESC, LEFT, RIGHT, UP, DOWN
|
|
1983
|
+
if (e.metaKey ||
|
|
1984
|
+
[TAB_KEY_CODE, ESC_KEY_CODE, 37, 39, 38, 40].indexOf(e.keyCode) !== -1)
|
|
1985
|
+
return;
|
|
1986
|
+
// ENTER
|
|
1987
|
+
if (e.keyCode === ENTER_KEY_CODE) {
|
|
1988
|
+
if (!this.options.showResultsWhileTyping) {
|
|
1989
|
+
if (!this._typeahead.selected) {
|
|
1990
|
+
this._geocode(value);
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
else {
|
|
1994
|
+
// Pressing enter on the search box will do a search for the currently string input
|
|
1995
|
+
if (this._typeahead.selected == null &&
|
|
1996
|
+
this.geocoderApi.getSuggestions) {
|
|
1997
|
+
this._geocode(value, true);
|
|
1998
|
+
// If suggestions API is not defined pressing enter while the input box is selected will try to fit the results into the current map view
|
|
1999
|
+
}
|
|
2000
|
+
else if (this._typeahead.selected == null) {
|
|
2001
|
+
if (this.options.showResultMarkers) {
|
|
2002
|
+
this._fitBoundsForMarkers();
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
return;
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
// Show results while typing and greater than min length
|
|
2009
|
+
if (value.length >= this.options.minLength &&
|
|
2010
|
+
this.options.showResultsWhileTyping) {
|
|
2011
|
+
this._geocode(value);
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
_showButton() {
|
|
2015
|
+
if (this._inputEl.value.length > 0)
|
|
2016
|
+
this._clearEl.style.display = "block";
|
|
2017
|
+
}
|
|
2018
|
+
_hideButton() {
|
|
2019
|
+
if (this._typeahead.selected)
|
|
2020
|
+
this._clearEl.style.display = "none";
|
|
2021
|
+
}
|
|
2022
|
+
_onBlur(e) {
|
|
2023
|
+
if (this.options.clearOnBlur) {
|
|
2024
|
+
this._clearOnBlur(e);
|
|
2025
|
+
}
|
|
2026
|
+
if (this.options.collapsed) {
|
|
2027
|
+
this._collapse();
|
|
2028
|
+
}
|
|
2029
|
+
}
|
|
2030
|
+
// Change events are fire by suggestions library whenever the enter key is pressed or input is blurred
|
|
2031
|
+
// This can sometimes cause strange behavior as this function is called before our own onKeyDown handler and thus
|
|
2032
|
+
// we cannot depend on some internal values of the suggestion state like `selected` as those will change or before
|
|
2033
|
+
// our onKeyDown handler.
|
|
2034
|
+
_onChange() {
|
|
2035
|
+
const selected = this._typeahead.selected;
|
|
2036
|
+
// If a suggestion was selected
|
|
2037
|
+
if (selected && !selected.geometry) {
|
|
2038
|
+
if (selected.placeId)
|
|
2039
|
+
this._geocode(selected.placeId, true, true);
|
|
2040
|
+
else
|
|
2041
|
+
this._geocode(selected.text, true);
|
|
2042
|
+
}
|
|
2043
|
+
else if (selected && JSON.stringify(selected) !== this.lastSelected) {
|
|
2044
|
+
this._clearEl.style.display = "none";
|
|
2045
|
+
if (this.options.flyTo) {
|
|
2046
|
+
let flyOptions;
|
|
2047
|
+
this._removeResultMarkers();
|
|
2048
|
+
if (selected.properties && exceptions[selected.properties.short_code]) {
|
|
2049
|
+
// Certain geocoder search results return (and therefore zoom to fit)
|
|
2050
|
+
// an unexpectedly large bounding box: for example, both Russia and the
|
|
2051
|
+
// USA span both sides of -180/180, or France includes the island of
|
|
2052
|
+
// Reunion in the Indian Ocean. An incomplete list of these exceptions
|
|
2053
|
+
// at ./exceptions.json provides "reasonable" bounding boxes as a
|
|
2054
|
+
// short-term solution; this may be amended as necessary.
|
|
2055
|
+
flyOptions = extend({}, this.options.flyTo);
|
|
2056
|
+
if (this._map) {
|
|
2057
|
+
this._map.fitBounds(exceptions[selected.properties.short_code].bbox, flyOptions);
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
else if (selected.bbox) {
|
|
2061
|
+
const bbox = selected.bbox;
|
|
2062
|
+
flyOptions = extend({}, this.options.flyTo);
|
|
2063
|
+
if (this._map) {
|
|
2064
|
+
this._map.fitBounds([
|
|
2065
|
+
[bbox[0], bbox[1]],
|
|
2066
|
+
[bbox[2], bbox[3]],
|
|
2067
|
+
], flyOptions);
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
else {
|
|
2071
|
+
const defaultFlyOptions = {
|
|
2072
|
+
zoom: this.options.zoom,
|
|
2073
|
+
};
|
|
2074
|
+
flyOptions = extend({}, defaultFlyOptions, this.options.flyTo);
|
|
2075
|
+
// ensure that center is not overriden by custom options
|
|
2076
|
+
if (selected.center) {
|
|
2077
|
+
flyOptions.center = selected.center;
|
|
2078
|
+
}
|
|
2079
|
+
else if (selected.geometry &&
|
|
2080
|
+
selected.geometry.type &&
|
|
2081
|
+
selected.geometry.type === "Point" &&
|
|
2082
|
+
selected.geometry.coordinates) {
|
|
2083
|
+
flyOptions.center = selected.geometry.coordinates;
|
|
2084
|
+
}
|
|
2085
|
+
if (this._map) {
|
|
2086
|
+
this._map.flyTo(flyOptions);
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
if (this.options.marker && this._maplibregl) {
|
|
2091
|
+
this._handleMarker(selected);
|
|
2092
|
+
}
|
|
2093
|
+
// After selecting a feature, re-focus the textarea and set
|
|
2094
|
+
// cursor at start, and reset the selected feature.
|
|
2095
|
+
this._inputEl.focus();
|
|
2096
|
+
this._inputEl.scrollLeft = 0;
|
|
2097
|
+
this._inputEl.setSelectionRange(0, 0);
|
|
2098
|
+
this.lastSelected = JSON.stringify(selected);
|
|
2099
|
+
this._typeahead.selected = null; // reset selection current selection value and set it to last selected
|
|
2100
|
+
this._eventEmitter.emit("result", { result: selected });
|
|
2101
|
+
}
|
|
2102
|
+
}
|
|
2103
|
+
_getConfigForRequest() {
|
|
2104
|
+
// Possible config proprerties to pass to client
|
|
2105
|
+
const keys = [
|
|
2106
|
+
"bbox",
|
|
2107
|
+
"limit",
|
|
2108
|
+
"proximity",
|
|
2109
|
+
"countries",
|
|
2110
|
+
"types",
|
|
2111
|
+
"language",
|
|
2112
|
+
"reverseMode",
|
|
2113
|
+
];
|
|
2114
|
+
// Create config object
|
|
2115
|
+
const config = keys.reduce((config, key) => {
|
|
2116
|
+
if (this.options[key]) {
|
|
2117
|
+
if (["countries", "types", "language"].indexOf(key) > -1) {
|
|
2118
|
+
(config[key] = this.options[key].split(/[\s,]+/));
|
|
2119
|
+
}
|
|
2120
|
+
else {
|
|
2121
|
+
(config[key] = this.options[key]);
|
|
2122
|
+
}
|
|
2123
|
+
if (key === "proximity" &&
|
|
2124
|
+
this.options[key] &&
|
|
2125
|
+
typeof this.options[key].longitude === "number" &&
|
|
2126
|
+
typeof this.options[key].latitude === "number") {
|
|
2127
|
+
config[key] = [
|
|
2128
|
+
this.options[key].longitude,
|
|
2129
|
+
this.options[key].latitude,
|
|
2130
|
+
];
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
return config;
|
|
2134
|
+
}, {});
|
|
2135
|
+
return config;
|
|
2136
|
+
}
|
|
2137
|
+
_geocode(searchInput_1) {
|
|
2138
|
+
return __awaiter(this, arguments, void 0, function* (searchInput, isSuggestion = false, isPlaceId = false) {
|
|
2139
|
+
this._loadingEl.style.display = "block";
|
|
2140
|
+
this._eventEmitter.emit("loading", { query: searchInput });
|
|
2141
|
+
const config = this._getConfigForRequest();
|
|
2142
|
+
const request = this._createGeocodeRequest(config, searchInput, isSuggestion, isPlaceId);
|
|
2143
|
+
const localGeocoderResults = this.options.localGeocoder
|
|
2144
|
+
? (this.options.localGeocoder(searchInput) || [])
|
|
2145
|
+
: [];
|
|
2146
|
+
try {
|
|
2147
|
+
const response = yield request;
|
|
2148
|
+
yield this._handleGeocodeResponse(response, config, searchInput, isSuggestion, localGeocoderResults);
|
|
2149
|
+
}
|
|
2150
|
+
catch (err) {
|
|
2151
|
+
this._handleGeocodeErrorResponse(err, localGeocoderResults);
|
|
2152
|
+
}
|
|
2153
|
+
return request;
|
|
2154
|
+
});
|
|
2155
|
+
}
|
|
2156
|
+
_createGeocodeRequest(config, searchInput, isSuggestion, isPlaceId) {
|
|
2157
|
+
if (this.options.localGeocoderOnly) {
|
|
2158
|
+
return Promise.resolve({});
|
|
2159
|
+
}
|
|
2160
|
+
if (this.options.reverseGeocode && COORDINATES_REGEXP.test(searchInput)) {
|
|
2161
|
+
// searchInput resembles coordinates, make the request a reverseGeocode
|
|
2162
|
+
return this._createReverseGeocodeRequest(searchInput, config);
|
|
2163
|
+
}
|
|
2164
|
+
config.query = searchInput;
|
|
2165
|
+
if (!this.geocoderApi.getSuggestions) {
|
|
2166
|
+
return this.geocoderApi.forwardGeocode(config);
|
|
2167
|
+
}
|
|
2168
|
+
if (!isSuggestion) {
|
|
2169
|
+
// user typed in text and should receive suggestions
|
|
2170
|
+
return this.geocoderApi.getSuggestions(config);
|
|
2171
|
+
}
|
|
2172
|
+
// user clicked on a suggestion
|
|
2173
|
+
if (this.geocoderApi.searchByPlaceId && isPlaceId) {
|
|
2174
|
+
// suggestion has place Id
|
|
2175
|
+
return this.geocoderApi.searchByPlaceId(config);
|
|
2176
|
+
}
|
|
2177
|
+
return this.geocoderApi.forwardGeocode(config);
|
|
2178
|
+
}
|
|
2179
|
+
_createReverseGeocodeRequest(searchInput, config) {
|
|
2180
|
+
// parse coordinates
|
|
2181
|
+
const coords = searchInput
|
|
2182
|
+
.split(/[\s(,)?]+/)
|
|
2183
|
+
.map((c) => parseFloat(c))
|
|
2184
|
+
.reverse();
|
|
2185
|
+
// client only accepts one type for reverseGeocode, so
|
|
2186
|
+
// use first config type if one, if not default to poi
|
|
2187
|
+
config.query = coords;
|
|
2188
|
+
config.limit = 1;
|
|
2189
|
+
// drop proximity which may have been set by trackProximity since it's not supported by the reverseGeocoder
|
|
2190
|
+
if ("proximity" in config) {
|
|
2191
|
+
delete config.proximity;
|
|
2192
|
+
}
|
|
2193
|
+
return this.geocoderApi.reverseGeocode(config);
|
|
2194
|
+
}
|
|
2195
|
+
_handleGeocodeResponse(response, config, searchInput, isSuggestion, localGeocoderResults) {
|
|
2196
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2197
|
+
this._loadingEl.style.display = "none";
|
|
2198
|
+
let res = {};
|
|
2199
|
+
if (!response) {
|
|
2200
|
+
res = {
|
|
2201
|
+
type: "FeatureCollection",
|
|
2202
|
+
features: [],
|
|
2203
|
+
};
|
|
2204
|
+
}
|
|
2205
|
+
else {
|
|
2206
|
+
res = response;
|
|
2207
|
+
}
|
|
2208
|
+
res.config = config;
|
|
2209
|
+
if (this.fresh) {
|
|
2210
|
+
this.fresh = false;
|
|
2211
|
+
}
|
|
2212
|
+
// supplement Maplibre Geocoding API results with locally populated results
|
|
2213
|
+
res.features = res.features
|
|
2214
|
+
? localGeocoderResults.concat(res.features)
|
|
2215
|
+
: localGeocoderResults;
|
|
2216
|
+
const externalGeocoderResultsPromise = this.options.externalGeocoder
|
|
2217
|
+
? (this.options.externalGeocoder(searchInput, res.features, config) || Promise.resolve([]))
|
|
2218
|
+
: Promise.resolve([]);
|
|
2219
|
+
// supplement Geocoding API results with features returned by a promise
|
|
2220
|
+
try {
|
|
2221
|
+
const features = yield externalGeocoderResultsPromise;
|
|
2222
|
+
res.features = res.features
|
|
2223
|
+
? features.concat(res.features)
|
|
2224
|
+
: features;
|
|
2225
|
+
}
|
|
2226
|
+
catch (_a) {
|
|
2227
|
+
// on error, display the original result
|
|
2228
|
+
}
|
|
2229
|
+
// apply results filter if provided
|
|
2230
|
+
if (this.options.filter && res.features.length) {
|
|
2231
|
+
res.features = res.features.filter(this.options.filter);
|
|
2232
|
+
}
|
|
2233
|
+
let results = [];
|
|
2234
|
+
if ('suggestions' in res) {
|
|
2235
|
+
results = res.suggestions;
|
|
2236
|
+
}
|
|
2237
|
+
else if ('place' in res) {
|
|
2238
|
+
results = [res.place];
|
|
2239
|
+
}
|
|
2240
|
+
else {
|
|
2241
|
+
results = res.features;
|
|
2242
|
+
}
|
|
2243
|
+
if (results.length) {
|
|
2244
|
+
this._clearEl.style.display = "block";
|
|
2245
|
+
this._typeahead.update(results);
|
|
2246
|
+
if ((!this.options.showResultsWhileTyping || isSuggestion) &&
|
|
2247
|
+
this.options.showResultMarkers &&
|
|
2248
|
+
(res.features.length > 0 || 'place' in res)) {
|
|
2249
|
+
this._fitBoundsForMarkers();
|
|
2250
|
+
}
|
|
2251
|
+
this._eventEmitter.emit("results", res);
|
|
2252
|
+
}
|
|
2253
|
+
else {
|
|
2254
|
+
this._clearEl.style.display = "none";
|
|
2255
|
+
this._typeahead.selected = null;
|
|
2256
|
+
this._renderNoResults();
|
|
2257
|
+
this._eventEmitter.emit("results", res);
|
|
2258
|
+
}
|
|
2259
|
+
});
|
|
2260
|
+
}
|
|
2261
|
+
_handleGeocodeErrorResponse(error, localGeocoderResults) {
|
|
2262
|
+
this._loadingEl.style.display = "none";
|
|
2263
|
+
// in the event of an error in the Geocoding API still display results from the localGeocoder
|
|
2264
|
+
if (localGeocoderResults.length && this.options.localGeocoder) {
|
|
2265
|
+
this._clearEl.style.display = "block";
|
|
2266
|
+
this._typeahead.update(localGeocoderResults);
|
|
2267
|
+
}
|
|
2268
|
+
else {
|
|
2269
|
+
this._clearEl.style.display = "none";
|
|
2270
|
+
this._typeahead.selected = null;
|
|
2271
|
+
this._renderError();
|
|
2272
|
+
}
|
|
2273
|
+
this._eventEmitter.emit("results", { features: localGeocoderResults });
|
|
2274
|
+
this._eventEmitter.emit("error", { error });
|
|
2275
|
+
}
|
|
2276
|
+
/**
|
|
2277
|
+
* Shared logic for clearing input
|
|
2278
|
+
* @param ev - the event that triggered the clear, if available
|
|
2279
|
+
*/
|
|
2280
|
+
_clear(ev) {
|
|
2281
|
+
if (ev)
|
|
2282
|
+
ev.preventDefault();
|
|
2283
|
+
this._inputEl.value = "";
|
|
2284
|
+
this._typeahead.selected = null;
|
|
2285
|
+
this._typeahead.clear();
|
|
2286
|
+
this._onChange();
|
|
2287
|
+
this._clearEl.style.display = "none";
|
|
2288
|
+
this._removeMarker();
|
|
2289
|
+
this._removeResultMarkers();
|
|
2290
|
+
this.lastSelected = null;
|
|
2291
|
+
this._eventEmitter.emit("clear");
|
|
2292
|
+
this.fresh = true;
|
|
2293
|
+
}
|
|
2294
|
+
/**
|
|
2295
|
+
* Clear and then focus the input.
|
|
2296
|
+
* @param ev - the event that triggered the clear, if available
|
|
2297
|
+
*
|
|
2298
|
+
*/
|
|
2299
|
+
clear(ev) {
|
|
2300
|
+
this._clear(ev);
|
|
2301
|
+
this._inputEl.focus();
|
|
2302
|
+
}
|
|
2303
|
+
/**
|
|
2304
|
+
* Clear the input, without refocusing it. Used to implement clearOnBlur
|
|
2305
|
+
* constructor option.
|
|
2306
|
+
* @param ev - the blur event
|
|
2307
|
+
*/
|
|
2308
|
+
_clearOnBlur(ev) {
|
|
2309
|
+
/*
|
|
2310
|
+
* If relatedTarget is not found, assume user targeted the suggestions list.
|
|
2311
|
+
* In that case, do not clear on blur. There are other edge cases where
|
|
2312
|
+
* ev.relatedTarget could be null. Clicking on list always results in null
|
|
2313
|
+
* relatedtarget because of upstream behavior in `suggestions`.
|
|
2314
|
+
*
|
|
2315
|
+
* The ideal solution would be to check if ev.relatedTarget is a child of
|
|
2316
|
+
* the list. See issue #258 for details on why we can't do that yet.
|
|
2317
|
+
*/
|
|
2318
|
+
if (ev.relatedTarget) {
|
|
2319
|
+
this._clear(ev);
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2322
|
+
_onQueryResult(results) {
|
|
2323
|
+
if (!('features' in results)) {
|
|
2324
|
+
return;
|
|
2325
|
+
}
|
|
2326
|
+
if (!results.features.length)
|
|
2327
|
+
return;
|
|
2328
|
+
const result = results.features[0];
|
|
2329
|
+
this._typeahead.selected = result;
|
|
2330
|
+
this._inputEl.value = result.place_name;
|
|
2331
|
+
this._onChange();
|
|
2332
|
+
}
|
|
2333
|
+
_updateProximity() {
|
|
2334
|
+
// proximity is designed for local scale, if the user is looking at the whole world,
|
|
2335
|
+
// it doesn't make sense to factor in the arbitrary centre of the map
|
|
2336
|
+
if (!this._map) {
|
|
2337
|
+
return;
|
|
2338
|
+
}
|
|
2339
|
+
if (this._map.getZoom() > this.options.proximityMinZoom) {
|
|
2340
|
+
const center = this._map.getCenter().wrap();
|
|
2341
|
+
this.setProximity({ longitude: center.lng, latitude: center.lat });
|
|
2342
|
+
}
|
|
2343
|
+
else {
|
|
2344
|
+
this.setProximity(null);
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
_collapse() {
|
|
2348
|
+
// do not collapse if input is in focus
|
|
2349
|
+
if (!this._inputEl.value && this._inputEl !== document.activeElement)
|
|
2350
|
+
this.container.classList.add("maplibregl-ctrl-geocoder--collapsed");
|
|
2351
|
+
}
|
|
2352
|
+
_unCollapse() {
|
|
2353
|
+
this.container.classList.remove("maplibregl-ctrl-geocoder--collapsed");
|
|
2354
|
+
}
|
|
2355
|
+
/**
|
|
2356
|
+
* Set & query the input
|
|
2357
|
+
* @param searchInput - location name or other search input
|
|
2358
|
+
*/
|
|
2359
|
+
query(searchInput) {
|
|
2360
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2361
|
+
const results = yield this._geocode(searchInput);
|
|
2362
|
+
this._onQueryResult(results);
|
|
2363
|
+
});
|
|
2364
|
+
}
|
|
2365
|
+
_renderError() {
|
|
2366
|
+
const errorMessage = `<div class='maplibre-gl-geocoder--error'>${this._localize("errorConnectionFailed")}</div>`;
|
|
2367
|
+
this._renderMessage(errorMessage);
|
|
2368
|
+
}
|
|
2369
|
+
_renderNoResults() {
|
|
2370
|
+
const errorMessage = `<div class='maplibre-gl-geocoder--error maplibre-gl-geocoder--no-results'>
|
|
2371
|
+
${this._localize("errorNoResults")}</div>`;
|
|
2372
|
+
this._renderMessage(errorMessage);
|
|
2373
|
+
}
|
|
2374
|
+
_renderMessage(msg) {
|
|
2375
|
+
this._typeahead.update([]);
|
|
2376
|
+
this._typeahead.selected = null;
|
|
2377
|
+
this._typeahead.clear();
|
|
2378
|
+
this._typeahead.renderError(msg);
|
|
2379
|
+
}
|
|
2380
|
+
/**
|
|
2381
|
+
* Get a localised string for a given key
|
|
2382
|
+
*
|
|
2383
|
+
* If language is provided in options, attempt to return localized string (defaults to English)
|
|
2384
|
+
* @param key - key in the localization object
|
|
2385
|
+
* @returns localized string
|
|
2386
|
+
*/
|
|
2387
|
+
_localize(key) {
|
|
2388
|
+
const language = subtag.language(this.options.language.split(',')[0]);
|
|
2389
|
+
return this.options.language && (localization === null || localization === void 0 ? void 0 : localization[key][language]) ? localization[key][language] : localization[key]['en'];
|
|
2390
|
+
}
|
|
2391
|
+
/**
|
|
2392
|
+
* Fits the map to the current bounds for the searched results
|
|
2393
|
+
*/
|
|
2394
|
+
_fitBoundsForMarkers() {
|
|
2395
|
+
if (this._typeahead.data.length < 1)
|
|
2396
|
+
return;
|
|
2397
|
+
// Filter out suggestions and restrict to limit
|
|
2398
|
+
const results = this._typeahead.data
|
|
2399
|
+
.filter((result) => {
|
|
2400
|
+
return typeof result === "string" ? false : true;
|
|
2401
|
+
})
|
|
2402
|
+
.slice(0, this.options.limit);
|
|
2403
|
+
this._clearEl.style.display = "none";
|
|
2404
|
+
if (this.options.flyTo && this._maplibregl) {
|
|
2405
|
+
if (this._map) {
|
|
2406
|
+
const defaultFlyOptions = { padding: 100 };
|
|
2407
|
+
const flyOptions = extend({}, defaultFlyOptions, this.options.flyTo);
|
|
2408
|
+
const bounds = new this._maplibregl.LngLatBounds();
|
|
2409
|
+
for (const feature of results) {
|
|
2410
|
+
bounds.extend(feature.geometry.coordinates);
|
|
2411
|
+
}
|
|
2412
|
+
this._map.fitBounds(bounds, flyOptions);
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2415
|
+
if (results.length > 0 && this._maplibregl) {
|
|
2416
|
+
this._handleResultMarkers(results);
|
|
2417
|
+
}
|
|
2418
|
+
return this;
|
|
2419
|
+
}
|
|
2420
|
+
/**
|
|
2421
|
+
* Set input
|
|
2422
|
+
* @param searchInput - location name or other search input
|
|
2423
|
+
*/
|
|
2424
|
+
setInput(searchInput) {
|
|
2425
|
+
// Set input value to passed value and clear everything else.
|
|
2426
|
+
this._inputEl.value = searchInput;
|
|
2427
|
+
this._typeahead.selected = null;
|
|
2428
|
+
this._typeahead.clear();
|
|
2429
|
+
if (searchInput.length >= this.options.minLength &&
|
|
2430
|
+
this.options.showResultsWhileTyping) {
|
|
2431
|
+
this._geocode(searchInput);
|
|
2432
|
+
}
|
|
2433
|
+
return this;
|
|
2434
|
+
}
|
|
2435
|
+
/**
|
|
2436
|
+
* Set proximity
|
|
2437
|
+
* @param proximity - The new `options.proximity` value. This is a geographical point given as an object with `latitude` and `longitude` properties.
|
|
2438
|
+
*/
|
|
2439
|
+
setProximity(proximity) {
|
|
2440
|
+
this.options.proximity = proximity;
|
|
2441
|
+
return this;
|
|
2442
|
+
}
|
|
2443
|
+
/**
|
|
2444
|
+
* Get proximity
|
|
2445
|
+
* @returns The geocoder proximity
|
|
2446
|
+
*/
|
|
2447
|
+
getProximity() {
|
|
2448
|
+
return this.options.proximity;
|
|
2449
|
+
}
|
|
2450
|
+
/**
|
|
2451
|
+
* Set the render function used in the results dropdown
|
|
2452
|
+
* @param fn - The function to use as a render function. This function accepts a single {@link CarmenGeojsonFeature} object as input and returns a string.
|
|
2453
|
+
*/
|
|
2454
|
+
setRenderFunction(fn) {
|
|
2455
|
+
if (fn && typeof fn == "function") {
|
|
2456
|
+
this._typeahead.render = fn;
|
|
2457
|
+
}
|
|
2458
|
+
return this;
|
|
2459
|
+
}
|
|
2460
|
+
/**
|
|
2461
|
+
* Get the function used to render the results dropdown
|
|
2462
|
+
*
|
|
2463
|
+
* @returns the render function
|
|
2464
|
+
*/
|
|
2465
|
+
getRenderFunction() {
|
|
2466
|
+
return this._typeahead.render;
|
|
2467
|
+
}
|
|
2468
|
+
/**
|
|
2469
|
+
* Get the language to use in UI elements and when making search requests
|
|
2470
|
+
*
|
|
2471
|
+
* Look first at the explicitly set options otherwise use the browser's language settings
|
|
2472
|
+
* @param language - Specify the language to use for response text and query result weighting. Options are IETF language tags comprised of a mandatory ISO 639-1 language code and optionally one or more IETF subtags for country or script. More than one value can also be specified, separated by commas.
|
|
2473
|
+
*/
|
|
2474
|
+
setLanguage(language) {
|
|
2475
|
+
this.options.language = language || this.options.language || navigator.language;
|
|
2476
|
+
return this;
|
|
2477
|
+
}
|
|
2478
|
+
/**
|
|
2479
|
+
* Get the language to use in UI elements and when making search requests
|
|
2480
|
+
* @returns The language(s) used by the plugin, if any
|
|
2481
|
+
*/
|
|
2482
|
+
getLanguage() {
|
|
2483
|
+
return this.options.language;
|
|
2484
|
+
}
|
|
2485
|
+
/**
|
|
2486
|
+
* Get the zoom level the map will move to when there is no bounding box on the selected result
|
|
2487
|
+
* @returns the map zoom
|
|
2488
|
+
*/
|
|
2489
|
+
getZoom() {
|
|
2490
|
+
return this.options.zoom;
|
|
2491
|
+
}
|
|
2492
|
+
/**
|
|
2493
|
+
* Set the zoom level
|
|
2494
|
+
* @param zoom - The zoom level that the map should animate to when a `bbox` isn't found in the response. If a `bbox` is found the map will fit to the `bbox`.
|
|
2495
|
+
* @returns this
|
|
2496
|
+
*/
|
|
2497
|
+
setZoom(zoom) {
|
|
2498
|
+
this.options.zoom = zoom;
|
|
2499
|
+
return this;
|
|
2500
|
+
}
|
|
2501
|
+
/**
|
|
2502
|
+
* Get the parameters used to fly to the selected response, if any
|
|
2503
|
+
* @returns The `flyTo` option
|
|
2504
|
+
*/
|
|
2505
|
+
getFlyTo() {
|
|
2506
|
+
return this.options.flyTo;
|
|
2507
|
+
}
|
|
2508
|
+
/**
|
|
2509
|
+
* Set the flyTo options
|
|
2510
|
+
* @param flyTo - If false, animating the map to a selected result is disabled. If true, animating the map will use the default animation parameters. If an object, it will be passed as `options` to the map [`flyTo`](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map#flyto) or [`fitBounds`](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map#fitbounds) method providing control over the animation of the transition.
|
|
2511
|
+
*/
|
|
2512
|
+
setFlyTo(flyTo) {
|
|
2513
|
+
this.options.flyTo = flyTo;
|
|
2514
|
+
return this;
|
|
2515
|
+
}
|
|
2516
|
+
/**
|
|
2517
|
+
* Get the value of the placeholder string
|
|
2518
|
+
* @returns The input element's placeholder value
|
|
2519
|
+
*/
|
|
2520
|
+
getPlaceholder() {
|
|
2521
|
+
return this.options.placeholder;
|
|
2522
|
+
}
|
|
2523
|
+
/**
|
|
2524
|
+
* Set the value of the input element's placeholder
|
|
2525
|
+
* @param placeholder - the text to use as the input element's placeholder
|
|
2526
|
+
*/
|
|
2527
|
+
setPlaceholder(placeholder) {
|
|
2528
|
+
this.placeholder = placeholder ? placeholder : this.options.placeholder || this._localize("placeholder");
|
|
2529
|
+
this._inputEl.placeholder = this.placeholder;
|
|
2530
|
+
this._inputEl.setAttribute("aria-label", this.placeholder);
|
|
2531
|
+
return this;
|
|
2532
|
+
}
|
|
2533
|
+
/**
|
|
2534
|
+
* Get the bounding box used by the plugin
|
|
2535
|
+
* @returns the bounding box, if any
|
|
2536
|
+
*/
|
|
2537
|
+
getBbox() {
|
|
2538
|
+
return this.options.bbox;
|
|
2539
|
+
}
|
|
2540
|
+
/**
|
|
2541
|
+
* Set the bounding box to limit search results to
|
|
2542
|
+
* @param bbox - a bounding box given as an array in the format [minX, minY, maxX, maxY].
|
|
2543
|
+
*/
|
|
2544
|
+
setBbox(bbox) {
|
|
2545
|
+
this.options.bbox = bbox;
|
|
2546
|
+
return this;
|
|
2547
|
+
}
|
|
2548
|
+
/**
|
|
2549
|
+
* Get a list of the countries to limit search results to
|
|
2550
|
+
* @returns a comma separated list of countries to limit to, if any
|
|
2551
|
+
*/
|
|
2552
|
+
getCountries() {
|
|
2553
|
+
return this.options.countries;
|
|
2554
|
+
}
|
|
2555
|
+
/**
|
|
2556
|
+
* Set the countries to limit search results to
|
|
2557
|
+
* @param countries - a comma separated list of countries to limit to
|
|
2558
|
+
*/
|
|
2559
|
+
setCountries(countries) {
|
|
2560
|
+
this.options.countries = countries;
|
|
2561
|
+
return this;
|
|
2562
|
+
}
|
|
2563
|
+
/**
|
|
2564
|
+
* Get a list of the types to limit search results to
|
|
2565
|
+
* @returns a comma separated list of types to limit to
|
|
2566
|
+
*/
|
|
2567
|
+
getTypes() {
|
|
2568
|
+
return this.options.types;
|
|
2569
|
+
}
|
|
2570
|
+
/**
|
|
2571
|
+
* Set the types to limit search results to
|
|
2572
|
+
* @param types - a comma separated list of types to limit to
|
|
2573
|
+
*/
|
|
2574
|
+
setTypes(types) {
|
|
2575
|
+
this.options.types = types;
|
|
2576
|
+
return this;
|
|
2577
|
+
}
|
|
2578
|
+
/**
|
|
2579
|
+
* Get the minimum number of characters typed to trigger results used in the plugin
|
|
2580
|
+
* @returns The minimum length in characters before a search is triggered
|
|
2581
|
+
*/
|
|
2582
|
+
getMinLength() {
|
|
2583
|
+
return this.options.minLength;
|
|
2584
|
+
}
|
|
2585
|
+
/**
|
|
2586
|
+
* Set the minimum number of characters typed to trigger results used by the plugin
|
|
2587
|
+
* @param minLength - the minimum length in characters
|
|
2588
|
+
*/
|
|
2589
|
+
setMinLength(minLength) {
|
|
2590
|
+
this.options.minLength = minLength;
|
|
2591
|
+
if (this._typeahead)
|
|
2592
|
+
this._typeahead.options.minLength = minLength;
|
|
2593
|
+
return this;
|
|
2594
|
+
}
|
|
2595
|
+
/**
|
|
2596
|
+
* Get the limit value for the number of results to display used by the plugin
|
|
2597
|
+
* @returns The limit value for the number of results to display used by the plugin
|
|
2598
|
+
*/
|
|
2599
|
+
getLimit() {
|
|
2600
|
+
return this.options.limit;
|
|
2601
|
+
}
|
|
2602
|
+
/**
|
|
2603
|
+
* Set the limit value for the number of results to display used by the plugin
|
|
2604
|
+
* @param limit - the number of search results to return
|
|
2605
|
+
*/
|
|
2606
|
+
setLimit(limit) {
|
|
2607
|
+
this.options.limit = limit;
|
|
2608
|
+
if (this._typeahead)
|
|
2609
|
+
this._typeahead.options.limit = limit;
|
|
2610
|
+
return this;
|
|
2611
|
+
}
|
|
2612
|
+
/**
|
|
2613
|
+
* Get the filter function used by the plugin
|
|
2614
|
+
* @returns the filter function
|
|
2615
|
+
*/
|
|
2616
|
+
getFilter() {
|
|
2617
|
+
return this.options.filter;
|
|
2618
|
+
}
|
|
2619
|
+
/**
|
|
2620
|
+
* Set the filter function used by the plugin.
|
|
2621
|
+
* @param filter - A function which accepts a {@link CarmenGeojsonFeature} to filter out results from the Geocoding API response before they are included in the suggestions list. Return `true` to keep the item, `false` otherwise.
|
|
2622
|
+
*/
|
|
2623
|
+
setFilter(filter) {
|
|
2624
|
+
this.options.filter = filter;
|
|
2625
|
+
return this;
|
|
2626
|
+
}
|
|
2627
|
+
/**
|
|
2628
|
+
* Set the geocoding api used by the plugin.
|
|
2629
|
+
*/
|
|
2630
|
+
setGeocoderApi(geocoderApi) {
|
|
2631
|
+
this.geocoderApi = geocoderApi;
|
|
2632
|
+
return this;
|
|
2633
|
+
}
|
|
2634
|
+
/**
|
|
2635
|
+
* Get the geocoding endpoint the plugin is currently set to
|
|
2636
|
+
* @returns the geocoding API
|
|
2637
|
+
*/
|
|
2638
|
+
getGeocoderApi() {
|
|
2639
|
+
return this.geocoderApi;
|
|
2640
|
+
}
|
|
2641
|
+
/**
|
|
2642
|
+
* Handle the placement of a result marking the selected result
|
|
2643
|
+
* @param selected - the selected geojson feature
|
|
2644
|
+
*/
|
|
2645
|
+
_handleMarker(selected) {
|
|
2646
|
+
// clean up any old marker that might be present
|
|
2647
|
+
if (!this._map) {
|
|
2648
|
+
return;
|
|
2649
|
+
}
|
|
2650
|
+
this._removeMarker();
|
|
2651
|
+
const defaultMarkerOptions = {
|
|
2652
|
+
color: "#4668F2",
|
|
2653
|
+
};
|
|
2654
|
+
const markerOptions = extend({}, defaultMarkerOptions, this.options.marker);
|
|
2655
|
+
this.mapMarker = new this._maplibregl.Marker(markerOptions);
|
|
2656
|
+
let popup;
|
|
2657
|
+
if (this.options.popup) {
|
|
2658
|
+
const defaultPopupOptions = {};
|
|
2659
|
+
const popupOptions = extend({}, defaultPopupOptions, this.options.popup);
|
|
2660
|
+
popup = new this._maplibregl.Popup(popupOptions).setHTML(this.options.popupRender(selected));
|
|
2661
|
+
}
|
|
2662
|
+
if (selected.center) {
|
|
2663
|
+
this.mapMarker.setLngLat(selected.center).addTo(this._map);
|
|
2664
|
+
if (this.options.popup)
|
|
2665
|
+
this.mapMarker.setPopup(popup);
|
|
2666
|
+
}
|
|
2667
|
+
else if (selected.geometry &&
|
|
2668
|
+
selected.geometry.type &&
|
|
2669
|
+
selected.geometry.type === "Point" &&
|
|
2670
|
+
selected.geometry.coordinates) {
|
|
2671
|
+
this.mapMarker.setLngLat(selected.geometry.coordinates).addTo(this._map);
|
|
2672
|
+
if (this.options.popup)
|
|
2673
|
+
this.mapMarker.setPopup(popup);
|
|
2674
|
+
}
|
|
2675
|
+
return this;
|
|
2676
|
+
}
|
|
2677
|
+
/**
|
|
2678
|
+
* Handle the removal of a result marker
|
|
2679
|
+
*/
|
|
2680
|
+
_removeMarker() {
|
|
2681
|
+
if (this.mapMarker) {
|
|
2682
|
+
this.mapMarker.remove();
|
|
2683
|
+
this.mapMarker = null;
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2686
|
+
/**
|
|
2687
|
+
* Handle the placement of a result marking the selected result
|
|
2688
|
+
* @param results - the top results to display on the map
|
|
2689
|
+
*/
|
|
2690
|
+
_handleResultMarkers(results) {
|
|
2691
|
+
// clean up any old marker that might be present
|
|
2692
|
+
if (!this._map) {
|
|
2693
|
+
return;
|
|
2694
|
+
}
|
|
2695
|
+
this._removeResultMarkers();
|
|
2696
|
+
const defaultMarkerOptions = {
|
|
2697
|
+
color: "#4668F2",
|
|
2698
|
+
};
|
|
2699
|
+
let markerOptions = extend({}, defaultMarkerOptions, this.options.showResultMarkers);
|
|
2700
|
+
for (const result of results) {
|
|
2701
|
+
let el;
|
|
2702
|
+
if (this.options.showResultMarkers) {
|
|
2703
|
+
if (this.options.showResultMarkers &&
|
|
2704
|
+
this.options.showResultMarkers.element) {
|
|
2705
|
+
el = this.options.showResultMarkers.element.cloneNode(true);
|
|
2706
|
+
markerOptions = extend(markerOptions, { element: el });
|
|
2707
|
+
}
|
|
2708
|
+
const marker = new this._maplibregl.Marker(extend({}, markerOptions, { element: el }));
|
|
2709
|
+
let popup;
|
|
2710
|
+
if (this.options.popup) {
|
|
2711
|
+
const defaultPopupOptions = {};
|
|
2712
|
+
const popupOptions = extend({}, defaultPopupOptions, this.options.popup);
|
|
2713
|
+
popup = new this._maplibregl.Popup(popupOptions).setHTML(this.options.popupRender(result));
|
|
2714
|
+
}
|
|
2715
|
+
if (result.center) {
|
|
2716
|
+
marker.setLngLat(result.center).addTo(this._map);
|
|
2717
|
+
if (this.options.popup)
|
|
2718
|
+
marker.setPopup(popup);
|
|
2719
|
+
}
|
|
2720
|
+
else if (result.geometry &&
|
|
2721
|
+
result.geometry.type &&
|
|
2722
|
+
result.geometry.type === "Point" &&
|
|
2723
|
+
result.geometry.coordinates) {
|
|
2724
|
+
marker.setLngLat(result.geometry.coordinates).addTo(this._map);
|
|
2725
|
+
if (this.options.popup)
|
|
2726
|
+
marker.setPopup(popup);
|
|
2727
|
+
}
|
|
2728
|
+
this.resultMarkers.push(marker);
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
return this;
|
|
2732
|
+
}
|
|
2733
|
+
/**
|
|
2734
|
+
* Handle the removal of a result marker
|
|
2735
|
+
*/
|
|
2736
|
+
_removeResultMarkers() {
|
|
2737
|
+
if (this.resultMarkers && this.resultMarkers.length > 0) {
|
|
2738
|
+
this.resultMarkers.forEach(function (marker) {
|
|
2739
|
+
marker.remove();
|
|
2740
|
+
});
|
|
2741
|
+
this.resultMarkers = [];
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2744
|
+
/**
|
|
2745
|
+
* Subscribe to events that happen within the plugin.
|
|
2746
|
+
* @param type - name of event. Available events and the data passed into their respective event objects are:
|
|
2747
|
+
*
|
|
2748
|
+
* - __clear__ `Emitted when the input is cleared`
|
|
2749
|
+
* - __loading__ `{ query } Emitted when the geocoder is looking up a query`
|
|
2750
|
+
* - __results__ `{ results } Fired when the geocoder returns a response`
|
|
2751
|
+
* - __result__ `{ result } Fired when input is set`
|
|
2752
|
+
* - __error__ `{ error } Error as string`
|
|
2753
|
+
* @param fn - function that's called when the event is emitted.
|
|
2754
|
+
*/
|
|
2755
|
+
on(type, fn) {
|
|
2756
|
+
this._eventEmitter.on(type, fn);
|
|
2757
|
+
return this;
|
|
2758
|
+
}
|
|
2759
|
+
/**
|
|
2760
|
+
* Subscribe to events that happen within the plugin only once.
|
|
2761
|
+
* @param type - Event name.
|
|
2762
|
+
* Available events and the data passed into their respective event objects are:
|
|
2763
|
+
*
|
|
2764
|
+
* - __clear__ `Emitted when the input is cleared`
|
|
2765
|
+
* - __loading__ `{ query } Emitted when the geocoder is looking up a query`
|
|
2766
|
+
* - __results__ `{ results } Fired when the geocoder returns a response`
|
|
2767
|
+
* - __result__ `{ result } Fired when input is set`
|
|
2768
|
+
* - __error__ `{ error } Error as string`
|
|
2769
|
+
* @returns a Promise that resolves when the event is emitted.
|
|
2770
|
+
*/
|
|
2771
|
+
once(type) {
|
|
2772
|
+
return new Promise((resolve) => {
|
|
2773
|
+
this._eventEmitter.once(type, resolve);
|
|
2774
|
+
});
|
|
2775
|
+
}
|
|
2776
|
+
/**
|
|
2777
|
+
* Remove an event
|
|
2778
|
+
* @param type - Event name.
|
|
2779
|
+
* @param fn - Function that should unsubscribe to the event emitted.
|
|
2780
|
+
*/
|
|
2781
|
+
off(type, fn) {
|
|
2782
|
+
this._eventEmitter.removeListener(type, fn);
|
|
2783
|
+
return this;
|
|
2784
|
+
}
|
|
2785
|
+
}
|
|
2786
|
+
|
|
2787
|
+
return MaplibreGeocoder;
|
|
2788
|
+
|
|
2789
|
+
}));
|
|
2790
|
+
//# sourceMappingURL=maplibre-gl-geocoder.js.map
|