blacklight_heatmaps 1.3.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -1
  3. data/Rakefile +7 -0
  4. data/app/assets/javascripts/blacklight_heatmaps/default.esm.js +2001 -0
  5. data/app/assets/javascripts/blacklight_heatmaps/default.esm.js.map +1 -0
  6. data/app/assets/javascripts/blacklight_heatmaps/default.js +2006 -8
  7. data/app/assets/javascripts/blacklight_heatmaps/default.js.map +1 -0
  8. data/app/{assets/javascripts/blacklight_heatmaps → javascript}/basemaps.js +4 -2
  9. data/app/javascript/blacklight_heatmaps.js +43 -0
  10. data/app/javascript/icons.js +5 -0
  11. data/app/javascript/viewers/index.js +76 -0
  12. data/app/javascript/viewers/show.js +24 -0
  13. data/lib/blacklight_heatmaps/version.rb +1 -1
  14. data/lib/generators/blacklight_heatmaps/install_generator.rb +40 -5
  15. data/lib/generators/blacklight_heatmaps/templates/blacklight_heatmaps.css +11 -0
  16. data/spec/examples.txt +7 -0
  17. data/spec/features/configurable_basemap_spec.rb +1 -2
  18. data/spec/features/index_page_map_spec.rb +1 -1
  19. data/spec/features/show_page_map_spec.rb +1 -1
  20. data/spec/spec_helper.rb +0 -2
  21. data/spec/test_app_templates/lib/generators/test_app_generator.rb +11 -12
  22. data/vendor/assets/javascripts/geostats.js +511 -284
  23. data/vendor/assets/javascripts/leaflet_solr_heatmap.js +6 -4
  24. metadata +48 -45
  25. data/app/assets/javascripts/blacklight_heatmaps/blacklight_heatmaps.js +0 -18
  26. data/app/assets/javascripts/blacklight_heatmaps/icons.js +0 -3
  27. data/app/assets/javascripts/blacklight_heatmaps/viewers/index.js +0 -91
  28. data/app/assets/javascripts/blacklight_heatmaps/viewers/show.js +0 -39
  29. data/app/assets/javascripts/index.js +0 -8
  30. data/lib/generators/blacklight_heatmaps/templates/blacklight_heatmaps.js +0 -1
  31. data/lib/generators/blacklight_heatmaps/templates/blacklight_heatmaps.scss +0 -1
