· 7 years ago · Oct 26, 2018, 07:14 AM
1(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
2
3},{}],2:[function(require,module,exports){
4(function (process){
5// .dirname, .basename, and .extname methods are extracted from Node.js v8.11.1,
6// backported and transplited with Babel, with backwards-compat fixes
7
8// Copyright Joyent, Inc. and other Node contributors.
9//
10// Permission is hereby granted, free of charge, to any person obtaining a
11// copy of this software and associated documentation files (the
12// "Software"), to deal in the Software without restriction, including
13// without limitation the rights to use, copy, modify, merge, publish,
14// distribute, sublicense, and/or sell copies of the Software, and to permit
15// persons to whom the Software is furnished to do so, subject to the
16// following conditions:
17//
18// The above copyright notice and this permission notice shall be included
19// in all copies or substantial portions of the Software.
20//
21// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
24// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
25// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
26// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
27// USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29// resolves . and .. elements in a path array with directory names there
30// must be no slashes, empty elements, or device names (c:\) in the array
31// (so also no leading and trailing slashes - it does not distinguish
32// relative and absolute paths)
33function normalizeArray(parts, allowAboveRoot) {
34 // if the path tries to go above the root, `up` ends up > 0
35 var up = 0;
36 for (var i = parts.length - 1; i >= 0; i--) {
37 var last = parts[i];
38 if (last === '.') {
39 parts.splice(i, 1);
40 } else if (last === '..') {
41 parts.splice(i, 1);
42 up++;
43 } else if (up) {
44 parts.splice(i, 1);
45 up--;
46 }
47 }
48
49 // if the path is allowed to go above the root, restore leading ..s
50 if (allowAboveRoot) {
51 for (; up--; up) {
52 parts.unshift('..');
53 }
54 }
55
56 return parts;
57}
58
59// path.resolve([from ...], to)
60// posix version
61exports.resolve = function() {
62 var resolvedPath = '',
63 resolvedAbsolute = false;
64
65 for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
66 var path = (i >= 0) ? arguments[i] : process.cwd();
67
68 // Skip empty and invalid entries
69 if (typeof path !== 'string') {
70 throw new TypeError('Arguments to path.resolve must be strings');
71 } else if (!path) {
72 continue;
73 }
74
75 resolvedPath = path + '/' + resolvedPath;
76 resolvedAbsolute = path.charAt(0) === '/';
77 }
78
79 // At this point the path should be resolved to a full absolute path, but
80 // handle relative paths to be safe (might happen when process.cwd() fails)
81
82 // Normalize the path
83 resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
84 return !!p;
85 }), !resolvedAbsolute).join('/');
86
87 return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
88};
89
90// path.normalize(path)
91// posix version
92exports.normalize = function(path) {
93 var isAbsolute = exports.isAbsolute(path),
94 trailingSlash = substr(path, -1) === '/';
95
96 // Normalize the path
97 path = normalizeArray(filter(path.split('/'), function(p) {
98 return !!p;
99 }), !isAbsolute).join('/');
100
101 if (!path && !isAbsolute) {
102 path = '.';
103 }
104 if (path && trailingSlash) {
105 path += '/';
106 }
107
108 return (isAbsolute ? '/' : '') + path;
109};
110
111// posix version
112exports.isAbsolute = function(path) {
113 return path.charAt(0) === '/';
114};
115
116// posix version
117exports.join = function() {
118 var paths = Array.prototype.slice.call(arguments, 0);
119 return exports.normalize(filter(paths, function(p, index) {
120 if (typeof p !== 'string') {
121 throw new TypeError('Arguments to path.join must be strings');
122 }
123 return p;
124 }).join('/'));
125};
126
127
128// path.relative(from, to)
129// posix version
130exports.relative = function(from, to) {
131 from = exports.resolve(from).substr(1);
132 to = exports.resolve(to).substr(1);
133
134 function trim(arr) {
135 var start = 0;
136 for (; start < arr.length; start++) {
137 if (arr[start] !== '') break;
138 }
139
140 var end = arr.length - 1;
141 for (; end >= 0; end--) {
142 if (arr[end] !== '') break;
143 }
144
145 if (start > end) return [];
146 return arr.slice(start, end - start + 1);
147 }
148
149 var fromParts = trim(from.split('/'));
150 var toParts = trim(to.split('/'));
151
152 var length = Math.min(fromParts.length, toParts.length);
153 var samePartsLength = length;
154 for (var i = 0; i < length; i++) {
155 if (fromParts[i] !== toParts[i]) {
156 samePartsLength = i;
157 break;
158 }
159 }
160
161 var outputParts = [];
162 for (var i = samePartsLength; i < fromParts.length; i++) {
163 outputParts.push('..');
164 }
165
166 outputParts = outputParts.concat(toParts.slice(samePartsLength));
167
168 return outputParts.join('/');
169};
170
171exports.sep = '/';
172exports.delimiter = ':';
173
174exports.dirname = function (path) {
175 if (typeof path !== 'string') path = path + '';
176 if (path.length === 0) return '.';
177 var code = path.charCodeAt(0);
178 var hasRoot = code === 47 /*/*/;
179 var end = -1;
180 var matchedSlash = true;
181 for (var i = path.length - 1; i >= 1; --i) {
182 code = path.charCodeAt(i);
183 if (code === 47 /*/*/) {
184 if (!matchedSlash) {
185 end = i;
186 break;
187 }
188 } else {
189 // We saw the first non-path separator
190 matchedSlash = false;
191 }
192 }
193
194 if (end === -1) return hasRoot ? '/' : '.';
195 if (hasRoot && end === 1) {
196 // return '//';
197 // Backwards-compat fix:
198 return '/';
199 }
200 return path.slice(0, end);
201};
202
203function basename(path) {
204 if (typeof path !== 'string') path = path + '';
205
206 var start = 0;
207 var end = -1;
208 var matchedSlash = true;
209 var i;
210
211 for (i = path.length - 1; i >= 0; --i) {
212 if (path.charCodeAt(i) === 47 /*/*/) {
213 // If we reached a path separator that was not part of a set of path
214 // separators at the end of the string, stop now
215 if (!matchedSlash) {
216 start = i + 1;
217 break;
218 }
219 } else if (end === -1) {
220 // We saw the first non-path separator, mark this as the end of our
221 // path component
222 matchedSlash = false;
223 end = i + 1;
224 }
225 }
226
227 if (end === -1) return '';
228 return path.slice(start, end);
229}
230
231// Uses a mixed approach for backwards-compatibility, as ext behavior changed
232// in new Node.js versions, so only basename() above is backported here
233exports.basename = function (path, ext) {
234 var f = basename(path);
235 if (ext && f.substr(-1 * ext.length) === ext) {
236 f = f.substr(0, f.length - ext.length);
237 }
238 return f;
239};
240
241exports.extname = function (path) {
242 if (typeof path !== 'string') path = path + '';
243 var startDot = -1;
244 var startPart = 0;
245 var end = -1;
246 var matchedSlash = true;
247 // Track the state of characters (if any) we see before our first dot and
248 // after any path separator we find
249 var preDotState = 0;
250 for (var i = path.length - 1; i >= 0; --i) {
251 var code = path.charCodeAt(i);
252 if (code === 47 /*/*/) {
253 // If we reached a path separator that was not part of a set of path
254 // separators at the end of the string, stop now
255 if (!matchedSlash) {
256 startPart = i + 1;
257 break;
258 }
259 continue;
260 }
261 if (end === -1) {
262 // We saw the first non-path separator, mark this as the end of our
263 // extension
264 matchedSlash = false;
265 end = i + 1;
266 }
267 if (code === 46 /*.*/) {
268 // If this is our first dot, mark it as the start of our extension
269 if (startDot === -1)
270 startDot = i;
271 else if (preDotState !== 1)
272 preDotState = 1;
273 } else if (startDot !== -1) {
274 // We saw a non-dot and non-path separator before our dot, so we should
275 // have a good chance at having a non-empty extension
276 preDotState = -1;
277 }
278 }
279
280 if (startDot === -1 || end === -1 ||
281 // We saw a non-dot character immediately before the dot
282 preDotState === 0 ||
283 // The (right-most) trimmed path component is exactly '..'
284 preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
285 return '';
286 }
287 return path.slice(startDot, end);
288};
289
290function filter (xs, f) {
291 if (xs.filter) return xs.filter(f);
292 var res = [];
293 for (var i = 0; i < xs.length; i++) {
294 if (f(xs[i], i, xs)) res.push(xs[i]);
295 }
296 return res;
297}
298
299// String.prototype.substr - negative index don't work in IE8
300var substr = 'ab'.substr(-1) === 'b'
301 ? function (str, start, len) { return str.substr(start, len) }
302 : function (str, start, len) {
303 if (start < 0) start = str.length + start;
304 return str.substr(start, len);
305 }
306;
307
308}).call(this,require('_process'))
309},{"_process":3}],3:[function(require,module,exports){
310// shim for using process in browser
311var process = module.exports = {};
312
313// cached from whatever global is present so that test runners that stub it
314// don't break things. But we need to wrap it in a try catch in case it is
315// wrapped in strict mode code which doesn't define any globals. It's inside a
316// function because try/catches deoptimize in certain engines.
317
318var cachedSetTimeout;
319var cachedClearTimeout;
320
321function defaultSetTimout() {
322 throw new Error('setTimeout has not been defined');
323}
324function defaultClearTimeout () {
325 throw new Error('clearTimeout has not been defined');
326}
327(function () {
328 try {
329 if (typeof setTimeout === 'function') {
330 cachedSetTimeout = setTimeout;
331 } else {
332 cachedSetTimeout = defaultSetTimout;
333 }
334 } catch (e) {
335 cachedSetTimeout = defaultSetTimout;
336 }
337 try {
338 if (typeof clearTimeout === 'function') {
339 cachedClearTimeout = clearTimeout;
340 } else {
341 cachedClearTimeout = defaultClearTimeout;
342 }
343 } catch (e) {
344 cachedClearTimeout = defaultClearTimeout;
345 }
346} ())
347function runTimeout(fun) {
348 if (cachedSetTimeout === setTimeout) {
349 //normal enviroments in sane situations
350 return setTimeout(fun, 0);
351 }
352 // if setTimeout wasn't available but was latter defined
353 if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
354 cachedSetTimeout = setTimeout;
355 return setTimeout(fun, 0);
356 }
357 try {
358 // when when somebody has screwed with setTimeout but no I.E. maddness
359 return cachedSetTimeout(fun, 0);
360 } catch(e){
361 try {
362 // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
363 return cachedSetTimeout.call(null, fun, 0);
364 } catch(e){
365 // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
366 return cachedSetTimeout.call(this, fun, 0);
367 }
368 }
369
370
371}
372function runClearTimeout(marker) {
373 if (cachedClearTimeout === clearTimeout) {
374 //normal enviroments in sane situations
375 return clearTimeout(marker);
376 }
377 // if clearTimeout wasn't available but was latter defined
378 if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
379 cachedClearTimeout = clearTimeout;
380 return clearTimeout(marker);
381 }
382 try {
383 // when when somebody has screwed with setTimeout but no I.E. maddness
384 return cachedClearTimeout(marker);
385 } catch (e){
386 try {
387 // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
388 return cachedClearTimeout.call(null, marker);
389 } catch (e){
390 // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
391 // Some versions of I.E. have different rules for clearTimeout vs setTimeout
392 return cachedClearTimeout.call(this, marker);
393 }
394 }
395
396
397
398}
399var queue = [];
400var draining = false;
401var currentQueue;
402var queueIndex = -1;
403
404function cleanUpNextTick() {
405 if (!draining || !currentQueue) {
406 return;
407 }
408 draining = false;
409 if (currentQueue.length) {
410 queue = currentQueue.concat(queue);
411 } else {
412 queueIndex = -1;
413 }
414 if (queue.length) {
415 drainQueue();
416 }
417}
418
419function drainQueue() {
420 if (draining) {
421 return;
422 }
423 var timeout = runTimeout(cleanUpNextTick);
424 draining = true;
425
426 var len = queue.length;
427 while(len) {
428 currentQueue = queue;
429 queue = [];
430 while (++queueIndex < len) {
431 if (currentQueue) {
432 currentQueue[queueIndex].run();
433 }
434 }
435 queueIndex = -1;
436 len = queue.length;
437 }
438 currentQueue = null;
439 draining = false;
440 runClearTimeout(timeout);
441}
442
443process.nextTick = function (fun) {
444 var args = new Array(arguments.length - 1);
445 if (arguments.length > 1) {
446 for (var i = 1; i < arguments.length; i++) {
447 args[i - 1] = arguments[i];
448 }
449 }
450 queue.push(new Item(fun, args));
451 if (queue.length === 1 && !draining) {
452 runTimeout(drainQueue);
453 }
454};
455
456// v8 likes predictible objects
457function Item(fun, array) {
458 this.fun = fun;
459 this.array = array;
460}
461Item.prototype.run = function () {
462 this.fun.apply(null, this.array);
463};
464process.title = 'browser';
465process.browser = true;
466process.env = {};
467process.argv = [];
468process.version = ''; // empty string to avoid regexp issues
469process.versions = {};
470
471function noop() {}
472
473process.on = noop;
474process.addListener = noop;
475process.once = noop;
476process.off = noop;
477process.removeListener = noop;
478process.removeAllListeners = noop;
479process.emit = noop;
480process.prependListener = noop;
481process.prependOnceListener = noop;
482
483process.listeners = function (name) { return [] }
484
485process.binding = function (name) {
486 throw new Error('process.binding is not supported');
487};
488
489process.cwd = function () { return '/' };
490process.chdir = function (dir) {
491 throw new Error('process.chdir is not supported');
492};
493process.umask = function() { return 0; };
494
495},{}],4:[function(require,module,exports){
496module.exports = Extent;
497
498function Extent() {
499 if (!(this instanceof Extent)) {
500 return new Extent();
501 }
502 this._bbox = [Infinity, Infinity, -Infinity, -Infinity];
503 this._valid = false;
504}
505
506Extent.prototype.include = function(ll) {
507 this._valid = true;
508 this._bbox[0] = Math.min(this._bbox[0], ll[0]);
509 this._bbox[1] = Math.min(this._bbox[1], ll[1]);
510 this._bbox[2] = Math.max(this._bbox[2], ll[0]);
511 this._bbox[3] = Math.max(this._bbox[3], ll[1]);
512 return this;
513};
514
515Extent.prototype.union = function(other) {
516 this._valid = true;
517 this._bbox[0] = Math.min(this._bbox[0], other[0]);
518 this._bbox[1] = Math.min(this._bbox[1], other[1]);
519 this._bbox[2] = Math.max(this._bbox[2], other[2]);
520 this._bbox[3] = Math.max(this._bbox[3], other[3]);
521 return this;
522};
523
524Extent.prototype.bbox = function() {
525 if (!this._valid) return null;
526 return this._bbox;
527};
528
529Extent.prototype.contains = function(ll) {
530 if (!this._valid) return null;
531 return this._bbox[0] <= ll[0] &&
532 this._bbox[1] <= ll[1] &&
533 this._bbox[2] >= ll[0] &&
534 this._bbox[3] >= ll[1];
535};
536
537Extent.prototype.polygon = function() {
538 if (!this._valid) return null;
539 return {
540 type: 'Polygon',
541 coordinates: [
542 [
543 // W, S
544 [this._bbox[0], this._bbox[1]],
545 // E, S
546 [this._bbox[2], this._bbox[1]],
547 // E, N
548 [this._bbox[2], this._bbox[3]],
549 // W, N
550 [this._bbox[0], this._bbox[3]],
551 // W, S
552 [this._bbox[0], this._bbox[1]]
553 ]
554 ]
555 };
556};
557
558},{}],5:[function(require,module,exports){
559var wgs84 = require('wgs84');
560
561module.exports.geometry = geometry;
562module.exports.ring = ringArea;
563
564function geometry(_) {
565 var area = 0, i;
566 switch (_.type) {
567 case 'Polygon':
568 return polygonArea(_.coordinates);
569 case 'MultiPolygon':
570 for (i = 0; i < _.coordinates.length; i++) {
571 area += polygonArea(_.coordinates[i]);
572 }
573 return area;
574 case 'Point':
575 case 'MultiPoint':
576 case 'LineString':
577 case 'MultiLineString':
578 return 0;
579 case 'GeometryCollection':
580 for (i = 0; i < _.geometries.length; i++) {
581 area += geometry(_.geometries[i]);
582 }
583 return area;
584 }
585}
586
587function polygonArea(coords) {
588 var area = 0;
589 if (coords && coords.length > 0) {
590 area += Math.abs(ringArea(coords[0]));
591 for (var i = 1; i < coords.length; i++) {
592 area -= Math.abs(ringArea(coords[i]));
593 }
594 }
595 return area;
596}
597
598/**
599 * Calculate the approximate area of the polygon were it projected onto
600 * the earth. Note that this area will be positive if ring is oriented
601 * clockwise, otherwise it will be negative.
602 *
603 * Reference:
604 * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
605 * Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
606 * Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409
607 *
608 * Returns:
609 * {float} The approximate signed geodesic area of the polygon in square
610 * meters.
611 */
612
613function ringArea(coords) {
614 var p1, p2, p3, lowerIndex, middleIndex, upperIndex,
615 area = 0,
616 coordsLength = coords.length;
617
618 if (coordsLength > 2) {
619 for (i = 0; i < coordsLength; i++) {
620 if (i === coordsLength - 2) {// i = N-2
621 lowerIndex = coordsLength - 2;
622 middleIndex = coordsLength -1;
623 upperIndex = 0;
624 } else if (i === coordsLength - 1) {// i = N-1
625 lowerIndex = coordsLength - 1;
626 middleIndex = 0;
627 upperIndex = 1;
628 } else { // i = 0 to N-3
629 lowerIndex = i;
630 middleIndex = i+1;
631 upperIndex = i+2;
632 }
633 p1 = coords[lowerIndex];
634 p2 = coords[middleIndex];
635 p3 = coords[upperIndex];
636 area += ( rad(p3[0]) - rad(p1[0]) ) * Math.sin( rad(p2[1]));
637 }
638
639 area = area * wgs84.RADIUS * wgs84.RADIUS / 2;
640 }
641
642 return area;
643}
644
645function rad(_) {
646 return _ * Math.PI / 180;
647}
648},{"wgs84":61}],6:[function(require,module,exports){
649module.exports = function flatten(list, depth) {
650 return _flatten(list);
651
652 function _flatten(list) {
653 if (Array.isArray(list) && list.length &&
654 typeof list[0] === 'number') {
655 return [list];
656 }
657 return list.reduce(function (acc, item) {
658 if (Array.isArray(item) && Array.isArray(item[0])) {
659 return acc.concat(_flatten(item));
660 } else {
661 acc.push(item);
662 return acc;
663 }
664 }, []);
665 }
666};
667
668},{}],7:[function(require,module,exports){
669var geojsonNormalize = require('geojson-normalize'),
670 geojsonFlatten = require('geojson-flatten'),
671 flatten = require('./flatten');
672
673module.exports = function(_) {
674 if (!_) return [];
675 var normalized = geojsonFlatten(geojsonNormalize(_)),
676 coordinates = [];
677 normalized.features.forEach(function(feature) {
678 if (!feature.geometry) return;
679 coordinates = coordinates.concat(flatten(feature.geometry.coordinates));
680 });
681 return coordinates;
682};
683
684},{"./flatten":6,"geojson-flatten":10,"geojson-normalize":8}],8:[function(require,module,exports){
685module.exports = normalize;
686
687var types = {
688 Point: 'geometry',
689 MultiPoint: 'geometry',
690 LineString: 'geometry',
691 MultiLineString: 'geometry',
692 Polygon: 'geometry',
693 MultiPolygon: 'geometry',
694 GeometryCollection: 'geometry',
695 Feature: 'feature',
696 FeatureCollection: 'featurecollection'
697};
698
699/**
700 * Normalize a GeoJSON feature into a FeatureCollection.
701 *
702 * @param {object} gj geojson data
703 * @returns {object} normalized geojson data
704 */
705function normalize(gj) {
706 if (!gj || !gj.type) return null;
707 var type = types[gj.type];
708 if (!type) return null;
709
710 if (type === 'geometry') {
711 return {
712 type: 'FeatureCollection',
713 features: [{
714 type: 'Feature',
715 properties: {},
716 geometry: gj
717 }]
718 };
719 } else if (type === 'feature') {
720 return {
721 type: 'FeatureCollection',
722 features: [gj]
723 };
724 } else if (type === 'featurecollection') {
725 return gj;
726 }
727}
728
729},{}],9:[function(require,module,exports){
730var geojsonCoords = require('geojson-coords'),
731 traverse = require('traverse'),
732 extent = require('extent');
733
734module.exports = function(_) {
735 return getExtent(_).bbox();
736};
737
738module.exports.polygon = function(_) {
739 return getExtent(_).polygon();
740};
741
742module.exports.bboxify = function(_) {
743 return traverse(_).map(function(value) {
744 if (value && typeof value.type === 'string') {
745 value.bbox = getExtent(value).bbox();
746 this.update(value);
747 }
748 });
749};
750
751function getExtent(_) {
752 var bbox = [Infinity, Infinity, -Infinity, -Infinity],
753 ext = extent(),
754 coords = geojsonCoords(_);
755 for (var i = 0; i < coords.length; i++) ext.include(coords[i]);
756 return ext;
757}
758
759},{"extent":4,"geojson-coords":7,"traverse":60}],10:[function(require,module,exports){
760module.exports = flatten;
761
762function flatten(gj, up) {
763 switch ((gj && gj.type) || null) {
764 case 'FeatureCollection':
765 gj.features = gj.features.reduce(function(mem, feature) {
766 return mem.concat(flatten(feature));
767 }, []);
768 return gj;
769 case 'Feature':
770 return flatten(gj.geometry).map(function(geom) {
771 return {
772 type: 'Feature',
773 properties: JSON.parse(JSON.stringify(gj.properties)),
774 geometry: geom
775 };
776 });
777 case 'MultiPoint':
778 return gj.coordinates.map(function(_) {
779 return { type: 'Point', coordinates: _ };
780 });
781 case 'MultiPolygon':
782 return gj.coordinates.map(function(_) {
783 return { type: 'Polygon', coordinates: _ };
784 });
785 case 'MultiLineString':
786 return gj.coordinates.map(function(_) {
787 return { type: 'LineString', coordinates: _ };
788 });
789 case 'GeometryCollection':
790 return gj.geometries;
791 case 'Point':
792 case 'Polygon':
793 case 'LineString':
794 return [gj];
795 default:
796 return gj;
797 }
798}
799
800},{}],11:[function(require,module,exports){
801arguments[4][8][0].apply(exports,arguments)
802},{"dup":8}],12:[function(require,module,exports){
803var jsonlint = require('jsonlint-lines'),
804 geojsonHintObject = require('./object');
805
806/**
807 * @alias geojsonhint
808 * @param {(string|object)} GeoJSON given as a string or as an object
809 * @param {Object} options
810 * @param {boolean} [options.noDuplicateMembers=true] forbid repeated
811 * properties. This is only available for string input, becaused parsed
812 * Objects cannot have duplicate properties.
813 * @param {boolean} [options.precisionWarning=true] warn if GeoJSON contains
814 * unnecessary coordinate precision.
815 * @returns {Array<Object>} an array of errors
816 */
817function hint(str, options) {
818
819 var gj, errors = [];
820
821 if (typeof str === 'object') {
822 gj = str;
823 } else if (typeof str === 'string') {
824 try {
825 gj = jsonlint.parse(str);
826 } catch(e) {
827 var match = e.message.match(/line (\d+)/);
828 var lineNumber = parseInt(match[1], 10);
829 return [{
830 line: lineNumber - 1,
831 message: e.message,
832 error: e
833 }];
834 }
835 } else {
836 return [{
837 message: 'Expected string or object as input',
838 line: 0
839 }];
840 }
841
842 errors = errors.concat(geojsonHintObject.hint(gj, options));
843
844 return errors;
845}
846
847module.exports.hint = hint;
848
849},{"./object":13,"jsonlint-lines":16}],13:[function(require,module,exports){
850var rightHandRule = require('./rhr');
851
852/**
853 * @alias geojsonhint
854 * @param {(string|object)} GeoJSON given as a string or as an object
855 * @param {Object} options
856 * @param {boolean} [options.noDuplicateMembers=true] forbid repeated
857 * properties. This is only available for string input, becaused parsed
858 * Objects cannot have duplicate properties.
859 * @param {boolean} [options.precisionWarning=true] warn if GeoJSON contains
860 * unnecessary coordinate precision.
861 * @returns {Array<Object>} an array of errors
862 */
863function hint(gj, options) {
864
865 var errors = [];
866 var precisionWarningCount = 0;
867 var maxPrecisionWarnings = 10;
868 var maxPrecision = 6;
869
870 function root(_) {
871
872 if ((!options || options.noDuplicateMembers !== false) &&
873 _.__duplicateProperties__) {
874 errors.push({
875 message: 'An object contained duplicate members, making parsing ambigous: ' + _.__duplicateProperties__.join(', '),
876 line: _.__line__
877 });
878 }
879
880 if (requiredProperty(_, 'type', 'string')) {
881 return;
882 }
883
884 if (!types[_.type]) {
885 var expectedType = typesLower[_.type.toLowerCase()];
886 if (expectedType !== undefined) {
887 errors.push({
888 message: 'Expected ' + expectedType + ' but got ' + _.type + ' (case sensitive)',
889 line: _.__line__
890 });
891 } else {
892 errors.push({
893 message: 'The type ' + _.type + ' is unknown',
894 line: _.__line__
895 });
896 }
897 } else if (_) {
898 types[_.type](_);
899 }
900 }
901
902 function everyIs(_, type) {
903 // make a single exception because typeof null === 'object'
904 return _.every(function(x) {
905 return x !== null && typeof x === type;
906 });
907 }
908
909 function requiredProperty(_, name, type) {
910 if (typeof _[name] === 'undefined') {
911 return errors.push({
912 message: '"' + name + '" member required',
913 line: _.__line__
914 });
915 } else if (type === 'array') {
916 if (!Array.isArray(_[name])) {
917 return errors.push({
918 message: '"' + name +
919 '" member should be an array, but is an ' +
920 (typeof _[name]) + ' instead',
921 line: _.__line__
922 });
923 }
924 } else if (type === 'object' && _[name] && _[name].constructor.name !== 'Object') {
925 return errors.push({
926 message: '"' + name +
927 '" member should be ' + (type) +
928 ', but is an ' + (_[name].constructor.name) + ' instead',
929 line: _.__line__
930 });
931 } else if (type && typeof _[name] !== type) {
932 return errors.push({
933 message: '"' + name +
934 '" member should be ' + (type) +
935 ', but is an ' + (typeof _[name]) + ' instead',
936 line: _.__line__
937 });
938 }
939 }
940
941 // http://geojson.org/geojson-spec.html#feature-collection-objects
942 function FeatureCollection(featureCollection) {
943 crs(featureCollection);
944 bbox(featureCollection);
945 if (featureCollection.properties !== undefined) {
946 errors.push({
947 message: 'FeatureCollection object cannot contain a "properties" member',
948 line: featureCollection.__line__
949 });
950 }
951 if (featureCollection.coordinates !== undefined) {
952 errors.push({
953 message: 'FeatureCollection object cannot contain a "coordinates" member',
954 line: featureCollection.__line__
955 });
956 }
957 if (!requiredProperty(featureCollection, 'features', 'array')) {
958 if (!everyIs(featureCollection.features, 'object')) {
959 return errors.push({
960 message: 'Every feature must be an object',
961 line: featureCollection.__line__
962 });
963 }
964 featureCollection.features.forEach(Feature);
965 }
966 }
967
968 // http://geojson.org/geojson-spec.html#positions
969 function position(_, line) {
970 if (!Array.isArray(_)) {
971 return errors.push({
972 message: 'position should be an array, is a ' + (typeof _) +
973 ' instead',
974 line: _.__line__ || line
975 });
976 }
977 if (_.length < 2) {
978 return errors.push({
979 message: 'position must have 2 or more elements',
980 line: _.__line__ || line
981 });
982 }
983 if (_.length > 3) {
984 return errors.push({
985 message: 'position should not have more than 3 elements',
986 line: _.__line__ || line
987 });
988 }
989 if (!everyIs(_, 'number')) {
990 return errors.push({
991 message: 'each element in a position must be a number',
992 line: _.__line__ || line
993 });
994 }
995
996 if (options && options.precisionWarning) {
997 if (precisionWarningCount === maxPrecisionWarnings) {
998 precisionWarningCount += 1;
999 return errors.push({
1000 message: 'truncated warnings: we\'ve encountered coordinate precision warning ' + maxPrecisionWarnings + ' times, no more warnings will be reported',
1001 level: 'message',
1002 line: _.__line__ || line
1003 });
1004 } else if (precisionWarningCount < maxPrecisionWarnings) {
1005 _.forEach(function(num) {
1006 var precision = 0;
1007 var decimalStr = String(num).split('.')[1];
1008 if (decimalStr !== undefined)
1009 precision = decimalStr.length;
1010 if (precision > maxPrecision) {
1011 precisionWarningCount += 1;
1012 return errors.push({
1013 message: 'precision of coordinates should be reduced',
1014 level: 'message',
1015 line: _.__line__ || line
1016 });
1017 }
1018 });
1019 }
1020 }
1021 }
1022
1023 function positionArray(coords, type, depth, line) {
1024 if (line === undefined && coords.__line__ !== undefined) {
1025 line = coords.__line__;
1026 }
1027 if (depth === 0) {
1028 return position(coords, line);
1029 }
1030 if (depth === 1 && type) {
1031 if (type === 'LinearRing') {
1032 if (!Array.isArray(coords[coords.length - 1])) {
1033 errors.push({
1034 message: 'a number was found where a coordinate array should have been found: this needs to be nested more deeply',
1035 line: line
1036 });
1037 return true;
1038 }
1039 if (coords.length < 4) {
1040 errors.push({
1041 message: 'a LinearRing of coordinates needs to have four or more positions',
1042 line: line
1043 });
1044 }
1045 if (coords.length &&
1046 (coords[coords.length - 1].length !== coords[0].length ||
1047 !coords[coords.length - 1].every(function(pos, index) {
1048 return coords[0][index] === pos;
1049 }))) {
1050 errors.push({
1051 message: 'the first and last positions in a LinearRing of coordinates must be the same',
1052 line: line
1053 });
1054 return true;
1055 }
1056 } else if (type === 'Line' && coords.length < 2) {
1057 return errors.push({
1058 message: 'a line needs to have two or more coordinates to be valid',
1059 line: line
1060 });
1061 }
1062 }
1063 if (!Array.isArray(coords)) {
1064 errors.push({
1065 message: 'a number was found where a coordinate array should have been found: this needs to be nested more deeply',
1066 line: line
1067 });
1068 } else {
1069 var results = coords.map(function(c) {
1070 return positionArray(c, type, depth - 1, c.__line__ || line);
1071 });
1072 return results.some(function(r) {
1073 return r;
1074 });
1075 }
1076 }
1077
1078 function crs(_) {
1079 if (!_.crs) return;
1080 var defaultCRSName = 'urn:ogc:def:crs:OGC:1.3:CRS84';
1081 if (typeof _.crs === 'object' && _.crs.properties && _.crs.properties.name === defaultCRSName) {
1082 errors.push({
1083 message: 'old-style crs member is not recommended, this object is equivalent to the default and should be removed',
1084 line: _.__line__
1085 });
1086 } else {
1087 errors.push({
1088 message: 'old-style crs member is not recommended',
1089 line: _.__line__
1090 });
1091 }
1092 }
1093
1094 function bbox(_) {
1095 if (!_.bbox) {
1096 return;
1097 }
1098 if (Array.isArray(_.bbox)) {
1099 if (!everyIs(_.bbox, 'number')) {
1100 errors.push({
1101 message: 'each element in a bbox member must be a number',
1102 line: _.bbox.__line__
1103 });
1104 }
1105 if (!(_.bbox.length === 4 || _.bbox.length === 6)) {
1106 errors.push({
1107 message: 'bbox must contain 4 elements (for 2D) or 6 elements (for 3D)',
1108 line: _.bbox.__line__
1109 });
1110 }
1111 return errors.length;
1112 }
1113 errors.push({
1114 message: 'bbox member must be an array of numbers, but is a ' + (typeof _.bbox),
1115 line: _.__line__
1116 });
1117 }
1118
1119 function geometrySemantics(geom) {
1120 if (geom.properties !== undefined) {
1121 errors.push({
1122 message: 'geometry object cannot contain a "properties" member',
1123 line: geom.__line__
1124 });
1125 }
1126 if (geom.geometry !== undefined) {
1127 errors.push({
1128 message: 'geometry object cannot contain a "geometry" member',
1129 line: geom.__line__
1130 });
1131 }
1132 if (geom.features !== undefined) {
1133 errors.push({
1134 message: 'geometry object cannot contain a "features" member',
1135 line: geom.__line__
1136 });
1137 }
1138 }
1139
1140 // http://geojson.org/geojson-spec.html#point
1141 function Point(point) {
1142 crs(point);
1143 bbox(point);
1144 geometrySemantics(point);
1145 if (!requiredProperty(point, 'coordinates', 'array')) {
1146 position(point.coordinates);
1147 }
1148 }
1149
1150 // http://geojson.org/geojson-spec.html#polygon
1151 function Polygon(polygon) {
1152 crs(polygon);
1153 bbox(polygon);
1154 if (!requiredProperty(polygon, 'coordinates', 'array')) {
1155 if (!positionArray(polygon.coordinates, 'LinearRing', 2)) {
1156 rightHandRule(polygon, errors);
1157 }
1158 }
1159 }
1160
1161 // http://geojson.org/geojson-spec.html#multipolygon
1162 function MultiPolygon(multiPolygon) {
1163 crs(multiPolygon);
1164 bbox(multiPolygon);
1165 if (!requiredProperty(multiPolygon, 'coordinates', 'array')) {
1166 if (!positionArray(multiPolygon.coordinates, 'LinearRing', 3)) {
1167 rightHandRule(multiPolygon, errors);
1168 }
1169 }
1170 }
1171
1172 // http://geojson.org/geojson-spec.html#linestring
1173 function LineString(lineString) {
1174 crs(lineString);
1175 bbox(lineString);
1176 if (!requiredProperty(lineString, 'coordinates', 'array')) {
1177 positionArray(lineString.coordinates, 'Line', 1);
1178 }
1179 }
1180
1181 // http://geojson.org/geojson-spec.html#multilinestring
1182 function MultiLineString(multiLineString) {
1183 crs(multiLineString);
1184 bbox(multiLineString);
1185 if (!requiredProperty(multiLineString, 'coordinates', 'array')) {
1186 positionArray(multiLineString.coordinates, 'Line', 2);
1187 }
1188 }
1189
1190 // http://geojson.org/geojson-spec.html#multipoint
1191 function MultiPoint(multiPoint) {
1192 crs(multiPoint);
1193 bbox(multiPoint);
1194 if (!requiredProperty(multiPoint, 'coordinates', 'array')) {
1195 positionArray(multiPoint.coordinates, '', 1);
1196 }
1197 }
1198
1199 function GeometryCollection(geometryCollection) {
1200 crs(geometryCollection);
1201 bbox(geometryCollection);
1202 if (!requiredProperty(geometryCollection, 'geometries', 'array')) {
1203 if (!everyIs(geometryCollection.geometries, 'object')) {
1204 errors.push({
1205 message: 'The geometries array in a GeometryCollection must contain only geometry objects',
1206 line: geometryCollection.__line__
1207 });
1208 }
1209 if (geometryCollection.geometries.length === 1) {
1210 errors.push({
1211 message: 'GeometryCollection with a single geometry should be avoided in favor of single part or a single object of multi-part type',
1212 line: geometryCollection.geometries.__line__
1213 });
1214 }
1215 geometryCollection.geometries.forEach(function(geometry) {
1216 if (geometry) {
1217 if (geometry.type === 'GeometryCollection') {
1218 errors.push({
1219 message: 'GeometryCollection should avoid nested geometry collections',
1220 line: geometryCollection.geometries.__line__
1221 });
1222 }
1223 root(geometry);
1224 }
1225 });
1226 }
1227 }
1228
1229 function Feature(feature) {
1230 crs(feature);
1231 bbox(feature);
1232 // https://github.com/geojson/draft-geojson/blob/master/middle.mkd#feature-object
1233 if (feature.id !== undefined &&
1234 typeof feature.id !== 'string' &&
1235 typeof feature.id !== 'number') {
1236 errors.push({
1237 message: 'Feature "id" member must have a string or number value',
1238 line: feature.__line__
1239 });
1240 }
1241 if (feature.features !== undefined) {
1242 errors.push({
1243 message: 'Feature object cannot contain a "features" member',
1244 line: feature.__line__
1245 });
1246 }
1247 if (feature.coordinates !== undefined) {
1248 errors.push({
1249 message: 'Feature object cannot contain a "coordinates" member',
1250 line: feature.__line__
1251 });
1252 }
1253 if (feature.type !== 'Feature') {
1254 errors.push({
1255 message: 'GeoJSON features must have a type=feature member',
1256 line: feature.__line__
1257 });
1258 }
1259 requiredProperty(feature, 'properties', 'object');
1260 if (!requiredProperty(feature, 'geometry', 'object')) {
1261 // http://geojson.org/geojson-spec.html#feature-objects
1262 // tolerate null geometry
1263 if (feature.geometry) root(feature.geometry);
1264 }
1265 }
1266
1267 var types = {
1268 Point: Point,
1269 Feature: Feature,
1270 MultiPoint: MultiPoint,
1271 LineString: LineString,
1272 MultiLineString: MultiLineString,
1273 FeatureCollection: FeatureCollection,
1274 GeometryCollection: GeometryCollection,
1275 Polygon: Polygon,
1276 MultiPolygon: MultiPolygon
1277 };
1278
1279 var typesLower = Object.keys(types).reduce(function(prev, curr) {
1280 prev[curr.toLowerCase()] = curr;
1281 return prev;
1282 }, {});
1283
1284 if (typeof gj !== 'object' ||
1285 gj === null ||
1286 gj === undefined) {
1287 errors.push({
1288 message: 'The root of a GeoJSON object must be an object.',
1289 line: 0
1290 });
1291 return errors;
1292 }
1293
1294 root(gj);
1295
1296 errors.forEach(function(err) {
1297 if ({}.hasOwnProperty.call(err, 'line') && err.line === undefined) {
1298 delete err.line;
1299 }
1300 });
1301
1302 return errors;
1303}
1304
1305module.exports.hint = hint;
1306
1307},{"./rhr":14}],14:[function(require,module,exports){
1308function rad(x) {
1309 return x * Math.PI / 180;
1310}
1311
1312function isRingClockwise (coords) {
1313 var area = 0;
1314 if (coords.length > 2) {
1315 var p1, p2;
1316 for (var i = 0; i < coords.length - 1; i++) {
1317 p1 = coords[i];
1318 p2 = coords[i + 1];
1319 area += rad(p2[0] - p1[0]) * (2 + Math.sin(rad(p1[1])) + Math.sin(rad(p2[1])));
1320 }
1321 }
1322
1323 return area >= 0;
1324}
1325
1326function isPolyRHR (coords) {
1327 if (coords && coords.length > 0) {
1328 if (isRingClockwise(coords[0]))
1329 return false;
1330 var interiorCoords = coords.slice(1, coords.length);
1331 if (!interiorCoords.every(isRingClockwise))
1332 return false;
1333 }
1334 return true;
1335}
1336
1337function rightHandRule (geometry) {
1338 if (geometry.type === 'Polygon') {
1339 return isPolyRHR(geometry.coordinates);
1340 } else if (geometry.type === 'MultiPolygon') {
1341 return geometry.coordinates.every(isPolyRHR);
1342 }
1343}
1344
1345module.exports = function validateRightHandRule(geometry, errors) {
1346 if (!rightHandRule(geometry)) {
1347 errors.push({
1348 message: 'Polygons and MultiPolygons should follow the right-hand rule',
1349 level: 'message',
1350 line: geometry.__line__
1351 });
1352 }
1353};
1354
1355},{}],15:[function(require,module,exports){
1356var hat = module.exports = function (bits, base) {
1357 if (!base) base = 16;
1358 if (bits === undefined) bits = 128;
1359 if (bits <= 0) return '0';
1360
1361 var digits = Math.log(Math.pow(2, bits)) / Math.log(base);
1362 for (var i = 2; digits === Infinity; i *= 2) {
1363 digits = Math.log(Math.pow(2, bits / i)) / Math.log(base) * i;
1364 }
1365
1366 var rem = digits - Math.floor(digits);
1367
1368 var res = '';
1369
1370 for (var i = 0; i < Math.floor(digits); i++) {
1371 var x = Math.floor(Math.random() * base).toString(base);
1372 res = x + res;
1373 }
1374
1375 if (rem) {
1376 var b = Math.pow(base, rem);
1377 var x = Math.floor(Math.random() * b).toString(base);
1378 res = x + res;
1379 }
1380
1381 var parsed = parseInt(res, base);
1382 if (parsed !== Infinity && parsed >= Math.pow(2, bits)) {
1383 return hat(bits, base)
1384 }
1385 else return res;
1386};
1387
1388hat.rack = function (bits, base, expandBy) {
1389 var fn = function (data) {
1390 var iters = 0;
1391 do {
1392 if (iters ++ > 10) {
1393 if (expandBy) bits += expandBy;
1394 else throw new Error('too many ID collisions, use more bits')
1395 }
1396
1397 var id = hat(bits, base);
1398 } while (Object.hasOwnProperty.call(hats, id));
1399
1400 hats[id] = data;
1401 return id;
1402 };
1403 var hats = fn.hats = {};
1404
1405 fn.get = function (id) {
1406 return fn.hats[id];
1407 };
1408
1409 fn.set = function (id, value) {
1410 fn.hats[id] = value;
1411 return fn;
1412 };
1413
1414 fn.bits = bits || 128;
1415 fn.base = base || 16;
1416 return fn;
1417};
1418
1419},{}],16:[function(require,module,exports){
1420(function (process){
1421/* parser generated by jison 0.4.17 */
1422/*
1423 Returns a Parser object of the following structure:
1424
1425 Parser: {
1426 yy: {}
1427 }
1428
1429 Parser.prototype: {
1430 yy: {},
1431 trace: function(),
1432 symbols_: {associative list: name ==> number},
1433 terminals_: {associative list: number ==> name},
1434 productions_: [...],
1435 performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
1436 table: [...],
1437 defaultActions: {...},
1438 parseError: function(str, hash),
1439 parse: function(input),
1440
1441 lexer: {
1442 EOF: 1,
1443 parseError: function(str, hash),
1444 setInput: function(input),
1445 input: function(),
1446 unput: function(str),
1447 more: function(),
1448 less: function(n),
1449 pastInput: function(),
1450 upcomingInput: function(),
1451 showPosition: function(),
1452 test_match: function(regex_match_array, rule_index),
1453 next: function(),
1454 lex: function(),
1455 begin: function(condition),
1456 popState: function(),
1457 _currentRules: function(),
1458 topState: function(),
1459 pushState: function(condition),
1460
1461 options: {
1462 ranges: boolean (optional: true ==> token location info will include a .range[] member)
1463 flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
1464 backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
1465 },
1466
1467 performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
1468 rules: [...],
1469 conditions: {associative list: name ==> set},
1470 }
1471 }
1472
1473
1474 token location info (@$, _$, etc.): {
1475 first_line: n,
1476 last_line: n,
1477 first_column: n,
1478 last_column: n,
1479 range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)
1480 }
1481
1482
1483 the parseError function receives a 'hash' object with these members for lexer and parser errors: {
1484 text: (matched text)
1485 token: (the produced terminal token, if any)
1486 line: (yylineno)
1487 }
1488 while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
1489 loc: (yylloc)
1490 expected: (string describing the set of expected tokens)
1491 recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
1492 }
1493*/
1494var jsonlint = (function(){
1495var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,12],$V1=[1,13],$V2=[1,9],$V3=[1,10],$V4=[1,11],$V5=[1,14],$V6=[1,15],$V7=[14,18,22,24],$V8=[18,22],$V9=[22,24];
1496var parser = {trace: function trace() { },
1497yy: {},
1498symbols_: {"error":2,"JSONString":3,"STRING":4,"JSONNumber":5,"NUMBER":6,"JSONNullLiteral":7,"NULL":8,"JSONBooleanLiteral":9,"TRUE":10,"FALSE":11,"JSONText":12,"JSONValue":13,"EOF":14,"JSONObject":15,"JSONArray":16,"{":17,"}":18,"JSONMemberList":19,"JSONMember":20,":":21,",":22,"[":23,"]":24,"JSONElementList":25,"$accept":0,"$end":1},
1499terminals_: {2:"error",4:"STRING",6:"NUMBER",8:"NULL",10:"TRUE",11:"FALSE",14:"EOF",17:"{",18:"}",21:":",22:",",23:"[",24:"]"},
1500productions_: [0,[3,1],[5,1],[7,1],[9,1],[9,1],[12,2],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[15,2],[15,3],[20,3],[19,1],[19,3],[16,2],[16,3],[25,1],[25,3]],
1501performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
1502/* this == yyval */
1503
1504var $0 = $$.length - 1;
1505switch (yystate) {
1506case 1:
1507 // replace escaped characters with actual character
1508 this.$ = yytext.replace(/\\(\\|")/g, "$"+"1")
1509 .replace(/\\n/g,'\n')
1510 .replace(/\\r/g,'\r')
1511 .replace(/\\t/g,'\t')
1512 .replace(/\\v/g,'\v')
1513 .replace(/\\f/g,'\f')
1514 .replace(/\\b/g,'\b');
1515
1516break;
1517case 2:
1518this.$ = Number(yytext);
1519break;
1520case 3:
1521this.$ = null;
1522break;
1523case 4:
1524this.$ = true;
1525break;
1526case 5:
1527this.$ = false;
1528break;
1529case 6:
1530return this.$ = $$[$0-1];
1531break;
1532case 13:
1533this.$ = {}; Object.defineProperty(this.$, '__line__', {
1534 value: this._$.first_line,
1535 enumerable: false
1536 })
1537break;
1538case 14: case 19:
1539this.$ = $$[$0-1]; Object.defineProperty(this.$, '__line__', {
1540 value: this._$.first_line,
1541 enumerable: false
1542 })
1543break;
1544case 15:
1545this.$ = [$$[$0-2], $$[$0]];
1546break;
1547case 16:
1548this.$ = {}; this.$[$$[$0][0]] = $$[$0][1];
1549break;
1550case 17:
1551
1552 this.$ = $$[$0-2];
1553 if ($$[$0-2][$$[$0][0]] !== undefined) {
1554 if (!this.$.__duplicateProperties__) {
1555 Object.defineProperty(this.$, '__duplicateProperties__', {
1556 value: [],
1557 enumerable: false
1558 });
1559 }
1560 this.$.__duplicateProperties__.push($$[$0][0]);
1561 }
1562 $$[$0-2][$$[$0][0]] = $$[$0][1];
1563
1564break;
1565case 18:
1566this.$ = []; Object.defineProperty(this.$, '__line__', {
1567 value: this._$.first_line,
1568 enumerable: false
1569 })
1570break;
1571case 20:
1572this.$ = [$$[$0]];
1573break;
1574case 21:
1575this.$ = $$[$0-2]; $$[$0-2].push($$[$0]);
1576break;
1577}
1578},
1579table: [{3:5,4:$V0,5:6,6:$V1,7:3,8:$V2,9:4,10:$V3,11:$V4,12:1,13:2,15:7,16:8,17:$V5,23:$V6},{1:[3]},{14:[1,16]},o($V7,[2,7]),o($V7,[2,8]),o($V7,[2,9]),o($V7,[2,10]),o($V7,[2,11]),o($V7,[2,12]),o($V7,[2,3]),o($V7,[2,4]),o($V7,[2,5]),o([14,18,21,22,24],[2,1]),o($V7,[2,2]),{3:20,4:$V0,18:[1,17],19:18,20:19},{3:5,4:$V0,5:6,6:$V1,7:3,8:$V2,9:4,10:$V3,11:$V4,13:23,15:7,16:8,17:$V5,23:$V6,24:[1,21],25:22},{1:[2,6]},o($V7,[2,13]),{18:[1,24],22:[1,25]},o($V8,[2,16]),{21:[1,26]},o($V7,[2,18]),{22:[1,28],24:[1,27]},o($V9,[2,20]),o($V7,[2,14]),{3:20,4:$V0,20:29},{3:5,4:$V0,5:6,6:$V1,7:3,8:$V2,9:4,10:$V3,11:$V4,13:30,15:7,16:8,17:$V5,23:$V6},o($V7,[2,19]),{3:5,4:$V0,5:6,6:$V1,7:3,8:$V2,9:4,10:$V3,11:$V4,13:31,15:7,16:8,17:$V5,23:$V6},o($V8,[2,17]),o($V8,[2,15]),o($V9,[2,21])],
1580defaultActions: {16:[2,6]},
1581parseError: function parseError(str, hash) {
1582 if (hash.recoverable) {
1583 this.trace(str);
1584 } else {
1585 function _parseError (msg, hash) {
1586 this.message = msg;
1587 this.hash = hash;
1588 }
1589 _parseError.prototype = Error;
1590
1591 throw new _parseError(str, hash);
1592 }
1593},
1594parse: function parse(input) {
1595 var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
1596 var args = lstack.slice.call(arguments, 1);
1597 var lexer = Object.create(this.lexer);
1598 var sharedState = { yy: {} };
1599 for (var k in this.yy) {
1600 if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
1601 sharedState.yy[k] = this.yy[k];
1602 }
1603 }
1604 lexer.setInput(input, sharedState.yy);
1605 sharedState.yy.lexer = lexer;
1606 sharedState.yy.parser = this;
1607 if (typeof lexer.yylloc == 'undefined') {
1608 lexer.yylloc = {};
1609 }
1610 var yyloc = lexer.yylloc;
1611 lstack.push(yyloc);
1612 var ranges = lexer.options && lexer.options.ranges;
1613 if (typeof sharedState.yy.parseError === 'function') {
1614 this.parseError = sharedState.yy.parseError;
1615 } else {
1616 this.parseError = Object.getPrototypeOf(this).parseError;
1617 }
1618 function popStack(n) {
1619 stack.length = stack.length - 2 * n;
1620 vstack.length = vstack.length - n;
1621 lstack.length = lstack.length - n;
1622 }
1623 _token_stack:
1624 var lex = function () {
1625 var token;
1626 token = lexer.lex() || EOF;
1627 if (typeof token !== 'number') {
1628 token = self.symbols_[token] || token;
1629 }
1630 return token;
1631 };
1632 var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
1633 while (true) {
1634 state = stack[stack.length - 1];
1635 if (this.defaultActions[state]) {
1636 action = this.defaultActions[state];
1637 } else {
1638 if (symbol === null || typeof symbol == 'undefined') {
1639 symbol = lex();
1640 }
1641 action = table[state] && table[state][symbol];
1642 }
1643 if (typeof action === 'undefined' || !action.length || !action[0]) {
1644 var errStr = '';
1645 expected = [];
1646 for (p in table[state]) {
1647 if (this.terminals_[p] && p > TERROR) {
1648 expected.push('\'' + this.terminals_[p] + '\'');
1649 }
1650 }
1651 if (lexer.showPosition) {
1652 errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
1653 } else {
1654 errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
1655 }
1656 this.parseError(errStr, {
1657 text: lexer.match,
1658 token: this.terminals_[symbol] || symbol,
1659 line: lexer.yylineno,
1660 loc: yyloc,
1661 expected: expected
1662 });
1663 }
1664 if (action[0] instanceof Array && action.length > 1) {
1665 throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
1666 }
1667 switch (action[0]) {
1668 case 1:
1669 stack.push(symbol);
1670 vstack.push(lexer.yytext);
1671 lstack.push(lexer.yylloc);
1672 stack.push(action[1]);
1673 symbol = null;
1674 if (!preErrorSymbol) {
1675 yyleng = lexer.yyleng;
1676 yytext = lexer.yytext;
1677 yylineno = lexer.yylineno;
1678 yyloc = lexer.yylloc;
1679 if (recovering > 0) {
1680 recovering--;
1681 }
1682 } else {
1683 symbol = preErrorSymbol;
1684 preErrorSymbol = null;
1685 }
1686 break;
1687 case 2:
1688 len = this.productions_[action[1]][1];
1689 yyval.$ = vstack[vstack.length - len];
1690 yyval._$ = {
1691 first_line: lstack[lstack.length - (len || 1)].first_line,
1692 last_line: lstack[lstack.length - 1].last_line,
1693 first_column: lstack[lstack.length - (len || 1)].first_column,
1694 last_column: lstack[lstack.length - 1].last_column
1695 };
1696 if (ranges) {
1697 yyval._$.range = [
1698 lstack[lstack.length - (len || 1)].range[0],
1699 lstack[lstack.length - 1].range[1]
1700 ];
1701 }
1702 r = this.performAction.apply(yyval, [
1703 yytext,
1704 yyleng,
1705 yylineno,
1706 sharedState.yy,
1707 action[1],
1708 vstack,
1709 lstack
1710 ].concat(args));
1711 if (typeof r !== 'undefined') {
1712 return r;
1713 }
1714 if (len) {
1715 stack = stack.slice(0, -1 * len * 2);
1716 vstack = vstack.slice(0, -1 * len);
1717 lstack = lstack.slice(0, -1 * len);
1718 }
1719 stack.push(this.productions_[action[1]][0]);
1720 vstack.push(yyval.$);
1721 lstack.push(yyval._$);
1722 newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
1723 stack.push(newState);
1724 break;
1725 case 3:
1726 return true;
1727 }
1728 }
1729 return true;
1730}};
1731/* generated by jison-lex 0.3.4 */
1732var lexer = (function(){
1733var lexer = ({
1734
1735EOF:1,
1736
1737parseError:function parseError(str, hash) {
1738 if (this.yy.parser) {
1739 this.yy.parser.parseError(str, hash);
1740 } else {
1741 throw new Error(str);
1742 }
1743 },
1744
1745// resets the lexer, sets new input
1746setInput:function (input, yy) {
1747 this.yy = yy || this.yy || {};
1748 this._input = input;
1749 this._more = this._backtrack = this.done = false;
1750 this.yylineno = this.yyleng = 0;
1751 this.yytext = this.matched = this.match = '';
1752 this.conditionStack = ['INITIAL'];
1753 this.yylloc = {
1754 first_line: 1,
1755 first_column: 0,
1756 last_line: 1,
1757 last_column: 0
1758 };
1759 if (this.options.ranges) {
1760 this.yylloc.range = [0,0];
1761 }
1762 this.offset = 0;
1763 return this;
1764 },
1765
1766// consumes and returns one char from the input
1767input:function () {
1768 var ch = this._input[0];
1769 this.yytext += ch;
1770 this.yyleng++;
1771 this.offset++;
1772 this.match += ch;
1773 this.matched += ch;
1774 var lines = ch.match(/(?:\r\n?|\n).*/g);
1775 if (lines) {
1776 this.yylineno++;
1777 this.yylloc.last_line++;
1778 } else {
1779 this.yylloc.last_column++;
1780 }
1781 if (this.options.ranges) {
1782 this.yylloc.range[1]++;
1783 }
1784
1785 this._input = this._input.slice(1);
1786 return ch;
1787 },
1788
1789// unshifts one char (or a string) into the input
1790unput:function (ch) {
1791 var len = ch.length;
1792 var lines = ch.split(/(?:\r\n?|\n)/g);
1793
1794 this._input = ch + this._input;
1795 this.yytext = this.yytext.substr(0, this.yytext.length - len);
1796 //this.yyleng -= len;
1797 this.offset -= len;
1798 var oldLines = this.match.split(/(?:\r\n?|\n)/g);
1799 this.match = this.match.substr(0, this.match.length - 1);
1800 this.matched = this.matched.substr(0, this.matched.length - 1);
1801
1802 if (lines.length - 1) {
1803 this.yylineno -= lines.length - 1;
1804 }
1805 var r = this.yylloc.range;
1806
1807 this.yylloc = {
1808 first_line: this.yylloc.first_line,
1809 last_line: this.yylineno + 1,
1810 first_column: this.yylloc.first_column,
1811 last_column: lines ?
1812 (lines.length === oldLines.length ? this.yylloc.first_column : 0)
1813 + oldLines[oldLines.length - lines.length].length - lines[0].length :
1814 this.yylloc.first_column - len
1815 };
1816
1817 if (this.options.ranges) {
1818 this.yylloc.range = [r[0], r[0] + this.yyleng - len];
1819 }
1820 this.yyleng = this.yytext.length;
1821 return this;
1822 },
1823
1824// When called from action, caches matched text and appends it on next action
1825more:function () {
1826 this._more = true;
1827 return this;
1828 },
1829
1830// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
1831reject:function () {
1832 if (this.options.backtrack_lexer) {
1833 this._backtrack = true;
1834 } else {
1835 return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
1836 text: "",
1837 token: null,
1838 line: this.yylineno
1839 });
1840
1841 }
1842 return this;
1843 },
1844
1845// retain first n characters of the match
1846less:function (n) {
1847 this.unput(this.match.slice(n));
1848 },
1849
1850// displays already matched input, i.e. for error messages
1851pastInput:function () {
1852 var past = this.matched.substr(0, this.matched.length - this.match.length);
1853 return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
1854 },
1855
1856// displays upcoming input, i.e. for error messages
1857upcomingInput:function () {
1858 var next = this.match;
1859 if (next.length < 20) {
1860 next += this._input.substr(0, 20-next.length);
1861 }
1862 return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
1863 },
1864
1865// displays the character position where the lexing error occurred, i.e. for error messages
1866showPosition:function () {
1867 var pre = this.pastInput();
1868 var c = new Array(pre.length + 1).join("-");
1869 return pre + this.upcomingInput() + "\n" + c + "^";
1870 },
1871
1872// test the lexed token: return FALSE when not a match, otherwise return token
1873test_match:function (match, indexed_rule) {
1874 var token,
1875 lines,
1876 backup;
1877
1878 if (this.options.backtrack_lexer) {
1879 // save context
1880 backup = {
1881 yylineno: this.yylineno,
1882 yylloc: {
1883 first_line: this.yylloc.first_line,
1884 last_line: this.last_line,
1885 first_column: this.yylloc.first_column,
1886 last_column: this.yylloc.last_column
1887 },
1888 yytext: this.yytext,
1889 match: this.match,
1890 matches: this.matches,
1891 matched: this.matched,
1892 yyleng: this.yyleng,
1893 offset: this.offset,
1894 _more: this._more,
1895 _input: this._input,
1896 yy: this.yy,
1897 conditionStack: this.conditionStack.slice(0),
1898 done: this.done
1899 };
1900 if (this.options.ranges) {
1901 backup.yylloc.range = this.yylloc.range.slice(0);
1902 }
1903 }
1904
1905 lines = match[0].match(/(?:\r\n?|\n).*/g);
1906 if (lines) {
1907 this.yylineno += lines.length;
1908 }
1909 this.yylloc = {
1910 first_line: this.yylloc.last_line,
1911 last_line: this.yylineno + 1,
1912 first_column: this.yylloc.last_column,
1913 last_column: lines ?
1914 lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
1915 this.yylloc.last_column + match[0].length
1916 };
1917 this.yytext += match[0];
1918 this.match += match[0];
1919 this.matches = match;
1920 this.yyleng = this.yytext.length;
1921 if (this.options.ranges) {
1922 this.yylloc.range = [this.offset, this.offset += this.yyleng];
1923 }
1924 this._more = false;
1925 this._backtrack = false;
1926 this._input = this._input.slice(match[0].length);
1927 this.matched += match[0];
1928 token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
1929 if (this.done && this._input) {
1930 this.done = false;
1931 }
1932 if (token) {
1933 return token;
1934 } else if (this._backtrack) {
1935 // recover context
1936 for (var k in backup) {
1937 this[k] = backup[k];
1938 }
1939 return false; // rule action called reject() implying the next rule should be tested instead.
1940 }
1941 return false;
1942 },
1943
1944// return next match in input
1945next:function () {
1946 if (this.done) {
1947 return this.EOF;
1948 }
1949 if (!this._input) {
1950 this.done = true;
1951 }
1952
1953 var token,
1954 match,
1955 tempMatch,
1956 index;
1957 if (!this._more) {
1958 this.yytext = '';
1959 this.match = '';
1960 }
1961 var rules = this._currentRules();
1962 for (var i = 0; i < rules.length; i++) {
1963 tempMatch = this._input.match(this.rules[rules[i]]);
1964 if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
1965 match = tempMatch;
1966 index = i;
1967 if (this.options.backtrack_lexer) {
1968 token = this.test_match(tempMatch, rules[i]);
1969 if (token !== false) {
1970 return token;
1971 } else if (this._backtrack) {
1972 match = false;
1973 continue; // rule action called reject() implying a rule MISmatch.
1974 } else {
1975 // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
1976 return false;
1977 }
1978 } else if (!this.options.flex) {
1979 break;
1980 }
1981 }
1982 }
1983 if (match) {
1984 token = this.test_match(match, rules[index]);
1985 if (token !== false) {
1986 return token;
1987 }
1988 // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
1989 return false;
1990 }
1991 if (this._input === "") {
1992 return this.EOF;
1993 } else {
1994 return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
1995 text: "",
1996 token: null,
1997 line: this.yylineno
1998 });
1999 }
2000 },
2001
2002// return next match that has a token
2003lex:function lex() {
2004 var r = this.next();
2005 if (r) {
2006 return r;
2007 } else {
2008 return this.lex();
2009 }
2010 },
2011
2012// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
2013begin:function begin(condition) {
2014 this.conditionStack.push(condition);
2015 },
2016
2017// pop the previously active lexer condition state off the condition stack
2018popState:function popState() {
2019 var n = this.conditionStack.length - 1;
2020 if (n > 0) {
2021 return this.conditionStack.pop();
2022 } else {
2023 return this.conditionStack[0];
2024 }
2025 },
2026
2027// produce the lexer rule set which is active for the currently active lexer condition state
2028_currentRules:function _currentRules() {
2029 if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
2030 return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
2031 } else {
2032 return this.conditions["INITIAL"].rules;
2033 }
2034 },
2035
2036// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
2037topState:function topState(n) {
2038 n = this.conditionStack.length - 1 - Math.abs(n || 0);
2039 if (n >= 0) {
2040 return this.conditionStack[n];
2041 } else {
2042 return "INITIAL";
2043 }
2044 },
2045
2046// alias for begin(condition)
2047pushState:function pushState(condition) {
2048 this.begin(condition);
2049 },
2050
2051// return the number of states currently on the stack
2052stateStackSize:function stateStackSize() {
2053 return this.conditionStack.length;
2054 },
2055options: {},
2056performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
2057var YYSTATE=YY_START;
2058switch($avoiding_name_collisions) {
2059case 0:/* skip whitespace */
2060break;
2061case 1:return 6
2062break;
2063case 2:yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2); return 4
2064break;
2065case 3:return 17
2066break;
2067case 4:return 18
2068break;
2069case 5:return 23
2070break;
2071case 6:return 24
2072break;
2073case 7:return 22
2074break;
2075case 8:return 21
2076break;
2077case 9:return 10
2078break;
2079case 10:return 11
2080break;
2081case 11:return 8
2082break;
2083case 12:return 14
2084break;
2085case 13:return 'INVALID'
2086break;
2087}
2088},
2089rules: [/^(?:\s+)/,/^(?:(-?([0-9]|[1-9][0-9]+))(\.[0-9]+)?([eE][-+]?[0-9]+)?\b)/,/^(?:"(?:\\[\\"bfnrt\/]|\\u[a-fA-F0-9]{4}|[^\\\0-\x09\x0a-\x1f"])*")/,/^(?:\{)/,/^(?:\})/,/^(?:\[)/,/^(?:\])/,/^(?:,)/,/^(?::)/,/^(?:true\b)/,/^(?:false\b)/,/^(?:null\b)/,/^(?:$)/,/^(?:.)/],
2090conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"inclusive":true}}
2091});
2092return lexer;
2093})();
2094parser.lexer = lexer;
2095function Parser () {
2096 this.yy = {};
2097}
2098Parser.prototype = parser;parser.Parser = Parser;
2099return new Parser;
2100})();
2101
2102
2103if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
2104exports.parser = jsonlint;
2105exports.Parser = jsonlint.Parser;
2106exports.parse = function () { return jsonlint.parse.apply(jsonlint, arguments); };
2107exports.main = function commonjsMain(args) {
2108 if (!args[1]) {
2109 console.log('Usage: '+args[0]+' FILE');
2110 process.exit(1);
2111 }
2112 var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8");
2113 return exports.parser.parse(source);
2114};
2115if (typeof module !== 'undefined' && require.main === module) {
2116 exports.main(process.argv.slice(1));
2117}
2118}
2119}).call(this,require('_process'))
2120},{"_process":3,"fs":1,"path":2}],17:[function(require,module,exports){
2121(function (global){
2122/**
2123 * Lodash (Custom Build) <https://lodash.com/>
2124 * Build: `lodash modularize exports="npm" -o ./`
2125 * Copyright JS Foundation and other contributors <https://js.foundation/>
2126 * Released under MIT license <https://lodash.com/license>
2127 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
2128 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
2129 */
2130
2131/** Used as the size to enable large array optimizations. */
2132var LARGE_ARRAY_SIZE = 200;
2133
2134/** Used to stand-in for `undefined` hash values. */
2135var HASH_UNDEFINED = '__lodash_hash_undefined__';
2136
2137/** Used to compose bitmasks for value comparisons. */
2138var COMPARE_PARTIAL_FLAG = 1,
2139 COMPARE_UNORDERED_FLAG = 2;
2140
2141/** Used as references for various `Number` constants. */
2142var MAX_SAFE_INTEGER = 9007199254740991;
2143
2144/** `Object#toString` result references. */
2145var argsTag = '[object Arguments]',
2146 arrayTag = '[object Array]',
2147 asyncTag = '[object AsyncFunction]',
2148 boolTag = '[object Boolean]',
2149 dateTag = '[object Date]',
2150 errorTag = '[object Error]',
2151 funcTag = '[object Function]',
2152 genTag = '[object GeneratorFunction]',
2153 mapTag = '[object Map]',
2154 numberTag = '[object Number]',
2155 nullTag = '[object Null]',
2156 objectTag = '[object Object]',
2157 promiseTag = '[object Promise]',
2158 proxyTag = '[object Proxy]',
2159 regexpTag = '[object RegExp]',
2160 setTag = '[object Set]',
2161 stringTag = '[object String]',
2162 symbolTag = '[object Symbol]',
2163 undefinedTag = '[object Undefined]',
2164 weakMapTag = '[object WeakMap]';
2165
2166var arrayBufferTag = '[object ArrayBuffer]',
2167 dataViewTag = '[object DataView]',
2168 float32Tag = '[object Float32Array]',
2169 float64Tag = '[object Float64Array]',
2170 int8Tag = '[object Int8Array]',
2171 int16Tag = '[object Int16Array]',
2172 int32Tag = '[object Int32Array]',
2173 uint8Tag = '[object Uint8Array]',
2174 uint8ClampedTag = '[object Uint8ClampedArray]',
2175 uint16Tag = '[object Uint16Array]',
2176 uint32Tag = '[object Uint32Array]';
2177
2178/**
2179 * Used to match `RegExp`
2180 * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
2181 */
2182var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
2183
2184/** Used to detect host constructors (Safari). */
2185var reIsHostCtor = /^\[object .+?Constructor\]$/;
2186
2187/** Used to detect unsigned integer values. */
2188var reIsUint = /^(?:0|[1-9]\d*)$/;
2189
2190/** Used to identify `toStringTag` values of typed arrays. */
2191var typedArrayTags = {};
2192typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
2193typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
2194typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
2195typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
2196typedArrayTags[uint32Tag] = true;
2197typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
2198typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
2199typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
2200typedArrayTags[errorTag] = typedArrayTags[funcTag] =
2201typedArrayTags[mapTag] = typedArrayTags[numberTag] =
2202typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
2203typedArrayTags[setTag] = typedArrayTags[stringTag] =
2204typedArrayTags[weakMapTag] = false;
2205
2206/** Detect free variable `global` from Node.js. */
2207var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
2208
2209/** Detect free variable `self`. */
2210var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
2211
2212/** Used as a reference to the global object. */
2213var root = freeGlobal || freeSelf || Function('return this')();
2214
2215/** Detect free variable `exports`. */
2216var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
2217
2218/** Detect free variable `module`. */
2219var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
2220
2221/** Detect the popular CommonJS extension `module.exports`. */
2222var moduleExports = freeModule && freeModule.exports === freeExports;
2223
2224/** Detect free variable `process` from Node.js. */
2225var freeProcess = moduleExports && freeGlobal.process;
2226
2227/** Used to access faster Node.js helpers. */
2228var nodeUtil = (function() {
2229 try {
2230 return freeProcess && freeProcess.binding && freeProcess.binding('util');
2231 } catch (e) {}
2232}());
2233
2234/* Node.js helper references. */
2235var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
2236
2237/**
2238 * A specialized version of `_.filter` for arrays without support for
2239 * iteratee shorthands.
2240 *
2241 * @private
2242 * @param {Array} [array] The array to iterate over.
2243 * @param {Function} predicate The function invoked per iteration.
2244 * @returns {Array} Returns the new filtered array.
2245 */
2246function arrayFilter(array, predicate) {
2247 var index = -1,
2248 length = array == null ? 0 : array.length,
2249 resIndex = 0,
2250 result = [];
2251
2252 while (++index < length) {
2253 var value = array[index];
2254 if (predicate(value, index, array)) {
2255 result[resIndex++] = value;
2256 }
2257 }
2258 return result;
2259}
2260
2261/**
2262 * Appends the elements of `values` to `array`.
2263 *
2264 * @private
2265 * @param {Array} array The array to modify.
2266 * @param {Array} values The values to append.
2267 * @returns {Array} Returns `array`.
2268 */
2269function arrayPush(array, values) {
2270 var index = -1,
2271 length = values.length,
2272 offset = array.length;
2273
2274 while (++index < length) {
2275 array[offset + index] = values[index];
2276 }
2277 return array;
2278}
2279
2280/**
2281 * A specialized version of `_.some` for arrays without support for iteratee
2282 * shorthands.
2283 *
2284 * @private
2285 * @param {Array} [array] The array to iterate over.
2286 * @param {Function} predicate The function invoked per iteration.
2287 * @returns {boolean} Returns `true` if any element passes the predicate check,
2288 * else `false`.
2289 */
2290function arraySome(array, predicate) {
2291 var index = -1,
2292 length = array == null ? 0 : array.length;
2293
2294 while (++index < length) {
2295 if (predicate(array[index], index, array)) {
2296 return true;
2297 }
2298 }
2299 return false;
2300}
2301
2302/**
2303 * The base implementation of `_.times` without support for iteratee shorthands
2304 * or max array length checks.
2305 *
2306 * @private
2307 * @param {number} n The number of times to invoke `iteratee`.
2308 * @param {Function} iteratee The function invoked per iteration.
2309 * @returns {Array} Returns the array of results.
2310 */
2311function baseTimes(n, iteratee) {
2312 var index = -1,
2313 result = Array(n);
2314
2315 while (++index < n) {
2316 result[index] = iteratee(index);
2317 }
2318 return result;
2319}
2320
2321/**
2322 * The base implementation of `_.unary` without support for storing metadata.
2323 *
2324 * @private
2325 * @param {Function} func The function to cap arguments for.
2326 * @returns {Function} Returns the new capped function.
2327 */
2328function baseUnary(func) {
2329 return function(value) {
2330 return func(value);
2331 };
2332}
2333
2334/**
2335 * Checks if a `cache` value for `key` exists.
2336 *
2337 * @private
2338 * @param {Object} cache The cache to query.
2339 * @param {string} key The key of the entry to check.
2340 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2341 */
2342function cacheHas(cache, key) {
2343 return cache.has(key);
2344}
2345
2346/**
2347 * Gets the value at `key` of `object`.
2348 *
2349 * @private
2350 * @param {Object} [object] The object to query.
2351 * @param {string} key The key of the property to get.
2352 * @returns {*} Returns the property value.
2353 */
2354function getValue(object, key) {
2355 return object == null ? undefined : object[key];
2356}
2357
2358/**
2359 * Converts `map` to its key-value pairs.
2360 *
2361 * @private
2362 * @param {Object} map The map to convert.
2363 * @returns {Array} Returns the key-value pairs.
2364 */
2365function mapToArray(map) {
2366 var index = -1,
2367 result = Array(map.size);
2368
2369 map.forEach(function(value, key) {
2370 result[++index] = [key, value];
2371 });
2372 return result;
2373}
2374
2375/**
2376 * Creates a unary function that invokes `func` with its argument transformed.
2377 *
2378 * @private
2379 * @param {Function} func The function to wrap.
2380 * @param {Function} transform The argument transform.
2381 * @returns {Function} Returns the new function.
2382 */
2383function overArg(func, transform) {
2384 return function(arg) {
2385 return func(transform(arg));
2386 };
2387}
2388
2389/**
2390 * Converts `set` to an array of its values.
2391 *
2392 * @private
2393 * @param {Object} set The set to convert.
2394 * @returns {Array} Returns the values.
2395 */
2396function setToArray(set) {
2397 var index = -1,
2398 result = Array(set.size);
2399
2400 set.forEach(function(value) {
2401 result[++index] = value;
2402 });
2403 return result;
2404}
2405
2406/** Used for built-in method references. */
2407var arrayProto = Array.prototype,
2408 funcProto = Function.prototype,
2409 objectProto = Object.prototype;
2410
2411/** Used to detect overreaching core-js shims. */
2412var coreJsData = root['__core-js_shared__'];
2413
2414/** Used to resolve the decompiled source of functions. */
2415var funcToString = funcProto.toString;
2416
2417/** Used to check objects for own properties. */
2418var hasOwnProperty = objectProto.hasOwnProperty;
2419
2420/** Used to detect methods masquerading as native. */
2421var maskSrcKey = (function() {
2422 var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
2423 return uid ? ('Symbol(src)_1.' + uid) : '';
2424}());
2425
2426/**
2427 * Used to resolve the
2428 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
2429 * of values.
2430 */
2431var nativeObjectToString = objectProto.toString;
2432
2433/** Used to detect if a method is native. */
2434var reIsNative = RegExp('^' +
2435 funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
2436 .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
2437);
2438
2439/** Built-in value references. */
2440var Buffer = moduleExports ? root.Buffer : undefined,
2441 Symbol = root.Symbol,
2442 Uint8Array = root.Uint8Array,
2443 propertyIsEnumerable = objectProto.propertyIsEnumerable,
2444 splice = arrayProto.splice,
2445 symToStringTag = Symbol ? Symbol.toStringTag : undefined;
2446
2447/* Built-in method references for those with the same name as other `lodash` methods. */
2448var nativeGetSymbols = Object.getOwnPropertySymbols,
2449 nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
2450 nativeKeys = overArg(Object.keys, Object);
2451
2452/* Built-in method references that are verified to be native. */
2453var DataView = getNative(root, 'DataView'),
2454 Map = getNative(root, 'Map'),
2455 Promise = getNative(root, 'Promise'),
2456 Set = getNative(root, 'Set'),
2457 WeakMap = getNative(root, 'WeakMap'),
2458 nativeCreate = getNative(Object, 'create');
2459
2460/** Used to detect maps, sets, and weakmaps. */
2461var dataViewCtorString = toSource(DataView),
2462 mapCtorString = toSource(Map),
2463 promiseCtorString = toSource(Promise),
2464 setCtorString = toSource(Set),
2465 weakMapCtorString = toSource(WeakMap);
2466
2467/** Used to convert symbols to primitives and strings. */
2468var symbolProto = Symbol ? Symbol.prototype : undefined,
2469 symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;
2470
2471/**
2472 * Creates a hash object.
2473 *
2474 * @private
2475 * @constructor
2476 * @param {Array} [entries] The key-value pairs to cache.
2477 */
2478function Hash(entries) {
2479 var index = -1,
2480 length = entries == null ? 0 : entries.length;
2481
2482 this.clear();
2483 while (++index < length) {
2484 var entry = entries[index];
2485 this.set(entry[0], entry[1]);
2486 }
2487}
2488
2489/**
2490 * Removes all key-value entries from the hash.
2491 *
2492 * @private
2493 * @name clear
2494 * @memberOf Hash
2495 */
2496function hashClear() {
2497 this.__data__ = nativeCreate ? nativeCreate(null) : {};
2498 this.size = 0;
2499}
2500
2501/**
2502 * Removes `key` and its value from the hash.
2503 *
2504 * @private
2505 * @name delete
2506 * @memberOf Hash
2507 * @param {Object} hash The hash to modify.
2508 * @param {string} key The key of the value to remove.
2509 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
2510 */
2511function hashDelete(key) {
2512 var result = this.has(key) && delete this.__data__[key];
2513 this.size -= result ? 1 : 0;
2514 return result;
2515}
2516
2517/**
2518 * Gets the hash value for `key`.
2519 *
2520 * @private
2521 * @name get
2522 * @memberOf Hash
2523 * @param {string} key The key of the value to get.
2524 * @returns {*} Returns the entry value.
2525 */
2526function hashGet(key) {
2527 var data = this.__data__;
2528 if (nativeCreate) {
2529 var result = data[key];
2530 return result === HASH_UNDEFINED ? undefined : result;
2531 }
2532 return hasOwnProperty.call(data, key) ? data[key] : undefined;
2533}
2534
2535/**
2536 * Checks if a hash value for `key` exists.
2537 *
2538 * @private
2539 * @name has
2540 * @memberOf Hash
2541 * @param {string} key The key of the entry to check.
2542 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2543 */
2544function hashHas(key) {
2545 var data = this.__data__;
2546 return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);
2547}
2548
2549/**
2550 * Sets the hash `key` to `value`.
2551 *
2552 * @private
2553 * @name set
2554 * @memberOf Hash
2555 * @param {string} key The key of the value to set.
2556 * @param {*} value The value to set.
2557 * @returns {Object} Returns the hash instance.
2558 */
2559function hashSet(key, value) {
2560 var data = this.__data__;
2561 this.size += this.has(key) ? 0 : 1;
2562 data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
2563 return this;
2564}
2565
2566// Add methods to `Hash`.
2567Hash.prototype.clear = hashClear;
2568Hash.prototype['delete'] = hashDelete;
2569Hash.prototype.get = hashGet;
2570Hash.prototype.has = hashHas;
2571Hash.prototype.set = hashSet;
2572
2573/**
2574 * Creates an list cache object.
2575 *
2576 * @private
2577 * @constructor
2578 * @param {Array} [entries] The key-value pairs to cache.
2579 */
2580function ListCache(entries) {
2581 var index = -1,
2582 length = entries == null ? 0 : entries.length;
2583
2584 this.clear();
2585 while (++index < length) {
2586 var entry = entries[index];
2587 this.set(entry[0], entry[1]);
2588 }
2589}
2590
2591/**
2592 * Removes all key-value entries from the list cache.
2593 *
2594 * @private
2595 * @name clear
2596 * @memberOf ListCache
2597 */
2598function listCacheClear() {
2599 this.__data__ = [];
2600 this.size = 0;
2601}
2602
2603/**
2604 * Removes `key` and its value from the list cache.
2605 *
2606 * @private
2607 * @name delete
2608 * @memberOf ListCache
2609 * @param {string} key The key of the value to remove.
2610 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
2611 */
2612function listCacheDelete(key) {
2613 var data = this.__data__,
2614 index = assocIndexOf(data, key);
2615
2616 if (index < 0) {
2617 return false;
2618 }
2619 var lastIndex = data.length - 1;
2620 if (index == lastIndex) {
2621 data.pop();
2622 } else {
2623 splice.call(data, index, 1);
2624 }
2625 --this.size;
2626 return true;
2627}
2628
2629/**
2630 * Gets the list cache value for `key`.
2631 *
2632 * @private
2633 * @name get
2634 * @memberOf ListCache
2635 * @param {string} key The key of the value to get.
2636 * @returns {*} Returns the entry value.
2637 */
2638function listCacheGet(key) {
2639 var data = this.__data__,
2640 index = assocIndexOf(data, key);
2641
2642 return index < 0 ? undefined : data[index][1];
2643}
2644
2645/**
2646 * Checks if a list cache value for `key` exists.
2647 *
2648 * @private
2649 * @name has
2650 * @memberOf ListCache
2651 * @param {string} key The key of the entry to check.
2652 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2653 */
2654function listCacheHas(key) {
2655 return assocIndexOf(this.__data__, key) > -1;
2656}
2657
2658/**
2659 * Sets the list cache `key` to `value`.
2660 *
2661 * @private
2662 * @name set
2663 * @memberOf ListCache
2664 * @param {string} key The key of the value to set.
2665 * @param {*} value The value to set.
2666 * @returns {Object} Returns the list cache instance.
2667 */
2668function listCacheSet(key, value) {
2669 var data = this.__data__,
2670 index = assocIndexOf(data, key);
2671
2672 if (index < 0) {
2673 ++this.size;
2674 data.push([key, value]);
2675 } else {
2676 data[index][1] = value;
2677 }
2678 return this;
2679}
2680
2681// Add methods to `ListCache`.
2682ListCache.prototype.clear = listCacheClear;
2683ListCache.prototype['delete'] = listCacheDelete;
2684ListCache.prototype.get = listCacheGet;
2685ListCache.prototype.has = listCacheHas;
2686ListCache.prototype.set = listCacheSet;
2687
2688/**
2689 * Creates a map cache object to store key-value pairs.
2690 *
2691 * @private
2692 * @constructor
2693 * @param {Array} [entries] The key-value pairs to cache.
2694 */
2695function MapCache(entries) {
2696 var index = -1,
2697 length = entries == null ? 0 : entries.length;
2698
2699 this.clear();
2700 while (++index < length) {
2701 var entry = entries[index];
2702 this.set(entry[0], entry[1]);
2703 }
2704}
2705
2706/**
2707 * Removes all key-value entries from the map.
2708 *
2709 * @private
2710 * @name clear
2711 * @memberOf MapCache
2712 */
2713function mapCacheClear() {
2714 this.size = 0;
2715 this.__data__ = {
2716 'hash': new Hash,
2717 'map': new (Map || ListCache),
2718 'string': new Hash
2719 };
2720}
2721
2722/**
2723 * Removes `key` and its value from the map.
2724 *
2725 * @private
2726 * @name delete
2727 * @memberOf MapCache
2728 * @param {string} key The key of the value to remove.
2729 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
2730 */
2731function mapCacheDelete(key) {
2732 var result = getMapData(this, key)['delete'](key);
2733 this.size -= result ? 1 : 0;
2734 return result;
2735}
2736
2737/**
2738 * Gets the map value for `key`.
2739 *
2740 * @private
2741 * @name get
2742 * @memberOf MapCache
2743 * @param {string} key The key of the value to get.
2744 * @returns {*} Returns the entry value.
2745 */
2746function mapCacheGet(key) {
2747 return getMapData(this, key).get(key);
2748}
2749
2750/**
2751 * Checks if a map value for `key` exists.
2752 *
2753 * @private
2754 * @name has
2755 * @memberOf MapCache
2756 * @param {string} key The key of the entry to check.
2757 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2758 */
2759function mapCacheHas(key) {
2760 return getMapData(this, key).has(key);
2761}
2762
2763/**
2764 * Sets the map `key` to `value`.
2765 *
2766 * @private
2767 * @name set
2768 * @memberOf MapCache
2769 * @param {string} key The key of the value to set.
2770 * @param {*} value The value to set.
2771 * @returns {Object} Returns the map cache instance.
2772 */
2773function mapCacheSet(key, value) {
2774 var data = getMapData(this, key),
2775 size = data.size;
2776
2777 data.set(key, value);
2778 this.size += data.size == size ? 0 : 1;
2779 return this;
2780}
2781
2782// Add methods to `MapCache`.
2783MapCache.prototype.clear = mapCacheClear;
2784MapCache.prototype['delete'] = mapCacheDelete;
2785MapCache.prototype.get = mapCacheGet;
2786MapCache.prototype.has = mapCacheHas;
2787MapCache.prototype.set = mapCacheSet;
2788
2789/**
2790 *
2791 * Creates an array cache object to store unique values.
2792 *
2793 * @private
2794 * @constructor
2795 * @param {Array} [values] The values to cache.
2796 */
2797function SetCache(values) {
2798 var index = -1,
2799 length = values == null ? 0 : values.length;
2800
2801 this.__data__ = new MapCache;
2802 while (++index < length) {
2803 this.add(values[index]);
2804 }
2805}
2806
2807/**
2808 * Adds `value` to the array cache.
2809 *
2810 * @private
2811 * @name add
2812 * @memberOf SetCache
2813 * @alias push
2814 * @param {*} value The value to cache.
2815 * @returns {Object} Returns the cache instance.
2816 */
2817function setCacheAdd(value) {
2818 this.__data__.set(value, HASH_UNDEFINED);
2819 return this;
2820}
2821
2822/**
2823 * Checks if `value` is in the array cache.
2824 *
2825 * @private
2826 * @name has
2827 * @memberOf SetCache
2828 * @param {*} value The value to search for.
2829 * @returns {number} Returns `true` if `value` is found, else `false`.
2830 */
2831function setCacheHas(value) {
2832 return this.__data__.has(value);
2833}
2834
2835// Add methods to `SetCache`.
2836SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
2837SetCache.prototype.has = setCacheHas;
2838
2839/**
2840 * Creates a stack cache object to store key-value pairs.
2841 *
2842 * @private
2843 * @constructor
2844 * @param {Array} [entries] The key-value pairs to cache.
2845 */
2846function Stack(entries) {
2847 var data = this.__data__ = new ListCache(entries);
2848 this.size = data.size;
2849}
2850
2851/**
2852 * Removes all key-value entries from the stack.
2853 *
2854 * @private
2855 * @name clear
2856 * @memberOf Stack
2857 */
2858function stackClear() {
2859 this.__data__ = new ListCache;
2860 this.size = 0;
2861}
2862
2863/**
2864 * Removes `key` and its value from the stack.
2865 *
2866 * @private
2867 * @name delete
2868 * @memberOf Stack
2869 * @param {string} key The key of the value to remove.
2870 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
2871 */
2872function stackDelete(key) {
2873 var data = this.__data__,
2874 result = data['delete'](key);
2875
2876 this.size = data.size;
2877 return result;
2878}
2879
2880/**
2881 * Gets the stack value for `key`.
2882 *
2883 * @private
2884 * @name get
2885 * @memberOf Stack
2886 * @param {string} key The key of the value to get.
2887 * @returns {*} Returns the entry value.
2888 */
2889function stackGet(key) {
2890 return this.__data__.get(key);
2891}
2892
2893/**
2894 * Checks if a stack value for `key` exists.
2895 *
2896 * @private
2897 * @name has
2898 * @memberOf Stack
2899 * @param {string} key The key of the entry to check.
2900 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2901 */
2902function stackHas(key) {
2903 return this.__data__.has(key);
2904}
2905
2906/**
2907 * Sets the stack `key` to `value`.
2908 *
2909 * @private
2910 * @name set
2911 * @memberOf Stack
2912 * @param {string} key The key of the value to set.
2913 * @param {*} value The value to set.
2914 * @returns {Object} Returns the stack cache instance.
2915 */
2916function stackSet(key, value) {
2917 var data = this.__data__;
2918 if (data instanceof ListCache) {
2919 var pairs = data.__data__;
2920 if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
2921 pairs.push([key, value]);
2922 this.size = ++data.size;
2923 return this;
2924 }
2925 data = this.__data__ = new MapCache(pairs);
2926 }
2927 data.set(key, value);
2928 this.size = data.size;
2929 return this;
2930}
2931
2932// Add methods to `Stack`.
2933Stack.prototype.clear = stackClear;
2934Stack.prototype['delete'] = stackDelete;
2935Stack.prototype.get = stackGet;
2936Stack.prototype.has = stackHas;
2937Stack.prototype.set = stackSet;
2938
2939/**
2940 * Creates an array of the enumerable property names of the array-like `value`.
2941 *
2942 * @private
2943 * @param {*} value The value to query.
2944 * @param {boolean} inherited Specify returning inherited property names.
2945 * @returns {Array} Returns the array of property names.
2946 */
2947function arrayLikeKeys(value, inherited) {
2948 var isArr = isArray(value),
2949 isArg = !isArr && isArguments(value),
2950 isBuff = !isArr && !isArg && isBuffer(value),
2951 isType = !isArr && !isArg && !isBuff && isTypedArray(value),
2952 skipIndexes = isArr || isArg || isBuff || isType,
2953 result = skipIndexes ? baseTimes(value.length, String) : [],
2954 length = result.length;
2955
2956 for (var key in value) {
2957 if ((inherited || hasOwnProperty.call(value, key)) &&
2958 !(skipIndexes && (
2959 // Safari 9 has enumerable `arguments.length` in strict mode.
2960 key == 'length' ||
2961 // Node.js 0.10 has enumerable non-index properties on buffers.
2962 (isBuff && (key == 'offset' || key == 'parent')) ||
2963 // PhantomJS 2 has enumerable non-index properties on typed arrays.
2964 (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
2965 // Skip index properties.
2966 isIndex(key, length)
2967 ))) {
2968 result.push(key);
2969 }
2970 }
2971 return result;
2972}
2973
2974/**
2975 * Gets the index at which the `key` is found in `array` of key-value pairs.
2976 *
2977 * @private
2978 * @param {Array} array The array to inspect.
2979 * @param {*} key The key to search for.
2980 * @returns {number} Returns the index of the matched value, else `-1`.
2981 */
2982function assocIndexOf(array, key) {
2983 var length = array.length;
2984 while (length--) {
2985 if (eq(array[length][0], key)) {
2986 return length;
2987 }
2988 }
2989 return -1;
2990}
2991
2992/**
2993 * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
2994 * `keysFunc` and `symbolsFunc` to get the enumerable property names and
2995 * symbols of `object`.
2996 *
2997 * @private
2998 * @param {Object} object The object to query.
2999 * @param {Function} keysFunc The function to get the keys of `object`.
3000 * @param {Function} symbolsFunc The function to get the symbols of `object`.
3001 * @returns {Array} Returns the array of property names and symbols.
3002 */
3003function baseGetAllKeys(object, keysFunc, symbolsFunc) {
3004 var result = keysFunc(object);
3005 return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
3006}
3007
3008/**
3009 * The base implementation of `getTag` without fallbacks for buggy environments.
3010 *
3011 * @private
3012 * @param {*} value The value to query.
3013 * @returns {string} Returns the `toStringTag`.
3014 */
3015function baseGetTag(value) {
3016 if (value == null) {
3017 return value === undefined ? undefinedTag : nullTag;
3018 }
3019 return (symToStringTag && symToStringTag in Object(value))
3020 ? getRawTag(value)
3021 : objectToString(value);
3022}
3023
3024/**
3025 * The base implementation of `_.isArguments`.
3026 *
3027 * @private
3028 * @param {*} value The value to check.
3029 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
3030 */
3031function baseIsArguments(value) {
3032 return isObjectLike(value) && baseGetTag(value) == argsTag;
3033}
3034
3035/**
3036 * The base implementation of `_.isEqual` which supports partial comparisons
3037 * and tracks traversed objects.
3038 *
3039 * @private
3040 * @param {*} value The value to compare.
3041 * @param {*} other The other value to compare.
3042 * @param {boolean} bitmask The bitmask flags.
3043 * 1 - Unordered comparison
3044 * 2 - Partial comparison
3045 * @param {Function} [customizer] The function to customize comparisons.
3046 * @param {Object} [stack] Tracks traversed `value` and `other` objects.
3047 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
3048 */
3049function baseIsEqual(value, other, bitmask, customizer, stack) {
3050 if (value === other) {
3051 return true;
3052 }
3053 if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
3054 return value !== value && other !== other;
3055 }
3056 return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
3057}
3058
3059/**
3060 * A specialized version of `baseIsEqual` for arrays and objects which performs
3061 * deep comparisons and tracks traversed objects enabling objects with circular
3062 * references to be compared.
3063 *
3064 * @private
3065 * @param {Object} object The object to compare.
3066 * @param {Object} other The other object to compare.
3067 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
3068 * @param {Function} customizer The function to customize comparisons.
3069 * @param {Function} equalFunc The function to determine equivalents of values.
3070 * @param {Object} [stack] Tracks traversed `object` and `other` objects.
3071 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
3072 */
3073function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
3074 var objIsArr = isArray(object),
3075 othIsArr = isArray(other),
3076 objTag = objIsArr ? arrayTag : getTag(object),
3077 othTag = othIsArr ? arrayTag : getTag(other);
3078
3079 objTag = objTag == argsTag ? objectTag : objTag;
3080 othTag = othTag == argsTag ? objectTag : othTag;
3081
3082 var objIsObj = objTag == objectTag,
3083 othIsObj = othTag == objectTag,
3084 isSameTag = objTag == othTag;
3085
3086 if (isSameTag && isBuffer(object)) {
3087 if (!isBuffer(other)) {
3088 return false;
3089 }
3090 objIsArr = true;
3091 objIsObj = false;
3092 }
3093 if (isSameTag && !objIsObj) {
3094 stack || (stack = new Stack);
3095 return (objIsArr || isTypedArray(object))
3096 ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
3097 : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
3098 }
3099 if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
3100 var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
3101 othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
3102
3103 if (objIsWrapped || othIsWrapped) {
3104 var objUnwrapped = objIsWrapped ? object.value() : object,
3105 othUnwrapped = othIsWrapped ? other.value() : other;
3106
3107 stack || (stack = new Stack);
3108 return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
3109 }
3110 }
3111 if (!isSameTag) {
3112 return false;
3113 }
3114 stack || (stack = new Stack);
3115 return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
3116}
3117
3118/**
3119 * The base implementation of `_.isNative` without bad shim checks.
3120 *
3121 * @private
3122 * @param {*} value The value to check.
3123 * @returns {boolean} Returns `true` if `value` is a native function,
3124 * else `false`.
3125 */
3126function baseIsNative(value) {
3127 if (!isObject(value) || isMasked(value)) {
3128 return false;
3129 }
3130 var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
3131 return pattern.test(toSource(value));
3132}
3133
3134/**
3135 * The base implementation of `_.isTypedArray` without Node.js optimizations.
3136 *
3137 * @private
3138 * @param {*} value The value to check.
3139 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
3140 */
3141function baseIsTypedArray(value) {
3142 return isObjectLike(value) &&
3143 isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
3144}
3145
3146/**
3147 * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
3148 *
3149 * @private
3150 * @param {Object} object The object to query.
3151 * @returns {Array} Returns the array of property names.
3152 */
3153function baseKeys(object) {
3154 if (!isPrototype(object)) {
3155 return nativeKeys(object);
3156 }
3157 var result = [];
3158 for (var key in Object(object)) {
3159 if (hasOwnProperty.call(object, key) && key != 'constructor') {
3160 result.push(key);
3161 }
3162 }
3163 return result;
3164}
3165
3166/**
3167 * A specialized version of `baseIsEqualDeep` for arrays with support for
3168 * partial deep comparisons.
3169 *
3170 * @private
3171 * @param {Array} array The array to compare.
3172 * @param {Array} other The other array to compare.
3173 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
3174 * @param {Function} customizer The function to customize comparisons.
3175 * @param {Function} equalFunc The function to determine equivalents of values.
3176 * @param {Object} stack Tracks traversed `array` and `other` objects.
3177 * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
3178 */
3179function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
3180 var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
3181 arrLength = array.length,
3182 othLength = other.length;
3183
3184 if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
3185 return false;
3186 }
3187 // Assume cyclic values are equal.
3188 var stacked = stack.get(array);
3189 if (stacked && stack.get(other)) {
3190 return stacked == other;
3191 }
3192 var index = -1,
3193 result = true,
3194 seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;
3195
3196 stack.set(array, other);
3197 stack.set(other, array);
3198
3199 // Ignore non-index properties.
3200 while (++index < arrLength) {
3201 var arrValue = array[index],
3202 othValue = other[index];
3203
3204 if (customizer) {
3205 var compared = isPartial
3206 ? customizer(othValue, arrValue, index, other, array, stack)
3207 : customizer(arrValue, othValue, index, array, other, stack);
3208 }
3209 if (compared !== undefined) {
3210 if (compared) {
3211 continue;
3212 }
3213 result = false;
3214 break;
3215 }
3216 // Recursively compare arrays (susceptible to call stack limits).
3217 if (seen) {
3218 if (!arraySome(other, function(othValue, othIndex) {
3219 if (!cacheHas(seen, othIndex) &&
3220 (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
3221 return seen.push(othIndex);
3222 }
3223 })) {
3224 result = false;
3225 break;
3226 }
3227 } else if (!(
3228 arrValue === othValue ||
3229 equalFunc(arrValue, othValue, bitmask, customizer, stack)
3230 )) {
3231 result = false;
3232 break;
3233 }
3234 }
3235 stack['delete'](array);
3236 stack['delete'](other);
3237 return result;
3238}
3239
3240/**
3241 * A specialized version of `baseIsEqualDeep` for comparing objects of
3242 * the same `toStringTag`.
3243 *
3244 * **Note:** This function only supports comparing values with tags of
3245 * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
3246 *
3247 * @private
3248 * @param {Object} object The object to compare.
3249 * @param {Object} other The other object to compare.
3250 * @param {string} tag The `toStringTag` of the objects to compare.
3251 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
3252 * @param {Function} customizer The function to customize comparisons.
3253 * @param {Function} equalFunc The function to determine equivalents of values.
3254 * @param {Object} stack Tracks traversed `object` and `other` objects.
3255 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
3256 */
3257function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
3258 switch (tag) {
3259 case dataViewTag:
3260 if ((object.byteLength != other.byteLength) ||
3261 (object.byteOffset != other.byteOffset)) {
3262 return false;
3263 }
3264 object = object.buffer;
3265 other = other.buffer;
3266
3267 case arrayBufferTag:
3268 if ((object.byteLength != other.byteLength) ||
3269 !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
3270 return false;
3271 }
3272 return true;
3273
3274 case boolTag:
3275 case dateTag:
3276 case numberTag:
3277 // Coerce booleans to `1` or `0` and dates to milliseconds.
3278 // Invalid dates are coerced to `NaN`.
3279 return eq(+object, +other);
3280
3281 case errorTag:
3282 return object.name == other.name && object.message == other.message;
3283
3284 case regexpTag:
3285 case stringTag:
3286 // Coerce regexes to strings and treat strings, primitives and objects,
3287 // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
3288 // for more details.
3289 return object == (other + '');
3290
3291 case mapTag:
3292 var convert = mapToArray;
3293
3294 case setTag:
3295 var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
3296 convert || (convert = setToArray);
3297
3298 if (object.size != other.size && !isPartial) {
3299 return false;
3300 }
3301 // Assume cyclic values are equal.
3302 var stacked = stack.get(object);
3303 if (stacked) {
3304 return stacked == other;
3305 }
3306 bitmask |= COMPARE_UNORDERED_FLAG;
3307
3308 // Recursively compare objects (susceptible to call stack limits).
3309 stack.set(object, other);
3310 var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
3311 stack['delete'](object);
3312 return result;
3313
3314 case symbolTag:
3315 if (symbolValueOf) {
3316 return symbolValueOf.call(object) == symbolValueOf.call(other);
3317 }
3318 }
3319 return false;
3320}
3321
3322/**
3323 * A specialized version of `baseIsEqualDeep` for objects with support for
3324 * partial deep comparisons.
3325 *
3326 * @private
3327 * @param {Object} object The object to compare.
3328 * @param {Object} other The other object to compare.
3329 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
3330 * @param {Function} customizer The function to customize comparisons.
3331 * @param {Function} equalFunc The function to determine equivalents of values.
3332 * @param {Object} stack Tracks traversed `object` and `other` objects.
3333 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
3334 */
3335function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
3336 var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
3337 objProps = getAllKeys(object),
3338 objLength = objProps.length,
3339 othProps = getAllKeys(other),
3340 othLength = othProps.length;
3341
3342 if (objLength != othLength && !isPartial) {
3343 return false;
3344 }
3345 var index = objLength;
3346 while (index--) {
3347 var key = objProps[index];
3348 if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
3349 return false;
3350 }
3351 }
3352 // Assume cyclic values are equal.
3353 var stacked = stack.get(object);
3354 if (stacked && stack.get(other)) {
3355 return stacked == other;
3356 }
3357 var result = true;
3358 stack.set(object, other);
3359 stack.set(other, object);
3360
3361 var skipCtor = isPartial;
3362 while (++index < objLength) {
3363 key = objProps[index];
3364 var objValue = object[key],
3365 othValue = other[key];
3366
3367 if (customizer) {
3368 var compared = isPartial
3369 ? customizer(othValue, objValue, key, other, object, stack)
3370 : customizer(objValue, othValue, key, object, other, stack);
3371 }
3372 // Recursively compare objects (susceptible to call stack limits).
3373 if (!(compared === undefined
3374 ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
3375 : compared
3376 )) {
3377 result = false;
3378 break;
3379 }
3380 skipCtor || (skipCtor = key == 'constructor');
3381 }
3382 if (result && !skipCtor) {
3383 var objCtor = object.constructor,
3384 othCtor = other.constructor;
3385
3386 // Non `Object` object instances with different constructors are not equal.
3387 if (objCtor != othCtor &&
3388 ('constructor' in object && 'constructor' in other) &&
3389 !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
3390 typeof othCtor == 'function' && othCtor instanceof othCtor)) {
3391 result = false;
3392 }
3393 }
3394 stack['delete'](object);
3395 stack['delete'](other);
3396 return result;
3397}
3398
3399/**
3400 * Creates an array of own enumerable property names and symbols of `object`.
3401 *
3402 * @private
3403 * @param {Object} object The object to query.
3404 * @returns {Array} Returns the array of property names and symbols.
3405 */
3406function getAllKeys(object) {
3407 return baseGetAllKeys(object, keys, getSymbols);
3408}
3409
3410/**
3411 * Gets the data for `map`.
3412 *
3413 * @private
3414 * @param {Object} map The map to query.
3415 * @param {string} key The reference key.
3416 * @returns {*} Returns the map data.
3417 */
3418function getMapData(map, key) {
3419 var data = map.__data__;
3420 return isKeyable(key)
3421 ? data[typeof key == 'string' ? 'string' : 'hash']
3422 : data.map;
3423}
3424
3425/**
3426 * Gets the native function at `key` of `object`.
3427 *
3428 * @private
3429 * @param {Object} object The object to query.
3430 * @param {string} key The key of the method to get.
3431 * @returns {*} Returns the function if it's native, else `undefined`.
3432 */
3433function getNative(object, key) {
3434 var value = getValue(object, key);
3435 return baseIsNative(value) ? value : undefined;
3436}
3437
3438/**
3439 * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
3440 *
3441 * @private
3442 * @param {*} value The value to query.
3443 * @returns {string} Returns the raw `toStringTag`.
3444 */
3445function getRawTag(value) {
3446 var isOwn = hasOwnProperty.call(value, symToStringTag),
3447 tag = value[symToStringTag];
3448
3449 try {
3450 value[symToStringTag] = undefined;
3451 var unmasked = true;
3452 } catch (e) {}
3453
3454 var result = nativeObjectToString.call(value);
3455 if (unmasked) {
3456 if (isOwn) {
3457 value[symToStringTag] = tag;
3458 } else {
3459 delete value[symToStringTag];
3460 }
3461 }
3462 return result;
3463}
3464
3465/**
3466 * Creates an array of the own enumerable symbols of `object`.
3467 *
3468 * @private
3469 * @param {Object} object The object to query.
3470 * @returns {Array} Returns the array of symbols.
3471 */
3472var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
3473 if (object == null) {
3474 return [];
3475 }
3476 object = Object(object);
3477 return arrayFilter(nativeGetSymbols(object), function(symbol) {
3478 return propertyIsEnumerable.call(object, symbol);
3479 });
3480};
3481
3482/**
3483 * Gets the `toStringTag` of `value`.
3484 *
3485 * @private
3486 * @param {*} value The value to query.
3487 * @returns {string} Returns the `toStringTag`.
3488 */
3489var getTag = baseGetTag;
3490
3491// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
3492if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
3493 (Map && getTag(new Map) != mapTag) ||
3494 (Promise && getTag(Promise.resolve()) != promiseTag) ||
3495 (Set && getTag(new Set) != setTag) ||
3496 (WeakMap && getTag(new WeakMap) != weakMapTag)) {
3497 getTag = function(value) {
3498 var result = baseGetTag(value),
3499 Ctor = result == objectTag ? value.constructor : undefined,
3500 ctorString = Ctor ? toSource(Ctor) : '';
3501
3502 if (ctorString) {
3503 switch (ctorString) {
3504 case dataViewCtorString: return dataViewTag;
3505 case mapCtorString: return mapTag;
3506 case promiseCtorString: return promiseTag;
3507 case setCtorString: return setTag;
3508 case weakMapCtorString: return weakMapTag;
3509 }
3510 }
3511 return result;
3512 };
3513}
3514
3515/**
3516 * Checks if `value` is a valid array-like index.
3517 *
3518 * @private
3519 * @param {*} value The value to check.
3520 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
3521 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
3522 */
3523function isIndex(value, length) {
3524 length = length == null ? MAX_SAFE_INTEGER : length;
3525 return !!length &&
3526 (typeof value == 'number' || reIsUint.test(value)) &&
3527 (value > -1 && value % 1 == 0 && value < length);
3528}
3529
3530/**
3531 * Checks if `value` is suitable for use as unique object key.
3532 *
3533 * @private
3534 * @param {*} value The value to check.
3535 * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
3536 */
3537function isKeyable(value) {
3538 var type = typeof value;
3539 return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
3540 ? (value !== '__proto__')
3541 : (value === null);
3542}
3543
3544/**
3545 * Checks if `func` has its source masked.
3546 *
3547 * @private
3548 * @param {Function} func The function to check.
3549 * @returns {boolean} Returns `true` if `func` is masked, else `false`.
3550 */
3551function isMasked(func) {
3552 return !!maskSrcKey && (maskSrcKey in func);
3553}
3554
3555/**
3556 * Checks if `value` is likely a prototype object.
3557 *
3558 * @private
3559 * @param {*} value The value to check.
3560 * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
3561 */
3562function isPrototype(value) {
3563 var Ctor = value && value.constructor,
3564 proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
3565
3566 return value === proto;
3567}
3568
3569/**
3570 * Converts `value` to a string using `Object.prototype.toString`.
3571 *
3572 * @private
3573 * @param {*} value The value to convert.
3574 * @returns {string} Returns the converted string.
3575 */
3576function objectToString(value) {
3577 return nativeObjectToString.call(value);
3578}
3579
3580/**
3581 * Converts `func` to its source code.
3582 *
3583 * @private
3584 * @param {Function} func The function to convert.
3585 * @returns {string} Returns the source code.
3586 */
3587function toSource(func) {
3588 if (func != null) {
3589 try {
3590 return funcToString.call(func);
3591 } catch (e) {}
3592 try {
3593 return (func + '');
3594 } catch (e) {}
3595 }
3596 return '';
3597}
3598
3599/**
3600 * Performs a
3601 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
3602 * comparison between two values to determine if they are equivalent.
3603 *
3604 * @static
3605 * @memberOf _
3606 * @since 4.0.0
3607 * @category Lang
3608 * @param {*} value The value to compare.
3609 * @param {*} other The other value to compare.
3610 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
3611 * @example
3612 *
3613 * var object = { 'a': 1 };
3614 * var other = { 'a': 1 };
3615 *
3616 * _.eq(object, object);
3617 * // => true
3618 *
3619 * _.eq(object, other);
3620 * // => false
3621 *
3622 * _.eq('a', 'a');
3623 * // => true
3624 *
3625 * _.eq('a', Object('a'));
3626 * // => false
3627 *
3628 * _.eq(NaN, NaN);
3629 * // => true
3630 */
3631function eq(value, other) {
3632 return value === other || (value !== value && other !== other);
3633}
3634
3635/**
3636 * Checks if `value` is likely an `arguments` object.
3637 *
3638 * @static
3639 * @memberOf _
3640 * @since 0.1.0
3641 * @category Lang
3642 * @param {*} value The value to check.
3643 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
3644 * else `false`.
3645 * @example
3646 *
3647 * _.isArguments(function() { return arguments; }());
3648 * // => true
3649 *
3650 * _.isArguments([1, 2, 3]);
3651 * // => false
3652 */
3653var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
3654 return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
3655 !propertyIsEnumerable.call(value, 'callee');
3656};
3657
3658/**
3659 * Checks if `value` is classified as an `Array` object.
3660 *
3661 * @static
3662 * @memberOf _
3663 * @since 0.1.0
3664 * @category Lang
3665 * @param {*} value The value to check.
3666 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
3667 * @example
3668 *
3669 * _.isArray([1, 2, 3]);
3670 * // => true
3671 *
3672 * _.isArray(document.body.children);
3673 * // => false
3674 *
3675 * _.isArray('abc');
3676 * // => false
3677 *
3678 * _.isArray(_.noop);
3679 * // => false
3680 */
3681var isArray = Array.isArray;
3682
3683/**
3684 * Checks if `value` is array-like. A value is considered array-like if it's
3685 * not a function and has a `value.length` that's an integer greater than or
3686 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
3687 *
3688 * @static
3689 * @memberOf _
3690 * @since 4.0.0
3691 * @category Lang
3692 * @param {*} value The value to check.
3693 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
3694 * @example
3695 *
3696 * _.isArrayLike([1, 2, 3]);
3697 * // => true
3698 *
3699 * _.isArrayLike(document.body.children);
3700 * // => true
3701 *
3702 * _.isArrayLike('abc');
3703 * // => true
3704 *
3705 * _.isArrayLike(_.noop);
3706 * // => false
3707 */
3708function isArrayLike(value) {
3709 return value != null && isLength(value.length) && !isFunction(value);
3710}
3711
3712/**
3713 * Checks if `value` is a buffer.
3714 *
3715 * @static
3716 * @memberOf _
3717 * @since 4.3.0
3718 * @category Lang
3719 * @param {*} value The value to check.
3720 * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
3721 * @example
3722 *
3723 * _.isBuffer(new Buffer(2));
3724 * // => true
3725 *
3726 * _.isBuffer(new Uint8Array(2));
3727 * // => false
3728 */
3729var isBuffer = nativeIsBuffer || stubFalse;
3730
3731/**
3732 * Performs a deep comparison between two values to determine if they are
3733 * equivalent.
3734 *
3735 * **Note:** This method supports comparing arrays, array buffers, booleans,
3736 * date objects, error objects, maps, numbers, `Object` objects, regexes,
3737 * sets, strings, symbols, and typed arrays. `Object` objects are compared
3738 * by their own, not inherited, enumerable properties. Functions and DOM
3739 * nodes are compared by strict equality, i.e. `===`.
3740 *
3741 * @static
3742 * @memberOf _
3743 * @since 0.1.0
3744 * @category Lang
3745 * @param {*} value The value to compare.
3746 * @param {*} other The other value to compare.
3747 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
3748 * @example
3749 *
3750 * var object = { 'a': 1 };
3751 * var other = { 'a': 1 };
3752 *
3753 * _.isEqual(object, other);
3754 * // => true
3755 *
3756 * object === other;
3757 * // => false
3758 */
3759function isEqual(value, other) {
3760 return baseIsEqual(value, other);
3761}
3762
3763/**
3764 * Checks if `value` is classified as a `Function` object.
3765 *
3766 * @static
3767 * @memberOf _
3768 * @since 0.1.0
3769 * @category Lang
3770 * @param {*} value The value to check.
3771 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
3772 * @example
3773 *
3774 * _.isFunction(_);
3775 * // => true
3776 *
3777 * _.isFunction(/abc/);
3778 * // => false
3779 */
3780function isFunction(value) {
3781 if (!isObject(value)) {
3782 return false;
3783 }
3784 // The use of `Object#toString` avoids issues with the `typeof` operator
3785 // in Safari 9 which returns 'object' for typed arrays and other constructors.
3786 var tag = baseGetTag(value);
3787 return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
3788}
3789
3790/**
3791 * Checks if `value` is a valid array-like length.
3792 *
3793 * **Note:** This method is loosely based on
3794 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
3795 *
3796 * @static
3797 * @memberOf _
3798 * @since 4.0.0
3799 * @category Lang
3800 * @param {*} value The value to check.
3801 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
3802 * @example
3803 *
3804 * _.isLength(3);
3805 * // => true
3806 *
3807 * _.isLength(Number.MIN_VALUE);
3808 * // => false
3809 *
3810 * _.isLength(Infinity);
3811 * // => false
3812 *
3813 * _.isLength('3');
3814 * // => false
3815 */
3816function isLength(value) {
3817 return typeof value == 'number' &&
3818 value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
3819}
3820
3821/**
3822 * Checks if `value` is the
3823 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
3824 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
3825 *
3826 * @static
3827 * @memberOf _
3828 * @since 0.1.0
3829 * @category Lang
3830 * @param {*} value The value to check.
3831 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
3832 * @example
3833 *
3834 * _.isObject({});
3835 * // => true
3836 *
3837 * _.isObject([1, 2, 3]);
3838 * // => true
3839 *
3840 * _.isObject(_.noop);
3841 * // => true
3842 *
3843 * _.isObject(null);
3844 * // => false
3845 */
3846function isObject(value) {
3847 var type = typeof value;
3848 return value != null && (type == 'object' || type == 'function');
3849}
3850
3851/**
3852 * Checks if `value` is object-like. A value is object-like if it's not `null`
3853 * and has a `typeof` result of "object".
3854 *
3855 * @static
3856 * @memberOf _
3857 * @since 4.0.0
3858 * @category Lang
3859 * @param {*} value The value to check.
3860 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
3861 * @example
3862 *
3863 * _.isObjectLike({});
3864 * // => true
3865 *
3866 * _.isObjectLike([1, 2, 3]);
3867 * // => true
3868 *
3869 * _.isObjectLike(_.noop);
3870 * // => false
3871 *
3872 * _.isObjectLike(null);
3873 * // => false
3874 */
3875function isObjectLike(value) {
3876 return value != null && typeof value == 'object';
3877}
3878
3879/**
3880 * Checks if `value` is classified as a typed array.
3881 *
3882 * @static
3883 * @memberOf _
3884 * @since 3.0.0
3885 * @category Lang
3886 * @param {*} value The value to check.
3887 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
3888 * @example
3889 *
3890 * _.isTypedArray(new Uint8Array);
3891 * // => true
3892 *
3893 * _.isTypedArray([]);
3894 * // => false
3895 */
3896var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
3897
3898/**
3899 * Creates an array of the own enumerable property names of `object`.
3900 *
3901 * **Note:** Non-object values are coerced to objects. See the
3902 * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
3903 * for more details.
3904 *
3905 * @static
3906 * @since 0.1.0
3907 * @memberOf _
3908 * @category Object
3909 * @param {Object} object The object to query.
3910 * @returns {Array} Returns the array of property names.
3911 * @example
3912 *
3913 * function Foo() {
3914 * this.a = 1;
3915 * this.b = 2;
3916 * }
3917 *
3918 * Foo.prototype.c = 3;
3919 *
3920 * _.keys(new Foo);
3921 * // => ['a', 'b'] (iteration order is not guaranteed)
3922 *
3923 * _.keys('hi');
3924 * // => ['0', '1']
3925 */
3926function keys(object) {
3927 return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
3928}
3929
3930/**
3931 * This method returns a new empty array.
3932 *
3933 * @static
3934 * @memberOf _
3935 * @since 4.13.0
3936 * @category Util
3937 * @returns {Array} Returns the new empty array.
3938 * @example
3939 *
3940 * var arrays = _.times(2, _.stubArray);
3941 *
3942 * console.log(arrays);
3943 * // => [[], []]
3944 *
3945 * console.log(arrays[0] === arrays[1]);
3946 * // => false
3947 */
3948function stubArray() {
3949 return [];
3950}
3951
3952/**
3953 * This method returns `false`.
3954 *
3955 * @static
3956 * @memberOf _
3957 * @since 4.13.0
3958 * @category Util
3959 * @returns {boolean} Returns `false`.
3960 * @example
3961 *
3962 * _.times(2, _.stubFalse);
3963 * // => [false, false]
3964 */
3965function stubFalse() {
3966 return false;
3967}
3968
3969module.exports = isEqual;
3970
3971}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
3972},{}],18:[function(require,module,exports){
3973'use strict';
3974
3975var runSetup = require('./src/setup');
3976var setupOptions = require('./src/options');
3977var setupAPI = require('./src/api');
3978var Constants = require('./src/constants');
3979
3980var setupDraw = function setupDraw(options, api) {
3981 options = setupOptions(options);
3982
3983 var ctx = {
3984 options: options
3985 };
3986
3987 api = setupAPI(ctx, api);
3988 ctx.api = api;
3989
3990 var setup = runSetup(ctx);
3991
3992 api.onAdd = setup.onAdd;
3993 api.onRemove = setup.onRemove;
3994 api.types = Constants.types;
3995 api.options = options;
3996
3997 return api;
3998};
3999
4000module.exports = function (options) {
4001 setupDraw(options, this);
4002};
4003
4004},{"./src/api":19,"./src/constants":20,"./src/options":54,"./src/setup":56}],19:[function(require,module,exports){
4005'use strict';
4006
4007var isEqual = require('lodash.isequal');
4008var normalize = require('geojson-normalize');
4009var hat = require('hat');
4010var featuresAt = require('./lib/features_at');
4011var stringSetsAreEqual = require('./lib/string_sets_are_equal');
4012var geojsonhint = require('geojsonhint');
4013var Constants = require('./constants');
4014var StringSet = require('./lib/string_set');
4015
4016var featureTypes = {
4017 Polygon: require('./feature_types/polygon'),
4018 LineString: require('./feature_types/line_string'),
4019 Point: require('./feature_types/point'),
4020 MultiPolygon: require('./feature_types/multi_feature'),
4021 MultiLineString: require('./feature_types/multi_feature'),
4022 MultiPoint: require('./feature_types/multi_feature')
4023};
4024
4025module.exports = function (ctx, api) {
4026
4027 api.modes = Constants.modes;
4028
4029 api.getFeatureIdsAt = function (point) {
4030 var features = featuresAt({ point: point }, null, ctx);
4031 return features.map(function (feature) {
4032 return feature.properties.id;
4033 });
4034 };
4035
4036 api.getSelectedIds = function () {
4037 return ctx.store.getSelectedIds();
4038 };
4039
4040 api.getSelected = function () {
4041 return {
4042 type: Constants.geojsonTypes.FEATURE_COLLECTION,
4043 features: ctx.store.getSelectedIds().map(function (id) {
4044 return ctx.store.get(id);
4045 }).map(function (feature) {
4046 return feature.toGeoJSON();
4047 })
4048 };
4049 };
4050
4051 api.set = function (featureCollection) {
4052 if (featureCollection.type === undefined || featureCollection.type !== Constants.geojsonTypes.FEATURE_COLLECTION || !Array.isArray(featureCollection.features)) {
4053 throw new Error('Invalid FeatureCollection');
4054 }
4055 var renderBatch = ctx.store.createRenderBatch();
4056 var toDelete = ctx.store.getAllIds().slice();
4057 var newIds = api.add(featureCollection);
4058 var newIdsLookup = new StringSet(newIds);
4059
4060 toDelete = toDelete.filter(function (id) {
4061 return !newIdsLookup.has(id);
4062 });
4063 if (toDelete.length) {
4064 api.delete(toDelete);
4065 }
4066
4067 renderBatch();
4068 return newIds;
4069 };
4070
4071 api.add = function (geojson) {
4072 var errors = geojsonhint.hint(geojson, { precisionWarning: false }).filter(function (e) {
4073 return e.level !== 'message';
4074 });
4075 if (errors.length) {
4076 throw new Error(errors[0].message);
4077 }
4078 var featureCollection = JSON.parse(JSON.stringify(normalize(geojson)));
4079
4080 var ids = featureCollection.features.map(function (feature) {
4081 feature.id = feature.id || hat();
4082
4083 if (feature.geometry === null) {
4084 throw new Error('Invalid geometry: null');
4085 }
4086
4087 if (ctx.store.get(feature.id) === undefined || ctx.store.get(feature.id).type !== feature.geometry.type) {
4088 // If the feature has not yet been created ...
4089 var Model = featureTypes[feature.geometry.type];
4090 if (Model === undefined) {
4091 throw new Error('Invalid geometry type: ' + feature.geometry.type + '.');
4092 }
4093 var internalFeature = new Model(ctx, feature);
4094 ctx.store.add(internalFeature);
4095 } else {
4096 // If a feature of that id has already been created, and we are swapping it out ...
4097 var _internalFeature = ctx.store.get(feature.id);
4098 _internalFeature.properties = feature.properties;
4099 if (!isEqual(_internalFeature.getCoordinates(), feature.geometry.coordinates)) {
4100 _internalFeature.incomingCoords(feature.geometry.coordinates);
4101 }
4102 }
4103 return feature.id;
4104 });
4105
4106 ctx.store.render();
4107 return ids;
4108 };
4109
4110 api.get = function (id) {
4111 var feature = ctx.store.get(id);
4112 if (feature) {
4113 return feature.toGeoJSON();
4114 }
4115 };
4116
4117 api.getAll = function () {
4118 return {
4119 type: Constants.geojsonTypes.FEATURE_COLLECTION,
4120 features: ctx.store.getAll().map(function (feature) {
4121 return feature.toGeoJSON();
4122 })
4123 };
4124 };
4125
4126 api.delete = function (featureIds) {
4127 ctx.store.delete(featureIds, { silent: true });
4128 // If we were in direct select mode and our selected feature no longer exists
4129 // (because it was deleted), we need to get out of that mode.
4130 if (api.getMode() === Constants.modes.DIRECT_SELECT && !ctx.store.getSelectedIds().length) {
4131 ctx.events.changeMode(Constants.modes.SIMPLE_SELECT, undefined, { silent: true });
4132 } else {
4133 ctx.store.render();
4134 }
4135
4136 return api;
4137 };
4138
4139 api.deleteAll = function () {
4140 ctx.store.delete(ctx.store.getAllIds(), { silent: true });
4141 // If we were in direct select mode, now our selected feature no longer exists,
4142 // so escape that mode.
4143 if (api.getMode() === Constants.modes.DIRECT_SELECT) {
4144 ctx.events.changeMode(Constants.modes.SIMPLE_SELECT, undefined, { silent: true });
4145 } else {
4146 ctx.store.render();
4147 }
4148
4149 return api;
4150 };
4151
4152 api.changeMode = function (mode) {
4153 var modeOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
4154
4155 // Avoid changing modes just to re-select what's already selected
4156 if (mode === Constants.modes.SIMPLE_SELECT && api.getMode() === Constants.modes.SIMPLE_SELECT) {
4157 if (stringSetsAreEqual(modeOptions.featureIds || [], ctx.store.getSelectedIds())) return api;
4158 // And if we are changing the selection within simple_select mode, just change the selection,
4159 // instead of stopping and re-starting the mode
4160 ctx.store.setSelected(modeOptions.featureIds, { silent: true });
4161 ctx.store.render();
4162 return api;
4163 }
4164
4165 if (mode === Constants.modes.DIRECT_SELECT && api.getMode() === Constants.modes.DIRECT_SELECT && modeOptions.featureId === ctx.store.getSelectedIds()[0]) {
4166 return api;
4167 }
4168
4169 ctx.events.changeMode(mode, modeOptions, { silent: true });
4170 return api;
4171 };
4172
4173 api.getMode = function () {
4174 return ctx.events.getMode();
4175 };
4176
4177 api.trash = function () {
4178 ctx.events.trash({ silent: true });
4179 return api;
4180 };
4181
4182 api.combineFeatures = function () {
4183 ctx.events.combineFeatures({ silent: true });
4184 return api;
4185 };
4186
4187 api.uncombineFeatures = function () {
4188 ctx.events.uncombineFeatures({ silent: true });
4189 return api;
4190 };
4191
4192 api.setFeatureProperty = function (featureId, property, value) {
4193 ctx.store.setFeatureProperty(featureId, property, value);
4194 return api;
4195 };
4196
4197 return api;
4198};
4199
4200},{"./constants":20,"./feature_types/line_string":23,"./feature_types/multi_feature":24,"./feature_types/point":25,"./feature_types/polygon":26,"./lib/features_at":34,"./lib/string_set":43,"./lib/string_sets_are_equal":44,"geojson-normalize":11,"geojsonhint":12,"hat":15,"lodash.isequal":17}],20:[function(require,module,exports){
4201'use strict';
4202
4203module.exports = {
4204 classes: {
4205 CONTROL_BASE: 'mapboxgl-ctrl',
4206 CONTROL_PREFIX: 'mapboxgl-ctrl-',
4207 CONTROL_BUTTON: 'mapbox-gl-draw_ctrl-draw-btn',
4208 CONTROL_BUTTON_LINE: 'mapbox-gl-draw_line',
4209 CONTROL_BUTTON_POLYGON: 'mapbox-gl-draw_polygon',
4210 CONTROL_BUTTON_POINT: 'mapbox-gl-draw_point',
4211 CONTROL_BUTTON_TRASH: 'mapbox-gl-draw_trash',
4212 CONTROL_BUTTON_COMBINE_FEATURES: 'mapbox-gl-draw_combine',
4213 CONTROL_BUTTON_UNCOMBINE_FEATURES: 'mapbox-gl-draw_uncombine',
4214 CONTROL_GROUP: 'mapboxgl-ctrl-group',
4215 ATTRIBUTION: 'mapboxgl-ctrl-attrib',
4216 ACTIVE_BUTTON: 'active',
4217 BOX_SELECT: 'mapbox-gl-draw_boxselect'
4218 },
4219 sources: {
4220 HOT: 'mapbox-gl-draw-hot',
4221 COLD: 'mapbox-gl-draw-cold'
4222 },
4223 cursors: {
4224 ADD: 'add',
4225 MOVE: 'move',
4226 DRAG: 'drag',
4227 POINTER: 'pointer',
4228 NONE: 'none'
4229 },
4230 types: {
4231 POLYGON: 'polygon',
4232 LINE: 'line_string',
4233 POINT: 'point'
4234 },
4235 geojsonTypes: {
4236 FEATURE: 'Feature',
4237 POLYGON: 'Polygon',
4238 LINE_STRING: 'LineString',
4239 POINT: 'Point',
4240 FEATURE_COLLECTION: 'FeatureCollection',
4241 MULTI_PREFIX: 'Multi',
4242 MULTI_POINT: 'MultiPoint',
4243 MULTI_LINE_STRING: 'MultiLineString',
4244 MULTI_POLYGON: 'MultiPolygon'
4245 },
4246 modes: {
4247 DRAW_LINE_STRING: 'draw_line_string',
4248 DRAW_POLYGON: 'draw_polygon',
4249 DRAW_POINT: 'draw_point',
4250 SIMPLE_SELECT: 'simple_select',
4251 DIRECT_SELECT: 'direct_select',
4252 STATIC: 'static'
4253 },
4254 events: {
4255 CREATE: 'draw.create',
4256 DELETE: 'draw.delete',
4257 UPDATE: 'draw.update',
4258 SELECTION_CHANGE: 'draw.selectionchange',
4259 MODE_CHANGE: 'draw.modechange',
4260 ACTIONABLE: 'draw.actionable',
4261 RENDER: 'draw.render',
4262 COMBINE_FEATURES: 'draw.combine',
4263 UNCOMBINE_FEATURES: 'draw.uncombine'
4264 },
4265 updateActions: {
4266 MOVE: 'move',
4267 CHANGE_COORDINATES: 'change_coordinates'
4268 },
4269 meta: {
4270 FEATURE: 'feature',
4271 MIDPOINT: 'midpoint',
4272 VERTEX: 'vertex'
4273 },
4274 activeStates: {
4275 ACTIVE: 'true',
4276 INACTIVE: 'false'
4277 },
4278 LAT_MIN: -90,
4279 LAT_RENDERED_MIN: -85,
4280 LAT_MAX: 90,
4281 LAT_RENDERED_MAX: 85,
4282 LNG_MIN: -270,
4283 LNG_MAX: 270
4284};
4285
4286},{}],21:[function(require,module,exports){
4287'use strict';
4288
4289var _modes;
4290
4291function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
4292
4293var setupModeHandler = require('./lib/mode_handler');
4294var getFeaturesAndSetCursor = require('./lib/get_features_and_set_cursor');
4295var isClick = require('./lib/is_click');
4296var Constants = require('./constants');
4297
4298var modes = (_modes = {}, _defineProperty(_modes, Constants.modes.SIMPLE_SELECT, require('./modes/simple_select')), _defineProperty(_modes, Constants.modes.DIRECT_SELECT, require('./modes/direct_select')), _defineProperty(_modes, Constants.modes.DRAW_POINT, require('./modes/draw_point')), _defineProperty(_modes, Constants.modes.DRAW_LINE_STRING, require('./modes/draw_line_string')), _defineProperty(_modes, Constants.modes.DRAW_POLYGON, require('./modes/draw_polygon')), _defineProperty(_modes, Constants.modes.STATIC, require('./modes/static')), _modes);
4299
4300module.exports = function (ctx) {
4301
4302 var mouseDownInfo = {};
4303 var events = {};
4304 var _currentModeName = Constants.modes.SIMPLE_SELECT;
4305 var currentMode = setupModeHandler(modes.simple_select(ctx), ctx);
4306
4307 events.drag = function (event) {
4308 if (isClick(mouseDownInfo, {
4309 point: event.point,
4310 time: new Date().getTime()
4311 })) {
4312 event.originalEvent.stopPropagation();
4313 } else {
4314 ctx.ui.queueMapClasses({ mouse: Constants.cursors.DRAG });
4315 currentMode.drag(event);
4316 }
4317 };
4318
4319 events.mousemove = function (event) {
4320 var button = event.originalEvent.buttons !== undefined ? event.originalEvent.buttons : event.originalEvent.which;
4321 if (button === 1) {
4322 return events.drag(event);
4323 }
4324 var target = getFeaturesAndSetCursor(event, ctx);
4325 event.featureTarget = target;
4326 currentMode.mousemove(event);
4327 };
4328
4329 events.mousedown = function (event) {
4330 mouseDownInfo = {
4331 time: new Date().getTime(),
4332 point: event.point
4333 };
4334 var target = getFeaturesAndSetCursor(event, ctx);
4335 event.featureTarget = target;
4336 currentMode.mousedown(event);
4337 };
4338
4339 events.mouseup = function (event) {
4340 var target = getFeaturesAndSetCursor(event, ctx);
4341 event.featureTarget = target;
4342
4343 if (isClick(mouseDownInfo, {
4344 point: event.point,
4345 time: new Date().getTime()
4346 })) {
4347 currentMode.click(event);
4348 } else {
4349 currentMode.mouseup(event);
4350 }
4351 };
4352
4353 events.mouseout = function (event) {
4354 currentMode.mouseout(event);
4355 };
4356
4357 // 8 - Backspace
4358 // 46 - Delete
4359 var isKeyModeValid = function isKeyModeValid(code) {
4360 return !(code === 8 || code === 46 || code >= 48 && code <= 57);
4361 };
4362
4363 events.keydown = function (event) {
4364
4365 if ((event.keyCode === 8 || event.keyCode === 46) && ctx.options.controls.trash) {
4366 event.preventDefault();
4367 currentMode.trash();
4368 } else if (isKeyModeValid(event.keyCode)) {
4369 currentMode.keydown(event);
4370 } else if (event.keyCode === 49 && ctx.options.controls.point) {
4371 changeMode(Constants.modes.DRAW_POINT);
4372 } else if (event.keyCode === 50 && ctx.options.controls.line_string) {
4373 changeMode(Constants.modes.DRAW_LINE_STRING);
4374 } else if (event.keyCode === 51 && ctx.options.controls.polygon) {
4375 changeMode(Constants.modes.DRAW_POLYGON);
4376 }
4377 };
4378
4379 events.keyup = function (event) {
4380 if (isKeyModeValid(event.keyCode)) {
4381 currentMode.keyup(event);
4382 }
4383 };
4384
4385 events.zoomend = function () {
4386 ctx.store.changeZoom();
4387 };
4388
4389 events.data = function (event) {
4390 if (event.dataType === 'style') {
4391 var setup = ctx.setup,
4392 map = ctx.map,
4393 options = ctx.options,
4394 store = ctx.store;
4395
4396 var hasLayers = !!options.styles.find(function (style) {
4397 return map.getLayer(style.id);
4398 });
4399 if (!hasLayers) {
4400 setup.addLayers();
4401 store.setDirty();
4402 store.render();
4403 }
4404 }
4405 };
4406
4407 function changeMode(modename, nextModeOptions) {
4408 var eventOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
4409
4410 currentMode.stop();
4411
4412 var modebuilder = modes[modename];
4413 if (modebuilder === undefined) {
4414 throw new Error(modename + ' is not valid');
4415 }
4416 _currentModeName = modename;
4417 var mode = modebuilder(ctx, nextModeOptions);
4418 currentMode = setupModeHandler(mode, ctx);
4419
4420 if (!eventOptions.silent) {
4421 ctx.map.fire(Constants.events.MODE_CHANGE, { mode: modename });
4422 }
4423
4424 ctx.store.setDirty();
4425 ctx.store.render();
4426 }
4427
4428 var actionState = {
4429 trash: false,
4430 combineFeatures: false,
4431 uncombineFeatures: false
4432 };
4433
4434 function actionable(actions) {
4435 var changed = false;
4436 Object.keys(actions).forEach(function (action) {
4437 if (actionState[action] === undefined) throw new Error('Invalid action type');
4438 if (actionState[action] !== actions[action]) changed = true;
4439 actionState[action] = actions[action];
4440 });
4441 if (changed) ctx.map.fire(Constants.events.ACTIONABLE, { actions: actionState });
4442 }
4443
4444 var api = {
4445 changeMode: changeMode,
4446 actionable: actionable,
4447 currentModeName: function currentModeName() {
4448 return _currentModeName;
4449 },
4450 currentModeRender: function currentModeRender(geojson, push) {
4451 return currentMode.render(geojson, push);
4452 },
4453 fire: function fire(name, event) {
4454 if (events[name]) {
4455 events[name](event);
4456 }
4457 },
4458 addEventListeners: function addEventListeners() {
4459 ctx.map.on('mousemove', events.mousemove);
4460 ctx.map.on('mousedown', events.mousedown);
4461 ctx.map.on('mouseup', events.mouseup);
4462 ctx.map.on('data', events.data);
4463
4464 ctx.container.addEventListener('mouseout', events.mouseout);
4465
4466 if (ctx.options.keybindings) {
4467 ctx.container.addEventListener('keydown', events.keydown);
4468 ctx.container.addEventListener('keyup', events.keyup);
4469 }
4470 },
4471 removeEventListeners: function removeEventListeners() {
4472 ctx.map.off('mousemove', events.mousemove);
4473 ctx.map.off('mousedown', events.mousedown);
4474 ctx.map.off('mouseup', events.mouseup);
4475 ctx.map.off('data', events.data);
4476
4477 ctx.container.removeEventListener('mouseout', events.mouseout);
4478
4479 if (ctx.options.keybindings) {
4480 ctx.container.removeEventListener('keydown', events.keydown);
4481 ctx.container.removeEventListener('keyup', events.keyup);
4482 }
4483 },
4484 trash: function trash(options) {
4485 currentMode.trash(options);
4486 },
4487 combineFeatures: function combineFeatures() {
4488 currentMode.combineFeatures();
4489 },
4490 uncombineFeatures: function uncombineFeatures() {
4491 currentMode.uncombineFeatures();
4492 },
4493 getMode: function getMode() {
4494 return _currentModeName;
4495 }
4496 };
4497
4498 return api;
4499};
4500
4501},{"./constants":20,"./lib/get_features_and_set_cursor":35,"./lib/is_click":36,"./lib/mode_handler":39,"./modes/direct_select":48,"./modes/draw_line_string":49,"./modes/draw_point":50,"./modes/draw_polygon":51,"./modes/simple_select":52,"./modes/static":53}],22:[function(require,module,exports){
4502'use strict';
4503
4504var hat = require('hat');
4505var Constants = require('../constants');
4506
4507var Feature = function Feature(ctx, geojson) {
4508 this.ctx = ctx;
4509 this.properties = geojson.properties || {};
4510 this.coordinates = geojson.geometry.coordinates;
4511 this.id = geojson.id || hat();
4512 this.type = geojson.geometry.type;
4513};
4514
4515Feature.prototype.changed = function () {
4516 this.ctx.store.featureChanged(this.id);
4517};
4518
4519Feature.prototype.incomingCoords = function (coords) {
4520 this.setCoordinates(coords);
4521};
4522
4523Feature.prototype.setCoordinates = function (coords) {
4524 this.coordinates = coords;
4525 this.changed();
4526};
4527
4528Feature.prototype.getCoordinates = function () {
4529 return JSON.parse(JSON.stringify(this.coordinates));
4530};
4531
4532Feature.prototype.setProperty = function (property, value) {
4533 this.properties[property] = value;
4534};
4535
4536Feature.prototype.toGeoJSON = function () {
4537 return JSON.parse(JSON.stringify({
4538 id: this.id,
4539 type: Constants.geojsonTypes.FEATURE,
4540 properties: this.properties,
4541 geometry: {
4542 coordinates: this.getCoordinates(),
4543 type: this.type
4544 }
4545 }));
4546};
4547
4548Feature.prototype.internal = function (mode) {
4549 var properties = {
4550 id: this.id,
4551 meta: Constants.meta.FEATURE,
4552 'meta:type': this.type,
4553 active: Constants.activeStates.INACTIVE,
4554 mode: mode
4555 };
4556
4557 if (this.ctx.options.userProperties) {
4558 for (var name in this.properties) {
4559 properties['user_' + name] = this.properties[name];
4560 }
4561 }
4562
4563 return {
4564 type: Constants.geojsonTypes.FEATURE,
4565 properties: properties,
4566 geometry: {
4567 coordinates: this.getCoordinates(),
4568 type: this.type
4569 }
4570 };
4571};
4572
4573module.exports = Feature;
4574
4575},{"../constants":20,"hat":15}],23:[function(require,module,exports){
4576'use strict';
4577
4578var Feature = require('./feature');
4579
4580var LineString = function LineString(ctx, geojson) {
4581 Feature.call(this, ctx, geojson);
4582};
4583
4584LineString.prototype = Object.create(Feature.prototype);
4585
4586LineString.prototype.isValid = function () {
4587 return this.coordinates.length > 1;
4588};
4589
4590LineString.prototype.addCoordinate = function (path, lng, lat) {
4591 this.changed();
4592 var id = parseInt(path, 10);
4593 this.coordinates.splice(id, 0, [lng, lat]);
4594};
4595
4596LineString.prototype.getCoordinate = function (path) {
4597 var id = parseInt(path, 10);
4598 return JSON.parse(JSON.stringify(this.coordinates[id]));
4599};
4600
4601LineString.prototype.removeCoordinate = function (path) {
4602 this.changed();
4603 this.coordinates.splice(parseInt(path, 10), 1);
4604};
4605
4606LineString.prototype.updateCoordinate = function (path, lng, lat) {
4607 var id = parseInt(path, 10);
4608 this.coordinates[id] = [lng, lat];
4609 this.changed();
4610};
4611
4612module.exports = LineString;
4613
4614},{"./feature":22}],24:[function(require,module,exports){
4615'use strict';
4616
4617var Feature = require('./feature');
4618var Constants = require('../constants');
4619var hat = require('hat');
4620
4621var models = {
4622 MultiPoint: require('./point'),
4623 MultiLineString: require('./line_string'),
4624 MultiPolygon: require('./polygon')
4625};
4626
4627var takeAction = function takeAction(features, action, path, lng, lat) {
4628 var parts = path.split('.');
4629 var idx = parseInt(parts[0], 10);
4630 var tail = !parts[1] ? null : parts.slice(1).join('.');
4631 return features[idx][action](tail, lng, lat);
4632};
4633
4634var MultiFeature = function MultiFeature(ctx, geojson) {
4635 Feature.call(this, ctx, geojson);
4636
4637 delete this.coordinates;
4638 this.model = models[geojson.geometry.type];
4639 if (this.model === undefined) throw new TypeError(geojson.geometry.type + ' is not a valid type');
4640 this.features = this._coordinatesToFeatures(geojson.geometry.coordinates);
4641};
4642
4643MultiFeature.prototype = Object.create(Feature.prototype);
4644
4645MultiFeature.prototype._coordinatesToFeatures = function (coordinates) {
4646 var _this = this;
4647
4648 var Model = this.model.bind(this);
4649 return coordinates.map(function (coords) {
4650 return new Model(_this.ctx, {
4651 id: hat(),
4652 type: Constants.geojsonTypes.FEATURE,
4653 properties: {},
4654 geometry: {
4655 coordinates: coords,
4656 type: _this.type.replace('Multi', '')
4657 }
4658 });
4659 });
4660};
4661
4662MultiFeature.prototype.isValid = function () {
4663 return this.features.every(function (f) {
4664 return f.isValid();
4665 });
4666};
4667
4668MultiFeature.prototype.setCoordinates = function (coords) {
4669 this.features = this._coordinatesToFeatures(coords);
4670 this.changed();
4671};
4672
4673MultiFeature.prototype.getCoordinate = function (path) {
4674 return takeAction(this.features, 'getCoordinate', path);
4675};
4676
4677MultiFeature.prototype.getCoordinates = function () {
4678 return JSON.parse(JSON.stringify(this.features.map(function (f) {
4679 if (f.type === Constants.geojsonTypes.POLYGON) return f.getCoordinates();
4680 return f.coordinates;
4681 })));
4682};
4683
4684MultiFeature.prototype.updateCoordinate = function (path, lng, lat) {
4685 takeAction(this.features, 'updateCoordinate', path, lng, lat);
4686 this.changed();
4687};
4688
4689MultiFeature.prototype.addCoordinate = function (path, lng, lat) {
4690 takeAction(this.features, 'addCoordinate', path, lng, lat);
4691 this.changed();
4692};
4693
4694MultiFeature.prototype.removeCoordinate = function (path) {
4695 takeAction(this.features, 'removeCoordinate', path);
4696 this.changed();
4697};
4698
4699MultiFeature.prototype.getFeatures = function () {
4700 return this.features;
4701};
4702
4703module.exports = MultiFeature;
4704
4705},{"../constants":20,"./feature":22,"./line_string":23,"./point":25,"./polygon":26,"hat":15}],25:[function(require,module,exports){
4706'use strict';
4707
4708var Feature = require('./feature');
4709
4710var Point = function Point(ctx, geojson) {
4711 Feature.call(this, ctx, geojson);
4712};
4713
4714Point.prototype = Object.create(Feature.prototype);
4715
4716Point.prototype.isValid = function () {
4717 return typeof this.coordinates[0] === 'number' && typeof this.coordinates[1] === 'number';
4718};
4719
4720Point.prototype.updateCoordinate = function (pathOrLng, lngOrLat, lat) {
4721 if (arguments.length === 3) {
4722 this.coordinates = [lngOrLat, lat];
4723 } else {
4724 this.coordinates = [pathOrLng, lngOrLat];
4725 }
4726 this.changed();
4727};
4728
4729Point.prototype.getCoordinate = function () {
4730 return this.getCoordinates();
4731};
4732
4733module.exports = Point;
4734
4735},{"./feature":22}],26:[function(require,module,exports){
4736'use strict';
4737
4738var Feature = require('./feature');
4739
4740var Polygon = function Polygon(ctx, geojson) {
4741 Feature.call(this, ctx, geojson);
4742 this.coordinates = this.coordinates.map(function (ring) {
4743 return ring.slice(0, -1);
4744 });
4745};
4746
4747Polygon.prototype = Object.create(Feature.prototype);
4748
4749Polygon.prototype.isValid = function () {
4750 if (this.coordinates.length === 0) return false;
4751 return this.coordinates.every(function (ring) {
4752 return ring.length > 2;
4753 });
4754};
4755
4756// Expects valid geoJSON polygon geometry: first and last positions must be equivalent.
4757Polygon.prototype.incomingCoords = function (coords) {
4758 this.coordinates = coords.map(function (ring) {
4759 return ring.slice(0, -1);
4760 });
4761 this.changed();
4762};
4763
4764// Does NOT expect valid geoJSON polygon geometry: first and last positions should not be equivalent.
4765Polygon.prototype.setCoordinates = function (coords) {
4766 this.coordinates = coords;
4767 this.changed();
4768};
4769
4770Polygon.prototype.addCoordinate = function (path, lng, lat) {
4771 this.changed();
4772 var ids = path.split('.').map(function (x) {
4773 return parseInt(x, 10);
4774 });
4775
4776 var ring = this.coordinates[ids[0]];
4777
4778 ring.splice(ids[1], 0, [lng, lat]);
4779};
4780
4781Polygon.prototype.removeCoordinate = function (path) {
4782 this.changed();
4783 var ids = path.split('.').map(function (x) {
4784 return parseInt(x, 10);
4785 });
4786 var ring = this.coordinates[ids[0]];
4787 if (ring) {
4788 ring.splice(ids[1], 1);
4789 if (ring.length < 3) {
4790 this.coordinates.splice(ids[0], 1);
4791 }
4792 }
4793};
4794
4795Polygon.prototype.getCoordinate = function (path) {
4796 var ids = path.split('.').map(function (x) {
4797 return parseInt(x, 10);
4798 });
4799 var ring = this.coordinates[ids[0]];
4800 return JSON.parse(JSON.stringify(ring[ids[1]]));
4801};
4802
4803Polygon.prototype.getCoordinates = function () {
4804 return this.coordinates.map(function (coords) {
4805 return coords.concat([coords[0]]);
4806 });
4807};
4808
4809Polygon.prototype.updateCoordinate = function (path, lng, lat) {
4810 this.changed();
4811 var parts = path.split('.');
4812 var ringId = parseInt(parts[0], 10);
4813 var coordId = parseInt(parts[1], 10);
4814
4815 if (this.coordinates[ringId] === undefined) {
4816 this.coordinates[ringId] = [];
4817 }
4818
4819 this.coordinates[ringId][coordId] = [lng, lat];
4820};
4821
4822module.exports = Polygon;
4823
4824},{"./feature":22}],27:[function(require,module,exports){
4825'use strict';
4826
4827var Constants = require('../constants');
4828
4829module.exports = {
4830 isOfMetaType: function isOfMetaType(type) {
4831 return function (e) {
4832 var featureTarget = e.featureTarget;
4833 if (!featureTarget) return false;
4834 if (!featureTarget.properties) return false;
4835 return featureTarget.properties.meta === type;
4836 };
4837 },
4838 isShiftMousedown: function isShiftMousedown(e) {
4839 if (!e.originalEvent) return false;
4840 if (!e.originalEvent.shiftKey) return false;
4841 return e.originalEvent.button === 0;
4842 },
4843 isActiveFeature: function isActiveFeature(e) {
4844 if (!e.featureTarget) return false;
4845 if (!e.featureTarget.properties) return false;
4846 return e.featureTarget.properties.active === Constants.activeStates.ACTIVE && e.featureTarget.properties.meta === Constants.meta.FEATURE;
4847 },
4848 isInactiveFeature: function isInactiveFeature(e) {
4849 if (!e.featureTarget) return false;
4850 if (!e.featureTarget.properties) return false;
4851 return e.featureTarget.properties.active === Constants.activeStates.INACTIVE && e.featureTarget.properties.meta === Constants.meta.FEATURE;
4852 },
4853 noTarget: function noTarget(e) {
4854 return e.featureTarget === undefined;
4855 },
4856 isFeature: function isFeature(e) {
4857 if (!e.featureTarget) return false;
4858 if (!e.featureTarget.properties) return false;
4859 return e.featureTarget.properties.meta === Constants.meta.FEATURE;
4860 },
4861 isVertex: function isVertex(e) {
4862 var featureTarget = e.featureTarget;
4863 if (!featureTarget) return false;
4864 if (!featureTarget.properties) return false;
4865 return featureTarget.properties.meta === Constants.meta.VERTEX;
4866 },
4867 isShiftDown: function isShiftDown(e) {
4868 if (!e.originalEvent) return false;
4869 return e.originalEvent.shiftKey === true;
4870 },
4871 isEscapeKey: function isEscapeKey(e) {
4872 return e.keyCode === 27;
4873 },
4874 isEnterKey: function isEnterKey(e) {
4875 return e.keyCode === 13;
4876 },
4877 true: function _true() {
4878 return true;
4879 }
4880};
4881
4882},{"../constants":20}],28:[function(require,module,exports){
4883'use strict';
4884
4885var extent = require('geojson-extent');
4886var Constants = require('../constants');
4887
4888var LAT_MIN = Constants.LAT_MIN,
4889 LAT_MAX = Constants.LAT_MAX,
4890 LAT_RENDERED_MIN = Constants.LAT_RENDERED_MIN,
4891 LAT_RENDERED_MAX = Constants.LAT_RENDERED_MAX,
4892 LNG_MIN = Constants.LNG_MIN,
4893 LNG_MAX = Constants.LNG_MAX;
4894
4895// Ensure that we do not drag north-south far enough for
4896// - any part of any feature to exceed the poles
4897// - any feature to be completely lost in the space between the projection's
4898// edge and the poles, such that it couldn't be re-selected and moved back
4899
4900module.exports = function (geojsonFeatures, delta) {
4901 // "inner edge" = a feature's latitude closest to the equator
4902 var northInnerEdge = LAT_MIN;
4903 var southInnerEdge = LAT_MAX;
4904 // "outer edge" = a feature's latitude furthest from the equator
4905 var northOuterEdge = LAT_MIN;
4906 var southOuterEdge = LAT_MAX;
4907
4908 var westEdge = LNG_MAX;
4909 var eastEdge = LNG_MIN;
4910
4911 geojsonFeatures.forEach(function (feature) {
4912 var bounds = extent(feature);
4913 var featureSouthEdge = bounds[1];
4914 var featureNorthEdge = bounds[3];
4915 var featureWestEdge = bounds[0];
4916 var featureEastEdge = bounds[2];
4917 if (featureSouthEdge > northInnerEdge) northInnerEdge = featureSouthEdge;
4918 if (featureNorthEdge < southInnerEdge) southInnerEdge = featureNorthEdge;
4919 if (featureNorthEdge > northOuterEdge) northOuterEdge = featureNorthEdge;
4920 if (featureSouthEdge < southOuterEdge) southOuterEdge = featureSouthEdge;
4921 if (featureWestEdge < westEdge) westEdge = featureWestEdge;
4922 if (featureEastEdge > eastEdge) eastEdge = featureEastEdge;
4923 });
4924
4925 // These changes are not mutually exclusive: we might hit the inner
4926 // edge but also have hit the outer edge and therefore need
4927 // another readjustment
4928 var constrainedDelta = delta;
4929 if (northInnerEdge + constrainedDelta.lat > LAT_RENDERED_MAX) {
4930 constrainedDelta.lat = LAT_RENDERED_MAX - northInnerEdge;
4931 }
4932 if (northOuterEdge + constrainedDelta.lat > LAT_MAX) {
4933 constrainedDelta.lat = LAT_MAX - northOuterEdge;
4934 }
4935 if (southInnerEdge + constrainedDelta.lat < LAT_RENDERED_MIN) {
4936 constrainedDelta.lat = LAT_RENDERED_MIN - southInnerEdge;
4937 }
4938 if (southOuterEdge + constrainedDelta.lat < LAT_MIN) {
4939 constrainedDelta.lat = LAT_MIN - southOuterEdge;
4940 }
4941 if (westEdge + constrainedDelta.lng <= LNG_MIN) {
4942 constrainedDelta.lng += Math.ceil(Math.abs(constrainedDelta.lng) / 360) * 360;
4943 }
4944 if (eastEdge + constrainedDelta.lng >= LNG_MAX) {
4945 constrainedDelta.lng -= Math.ceil(Math.abs(constrainedDelta.lng) / 360) * 360;
4946 }
4947
4948 return constrainedDelta;
4949};
4950
4951},{"../constants":20,"geojson-extent":9}],29:[function(require,module,exports){
4952'use strict';
4953
4954var Constants = require('../constants');
4955
4956module.exports = function (parent, startVertex, endVertex, map) {
4957 var startCoord = startVertex.geometry.coordinates;
4958 var endCoord = endVertex.geometry.coordinates;
4959
4960 // If a coordinate exceeds the projection, we can't calculate a midpoint,
4961 // so run away
4962 if (startCoord[1] > Constants.LAT_RENDERED_MAX || startCoord[1] < Constants.LAT_RENDERED_MIN || endCoord[1] > Constants.LAT_RENDERED_MAX || endCoord[1] < Constants.LAT_RENDERED_MIN) {
4963 return null;
4964 }
4965
4966 var ptA = map.project([startCoord[0], startCoord[1]]);
4967 var ptB = map.project([endCoord[0], endCoord[1]]);
4968 var mid = map.unproject([(ptA.x + ptB.x) / 2, (ptA.y + ptB.y) / 2]);
4969
4970 return {
4971 type: Constants.geojsonTypes.FEATURE,
4972 properties: {
4973 meta: Constants.meta.MIDPOINT,
4974 parent: parent,
4975 lng: mid.lng,
4976 lat: mid.lat,
4977 coord_path: endVertex.properties.coord_path
4978 },
4979 geometry: {
4980 type: Constants.geojsonTypes.POINT,
4981 coordinates: [mid.lng, mid.lat]
4982 }
4983 };
4984};
4985
4986},{"../constants":20}],30:[function(require,module,exports){
4987'use strict';
4988
4989var createVertex = require('./create_vertex');
4990var createMidpoint = require('./create_midpoint');
4991var Constants = require('../constants');
4992
4993function createSupplementaryPoints(geojson) {
4994 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
4995 var basePath = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
4996 var _geojson$geometry = geojson.geometry,
4997 type = _geojson$geometry.type,
4998 coordinates = _geojson$geometry.coordinates;
4999
5000 var featureId = geojson.properties && geojson.properties.id;
5001
5002 var supplementaryPoints = [];
5003
5004 if (type === Constants.geojsonTypes.POINT) {
5005 // For points, just create a vertex
5006 supplementaryPoints.push(createVertex(featureId, coordinates, basePath, isSelectedPath(basePath)));
5007 } else if (type === Constants.geojsonTypes.POLYGON) {
5008 // Cycle through a Polygon's rings and
5009 // process each line
5010 coordinates.forEach(function (line, lineIndex) {
5011 processLine(line, basePath !== null ? basePath + '.' + lineIndex : String(lineIndex));
5012 });
5013 } else if (type === Constants.geojsonTypes.LINE_STRING) {
5014 processLine(coordinates, basePath);
5015 } else if (type.indexOf(Constants.geojsonTypes.MULTI_PREFIX) === 0) {
5016 processMultiGeometry();
5017 }
5018
5019 function processLine(line, lineBasePath) {
5020 var firstPointString = '';
5021 var lastVertex = null;
5022 line.forEach(function (point, pointIndex) {
5023 var pointPath = lineBasePath !== undefined && lineBasePath !== null ? lineBasePath + '.' + pointIndex : String(pointIndex);
5024 var vertex = createVertex(featureId, point, pointPath, isSelectedPath(pointPath));
5025
5026 // If we're creating midpoints, check if there was a
5027 // vertex before this one. If so, add a midpoint
5028 // between that vertex and this one.
5029 if (options.midpoints && lastVertex) {
5030 var midpoint = createMidpoint(featureId, lastVertex, vertex, options.map);
5031 if (midpoint) {
5032 supplementaryPoints.push(midpoint);
5033 }
5034 }
5035 lastVertex = vertex;
5036
5037 // A Polygon line's last point is the same as the first point. If we're on the last
5038 // point, we want to draw a midpoint before it but not another vertex on it
5039 // (since we already a vertex there, from the first point).
5040 var stringifiedPoint = JSON.stringify(point);
5041 if (firstPointString !== stringifiedPoint) {
5042 supplementaryPoints.push(vertex);
5043 }
5044 if (pointIndex === 0) {
5045 firstPointString = stringifiedPoint;
5046 }
5047 });
5048 }
5049
5050 function isSelectedPath(path) {
5051 if (!options.selectedPaths) return false;
5052 return options.selectedPaths.indexOf(path) !== -1;
5053 }
5054
5055 // Split a multi-geometry into constituent
5056 // geometries, and accumulate the supplementary points
5057 // for each of those constituents
5058 function processMultiGeometry() {
5059 var subType = type.replace(Constants.geojsonTypes.MULTI_PREFIX, '');
5060 coordinates.forEach(function (subCoordinates, index) {
5061 var subFeature = {
5062 type: Constants.geojsonTypes.FEATURE,
5063 properties: geojson.properties,
5064 geometry: {
5065 type: subType,
5066 coordinates: subCoordinates
5067 }
5068 };
5069 supplementaryPoints = supplementaryPoints.concat(createSupplementaryPoints(subFeature, options, index));
5070 });
5071 }
5072
5073 return supplementaryPoints;
5074}
5075
5076module.exports = createSupplementaryPoints;
5077
5078},{"../constants":20,"./create_midpoint":29,"./create_vertex":31}],31:[function(require,module,exports){
5079'use strict';
5080
5081var Constants = require('../constants');
5082
5083/**
5084 * Returns GeoJSON for a Point representing the
5085 * vertex of another feature.
5086 *
5087 * @param {string} parentId
5088 * @param {Array<number>} coordinates
5089 * @param {string} path - Dot-separated numbers indicating exactly
5090 * where the point exists within its parent feature's coordinates.
5091 * @param {boolean} selected
5092 * @return {GeoJSON} Point
5093 */
5094module.exports = function (parentId, coordinates, path, selected) {
5095 return {
5096 type: Constants.geojsonTypes.FEATURE,
5097 properties: {
5098 meta: Constants.meta.VERTEX,
5099 parent: parentId,
5100 coord_path: path,
5101 active: selected ? Constants.activeStates.ACTIVE : Constants.activeStates.INACTIVE
5102 },
5103 geometry: {
5104 type: Constants.geojsonTypes.POINT,
5105 coordinates: coordinates
5106 }
5107 };
5108};
5109
5110},{"../constants":20}],32:[function(require,module,exports){
5111"use strict";
5112
5113module.exports = {
5114 enable: function enable(ctx) {
5115 setTimeout(function () {
5116 if (!ctx.map || !ctx.map.doubleClickZoom) return;
5117 ctx.map.doubleClickZoom.enable();
5118 }, 0);
5119 },
5120 disable: function disable(ctx) {
5121 setTimeout(function () {
5122 if (!ctx.map || !ctx.map.doubleClickZoom) return;
5123 ctx.map.doubleClickZoom.disable();
5124 }, 0);
5125 }
5126};
5127
5128},{}],33:[function(require,module,exports){
5129"use strict";
5130
5131module.exports = function (a, b) {
5132 var x = a.x - b.x;
5133 var y = a.y - b.y;
5134 return Math.sqrt(x * x + y * y);
5135};
5136
5137},{}],34:[function(require,module,exports){
5138'use strict';
5139
5140var sortFeatures = require('./sort_features');
5141var mapEventToBoundingBox = require('./map_event_to_bounding_box');
5142var Constants = require('../constants');
5143var StringSet = require('./string_set');
5144
5145var META_TYPES = [Constants.meta.FEATURE, Constants.meta.MIDPOINT, Constants.meta.VERTEX];
5146
5147// Requires either event or bbox
5148module.exports = function (event, bbox, ctx) {
5149 if (ctx.map === null) return [];
5150
5151 var box = event ? mapEventToBoundingBox(event, ctx.options.clickBuffer) : bbox;
5152
5153 var queryParams = {};
5154 if (ctx.options.styles) queryParams.layers = ctx.options.styles.map(function (s) {
5155 return s.id;
5156 });
5157
5158 var features = ctx.map.queryRenderedFeatures(box, queryParams).filter(function (feature) {
5159 return META_TYPES.indexOf(feature.properties.meta) !== -1;
5160 });
5161
5162 var featureIds = new StringSet();
5163 var uniqueFeatures = [];
5164 features.forEach(function (feature) {
5165 var featureId = feature.properties.id;
5166 if (featureIds.has(featureId)) return;
5167 featureIds.add(featureId);
5168 uniqueFeatures.push(feature);
5169 });
5170
5171 return sortFeatures(uniqueFeatures);
5172};
5173
5174},{"../constants":20,"./map_event_to_bounding_box":38,"./sort_features":42,"./string_set":43}],35:[function(require,module,exports){
5175'use strict';
5176
5177var featuresAt = require('./features_at');
5178var Constants = require('../constants');
5179
5180module.exports = function getFeatureAtAndSetCursors(event, ctx) {
5181 var features = featuresAt(event, null, ctx);
5182 var classes = { mouse: Constants.cursors.NONE };
5183
5184 if (features[0]) {
5185 classes.mouse = features[0].properties.active === Constants.activeStates.ACTIVE ? Constants.cursors.MOVE : Constants.cursors.POINTER;
5186 classes.feature = features[0].properties.meta;
5187 }
5188
5189 if (ctx.events.currentModeName().indexOf('draw') !== -1) {
5190 classes.mouse = Constants.cursors.ADD;
5191 }
5192
5193 ctx.ui.queueMapClasses(classes);
5194 ctx.ui.updateMapClasses();
5195
5196 return features[0];
5197};
5198
5199},{"../constants":20,"./features_at":34}],36:[function(require,module,exports){
5200'use strict';
5201
5202var euclideanDistance = require('./euclidean_distance');
5203
5204var FINE_TOLERANCE = 4;
5205var GROSS_TOLERANCE = 12;
5206var INTERVAL = 500;
5207
5208module.exports = function isClick(start, end) {
5209 var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
5210
5211 var fineTolerance = options.fineTolerance != null ? options.fineTolerance : FINE_TOLERANCE;
5212 var grossTolerance = options.grossTolerance != null ? options.grossTolerance : GROSS_TOLERANCE;
5213 var interval = options.interval != null ? options.interval : INTERVAL;
5214
5215 start.point = start.point || end.point;
5216 start.time = start.time || end.time;
5217 var moveDistance = euclideanDistance(start.point, end.point);
5218
5219 return moveDistance < fineTolerance || moveDistance < grossTolerance && end.time - start.time < interval;
5220};
5221
5222},{"./euclidean_distance":33}],37:[function(require,module,exports){
5223"use strict";
5224
5225function isEventAtCoordinates(event, coordinates) {
5226 if (!event.lngLat) return false;
5227 return event.lngLat.lng === coordinates[0] && event.lngLat.lat === coordinates[1];
5228}
5229
5230module.exports = isEventAtCoordinates;
5231
5232},{}],38:[function(require,module,exports){
5233"use strict";
5234
5235/**
5236 * Returns a bounding box representing the event's location.
5237 *
5238 * @param {Event} mapEvent - Mapbox GL JS map event, with a point properties.
5239 * @return {Array<Array<number>>} Bounding box.
5240 */
5241function mapEventToBoundingBox(mapEvent) {
5242 var buffer = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
5243
5244 return [[mapEvent.point.x - buffer, mapEvent.point.y - buffer], [mapEvent.point.x + buffer, mapEvent.point.y + buffer]];
5245}
5246
5247module.exports = mapEventToBoundingBox;
5248
5249},{}],39:[function(require,module,exports){
5250'use strict';
5251
5252var ModeHandler = function ModeHandler(mode, DrawContext) {
5253
5254 var handlers = {
5255 drag: [],
5256 click: [],
5257 mousemove: [],
5258 mousedown: [],
5259 mouseup: [],
5260 mouseout: [],
5261 keydown: [],
5262 keyup: []
5263 };
5264
5265 var ctx = {
5266 on: function on(event, selector, fn) {
5267 if (handlers[event] === undefined) {
5268 throw new Error('Invalid event type: ' + event);
5269 }
5270 handlers[event].push({
5271 selector: selector,
5272 fn: fn
5273 });
5274 },
5275 render: function render(id) {
5276 DrawContext.store.featureChanged(id);
5277 }
5278 };
5279
5280 var delegate = function delegate(eventName, event) {
5281 var handles = handlers[eventName];
5282 var iHandle = handles.length;
5283 while (iHandle--) {
5284 var handle = handles[iHandle];
5285 if (handle.selector(event)) {
5286 handle.fn.call(ctx, event);
5287 DrawContext.store.render();
5288 DrawContext.ui.updateMapClasses();
5289
5290 // ensure an event is only handled once
5291 // we do this to let modes have multiple overlapping selectors
5292 // and relay on order of oppertations to filter
5293 break;
5294 }
5295 }
5296 };
5297
5298 mode.start.call(ctx);
5299
5300 return {
5301 render: mode.render,
5302 stop: function stop() {
5303 if (mode.stop) mode.stop();
5304 },
5305 trash: function trash() {
5306 if (mode.trash) {
5307 mode.trash();
5308 DrawContext.store.render();
5309 }
5310 },
5311 combineFeatures: function combineFeatures() {
5312 if (mode.combineFeatures) {
5313 mode.combineFeatures();
5314 }
5315 },
5316 uncombineFeatures: function uncombineFeatures() {
5317 if (mode.uncombineFeatures) {
5318 mode.uncombineFeatures();
5319 }
5320 },
5321 drag: function drag(event) {
5322 delegate('drag', event);
5323 },
5324 click: function click(event) {
5325 delegate('click', event);
5326 },
5327 mousemove: function mousemove(event) {
5328 delegate('mousemove', event);
5329 },
5330 mousedown: function mousedown(event) {
5331 delegate('mousedown', event);
5332 },
5333 mouseup: function mouseup(event) {
5334 delegate('mouseup', event);
5335 },
5336 mouseout: function mouseout(event) {
5337 delegate('mouseout', event);
5338 },
5339 keydown: function keydown(event) {
5340 delegate('keydown', event);
5341 },
5342 keyup: function keyup(event) {
5343 delegate('keyup', event);
5344 }
5345 };
5346};
5347
5348module.exports = ModeHandler;
5349
5350},{}],40:[function(require,module,exports){
5351'use strict';
5352
5353var Point = require('point-geometry');
5354
5355/**
5356 * Returns a Point representing a mouse event's position
5357 * relative to a containing element.
5358 *
5359 * @param {MouseEvent} mouseEvent
5360 * @param {Node} container
5361 * @returns {Point}
5362 */
5363function mouseEventPoint(mouseEvent, container) {
5364 var rect = container.getBoundingClientRect();
5365 return new Point(mouseEvent.clientX - rect.left - container.clientLeft, mouseEvent.clientY - rect.top - container.clientTop);
5366}
5367
5368module.exports = mouseEventPoint;
5369
5370},{"point-geometry":59}],41:[function(require,module,exports){
5371'use strict';
5372
5373var constrainFeatureMovement = require('./constrain_feature_movement');
5374var Constants = require('../constants');
5375
5376module.exports = function (features, delta) {
5377 var constrainedDelta = constrainFeatureMovement(features.map(function (feature) {
5378 return feature.toGeoJSON();
5379 }), delta);
5380
5381 features.forEach(function (feature) {
5382 var currentCoordinates = feature.getCoordinates();
5383
5384 var moveCoordinate = function moveCoordinate(coord) {
5385 var point = {
5386 lng: coord[0] + constrainedDelta.lng,
5387 lat: coord[1] + constrainedDelta.lat
5388 };
5389 return [point.lng, point.lat];
5390 };
5391 var moveRing = function moveRing(ring) {
5392 return ring.map(function (coord) {
5393 return moveCoordinate(coord);
5394 });
5395 };
5396 var moveMultiPolygon = function moveMultiPolygon(multi) {
5397 return multi.map(function (ring) {
5398 return moveRing(ring);
5399 });
5400 };
5401
5402 var nextCoordinates = void 0;
5403 if (feature.type === Constants.geojsonTypes.POINT) {
5404 nextCoordinates = moveCoordinate(currentCoordinates);
5405 } else if (feature.type === Constants.geojsonTypes.LINE_STRING || feature.type === Constants.geojsonTypes.MULTI_POINT) {
5406 nextCoordinates = currentCoordinates.map(moveCoordinate);
5407 } else if (feature.type === Constants.geojsonTypes.POLYGON || feature.type === Constants.geojsonTypes.MULTI_LINE_STRING) {
5408 nextCoordinates = currentCoordinates.map(moveRing);
5409 } else if (feature.type === Constants.geojsonTypes.MULTI_POLYGON) {
5410 nextCoordinates = currentCoordinates.map(moveMultiPolygon);
5411 }
5412
5413 feature.incomingCoords(nextCoordinates);
5414 });
5415};
5416
5417},{"../constants":20,"./constrain_feature_movement":28}],42:[function(require,module,exports){
5418'use strict';
5419
5420var area = require('geojson-area');
5421var Constants = require('../constants');
5422
5423var FEATURE_SORT_RANKS = {
5424 Point: 0,
5425 LineString: 1,
5426 Polygon: 2
5427};
5428
5429function comparator(a, b) {
5430 var score = FEATURE_SORT_RANKS[a.geometry.type] - FEATURE_SORT_RANKS[b.geometry.type];
5431
5432 if (score === 0 && a.geometry.type === Constants.geojsonTypes.POLYGON) {
5433 return a.area - b.area;
5434 }
5435
5436 return score;
5437}
5438
5439// Sort in the order above, then sort polygons by area ascending.
5440function sortFeatures(features) {
5441 return features.map(function (feature) {
5442 if (feature.geometry.type === Constants.geojsonTypes.POLYGON) {
5443 feature.area = area.geometry({
5444 type: Constants.geojsonTypes.FEATURE,
5445 property: {},
5446 geometry: feature.geometry
5447 });
5448 }
5449 return feature;
5450 }).sort(comparator).map(function (feature) {
5451 delete feature.area;
5452 return feature;
5453 });
5454}
5455
5456module.exports = sortFeatures;
5457
5458},{"../constants":20,"geojson-area":5}],43:[function(require,module,exports){
5459"use strict";
5460
5461function StringSet(items) {
5462 this._items = {};
5463 this._length = items ? items.length : 0;
5464 if (!items) return;
5465 for (var i = 0, l = items.length; i < l; i++) {
5466 if (items[i] === undefined) continue;
5467 this._items[items[i]] = i;
5468 }
5469}
5470
5471StringSet.prototype.add = function (x) {
5472 this._length = this._items[x] ? this._length : this._length + 1;
5473 this._items[x] = this._items[x] ? this._items[x] : this._length;
5474 return this;
5475};
5476
5477StringSet.prototype.delete = function (x) {
5478 this._length = this._items[x] ? this._length - 1 : this._length;
5479 delete this._items[x];
5480 return this;
5481};
5482
5483StringSet.prototype.has = function (x) {
5484 return this._items[x] !== undefined;
5485};
5486
5487StringSet.prototype.values = function () {
5488 var _this = this;
5489
5490 var orderedKeys = Object.keys(this._items).sort(function (a, b) {
5491 return _this._items[a] - _this._items[b];
5492 });
5493 return orderedKeys;
5494};
5495
5496StringSet.prototype.clear = function () {
5497 this._length = 0;
5498 this._items = {};
5499 return this;
5500};
5501
5502module.exports = StringSet;
5503
5504},{}],44:[function(require,module,exports){
5505"use strict";
5506
5507module.exports = function (a, b) {
5508 if (a.length !== b.length) return false;
5509 return JSON.stringify(a.map(function (id) {
5510 return id;
5511 }).sort()) === JSON.stringify(b.map(function (id) {
5512 return id;
5513 }).sort());
5514};
5515
5516},{}],45:[function(require,module,exports){
5517'use strict';
5518
5519module.exports = [{
5520 'id': 'gl-draw-polygon-fill-inactive',
5521 'type': 'fill',
5522 'filter': ['all', ['==', 'active', 'false'], ['==', '$type', 'Polygon'], ['!=', 'mode', 'static']],
5523 'paint': {
5524 'fill-color': '#3bb2d0',
5525 'fill-outline-color': '#3bb2d0',
5526 'fill-opacity': 0.1
5527 }
5528}, {
5529 'id': 'gl-draw-polygon-fill-active',
5530 'type': 'fill',
5531 'filter': ['all', ['==', 'active', 'true'], ['==', '$type', 'Polygon']],
5532 'paint': {
5533 'fill-color': '#fbb03b',
5534 'fill-outline-color': '#fbb03b',
5535 'fill-opacity': 0.1
5536 }
5537}, {
5538 'id': 'gl-draw-polygon-midpoint',
5539 'type': 'circle',
5540 'filter': ['all', ['==', '$type', 'Point'], ['==', 'meta', 'midpoint']],
5541 'paint': {
5542 'circle-radius': 3,
5543 'circle-color': '#fbb03b'
5544 }
5545}, {
5546 'id': 'gl-draw-polygon-stroke-inactive',
5547 'type': 'line',
5548 'filter': ['all', ['==', 'active', 'false'], ['==', '$type', 'Polygon'], ['!=', 'mode', 'static']],
5549 'layout': {
5550 'line-cap': 'round',
5551 'line-join': 'round'
5552 },
5553 'paint': {
5554 'line-color': '#3bb2d0',
5555 'line-width': 2
5556 }
5557}, {
5558 'id': 'gl-draw-polygon-stroke-active',
5559 'type': 'line',
5560 'filter': ['all', ['==', 'active', 'true'], ['==', '$type', 'Polygon']],
5561 'layout': {
5562 'line-cap': 'round',
5563 'line-join': 'round'
5564 },
5565 'paint': {
5566 'line-color': '#fbb03b',
5567 'line-dasharray': [0.2, 2],
5568 'line-width': 2
5569 }
5570}, {
5571 'id': 'gl-draw-line-inactive',
5572 'type': 'line',
5573 'filter': ['all', ['==', 'active', 'false'], ['==', '$type', 'LineString'], ['!=', 'mode', 'static']],
5574 'layout': {
5575 'line-cap': 'round',
5576 'line-join': 'round'
5577 },
5578 'paint': {
5579 'line-color': '#3bb2d0',
5580 'line-width': 2
5581 }
5582}, {
5583 'id': 'gl-draw-line-active',
5584 'type': 'line',
5585 'filter': ['all', ['==', '$type', 'LineString'], ['==', 'active', 'true']],
5586 'layout': {
5587 'line-cap': 'round',
5588 'line-join': 'round'
5589 },
5590 'paint': {
5591 'line-color': '#fbb03b',
5592 'line-dasharray': [0.2, 2],
5593 'line-width': 2
5594 }
5595}, {
5596 'id': 'gl-draw-polygon-and-line-vertex-stroke-inactive',
5597 'type': 'circle',
5598 'filter': ['all', ['==', 'meta', 'vertex'], ['==', '$type', 'Point'], ['!=', 'mode', 'static']],
5599 'paint': {
5600 'circle-radius': 5,
5601 'circle-color': '#fff'
5602 }
5603}, {
5604 'id': 'gl-draw-polygon-and-line-vertex-inactive',
5605 'type': 'circle',
5606 'filter': ['all', ['==', 'meta', 'vertex'], ['==', '$type', 'Point'], ['!=', 'mode', 'static']],
5607 'paint': {
5608 'circle-radius': 3,
5609 'circle-color': '#fbb03b'
5610 }
5611}, {
5612 'id': 'gl-draw-point-point-stroke-inactive',
5613 'type': 'circle',
5614 'filter': ['all', ['==', 'active', 'false'], ['==', '$type', 'Point'], ['==', 'meta', 'feature'], ['!=', 'mode', 'static']],
5615 'paint': {
5616 'circle-radius': 5,
5617 'circle-opacity': 1,
5618 'circle-color': '#fff'
5619 }
5620}, {
5621 'id': 'gl-draw-point-inactive',
5622 'type': 'circle',
5623 'filter': ['all', ['==', 'active', 'false'], ['==', '$type', 'Point'], ['==', 'meta', 'feature'], ['!=', 'mode', 'static']],
5624 'paint': {
5625 'circle-radius': 3,
5626 'circle-color': '#3bb2d0'
5627 }
5628}, {
5629 'id': 'gl-draw-point-stroke-active',
5630 'type': 'circle',
5631 'filter': ['all', ['==', '$type', 'Point'], ['==', 'active', 'true'], ['!=', 'meta', 'midpoint']],
5632 'paint': {
5633 'circle-radius': 7,
5634 'circle-color': '#fff'
5635 }
5636}, {
5637 'id': 'gl-draw-point-active',
5638 'type': 'circle',
5639 'filter': ['all', ['==', '$type', 'Point'], ['!=', 'meta', 'midpoint'], ['==', 'active', 'true']],
5640 'paint': {
5641 'circle-radius': 5,
5642 'circle-color': '#fbb03b'
5643 }
5644}, {
5645 'id': 'gl-draw-polygon-fill-static',
5646 'type': 'fill',
5647 'filter': ['all', ['==', 'mode', 'static'], ['==', '$type', 'Polygon']],
5648 'paint': {
5649 'fill-color': '#404040',
5650 'fill-outline-color': '#404040',
5651 'fill-opacity': 0.1
5652 }
5653}, {
5654 'id': 'gl-draw-polygon-stroke-static',
5655 'type': 'line',
5656 'filter': ['all', ['==', 'mode', 'static'], ['==', '$type', 'Polygon']],
5657 'layout': {
5658 'line-cap': 'round',
5659 'line-join': 'round'
5660 },
5661 'paint': {
5662 'line-color': '#404040',
5663 'line-width': 2
5664 }
5665}, {
5666 'id': 'gl-draw-line-static',
5667 'type': 'line',
5668 'filter': ['all', ['==', 'mode', 'static'], ['==', '$type', 'LineString']],
5669 'layout': {
5670 'line-cap': 'round',
5671 'line-join': 'round'
5672 },
5673 'paint': {
5674 'line-color': '#404040',
5675 'line-width': 2
5676 }
5677}, {
5678 'id': 'gl-draw-point-static',
5679 'type': 'circle',
5680 'filter': ['all', ['==', 'mode', 'static'], ['==', '$type', 'Point']],
5681 'paint': {
5682 'circle-radius': 5,
5683 'circle-color': '#404040'
5684 }
5685}];
5686
5687},{}],46:[function(require,module,exports){
5688"use strict";
5689
5690function throttle(fn, time, context) {
5691 var lock = void 0,
5692 args = void 0;
5693
5694 function later() {
5695 // reset lock and call if queued
5696 lock = false;
5697 if (args) {
5698 wrapperFn.apply(context, args);
5699 args = false;
5700 }
5701 }
5702
5703 function wrapperFn() {
5704 if (lock) {
5705 // called too soon, queue to call later
5706 args = arguments;
5707 } else {
5708 // lock until later then call
5709 lock = true;
5710 fn.apply(context, arguments);
5711 setTimeout(later, time);
5712 }
5713 }
5714
5715 return wrapperFn;
5716}
5717
5718module.exports = throttle;
5719
5720},{}],47:[function(require,module,exports){
5721"use strict";
5722
5723/**
5724 * Derive a dense array (no `undefined`s) from a single value or array.
5725 *
5726 * @param {any} x
5727 * @return {Array<any>}
5728 */
5729function toDenseArray(x) {
5730 return [].concat(x).filter(function (y) {
5731 return y !== undefined;
5732 });
5733}
5734
5735module.exports = toDenseArray;
5736
5737},{}],48:[function(require,module,exports){
5738'use strict';
5739
5740var _require = require('../lib/common_selectors'),
5741 noTarget = _require.noTarget,
5742 isOfMetaType = _require.isOfMetaType,
5743 isInactiveFeature = _require.isInactiveFeature,
5744 isShiftDown = _require.isShiftDown;
5745
5746var createSupplementaryPoints = require('../lib/create_supplementary_points');
5747var constrainFeatureMovement = require('../lib/constrain_feature_movement');
5748var doubleClickZoom = require('../lib/double_click_zoom');
5749var Constants = require('../constants');
5750var CommonSelectors = require('../lib/common_selectors');
5751var moveFeatures = require('../lib/move_features');
5752
5753var isVertex = isOfMetaType(Constants.meta.VERTEX);
5754var isMidpoint = isOfMetaType(Constants.meta.MIDPOINT);
5755
5756module.exports = function (ctx, opts) {
5757 var featureId = opts.featureId;
5758 var feature = ctx.store.get(featureId);
5759
5760 if (!feature) {
5761 throw new Error('You must provide a featureId to enter direct_select mode');
5762 }
5763
5764 if (feature.type === Constants.geojsonTypes.POINT) {
5765 throw new TypeError('direct_select mode doesn\'t handle point features');
5766 }
5767
5768 var dragMoveLocation = opts.startPos || null;
5769 var dragMoving = false;
5770 var canDragMove = false;
5771
5772 var selectedCoordPaths = opts.coordPath ? [opts.coordPath] : [];
5773
5774 var fireUpdate = function fireUpdate() {
5775 ctx.map.fire(Constants.events.UPDATE, {
5776 action: Constants.updateActions.CHANGE_COORDINATES,
5777 features: ctx.store.getSelected().map(function (f) {
5778 return f.toGeoJSON();
5779 })
5780 });
5781 };
5782
5783 var fireActionable = function fireActionable() {
5784 return ctx.events.actionable({
5785 combineFeatures: false,
5786 uncombineFeatures: false,
5787 trash: selectedCoordPaths.length > 0
5788 });
5789 };
5790
5791 var startDragging = function startDragging(e) {
5792 ctx.map.dragPan.disable();
5793 canDragMove = true;
5794 dragMoveLocation = e.lngLat;
5795 };
5796
5797 var stopDragging = function stopDragging() {
5798 ctx.map.dragPan.enable();
5799 dragMoving = false;
5800 canDragMove = false;
5801 dragMoveLocation = null;
5802 };
5803
5804 var onVertex = function onVertex(e) {
5805 startDragging(e);
5806 var about = e.featureTarget.properties;
5807 var selectedIndex = selectedCoordPaths.indexOf(about.coord_path);
5808 if (!isShiftDown(e) && selectedIndex === -1) {
5809 selectedCoordPaths = [about.coord_path];
5810 } else if (isShiftDown(e) && selectedIndex === -1) {
5811 selectedCoordPaths.push(about.coord_path);
5812 }
5813 feature.changed();
5814 };
5815
5816 var onMidpoint = function onMidpoint(e) {
5817 startDragging(e);
5818 var about = e.featureTarget.properties;
5819 feature.addCoordinate(about.coord_path, about.lng, about.lat);
5820 fireUpdate();
5821 selectedCoordPaths = [about.coord_path];
5822 };
5823
5824 var onFeature = function onFeature(e) {
5825 if (selectedCoordPaths.length === 0) startDragging(e);else stopDragging();
5826 };
5827
5828 var dragFeature = function dragFeature(e, delta) {
5829 moveFeatures(ctx.store.getSelected(), delta);
5830 dragMoveLocation = e.lngLat;
5831 };
5832
5833 var dragVertex = function dragVertex(e, delta) {
5834 var selectedCoords = selectedCoordPaths.map(function (coord_path) {
5835 return feature.getCoordinate(coord_path);
5836 });
5837 var selectedCoordPoints = selectedCoords.map(function (coords) {
5838 return {
5839 type: Constants.geojsonTypes.FEATURE,
5840 properties: {},
5841 geometry: {
5842 type: Constants.geojsonTypes.POINT,
5843 coordinates: coords
5844 }
5845 };
5846 });
5847
5848 var constrainedDelta = constrainFeatureMovement(selectedCoordPoints, delta);
5849 for (var i = 0; i < selectedCoords.length; i++) {
5850 var coord = selectedCoords[i];
5851 feature.updateCoordinate(selectedCoordPaths[i], coord[0] + constrainedDelta.lng, coord[1] + constrainedDelta.lat);
5852 }
5853 };
5854
5855 return {
5856 start: function start() {
5857 ctx.store.setSelected(featureId);
5858 doubleClickZoom.disable(ctx);
5859
5860 // On mousemove that is not a drag, stop vertex movement.
5861 this.on('mousemove', CommonSelectors.true, function (e) {
5862 var isFeature = CommonSelectors.isActiveFeature(e);
5863 var onVertex = isVertex(e);
5864 var noCoords = selectedCoordPaths.length === 0;
5865 if (isFeature && noCoords) ctx.ui.queueMapClasses({ mouse: Constants.cursors.MOVE });else if (onVertex && !noCoords) ctx.ui.queueMapClasses({ mouse: Constants.cursors.MOVE });else ctx.ui.queueMapClasses({ mouse: Constants.cursors.NONE });
5866 stopDragging(e);
5867 });
5868
5869 // As soon as you mouse leaves the canvas, update the feature
5870 this.on('mouseout', function () {
5871 return dragMoving;
5872 }, fireUpdate);
5873
5874 this.on('mousedown', isVertex, onVertex);
5875 this.on('mousedown', CommonSelectors.isActiveFeature, onFeature);
5876 this.on('mousedown', isMidpoint, onMidpoint);
5877 this.on('drag', function () {
5878 return canDragMove;
5879 }, function (e) {
5880 dragMoving = true;
5881 e.originalEvent.stopPropagation();
5882
5883 var delta = {
5884 lng: e.lngLat.lng - dragMoveLocation.lng,
5885 lat: e.lngLat.lat - dragMoveLocation.lat
5886 };
5887 if (selectedCoordPaths.length > 0) dragVertex(e, delta);else dragFeature(e, delta);
5888
5889 dragMoveLocation = e.lngLat;
5890 });
5891 this.on('click', CommonSelectors.true, stopDragging);
5892 this.on('mouseup', CommonSelectors.true, function () {
5893 if (dragMoving) {
5894 fireUpdate();
5895 }
5896 stopDragging();
5897 });
5898 this.on('click', noTarget, function () {
5899 ctx.events.changeMode(Constants.modes.SIMPLE_SELECT);
5900 });
5901 this.on('click', isInactiveFeature, function () {
5902 ctx.events.changeMode(Constants.modes.SIMPLE_SELECT);
5903 });
5904 this.on('click', CommonSelectors.isActiveFeature, function () {
5905 selectedCoordPaths = [];
5906 feature.changed();
5907 });
5908 },
5909 stop: function stop() {
5910 doubleClickZoom.enable(ctx);
5911 },
5912 render: function render(geojson, push) {
5913 if (featureId === geojson.properties.id) {
5914 geojson.properties.active = Constants.activeStates.ACTIVE;
5915 push(geojson);
5916 createSupplementaryPoints(geojson, {
5917 map: ctx.map,
5918 midpoints: true,
5919 selectedPaths: selectedCoordPaths
5920 }).forEach(push);
5921 } else {
5922 geojson.properties.active = Constants.activeStates.INACTIVE;
5923 push(geojson);
5924 }
5925 fireActionable();
5926 },
5927 trash: function trash() {
5928 selectedCoordPaths.sort().reverse().forEach(function (id) {
5929 return feature.removeCoordinate(id);
5930 });
5931 ctx.map.fire(Constants.events.UPDATE, {
5932 action: Constants.updateActions.CHANGE_COORDINATES,
5933 features: ctx.store.getSelected().map(function (f) {
5934 return f.toGeoJSON();
5935 })
5936 });
5937 selectedCoordPaths = [];
5938 fireActionable();
5939 if (feature.isValid() === false) {
5940 ctx.store.delete([featureId]);
5941 ctx.events.changeMode(Constants.modes.SIMPLE_SELECT, {});
5942 }
5943 }
5944 };
5945};
5946
5947},{"../constants":20,"../lib/common_selectors":27,"../lib/constrain_feature_movement":28,"../lib/create_supplementary_points":30,"../lib/double_click_zoom":32,"../lib/move_features":41}],49:[function(require,module,exports){
5948'use strict';
5949
5950var CommonSelectors = require('../lib/common_selectors');
5951var LineString = require('../feature_types/line_string');
5952var isEventAtCoordinates = require('../lib/is_event_at_coordinates');
5953var doubleClickZoom = require('../lib/double_click_zoom');
5954var Constants = require('../constants');
5955var createVertex = require('../lib/create_vertex');
5956
5957module.exports = function (ctx) {
5958 var line = new LineString(ctx, {
5959 type: Constants.geojsonTypes.FEATURE,
5960 properties: {},
5961 geometry: {
5962 type: Constants.geojsonTypes.LINE_STRING,
5963 coordinates: []
5964 }
5965 });
5966 var currentVertexPosition = 0;
5967
5968 if (ctx._test) ctx._test.line = line;
5969
5970 ctx.store.add(line);
5971
5972 return {
5973 start: function start() {
5974 ctx.store.clearSelected();
5975 doubleClickZoom.disable(ctx);
5976 ctx.ui.queueMapClasses({ mouse: Constants.cursors.ADD });
5977 ctx.ui.setActiveButton(Constants.types.LINE);
5978 this.on('mousemove', CommonSelectors.true, function (e) {
5979 line.updateCoordinate(currentVertexPosition, e.lngLat.lng, e.lngLat.lat);
5980 if (CommonSelectors.isVertex(e)) {
5981 ctx.ui.queueMapClasses({ mouse: Constants.cursors.POINTER });
5982 }
5983 });
5984 this.on('click', CommonSelectors.true, function (e) {
5985 if (currentVertexPosition > 0 && isEventAtCoordinates(e, line.coordinates[currentVertexPosition - 1])) {
5986 return ctx.events.changeMode(Constants.modes.SIMPLE_SELECT, { featureIds: [line.id] });
5987 }
5988 ctx.ui.queueMapClasses({ mouse: Constants.cursors.ADD });
5989 line.updateCoordinate(currentVertexPosition, e.lngLat.lng, e.lngLat.lat);
5990 currentVertexPosition++;
5991 });
5992 this.on('click', CommonSelectors.isVertex, function () {
5993 return ctx.events.changeMode(Constants.modes.SIMPLE_SELECT, { featureIds: [line.id] });
5994 });
5995 this.on('keyup', CommonSelectors.isEscapeKey, function () {
5996 ctx.store.delete([line.id], { silent: true });
5997 ctx.events.changeMode(Constants.modes.SIMPLE_SELECT);
5998 });
5999 this.on('keyup', CommonSelectors.isEnterKey, function () {
6000 ctx.events.changeMode(Constants.modes.SIMPLE_SELECT, { featureIds: [line.id] });
6001 });
6002 ctx.events.actionable({
6003 combineFeatures: false,
6004 uncombineFeatures: false,
6005 trash: true
6006 });
6007 },
6008
6009 stop: function stop() {
6010 doubleClickZoom.enable(ctx);
6011 ctx.ui.setActiveButton();
6012
6013 // check to see if we've deleted this feature
6014 if (ctx.store.get(line.id) === undefined) return;
6015
6016 //remove last added coordinate
6017 line.removeCoordinate('' + currentVertexPosition);
6018 if (line.isValid()) {
6019 ctx.map.fire(Constants.events.CREATE, {
6020 features: [line.toGeoJSON()]
6021 });
6022 } else {
6023 ctx.store.delete([line.id], { silent: true });
6024 ctx.events.changeMode(Constants.modes.SIMPLE_SELECT, {}, { silent: true });
6025 }
6026 },
6027 render: function render(geojson, callback) {
6028 var isActiveLine = geojson.properties.id === line.id;
6029 geojson.properties.active = isActiveLine ? Constants.activeStates.ACTIVE : Constants.activeStates.INACTIVE;
6030 if (!isActiveLine) return callback(geojson);
6031
6032 // Only render the line if it has at least one real coordinate
6033 if (geojson.geometry.coordinates.length < 2) return;
6034 geojson.properties.meta = Constants.meta.FEATURE;
6035
6036 if (geojson.geometry.coordinates.length >= 3) {
6037 callback(createVertex(line.id, geojson.geometry.coordinates[geojson.geometry.coordinates.length - 2], '' + (geojson.geometry.coordinates.length - 2), false));
6038 }
6039
6040 callback(geojson);
6041 },
6042 trash: function trash() {
6043 ctx.store.delete([line.id], { silent: true });
6044 ctx.events.changeMode(Constants.modes.SIMPLE_SELECT);
6045 }
6046 };
6047};
6048
6049},{"../constants":20,"../feature_types/line_string":23,"../lib/common_selectors":27,"../lib/create_vertex":31,"../lib/double_click_zoom":32,"../lib/is_event_at_coordinates":37}],50:[function(require,module,exports){
6050'use strict';
6051
6052var CommonSelectors = require('../lib/common_selectors');
6053var Point = require('../feature_types/point');
6054var Constants = require('../constants');
6055
6056module.exports = function (ctx) {
6057
6058 var point = new Point(ctx, {
6059 type: Constants.geojsonTypes.FEATURE,
6060 properties: {},
6061 geometry: {
6062 type: Constants.geojsonTypes.POINT,
6063 coordinates: []
6064 }
6065 });
6066
6067 if (ctx._test) ctx._test.point = point;
6068
6069 ctx.store.add(point);
6070
6071 function stopDrawingAndRemove() {
6072 ctx.events.changeMode(Constants.modes.SIMPLE_SELECT);
6073 ctx.store.delete([point.id], { silent: true });
6074 }
6075
6076 function handleClick(e) {
6077 ctx.ui.queueMapClasses({ mouse: Constants.cursors.MOVE });
6078 point.updateCoordinate('', e.lngLat.lng, e.lngLat.lat);
6079 ctx.map.fire(Constants.events.CREATE, {
6080 features: [point.toGeoJSON()]
6081 });
6082 ctx.events.changeMode(Constants.modes.SIMPLE_SELECT, { featureIds: [point.id] });
6083 }
6084
6085 return {
6086 start: function start() {
6087 ctx.store.clearSelected();
6088 ctx.ui.queueMapClasses({ mouse: Constants.cursors.ADD });
6089 ctx.ui.setActiveButton(Constants.types.POINT);
6090 this.on('click', CommonSelectors.true, handleClick);
6091 this.on('keyup', CommonSelectors.isEscapeKey, stopDrawingAndRemove);
6092 this.on('keyup', CommonSelectors.isEnterKey, stopDrawingAndRemove);
6093 ctx.events.actionable({
6094 combineFeatures: false,
6095 uncombineFeatures: false,
6096 trash: true
6097 });
6098 },
6099 stop: function stop() {
6100 ctx.ui.setActiveButton();
6101 if (!point.getCoordinate().length) {
6102 ctx.store.delete([point.id], { silent: true });
6103 }
6104 },
6105 render: function render(geojson, callback) {
6106 var isActivePoint = geojson.properties.id === point.id;
6107 geojson.properties.active = isActivePoint ? Constants.activeStates.ACTIVE : Constants.activeStates.INACTIVE;
6108 if (!isActivePoint) return callback(geojson);
6109 // Never render the point we're drawing
6110 },
6111 trash: function trash() {
6112 stopDrawingAndRemove();
6113 }
6114 };
6115};
6116
6117},{"../constants":20,"../feature_types/point":25,"../lib/common_selectors":27}],51:[function(require,module,exports){
6118'use strict';
6119
6120var CommonSelectors = require('../lib/common_selectors');
6121var Polygon = require('../feature_types/polygon');
6122var doubleClickZoom = require('../lib/double_click_zoom');
6123var Constants = require('../constants');
6124var isEventAtCoordinates = require('../lib/is_event_at_coordinates');
6125var createVertex = require('../lib/create_vertex');
6126
6127module.exports = function (ctx) {
6128
6129 var polygon = new Polygon(ctx, {
6130 type: Constants.geojsonTypes.FEATURE,
6131 properties: {},
6132 geometry: {
6133 type: Constants.geojsonTypes.POLYGON,
6134 coordinates: [[]]
6135 }
6136 });
6137 var currentVertexPosition = 0;
6138
6139 if (ctx._test) ctx._test.polygon = polygon;
6140
6141 ctx.store.add(polygon);
6142
6143 return {
6144 start: function start() {
6145 ctx.store.clearSelected();
6146 doubleClickZoom.disable(ctx);
6147 ctx.ui.queueMapClasses({ mouse: Constants.cursors.ADD });
6148 ctx.ui.setActiveButton(Constants.types.POLYGON);
6149 this.on('mousemove', CommonSelectors.true, function (e) {
6150 polygon.updateCoordinate('0.' + currentVertexPosition, e.lngLat.lng, e.lngLat.lat);
6151 if (CommonSelectors.isVertex(e)) {
6152 ctx.ui.queueMapClasses({ mouse: Constants.cursors.POINTER });
6153 }
6154 });
6155 this.on('click', CommonSelectors.true, function (e) {
6156 if (currentVertexPosition > 0 && isEventAtCoordinates(e, polygon.coordinates[0][currentVertexPosition - 1])) {
6157 return ctx.events.changeMode(Constants.modes.SIMPLE_SELECT, { featureIds: [polygon.id] });
6158 }
6159 ctx.ui.queueMapClasses({ mouse: Constants.cursors.ADD });
6160 polygon.updateCoordinate('0.' + currentVertexPosition, e.lngLat.lng, e.lngLat.lat);
6161 currentVertexPosition++;
6162 });
6163 this.on('click', CommonSelectors.isVertex, function () {
6164 return ctx.events.changeMode(Constants.modes.SIMPLE_SELECT, { featureIds: [polygon.id] });
6165 });
6166 this.on('keyup', CommonSelectors.isEscapeKey, function () {
6167 ctx.store.delete([polygon.id], { silent: true });
6168 ctx.events.changeMode(Constants.modes.SIMPLE_SELECT);
6169 });
6170 this.on('keyup', CommonSelectors.isEnterKey, function () {
6171 ctx.events.changeMode(Constants.modes.SIMPLE_SELECT, { featureIds: [polygon.id] });
6172 });
6173 ctx.events.actionable({
6174 combineFeatures: false,
6175 uncombineFeatures: false,
6176 trash: true
6177 });
6178 },
6179
6180
6181 stop: function stop() {
6182 ctx.ui.queueMapClasses({ mouse: Constants.cursors.NONE });
6183 doubleClickZoom.enable(ctx);
6184 ctx.ui.setActiveButton();
6185
6186 // check to see if we've deleted this feature
6187 if (ctx.store.get(polygon.id) === undefined) return;
6188
6189 //remove last added coordinate
6190 polygon.removeCoordinate('0.' + currentVertexPosition);
6191 if (polygon.isValid()) {
6192 ctx.map.fire(Constants.events.CREATE, {
6193 features: [polygon.toGeoJSON()]
6194 });
6195 } else {
6196 ctx.store.delete([polygon.id], { silent: true });
6197 ctx.events.changeMode(Constants.modes.SIMPLE_SELECT, {}, { silent: true });
6198 }
6199 },
6200
6201 render: function render(geojson, callback) {
6202 var isActivePolygon = geojson.properties.id === polygon.id;
6203 geojson.properties.active = isActivePolygon ? Constants.activeStates.ACTIVE : Constants.activeStates.INACTIVE;
6204 if (!isActivePolygon) return callback(geojson);
6205
6206 // Don't render a polygon until it has two positions
6207 // (and a 3rd which is just the first repeated)
6208 if (geojson.geometry.coordinates.length === 0) return;
6209
6210 var coordinateCount = geojson.geometry.coordinates[0].length;
6211
6212 // If we have fewer than two positions (plus the closer),
6213 // it's not yet a shape to render
6214 if (coordinateCount < 3) return;
6215
6216 geojson.properties.meta = Constants.meta.FEATURE;
6217
6218 if (coordinateCount > 4) {
6219 // Add a start position marker to the map, clicking on this will finish the feature
6220 // This should only be shown when we're in a valid spot
6221 callback(createVertex(polygon.id, geojson.geometry.coordinates[0][0], '0.0', false));
6222 var endPos = geojson.geometry.coordinates[0].length - 3;
6223 callback(createVertex(polygon.id, geojson.geometry.coordinates[0][endPos], '0.' + endPos, false));
6224 }
6225
6226 // If we have more than two positions (plus the closer),
6227 // render the Polygon
6228 if (coordinateCount > 3) {
6229 return callback(geojson);
6230 }
6231
6232 // If we've only drawn two positions (plus the closer),
6233 // make a LineString instead of a Polygon
6234 var lineCoordinates = [[geojson.geometry.coordinates[0][0][0], geojson.geometry.coordinates[0][0][1]], [geojson.geometry.coordinates[0][1][0], geojson.geometry.coordinates[0][1][1]]];
6235 return callback({
6236 type: Constants.geojsonTypes.FEATURE,
6237 properties: geojson.properties,
6238 geometry: {
6239 coordinates: lineCoordinates,
6240 type: Constants.geojsonTypes.LINE_STRING
6241 }
6242 });
6243 },
6244 trash: function trash() {
6245 ctx.store.delete([polygon.id], { silent: true });
6246 ctx.events.changeMode(Constants.modes.SIMPLE_SELECT);
6247 }
6248 };
6249};
6250
6251},{"../constants":20,"../feature_types/polygon":26,"../lib/common_selectors":27,"../lib/create_vertex":31,"../lib/double_click_zoom":32,"../lib/is_event_at_coordinates":37}],52:[function(require,module,exports){
6252'use strict';
6253
6254var CommonSelectors = require('../lib/common_selectors');
6255var mouseEventPoint = require('../lib/mouse_event_point');
6256var featuresAt = require('../lib/features_at');
6257var createSupplementaryPoints = require('../lib/create_supplementary_points');
6258var StringSet = require('../lib/string_set');
6259var doubleClickZoom = require('../lib/double_click_zoom');
6260var moveFeatures = require('../lib/move_features');
6261var Constants = require('../constants');
6262var MultiFeature = require('../feature_types/multi_feature');
6263
6264module.exports = function (ctx) {
6265 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
6266
6267 var dragMoveLocation = null;
6268 var boxSelectStartLocation = null;
6269 var boxSelectElement = void 0;
6270 var boxSelecting = false;
6271 var canBoxSelect = false;
6272 var dragMoving = false;
6273 var canDragMove = false;
6274
6275 var initiallySelectedFeatureIds = options.featureIds || [];
6276
6277 var fireUpdate = function fireUpdate() {
6278 ctx.map.fire(Constants.events.UPDATE, {
6279 action: Constants.updateActions.MOVE,
6280 features: ctx.store.getSelected().map(function (f) {
6281 return f.toGeoJSON();
6282 })
6283 });
6284 };
6285
6286 var fireActionable = function fireActionable() {
6287 var selectedFeatures = ctx.store.getSelected();
6288
6289 var multiFeatures = selectedFeatures.filter(function (feature) {
6290 return feature instanceof MultiFeature;
6291 });
6292
6293 var combineFeatures = false;
6294
6295 if (selectedFeatures.length > 1) {
6296 combineFeatures = true;
6297 var featureType = selectedFeatures[0].type.replace('Multi', '');
6298 selectedFeatures.forEach(function (feature) {
6299 if (feature.type.replace('Multi', '') !== featureType) {
6300 combineFeatures = false;
6301 }
6302 });
6303 }
6304
6305 var uncombineFeatures = multiFeatures.length > 0;
6306 var trash = selectedFeatures.length > 0;
6307
6308 ctx.events.actionable({
6309 combineFeatures: combineFeatures, uncombineFeatures: uncombineFeatures, trash: trash
6310 });
6311 };
6312
6313 var getUniqueIds = function getUniqueIds(allFeatures) {
6314 if (!allFeatures.length) return [];
6315 var ids = allFeatures.map(function (s) {
6316 return s.properties.id;
6317 }).filter(function (id) {
6318 return id !== undefined;
6319 }).reduce(function (memo, id) {
6320 memo.add(id);
6321 return memo;
6322 }, new StringSet());
6323
6324 return ids.values();
6325 };
6326
6327 var stopExtendedInteractions = function stopExtendedInteractions() {
6328 if (boxSelectElement) {
6329 if (boxSelectElement.parentNode) boxSelectElement.parentNode.removeChild(boxSelectElement);
6330 boxSelectElement = null;
6331 }
6332
6333 ctx.map.dragPan.enable();
6334
6335 boxSelecting = false;
6336 canBoxSelect = false;
6337 dragMoving = false;
6338 canDragMove = false;
6339 };
6340
6341 return {
6342 stop: function stop() {
6343 doubleClickZoom.enable(ctx);
6344 },
6345 start: function start() {
6346 // Select features that should start selected,
6347 // probably passed in from a `draw_*` mode
6348 if (ctx.store) {
6349 ctx.store.setSelected(initiallySelectedFeatureIds.filter(function (id) {
6350 return ctx.store.get(id) !== undefined;
6351 }));
6352 fireActionable();
6353 }
6354
6355 // Any mouseup should stop box selecting and dragMoving
6356 this.on('mouseup', CommonSelectors.true, stopExtendedInteractions);
6357
6358 // On mousemove that is not a drag, stop extended interactions.
6359 // This is useful if you drag off the canvas, release the button,
6360 // then move the mouse back over the canvas --- we don't allow the
6361 // interaction to continue then, but we do let it continue if you held
6362 // the mouse button that whole time
6363 this.on('mousemove', CommonSelectors.true, stopExtendedInteractions);
6364
6365 // As soon as you mouse leaves the canvas, update the feature
6366 this.on('mouseout', function () {
6367 return dragMoving;
6368 }, fireUpdate);
6369
6370 // Click (with or without shift) on no feature
6371 this.on('click', CommonSelectors.noTarget, function () {
6372 var _this = this;
6373
6374 // Clear the re-render selection
6375 var wasSelected = ctx.store.getSelectedIds();
6376 if (wasSelected.length) {
6377 ctx.store.clearSelected();
6378 wasSelected.forEach(function (id) {
6379 return _this.render(id);
6380 });
6381 }
6382 doubleClickZoom.enable(ctx);
6383 stopExtendedInteractions();
6384 });
6385
6386 // Click (with or without shift) on a vertex
6387 this.on('click', CommonSelectors.isOfMetaType(Constants.meta.VERTEX), function (e) {
6388 // Enter direct select mode
6389 ctx.events.changeMode(Constants.modes.DIRECT_SELECT, {
6390 featureId: e.featureTarget.properties.parent,
6391 coordPath: e.featureTarget.properties.coord_path,
6392 startPos: e.lngLat
6393 });
6394 ctx.ui.queueMapClasses({ mouse: Constants.cursors.MOVE });
6395 });
6396
6397 // Mousedown on a selected feature
6398 this.on('mousedown', CommonSelectors.isActiveFeature, function (e) {
6399 // Stop any already-underway extended interactions
6400 stopExtendedInteractions();
6401
6402 // Disable map.dragPan immediately so it can't start
6403 ctx.map.dragPan.disable();
6404
6405 // Re-render it and enable drag move
6406 this.render(e.featureTarget.properties.id);
6407
6408 // Set up the state for drag moving
6409 canDragMove = true;
6410 dragMoveLocation = e.lngLat;
6411 });
6412
6413 // Click (with or without shift) on any feature
6414 this.on('click', CommonSelectors.isFeature, function (e) {
6415 // Stop everything
6416 doubleClickZoom.disable(ctx);
6417 stopExtendedInteractions();
6418
6419 var isShiftClick = CommonSelectors.isShiftDown(e);
6420 var selectedFeatureIds = ctx.store.getSelectedIds();
6421 var featureId = e.featureTarget.properties.id;
6422 var isFeatureSelected = ctx.store.isSelected(featureId);
6423
6424 // Click (without shift) on any selected feature but a point
6425 if (!isShiftClick && isFeatureSelected && ctx.store.get(featureId).type !== Constants.geojsonTypes.POINT) {
6426 // Enter direct select mode
6427 return ctx.events.changeMode(Constants.modes.DIRECT_SELECT, {
6428 featureId: featureId
6429 });
6430 }
6431
6432 // Shift-click on a selected feature
6433 if (isFeatureSelected && isShiftClick) {
6434 // Deselect it
6435 ctx.store.deselect(featureId);
6436 ctx.ui.queueMapClasses({ mouse: Constants.cursors.POINTER });
6437 if (selectedFeatureIds.length === 1) {
6438 doubleClickZoom.enable(ctx);
6439 }
6440 // Shift-click on an unselected feature
6441 } else if (!isFeatureSelected && isShiftClick) {
6442 // Add it to the selection
6443 ctx.store.select(featureId);
6444 ctx.ui.queueMapClasses({ mouse: Constants.cursors.MOVE });
6445 // Click (without shift) on an unselected feature
6446 } else if (!isFeatureSelected && !isShiftClick) {
6447 // Make it the only selected feature
6448 selectedFeatureIds.forEach(this.render);
6449 ctx.store.setSelected(featureId);
6450 ctx.ui.queueMapClasses({ mouse: Constants.cursors.MOVE });
6451 }
6452
6453 // No matter what, re-render the clicked feature
6454 this.render(featureId);
6455 });
6456
6457 // Dragging when drag move is enabled
6458 this.on('drag', function () {
6459 return canDragMove;
6460 }, function (e) {
6461 dragMoving = true;
6462 e.originalEvent.stopPropagation();
6463
6464 var delta = {
6465 lng: e.lngLat.lng - dragMoveLocation.lng,
6466 lat: e.lngLat.lat - dragMoveLocation.lat
6467 };
6468
6469 moveFeatures(ctx.store.getSelected(), delta);
6470
6471 dragMoveLocation = e.lngLat;
6472 });
6473
6474 // Mouseup, always
6475 this.on('mouseup', CommonSelectors.true, function (e) {
6476 // End any extended interactions
6477 if (dragMoving) {
6478 fireUpdate();
6479 } else if (boxSelecting) {
6480 var bbox = [boxSelectStartLocation, mouseEventPoint(e.originalEvent, ctx.container)];
6481 var featuresInBox = featuresAt(null, bbox, ctx);
6482 var idsToSelect = getUniqueIds(featuresInBox).filter(function (id) {
6483 return !ctx.store.isSelected(id);
6484 });
6485
6486 if (idsToSelect.length) {
6487 ctx.store.select(idsToSelect);
6488 idsToSelect.forEach(this.render);
6489 ctx.ui.queueMapClasses({ mouse: Constants.cursors.MOVE });
6490 }
6491 }
6492 stopExtendedInteractions();
6493 });
6494
6495 if (ctx.options.boxSelect) {
6496 // Shift-mousedown anywhere
6497 this.on('mousedown', CommonSelectors.isShiftMousedown, function (e) {
6498 stopExtendedInteractions();
6499 ctx.map.dragPan.disable();
6500 // Enable box select
6501 boxSelectStartLocation = mouseEventPoint(e.originalEvent, ctx.container);
6502 canBoxSelect = true;
6503 });
6504
6505 // Drag when box select is enabled
6506 this.on('drag', function () {
6507 return canBoxSelect;
6508 }, function (e) {
6509 boxSelecting = true;
6510 ctx.ui.queueMapClasses({ mouse: Constants.cursors.ADD });
6511
6512 // Create the box node if it doesn't exist
6513 if (!boxSelectElement) {
6514 boxSelectElement = document.createElement('div');
6515 boxSelectElement.classList.add(Constants.classes.BOX_SELECT);
6516 ctx.container.appendChild(boxSelectElement);
6517 }
6518
6519 // Adjust the box node's width and xy position
6520 var current = mouseEventPoint(e.originalEvent, ctx.container);
6521 var minX = Math.min(boxSelectStartLocation.x, current.x);
6522 var maxX = Math.max(boxSelectStartLocation.x, current.x);
6523 var minY = Math.min(boxSelectStartLocation.y, current.y);
6524 var maxY = Math.max(boxSelectStartLocation.y, current.y);
6525 var translateValue = 'translate(' + minX + 'px, ' + minY + 'px)';
6526 boxSelectElement.style.transform = translateValue;
6527 boxSelectElement.style.WebkitTransform = translateValue;
6528 boxSelectElement.style.width = maxX - minX + 'px';
6529 boxSelectElement.style.height = maxY - minY + 'px';
6530 });
6531 }
6532 },
6533 render: function render(geojson, push) {
6534 geojson.properties.active = ctx.store.isSelected(geojson.properties.id) ? Constants.activeStates.ACTIVE : Constants.activeStates.INACTIVE;
6535 push(geojson);
6536 fireActionable();
6537 if (geojson.properties.active !== Constants.activeStates.ACTIVE || geojson.geometry.type === Constants.geojsonTypes.POINT) return;
6538 createSupplementaryPoints(geojson).forEach(push);
6539 },
6540 trash: function trash() {
6541 ctx.store.delete(ctx.store.getSelectedIds());
6542 fireActionable();
6543 },
6544 combineFeatures: function combineFeatures() {
6545 var selectedFeatures = ctx.store.getSelected();
6546
6547 if (selectedFeatures.length === 0 || selectedFeatures.length < 2) return;
6548
6549 var coordinates = [],
6550 featuresCombined = [];
6551 var featureType = selectedFeatures[0].type.replace('Multi', '');
6552
6553 for (var i = 0; i < selectedFeatures.length; i++) {
6554 var feature = selectedFeatures[i];
6555
6556 if (feature.type.replace('Multi', '') !== featureType) {
6557 return;
6558 }
6559 if (feature.type.includes('Multi')) {
6560 feature.getCoordinates().forEach(function (subcoords) {
6561 coordinates.push(subcoords);
6562 });
6563 } else {
6564 coordinates.push(feature.getCoordinates());
6565 }
6566
6567 featuresCombined.push(feature.toGeoJSON());
6568 }
6569
6570 if (featuresCombined.length > 1) {
6571
6572 var multiFeature = new MultiFeature(ctx, {
6573 type: Constants.geojsonTypes.FEATURE,
6574 properties: featuresCombined[0].properties,
6575 geometry: {
6576 type: 'Multi' + featureType,
6577 coordinates: coordinates
6578 }
6579 });
6580
6581 ctx.store.add(multiFeature);
6582 ctx.store.delete(ctx.store.getSelectedIds(), { silent: true });
6583 ctx.store.setSelected([multiFeature.id]);
6584
6585 ctx.map.fire(Constants.events.COMBINE_FEATURES, {
6586 createdFeatures: [multiFeature.toGeoJSON()],
6587 deletedFeatures: featuresCombined
6588 });
6589 }
6590 fireActionable();
6591 },
6592 uncombineFeatures: function uncombineFeatures() {
6593 var selectedFeatures = ctx.store.getSelected();
6594 if (selectedFeatures.length === 0) return;
6595
6596 var createdFeatures = [];
6597 var featuresUncombined = [];
6598
6599 var _loop = function _loop(i) {
6600 var feature = selectedFeatures[i];
6601
6602 if (feature instanceof MultiFeature) {
6603 feature.getFeatures().forEach(function (subFeature) {
6604 ctx.store.add(subFeature);
6605 subFeature.properties = feature.properties;
6606 createdFeatures.push(subFeature.toGeoJSON());
6607 ctx.store.select([subFeature.id]);
6608 });
6609 ctx.store.delete(feature.id, { silent: true });
6610 featuresUncombined.push(feature.toGeoJSON());
6611 }
6612 };
6613
6614 for (var i = 0; i < selectedFeatures.length; i++) {
6615 _loop(i);
6616 }
6617
6618 if (createdFeatures.length > 1) {
6619 ctx.map.fire(Constants.events.UNCOMBINE_FEATURES, {
6620 createdFeatures: createdFeatures,
6621 deletedFeatures: featuresUncombined
6622 });
6623 }
6624 fireActionable();
6625 }
6626 };
6627};
6628
6629},{"../constants":20,"../feature_types/multi_feature":24,"../lib/common_selectors":27,"../lib/create_supplementary_points":30,"../lib/double_click_zoom":32,"../lib/features_at":34,"../lib/mouse_event_point":40,"../lib/move_features":41,"../lib/string_set":43}],53:[function(require,module,exports){
6630"use strict";
6631
6632module.exports = function (ctx) {
6633 return {
6634 stop: function stop() {},
6635 start: function start() {
6636 ctx.events.actionable({
6637 combineFeatures: false,
6638 uncombineFeatures: false,
6639 trash: false
6640 });
6641 },
6642 render: function render(geojson, push) {
6643 push(geojson);
6644 }
6645 };
6646};
6647
6648},{}],54:[function(require,module,exports){
6649'use strict';
6650
6651var xtend = require('xtend');
6652var Constants = require('./constants');
6653
6654var defaultOptions = {
6655 defaultMode: Constants.modes.SIMPLE_SELECT,
6656 keybindings: true,
6657 clickBuffer: 2,
6658 boxSelect: true,
6659 displayControlsDefault: true,
6660 styles: require('./lib/theme'),
6661 controls: {},
6662 userProperties: false
6663};
6664
6665var showControls = {
6666 point: true,
6667 line_string: true,
6668 polygon: true,
6669 trash: true,
6670 combine_features: true,
6671 uncombine_features: true
6672};
6673
6674var hideControls = {
6675 point: false,
6676 line_string: false,
6677 polygon: false,
6678 trash: false,
6679 combine_features: false,
6680 uncombine_features: false
6681};
6682
6683function addSources(styles, sourceBucket) {
6684 return styles.map(function (style) {
6685 if (style.source) return style;
6686 return xtend(style, {
6687 id: style.id + '.' + sourceBucket,
6688 source: sourceBucket === 'hot' ? Constants.sources.HOT : Constants.sources.COLD
6689 });
6690 });
6691}
6692
6693module.exports = function () {
6694 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
6695
6696 var withDefaults = xtend(options);
6697
6698 if (!options.controls) {
6699 withDefaults.controls = {};
6700 }
6701
6702 if (options.displayControlsDefault === false) {
6703 withDefaults.controls = xtend(hideControls, options.controls);
6704 } else {
6705 withDefaults.controls = xtend(showControls, options.controls);
6706 }
6707
6708 withDefaults = xtend(defaultOptions, withDefaults);
6709
6710 // Layers with a shared source should be adjacent for performance reasons
6711 withDefaults.styles = addSources(withDefaults.styles, 'cold').concat(addSources(withDefaults.styles, 'hot'));
6712
6713 return withDefaults;
6714};
6715
6716},{"./constants":20,"./lib/theme":45,"xtend":62}],55:[function(require,module,exports){
6717'use strict';
6718
6719var Constants = require('./constants');
6720
6721module.exports = function render() {
6722 var store = this;
6723 var mapExists = store.ctx.map && store.ctx.map.getSource(Constants.sources.HOT) !== undefined;
6724 if (!mapExists) return cleanup();
6725
6726 var mode = store.ctx.events.currentModeName();
6727
6728 store.ctx.ui.queueMapClasses({ mode: mode });
6729
6730 var newHotIds = [];
6731 var newColdIds = [];
6732
6733 if (store.isDirty) {
6734 newColdIds = store.getAllIds();
6735 } else {
6736 newHotIds = store.getChangedIds().filter(function (id) {
6737 return store.get(id) !== undefined;
6738 });
6739 newColdIds = store.sources.hot.filter(function (geojson) {
6740 return geojson.properties.id && newHotIds.indexOf(geojson.properties.id) === -1 && store.get(geojson.properties.id) !== undefined;
6741 }).map(function (geojson) {
6742 return geojson.properties.id;
6743 });
6744 }
6745
6746 store.sources.hot = [];
6747 var lastColdCount = store.sources.cold.length;
6748 store.sources.cold = store.isDirty ? [] : store.sources.cold.filter(function (geojson) {
6749 var id = geojson.properties.id || geojson.properties.parent;
6750 return newHotIds.indexOf(id) === -1;
6751 });
6752
6753 var coldChanged = lastColdCount !== store.sources.cold.length || newColdIds.length > 0;
6754
6755 newHotIds.forEach(function (id) {
6756 return renderFeature(id, 'hot');
6757 });
6758 newColdIds.forEach(function (id) {
6759 return renderFeature(id, 'cold');
6760 });
6761
6762 function renderFeature(id, source) {
6763 var feature = store.get(id);
6764 var featureInternal = feature.internal(mode);
6765 store.ctx.events.currentModeRender(featureInternal, function (geojson) {
6766 store.sources[source].push(geojson);
6767 });
6768 }
6769
6770 if (coldChanged) {
6771 store.ctx.map.getSource(Constants.sources.COLD).setData({
6772 type: Constants.geojsonTypes.FEATURE_COLLECTION,
6773 features: store.sources.cold
6774 });
6775 }
6776
6777 store.ctx.map.getSource(Constants.sources.HOT).setData({
6778 type: Constants.geojsonTypes.FEATURE_COLLECTION,
6779 features: store.sources.hot
6780 });
6781
6782 if (store._emitSelectionChange) {
6783 store.ctx.map.fire(Constants.events.SELECTION_CHANGE, {
6784 features: store.getSelected().map(function (feature) {
6785 return feature.toGeoJSON();
6786 })
6787 });
6788 store._emitSelectionChange = false;
6789 }
6790
6791 if (store._deletedFeaturesToEmit.length) {
6792 var geojsonToEmit = store._deletedFeaturesToEmit.map(function (feature) {
6793 return feature.toGeoJSON();
6794 });
6795
6796 store._deletedFeaturesToEmit = [];
6797
6798 store.ctx.map.fire(Constants.events.DELETE, {
6799 features: geojsonToEmit
6800 });
6801 }
6802
6803 store.ctx.map.fire(Constants.events.RENDER, {});
6804 cleanup();
6805
6806 function cleanup() {
6807 store.isDirty = false;
6808 store.clearChangedIds();
6809 }
6810};
6811
6812},{"./constants":20}],56:[function(require,module,exports){
6813'use strict';
6814
6815var events = require('./events');
6816var Store = require('./store');
6817var ui = require('./ui');
6818var Constants = require('./constants');
6819
6820module.exports = function (ctx) {
6821
6822 ctx.events = events(ctx);
6823
6824 ctx.map = null;
6825 ctx.container = null;
6826 ctx.store = null;
6827 ctx.ui = ui(ctx);
6828
6829 var controlContainer = null;
6830
6831 var setup = {
6832 onRemove: function onRemove() {
6833 setup.removeLayers();
6834 ctx.ui.removeButtons();
6835 ctx.events.removeEventListeners();
6836 ctx.map = null;
6837 ctx.container = null;
6838 ctx.store = null;
6839
6840 if (controlContainer && controlContainer.parentNode) controlContainer.parentNode.removeChild(controlContainer);
6841 controlContainer = null;
6842
6843 return this;
6844 },
6845 onAdd: function onAdd(map) {
6846 ctx.map = map;
6847 ctx.container = map.getContainer();
6848 ctx.store = new Store(ctx);
6849
6850 controlContainer = ctx.ui.addButtons();
6851
6852 if (ctx.options.boxSelect) {
6853 map.boxZoom.disable();
6854 // Need to toggle dragPan on and off or else first
6855 // dragPan disable attempt in simple_select doesn't work
6856 map.dragPan.disable();
6857 map.dragPan.enable();
6858 }
6859
6860 var intervalId = null;
6861
6862 var connect = function connect() {
6863 map.off('load', connect);
6864 clearInterval(intervalId);
6865 setup.addLayers();
6866 ctx.events.addEventListeners();
6867 };
6868
6869 if (map.loaded()) {
6870 connect();
6871 } else {
6872 map.on('load', connect);
6873 intervalId = setInterval(function () {
6874 if (map.loaded()) connect();
6875 }, 16);
6876 }
6877
6878 return controlContainer;
6879 },
6880 addLayers: function addLayers() {
6881 // drawn features style
6882 ctx.map.addSource(Constants.sources.COLD, {
6883 data: {
6884 type: Constants.geojsonTypes.FEATURE_COLLECTION,
6885 features: []
6886 },
6887 type: 'geojson'
6888 });
6889
6890 // hot features style
6891 ctx.map.addSource(Constants.sources.HOT, {
6892 data: {
6893 type: Constants.geojsonTypes.FEATURE_COLLECTION,
6894 features: []
6895 },
6896 type: 'geojson'
6897 });
6898
6899 ctx.options.styles.forEach(function (style) {
6900 ctx.map.addLayer(style);
6901 });
6902
6903 ctx.store.render();
6904 },
6905 removeLayers: function removeLayers() {
6906 ctx.options.styles.forEach(function (style) {
6907 ctx.map.removeLayer(style.id);
6908 });
6909
6910 ctx.map.removeSource(Constants.sources.COLD);
6911 ctx.map.removeSource(Constants.sources.HOT);
6912 }
6913 };
6914
6915 ctx.setup = setup;
6916
6917 return setup;
6918};
6919
6920},{"./constants":20,"./events":21,"./store":57,"./ui":58}],57:[function(require,module,exports){
6921'use strict';
6922
6923var throttle = require('./lib/throttle');
6924var toDenseArray = require('./lib/to_dense_array');
6925var StringSet = require('./lib/string_set');
6926var render = require('./render');
6927
6928var Store = module.exports = function (ctx) {
6929 this._features = {};
6930 this._featureIds = new StringSet();
6931 this._selectedFeatureIds = new StringSet();
6932 this._changedFeatureIds = new StringSet();
6933 this._deletedFeaturesToEmit = [];
6934 this._emitSelectionChange = false;
6935 this.ctx = ctx;
6936 this.sources = {
6937 hot: [],
6938 cold: []
6939 };
6940 this.render = throttle(render, 16, this);
6941 this.isDirty = false;
6942};
6943
6944/**
6945 * Delays all rendering until the returned function is invoked
6946 * @return {Function} renderBatch
6947 */
6948Store.prototype.createRenderBatch = function () {
6949 var _this = this;
6950
6951 var holdRender = this.render;
6952 var numRenders = 0;
6953 this.render = function () {
6954 numRenders++;
6955 };
6956
6957 return function () {
6958 _this.render = holdRender;
6959 if (numRenders > 0) {
6960 _this.render();
6961 }
6962 };
6963};
6964
6965/**
6966 * Sets the store's state to dirty.
6967 * @return {Store} this
6968 */
6969Store.prototype.setDirty = function () {
6970 this.isDirty = true;
6971 return this;
6972};
6973
6974/**
6975 * Sets a feature's state to changed.
6976 * @param {string} featureId
6977 * @return {Store} this
6978 */
6979Store.prototype.featureChanged = function (featureId) {
6980 this._changedFeatureIds.add(featureId);
6981 return this;
6982};
6983
6984/**
6985 * Gets the ids of all features currently in changed state.
6986 * @return {Store} this
6987 */
6988Store.prototype.getChangedIds = function () {
6989 return this._changedFeatureIds.values();
6990};
6991
6992/**
6993 * Sets all features to unchanged state.
6994 * @return {Store} this
6995 */
6996Store.prototype.clearChangedIds = function () {
6997 this._changedFeatureIds.clear();
6998 return this;
6999};
7000
7001/**
7002 * Gets the ids of all features in the store.
7003 * @return {Store} this
7004 */
7005Store.prototype.getAllIds = function () {
7006 return this._featureIds.values();
7007};
7008
7009/**
7010 * Adds a feature to the store.
7011 * @param {Object} feature
7012 *
7013 * @return {Store} this
7014 */
7015Store.prototype.add = function (feature) {
7016 this.featureChanged(feature.id);
7017 this._features[feature.id] = feature;
7018 this._featureIds.add(feature.id);
7019 return this;
7020};
7021
7022/**
7023 * Deletes a feature or array of features from the store.
7024 * Cleans up after the deletion by deselecting the features.
7025 * If changes were made, sets the state to the dirty
7026 * and fires an event.
7027 * @param {string | Array<string>} featureIds
7028 * @param {Object} [options]
7029 * @param {Object} [options.silent] - If `true`, this invocation will not fire an event.
7030 * @return {Store} this
7031 */
7032Store.prototype.delete = function (featureIds) {
7033 var _this2 = this;
7034
7035 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
7036
7037 toDenseArray(featureIds).forEach(function (id) {
7038 if (!_this2._featureIds.has(id)) return;
7039 _this2._featureIds.delete(id);
7040 _this2._selectedFeatureIds.delete(id);
7041 if (!options.silent) {
7042 if (_this2._deletedFeaturesToEmit.indexOf(_this2._features[id]) === -1) {
7043 _this2._deletedFeaturesToEmit.push(_this2._features[id]);
7044 }
7045 }
7046 delete _this2._features[id];
7047 _this2.isDirty = true;
7048 });
7049 return this;
7050};
7051
7052/**
7053 * Returns a feature in the store matching the specified value.
7054 * @return {Object | undefined} feature
7055 */
7056Store.prototype.get = function (id) {
7057 return this._features[id];
7058};
7059
7060/**
7061 * Returns all features in the store.
7062 * @return {Array<Object>}
7063 */
7064Store.prototype.getAll = function () {
7065 var _this3 = this;
7066
7067 return Object.keys(this._features).map(function (id) {
7068 return _this3._features[id];
7069 });
7070};
7071
7072/**
7073 * Adds features to the current selection.
7074 * @param {string | Array<string>} featureIds
7075 * @param {Object} [options]
7076 * @param {Object} [options.silent] - If `true`, this invocation will not fire an event.
7077 * @return {Store} this
7078 */
7079Store.prototype.select = function (featureIds) {
7080 var _this4 = this;
7081
7082 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
7083
7084 toDenseArray(featureIds).forEach(function (id) {
7085 if (_this4._selectedFeatureIds.has(id)) return;
7086 _this4._selectedFeatureIds.add(id);
7087 _this4._changedFeatureIds.add(id);
7088 if (!options.silent) {
7089 _this4._emitSelectionChange = true;
7090 }
7091 });
7092 return this;
7093};
7094
7095/**
7096 * Deletes features from the current selection.
7097 * @param {string | Array<string>} featureIds
7098 * @param {Object} [options]
7099 * @param {Object} [options.silent] - If `true`, this invocation will not fire an event.
7100 * @return {Store} this
7101 */
7102Store.prototype.deselect = function (featureIds) {
7103 var _this5 = this;
7104
7105 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
7106
7107 toDenseArray(featureIds).forEach(function (id) {
7108 if (!_this5._selectedFeatureIds.has(id)) return;
7109 _this5._selectedFeatureIds.delete(id);
7110 _this5._changedFeatureIds.add(id);
7111 if (!options.silent) {
7112 _this5._emitSelectionChange = true;
7113 }
7114 });
7115 return this;
7116};
7117
7118/**
7119 * Clears the current selection.
7120 * @param {Object} [options]
7121 * @param {Object} [options.silent] - If `true`, this invocation will not fire an event.
7122 * @return {Store} this
7123 */
7124Store.prototype.clearSelected = function () {
7125 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
7126
7127 this.deselect(this._selectedFeatureIds.values(), { silent: options.silent });
7128 return this;
7129};
7130
7131/**
7132 * Sets the store's selection, clearing any prior values.
7133 * If no feature ids are passed, the store is just cleared.
7134 * @param {string | Array<string> | undefined} featureIds
7135 * @param {Object} [options]
7136 * @param {Object} [options.silent] - If `true`, this invocation will not fire an event.
7137 * @return {Store} this
7138 */
7139Store.prototype.setSelected = function (featureIds) {
7140 var _this6 = this;
7141
7142 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
7143
7144 featureIds = toDenseArray(featureIds);
7145
7146 // Deselect any features not in the new selection
7147 this.deselect(this._selectedFeatureIds.values().filter(function (id) {
7148 return featureIds.indexOf(id) === -1;
7149 }), { silent: options.silent });
7150
7151 // Select any features in the new selection that were not already selected
7152 this.select(featureIds.filter(function (id) {
7153 return !_this6._selectedFeatureIds.has(id);
7154 }), { silent: options.silent });
7155
7156 return this;
7157};
7158
7159/**
7160 * Returns the ids of features in the current selection.
7161 * @return {Array<string>} Selected feature ids.
7162 */
7163Store.prototype.getSelectedIds = function () {
7164 return this._selectedFeatureIds.values();
7165};
7166
7167/**
7168 * Returns features in the current selection.
7169 * @return {Array<Object>} Selected features.
7170 */
7171Store.prototype.getSelected = function () {
7172 var _this7 = this;
7173
7174 return this._selectedFeatureIds.values().map(function (id) {
7175 return _this7.get(id);
7176 });
7177};
7178
7179/**
7180 * Indicates whether a feature is selected.
7181 * @param {string} featureId
7182 * @return {boolean} `true` if the feature is selected, `false` if not.
7183 */
7184Store.prototype.isSelected = function (featureId) {
7185 return this._selectedFeatureIds.has(featureId);
7186};
7187
7188/**
7189 * Sets a property on the given feature
7190 * @param {string} featureId
7191 * @param {string} property property
7192 * @param {string} property value
7193*/
7194Store.prototype.setFeatureProperty = function (featureId, property, value) {
7195 this.get(featureId).setProperty(property, value);
7196 this.featureChanged(featureId);
7197};
7198
7199},{"./lib/string_set":43,"./lib/throttle":46,"./lib/to_dense_array":47,"./render":55}],58:[function(require,module,exports){
7200'use strict';
7201
7202var xtend = require('xtend');
7203var Constants = require('./constants');
7204
7205var classTypes = ['mode', 'feature', 'mouse'];
7206
7207module.exports = function (ctx) {
7208
7209 var buttonElements = {};
7210 var activeButton = null;
7211
7212 var currentMapClasses = {
7213 mode: null, // e.g. mode-direct_select
7214 feature: null, // e.g. feature-vertex
7215 mouse: null // e.g. mouse-move
7216 };
7217
7218 var nextMapClasses = {
7219 mode: null,
7220 feature: null,
7221 mouse: null
7222 };
7223
7224 function queueMapClasses(options) {
7225 nextMapClasses = xtend(nextMapClasses, options);
7226 }
7227
7228 function updateMapClasses() {
7229 if (!ctx.container) return;
7230
7231 var classesToRemove = [];
7232 var classesToAdd = [];
7233
7234 classTypes.forEach(function (type) {
7235 if (nextMapClasses[type] === currentMapClasses[type]) return;
7236
7237 classesToRemove.push(type + '-' + currentMapClasses[type]);
7238 if (nextMapClasses[type] !== null) {
7239 classesToAdd.push(type + '-' + nextMapClasses[type]);
7240 }
7241 });
7242
7243 if (classesToRemove.length > 0) {
7244 ctx.container.classList.remove.apply(ctx.container.classList, classesToRemove);
7245 }
7246
7247 if (classesToAdd.length > 0) {
7248 ctx.container.classList.add.apply(ctx.container.classList, classesToAdd);
7249 }
7250
7251 currentMapClasses = xtend(currentMapClasses, nextMapClasses);
7252 }
7253
7254 function createControlButton(id) {
7255 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
7256
7257 var button = document.createElement('button');
7258 button.className = Constants.classes.CONTROL_BUTTON + ' ' + options.className;
7259 button.setAttribute('title', options.title);
7260 options.container.appendChild(button);
7261
7262 button.addEventListener('click', function (e) {
7263 e.preventDefault();
7264 e.stopPropagation();
7265
7266 var clickedButton = e.target;
7267 if (clickedButton === activeButton) {
7268 deactivateButtons();
7269 return;
7270 }
7271
7272 setActiveButton(id);
7273 options.onActivate();
7274 }, true);
7275
7276 return button;
7277 }
7278
7279 function deactivateButtons() {
7280 if (!activeButton) return;
7281 activeButton.classList.remove(Constants.classes.ACTIVE_BUTTON);
7282 activeButton = null;
7283 }
7284
7285 function setActiveButton(id) {
7286 deactivateButtons();
7287
7288 var button = buttonElements[id];
7289 if (!button) return;
7290
7291 if (button && id !== 'trash') {
7292 button.classList.add(Constants.classes.ACTIVE_BUTTON);
7293 activeButton = button;
7294 }
7295 }
7296
7297 function addButtons() {
7298 var controls = ctx.options.controls;
7299 var controlGroup = document.createElement('div');
7300 controlGroup.className = Constants.classes.CONTROL_GROUP + ' ' + Constants.classes.CONTROL_BASE;
7301
7302 if (!controls) return controlGroup;
7303
7304 if (controls[Constants.types.LINE]) {
7305 buttonElements[Constants.types.LINE] = createControlButton(Constants.types.LINE, {
7306 container: controlGroup,
7307 className: Constants.classes.CONTROL_BUTTON_LINE,
7308 title: 'LineString tool ' + (ctx.options.keybindings && '(l)'),
7309 onActivate: function onActivate() {
7310 return ctx.events.changeMode(Constants.modes.DRAW_LINE_STRING);
7311 }
7312 });
7313 }
7314
7315 if (controls[Constants.types.POLYGON]) {
7316 buttonElements[Constants.types.POLYGON] = createControlButton(Constants.types.POLYGON, {
7317 container: controlGroup,
7318 className: Constants.classes.CONTROL_BUTTON_POLYGON,
7319 title: 'Polygon tool ' + (ctx.options.keybindings && '(p)'),
7320 onActivate: function onActivate() {
7321 return ctx.events.changeMode(Constants.modes.DRAW_POLYGON);
7322 }
7323 });
7324 }
7325
7326 if (controls[Constants.types.POINT]) {
7327 buttonElements[Constants.types.POINT] = createControlButton(Constants.types.POINT, {
7328 container: controlGroup,
7329 className: Constants.classes.CONTROL_BUTTON_POINT,
7330 title: 'Marker tool ' + (ctx.options.keybindings && '(m)'),
7331 onActivate: function onActivate() {
7332 return ctx.events.changeMode(Constants.modes.DRAW_POINT);
7333 }
7334 });
7335 }
7336
7337 if (controls.trash) {
7338 buttonElements.trash = createControlButton('trash', {
7339 container: controlGroup,
7340 className: Constants.classes.CONTROL_BUTTON_TRASH,
7341 title: 'Delete',
7342 onActivate: function onActivate() {
7343 ctx.events.trash();
7344 }
7345 });
7346 }
7347
7348 if (controls.combine_features) {
7349 buttonElements.combine_features = createControlButton('combineFeatures', {
7350 container: controlGroup,
7351 className: Constants.classes.CONTROL_BUTTON_COMBINE_FEATURES,
7352 title: 'Combine',
7353 onActivate: function onActivate() {
7354 ctx.events.combineFeatures();
7355 }
7356 });
7357 }
7358
7359 if (controls.uncombine_features) {
7360 buttonElements.uncombine_features = createControlButton('uncombineFeatures', {
7361 container: controlGroup,
7362 className: Constants.classes.CONTROL_BUTTON_UNCOMBINE_FEATURES,
7363 title: 'Uncombine',
7364 onActivate: function onActivate() {
7365 ctx.events.uncombineFeatures();
7366 }
7367 });
7368 }
7369
7370 return controlGroup;
7371 }
7372
7373 function removeButtons() {
7374 Object.keys(buttonElements).forEach(function (buttonId) {
7375 var button = buttonElements[buttonId];
7376 if (button.parentNode) {
7377 button.parentNode.removeChild(button);
7378 }
7379 delete buttonElements[buttonId];
7380 });
7381 }
7382
7383 return {
7384 setActiveButton: setActiveButton,
7385 queueMapClasses: queueMapClasses,
7386 updateMapClasses: updateMapClasses,
7387 addButtons: addButtons,
7388 removeButtons: removeButtons
7389 };
7390};
7391
7392},{"./constants":20,"xtend":62}],59:[function(require,module,exports){
7393'use strict';
7394
7395module.exports = Point;
7396
7397function Point(x, y) {
7398 this.x = x;
7399 this.y = y;
7400}
7401
7402Point.prototype = {
7403 clone: function() { return new Point(this.x, this.y); },
7404
7405 add: function(p) { return this.clone()._add(p); },
7406 sub: function(p) { return this.clone()._sub(p); },
7407 mult: function(k) { return this.clone()._mult(k); },
7408 div: function(k) { return this.clone()._div(k); },
7409 rotate: function(a) { return this.clone()._rotate(a); },
7410 matMult: function(m) { return this.clone()._matMult(m); },
7411 unit: function() { return this.clone()._unit(); },
7412 perp: function() { return this.clone()._perp(); },
7413 round: function() { return this.clone()._round(); },
7414
7415 mag: function() {
7416 return Math.sqrt(this.x * this.x + this.y * this.y);
7417 },
7418
7419 equals: function(p) {
7420 return this.x === p.x &&
7421 this.y === p.y;
7422 },
7423
7424 dist: function(p) {
7425 return Math.sqrt(this.distSqr(p));
7426 },
7427
7428 distSqr: function(p) {
7429 var dx = p.x - this.x,
7430 dy = p.y - this.y;
7431 return dx * dx + dy * dy;
7432 },
7433
7434 angle: function() {
7435 return Math.atan2(this.y, this.x);
7436 },
7437
7438 angleTo: function(b) {
7439 return Math.atan2(this.y - b.y, this.x - b.x);
7440 },
7441
7442 angleWith: function(b) {
7443 return this.angleWithSep(b.x, b.y);
7444 },
7445
7446 // Find the angle of the two vectors, solving the formula for the cross product a x b = |a||b|sin(╬©) for ╬©.
7447 angleWithSep: function(x, y) {
7448 return Math.atan2(
7449 this.x * y - this.y * x,
7450 this.x * x + this.y * y);
7451 },
7452
7453 _matMult: function(m) {
7454 var x = m[0] * this.x + m[1] * this.y,
7455 y = m[2] * this.x + m[3] * this.y;
7456 this.x = x;
7457 this.y = y;
7458 return this;
7459 },
7460
7461 _add: function(p) {
7462 this.x += p.x;
7463 this.y += p.y;
7464 return this;
7465 },
7466
7467 _sub: function(p) {
7468 this.x -= p.x;
7469 this.y -= p.y;
7470 return this;
7471 },
7472
7473 _mult: function(k) {
7474 this.x *= k;
7475 this.y *= k;
7476 return this;
7477 },
7478
7479 _div: function(k) {
7480 this.x /= k;
7481 this.y /= k;
7482 return this;
7483 },
7484
7485 _unit: function() {
7486 this._div(this.mag());
7487 return this;
7488 },
7489
7490 _perp: function() {
7491 var y = this.y;
7492 this.y = this.x;
7493 this.x = -y;
7494 return this;
7495 },
7496
7497 _rotate: function(angle) {
7498 var cos = Math.cos(angle),
7499 sin = Math.sin(angle),
7500 x = cos * this.x - sin * this.y,
7501 y = sin * this.x + cos * this.y;
7502 this.x = x;
7503 this.y = y;
7504 return this;
7505 },
7506
7507 _round: function() {
7508 this.x = Math.round(this.x);
7509 this.y = Math.round(this.y);
7510 return this;
7511 }
7512};
7513
7514// constructs Point from an array if necessary
7515Point.convert = function (a) {
7516 if (a instanceof Point) {
7517 return a;
7518 }
7519 if (Array.isArray(a)) {
7520 return new Point(a[0], a[1]);
7521 }
7522 return a;
7523};
7524
7525},{}],60:[function(require,module,exports){
7526var traverse = module.exports = function (obj) {
7527 return new Traverse(obj);
7528};
7529
7530function Traverse (obj) {
7531 this.value = obj;
7532}
7533
7534Traverse.prototype.get = function (ps) {
7535 var node = this.value;
7536 for (var i = 0; i < ps.length; i ++) {
7537 var key = ps[i];
7538 if (!node || !hasOwnProperty.call(node, key)) {
7539 node = undefined;
7540 break;
7541 }
7542 node = node[key];
7543 }
7544 return node;
7545};
7546
7547Traverse.prototype.has = function (ps) {
7548 var node = this.value;
7549 for (var i = 0; i < ps.length; i ++) {
7550 var key = ps[i];
7551 if (!node || !hasOwnProperty.call(node, key)) {
7552 return false;
7553 }
7554 node = node[key];
7555 }
7556 return true;
7557};
7558
7559Traverse.prototype.set = function (ps, value) {
7560 var node = this.value;
7561 for (var i = 0; i < ps.length - 1; i ++) {
7562 var key = ps[i];
7563 if (!hasOwnProperty.call(node, key)) node[key] = {};
7564 node = node[key];
7565 }
7566 node[ps[i]] = value;
7567 return value;
7568};
7569
7570Traverse.prototype.map = function (cb) {
7571 return walk(this.value, cb, true);
7572};
7573
7574Traverse.prototype.forEach = function (cb) {
7575 this.value = walk(this.value, cb, false);
7576 return this.value;
7577};
7578
7579Traverse.prototype.reduce = function (cb, init) {
7580 var skip = arguments.length === 1;
7581 var acc = skip ? this.value : init;
7582 this.forEach(function (x) {
7583 if (!this.isRoot || !skip) {
7584 acc = cb.call(this, acc, x);
7585 }
7586 });
7587 return acc;
7588};
7589
7590Traverse.prototype.paths = function () {
7591 var acc = [];
7592 this.forEach(function (x) {
7593 acc.push(this.path);
7594 });
7595 return acc;
7596};
7597
7598Traverse.prototype.nodes = function () {
7599 var acc = [];
7600 this.forEach(function (x) {
7601 acc.push(this.node);
7602 });
7603 return acc;
7604};
7605
7606Traverse.prototype.clone = function () {
7607 var parents = [], nodes = [];
7608
7609 return (function clone (src) {
7610 for (var i = 0; i < parents.length; i++) {
7611 if (parents[i] === src) {
7612 return nodes[i];
7613 }
7614 }
7615
7616 if (typeof src === 'object' && src !== null) {
7617 var dst = copy(src);
7618
7619 parents.push(src);
7620 nodes.push(dst);
7621
7622 forEach(objectKeys(src), function (key) {
7623 dst[key] = clone(src[key]);
7624 });
7625
7626 parents.pop();
7627 nodes.pop();
7628 return dst;
7629 }
7630 else {
7631 return src;
7632 }
7633 })(this.value);
7634};
7635
7636function walk (root, cb, immutable) {
7637 var path = [];
7638 var parents = [];
7639 var alive = true;
7640
7641 return (function walker (node_) {
7642 var node = immutable ? copy(node_) : node_;
7643 var modifiers = {};
7644
7645 var keepGoing = true;
7646
7647 var state = {
7648 node : node,
7649 node_ : node_,
7650 path : [].concat(path),
7651 parent : parents[parents.length - 1],
7652 parents : parents,
7653 key : path.slice(-1)[0],
7654 isRoot : path.length === 0,
7655 level : path.length,
7656 circular : null,
7657 update : function (x, stopHere) {
7658 if (!state.isRoot) {
7659 state.parent.node[state.key] = x;
7660 }
7661 state.node = x;
7662 if (stopHere) keepGoing = false;
7663 },
7664 'delete' : function (stopHere) {
7665 delete state.parent.node[state.key];
7666 if (stopHere) keepGoing = false;
7667 },
7668 remove : function (stopHere) {
7669 if (isArray(state.parent.node)) {
7670 state.parent.node.splice(state.key, 1);
7671 }
7672 else {
7673 delete state.parent.node[state.key];
7674 }
7675 if (stopHere) keepGoing = false;
7676 },
7677 keys : null,
7678 before : function (f) { modifiers.before = f },
7679 after : function (f) { modifiers.after = f },
7680 pre : function (f) { modifiers.pre = f },
7681 post : function (f) { modifiers.post = f },
7682 stop : function () { alive = false },
7683 block : function () { keepGoing = false }
7684 };
7685
7686 if (!alive) return state;
7687
7688 function updateState() {
7689 if (typeof state.node === 'object' && state.node !== null) {
7690 if (!state.keys || state.node_ !== state.node) {
7691 state.keys = objectKeys(state.node)
7692 }
7693
7694 state.isLeaf = state.keys.length == 0;
7695
7696 for (var i = 0; i < parents.length; i++) {
7697 if (parents[i].node_ === node_) {
7698 state.circular = parents[i];
7699 break;
7700 }
7701 }
7702 }
7703 else {
7704 state.isLeaf = true;
7705 state.keys = null;
7706 }
7707
7708 state.notLeaf = !state.isLeaf;
7709 state.notRoot = !state.isRoot;
7710 }
7711
7712 updateState();
7713
7714 // use return values to update if defined
7715 var ret = cb.call(state, state.node);
7716 if (ret !== undefined && state.update) state.update(ret);
7717
7718 if (modifiers.before) modifiers.before.call(state, state.node);
7719
7720 if (!keepGoing) return state;
7721
7722 if (typeof state.node == 'object'
7723 && state.node !== null && !state.circular) {
7724 parents.push(state);
7725
7726 updateState();
7727
7728 forEach(state.keys, function (key, i) {
7729 path.push(key);
7730
7731 if (modifiers.pre) modifiers.pre.call(state, state.node[key], key);
7732
7733 var child = walker(state.node[key]);
7734 if (immutable && hasOwnProperty.call(state.node, key)) {
7735 state.node[key] = child.node;
7736 }
7737
7738 child.isLast = i == state.keys.length - 1;
7739 child.isFirst = i == 0;
7740
7741 if (modifiers.post) modifiers.post.call(state, child);
7742
7743 path.pop();
7744 });
7745 parents.pop();
7746 }
7747
7748 if (modifiers.after) modifiers.after.call(state, state.node);
7749
7750 return state;
7751 })(root).node;
7752}
7753
7754function copy (src) {
7755 if (typeof src === 'object' && src !== null) {
7756 var dst;
7757
7758 if (isArray(src)) {
7759 dst = [];
7760 }
7761 else if (isDate(src)) {
7762 dst = new Date(src.getTime ? src.getTime() : src);
7763 }
7764 else if (isRegExp(src)) {
7765 dst = new RegExp(src);
7766 }
7767 else if (isError(src)) {
7768 dst = { message: src.message };
7769 }
7770 else if (isBoolean(src)) {
7771 dst = new Boolean(src);
7772 }
7773 else if (isNumber(src)) {
7774 dst = new Number(src);
7775 }
7776 else if (isString(src)) {
7777 dst = new String(src);
7778 }
7779 else if (Object.create && Object.getPrototypeOf) {
7780 dst = Object.create(Object.getPrototypeOf(src));
7781 }
7782 else if (src.constructor === Object) {
7783 dst = {};
7784 }
7785 else {
7786 var proto =
7787 (src.constructor && src.constructor.prototype)
7788 || src.__proto__
7789 || {}
7790 ;
7791 var T = function () {};
7792 T.prototype = proto;
7793 dst = new T;
7794 }
7795
7796 forEach(objectKeys(src), function (key) {
7797 dst[key] = src[key];
7798 });
7799 return dst;
7800 }
7801 else return src;
7802}
7803
7804var objectKeys = Object.keys || function keys (obj) {
7805 var res = [];
7806 for (var key in obj) res.push(key)
7807 return res;
7808};
7809
7810function toS (obj) { return Object.prototype.toString.call(obj) }
7811function isDate (obj) { return toS(obj) === '[object Date]' }
7812function isRegExp (obj) { return toS(obj) === '[object RegExp]' }
7813function isError (obj) { return toS(obj) === '[object Error]' }
7814function isBoolean (obj) { return toS(obj) === '[object Boolean]' }
7815function isNumber (obj) { return toS(obj) === '[object Number]' }
7816function isString (obj) { return toS(obj) === '[object String]' }
7817
7818var isArray = Array.isArray || function isArray (xs) {
7819 return Object.prototype.toString.call(xs) === '[object Array]';
7820};
7821
7822var forEach = function (xs, fn) {
7823 if (xs.forEach) return xs.forEach(fn)
7824 else for (var i = 0; i < xs.length; i++) {
7825 fn(xs[i], i, xs);
7826 }
7827};
7828
7829forEach(objectKeys(Traverse.prototype), function (key) {
7830 traverse[key] = function (obj) {
7831 var args = [].slice.call(arguments, 1);
7832 var t = new Traverse(obj);
7833 return t[key].apply(t, args);
7834 };
7835});
7836
7837var hasOwnProperty = Object.hasOwnProperty || function (obj, key) {
7838 return key in obj;
7839};
7840
7841},{}],61:[function(require,module,exports){
7842module.exports.RADIUS = 6378137;
7843module.exports.FLATTENING = 1/298.257223563;
7844module.exports.POLAR_RADIUS = 6356752.3142;
7845
7846},{}],62:[function(require,module,exports){
7847module.exports = extend
7848
7849var hasOwnProperty = Object.prototype.hasOwnProperty;
7850
7851function extend() {
7852 var target = {}
7853
7854 for (var i = 0; i < arguments.length; i++) {
7855 var source = arguments[i]
7856
7857 for (var key in source) {
7858 if (hasOwnProperty.call(source, key)) {
7859 target[key] = source[key]
7860 }
7861 }
7862 }
7863
7864 return target
7865}
7866
7867},{}]},{},[18]);