@raruto/leaflet-elevation 1.9.5 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.css CHANGED
@@ -28,7 +28,7 @@
28
28
  }
29
29
 
30
30
  .elevation-control.elevation .background {
31
- background-color: rgba(70, 130, 180, 0.2);
31
+ background-color: var(--ele-bg, rgba(70, 130, 180, 0.2));
32
32
  border-radius: 5px;
33
33
  overflow: visible;
34
34
  display: block;
@@ -36,15 +36,20 @@
36
36
  user-select: none;
37
37
  }
38
38
 
39
+ .elevation-control.elevation .axis .tick,
40
+ .elevation-control.elevation .axis .domain {
41
+ pointer-events: none;
42
+ }
43
+
39
44
  .elevation-control.elevation .axis line,
40
45
  .elevation-control.elevation .axis path {
41
- stroke: #2D1130;
46
+ stroke: var(--ele-axis, #2D1130);
42
47
  stroke-width: 1;
43
48
  fill: none;
44
49
  }
45
50
 
46
51
  .elevation-control.elevation .grid .tick line {
47
- stroke: #EEE;
52
+ stroke: var(--ele-grid, #EEE);
48
53
  stroke-width: 1px;
49
54
  shape-rendering: crispEdges;
50
55
  }
@@ -68,14 +73,14 @@
68
73
  }
69
74
 
70
75
  .elevation-control.elevation .area {
71
- fill: #4682B4;
72
- stroke: #000;
76
+ fill: var(--ele-area, #4682B4);
77
+ stroke: var(--ele-stroke, #000);
73
78
  stroke-width: 1.2;
74
79
  paint-order: stroke fill;
75
80
  }
76
81
 
77
82
  .elevation-detached .elevation-control.elevation .area {
78
- fill-opacity: 0.8;
83
+ fill-opacity: var(--ele-alpha, 0.8);
79
84
  }
80
85
 
81
86
  .elevation-control.elevation .horizontal-drag-line {
@@ -104,7 +109,7 @@
104
109
  }
105
110
 
106
111
  .elevation-control.elevation .mouse-focus-line {
107
- stroke: #0D1821;
112
+ stroke: #000;
108
113
  stroke-width: 1;
109
114
  pointer-events: none;
110
115
  }
@@ -128,7 +133,7 @@
128
133
  }
129
134
 
130
135
  .elevation-control.elevation .brush .selection {
131
- fill: rgba(23, 74, 117, 0.4);
136
+ fill: var(--ele-brush, rgba(23, 74, 117, 0.4));
132
137
  stroke: none;
133
138
  fill-opacity: unset;
134
139
  }
@@ -207,7 +212,7 @@
207
212
  }
208
213
 
209
214
  .elevation-control.elevation .elevation-toggle-icon {
210
- background: url(../images/elevation.svg) no-repeat center center;
215
+ background: var(--ele-icon, url(../images/elevation-lime.svg)) no-repeat center center;
211
216
  }
212
217
 
213
218
  .elevation-control.elevation.elevation-expanded .elevation-toggle-icon.close-button {
@@ -241,7 +246,7 @@
241
246
  .leaflet-elevation-pane .height-focus,
242
247
  .leaflet-overlay-pane .height-focus {
243
248
  stroke: #000;
244
- fill: #FFF;
249
+ fill: var(--ele-circle, var(--ele-area, #FFF));
245
250
  }
246
251
 
247
252
  .leaflet-elevation-pane .height-focus.line,
@@ -260,193 +265,79 @@
260
265
  stroke-width: 2px;
261
266
  }
262
267
 
263
- .elevation-waypoint-icon:before {
264
- background: url(../images/elevation-pushpin.svg) no-repeat center center / contain;
268
+ .elevation-waypoint-icon:before,
269
+ .elevation-position-icon:before {
265
270
  content: "";
266
271
  width: 100%;
267
272
  height: 100%;
268
273
  display: inline-block;
269
274
  }
270
275
 
276
+ .elevation-waypoint-icon:before {
277
+ background: url(../images/elevation-pushpin.svg) no-repeat center center / contain;
278
+ }
279
+
271
280
  .elevation-position-icon:before {
272
281
  background: url(../images/elevation-position.svg) no-repeat center center / contain;
273
- content: "";
274
- width: 100%;
275
- height: 100%;
276
- display: inline-block;
277
282
  }
278
283
 
279
284
  .elevation-polyline {
285
+ stroke: var(--ele-poly, var(--ele-area, #000));
280
286
  filter: drop-shadow(1px 1px 0 #FFF) drop-shadow(-1px -1px 0 #FFF) drop-shadow(1px -1px 0 #FFF) drop-shadow(-1px 1px 0 #FFF);
281
287
  }
282
288
 
283
- .elevation-placeholder {
284
- margin: auto;
285
- height: auto;
286
- width: 100%;
287
- }
288
-
289
- .elevation-placeholder~* {
290
- display: none !important;
291
- }
292
-
293
289
  /* LIME THEME //////////////////////////////////////////////// */
294
- .lime-theme.elevation-control.elevation .background {
295
- background-color: rgba(156, 194, 34, 0.2);
296
- }
297
-
298
- .lime-theme.elevation-control.elevation .axis line,
299
- .lime-theme.elevation-control.elevation .axis path {
300
- stroke: #566B13;
301
- }
302
-
303
- .lime-theme.elevation-control.elevation .grid .tick line {
304
- stroke: #CCC;
305
- }
306
-
307
- .lime-theme.elevation-control.elevation .brush .selection {
308
- fill: rgba(99, 126, 11, 0.4);
309
- }
310
-
311
- .lime-theme.elevation-control.elevation .elevation-toggle-icon {
312
- background: url(../images/elevation-lime.svg) no-repeat center center;
313
- }
314
-
315
- .lime-theme.elevation-control.elevation .area {
316
- fill: #9CC222;
317
- }
318
-
319
- .lime-theme.elevation-control.elevation .mouse-focus-line {
320
- stroke: #101404;
321
- }
322
-
323
- .lime-theme.height-focus {
324
- stroke: #000;
325
- fill: #9CC222;
326
- }
327
-
328
- .lime-theme.elevation-polyline {
329
- stroke: #566B13;
290
+ .lime-theme {
291
+ --ele-bg: rgba(156, 194, 34, 0.2);
292
+ --ele-axis: #566B13;
293
+ --ele-area: #9CC222;
294
+ --ele-grid: #CCC;
295
+ --ele-brush: rgba(99, 126, 11, 0.4);
296
+ --ele-icon: url(../images/elevation-lime.svg);
297
+ --ele-poly: #566B13;
330
298
  }
331
299
 
332
300
  /* STEELBLUE THEME //////////////////////////////////////////////// */
333
- .steelblue-theme.elevation-control.elevation .background {
334
- background-color: rgba(70, 130, 180, 0.2);
335
- }
336
-
337
- .steelblue-theme.elevation-control.elevation .axis line,
338
- .steelblue-theme.elevation-control.elevation .axis path {
339
- stroke: #0D1821;
340
- }
341
-
342
- .steelblue-theme.elevation-control.elevation .brush .selection {
343
- fill: rgba(23, 74, 117, 0.4);
344
- }
345
-
346
- .steelblue-theme.elevation-control.elevation .elevation-toggle-icon {
347
- background: url(../images/elevation-steelblue.svg) no-repeat center center;
348
- }
349
-
350
- .steelblue-theme.elevation-control.elevation .area {
351
- fill: #4682B4;
352
- }
353
-
354
- .steelblue-theme.elevation-control.elevation .mouse-focus-line {
355
- stroke: #0D1821;
356
- }
357
-
358
- .steelblue-theme.height-focus {
359
- stroke: #000;
360
- fill: #4682B4;
361
- }
362
-
363
- .steelblue-theme.elevation-polyline {
364
- stroke: #4682B4;
301
+ .steelblue-theme {
302
+ --ele-axis: #0D1821;
303
+ --ele-area: #4682B4;
304
+ --ele-brush: rgba(23, 74, 117, 0.4);
305
+ --ele-icon: url(../images/elevation-steelblue.svg);
365
306
  }
366
307
 
367
308
  /* PURPLE THEME //////////////////////////////////////////////// */
368
- .purple-theme.elevation-control.elevation .background {
369
- background-color: rgba(115, 44, 123, 0.2);
370
- }
371
-
372
- .purple-theme.elevation-control.elevation .axis line,
373
- .purple-theme.elevation-control.elevation .axis path {
374
- stroke: #2D1130;
375
- }
376
-
377
- .purple-theme.elevation-control.elevation .brush .selection {
378
- fill: rgba(74, 14, 80, 0.4);
379
- }
380
-
381
- .purple-theme.elevation-control.elevation .elevation-toggle-icon {
382
- background: url(../images/elevation-purple.svg) no-repeat center center;
383
- }
384
-
385
- .purple-theme.elevation-control.elevation .area {
386
- fill: #732C7B;
387
- }
388
-
389
- .purple-theme.elevation-control.elevation .mouse-focus-line {
390
- stroke: #000;
391
- }
392
-
393
- .purple-theme.height-focus {
394
- stroke: #000;
395
- fill: #732C7B;
396
- }
397
-
398
- .purple-theme.elevation-polyline {
399
- stroke: #732C7B;
309
+ .purple-theme {
310
+ --ele-bg: rgba(115, 44, 123, 0.2);
311
+ --ele-area: #732C7B;
312
+ --ele-brush: rgba(74, 14, 80, 0.4);
313
+ --ele-icon: url(../images/elevation-purple.svg);
400
314
  }
401
315
 
402
316
  /* YELLOW THEME //////////////////////////////////////////////// */
403
- .yellow-theme.elevation-control.elevation .area {
404
- fill: #FF0;
405
- }
406
-
407
- .yellow-theme.elevation-polyline {
408
- stroke: #FF0;
317
+ .yellow-theme {
318
+ --ele-area: #FF0;
409
319
  }
410
320
 
411
321
  /* RED THEME //////////////////////////////////////////////// */
412
- .red-theme.elevation-control.elevation .area {
413
- fill: #F00;
414
- }
415
-
416
- .red-theme.elevation-polyline {
417
- stroke: #F00;
322
+ .red-theme {
323
+ --ele-area: #F00;
418
324
  }
419
325
 
420
326
  /* MAGENTA THEME //////////////////////////////////////////////// */
421
- .magenta-theme.elevation-control.elevation .background {
422
- background-color: rgba(255, 255, 255, 0.47);
423
- }
424
-
425
- .magenta-theme.elevation-control.elevation .area {
426
- fill: #FF005E;
427
- }
428
-
429
- .magenta-theme.elevation-polyline {
430
- stroke: #FF005E;
327
+ .magenta-theme {
328
+ --ele-bg: rgba(255, 255, 255, 0.47);
329
+ --ele-area: #FF005E;
431
330
  }
432
331
 
433
332
  /* LIGHTBLUE THEME //////////////////////////////////////////////// */
434
- .lightblue-theme.elevation-control.elevation .area {
435
- fill: #3366CC;
436
- stroke: #000;
333
+ .lightblue-theme {
334
+ --ele-area: #3366CC;
335
+ --ele-alpha: 0.45;
336
+ --ele-stroke: #4682B4;
337
+ --ele-circle: #fff;
437
338
  }
438
339
 
439
340
  .elevation-detached .lightblue-theme.elevation-control.elevation .area {
440
- fill-opacity: 0.45;
441
- stroke: #3366CC;
442
- }
443
-
444
- .lightblue-theme.height-focus {
445
- stroke: #000;
446
- fill: #FFFFFF;
447
- }
448
-
449
- .lightblue-theme.elevation-polyline {
450
341
  stroke: #3366CC;
451
342
  }
452
343
 
package/src/index.js CHANGED
@@ -36,19 +36,9 @@
36
36
 
37
37
  import 'leaflet-i18n';
38
38
  import * as _ from './utils';
39
- import * as D3 from './components';
40
- import { Chart } from './chart';
41
39
  import { Elevation } from './control';
42
- import './distance';
43
- import './time';
44
- import './altitude';
45
- import './slope';
46
- import './speed';
47
- import './acceleration';
48
40
 
49
41
  Elevation.Utils = _;
50
- Elevation.Components = D3;
51
- Elevation.Chart = Chart;
52
42
 
53
43
  /* Temporary fix for empty values evaluated as false (leaflet-i18n v0.3.1) */
54
44
  (function(){
@@ -61,18 +51,4 @@ Elevation.Chart = Chart;
61
51
  };
62
52
  })();
63
53
 
64
- // Alias deprecated functions
65
- Elevation.addInitHook(function() {
66
- this.enableDragging = this.enableBrush;
67
- this.disableDragging = this.disableBrush;
68
- this.loadChart = this.addTo;
69
- this.loadData = this.load;
70
- this.loadGPX = this.load;
71
- this.loadGeoJSON = this.load;
72
- this.loadXML = this.load;
73
- this.loadFile = this.load;
74
- this._addGPXData = this._addGeoJSONData;
75
- this._registerFocusLabel = this._registerTooltip;
76
- });
77
-
78
54
  L.control.elevation = (options) => new Elevation(options);
package/src/options.js CHANGED
@@ -9,29 +9,14 @@ export var Options = {
9
9
  collapsed: false,
10
10
  detached: true,
11
11
  distance: true,
12
- distanceMarkers: {
13
- lazy: true,
14
- distance: true,
15
- direction: true
16
- },
17
- decimalsX: 2,
18
- decimalsY: 0,
12
+ distanceMarkers: { lazy: true, distance: true, direction: true },
19
13
  dragging: !L.Browser.mobile,
20
14
  downloadLink: 'link',
21
15
  elevationDiv: "#elevation-div",
22
16
  followMarker: true,
23
- forceAxisBounds: false,
24
- height: 200,
25
17
  imperial: false,
26
- interpolation: "curveLinear",
27
- lazyLoadJS: true,
28
18
  legend: true,
29
- margins: {
30
- top: 30,
31
- right: 30,
32
- bottom: 30,
33
- left: 40
34
- },
19
+ handlers: [],
35
20
  marker: 'elevation-line',
36
21
  markerIcon: L.divIcon({
37
22
  className: 'elevation-position-marker',
@@ -55,20 +40,15 @@ export var Options = {
55
40
  preferCanvas: false,
56
41
  reverseCoords: false,
57
42
  ruler: true,
58
- skipNullZCoords: false,
59
43
  theme: "lightblue-theme",
60
44
  summary: 'inline',
61
45
  slope: false,
62
- slopeDeltaMax: undefined,
63
- slopeRange: undefined,
64
46
  speed: false,
65
- speedDeltaMax: undefined,
66
- speedRange: undefined,
67
47
  time: false,
68
48
  timeFactor: 3600,
69
- timeFormat: false,
70
49
  timestamps: false,
71
- width: 600,
50
+ trkStart: L.circleMarker([0,0], { className: 'start-marker', radius: 6, weight: 2, color: '#fff', fillColor: '#00d800', fillOpacity: 1, interactive: false }),
51
+ trkEnd: L.circleMarker([0,0], { className: 'end-marker', radius: 6, weight: 2, color: '#fff', fillColor: '#ff0606', fillOpacity: 1, interactive: false }),
72
52
  waypoints: true,
73
53
  wptIcons: {
74
54
  '': L.divIcon({
@@ -81,12 +61,24 @@ export var Options = {
81
61
  wptLabels: true,
82
62
  xAttr: "dist",
83
63
  xLabel: "km",
84
- xTicks: undefined,
85
64
  yAttr: "z",
86
- yAxisMax: undefined,
87
- yAxisMin: undefined,
88
65
  yLabel: "m",
89
- yTicks: undefined,
90
66
  zFollow: false,
91
67
  zooming: !L.Browser.Mobile,
68
+
69
+ // Quite uncommon and undocumented options (quite useless)
70
+ decimalsX: 2,
71
+ decimalsY: 0,
72
+ forceAxisBounds: false,
73
+ interpolation: "curveLinear",
74
+ skipNullZCoords: false,
75
+ yAxisMax: undefined,
76
+ yAxisMin: undefined,
77
+
78
+ // Probably no longer functional as expected (internally overwritten)
79
+ margins: { top: 30, right: 30, bottom: 30, left: 40 },
80
+ height: 200,
81
+ width: 600,
82
+ xTicks: undefined,
83
+ yTicks: undefined,
92
84
  };
package/src/utils.js CHANGED
@@ -1,10 +1,23 @@
1
+ /**
2
+ * TODO: exget computed styles of theese values from actual "CSS vars"
3
+ **/
4
+ export const Colors = {
5
+ 'lightblue': { area: '#3366CC', alpha: 0.45, stroke: '#3366CC' },
6
+ 'magenta' : { area: '#FF005E' },
7
+ 'yellow' : { area: '#FF0' },
8
+ 'purple' : { area: '#732C7B' },
9
+ 'steelblue': { area: '#4682B4' },
10
+ 'red' : { area: '#F00' },
11
+ 'lime' : { area: '#9CC222', line: '#566B13' }
12
+ };
13
+
1
14
  const SEC = 1000;
2
15
  const MIN = SEC * 60;
3
16
  const HOUR = MIN * 60;
4
17
  const DAY = HOUR * 24;
5
18
 
6
19
  /**
7
- * Convert a duration time (millis) to a human readable string (%Dd %H:%M'%S")
20
+ * Convert a time (millis) to a human readable duration string (%Dd %H:%M'%S")
8
21
  */
9
22
  export function formatTime(t) {
10
23
  let d = Math.floor(t / DAY);
@@ -17,6 +30,20 @@ export function formatTime(t) {
17
30
  return (d ? d + "d " : '') + h.toString().padStart(2, 0) + ':' + m.toString().padStart(2, 0) + "'" + s.toString().padStart(2, 0) + '"';
18
31
  }
19
32
 
33
+ /**
34
+ * Convert a time (millis) to human readable date string (dd-mm-yyyy hh:mm:ss)
35
+ */
36
+ export function formatDate(format) {
37
+ if (!format) {
38
+ return (time) => (new Date(time)).toLocaleString().replaceAll('/', '-').replaceAll(',', ' ');
39
+ } else if (format == 'time') {
40
+ return (time) => (new Date(time)).toLocaleTimeString();
41
+ } else if (format == 'date') {
42
+ return (time) => (new Date(time)).toLocaleDateString();
43
+ }
44
+ return (time) => format(time);
45
+ }
46
+
20
47
  /**
21
48
  * Generate download data event.
22
49
  */
@@ -28,23 +55,6 @@ export function formatTime(t) {
28
55
  b.removeChild(a);
29
56
  }
30
57
 
31
- /**
32
- * Async JS script download.
33
- */
34
- export function lazyLoader(url, skip, loader) {
35
- if (skip === false) {
36
- return Promise.resolve();
37
- }
38
- if (loader instanceof Promise) {
39
- return loader;
40
- }
41
- return new Promise((resolve, reject) => {
42
- let tag = document.createElement("script");
43
- tag.addEventListener('load', resolve, { once: true });
44
- tag.src = url;
45
- document.head.appendChild(tag);
46
- });
47
- }
48
58
 
49
59
  /**
50
60
  * Convert SVG Path into Path2D and then update canvas
@@ -75,113 +85,75 @@ export function lazyLoader(url, skip, loader) {
75
85
  }
76
86
 
77
87
  /**
78
- * Limit a number between min / max values
79
- */
80
- export function clamp(val, range) {
81
- if (range) return val < range[0] ? range[0] : val > range[1] ? range[1] : val;
82
- return val;
83
- }
84
-
85
- /**
86
- * A little bit safier than L.DomUtil.addClass
88
+ * Loop and extract GPX Extensions handled by "@tmcw/toGeoJSON" (eg. "coordinateProperties" > "times")
87
89
  */
88
- export function addClass(targetNode, className) {
89
- if (targetNode) className.split(" ").every(s => s && L.DomUtil.addClass(targetNode, s));
90
- }
91
-
92
- /**
93
- * A little bit safier than L.DomUtil.removeClass()
94
- */
95
- export function removeClass(targetNode, className) {
96
- if (targetNode) className.split(" ").every(s => s && L.DomUtil.removeClass(targetNode, s));
97
- }
98
-
99
- export function toggleClass(targetNode, className, conditional) {
100
- return (conditional ? addClass : removeClass).call(null, targetNode, className)
101
- }
102
-
103
- export function replaceClass(targetNode, removeClassName, addClassName) {
104
- if (removeClassName) removeClass(targetNode, removeClassName);
105
- if (addClassName) addClass(targetNode, addClassName);
106
- }
107
-
108
- export function style(targetNode, name, value) {
109
- if (typeof value === "undefined") return L.DomUtil.getStyle(targetNode, name);
110
- else return targetNode.style.setProperty(name, value);
111
- }
112
-
113
- export function toggleStyle(targetNode, name, value, conditional) {
114
- return style(targetNode, name, conditional ? value : '');
115
- }
116
-
117
- export function toggleEvent(leafletElement, eventName, handler, conditional) {
118
- return leafletElement[conditional ? 'on' : 'off'](eventName, handler);
119
- }
120
-
121
- /**
122
- * A little bit shorter than L.DomUtil.create()
123
- */
124
- export function create(tagName, className, attributes, parent) {
125
- let elem = L.DomUtil.create(tagName, className || "");
126
- if (attributes) setAttributes(elem, attributes);
127
- if (parent) append(parent, elem);
128
- return elem;
90
+ export function coordPropsToMeta(coordProps, name, parser) {
91
+ return coordProps && (({props, point, id}) => {
92
+ if (props) {
93
+ for (const key of coordProps) {
94
+ if (key in props) {
95
+ point.meta[name] = (parser || parseInt).call(this, props[key], id);
96
+ break;
97
+ }
98
+ }
99
+ }
100
+ });
129
101
  }
130
102
 
131
103
  /**
132
- * Same as node.appendChild()
104
+ * Extract numeric property (id) from GeoJSON object
133
105
  */
134
- export function append(parent, child) {
135
- return parent.appendChild(child);
136
- }
106
+ export const parseInt = (property, id) => window.parseInt((typeof property === 'object' ? property[id] : property));
137
107
 
138
108
  /**
139
- * Same as node.insertAdjacentElement()
109
+ * Extract datetime property (id) from GeoJSON object
140
110
  */
141
- export function insert(parent, child, position) {
142
- return parent.insertAdjacentElement(position, child);
143
- }
111
+ export const parseDate = (property, id) => new Date(Date.parse((typeof property === 'object' ? property[id] : property)));
144
112
 
145
113
  /**
146
- * Loop for node.setAttribute()
114
+ * A little bit shorter than L.DomUtil
147
115
  */
148
- export function setAttributes(elem, attrs) {
149
- for (let k in attrs) { elem.setAttribute(k, attrs[k]); }
150
- }
116
+ export const addClass = (n, str) => n && str.split(" ").every(s => s && L.DomUtil.addClass(n, s));
117
+ export const removeClass = (n, str) => n && str.split(" ").every(s => s && L.DomUtil.removeClass(n, s));
118
+ export const toggleClass = (n, str, cond) => (cond ? addClass : removeClass)(n, str);
119
+ export const replaceClass = (n, rem, add) => (rem && removeClass(n, rem)) || (add && addClass(n, add));
120
+ export const style = (n, k, v) => (typeof v === "undefined" && L.DomUtil.getStyle(n, k)) || n.style.setProperty(k, v);
121
+ export const toggleStyle = (n, k, v, cond) => style(n, k, cond ? v : '');
122
+ export const setAttributes = (n, attrs) => { for (let k in attrs) { n.setAttribute(k, attrs[k]); } };
123
+ export const toggleEvent = (el, e, fn, cond) => el[cond ? 'on' : 'off'](e, fn);
124
+ export const create = (tag, str, attrs, n) => { let elem = L.DomUtil.create(tag, str || ""); if (attrs) setAttributes(elem, attrs); if (n) append(n, elem); return elem; };
125
+ export const append = (n, c) => n.appendChild(c);
126
+ export const insert = (n, c, pos) => n.insertAdjacentElement(pos, c);
127
+ export const select = (str, n) => (n || document).querySelector(str);
128
+ export const each = (obj, fn) => { for (let i in obj) fn(obj[i], i); };
129
+ export const randomId = () => Math.random().toString(36).substr(2, 9);
151
130
 
152
131
  /**
153
- * Same as node.querySelector().
132
+ * TODO: use generators instead? (ie. "yield")
154
133
  */
155
- export function select(selector, context) {
156
- return (context || document).querySelector(selector);
157
- }
134
+ export const iMax = (iVal, max) => (iVal > max ? iVal : max) || -Infinity;
135
+ export const iMin = (iVal, min) => (iVal < min ? iVal : min) || +Infinity;
136
+ export const iAvg = (iVal, avg) => (iVal + (avg || 0)) / 2.0;
137
+ export const iSum = (iVal, sum) => iVal + (sum || 0);
158
138
 
159
139
  /**
160
- * Alias for L.DomEvent.on.
140
+ * Alias for some leaflet core functions
161
141
  */
162
- export const on = L.DomEvent.on;
142
+ export const { on, off } = L.DomEvent;
143
+ export const { throttle } = L.Util;
144
+ export const { hasClass } = L.DomUtil;
163
145
 
164
146
  /**
165
- * Alias for L.DomEvent.off.
147
+ * Limit floating point precision
166
148
  */
167
- export const off = L.DomEvent.off;
149
+ export const round = L.Util.formatNum;
168
150
 
169
151
  /**
170
- * Alias for L.DomUtil.hasClass.
171
- */
172
- export const hasClass = L.DomUtil.hasClass;
173
-
174
-
175
- /**
176
- * Generate a random string
152
+ * Limit a number between min / max values
177
153
  */
178
- export function randomId() {
179
- return Math.random().toString(36).substr(2, 9);
180
- }
154
+ export const clamp = (val, range) => range ? (val < range[0] ? range[0] : val > range[1] ? range[1] : val) : val;
181
155
 
182
156
  /**
183
- * Execute a function foreach element in object
157
+ * Limit a delta difference between two values
184
158
  */
185
- export function each(obj, fn) {
186
- for (let i in obj) fn(obj[i], i);
187
- }
159
+ export const wrapDelta = (curr, prev, deltaMax) => Math.abs(curr - prev) > deltaMax ? prev + deltaMax * Math.sign(curr - prev) : curr;