@@ -0,0 +1,2001 @@
1
+ import L$1 from 'leaflet';
2
+ import 'leaflet-sidebar';
3
+
4
+ function getDefaultExportFromCjs (x) {
5
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
6
+ }
7
+
8
+ var geostats$1 = {exports: {}};
9
+
10
+ /**
11
+ * geostats() is a tiny and standalone javascript library for classification
12
+ * Project page - https://github.com/simogeo/geostats
13
+ * Copyright (c) 2011 Simon Georget, http://www.intermezzo-coop.eu
14
+ * Licensed under the MIT license
15
+ */
16
+
17
+ var hasRequiredGeostats;
18
+
19
+ function requireGeostats () {
20
+ if (hasRequiredGeostats) return geostats$1.exports;
21
+ hasRequiredGeostats = 1;
22
+ (function (module, exports) {
23
+ (function (definition) {
24
+ // This file will function properly as a <script> tag, or a module
25
+ // using CommonJS and NodeJS or RequireJS module formats.
26
+
27
+ // CommonJS
28
+ {
29
+ module.exports = definition();
30
+
31
+ // RequireJS
32
+ }
33
+
34
+ })(function () {
35
+
36
+ var isInt = function(n) {
37
+ return typeof n === 'number' && parseFloat(n) == parseInt(n, 10) && !isNaN(n);
38
+ }; // 6 characters
39
+
40
+ var _t = function(str) {
41
+ return str;
42
+ };
43
+
44
+ //taking from http://stackoverflow.com/questions/18082/validate-decimal-numbers-in-javascript-isnumeric
45
+ var isNumber = function(n) {
46
+ return !isNaN(parseFloat(n)) && isFinite(n);
47
+ };
48
+
49
+
50
+
51
+ //indexOf polyfill
52
+ // from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
53
+ if (!Array.prototype.indexOf) {
54
+ Array.prototype.indexOf = function (searchElement, fromIndex) {
55
+ if ( this === undefined || this === null ) {
56
+ throw new TypeError( '"this" is null or not defined' );
57
+ }
58
+
59
+ var length = this.length >>> 0; // Hack to convert object.length to a UInt32
60
+
61
+ fromIndex = +fromIndex || 0;
62
+
63
+ if (Math.abs(fromIndex) === Infinity) {
64
+ fromIndex = 0;
65
+ }
66
+
67
+ if (fromIndex < 0) {
68
+ fromIndex += length;
69
+ if (fromIndex < 0) {
70
+ fromIndex = 0;
71
+ }
72
+ }
73
+
74
+ for (;fromIndex < length; fromIndex++) {
75
+ if (this[fromIndex] === searchElement) {
76
+ return fromIndex;
77
+ }
78
+ }
79
+
80
+ return -1;
81
+ };
82
+ }
83
+
84
+ var geostats = function(a) {
85
+
86
+ this.objectID = '';
87
+ this.separator = ' - ';
88
+ this.legendSeparator = this.separator;
89
+ this.method = '';
90
+ this.precision = 0;
91
+ this.precisionflag = 'auto';
92
+ this.roundlength = 2; // Number of decimals, round values
93
+ this.is_uniqueValues = false;
94
+ this.debug = false;
95
+ this.silent = false;
96
+
97
+ this.bounds = Array();
98
+ this.ranges = Array();
99
+ this.inner_ranges = null;
100
+ this.colors = Array();
101
+ this.counter = Array();
102
+
103
+ // statistics information
104
+ this.stat_sorted = null;
105
+ this.stat_mean = null;
106
+ this.stat_median = null;
107
+ this.stat_sum = null;
108
+ this.stat_max = null;
109
+ this.stat_min = null;
110
+ this.stat_pop = null;
111
+ this.stat_variance = null;
112
+ this.stat_stddev = null;
113
+ this.stat_cov = null;
114
+
115
+
116
+ /**
117
+ * logging method
118
+ */
119
+ this.log = function(msg, force) {
120
+
121
+ if(this.debug == true || force != null)
122
+ console.log(this.objectID + "(object id) :: " + msg);
123
+
124
+ };
125
+
126
+ /**
127
+ * Set bounds
128
+ */
129
+ this.setBounds = function(a) {
130
+
131
+ this.log('Setting bounds (' + a.length + ') : ' + a.join());
132
+
133
+ this.bounds = Array(); // init empty array to prevent bug when calling classification after another with less items (sample getQuantile(6) and getQuantile(4))
134
+
135
+ this.bounds = a;
136
+ //this.bounds = this.decimalFormat(a);
137
+
138
+ };
139
+
140
+ /**
141
+ * Set a new serie
142
+ */
143
+ this.setSerie = function(a) {
144
+
145
+ this.log('Setting serie (' + a.length + ') : ' + a.join());
146
+
147
+ this.serie = Array(); // init empty array to prevent bug when calling classification after another with less items (sample getQuantile(6) and getQuantile(4))
148
+ this.serie = a;
149
+
150
+ //reset statistics after changing serie
151
+ this.resetStatistics();
152
+
153
+ this.setPrecision();
154
+
155
+ };
156
+
157
+ /**
158
+ * Set colors
159
+ */
160
+ this.setColors = function(colors) {
161
+
162
+ this.log('Setting color ramp (' + colors.length + ') : ' + colors.join());
163
+
164
+ this.colors = colors;
165
+
166
+ };
167
+
168
+ /**
169
+ * Get feature count
170
+ * With bounds array(0, 0.75, 1.5, 2.25, 3);
171
+ * should populate this.counter with 5 keys
172
+ * and increment counters for each key
173
+ */
174
+ this.doCount = function() {
175
+
176
+ if (this._nodata())
177
+ return;
178
+
179
+
180
+ var tmp = this.sorted();
181
+
182
+ this.counter = new Array();
183
+
184
+ // we init counter with 0 value
185
+ if(this.is_uniqueValues == true) {
186
+ for (var i = 0; i < this.bounds.length; i++) {
187
+ this.counter[i]= 0;
188
+ }
189
+ } else {
190
+ for (var i = 0; i < this.bounds.length -1; i++) {
191
+ this.counter[i]= 0;
192
+ }
193
+ }
194
+
195
+ for (var j=0; j < tmp.length; j++) {
196
+
197
+ // get current class for value to increment the counter
198
+ var cclass = this.getClass(tmp[j]);
199
+ this.counter[cclass]++;
200
+
201
+ }
202
+
203
+ };
204
+
205
+ /**
206
+ * Set decimal precision according to user input
207
+ * or automatcally determined according
208
+ * to the given serie.
209
+ */
210
+ this.setPrecision = function(decimals) {
211
+
212
+ // only when called from user
213
+ if(typeof decimals !== "undefined") {
214
+ this.precisionflag = 'manual';
215
+ this.precision = decimals;
216
+ }
217
+
218
+ // we calculate the maximal decimal length on given serie
219
+ if(this.precisionflag == 'auto') {
220
+
221
+ for (var i = 0; i < this.serie.length; i++) {
222
+
223
+ // check if the given value is a number and a float
224
+ if (!isNaN((this.serie[i]+"")) && (this.serie[i]+"").toString().indexOf('.') != -1) {
225
+ var precision = (this.serie[i] + "").split(".")[1].length;
226
+ } else {
227
+ var precision = 0;
228
+ }
229
+
230
+ if(precision > this.precision) {
231
+ this.precision = precision;
232
+ }
233
+
234
+ }
235
+
236
+ }
237
+ if(this.precision > 20) {
238
+ // prevent "Uncaught RangeError: toFixed() digits argument must be between 0 and 20" bug. See https://github.com/simogeo/geostats/issues/34
239
+ this.log('this.precision value (' + this.precision + ') is greater than max value. Automatic set-up to 20 to prevent "Uncaught RangeError: toFixed()" when calling decimalFormat() method.');
240
+ this.precision = 20;
241
+ }
242
+
243
+ this.log('Calling setPrecision(). Mode : ' + this.precisionflag + ' - Decimals : '+ this.precision);
244
+
245
+ this.serie = this.decimalFormat(this.serie);
246
+
247
+ };
248
+
249
+ /**
250
+ * Format array numbers regarding to precision
251
+ */
252
+ this.decimalFormat = function(a) {
253
+
254
+ var b = new Array();
255
+
256
+ for (var i = 0; i < a.length; i++) {
257
+ // check if the given value is a number
258
+ if (isNumber(a[i])) {
259
+ b[i] = parseFloat(parseFloat(a[i]).toFixed(this.precision));
260
+ } else {
261
+ b[i] = a[i];
262
+ }
263
+ }
264
+
265
+ return b;
266
+ };
267
+
268
+ /**
269
+ * Transform a bounds array to a range array the following array : array(0,
270
+ * 0.75, 1.5, 2.25, 3); becomes : array('0-0.75', '0.75-1.5', '1.5-2.25',
271
+ * '2.25-3');
272
+ */
273
+ this.setRanges = function() {
274
+
275
+ this.ranges = Array(); // init empty array to prevent bug when calling classification after another with less items (sample getQuantile(6) and getQuantile(4))
276
+
277
+ for (var i = 0; i < (this.bounds.length - 1); i++) {
278
+ this.ranges[i] = this.bounds[i] + this.separator + this.bounds[i + 1];
279
+ }
280
+ };
281
+
282
+ /** return min value */
283
+ this.min = function(exclude = []) {
284
+
285
+ if (this._nodata())
286
+ return;
287
+
288
+ if(!exclude.includes(this.serie[0])) this.stat_min = this.serie[0];
289
+ else this.stat_min = 999999999999;
290
+
291
+
292
+ for (var i = 0; i < this.pop(); i++) {
293
+ if (this.serie[i] < this.stat_min && !exclude.includes(this.serie[i])) {
294
+ this.stat_min = this.serie[i];
295
+ }
296
+ }
297
+
298
+ return this.stat_min;
299
+ };
300
+
301
+ /** return max value */
302
+ this.max = function(exclude = []) {
303
+
304
+ if (this._nodata())
305
+ return;
306
+
307
+ if(!exclude.includes(this.serie[0])) this.stat_max = this.serie[0];
308
+ else this.stat_max = -999999999999;
309
+
310
+ for (var i = 0; i < this.pop(); i++) {
311
+ if (this.serie[i] > this.stat_max && !exclude.includes(this.serie[i])) {
312
+ this.stat_max = this.serie[i];
313
+ }
314
+ }
315
+
316
+ return this.stat_max;
317
+ };
318
+
319
+ /** return sum value */
320
+ this.sum = function() {
321
+
322
+ if (this._nodata())
323
+ return;
324
+
325
+ if (this.stat_sum == null) {
326
+
327
+ this.stat_sum = 0;
328
+ for (var i = 0; i < this.pop(); i++) {
329
+ this.stat_sum += parseFloat(this.serie[i]);
330
+ }
331
+
332
+ }
333
+
334
+ return this.stat_sum;
335
+ };
336
+
337
+ /** return population number */
338
+ this.pop = function() {
339
+
340
+ if (this._nodata())
341
+ return;
342
+
343
+ if (this.stat_pop == null) {
344
+
345
+ this.stat_pop = this.serie.length;
346
+
347
+ }
348
+
349
+ return this.stat_pop;
350
+ };
351
+
352
+ /** return mean value */
353
+ this.mean = function() {
354
+
355
+ if (this._nodata())
356
+ return;
357
+
358
+ if (this.stat_mean == null) {
359
+
360
+ this.stat_mean = parseFloat(this.sum() / this.pop());
361
+
362
+ }
363
+
364
+ return this.stat_mean;
365
+ };
366
+
367
+ /** return median value */
368
+ this.median = function() {
369
+
370
+ if (this._nodata())
371
+ return;
372
+
373
+ if (this.stat_median == null) {
374
+
375
+ this.stat_median = 0;
376
+ var tmp = this.sorted();
377
+
378
+ // serie pop is odd
379
+ if (tmp.length % 2) {
380
+ this.stat_median = parseFloat(tmp[(Math.ceil(tmp.length / 2) - 1)]);
381
+
382
+ // serie pop is even
383
+ } else {
384
+ this.stat_median = ( parseFloat(tmp[((tmp.length / 2) - 1)]) + parseFloat(tmp[(tmp.length / 2)]) ) / 2;
385
+ }
386
+
387
+ }
388
+
389
+ return this.stat_median;
390
+ };
391
+
392
+ /** return variance value */
393
+ this.variance = function() {
394
+
395
+ var round = (typeof round === "undefined") ? true : false;
396
+
397
+ if (this._nodata())
398
+ return;
399
+
400
+ if (this.stat_variance == null) {
401
+
402
+ var tmp = 0, serie_mean = this.mean();
403
+ for (var i = 0; i < this.pop(); i++) {
404
+ tmp += Math.pow( (this.serie[i] - serie_mean), 2 );
405
+ }
406
+
407
+ this.stat_variance = tmp / this.pop();
408
+
409
+ if(round == true) {
410
+ this.stat_variance = Math.round(this.stat_variance * Math.pow(10,this.roundlength) )/ Math.pow(10,this.roundlength);
411
+ }
412
+
413
+ }
414
+
415
+ return this.stat_variance;
416
+ };
417
+
418
+ /** return standard deviation value */
419
+ this.stddev = function(round) {
420
+
421
+ var round = (typeof round === "undefined") ? true : false;
422
+
423
+ if (this._nodata())
424
+ return;
425
+
426
+ if (this.stat_stddev == null) {
427
+
428
+ this.stat_stddev = Math.sqrt(this.variance());
429
+
430
+ if(round == true) {
431
+ this.stat_stddev = Math.round(this.stat_stddev * Math.pow(10,this.roundlength) )/ Math.pow(10,this.roundlength);
432
+ }
433
+
434
+ }
435
+
436
+ return this.stat_stddev;
437
+ };
438
+
439
+ /** coefficient of variation - measure of dispersion */
440
+ this.cov = function(round) {
441
+
442
+ var round = (typeof round === "undefined") ? true : false;
443
+
444
+ if (this._nodata())
445
+ return;
446
+
447
+ if (this.stat_cov == null) {
448
+
449
+ this.stat_cov = this.stddev() / this.mean();
450
+
451
+ if(round == true) {
452
+ this.stat_cov = Math.round(this.stat_cov * Math.pow(10,this.roundlength) )/ Math.pow(10,this.roundlength);
453
+ }
454
+
455
+ }
456
+
457
+ return this.stat_cov;
458
+ };
459
+
460
+ /** reset all attributes after setting a new serie */
461
+ this.resetStatistics = function() {
462
+ this.stat_sorted = null;
463
+ this.stat_mean = null;
464
+ this.stat_median = null;
465
+ this.stat_sum = null;
466
+ this.stat_max = null;
467
+ this.stat_min = null;
468
+ this.stat_pop = null;
469
+ this.stat_variance = null;
470
+ this.stat_stddev = null;
471
+ this.stat_cov = null;
472
+ };
473
+
474
+ /** data test */
475
+ this._nodata = function() {
476
+ if (this.serie.length == 0) {
477
+
478
+ if(this.silent) this.log("[silent mode] Error. You should first enter a serie!", true);
479
+ else throw new TypeError("Error. You should first enter a serie!");
480
+ return 1;
481
+ } else
482
+ return 0;
483
+
484
+ };
485
+
486
+ /** data test */
487
+ this._classificationCheck = function(nbClass) {
488
+
489
+ if(nbClass >= this.pop()) {
490
+ var errnum ='Error. ' + nbClass + ' classes are defined for only ' + this.pop() + ' values in serie ! For the current serie, no more than ' + (this.pop() - 1 ) + ' classes can be defined.';
491
+
492
+ if(this.silent) this.log(errnum, true);
493
+ else {
494
+ alert(errnum);
495
+ throw new TypeError(errnum);
496
+ }
497
+
498
+ }
499
+
500
+ };
501
+
502
+ /** ensure nbClass is an integer */
503
+ this._nbClassInt = function(nbClass) {
504
+
505
+ var nbclassTmp = parseInt(nbClass, 10);
506
+ if (isNaN(nbclassTmp)) {
507
+ if(this.silent) this.log("[silent mode] '" + nbclassTmp + "' is not a valid integer. Enable to set class number.", true);
508
+ else throw new TypeError("'" + nbclassTmp + "' is not a valid integer. Enable to set class number.");
509
+ } else {
510
+ return nbclassTmp;
511
+ }
512
+
513
+ };
514
+
515
+ /** check if the serie contains negative value */
516
+ this._hasNegativeValue = function() {
517
+
518
+ for (var i = 0; i < this.serie.length; i++) {
519
+ if(this.serie[i] < 0)
520
+ return true;
521
+ }
522
+
523
+ return false;
524
+ };
525
+
526
+ /** check if the serie contains zero value */
527
+ this._hasZeroValue = function() {
528
+
529
+ for (var i = 0; i < this.serie.length; i++) {
530
+ if(parseFloat(this.serie[i]) === 0)
531
+ return true;
532
+ }
533
+
534
+ return false;
535
+ };
536
+
537
+ /** return sorted values (as array) */
538
+ this.sorted = function() {
539
+
540
+ if (this.stat_sorted == null) {
541
+
542
+ if(this.is_uniqueValues == false) {
543
+ this.stat_sorted = this.serie.sort(function(a, b) {
544
+ return a - b;
545
+ });
546
+ } else {
547
+ this.stat_sorted = this.serie.sort(function(a,b){
548
+ var nameA=a.toString().toLowerCase(), nameB=b.toString().toLowerCase();
549
+ if(nameA < nameB) return -1;
550
+ if(nameA > nameB) return 1;
551
+ return 0;
552
+ });
553
+ }
554
+ }
555
+
556
+ return this.stat_sorted;
557
+
558
+ };
559
+
560
+ /** return all info */
561
+ this.info = function() {
562
+
563
+ if (this._nodata())
564
+ return;
565
+
566
+ var content = '';
567
+ content += _t('Population') + ' : ' + this.pop() + ' - [' + _t('Min')
568
+ + ' : ' + this.min() + ' | ' + _t('Max') + ' : ' + this.max()
569
+ + ']' + "\n";
570
+ content += _t('Mean') + ' : ' + this.mean() + ' - ' + _t('Median') + ' : ' + this.median() + "\n";
571
+ content += _t('Variance') + ' : ' + this.variance() + ' - ' + _t('Standard deviation') + ' : ' + this.stddev()
572
+ + ' - ' + _t('Coefficient of variation') + ' : ' + this.cov() + "\n";
573
+
574
+ return content;
575
+ };
576
+
577
+ /**
578
+ * Set Manual classification Return an array with bounds : ie array(0,
579
+ * 0.75, 1.5, 2.25, 3);
580
+ * Set ranges and prepare data for displaying legend
581
+ *
582
+ */
583
+ this.setClassManually = function(array) {
584
+
585
+ if (this._nodata())
586
+ return;
587
+
588
+ if(array[0] !== this.min() || array[array.length-1] !== this.max()) {
589
+ if(this.silent) this.log("[silent mode] " + t('Given bounds may not be correct! please check your input.\nMin value : ' + this.min() + ' / Max value : ' + this.max()), true);
590
+ else throw new TypeError(_t('Given bounds may not be correct! please check your input.\nMin value : ' + this.min() + ' / Max value : ' + this.max()));
591
+ return;
592
+ }
593
+
594
+ this.setBounds(array);
595
+ this.setRanges();
596
+
597
+ // we specify the classification method
598
+ this.method = _t('manual classification') + ' (' + (array.length -1) + ' ' + _t('classes') + ')';
599
+
600
+ return this.bounds;
601
+ };
602
+
603
+ /**
604
+ * Equal intervals classification Return an array with bounds : ie array(0,
605
+ * 0.75, 1.5, 2.25, 3);
606
+ */
607
+ this.getClassEqInterval = function(nbClass, forceMin, forceMax) {
608
+
609
+ var nbClass = this._nbClassInt(nbClass); // ensure nbClass is an integer
610
+
611
+ if (this._nodata())
612
+ return;
613
+
614
+ var tmpMin = (typeof forceMin === "undefined") ? this.min() : forceMin;
615
+ var tmpMax = (typeof forceMax === "undefined") ? this.max() : forceMax;
616
+
617
+ var a = Array();
618
+ var val = tmpMin;
619
+ var interval = (tmpMax - tmpMin) / nbClass;
620
+
621
+ for (var i = 0; i <= nbClass; i++) {
622
+ a[i] = val;
623
+ val += interval;
624
+ }
625
+
626
+ //-> Fix last bound to Max of values
627
+ a[nbClass] = tmpMax;
628
+
629
+ this.setBounds(a);
630
+ this.setRanges();
631
+
632
+ // we specify the classification method
633
+ this.method = _t('eq. intervals') + ' (' + nbClass + ' ' + _t('classes') + ')';
634
+
635
+ return this.bounds;
636
+ };
637
+
638
+
639
+ this.getQuantiles = function(nbClass) {
640
+
641
+ var nbClass = this._nbClassInt(nbClass); // ensure nbClass is an integer
642
+
643
+ var tmp = this.sorted();
644
+ var quantiles = [];
645
+
646
+ var step = this.pop() / nbClass;
647
+ for (var i = 1; i < nbClass; i++) {
648
+ var qidx = Math.round(i*step+0.49);
649
+ quantiles.push(tmp[qidx-1]); // zero-based
650
+ }
651
+
652
+ return quantiles;
653
+ };
654
+
655
+ /**
656
+ * Quantile classification Return an array with bounds : ie array(0, 0.75,
657
+ * 1.5, 2.25, 3);
658
+ */
659
+ this.getClassQuantile = function(nbClass) {
660
+
661
+ var nbClass = this._nbClassInt(nbClass); // ensure nbClass is an integer
662
+
663
+ if (this._nodata())
664
+ return;
665
+
666
+ this._classificationCheck(nbClass); // be sure number of classes is valid
667
+
668
+ var tmp = this.sorted();
669
+ var bounds = this.getQuantiles(nbClass);
670
+ bounds.unshift(tmp[0]);
671
+
672
+ if (bounds[tmp.length - 1] !== tmp[tmp.length - 1])
673
+ bounds.push(tmp[tmp.length - 1]);
674
+
675
+ this.setBounds(bounds);
676
+ this.setRanges();
677
+
678
+ // we specify the classification method
679
+ this.method = _t('quantile') + ' (' + nbClass + ' ' + _t('classes') + ')';
680
+
681
+ return this.bounds;
682
+
683
+ };
684
+
685
+ /**
686
+ * Standard Deviation classification
687
+ * Return an array with bounds : ie array(0,
688
+ * 0.75, 1.5, 2.25, 3);
689
+ */
690
+ this.getClassStdDeviation = function(nbClass, matchBounds) {
691
+
692
+ var nbClass = this._nbClassInt(nbClass); // ensure nbClass is an integer
693
+
694
+ if (this._nodata())
695
+ return;
696
+
697
+ var tmpMax = this.max();
698
+ var tmpMin = this.min();
699
+ var tmpStdDev = this.stddev();
700
+ var tmpMean = this.mean();
701
+
702
+ var a = Array();
703
+
704
+ // number of classes is odd
705
+ if(nbClass % 2 == 1) {
706
+
707
+ // Euclidean division to get the inferior bound
708
+ var infBound = Math.floor(nbClass / 2);
709
+
710
+ var supBound = infBound + 1;
711
+
712
+ // we set the central bounds
713
+ a[infBound] = tmpMean - (tmpStdDev / 2);
714
+ a[supBound] = tmpMean + (tmpStdDev / 2);
715
+
716
+ // Values < to infBound, except first one
717
+ for (var i = infBound - 1; i > 0; i--) {
718
+ var val = a[i+1] - tmpStdDev;
719
+ a[i] = val;
720
+ }
721
+
722
+ // Values > to supBound, except last one
723
+ for (var i = supBound + 1; i < nbClass; i++) {
724
+ var val = a[i-1] + tmpStdDev;
725
+ a[i] = val;
726
+ }
727
+
728
+ // number of classes is even
729
+ } else {
730
+
731
+ var meanBound = nbClass / 2;
732
+
733
+ // we get the mean value
734
+ a[meanBound] = tmpMean;
735
+
736
+ // Values < to the mean, except first one
737
+ for (var i = meanBound - 1; i > 0; i--) {
738
+ var val = a[i+1] - tmpStdDev;
739
+ a[i] = val;
740
+ }
741
+
742
+ // Values > to the mean, except last one
743
+ for (var i = meanBound + 1; i < nbClass; i++) {
744
+ var val = a[i-1] + tmpStdDev;
745
+ a[i] = val;
746
+ }
747
+ }
748
+
749
+
750
+ // we finally set the first value
751
+ // do we excatly match min value or not ?
752
+ a[0] = (typeof matchBounds === "undefined") ? a[1]- tmpStdDev : tmpMin;
753
+
754
+ // we finally set the last value
755
+ // do we excatly match max value or not ?
756
+ a[nbClass] = (typeof matchBounds === "undefined") ? a[nbClass-1] + tmpStdDev : tmpMax;
757
+
758
+ this.setBounds(a);
759
+ this.setRanges();
760
+
761
+ // we specify the classification method
762
+ this.method = _t('std deviation') + ' (' + nbClass + ' ' + _t('classes')+ ')';
763
+
764
+ return this.bounds;
765
+ };
766
+
767
+
768
+ /**
769
+ * Geometric Progression classification
770
+ * http://en.wikipedia.org/wiki/Geometric_progression
771
+ * Return an array with bounds : ie array(0,
772
+ * 0.75, 1.5, 2.25, 3);
773
+ */
774
+ this.getClassGeometricProgression = function(nbClass) {
775
+
776
+ var nbClass = this._nbClassInt(nbClass); // ensure nbClass is an integer
777
+
778
+ if (this._nodata())
779
+ return;
780
+
781
+ if(this._hasNegativeValue() || this._hasZeroValue()) {
782
+ if(this.silent) this.log("[silent mode] " + _t('geometric progression can\'t be applied with a serie containing negative or zero values.'), true);
783
+ else throw new TypeError(_t('geometric progression can\'t be applied with a serie containing negative or zero values.'));
784
+ return;
785
+ }
786
+
787
+ var a = Array();
788
+ var tmpMin = this.min();
789
+ var tmpMax = this.max();
790
+
791
+ var logMax = Math.log(tmpMax) / Math.LN10; // max decimal logarithm (or base 10)
792
+ var logMin = Math.log(tmpMin) / Math.LN10;
793
+ var interval = (logMax - logMin) / nbClass;
794
+
795
+ // we compute log bounds
796
+ for (var i = 0; i < nbClass; i++) {
797
+ if(i == 0) {
798
+ a[i] = logMin;
799
+ } else {
800
+ a[i] = a[i-1] + interval;
801
+ }
802
+ }
803
+
804
+ // we compute antilog
805
+ a = a.map(function(x) { return Math.pow(10, x); });
806
+
807
+ // and we finally add max value
808
+ a.push(this.max());
809
+
810
+ this.setBounds(a);
811
+ this.setRanges();
812
+
813
+ // we specify the classification method
814
+ this.method = _t('geometric progression') + ' (' + nbClass + ' ' + _t('classes') + ')';
815
+
816
+ return this.bounds;
817
+ };
818
+
819
+ /**
820
+ * Arithmetic Progression classification
821
+ * http://en.wikipedia.org/wiki/Arithmetic_progression
822
+ * Return an array with bounds : ie array(0,
823
+ * 0.75, 1.5, 2.25, 3);
824
+ */
825
+ this.getClassArithmeticProgression = function(nbClass) {
826
+
827
+ var nbClass = this._nbClassInt(nbClass); // ensure nbClass is an integer
828
+
829
+ if (this._nodata())
830
+ return;
831
+
832
+ var denominator = 0;
833
+
834
+ // we compute the (french) "Raison"
835
+ for (var i = 1; i <= nbClass; i++) {
836
+ denominator += i;
837
+ }
838
+
839
+ var a = Array();
840
+ var tmpMin = this.min();
841
+ var tmpMax = this.max();
842
+
843
+ var interval = (tmpMax - tmpMin) / denominator;
844
+
845
+ for (var i = 0; i <= nbClass; i++) {
846
+ if(i == 0) {
847
+ a[i] = tmpMin;
848
+ } else if(i == nbClass) {
849
+ a[i] = tmpMax;
850
+ } else {
851
+ a[i] = a[i-1] + (i * interval);
852
+ }
853
+ }
854
+
855
+ this.setBounds(a);
856
+ this.setRanges();
857
+
858
+ // we specify the classification method
859
+ this.method = _t('arithmetic progression') + ' (' + nbClass + ' ' + _t('classes') + ')';
860
+
861
+ return this.bounds;
862
+ };
863
+
864
+ /**
865
+ * Credits : Doug Curl (javascript) and Daniel J Lewis (python implementation)
866
+ * http://www.arcgis.com/home/item.html?id=0b633ff2f40d412995b8be377211c47b
867
+ * http://danieljlewis.org/2010/06/07/jenks-natural-breaks-algorithm-in-python/
868
+ */
869
+ this.getClassJenks2 = function(nbClass) {
870
+
871
+ var nbClass = this._nbClassInt(nbClass); // ensure nbClass is an integer
872
+
873
+ if (this._nodata())
874
+ return;
875
+
876
+ this._classificationCheck(nbClass); // be sure number of classes is valid
877
+
878
+ var dataList = this.sorted();
879
+
880
+ // now iterate through the datalist:
881
+ // determine mat1 and mat2
882
+ // really not sure how these 2 different arrays are set - the code for
883
+ // each seems the same!
884
+ // but the effect are 2 different arrays: mat1 and mat2
885
+ var mat1 = [];
886
+ for ( var x = 0, xl = dataList.length + 1; x < xl; x++) {
887
+ var temp = [];
888
+ for ( var j = 0, jl = nbClass + 1; j < jl; j++) {
889
+ temp.push(0);
890
+ }
891
+ mat1.push(temp);
892
+ }
893
+
894
+ var mat2 = [];
895
+ for ( var i = 0, il = dataList.length + 1; i < il; i++) {
896
+ var temp2 = [];
897
+ for ( var c = 0, cl = nbClass + 1; c < cl; c++) {
898
+ temp2.push(0);
899
+ }
900
+ mat2.push(temp2);
901
+ }
902
+
903
+ // absolutely no idea what this does - best I can tell, it sets the 1st
904
+ // group in the
905
+ // mat1 and mat2 arrays to 1 and 0 respectively
906
+ for ( var y = 1, yl = nbClass + 1; y < yl; y++) {
907
+ mat1[0][y] = 1;
908
+ mat2[0][y] = 0;
909
+ for ( var t = 1, tl = dataList.length + 1; t < tl; t++) {
910
+ mat2[t][y] = Infinity;
911
+ }
912
+ var v = 0.0;
913
+ }
914
+
915
+ // and this part - I'm a little clueless on - but it works
916
+ // pretty sure it iterates across the entire dataset and compares each
917
+ // value to
918
+ // one another to and adjust the indices until you meet the rules:
919
+ // minimum deviation
920
+ // within a class and maximum separation between classes
921
+ for ( var l = 2, ll = dataList.length + 1; l < ll; l++) {
922
+ var s1 = 0.0;
923
+ var s2 = 0.0;
924
+ var w = 0.0;
925
+ for ( var m = 1, ml = l + 1; m < ml; m++) {
926
+ var i3 = l - m + 1;
927
+ var val = parseFloat(dataList[i3 - 1]);
928
+ s2 += val * val;
929
+ s1 += val;
930
+ w += 1;
931
+ v = s2 - (s1 * s1) / w;
932
+ var i4 = i3 - 1;
933
+ if (i4 != 0) {
934
+ for ( var p = 2, pl = nbClass + 1; p < pl; p++) {
935
+ if (mat2[l][p] >= (v + mat2[i4][p - 1])) {
936
+ mat1[l][p] = i3;
937
+ mat2[l][p] = v + mat2[i4][p - 1];
938
+ }
939
+ }
940
+ }
941
+ }
942
+ mat1[l][1] = 1;
943
+ mat2[l][1] = v;
944
+ }
945
+
946
+ var k = dataList.length;
947
+ var kclass = [];
948
+
949
+ // fill the kclass (classification) array with zeros:
950
+ for (var i = 0; i <= nbClass; i++) {
951
+ kclass.push(0);
952
+ }
953
+
954
+ // this is the last number in the array:
955
+ kclass[nbClass] = parseFloat(dataList[dataList.length - 1]);
956
+ // this is the first number - can set to zero, but want to set to lowest
957
+ // to use for legend:
958
+ kclass[0] = parseFloat(dataList[0]);
959
+ var countNum = nbClass;
960
+ while (countNum >= 2) {
961
+ var id = parseInt((mat1[k][countNum]) - 2);
962
+ kclass[countNum - 1] = dataList[id];
963
+ k = parseInt((mat1[k][countNum] - 1));
964
+ // spits out the rank and value of the break values:
965
+ // console.log("id="+id,"rank = " + String(mat1[k][countNum]),"val =
966
+ // " + String(dataList[id]))
967
+ // count down:
968
+ countNum -= 1;
969
+ }
970
+ // check to see if the 0 and 1 in the array are the same - if so, set 0
971
+ // to 0:
972
+ if (kclass[0] == kclass[1]) {
973
+ kclass[0] = 0;
974
+ }
975
+
976
+ this.setBounds(kclass);
977
+ this.setRanges();
978
+
979
+
980
+ this.method = _t('Jenks2') + ' (' + nbClass + ' ' + _t('classes') + ')';
981
+
982
+ return this.bounds; //array of breaks
983
+ };
984
+
985
+ /**
986
+ * Credits from simple-statistics library
987
+ * https://github.com/simple-statistics/simple-statistics
988
+ * https://gist.githubusercontent.com/tmcw/4969184/raw/cfd9572d00db6bcdc34f07b088738fc3a47846b4/simple_statistics.js
989
+ */
990
+ this.getClassJenks = function(nbClass) {
991
+
992
+ var nbClass = this._nbClassInt(nbClass); // ensure nbClass is an integer
993
+
994
+ if (this._nodata())
995
+ return;
996
+
997
+ this._classificationCheck(nbClass); // be sure number of classes is valid
998
+
999
+ var dataList = this.sorted();
1000
+
1001
+ // Compute the matrices required for Jenks breaks. These matrices
1002
+ // can be used for any classing of data with `classes <= n_classes`
1003
+ var jenksMatrices = function(data, n_classes) {
1004
+
1005
+ // in the original implementation, these matrices are referred to
1006
+ // as `LC` and `OP`
1007
+ //
1008
+ // * lower_class_limits (LC): optimal lower class limits
1009
+ // * variance_combinations (OP): optimal variance combinations for all classes
1010
+ var lower_class_limits = [],
1011
+ variance_combinations = [],
1012
+ // loop counters
1013
+ i, j,
1014
+ // the variance, as computed at each step in the calculation
1015
+ variance = 0;
1016
+
1017
+ // Initialize and fill each matrix with zeroes
1018
+ for (var i = 0; i < data.length + 1; i++) {
1019
+ var tmp1 = [], tmp2 = [];
1020
+ for (var j = 0; j < n_classes + 1; j++) {
1021
+ tmp1.push(0);
1022
+ tmp2.push(0);
1023
+ }
1024
+ lower_class_limits.push(tmp1);
1025
+ variance_combinations.push(tmp2);
1026
+ }
1027
+
1028
+ for (var i = 1; i < n_classes + 1; i++) {
1029
+ lower_class_limits[1][i] = 1;
1030
+ variance_combinations[1][i] = 0;
1031
+ // in the original implementation, 9999999 is used but
1032
+ // since Javascript has `Infinity`, we use that.
1033
+ for (var j = 2; j < data.length + 1; j++) {
1034
+ variance_combinations[j][i] = Infinity;
1035
+ }
1036
+ }
1037
+
1038
+ for (var l = 2; l < data.length + 1; l++) {
1039
+
1040
+ // `SZ` originally. this is the sum of the values seen thus
1041
+ // far when calculating variance.
1042
+ var sum = 0,
1043
+ // `ZSQ` originally. the sum of squares of values seen
1044
+ // thus far
1045
+ sum_squares = 0,
1046
+ // `WT` originally. This is the number of
1047
+ w = 0,
1048
+ // `IV` originally
1049
+ i4 = 0;
1050
+
1051
+ // in several instances, you could say `Math.pow(x, 2)`
1052
+ // instead of `x * x`, but this is slower in some browsers
1053
+ // introduces an unnecessary concept.
1054
+ for (var m = 1; m < l + 1; m++) {
1055
+
1056
+ // `III` originally
1057
+ var lower_class_limit = l - m + 1,
1058
+ val = data[lower_class_limit - 1];
1059
+
1060
+ // here we're estimating variance for each potential classing
1061
+ // of the data, for each potential number of classes. `w`
1062
+ // is the number of data points considered so far.
1063
+ w++;
1064
+
1065
+ // increase the current sum and sum-of-squares
1066
+ sum += val;
1067
+ sum_squares += val * val;
1068
+
1069
+ // the variance at this point in the sequence is the difference
1070
+ // between the sum of squares and the total x 2, over the number
1071
+ // of samples.
1072
+ variance = sum_squares - (sum * sum) / w;
1073
+
1074
+ i4 = lower_class_limit - 1;
1075
+
1076
+ if (i4 !== 0) {
1077
+ for (var j = 2; j < n_classes + 1; j++) {
1078
+ if (variance_combinations[l][j] >=
1079
+ (variance + variance_combinations[i4][j - 1])) {
1080
+ lower_class_limits[l][j] = lower_class_limit;
1081
+ variance_combinations[l][j] = variance +
1082
+ variance_combinations[i4][j - 1];
1083
+ }
1084
+ }
1085
+ }
1086
+ }
1087
+
1088
+ lower_class_limits[l][1] = 1;
1089
+ variance_combinations[l][1] = variance;
1090
+ }
1091
+
1092
+ return {
1093
+ lower_class_limits: lower_class_limits,
1094
+ variance_combinations: variance_combinations
1095
+ };
1096
+ };
1097
+
1098
+ // get our basic matrices
1099
+ var matrices = jenksMatrices(dataList, nbClass),
1100
+ // we only need lower class limits here
1101
+ lower_class_limits = matrices.lower_class_limits,
1102
+ k = dataList.length - 1,
1103
+ kclass = [],
1104
+ countNum = nbClass;
1105
+
1106
+ // the calculation of classes will never include the upper and
1107
+ // lower bounds, so we need to explicitly set them
1108
+ kclass[nbClass] = dataList[dataList.length - 1];
1109
+ kclass[0] = dataList[0];
1110
+
1111
+ // the lower_class_limits matrix is used as indexes into itself
1112
+ // here: the `k` variable is reused in each iteration.
1113
+ while (countNum > 1) {
1114
+ kclass[countNum - 1] = dataList[lower_class_limits[k][countNum] - 2];
1115
+ k = lower_class_limits[k][countNum] - 1;
1116
+ countNum--;
1117
+ }
1118
+
1119
+ this.setBounds(kclass);
1120
+ this.setRanges();
1121
+
1122
+
1123
+ this.method = _t('Jenks') + ' (' + nbClass + ' ' + _t('classes') + ')';
1124
+
1125
+ return this.bounds; //array of breaks
1126
+ };
1127
+
1128
+
1129
+ /**
1130
+ * Unique classification Return as many entries as unique values : ie array('blue', 'red', yellow')
1131
+ * 1.5, 2.25, 3);
1132
+ */
1133
+ this.getClassUniqueValues = function() {
1134
+
1135
+ if (this._nodata())
1136
+ return;
1137
+
1138
+ this.is_uniqueValues = true;
1139
+
1140
+ var tmp = this.sorted(); // display in alphabetical order
1141
+
1142
+ var a = Array();
1143
+
1144
+ for (var i = 0; i < this.pop(); i++) {
1145
+ if(a.indexOf(tmp[i]) === -1)
1146
+ a.push(tmp[i]);
1147
+ }
1148
+
1149
+ this.bounds = a;
1150
+
1151
+ // we specify the classification method
1152
+ this.method = _t('unique values');
1153
+
1154
+ return a;
1155
+
1156
+ };
1157
+
1158
+
1159
+ /**
1160
+ * Return the class of a given value.
1161
+ * For example value : 6
1162
+ * and bounds array = (0, 4, 8, 12);
1163
+ * Return 2
1164
+ */
1165
+ this.getClass = function(value) {
1166
+
1167
+ for (var i = 0; i < this.bounds.length; i++) {
1168
+
1169
+ if(this.is_uniqueValues == true) {
1170
+
1171
+ if(value == this.bounds[i]) {
1172
+ // console.log(value + ' - ' + this.bounds[i] + ' returned value : ' + i);
1173
+ return i;
1174
+ }
1175
+ } else {
1176
+ // parseFloat() is necessary
1177
+ if(parseFloat(value) <= this.bounds[i + 1]) {
1178
+ return i;
1179
+ }
1180
+ }
1181
+ }
1182
+
1183
+ return _t("Unable to get value's class.");
1184
+
1185
+ };
1186
+
1187
+ /**
1188
+ * Return the ranges array : array('0-0.75', '0.75-1.5', '1.5-2.25',
1189
+ * '2.25-3');
1190
+ */
1191
+ this.getRanges = function() {
1192
+
1193
+ return this.ranges;
1194
+
1195
+ };
1196
+
1197
+ /**
1198
+ * Returns the number/index of this.ranges that value falls into
1199
+ */
1200
+ this.getRangeNum = function(value) {
1201
+
1202
+ var bounds, i;
1203
+
1204
+ for (var i = 0; i < this.ranges.length; i++) {
1205
+ bounds = this.ranges[i].split(/ - /);
1206
+ if (value <= parseFloat(bounds[1])) {
1207
+ return i;
1208
+ }
1209
+ }
1210
+ };
1211
+
1212
+ /*
1213
+ * Compute inner ranges based on serie.
1214
+ * Produce discontinous ranges used for legend - return an array similar to :
1215
+ * array('0.00-0.74', '0.98-1.52', '1.78-2.25', '2.99-3.14');
1216
+ * If inner ranges already computed, return array values.
1217
+ */
1218
+ this.getInnerRanges = function() {
1219
+
1220
+ // if already computed, we return the result
1221
+ if(this.inner_ranges != null)
1222
+ return this.inner_ranges;
1223
+
1224
+
1225
+ var a = new Array();
1226
+ var tmp = this.sorted();
1227
+
1228
+ var cnt = 1; // bounds array counter
1229
+
1230
+ for (var i = 0; i < tmp.length; i++) {
1231
+
1232
+ if(i == 0) var range_firstvalue = tmp[i]; // we init first range value
1233
+
1234
+ if(parseFloat(tmp[i]) > parseFloat(this.bounds[cnt])) {
1235
+
1236
+ a[cnt - 1] = '' + range_firstvalue + this.separator + tmp[i-1];
1237
+
1238
+ var range_firstvalue = tmp[i];
1239
+
1240
+ cnt++;
1241
+
1242
+ }
1243
+
1244
+ // we reach the last range, we finally complete manually
1245
+ // and return the array
1246
+ if(cnt == (this.bounds.length - 1)) {
1247
+ // we set the last value
1248
+ a[cnt - 1] = '' + range_firstvalue + this.separator + tmp[tmp.length-1];
1249
+
1250
+ this.inner_ranges = a;
1251
+ return this.inner_ranges;
1252
+ }
1253
+
1254
+
1255
+ }
1256
+
1257
+ };
1258
+
1259
+ this.getSortedlist = function() {
1260
+
1261
+ return this.sorted().join(', ');
1262
+
1263
+ };
1264
+
1265
+ /**
1266
+ * Return an html legend
1267
+ * colors : specify an array of color (hexadecimal values)
1268
+ * legend : specify a text input for the legend. By default, just displays 'legend'
1269
+ * counter : if not null, display counter value
1270
+ * callback : if not null, callback function applied on legend boundaries
1271
+ * mode : null, 'default', 'distinct', 'discontinuous' :
1272
+ * - if mode is null, will display legend as 'default mode'
1273
+ * - 'default' : displays ranges like in ranges array (continuous values), sample : 29.26 - 378.80 / 378.80 - 2762.25 / 2762.25 - 6884.84
1274
+ * - 'distinct' : Add + 1 according to decimal precision to distinguish classes (discrete values), sample : 29.26 - 378.80 / 378.81 - 2762.25 / 2762.26 - 6884.84
1275
+ * - 'discontinuous' : indicates the range of data actually falling in each class , sample : 29.26 - 225.43 / 852.12 - 2762.20 / 3001.25 - 6884.84 / not implemented yet
1276
+ * order : null, 'ASC', 'DESC'
1277
+ */
1278
+ this.getHtmlLegend = function(colors, legend, counter, callback, mode, order) {
1279
+
1280
+ var cnt= '';
1281
+ var elements = new Array();
1282
+
1283
+ this.doCount(); // we do count, even if not displayed
1284
+
1285
+ if(colors != null) {
1286
+ ccolors = colors;
1287
+ }
1288
+ else {
1289
+ ccolors = this.colors;
1290
+ }
1291
+
1292
+ if(legend != null) {
1293
+ lg = legend;
1294
+ }
1295
+ else {
1296
+ lg = 'Legend';
1297
+ }
1298
+
1299
+ if(counter != null) {
1300
+ getcounter = true;
1301
+ }
1302
+ else {
1303
+ getcounter = false;
1304
+ }
1305
+
1306
+ if(callback != null) {
1307
+ fn = callback;
1308
+ }
1309
+ else {
1310
+ fn = function(o) {return o;};
1311
+ }
1312
+ if(mode == null) {
1313
+ mode = 'default';
1314
+ }
1315
+ if(mode == 'discontinuous') {
1316
+ this.getInnerRanges();
1317
+ // check if some classes are not populated / equivalent of in_array function
1318
+ if(this.counter.indexOf(0) !== -1) {
1319
+ if(this.silent) this.log("[silent mode] " + _t("Geostats cannot apply 'discontinuous' mode to the getHtmlLegend() method because some classes are not populated.\nPlease switch to 'default' or 'distinct' modes. Exit!"), true);
1320
+ else throw new TypeError(_t("Geostats cannot apply 'discontinuous' mode to the getHtmlLegend() method because some classes are not populated.\nPlease switch to 'default' or 'distinct' modes. Exit!"));
1321
+ return;
1322
+ }
1323
+
1324
+ }
1325
+ if(order !== 'DESC') order = 'ASC';
1326
+
1327
+ if(ccolors.length < this.ranges.length) {
1328
+ if(this.silent) this.log("[silent mode] " + _t('The number of colors should fit the number of ranges. Exit!'), true);
1329
+ else throw new TypeError(_t('The number of colors should fit the number of ranges. Exit!'));
1330
+ return;
1331
+ }
1332
+
1333
+ if(this.is_uniqueValues == false) {
1334
+
1335
+ for (var i = 0; i < (this.ranges.length); i++) {
1336
+ if(getcounter===true) {
1337
+ cnt = ' <span class="geostats-legend-counter">(' + this.counter[i] + ')</span>';
1338
+ }
1339
+ //console.log("Ranges : " + this.ranges[i]);
1340
+
1341
+ // default mode
1342
+ var tmp = this.ranges[i].split(this.separator);
1343
+
1344
+ var start_value = parseFloat(tmp[0]).toFixed(this.precision);
1345
+ var end_value = parseFloat(tmp[1]).toFixed(this.precision);
1346
+
1347
+
1348
+ // if mode == 'distinct' and we are not working on the first value
1349
+ if(mode == 'distinct' && i != 0) {
1350
+
1351
+ if(isInt(start_value)) {
1352
+ start_value = parseInt(start_value) + 1;
1353
+ // format to float if necessary
1354
+ if(this.precisionflag == 'manual' && this.precision != 0) start_value = parseFloat(start_value).toFixed(this.precision);
1355
+ } else {
1356
+
1357
+ start_value = parseFloat(start_value) + (1 / Math.pow(10,this.precision));
1358
+ // strangely the formula above return sometimes long decimal values,
1359
+ // the following instruction fix it
1360
+ start_value = parseFloat(start_value).toFixed(this.precision);
1361
+ }
1362
+ }
1363
+
1364
+ // if mode == 'discontinuous'
1365
+ if(mode == 'discontinuous') {
1366
+
1367
+ var tmp = this.inner_ranges[i].split(this.separator);
1368
+ // console.log("Ranges : " + this.inner_ranges[i]);
1369
+
1370
+ var start_value = parseFloat(tmp[0]).toFixed(this.precision);
1371
+ var end_value = parseFloat(tmp[1]).toFixed(this.precision);
1372
+
1373
+ }
1374
+
1375
+ // we apply callback function
1376
+ var el = fn(start_value) + this.legendSeparator + fn(end_value);
1377
+
1378
+ var block = '<div><div class="geostats-legend-block" style="background-color:' + ccolors[i] + '"></div> ' + el + cnt + '</div>';
1379
+ elements.push(block);
1380
+ }
1381
+
1382
+ } else {
1383
+
1384
+ // only if classification is done on unique values
1385
+ for (var i = 0; i < (this.bounds.length); i++) {
1386
+ if(getcounter===true) {
1387
+ cnt = ' <span class="geostats-legend-counter">(' + this.counter[i] + ')</span>';
1388
+ }
1389
+ var el = fn(this.bounds[i]);
1390
+ var block = '<div><div class="geostats-legend-block" style="background-color:' + ccolors[i] + '"></div> ' + el + cnt + '</div>';
1391
+
1392
+ elements.push(block);
1393
+ }
1394
+
1395
+ }
1396
+
1397
+ // do we reverse the return legend ?
1398
+ if(order === 'DESC') elements.reverse();
1399
+
1400
+ // finally we create HTML and return it
1401
+ var content = '<div class="geostats-legend"><div class="geostats-legend-title">' + _t(lg) + '</div>';
1402
+ for (var i = 0; i < (elements.length); i++) {
1403
+ content += elements[i];
1404
+ }
1405
+ content += '</div>';
1406
+
1407
+ return content;
1408
+ };
1409
+
1410
+
1411
+
1412
+ // object constructor
1413
+ // At the end of script. If not setPrecision() method is not known
1414
+
1415
+ // we create an object identifier for debugging
1416
+ this.objectID = new Date().getUTCMilliseconds();
1417
+ this.log('Creating new geostats object');
1418
+
1419
+ if(typeof a !== 'undefined' && a.length > 0) {
1420
+ this.serie = a;
1421
+ this.setPrecision();
1422
+ this.log('Setting serie (' + a.length + ') : ' + a.join());
1423
+ } else {
1424
+ this.serie = Array();
1425
+
1426
+ }
1427
+ // creating aliases on classification function for backward compatibility
1428
+ this.getJenks = this.getClassJenks;
1429
+ this.getJenks2 = this.getClassJenks2;
1430
+ this.getGeometricProgression = this.getClassGeometricProgression;
1431
+ this.getEqInterval = this.getClassEqInterval;
1432
+ this.getQuantile = this.getClassQuantile;
1433
+ this.getStdDeviation = this.getClassStdDeviation;
1434
+ this.getUniqueValues = this.getClassUniqueValues;
1435
+ this.getArithmeticProgression = this.getClassArithmeticProgression;
1436
+
1437
+ };
1438
+
1439
+
1440
+ return geostats;
1441
+ });
1442
+ } (geostats$1));
1443
+ return geostats$1.exports;
1444
+ }
1445
+
1446
+ var geostatsExports = requireGeostats();
1447
+ const geostats = /*@__PURE__*/getDefaultExportFromCjs(geostatsExports);
1448
+
1449
+ L.SolrHeatmap = L.GeoJSON.extend({
1450
+ options: {
1451
+ solrRequestHandler: 'select',
1452
+ type: 'geojsonGrid',
1453
+ colors: ['#f1eef6', '#d7b5d8', '#df65b0', '#dd1c77', '#980043'],
1454
+ maxSampleSize: Number.MAX_SAFE_INTEGER, // for Jenks classification
1455
+ logging: false,
1456
+ },
1457
+
1458
+ initialize: function (url, options) {
1459
+ var _this = this;
1460
+ options = L.setOptions(_this, options);
1461
+ _this._solrUrl = url;
1462
+ _this._layers = {};
1463
+ _this._getData();
1464
+ },
1465
+
1466
+ onAdd: function (map) {
1467
+ var _this = this;
1468
+
1469
+ // Call the parent function
1470
+ L.GeoJSON.prototype.onAdd.call(_this, map);
1471
+
1472
+ map.on('moveend', function () {
1473
+ _this._getData();
1474
+ });
1475
+ },
1476
+
1477
+ _computeHeatmapObject: function (data) {
1478
+ var _this = this;
1479
+ _this.facetHeatmap = data.response.facet_heatmaps[this.options.field];
1480
+ this._computeIntArrays();
1481
+ },
1482
+
1483
+ _clearLayers: function () {
1484
+ var _this = this;
1485
+
1486
+ switch (_this.options.type) {
1487
+ case 'geojsonGrid':
1488
+ _this.clearLayers();
1489
+ break;
1490
+ case 'clusters':
1491
+ _this.clusterMarkers.clearLayers();
1492
+ break;
1493
+ case 'heatmap':
1494
+ _this._map.removeLayer(_this.heatmapLayer);
1495
+ break;
1496
+ }
1497
+ },
1498
+
1499
+ _createGeojson: function () {
1500
+ var _this = this;
1501
+ var geojson = {};
1502
+
1503
+ geojson.type = 'FeatureCollection';
1504
+ geojson.features = [];
1505
+
1506
+ _this.facetHeatmap.counts_ints2D.forEach(function(value, row) {
1507
+ if (value === null) {
1508
+ return;
1509
+ }
1510
+
1511
+ value.forEach(function (val, column) {
1512
+ if (val === 0) {
1513
+ return;
1514
+ }
1515
+
1516
+ var newFeature = {
1517
+ type: 'Feature',
1518
+ geometry: {
1519
+ type: 'Polygon',
1520
+ coordinates: [
1521
+ [
1522
+ [_this._minLng(column), _this._minLat(row)],
1523
+ [_this._minLng(column), _this._maxLat(row)],
1524
+ [_this._maxLng(column), _this._maxLat(row)],
1525
+ [_this._maxLng(column), _this._minLat(row)],
1526
+ [_this._minLng(column), _this._minLat(row)]
1527
+ ]
1528
+ ]
1529
+ },
1530
+ properties: {
1531
+ count: val
1532
+ }
1533
+ };
1534
+ geojson.features.push(newFeature);
1535
+ });
1536
+ });
1537
+
1538
+ _this.addData(geojson);
1539
+ var colors = _this.options.colors;
1540
+ if (_this.facetHeatmap.counts_ints2D && _this.facetHeatmap.counts_ints2D.length > 0) {
1541
+ var classifications = _this._getClassifications(colors.length);
1542
+ _this._styleByCount(classifications);
1543
+ _this._showRenderTime();
1544
+ }
1545
+ },
1546
+
1547
+ _createHeatmap: function () {
1548
+ var _this = this;
1549
+ var heatmapCells = [];
1550
+ var cellSize = _this._getCellSize() * .75;
1551
+ var colors = _this.options.colors;
1552
+ var classifications = _this._getClassifications(colors.length - 1);
1553
+ var maxValue = classifications[classifications.length - 1];
1554
+ var gradient = _this._getGradient(classifications);
1555
+
1556
+ _this.facetHeatmap.counts_ints2D.forEach(function(value, row) {
1557
+ if (value === null) {
1558
+ return;
1559
+ }
1560
+
1561
+ value.forEach(function (val, column) {
1562
+ if (val === 0) {
1563
+ return;
1564
+ }
1565
+
1566
+ var scaledValue = Math.min((val / maxValue), 1);
1567
+ var current = [_this._minLat(row), _this._minLng(column), scaledValue];
1568
+ heatmapCells.push(current);
1569
+
1570
+ // need to create options object to set gradient, blu, radius, max
1571
+ });
1572
+ });
1573
+
1574
+ // settting max due to bug
1575
+ // http://stackoverflow.com/questions/26767722/leaflet-heat-issue-with-adding-points-with-intensity
1576
+ var options = { max: .0001, radius: cellSize, gradient: gradient };
1577
+ var heatmapLayer = L.heatLayer(heatmapCells, options);
1578
+ heatmapLayer.addTo(_this._map);
1579
+ _this.heatmapLayer = heatmapLayer;
1580
+ _this._showRenderTime();
1581
+ },
1582
+
1583
+ // heatmap display need hash of scaled counts value, color pairs
1584
+ _getGradient: function (classifications) {
1585
+ var gradient = {};
1586
+ var maxValue = classifications[classifications.length - 1];
1587
+ var colors = _this.options.colors;
1588
+ // skip first lower bound, assumed to be 0 from Jenks
1589
+ for (var i = 1; i < classifications.length; i++)
1590
+ gradient[classifications[i] / maxValue] = colors[i];
1591
+ return gradient;
1592
+ },
1593
+
1594
+ // compute size of heatmap cells in pixels
1595
+ _getCellSize: function () {
1596
+ const _this = this;
1597
+ var mapSize = _this._map.getSize(); // should't we use solr returned map extent?
1598
+ var widthInPixels = mapSize.x;
1599
+ var heightInPixels = mapSize.y;
1600
+ var heatmapRows = _this.facetHeatmap.rows;
1601
+ var heatmapColumns = _this.facetHeatmap.columns;
1602
+ var sizeX = widthInPixels / heatmapColumns;
1603
+ var sizeY = heightInPixels / heatmapRows;
1604
+ var size = Math.ceil(Math.max(sizeX, sizeY));
1605
+ return size;
1606
+ },
1607
+
1608
+ _showRenderTime: function () {
1609
+ if (this.options.logging) {
1610
+ var _this = this;
1611
+ var renderTime = 'Render time: ' + (Date.now() - _this.renderStart) + ' ms';
1612
+ console.log(renderTime);
1613
+ }
1614
+ },
1615
+
1616
+ _createClusters: function() {
1617
+ var _this = this;
1618
+
1619
+ _this.clusterMarkers = new L.MarkerClusterGroup({
1620
+ maxClusterRadius: 140,
1621
+ });
1622
+
1623
+ _this.facetHeatmap.counts_ints2D.forEach(function(value, row) {
1624
+ if (value === null) {
1625
+ return;
1626
+ }
1627
+
1628
+ value.forEach(function (val, column) {
1629
+ if (val === 0) {
1630
+ return;
1631
+ }
1632
+
1633
+ var bounds = new L.latLngBounds([
1634
+ [_this._minLat(row), _this._minLng(column)],
1635
+ [_this._maxLat(row), _this._maxLng(column)],
1636
+ ]);
1637
+ _this.clusterMarkers.addLayer(new L.Marker(bounds.getCenter(), {
1638
+ count: val,
1639
+ }).bindPopup(val.toString()));
1640
+ });
1641
+ });
1642
+
1643
+ _this._map.addLayer(_this.clusterMarkers);
1644
+ _this._showRenderTime();
1645
+ },
1646
+
1647
+ _computeIntArrays: function () {
1648
+ var _this = this;
1649
+
1650
+ _this.lengthX = (_this.facetHeatmap.maxX - _this.facetHeatmap.minX) / _this.facetHeatmap.columns;
1651
+ _this.lengthY = (_this.facetHeatmap.maxY - _this.facetHeatmap.minY) / _this.facetHeatmap.rows;
1652
+ _this._clearLayers();
1653
+ switch (_this.options.type) {
1654
+ case 'geojsonGrid':
1655
+ _this._createGeojson();
1656
+ break;
1657
+ case 'clusters':
1658
+ _this._createClusters();
1659
+ break;
1660
+ case 'heatmap':
1661
+ _this._createHeatmap();
1662
+ break;
1663
+ }
1664
+ },
1665
+
1666
+ _getClassifications: function (howMany) {
1667
+ var _this = this;
1668
+ var oneDArray = [];
1669
+ _this.facetHeatmap.counts_ints2D.forEach(function(value, row) {
1670
+ if (value != null) {
1671
+ oneDArray = oneDArray.concat(value);
1672
+ }
1673
+ });
1674
+
1675
+ var sampledArray = _this._sampleCounts(oneDArray);
1676
+
1677
+ var series = new geostats(sampledArray);
1678
+ _this.options.colors;
1679
+ var classifications = series.getClassJenks(howMany - 1);
1680
+ return classifications.reduce(function (previous, current) {
1681
+ if (previous.indexOf(current) == -1) {
1682
+ previous.push(current);
1683
+ }
1684
+
1685
+ return previous;
1686
+ }, []);
1687
+ },
1688
+
1689
+ _styleByCount: function (classifications) {
1690
+ var _this = this;
1691
+ var scale = _this.options.colors.slice(this.options.colors.length - classifications.length, this.options.colors.length);
1692
+
1693
+ _this.eachLayer(function (layer) {
1694
+ var color;
1695
+ classifications.forEach(function (val, i) {
1696
+ if (layer.feature.properties.count >= val) {
1697
+ color = scale[i];
1698
+ }
1699
+ });
1700
+
1701
+ layer.setStyle({
1702
+ fillColor: color,
1703
+ fillOpacity: 0.5,
1704
+ weight: 0,
1705
+ });
1706
+ });
1707
+ },
1708
+
1709
+ // Jenks classification can be slow so we optionally sample the data
1710
+ // typically any big sample of counts are much the same, don't need to classify on all of them
1711
+ _sampleCounts: function (passedArray) {
1712
+ const _this = this;
1713
+ if (passedArray.length <= _this.options.maxSampleSize) {
1714
+ return passedArray; // array too small to sample
1715
+ }
1716
+
1717
+ var maxValue = Math.max.apply(Math, passedArray);
1718
+ var sampledArray = [];
1719
+ var period = Math.ceil(passedArray.length / _this.options.maxSampleSize);
1720
+ for (let i = 0; i < passedArray.length; i = i + period) {
1721
+ sampledArray.push(passedArray[i]);
1722
+ }
1723
+
1724
+ sampledArray.push(maxValue); // make sure largest value gets in, doesn't matter much if duplicated
1725
+ return sampledArray;
1726
+ },
1727
+
1728
+ _minLng: function (column) {
1729
+ return this.facetHeatmap.minX + (this.lengthX * column);
1730
+ },
1731
+
1732
+ _minLat: function (row) {
1733
+ return this.facetHeatmap.maxY - (this.lengthY * row) - this.lengthY;
1734
+ },
1735
+
1736
+ _maxLng: function (column) {
1737
+ return this.facetHeatmap.minX + (this.lengthX * column) + this.lengthX;
1738
+ },
1739
+
1740
+ _maxLat: function (row) {
1741
+ return this.facetHeatmap.maxY - (this.lengthY * row);
1742
+ },
1743
+
1744
+ _getData: function () {
1745
+ var _this = this;
1746
+ var startTime = Date.now();
1747
+
1748
+ var url = new URL(_this._solrUrl);
1749
+ url.searchParams.append('bbox', _this._mapViewToBbox());
1750
+
1751
+ fetch(url, {
1752
+ headers: {
1753
+ 'Accept': 'application/json',
1754
+ }
1755
+ }).then(function (response) {
1756
+ return response.json();
1757
+ }).then(function (data) {
1758
+ var totalTime = 'Solr response time: ' + (Date.now() - startTime) + ' ms';
1759
+ if (_this.options.logging) {
1760
+ console.log(totalTime);
1761
+ }
1762
+
1763
+ _this.docsCount = data.response.numFound;
1764
+ _this.renderStart = Date.now();
1765
+ _this._computeHeatmapObject(data);
1766
+ _this.fireEvent('dataAdded', data);
1767
+ });
1768
+ },
1769
+
1770
+ _mapViewToBbox: function () {
1771
+ if (this._map === undefined) {
1772
+ return '-180,-90,180,90';
1773
+ }
1774
+
1775
+ var bounds = this._map.getBounds();
1776
+ var wrappedSw = bounds.getSouthWest().wrap();
1777
+ var wrappedNe = bounds.getNorthEast().wrap();
1778
+ return [wrappedSw.lng, bounds.getSouth(), wrappedNe.lng, bounds.getNorth()].join(',');
1779
+ },
1780
+
1781
+ _mapViewToEnvelope: function () {
1782
+ if (this._map === undefined) {
1783
+ return ':"Intersects(ENVELOPE(-180, 180, 90, -90))"';
1784
+ }
1785
+
1786
+ var bounds = this._map.getBounds();
1787
+ var wrappedSw = bounds.getSouthWest().wrap();
1788
+ var wrappedNe = bounds.getNorthEast().wrap();
1789
+ return ':"Intersects(ENVELOPE(' + wrappedSw.lng + ', ' + wrappedNe.lng + ', ' + bounds.getNorth() + ', ' + bounds.getSouth() + '))"';
1790
+ },
1791
+
1792
+ _mapViewToWkt: function () {
1793
+ if (this._map === undefined) {
1794
+ return '["-180 -90" TO "180 90"]';
1795
+ }
1796
+
1797
+ var bounds = this._map.getBounds();
1798
+ var wrappedSw = bounds.getSouthWest().wrap();
1799
+ var wrappedNe = bounds.getNorthEast().wrap();
1800
+ return '["' + wrappedSw.lng + ' ' + bounds.getSouth() + '" TO "' + wrappedNe.lng + ' ' + bounds.getNorth() + '"]';
1801
+ },
1802
+
1803
+ _solrQuery: function () {
1804
+ return '/' + this.options.solrRequestHandler + '?' + this.options.field;
1805
+ },
1806
+ });
1807
+
1808
+ L.solrHeatmap = function (url, options) {
1809
+ return new L.SolrHeatmap(url, options);
1810
+ };
1811
+
1812
+ // Check if L.MarkerCluster is included
1813
+ if (typeof L.MarkerCluster !== 'undefined') {
1814
+ L.MarkerCluster.prototype.initialize = function (group, zoom, a, b) {
1815
+
1816
+ L.Marker.prototype.initialize.call(this, a ? (a._cLatLng || a.getLatLng()) : new L.LatLng(0, 0), { icon: this });
1817
+
1818
+ this._group = group;
1819
+ this._zoom = zoom;
1820
+
1821
+ this._markers = [];
1822
+ this._childClusters = [];
1823
+ this._childCount = 0;
1824
+ this._iconNeedsUpdate = true;
1825
+
1826
+ this._bounds = new L.LatLngBounds();
1827
+
1828
+ if (a) {
1829
+ this._addChild(a);
1830
+ }
1831
+
1832
+ if (b) {
1833
+ this._addChild(b);
1834
+ this._childCount = b.options.count;
1835
+ }
1836
+ };
1837
+ }
1838
+
1839
+ const Basemaps = {
1840
+ darkMatter: L.tileLayer(
1841
+ 'https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png', {
1842
+ attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://cartodb.com/attributions">CartoDB</a>',
1843
+ maxZoom: 18,
1844
+ worldCopyJump: true,
1845
+ detectRetina: true,
1846
+ }
1847
+ ),
1848
+ positron: L.tileLayer(
1849
+ 'https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png', {
1850
+ attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://cartodb.com/attributions">CartoDB</a>',
1851
+ maxZoom: 18,
1852
+ worldCopyJump: true,
1853
+ detectRetina: true,
1854
+ }
1855
+ ),
1856
+ 'OpenStreetMap.HOT': L.tileLayer(
1857
+ 'https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
1858
+ attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, Tiles courtesy of <a href="http://hot.openstreetmap.org/" target="_blank">Humanitarian OpenStreetMap Team</a>',
1859
+ maxZoom: 19,
1860
+ }
1861
+ ),
1862
+ };
1863
+
1864
+ const Icons = {
1865
+ default: new L.Icon.Default()
1866
+ };
1867
+
1868
+ const IndexView = L.Class.extend({
1869
+ options: {},
1870
+
1871
+ initialize: function (el, options) {
1872
+ var requestUrl = el.dataset.searchUrl + '&format=heatmaps';
1873
+ var geometryField = el.dataset.geometryField;
1874
+ var template = el.dataset.sidebarTemplate;
1875
+ var colorRamp = JSON.parse(el.dataset.colorRamp);
1876
+
1877
+ // Blank out page link content first and disable pagination
1878
+ document.querySelectorAll('#sortAndPerPage .page-links').forEach(function (links) {
1879
+ links.innerHTML = '';
1880
+ });
1881
+ document.querySelectorAll('ul.pagination').forEach(function (links) {
1882
+ links.classList.add('d-none');
1883
+ });
1884
+
1885
+ var map = L.map(el.id).setView([0, 0], 1);
1886
+ BlacklightHeatmaps.selectBasemap(
1887
+ el.dataset.basemapProvider
1888
+ ).addTo(map);
1889
+
1890
+ var solrLayer = L.solrHeatmap(requestUrl, {
1891
+ field: geometryField,
1892
+ maxSampleSize: 50,
1893
+ colors: colorRamp,
1894
+ }).addTo(map);
1895
+
1896
+ var sidebar = L.control.sidebar('index-map-sidebar', {
1897
+ position: 'right',
1898
+ });
1899
+
1900
+ map.addControl(sidebar);
1901
+
1902
+ solrLayer.on('click', function (e) {
1903
+ if (!sidebar.isVisible()) {
1904
+ map.setView(e.latlng);
1905
+ } else {
1906
+ var point = map.project(e.latlng);
1907
+ var offset = sidebar.getOffset();
1908
+ var newPoint = L.point(point.x - (offset / 2), point.y);
1909
+ map.setView(map.unproject(newPoint));
1910
+ }
1911
+
1912
+ sidebar.show();
1913
+ });
1914
+
1915
+ solrLayer.on('dataAdded', function (e) {
1916
+ if (e.response && e.response.docs) {
1917
+ var html = '';
1918
+ e.response.docs.forEach(function (value) {
1919
+ html += L.Util.template(template, value);
1920
+ });
1921
+
1922
+ sidebar.setContent(html);
1923
+
1924
+ var docCount = e.response.pages.total_count;
1925
+
1926
+ document.querySelectorAll('#sortAndPerPage .page-links').forEach(function (links) {
1927
+ links.innerHTML = parseInt(docCount).toLocaleString() + ' ' + (docCount == 1 ? 'item' : 'items') + ' found';
1928
+ });
1929
+ }
1930
+ });
1931
+ },
1932
+
1933
+ pluralize: function (count, word) {
1934
+ switch (count) {
1935
+ case 1:
1936
+ return word;
1937
+ default:
1938
+ return word + 's';
1939
+ }
1940
+ },
1941
+ });
1942
+
1943
+ const ShowView = L.Class.extend({
1944
+ options: {},
1945
+
1946
+ initialize: function (el, options) {
1947
+ var json = JSON.parse(el.dataset.features);
1948
+
1949
+ var map = L.map(el.id).setView([0, 0], 1);
1950
+ BlacklightHeatmaps.selectBasemap(
1951
+ el.dataset.basemapProvider
1952
+ ).addTo(map);
1953
+
1954
+ var features = L.geoJson(json, {
1955
+ pointToLayer: function(feature, latlng) {
1956
+ return L.marker(latlng, {
1957
+ icon: BlacklightHeatmaps.Icons.default
1958
+ })
1959
+ }
1960
+ }).addTo(map);
1961
+
1962
+ map.fitBounds(features.getBounds());
1963
+ },
1964
+ });
1965
+
1966
+ const BlacklightHeatmaps$1 = L$1.Class.extend({
1967
+ statics: {
1968
+ __version__: '0.0.3',
1969
+
1970
+ selectBasemap: function (basemap) {
1971
+ if (basemap && basemap !== undefined) {
1972
+ return BlacklightHeatmaps$1.Basemaps[basemap];
1973
+ } else {
1974
+ return BlacklightHeatmaps$1.Basemaps.positron;
1975
+ }
1976
+ },
1977
+ },
1978
+ });
1979
+
1980
+ BlacklightHeatmaps$1.Basemaps = Basemaps;
1981
+ BlacklightHeatmaps$1.Icons = Icons;
1982
+ BlacklightHeatmaps$1.IndexView = IndexView;
1983
+ BlacklightHeatmaps$1.indexView = function (el, options) {
1984
+ return new IndexView(el, options)
1985
+ };
1986
+ BlacklightHeatmaps$1.ShowView = ShowView;
1987
+ BlacklightHeatmaps$1.showView = function (el, options) {
1988
+ return new ShowView(el, options);
1989
+ };
1990
+
1991
+ BlacklightHeatmaps$1.init = function () {
1992
+ document.querySelectorAll('[data-index-map]').forEach(function (el) {
1993
+ BlacklightHeatmaps$1.indexView(el, {});
1994
+ });
1995
+ document.querySelectorAll('[data-show-map]').forEach(function (el) {
1996
+ BlacklightHeatmaps$1.showView(el);
1997
+ });
1998
+ };
1999
+
2000
+ export { BlacklightHeatmaps$1 as default };
2001
+ //# sourceMappingURL=default.esm.js.map