@raruto/leaflet-elevation 1.9.2 → 1.9.5

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.
@@ -394,6 +394,7 @@
394
394
  _ref4$length = _ref4.length,
395
395
  length = _ref4$length === void 0 ? 0 : _ref4$length;
396
396
  return function (g) {
397
+ g.attr("class", "height-focus-group");
397
398
  var line = g.select('.height-focus.line');
398
399
  var circle = g.select('.height-focus.circle-lower');
399
400
  var text = g.select('.height-focus-label');
@@ -405,8 +406,10 @@
405
406
  line.attr("class", theme + " height-focus line").attr("x1", xCoord).attr("x2", xCoord).attr("y1", yCoord).attr("y2", length);
406
407
  text.attr("class", theme + " height-focus-label").style("pointer-events", "none").attr("x", xCoord + 5).attr("y", length);
407
408
  var label;
408
-
409
- for (var i in labels) {
409
+ Object.keys(labels).sort(function (a, b) {
410
+ return labels[a].order - labels[b].order;
411
+ }) // TODO: any performance issues?
412
+ .forEach(function (i) {
410
413
  label = text.select(".height-focus-" + labels[i].name);
411
414
 
412
415
  if (!label.size()) {
@@ -414,8 +417,7 @@
414
417
  }
415
418
 
416
419
  label.text(typeof labels[i].value !== "function" ? labels[i].value : labels[i].value(item));
417
- }
418
-
420
+ });
419
421
  text.select('tspan').attr("dy", text.selectAll('tspan').size() > 1 ? "-1.5em" : "0em");
420
422
  text.selectAll('tspan').attr("x", xCoord + 5);
421
423
  return g;
@@ -486,8 +488,10 @@
486
488
  rect.attr("class", "mouse-focus-label-rect").attr("x", xAlign - 5).attr("y", yAlign - 5).attr("width", bbox.width + 10).attr("height", bbox.height + 10).attr("rx", 3).attr("ry", 3);
487
489
  text.attr("class", "mouse-focus-label-text").style("font-weight", "700").attr("y", yAlign);
488
490
  var label;
489
-
490
- for (var i in labels) {
491
+ Object.keys(labels).sort(function (a, b) {
492
+ return labels[a].order - labels[b].order;
493
+ }) // TODO: any performance issues?
494
+ .forEach(function (i) {
491
495
  label = text.select(".mouse-focus-label-" + labels[i].name);
492
496
 
493
497
  if (!label.size()) {
@@ -495,8 +499,7 @@
495
499
  }
496
500
 
497
501
  label.text(typeof labels[i].value !== "function" ? labels[i].value : labels[i].value(item));
498
- }
499
-
502
+ });
500
503
  text.select('tspan').attr("dy", "1em");
501
504
  text.selectAll('tspan').attr("x", xAlign);
502
505
  return g;
@@ -1172,6 +1175,7 @@
1172
1175
  this._y = this._scales.altitude;
1173
1176
  },
1174
1177
  _registerAreaPath: function _registerAreaPath(props) {
1178
+ if (props.scale == 'y') props.scale = this._y;else if (props.scale == 'x') props.scale = this._x;
1175
1179
  var opts = this.options;
1176
1180
  if (!props.xAttr) props.xAttr = opts.xAttr;
1177
1181
  if (!props.yAttr) props.yAttr = opts.yAttr;
@@ -1191,9 +1195,11 @@
1191
1195
  }
1192
1196
  },
1193
1197
  _registerAxisGrid: function _registerAxisGrid(props) {
1198
+ if (props.scale == 'y') props.scale = this._y;else if (props.scale == 'x') props.scale = this._x;
1194
1199
  this._props.grids[props.name || props.axis] = props;
1195
1200
  },
1196
1201
  _registerAxisScale: function _registerAxisScale(props) {
1202
+ if (props.scale == 'y') props.scale = this._y;else if (props.scale == 'x') props.scale = this._x;
1197
1203
  var opts = this.options;
1198
1204
  var scale = props.scale;
1199
1205
 
@@ -1247,6 +1253,9 @@
1247
1253
  }));
1248
1254
  },
1249
1255
  _registerTooltip: function _registerTooltip(props) {
1256
+ var _props$order;
1257
+
1258
+ props.order = (_props$order = props.order) !== null && _props$order !== void 0 ? _props$order : 100;
1250
1259
  this._props.tooltipItems[props.name] = props;
1251
1260
  },
1252
1261
  _updateArea: function _updateArea() {
@@ -1557,7 +1566,6 @@
1557
1566
  switch (this.options.marker) {
1558
1567
  case 'elevation-line':
1559
1568
  // this._container = d3.create("g").attr("class", "height-focus-group");
1560
- this._container = d3.select(map.getPane('elevationPane')).select("svg > g").attr("class", "height-focus-group");
1561
1569
  break;
1562
1570
 
1563
1571
  case 'position-marker':
@@ -1578,8 +1586,7 @@
1578
1586
 
1579
1587
  switch (this.options.marker) {
1580
1588
  case 'elevation-line':
1581
- this._container.call(PositionMarker({}));
1582
-
1589
+ this._container = d3.select(map.getPane('elevationPane')).select("svg > g").call(PositionMarker({}));
1583
1590
  break;
1584
1591
 
1585
1592
  case 'position-marker':
@@ -1605,21 +1612,23 @@
1605
1612
 
1606
1613
  switch (this.options.marker) {
1607
1614
  case 'elevation-line':
1608
- var point = this._map.latLngToLayerPoint(this._latlng);
1615
+ if (this._container) {
1616
+ var point = this._map.latLngToLayerPoint(this._latlng);
1609
1617
 
1610
- point = L.extend({}, props.item, this._map._rotate ? this._map.rotatedPointToMapPanePoint(point) : point);
1618
+ point = L.extend({}, props.item, this._map._rotate ? this._map.rotatedPointToMapPanePoint(point) : point);
1611
1619
 
1612
- this._container.classed("leaflet-hidden", false);
1620
+ this._container.classed("leaflet-hidden", false);
1613
1621
 
1614
- this._container.call(PositionMarker({
1615
- theme: this.options.theme,
1616
- xCoord: point.x,
1617
- yCoord: point.y,
1618
- length: point.y - this._height() / props.maxElevation * point.z,
1619
- // normalized Y
1620
- labels: this._labels,
1621
- item: point
1622
- }));
1622
+ this._container.call(PositionMarker({
1623
+ theme: this.options.theme,
1624
+ xCoord: point.x,
1625
+ yCoord: point.y,
1626
+ length: point.y - this._height() / props.maxElevation * point.z,
1627
+ // normalized Y
1628
+ labels: this._labels,
1629
+ item: point
1630
+ }));
1631
+ }
1623
1632
 
1624
1633
  break;
1625
1634
 
@@ -1669,6 +1678,7 @@
1669
1678
  initialize: function initialize(opts, control) {
1670
1679
  this.options = opts;
1671
1680
  this.control = control;
1681
+ this.labels = {};
1672
1682
 
1673
1683
  var summary = this._container = create("div", "elevation-summary " + (opts.summary ? opts.summary + "-summary" : ''));
1674
1684
 
@@ -1690,9 +1700,22 @@
1690
1700
  this._container.innerHTML += "<span class=\"".concat(className, "\"><span class=\"summarylabel\">").concat(label, "</span><span class=\"summaryvalue\">").concat(value, "</span></span>");
1691
1701
  return this;
1692
1702
  },
1703
+ update: function update() {
1704
+ var _this2 = this;
1705
+
1706
+ Object.keys(this.labels).sort(function (a, b) {
1707
+ return _this2.labels[a].order - _this2.labels[b].order;
1708
+ }) // TODO: any performance issues?
1709
+ .forEach(function (i) {
1710
+ _this2.append(i, L._(_this2.labels[i].label), typeof _this2.labels[i].value !== "function" ? _this2.labels[i].value : _this2.labels[i].value(_this2.control.track_info));
1711
+ });
1712
+ },
1693
1713
  _registerSummary: function _registerSummary(data) {
1694
1714
  for (var i in data) {
1695
- this.append(i, L._(data[i].label), typeof data[i].value !== "function" ? data[i].value : data[i].value(this.control.track_info));
1715
+ var _data$i$order;
1716
+
1717
+ data[i].order = (_data$i$order = data[i].order) !== null && _data$i$order !== void 0 ? _data$i$order : 100;
1718
+ this.labels[i] = data[i];
1696
1719
  }
1697
1720
  }
1698
1721
  });
@@ -1706,7 +1729,11 @@
1706
1729
  collapsed: false,
1707
1730
  detached: true,
1708
1731
  distance: true,
1709
- distanceMarkers: false,
1732
+ distanceMarkers: {
1733
+ lazy: true,
1734
+ distance: true,
1735
+ direction: true
1736
+ },
1710
1737
  decimalsX: 2,
1711
1738
  decimalsY: 0,
1712
1739
  dragging: !L.Browser.mobile,
@@ -1752,15 +1779,15 @@
1752
1779
  theme: "lightblue-theme",
1753
1780
  summary: 'inline',
1754
1781
  slope: false,
1782
+ slopeDeltaMax: undefined,
1783
+ slopeRange: undefined,
1755
1784
  speed: false,
1756
- sLimit: undefined,
1785
+ speedDeltaMax: undefined,
1786
+ speedRange: undefined,
1757
1787
  time: false,
1758
1788
  timeFactor: 3600,
1759
1789
  timeFormat: false,
1760
1790
  timestamps: false,
1761
- sDeltaMax: undefined,
1762
- sInterpolation: "curveStepAfter",
1763
- sRange: undefined,
1764
1791
  width: 600,
1765
1792
  waypoints: true,
1766
1793
  wptIcons: {
@@ -1793,7 +1820,7 @@
1793
1820
  __TOGEOJSON: 'https://unpkg.com/@tmcw/togeojson@4.5.0/dist/togeojson.umd.js',
1794
1821
  __LGEOMUTIL: 'https://unpkg.com/leaflet-geometryutil@0.9.3/src/leaflet.geometryutil.js',
1795
1822
  __LALMOSTOVER: 'https://unpkg.com/leaflet-almostover@1.0.1/src/leaflet.almostover.js',
1796
- __LDISTANCEM: 'https://unpkg.com/@raruto/leaflet-elevation@1.9.2/libs/leaflet-distance-marker.min.js',
1823
+ __LDISTANCEM: 'https://unpkg.com/@raruto/leaflet-elevation@1.9.5/libs/leaflet-distance-marker.min.js',
1797
1824
 
1798
1825
  /*
1799
1826
  * Add data to the diagram either from GPX or GeoJSON and update the axis domain and data
@@ -1884,6 +1911,22 @@
1884
1911
  }
1885
1912
  },
1886
1913
 
1914
+ /**
1915
+ * TODO: Create a base class to handle custom data attributes (heart rate, cadence, temperature, ...)
1916
+ *
1917
+ * @link https://leafletjs.com/examples/extending/extending-3-controls.html#handlers
1918
+ */
1919
+ // addHandler: function (name, HandlerClass) {
1920
+ // if (HandlerClass) {
1921
+ // let handler = this[name] = new HandlerClass(this);
1922
+ // this.handlers.push(handler);
1923
+ // if (this.options[name]) {
1924
+ // handler.enable();
1925
+ // }
1926
+ // }
1927
+ // return this;
1928
+ // },
1929
+
1887
1930
  /**
1888
1931
  * Disable chart brushing.
1889
1932
  */
@@ -1931,7 +1974,7 @@
1931
1974
  },
1932
1975
 
1933
1976
  /**
1934
- * Get default zoom level when "followMarker" is true.
1977
+ * Get default zoom level (followMarker: true).
1935
1978
  */
1936
1979
  getZFollow: function getZFollow() {
1937
1980
  return this.options.zFollow;
@@ -1953,14 +1996,13 @@
1953
1996
  this._markers = L.featureGroup();
1954
1997
  this._markedSegments = L.polyline([]);
1955
1998
  this._chartEnabled = true, this.track_info = {};
1999
+ this.handlers = [];
1956
2000
  L.setOptions(this, options);
1957
2001
  if (this.options.followMarker) this._setMapView = L.Util.throttle(this._setMapView, 300, this);
1958
2002
  if (this.options.legend) this.options.margins.bottom += 30;
1959
2003
  if (this.options.theme) this.options.polylineSegments.className += ' ' + this.options.theme;
1960
2004
  if (this.options.wptIcons === true) this.options.wptIcons = Options.wptIcons;
1961
- if (this.options.distanceMarkers === true) this.options.distanceMarkers = {
1962
- lazy: true
1963
- };
2005
+ if (this.options.distanceMarkers === true) this.options.distanceMarkers = Options.distanceMarkers;
1964
2006
 
1965
2007
  this._markedSegments.setStyle(this.options.polylineSegments); // Leaflet canvas renderer colors
1966
2008
 
@@ -2014,7 +2056,7 @@
2014
2056
  },
2015
2057
 
2016
2058
  /**
2017
- * Load elevation data (GPX, GeoJSON or KML).
2059
+ * Load elevation data (GPX, GeoJSON, KML or TCX).
2018
2060
  */
2019
2061
  load: function load(data) {
2020
2062
  var _this3 = this;
@@ -2088,7 +2130,7 @@
2088
2130
  },
2089
2131
 
2090
2132
  /**
2091
- * Set default zoom level when "followMarker" is true.
2133
+ * Set default zoom level (followMarker: true).
2092
2134
  */
2093
2135
  setZFollow: function setZFollow(zoom) {
2094
2136
  this.options.zFollow = zoom;
@@ -2167,26 +2209,24 @@
2167
2209
  hr: null,
2168
2210
  cad: null,
2169
2211
  atemp: null
2170
- }; // "alt" property is generated inside "leaflet"
2171
-
2172
- if ("alt" in point) point.meta.ele = point.alt; // "coordinateProperties" property is generated inside "@tmcw/toGeoJSON"
2212
+ }; // "coordinateProperties" property is generated inside "@tmcw/toGeoJSON"
2173
2213
 
2174
2214
  var props = properties && properties.coordinateProperties || properties;
2175
2215
 
2176
- if (props) {
2177
- if ("coordTimes" in props) point.meta.time = new Date(Date.parse(props.coordTimes[i]));else if ("times" in props) point.meta.time = new Date(Date.parse(props.times[i]));else if ("time" in props) point.meta.time = new Date(Date.parse(_typeof(props.time) === 'object' ? props.time[i] : props.time));
2178
- if ("heartRates" in props) point.meta.hr = parseInt(props.heartRates[i]);else if ("heartRate" in props) point.meta.hr = parseInt(_typeof(props.heartRate) === 'object' ? props.heartRate[i] : props.heartRate);else if ("heart" in props) point.meta.hr = parseInt(_typeof(props.heart) === 'object' ? props.heart[i] : props.heart); // TODO: ask to "@tmcw/toGeoJSON" for "cadence" and "temperature" implementation
2179
- }
2216
+ _this6.fire("elepoint_init", {
2217
+ point: point,
2218
+ props: props,
2219
+ id: i
2220
+ });
2180
2221
 
2181
2222
  _this6._addPoint((_point$lat = point.lat) !== null && _point$lat !== void 0 ? _point$lat : point[1], (_point$lng = point.lng) !== null && _point$lng !== void 0 ? _point$lng : point[0], (_ref = (_point$alt = point.alt) !== null && _point$alt !== void 0 ? _point$alt : point.meta.ele) !== null && _ref !== void 0 ? _ref : point[2]);
2182
2223
 
2183
- _this6._fireEvt("elepoint_added", {
2224
+ _this6.fire("elepoint_added", {
2184
2225
  point: point,
2185
2226
  index: _this6._data.length - 1
2186
2227
  });
2187
2228
  });
2188
-
2189
- this._fireEvt("eletrack_added", {
2229
+ this.fire("eletrack_added", {
2190
2230
  coords: coords,
2191
2231
  index: this._data.length - 1
2192
2232
  });
@@ -2209,7 +2249,7 @@
2209
2249
  latlng: L.latLng(x, y, z)
2210
2250
  });
2211
2251
 
2212
- this._fireEvt("eledata_updated", {
2252
+ this.fire("eledata_updated", {
2213
2253
  index: this._data.length - 1
2214
2254
  });
2215
2255
  },
@@ -2418,7 +2458,7 @@
2418
2458
  },
2419
2459
 
2420
2460
  /**
2421
- * Generate "svg" chart DOM element.
2461
+ * Generate "svg" chart (DOM element).
2422
2462
  */
2423
2463
  _initChart: function _initChart(container) {
2424
2464
  var opts = this.options;
@@ -2444,13 +2484,10 @@
2444
2484
  this._x = this._chart._x;
2445
2485
  this._y = this._chart._y;
2446
2486
  d3.select(container).call(chart.render());
2447
- chart.on('reset_drag', this._hideMarker, this).on('mouse_enter', this._fireEvt.bind('elechart_enter'), this).on('dragged', this._dragendHandler, this).on('mouse_move', this._mousemoveHandler, this).on('mouse_out', this._mouseoutHandler, this).on('ruler_filter', this._rulerFilterHandler, this).on('zoom', this._updateChart, this).on('elepath_toggle', this._toggleChartHandler, this).on('margins_updated', this._resizeChart, this);
2448
-
2449
- this._fireEvt("elechart_axis");
2450
-
2451
- if (this.options.legend) this._fireEvt("elechart_legend");
2452
-
2453
- this._fireEvt("elechart_init");
2487
+ chart.on('reset_drag', this._hideMarker, this).on('mouse_enter', this._mouseenterHandler, this).on('dragged', this._dragendHandler, this).on('mouse_move', this._mousemoveHandler, this).on('mouse_out', this._mouseoutHandler, this).on('ruler_filter', this._rulerFilterHandler, this).on('zoom', this._updateChart, this).on('elepath_toggle', this._toggleChartHandler, this).on('margins_updated', this._resizeChart, this);
2488
+ this.fire("elechart_axis");
2489
+ if (this.options.legend) this.fire("elechart_legend");
2490
+ this.fire("elechart_init");
2454
2491
  },
2455
2492
  _initLayer: function _initLayer() {
2456
2493
  var _this10 = this;
@@ -2482,8 +2519,7 @@
2482
2519
  }).addTo(this._map); // default leaflet svg renderer
2483
2520
 
2484
2521
  this._marker = new Marker(this.options);
2485
-
2486
- this._fireEvt("elechart_marker");
2522
+ this.fire("elechart_marker");
2487
2523
  },
2488
2524
 
2489
2525
  /**
@@ -2647,8 +2683,14 @@
2647
2683
  this._hideMarker();
2648
2684
 
2649
2685
  this.fitBounds(L.latLngBounds([e.dragstart.latlng, e.dragend.latlng]));
2686
+ this.fire("elechart_dragged");
2687
+ },
2650
2688
 
2651
- this._fireEvt("elechart_dragged");
2689
+ /**
2690
+ * Trigger mouseenter event
2691
+ */
2692
+ _mouseenterHandler: function _mouseenterHandler(e) {
2693
+ this.fire('elechart_enter');
2652
2694
  },
2653
2695
 
2654
2696
  /*
@@ -2673,12 +2715,11 @@
2673
2715
  addClass(this._map.getContainer(), 'elechart-hover');
2674
2716
  }
2675
2717
 
2676
- this._fireEvt("elechart_change", {
2718
+ this.fire("elechart_change", {
2677
2719
  data: item,
2678
2720
  xCoord: xCoord
2679
2721
  });
2680
-
2681
- this._fireEvt("elechart_hover", {
2722
+ this.fire("elechart_hover", {
2682
2723
  data: item,
2683
2724
  xCoord: xCoord
2684
2725
  });
@@ -2701,7 +2742,7 @@
2701
2742
 
2702
2743
  this._updateMarker(item);
2703
2744
 
2704
- this._fireEvt("elechart_change", {
2745
+ this.fire("elechart_change", {
2705
2746
  data: item,
2706
2747
  xCoord: xCoord
2707
2748
  });
@@ -2722,7 +2763,7 @@
2722
2763
  removeClass(this._map.getContainer(), 'elechart-hover');
2723
2764
  }
2724
2765
 
2725
- this._fireEvt("elechart_leave");
2766
+ this.fire("elechart_leave");
2726
2767
  },
2727
2768
 
2728
2769
  /**
@@ -2828,46 +2869,97 @@
2828
2869
  },
2829
2870
 
2830
2871
  /**
2831
- * Add a point of interest over the diagram
2872
+ * Add chart profile to diagram
2832
2873
  */
2833
- _registerCheckPoint: function _registerCheckPoint(props) {
2874
+ _registerAreaPath: function _registerAreaPath(props) {
2834
2875
  var _this13 = this;
2835
2876
 
2836
- this.on("elechart_updated", function () {
2837
- return _this13._chart._registerCheckPoint(props);
2877
+ this.on("elechart_init", function () {
2878
+ return _this13._chart._registerAreaPath(props);
2838
2879
  });
2839
2880
  },
2840
2881
 
2841
2882
  /**
2842
- * Add chart profile to diagram
2883
+ * Add chart grid to diagram
2843
2884
  */
2844
- _registerAreaPath: function _registerAreaPath(props) {
2885
+ _registerAxisGrid: function _registerAxisGrid(props) {
2845
2886
  var _this14 = this;
2846
2887
 
2847
- this.on("elechart_init", function () {
2848
- return _this14._chart._registerAreaPath(props);
2888
+ this.on("elechart_axis", function () {
2889
+ return _this14._chart._registerAxisGrid(props);
2849
2890
  });
2850
2891
  },
2851
2892
 
2852
2893
  /**
2853
- * Add chart grid to diagram
2894
+ * Add chart axis to diagram
2854
2895
  */
2855
- _registerAxisGrid: function _registerAxisGrid(props) {
2896
+ _registerAxisScale: function _registerAxisScale(props) {
2856
2897
  var _this15 = this;
2857
2898
 
2858
2899
  this.on("elechart_axis", function () {
2859
- return _this15._chart._registerAxisGrid(props);
2900
+ return _this15._chart._registerAxisScale(props);
2860
2901
  });
2861
2902
  },
2862
2903
 
2863
2904
  /**
2864
- * Add chart axis to diagram
2905
+ * Add a point of interest over the diagram
2865
2906
  */
2866
- _registerAxisScale: function _registerAxisScale(props) {
2907
+ _registerCheckPoint: function _registerCheckPoint(props) {
2867
2908
  var _this16 = this;
2868
2909
 
2869
- this.on("elechart_axis", function () {
2870
- return _this16._chart._registerAxisScale(props);
2910
+ this.on("elechart_updated", function () {
2911
+ return _this16._chart._registerCheckPoint(props);
2912
+ });
2913
+ },
2914
+
2915
+ /**
2916
+ * Base handler for iterative track statistics (dist, time, z, slope, speed, acceleration, ...)
2917
+ */
2918
+ _registerDataAttribute: function _registerDataAttribute(props) {
2919
+ var _this17 = this;
2920
+
2921
+ // save here a reference to last used point
2922
+ var lastValid = null; // parse of "coordinateProperties" for later usage
2923
+
2924
+ if (props.init) {
2925
+ this.on("elepoint_init", function (e) {
2926
+ return props.init.call(_this17, e);
2927
+ });
2928
+ } // iteration
2929
+
2930
+
2931
+ this.on("elepoint_added", function (e) {
2932
+ // check and fix missing data on last added point
2933
+ if (props.skipNull === false) {
2934
+ var curr = _this17._data[e.index][props.name];
2935
+
2936
+ if (e.index > 0) {
2937
+ var prev = _this17._data[e.index - 1][props.name];
2938
+
2939
+ if (isNaN(prev)) {
2940
+ if (!isNaN(lastValid) && !isNaN(curr)) {
2941
+ prev = (lastValid + curr) / 2;
2942
+ } else if (!isNaN(lastValid)) {
2943
+ prev = lastValid;
2944
+ } else if (!isNaN(curr)) {
2945
+ prev = curr;
2946
+ }
2947
+
2948
+ if (!isNaN(prev)) return _this17._data.splice(e.index - 1, 1);
2949
+ _this17._data[e.index - 1][props.name] = prev;
2950
+ }
2951
+ } // update reference to last used point (ie. if it has data)
2952
+
2953
+
2954
+ if (!isNaN(curr)) {
2955
+ lastValid = curr;
2956
+ }
2957
+ } // retrieve point value
2958
+
2959
+
2960
+ _this17._data[e.index][props.name] = props.fetch.call(_this17, e.index, e.point); // update here some mixins (eg. "track_info", value validators, ...)
2961
+
2962
+ if (props.update) _this17._data[e.index][props.name] = props.update.call(_this17, _this17._data[e.index][props.name], e.index, e.point);
2871
2963
  });
2872
2964
  },
2873
2965
 
@@ -2875,14 +2967,14 @@
2875
2967
  * Add chart or marker tooltip info
2876
2968
  */
2877
2969
  _registerTooltip: function _registerTooltip(props) {
2878
- var _this17 = this;
2970
+ var _this18 = this;
2879
2971
 
2880
2972
  if (props.chart) {
2881
2973
  var label = L.extend({}, props, {
2882
2974
  value: props.chart
2883
2975
  });
2884
2976
  this.on("elechart_init", function () {
2885
- return _this17._chart._registerTooltip(label);
2977
+ return _this18._chart._registerTooltip(label);
2886
2978
  });
2887
2979
  }
2888
2980
 
@@ -2892,7 +2984,7 @@
2892
2984
  });
2893
2985
 
2894
2986
  this.on("elechart_marker", function () {
2895
- return _this17._marker._registerTooltip(_label);
2987
+ return _this18._marker._registerTooltip(_label);
2896
2988
  });
2897
2989
  }
2898
2990
  },
@@ -2901,10 +2993,10 @@
2901
2993
  * Add summary info to diagram
2902
2994
  */
2903
2995
  _registerSummary: function _registerSummary(props) {
2904
- var _this18 = this;
2996
+ var _this19 = this;
2905
2997
 
2906
2998
  this.on('elechart_summary', function () {
2907
- return _this18._summary._registerSummary(props);
2999
+ return _this19._summary._registerSummary(props);
2908
3000
  });
2909
3001
  },
2910
3002
 
@@ -2976,14 +3068,14 @@
2976
3068
  },
2977
3069
 
2978
3070
  /**
2979
- * Collapse or Expand current chart control.
3071
+ * Collapse or Expand chart control.
2980
3072
  */
2981
3073
  _toggle: function _toggle() {
2982
3074
  if (hasClass(this._container, "elevation-expanded")) this._collapse();else this._expand();
2983
3075
  },
2984
3076
 
2985
3077
  /**
2986
- * Sets the view of the map (center and zoom). Useful when "followMarker" is true.
3078
+ * Update map center and zoom (followMarker: true)
2987
3079
  */
2988
3080
  _setMapView: function _setMapView(item) {
2989
3081
  if (!this.options.followMarker || !this._map) return;
@@ -3009,14 +3101,14 @@
3009
3101
  * Toggle chart data on legend click
3010
3102
  */
3011
3103
  _toggleChartHandler: function _toggleChartHandler(e) {
3012
- var _this19 = this;
3104
+ var _this20 = this;
3013
3105
 
3014
3106
  var name = e.name,
3015
3107
  enabled = e.enabled;
3016
3108
  this._chartEnabled = this._chart._hasActiveLayers(); // toggle layer visibility on empty chart
3017
3109
 
3018
3110
  this._layers.eachLayer(function (layer) {
3019
- return toggleClass(layer.getElement && layer.getElement(), _this19.options.polyline.className + ' ' + _this19.options.theme, _this19._chartEnabled);
3111
+ return toggleClass(layer.getElement && layer.getElement(), _this20.options.polyline.className + ' ' + _this20.options.theme, _this20._chartEnabled);
3020
3112
  }); // toggle option value (eg. altitude = { 'disabled' || 'disabled' })
3021
3113
 
3022
3114
 
@@ -3036,10 +3128,8 @@
3036
3128
  if (
3037
3129
  /*!this._data.length ||*/
3038
3130
  !this._chart || !this._container) return;
3039
-
3040
- this._fireEvt("elechart_axis");
3041
-
3042
- this._fireEvt("elechart_area");
3131
+ this.fire("elechart_axis");
3132
+ this.fire("elechart_area");
3043
3133
 
3044
3134
  this._chart.update({
3045
3135
  data: this._data,
@@ -3048,8 +3138,7 @@
3048
3138
 
3049
3139
  this._x = this._chart._x;
3050
3140
  this._y = this._chart._y;
3051
-
3052
- this._fireEvt('elechart_updated');
3141
+ this.fire('elechart_updated');
3053
3142
  },
3054
3143
 
3055
3144
  /*
@@ -3090,12 +3179,14 @@
3090
3179
  * Update chart summary.
3091
3180
  */
3092
3181
  _updateSummary: function _updateSummary() {
3093
- var _this20 = this;
3182
+ var _this21 = this;
3094
3183
 
3095
3184
  this._summary.reset();
3096
3185
 
3097
3186
  if (this.options.summary) {
3098
- this._fireEvt("elechart_summary");
3187
+ this.fire("elechart_summary");
3188
+
3189
+ this._summary.update();
3099
3190
  }
3100
3191
 
3101
3192
  if (this.options.downloadLink && this._downloadURL) {
@@ -3105,19 +3196,19 @@
3105
3196
  select('.download a', this._summary._container).onclick = function (e) {
3106
3197
  e.preventDefault();
3107
3198
  var event = {
3108
- downloadLink: _this20.options.downloadLink,
3109
- confirm: saveFile.bind(_this20, _this20._downloadURL)
3199
+ downloadLink: _this21.options.downloadLink,
3200
+ confirm: saveFile.bind(_this21, _this21._downloadURL)
3110
3201
  };
3111
3202
 
3112
- if (_this20.options.downloadLink == 'modal' && typeof CustomEvent === "function") {
3203
+ if (_this21.options.downloadLink == 'modal' && typeof CustomEvent === "function") {
3113
3204
  document.dispatchEvent(new CustomEvent("eletrack_download", {
3114
3205
  detail: event
3115
3206
  }));
3116
- } else if (_this20.options.downloadLink == 'link' || _this20.options.downloadLink === true) {
3207
+ } else if (_this21.options.downloadLink == 'link' || _this21.options.downloadLink === true) {
3117
3208
  event.confirm();
3118
3209
  }
3119
3210
 
3120
- _this20._fireEvt('eletrack_download', event);
3211
+ _this21.fire('eletrack_download', event);
3121
3212
  };
3122
3213
  }
3123
3214
  },
@@ -3149,119 +3240,8 @@
3149
3240
  });
3150
3241
 
3151
3242
  Elevation.addInitHook(function () {
3152
- var opts = this.options;
3153
- var altitude = {};
3154
-
3155
- if (opts.imperial) {
3156
- opts.altitudeFactor = this.__footFactor;
3157
- altitude.label = "ft";
3158
- } else {
3159
- opts.altitudeFactor = opts.heightFactor || opts.altitudeFactor || 1;
3160
- altitude.label = opts.yLabel;
3161
- }
3162
-
3163
- this.on("eledata_updated", function (e) {
3164
- var data = this._data;
3165
- var i = e.index;
3166
- var z = data[i].z * opts.altitudeFactor;
3167
- var track = this.track_info;
3168
- var zMax = track.elevation_max || -Infinity;
3169
- var zMin = track.elevation_min || +Infinity; // check and fix missing elevation data on last added point
3170
-
3171
- if (!this.options.skipNullZCoords && i > 0) {
3172
- var prevZ = data[i - 1].z;
3173
-
3174
- if (isNaN(prevZ)) {
3175
- var lastZ = this._lastValidZ;
3176
- var currZ = z;
3177
-
3178
- if (!isNaN(lastZ) && !isNaN(currZ)) {
3179
- prevZ = (lastZ + currZ) / 2;
3180
- } else if (!isNaN(lastZ)) {
3181
- prevZ = lastZ;
3182
- } else if (!isNaN(currZ)) {
3183
- prevZ = currZ;
3184
- }
3185
-
3186
- if (!isNaN(prevZ)) return data.splice(i - 1, 1);
3187
- data[i - 1].z = prevZ;
3188
- }
3189
- } // skip point if it has not elevation
3190
-
3191
-
3192
- if (!isNaN(z)) {
3193
- this._lastValidZ = z;
3194
- }
3195
-
3196
- track.elevation_max = z > zMax ? z : zMax;
3197
- track.elevation_min = z < zMin ? z : zMin;
3198
- data[i].z = z;
3199
- });
3200
- this.on("elechart_axis", function () {
3201
- this._chart._registerAxisGrid({
3202
- axis: "y",
3203
- position: "left",
3204
- scale: this._chart._y
3205
- });
3206
- });
3207
-
3208
- if (this.options.altitude != "summary") {
3209
- this.on("elechart_axis", function () {
3210
- this._chart._registerAxisScale({
3211
- axis: "y",
3212
- position: "left",
3213
- scale: this._chart._y,
3214
- label: altitude.label,
3215
- labelX: -3,
3216
- labelY: -8,
3217
- name: "altitude"
3218
- });
3219
- });
3220
- this.on("elechart_init", function () {
3221
- var theme = this.options.theme.replace('-theme', '');
3222
- var color = Colors[theme] || {};
3223
-
3224
- this._chart._registerAreaPath({
3225
- name: 'altitude',
3226
- label: 'Altitude',
3227
- scaleX: 'distance',
3228
- scaleY: 'altitude',
3229
- color: color.area || theme,
3230
- strokeColor: this.options.detached ? color.stroke : '#000',
3231
- strokeOpacity: "1",
3232
- fillOpacity: this.options.detached ? color.alpha || '0.8' : 1,
3233
- preferCanvas: this.options.preferCanvas
3234
- });
3235
- });
3236
- }
3237
-
3238
- this._registerTooltip({
3239
- name: 'y',
3240
- chart: function chart(item) {
3241
- return L._("y: ") + d3.format("." + opts.decimalsY + "f")(item[opts.yAttr]) + " " + altitude.label;
3242
- },
3243
- marker: function marker(item) {
3244
- return d3.format("." + opts.decimalsY + "f")(item[opts.yAttr]) + " " + altitude.label;
3245
- }
3246
- });
3247
-
3248
- this._registerSummary({
3249
- "maxele": {
3250
- label: "Max Elevation: ",
3251
- value: function value(track) {
3252
- return (track.elevation_max || 0).toFixed(2) + '&nbsp;' + altitude.label;
3253
- }
3254
- },
3255
- "minele": {
3256
- label: "Min Elevation: ",
3257
- value: function value(track) {
3258
- return (track.elevation_min || 0).toFixed(2) + '&nbsp;' + altitude.label;
3259
- }
3260
- }
3261
- });
3262
- });
3243
+ var _this = this;
3263
3244
 
3264
- Elevation.addInitHook(function () {
3265
3245
  var opts = this.options;
3266
3246
  var distance = {};
3267
3247
 
@@ -3273,50 +3253,49 @@
3273
3253
  distance.label = opts.xLabel;
3274
3254
  }
3275
3255
 
3276
- this.on("eledata_updated", function (e) {
3277
- var data = this._data;
3278
- var i = e.index;
3279
- var track = this.track_info;
3280
- var dist = track.distance || 0;
3281
- var curr = data[i].latlng;
3282
- var prev = i > 0 ? data[i - 1].latlng : curr;
3283
- var delta = curr.distanceTo(prev) * opts.distanceFactor;
3284
- dist += Math.round(delta / 1000 * 100000) / 100000; // handles floating points calc
3285
-
3286
- track.distance = dist;
3287
- data[i].dist = dist;
3288
- });
3289
- this.on("elechart_axis", function () {
3290
- this._chart._registerAxisGrid({
3291
- axis: "x",
3292
- position: "bottom",
3293
- scale: this._chart._x
3294
- });
3256
+ this._registerDataAttribute({
3257
+ name: 'dist',
3258
+ init: function init() {// this.track_info.distance = 0;
3259
+ },
3260
+ fetch: function fetch(i) {
3261
+ var delta = _this._data[i].latlng.distanceTo(_this._data[i > 0 ? i - 1 : i].latlng) * opts.distanceFactor;
3262
+ return Math.round(delta / 1000 * 100000) / 100000; // handles floating points calc
3263
+ },
3264
+ update: function update(distance) {
3265
+ _this.track_info.distance = _this.track_info.distance || 0;
3266
+ _this.track_info.distance += distance;
3267
+ return _this.track_info.distance;
3268
+ }
3295
3269
  });
3296
3270
 
3297
3271
  if (this.options.distance != "summary") {
3298
- this.on("elechart_axis", function () {
3299
- var _this = this;
3300
-
3301
- this._chart._registerAxisScale({
3302
- axis: "x",
3303
- position: "bottom",
3304
- scale: this._chart._x,
3305
- label: distance.label,
3306
- labelY: 25,
3307
- labelX: function labelX() {
3308
- return _this._width() + 6;
3309
- },
3310
- name: "distance"
3311
- });
3272
+ this._registerAxisScale({
3273
+ axis: "x",
3274
+ position: "bottom",
3275
+ scale: "x",
3276
+ // this._chart._x,
3277
+ label: distance.label,
3278
+ labelY: 25,
3279
+ labelX: function labelX() {
3280
+ return _this._width() + 6;
3281
+ },
3282
+ name: "distance"
3312
3283
  });
3313
3284
  }
3314
3285
 
3286
+ this._registerAxisGrid({
3287
+ axis: "x",
3288
+ position: "bottom",
3289
+ scale: "x" // this._chart._x,
3290
+
3291
+ });
3292
+
3315
3293
  this._registerTooltip({
3316
3294
  name: 'x',
3317
3295
  chart: function chart(item) {
3318
3296
  return L._("x: ") + d3.format("." + opts.decimalsX + "f")(item[opts.xAttr]) + " " + distance.label;
3319
- }
3297
+ },
3298
+ order: 20
3320
3299
  });
3321
3300
 
3322
3301
  this._registerSummary({
@@ -3324,7 +3303,8 @@
3324
3303
  label: "Total Length: ",
3325
3304
  value: function value(track) {
3326
3305
  return (track.distance || 0).toFixed(2) + '&nbsp;' + distance.label;
3327
- }
3306
+ },
3307
+ order: 10
3328
3308
  }
3329
3309
  });
3330
3310
  });
@@ -3340,7 +3320,7 @@
3340
3320
  * Common AVG speeds:
3341
3321
  * ----------------------
3342
3322
  * slow walk = 1.8 km/h
3343
- * walking = 3.6 km/h
3323
+ * walking = 3.6 km/h <-- default: 3.6
3344
3324
  * running = 10.8 km/h
3345
3325
  * cycling = 18 km/h
3346
3326
  * driving = 72 km/h
@@ -3367,6 +3347,49 @@
3367
3347
  return formatTime(t).split("'")[0];
3368
3348
  };
3369
3349
 
3350
+ this._registerDataAttribute({
3351
+ name: 'time',
3352
+ init: function init(_ref) {
3353
+ var point = _ref.point,
3354
+ props = _ref.props,
3355
+ id = _ref.id;
3356
+
3357
+ // "coordinateProperties" property is generated inside "@tmcw/toGeoJSON"
3358
+ if (props) {
3359
+ if ("coordTimes" in props) point.meta.time = new Date(Date.parse(props.coordTimes[id]));else if ("times" in props) point.meta.time = new Date(Date.parse(props.times[id]));else if ("time" in props) point.meta.time = new Date(Date.parse(_typeof(props.time) === 'object' ? props.time[id] : props.time));
3360
+ }
3361
+ },
3362
+ fetch: function fetch(i, point) {
3363
+ // Add missing timestamps (see: options.timeAVGSpeed)
3364
+ if (!point.meta || !point.meta.time) {
3365
+ point.meta = point.meta || {};
3366
+
3367
+ if (i > 0) {
3368
+ var dx = this._data[i].dist - this._data[i - 1].dist;
3369
+
3370
+ var t0 = this._data[i - 1].time.getTime();
3371
+
3372
+ var dt = dx / this._timeAVGSpeed * this.options.timeFactor * 1000;
3373
+ point.meta.time = new Date(t0 + dt);
3374
+ } else {
3375
+ point.meta.time = new Date(Date.now());
3376
+ }
3377
+ } // Handle timezone offset
3378
+
3379
+
3380
+ if (point.meta.time.getTime() - point.meta.time.getTimezoneOffset() * 60 * 1000 === 0) {
3381
+ point.meta.time = 0;
3382
+ }
3383
+
3384
+ return point.meta.time.getTime();
3385
+ },
3386
+ update: function update(time, i) {
3387
+ this.track_info.time = (this.track_info.time || 0) + Math.abs(this._data[i].time - this._data[i > 0 ? i - 1 : i].time);
3388
+ this._data[i].duration = this.track_info.time;
3389
+ return new Date(time);
3390
+ }
3391
+ });
3392
+
3370
3393
  if (opts.time && opts.time != "summary" && !L.Browser.mobile) {
3371
3394
  this._registerAxisScale({
3372
3395
  axis: "x",
@@ -3392,38 +3415,13 @@
3392
3415
  });
3393
3416
  }
3394
3417
 
3395
- this.on('elepoint_added', function (e) {
3396
- var data = this._data;
3397
- var i = e.index; // Add missing timestamps (see: options.timeAVGSpeed)
3398
-
3399
- if (!e.point.meta || !e.point.meta.time) {
3400
- e.point.meta = e.point.meta || {};
3401
- var delta = data[i].dist - data[i > 0 ? i - 1 : i].dist;
3402
- var speed = this._timeAVGSpeed;
3403
- e.point.meta.time = new Date(i > 0 ? data[i - 1].time.getTime() + delta / speed * opts.timeFactor * 1000 : Date.now());
3404
- }
3405
-
3406
- var time = e.point.meta.time; // Handle timezone offset
3407
-
3408
- if (time.getTime() - time.getTimezoneOffset() * 60 * 1000 === 0) {
3409
- time = 0;
3410
- }
3411
-
3412
- var currT = time;
3413
- var prevT = i > 0 ? data[i - 1].time : currT;
3414
- var deltaT = Math.abs(currT - prevT);
3415
- var duration = (this.track_info.time || 0) + deltaT;
3416
- this.track_info.time = duration;
3417
- data[i].time = time;
3418
- data[i].duration = duration;
3419
- });
3420
-
3421
3418
  if (this.options.timestamps) {
3422
3419
  this._registerTooltip({
3423
3420
  name: 'date',
3424
3421
  chart: function chart(item) {
3425
3422
  return L._("t: ") + _this.options.timeFormat(item.time);
3426
- }
3423
+ },
3424
+ order: 20
3427
3425
  });
3428
3426
  }
3429
3427
 
@@ -3432,7 +3430,8 @@
3432
3430
  name: 'time',
3433
3431
  chart: function chart(item) {
3434
3432
  return L._("T: ") + formatTime(item.duration || 0);
3435
- }
3433
+ },
3434
+ order: 20
3436
3435
  });
3437
3436
 
3438
3437
  this._registerSummary({
@@ -3440,7 +3439,8 @@
3440
3439
  label: "Total Time: ",
3441
3440
  value: function value(track) {
3442
3441
  return formatTime(track.time || 0);
3443
- }
3442
+ },
3443
+ order: 20
3444
3444
  }
3445
3445
  });
3446
3446
  }
@@ -3449,80 +3449,208 @@
3449
3449
  Elevation.addInitHook(function () {
3450
3450
  var _this = this;
3451
3451
 
3452
- if (!this.options.slope) return;
3453
3452
  var opts = this.options;
3454
- var slope = {};
3455
- slope.label = opts.slopeLabel || '%';
3453
+ var altitude = {};
3454
+ var theme = opts.theme.replace('-theme', '');
3455
+ var color = Colors[theme] || {};
3456
3456
 
3457
- if (this.options.slope != "summary") {
3458
- this._registerAxisScale({
3459
- axis: "y",
3460
- position: "right",
3461
- scale: {
3462
- min: -1,
3463
- max: +1
3457
+ if (opts.imperial) {
3458
+ opts.altitudeFactor = this.__footFactor;
3459
+ altitude.label = "ft";
3460
+ } else {
3461
+ opts.altitudeFactor = opts.heightFactor || opts.altitudeFactor || 1;
3462
+ altitude.label = opts.yLabel;
3463
+ }
3464
+
3465
+ this._registerDataAttribute({
3466
+ name: 'z',
3467
+ skipNull: this.options.skipNullZCoords,
3468
+ init: function init(_ref) {
3469
+ var point = _ref.point;
3470
+ // "alt" property is generated inside "leaflet"
3471
+ if ("alt" in point) point.meta.ele = point.alt; // this.track_info.elevation_max = -Infinity;
3472
+ // this.track_info.elevation_min = +Infinity;
3473
+ // this.track_info.elevation_avg = 0;
3474
+ },
3475
+ fetch: function fetch(i) {
3476
+ return _this._data[i].z * opts.altitudeFactor;
3477
+ },
3478
+ update: function update(z, i) {
3479
+ _this.track_info.elevation_max = _this.track_info.elevation_max || -Infinity;
3480
+ _this.track_info.elevation_min = _this.track_info.elevation_max || +Infinity;
3481
+ _this.track_info.elevation_avg = _this.track_info.elevation_avg || 0;
3482
+ var data = _this._data;
3483
+ var track = _this.track_info; // Try to smooth "crazy" elevation values.
3484
+
3485
+ if (_this.options.altitudeDeltaMax) {
3486
+ var delta = z - data[i > 0 ? i - 1 : i].z;
3487
+ var deltaMax = _this.options.altitudeDeltaMax;
3488
+
3489
+ if (Math.abs(delta) > deltaMax) {
3490
+ z = data[i - 1].z + deltaMax * Math.sign(delta);
3491
+ }
3492
+ } // Range of acceptable elevation values.
3493
+
3494
+
3495
+ z = clamp(z, _this.options.altitudeRange);
3496
+ if (z > track.elevation_max) track.elevation_max = z;
3497
+ if (z < track.elevation_min) track.elevation_min = z;
3498
+ track.elevation_avg = (z + track.elevation_avg) / 2.0;
3499
+ return z;
3500
+ }
3501
+ });
3502
+
3503
+ this._registerAxisScale({
3504
+ axis: "y",
3505
+ position: "left",
3506
+ scale: "y",
3507
+ // this._chart._y,
3508
+ label: altitude.label,
3509
+ labelX: -3,
3510
+ labelY: -8,
3511
+ name: "altitude",
3512
+ visbile: this.options.altitude != "summary"
3513
+ });
3514
+
3515
+ this._registerAxisGrid({
3516
+ axis: "y",
3517
+ position: "left",
3518
+ scale: "y" // this._chart._y,
3519
+
3520
+ });
3521
+
3522
+ this._registerAreaPath({
3523
+ name: 'altitude',
3524
+ label: 'Altitude',
3525
+ scaleX: 'distance',
3526
+ scaleY: 'altitude',
3527
+ color: color.area || theme,
3528
+ strokeColor: opts.detached ? color.stroke : '#000',
3529
+ strokeOpacity: "1",
3530
+ fillOpacity: opts.detached ? color.alpha || '0.8' : 1,
3531
+ preferCanvas: opts.preferCanvas,
3532
+ visbile: this.options.altitude != "summary"
3533
+ });
3534
+
3535
+ this._registerTooltip({
3536
+ name: 'y',
3537
+ chart: function chart(item) {
3538
+ return L._("y: ") + d3.format("." + opts.decimalsY + "f")(item[opts.yAttr]) + " " + altitude.label;
3539
+ },
3540
+ marker: function marker(item) {
3541
+ return d3.format("." + opts.decimalsY + "f")(item[opts.yAttr]) + " " + altitude.label;
3542
+ },
3543
+ order: 10
3544
+ });
3545
+
3546
+ this._registerSummary({
3547
+ "maxele": {
3548
+ label: "Max Elevation: ",
3549
+ value: function value(track) {
3550
+ return (track.elevation_max || 0).toFixed(2) + '&nbsp;' + altitude.label;
3464
3551
  },
3465
- tickPadding: 16,
3466
- label: slope.label,
3467
- labelX: 25,
3468
- labelY: -8,
3469
- name: 'slope'
3470
- });
3552
+ order: 30
3553
+ },
3554
+ "minele": {
3555
+ label: "Min Elevation: ",
3556
+ value: function value(track) {
3557
+ return (track.elevation_min || 0).toFixed(2) + '&nbsp;' + altitude.label;
3558
+ },
3559
+ order: 30
3560
+ },
3561
+ "avgele": {
3562
+ label: "Avg Elevation: ",
3563
+ value: function value(track) {
3564
+ return (track.elevation_avg || 0).toFixed(2) + '&nbsp;' + altitude.label;
3565
+ },
3566
+ order: 30
3567
+ }
3568
+ });
3569
+ });
3471
3570
 
3472
- this._registerAreaPath({
3473
- name: 'slope',
3474
- label: 'Slope',
3475
- yAttr: 'slope',
3476
- scaleX: 'distance',
3477
- scaleY: 'slope',
3478
- color: '#F00',
3479
- strokeColor: '#000',
3480
- strokeOpacity: "0.5",
3481
- fillOpacity: "0.25"
3482
- });
3483
- }
3571
+ Elevation.addInitHook(function () {
3572
+ var _this = this;
3484
3573
 
3485
- this.on("eledata_updated", function (e) {
3486
- var data = this._data;
3487
- var i = e.index;
3488
- var z = data[i].z;
3489
- var delta = (data[i].dist - data[i > 0 ? i - 1 : i].dist) * 1000; // Slope / Gain
3574
+ if (!this.options.slope) return;
3575
+ var opts = this.options;
3576
+ var slope = {};
3577
+ slope.label = opts.slopeLabel || '%';
3490
3578
 
3491
- var track = this.track_info;
3492
- var tAsc = track.ascent || 0; // Total Ascent
3579
+ this._registerDataAttribute({
3580
+ name: 'slope',
3581
+ // init: () => {
3582
+ // // this.track_info.ascent = 0; // Total Ascent
3583
+ // // this.track_info.descent = 0; // Total Descent
3584
+ // // this.track_info.slope_max = -Infinity; // Slope Max
3585
+ // // this.track_info.slope_min = +Infinity; // Slope Min
3586
+ // // this.track_info.slope_avg = 0; // Acceleration Avg
3587
+ // },
3588
+ fetch: function fetch(i) {
3589
+ var data = _this._data;
3590
+ var dx = (data[i].dist - data[i > 0 ? i - 1 : i].dist) * 1000;
3591
+ var dz = data[i].z - data[i > 0 ? i - 1 : i].z;
3592
+ return !isNaN(dz) && dx !== 0 ? dz / dx * 100 : 0; // slope in % = ( height / length ) * 100;
3593
+ },
3594
+ update: function update(slope, i) {
3595
+ _this.track_info.ascent = _this.track_info.ascent || 0; // Total Ascent
3493
3596
 
3494
- var tDes = track.descent || 0; // Total Descent
3597
+ _this.track_info.descent = _this.track_info.descent || 0; // Total Descent
3495
3598
 
3496
- var sMax = track.slope_max || 0; // Slope Max
3599
+ _this.track_info.slope_max = _this.track_info.slope_max || -Infinity; // Slope Max
3497
3600
 
3498
- var sMin = track.slope_min || 0; // Slope Min
3601
+ _this.track_info.slope_min = _this.track_info.slope_min || +Infinity; // Slope Min
3499
3602
 
3500
- var slope = 0;
3603
+ _this.track_info.slope_avg = _this.track_info.slope_avg || 0; // Acceleration Avg
3501
3604
 
3502
- if (!isNaN(z)) {
3503
- var deltaZ = i > 0 ? z - data[i - 1].z : 0;
3504
- if (deltaZ > 0) tAsc += deltaZ;else if (deltaZ < 0) tDes -= deltaZ; // slope in % = ( height / length ) * 100
3605
+ var track = _this.track_info;
3606
+ var data = _this._data;
3607
+ var dz = data[i].z - data[i > 0 ? i - 1 : i].z; // Try to smooth "crazy" acceleration values.
3505
3608
 
3506
- if (delta !== 0) slope = deltaZ / delta * 100;
3507
- } // Try to smooth "crazy" slope values.
3609
+ if (_this.options.slopeDeltaMax) {
3610
+ var delta = slop - data[i > 0 ? i - 1 : i].slope;
3611
+ var deltaMax = _this.options.slopeDeltaMax;
3508
3612
 
3613
+ if (Math.abs(delta) > deltaMax) {
3614
+ slope = data[i - 1].slope + deltaMax * Math.sign(delta);
3615
+ }
3616
+ } // Range of acceptable slope values.
3509
3617
 
3510
- if (this.options.sDeltaMax) {
3511
- var deltaS = i > 0 ? slope - data[i - 1].slope : 0;
3512
- var maxDeltaS = this.options.sDeltaMax;
3513
3618
 
3514
- if (Math.abs(deltaS) > maxDeltaS) {
3515
- slope = data[i - 1].slope + maxDeltaS * Math.sign(deltaS);
3516
- }
3517
- } // Range of acceptable slope values.
3619
+ slope = clamp(slope, _this.options.slopeRange);
3620
+ if (dz > 0) _this.track_info.ascent += dz;else if (dz < 0) _this.track_info.descent -= dz;
3621
+ if (slope > track.slope_max) track.slope_max = slope;
3622
+ if (slope < track.slope_min) track.slope_min = slope;
3623
+ track.slope_avg = (slope + track.slope_avg) / 2.0;
3624
+ return L.Util.formatNum(slope, 2);
3625
+ }
3626
+ });
3518
3627
 
3628
+ this._registerAxisScale({
3629
+ axis: "y",
3630
+ position: "right",
3631
+ scale: {
3632
+ min: -1,
3633
+ max: +1
3634
+ },
3635
+ tickPadding: 16,
3636
+ label: slope.label,
3637
+ labelX: 25,
3638
+ labelY: -8,
3639
+ name: 'slope',
3640
+ visbile: this.options.slope != "summary"
3641
+ });
3519
3642
 
3520
- slope = clamp(slope, this.options.sRange);
3521
- track.ascent = tAsc;
3522
- track.descent = tDes;
3523
- track.slope_max = slope > sMax ? slope : sMax;
3524
- track.slope_min = slope < sMin ? slope : sMin;
3525
- data[i].slope = L.Util.formatNum(slope, 2);
3643
+ this._registerAreaPath({
3644
+ name: 'slope',
3645
+ label: 'Slope',
3646
+ yAttr: 'slope',
3647
+ scaleX: 'distance',
3648
+ scaleY: 'slope',
3649
+ color: '#F00',
3650
+ strokeColor: '#000',
3651
+ strokeOpacity: "0.5",
3652
+ fillOpacity: "0.25",
3653
+ visbile: this.options.slope != "summary"
3526
3654
  });
3527
3655
 
3528
3656
  this._registerTooltip({
@@ -3532,7 +3660,8 @@
3532
3660
  },
3533
3661
  marker: function marker(item) {
3534
3662
  return Math.round(item.slope) + slope.label;
3535
- }
3663
+ },
3664
+ order: 40
3536
3665
  });
3537
3666
 
3538
3667
  this._registerSummary({
@@ -3540,36 +3669,89 @@
3540
3669
  label: "Total Ascent: ",
3541
3670
  value: function value(track) {
3542
3671
  return Math.round(track.ascent || 0) + '&nbsp;' + (_this.options.imperial ? 'ft' : 'm');
3543
- }
3672
+ },
3673
+ order: 40
3544
3674
  },
3545
3675
  "descent": {
3546
3676
  label: "Total Descent: ",
3547
3677
  value: function value(track) {
3548
3678
  return Math.round(track.descent || 0) + '&nbsp;' + (_this.options.imperial ? 'ft' : 'm');
3549
- }
3679
+ },
3680
+ order: 40
3550
3681
  },
3551
3682
  "minslope": {
3552
3683
  label: "Min Slope: ",
3553
3684
  value: function value(track) {
3554
3685
  return Math.round(track.slope_min || 0) + '&nbsp;' + slope.label;
3555
- }
3686
+ },
3687
+ order: 40
3556
3688
  },
3557
3689
  "maxslope": {
3558
3690
  label: "Max Slope: ",
3559
3691
  value: function value(track) {
3560
3692
  return Math.round(track.slope_max || 0) + '&nbsp;' + slope.label;
3561
- }
3693
+ },
3694
+ order: 40
3695
+ },
3696
+ "avgslope": {
3697
+ label: "Avg Slope: ",
3698
+ value: function value(track) {
3699
+ return Math.round(track.slope_avg || 0) + '&nbsp;' + slope.label;
3700
+ },
3701
+ order: 40
3562
3702
  }
3563
3703
  });
3564
3704
  });
3565
3705
 
3566
3706
  Elevation.addInitHook(function () {
3707
+ var _this = this;
3708
+
3567
3709
  if (!this.options.speed && !this.options.acceleration) return;
3568
3710
  var opts = this.options;
3569
3711
  var speed = {};
3570
3712
  speed.label = opts.speedLabel || L._(opts.imperial ? 'mph' : 'km/h');
3571
3713
  opts.speedFactor = opts.speedFactor || 1;
3572
3714
 
3715
+ this._registerDataAttribute({
3716
+ name: 'speed',
3717
+ init: function init() {// this.track_info.speed_max = -Infinity; // Speed Max
3718
+ // this.track_info.speed_min = +Infinity; // Speed Min
3719
+ // this.track_info.speed_avg = 0; // Speed Avg
3720
+ },
3721
+ fetch: function fetch(i) {
3722
+ var data = _this._data;
3723
+ var dx = (data[i].dist - data[i > 0 ? i - 1 : i].dist) * 1000;
3724
+ var dt = data[i].time - data[i > 0 ? i - 1 : i].time;
3725
+ return dt > 0 ? Math.abs(dx / dt * opts.timeFactor) * opts.speedFactor : 0;
3726
+ },
3727
+ update: function update(speed, i) {
3728
+ _this.track_info.speed_max = _this.track_info.speed_max || -Infinity; // Speed Max
3729
+
3730
+ _this.track_info.speed_min = _this.track_info.speed_min || +Infinity; // Speed Min
3731
+
3732
+ _this.track_info.speed_avg = _this.track_info.speed_avg || 0; // Speed Avg
3733
+
3734
+ var data = _this._data;
3735
+ var track = _this.track_info; // Try to smooth "crazy" speed values.
3736
+
3737
+ if (_this.options.speedDeltaMax) {
3738
+ var delta = speed - data[i > 0 ? i - 1 : i].speed;
3739
+ var deltaMax = _this.options.speedDeltaMax;
3740
+
3741
+ if (Math.abs(delta) > deltaMax) {
3742
+ speed = data[i - 1].speed + deltaMax * Math.sign(delta);
3743
+ }
3744
+ } // Range of acceptable speed values.
3745
+
3746
+
3747
+ speed = clamp(speed, _this.options.speedRange);
3748
+ if (speed > track.speed_max) track.speed_max = speed;
3749
+ if (speed < track.speed_min) track.speed_min = speed;
3750
+ track.speed_avg = (speed + track.speed_avg) / 2.0;
3751
+ return L.Util.formatNum(speed, 2);
3752
+ }
3753
+ });
3754
+
3573
3755
  if (this.options.speed && this.options.speed != "summary") {
3574
3756
  this._registerAxisScale({
3575
3757
  axis: "y",
@@ -3598,44 +3780,6 @@
3598
3780
  });
3599
3781
  }
3600
3782
 
3601
- this.on('elepoint_added', function (e) {
3602
- var data = this._data;
3603
- var i = e.index;
3604
- var currT = data[i].time;
3605
- var prevT = i > 0 ? data[i - 1].time : currT;
3606
- var deltaT = currT - prevT;
3607
- var track = this.track_info;
3608
- var sMax = track.speed_max || -Infinity; // Speed Max
3609
-
3610
- var sMin = track.speed_min || +Infinity; // Speed Min
3611
-
3612
- var sAvg = track.speed_avg || 0; // Speed Avg
3613
-
3614
- var speed = 0;
3615
-
3616
- if (deltaT > 0) {
3617
- var delta = (data[i].dist - data[i > 0 ? i - 1 : i].dist) * 1000;
3618
- speed = Math.abs(delta / deltaT * opts.timeFactor) * opts.speedFactor;
3619
- } // Try to smooth "crazy" speed values.
3620
-
3621
-
3622
- if (this.options.speedDeltaMax) {
3623
- var deltaS = i > 0 ? speed - data[i - 1].speed : 0;
3624
- var maxDeltaS = this.options.speedDeltaMax;
3625
-
3626
- if (Math.abs(deltaS) > maxDeltaS) {
3627
- speed = data[i - 1].speed + maxDeltaS * Math.sign(deltaS);
3628
- }
3629
- } // Range of acceptable speed values.
3630
-
3631
-
3632
- speed = clamp(speed, this.options.speedRange);
3633
- track.speed_max = speed > sMax ? speed : sMax;
3634
- track.speed_min = speed < sMin ? speed : sMin;
3635
- track.speed_avg = (speed + sAvg) / 2.0;
3636
- data[i].speed = L.Util.formatNum(speed, 2);
3637
- });
3638
-
3639
3783
  if (this.options.speed) {
3640
3784
  this._registerTooltip({
3641
3785
  name: 'speed',
@@ -3644,7 +3788,8 @@
3644
3788
  },
3645
3789
  marker: function marker(item) {
3646
3790
  return Math.round(item.speed) + " " + speed.label;
3647
- }
3791
+ },
3792
+ order: 50
3648
3793
  });
3649
3794
 
3650
3795
  this._registerSummary({
@@ -3652,31 +3797,76 @@
3652
3797
  label: "Min Speed: ",
3653
3798
  value: function value(track) {
3654
3799
  return Math.round(track.speed_min || 0) + '&nbsp;' + speed.label;
3655
- }
3800
+ },
3801
+ order: 50
3656
3802
  },
3657
3803
  "maxspeed": {
3658
3804
  label: "Max Speed: ",
3659
3805
  value: function value(track) {
3660
3806
  return Math.round(track.speed_max || 0) + '&nbsp;' + speed.label;
3661
- }
3807
+ },
3808
+ order: 50
3662
3809
  },
3663
3810
  "avgspeed": {
3664
3811
  label: "Avg Speed: ",
3665
3812
  value: function value(track) {
3666
3813
  return Math.round(track.speed_avg || 0) + '&nbsp;' + speed.label;
3667
- }
3814
+ },
3815
+ order: 50
3668
3816
  }
3669
3817
  });
3670
3818
  }
3671
3819
  });
3672
3820
 
3673
3821
  Elevation.addInitHook(function () {
3822
+ var _this = this;
3823
+
3674
3824
  if (!this.options.acceleration) return;
3675
3825
  var opts = this.options;
3676
3826
  var acceleration = {};
3677
3827
  acceleration.label = opts.accelerationLabel || L._(opts.imperial ? 'ft/s²' : 'm/s²');
3678
3828
  opts.accelerationFactor = opts.accelerationFactor || 1;
3679
3829
 
3830
+ this._registerDataAttribute({
3831
+ name: 'acceleration',
3832
+ init: function init() {// this.track_info.acceleration_max = -Infinity; // Acceleration Max
3833
+ // this.track_info.acceleration_min = +Infinity; // Acceleration Min
3834
+ // this.track_info.acceleration_avg = 0; // Acceleration Avg
3835
+ },
3836
+ fetch: function fetch(i) {
3837
+ var data = _this._data;
3838
+ var dv = (data[i].speed - data[i > 0 ? i - 1 : i].speed) * (1000 / opts.timeFactor);
3839
+ var dt = (data[i].time - data[i > 0 ? i - 1 : i].time) / 1000;
3840
+ return dt > 0 ? Math.abs(dv / dt) * opts.accelerationFactor : 0;
3841
+ },
3842
+ update: function update(acceleration, i) {
3843
+ _this.track_info.acceleration_max = _this.track_info.acceleration_max || -Infinity; // Acceleration Max
3844
+
3845
+ _this.track_info.acceleration_min = _this.track_info.acceleration_min || +Infinity; // Acceleration Min
3846
+
3847
+ _this.track_info.acceleration_avg = _this.track_info.acceleration_avg || 0; // Acceleration Avg
3848
+
3849
+ var data = _this._data;
3850
+ var track = _this.track_info; // Try to smooth "crazy" acceleration values.
3851
+
3852
+ if (_this.options.accelerationDeltaMax) {
3853
+ var delta = acceleration - data[i > 0 ? i - 1 : i].acceleration;
3854
+ var deltaMax = _this.options.accelerationDeltaMax;
3855
+
3856
+ if (Math.abs(delta) > deltaMax) {
3857
+ acceleration = data[i - 1].acceleration + deltaMax * Math.sign(delta);
3858
+ }
3859
+ } // Range of acceptable acceleration values.
3860
+
3861
+
3862
+ acceleration = clamp(acceleration, _this.options.accelerationRange);
3863
+ if (acceleration > track.acceleration_max) track.acceleration_max = acceleration;
3864
+ if (acceleration < track.acceleration_min) track.acceleration_min = acceleration;
3865
+ track.acceleration_avg = (acceleration + track.acceleration_avg) / 2.0;
3866
+ return L.Util.formatNum(acceleration, 2);
3867
+ }
3868
+ });
3869
+
3680
3870
  if (this.options.acceleration != "summary") {
3681
3871
  this._registerAxisScale({
3682
3872
  axis: "y",
@@ -3705,46 +3895,6 @@
3705
3895
  });
3706
3896
  }
3707
3897
 
3708
- this.on('elepoint_added', function (e) {
3709
- var data = this._data;
3710
- var i = e.index;
3711
- var currT = data[i].time;
3712
- var prevT = i > 0 ? data[i - 1].time : currT;
3713
- var deltaT = (currT - prevT) / 1000;
3714
- var track = this.track_info;
3715
- var sMax = track.acceleration_max || -Infinity; // Acceleration Max
3716
-
3717
- var sMin = track.acceleration_min || +Infinity; // Acceleration Min
3718
-
3719
- var sAvg = track.acceleration_avg || 0; // Acceleration Avg
3720
-
3721
- var acceleration = 0;
3722
-
3723
- if (deltaT > 0) {
3724
- var curr = data[i].speed;
3725
- var prev = i > 0 ? data[i - 1].speed : curr;
3726
- var delta = (curr - prev) * (1000 / opts.timeFactor);
3727
- acceleration = Math.abs(delta / deltaT) * opts.accelerationFactor;
3728
- } // Try to smooth "crazy" acceleration values.
3729
-
3730
-
3731
- if (this.options.accelerationDeltaMax) {
3732
- var deltaA = i > 0 ? acceleration - data[i - 1].acceleration : 0;
3733
- var maxDeltaS = this.options.accelerationDeltaMax;
3734
-
3735
- if (Math.abs(deltaA) > maxDeltaS) {
3736
- acceleration = data[i - 1].acceleration + maxDeltaS * Math.sign(deltaA);
3737
- }
3738
- } // Range of acceptable acceleration values.
3739
-
3740
-
3741
- acceleration = clamp(acceleration, this.options.accelerationRange);
3742
- track.acceleration_max = acceleration > sMax ? acceleration : sMax;
3743
- track.acceleration_min = acceleration < sMin ? acceleration : sMin;
3744
- track.acceleration_avg = (acceleration + sAvg) / 2.0;
3745
- data[i].acceleration = L.Util.formatNum(acceleration, 2);
3746
- });
3747
-
3748
3898
  this._registerTooltip({
3749
3899
  name: 'acceleration',
3750
3900
  chart: function chart(item) {
@@ -3752,7 +3902,8 @@
3752
3902
  },
3753
3903
  marker: function marker(item) {
3754
3904
  return Math.round(item.acceleration) + " " + acceleration.label;
3755
- }
3905
+ },
3906
+ order: 60
3756
3907
  });
3757
3908
 
3758
3909
  this._registerSummary({
@@ -3760,19 +3911,22 @@
3760
3911
  label: "Min Acceleration: ",
3761
3912
  value: function value(track) {
3762
3913
  return Math.round(track.acceleration_min || 0) + '&nbsp;' + acceleration.label;
3763
- }
3914
+ },
3915
+ order: 60
3764
3916
  },
3765
3917
  "maxacceleration": {
3766
3918
  label: "Max Acceleration: ",
3767
3919
  value: function value(track) {
3768
3920
  return Math.round(track.acceleration_max || 0) + '&nbsp;' + acceleration.label;
3769
- }
3921
+ },
3922
+ order: 60
3770
3923
  },
3771
3924
  "avgacceleration": {
3772
3925
  label: "Avg Acceleration: ",
3773
3926
  value: function value(track) {
3774
3927
  return Math.round(track.acceleration_avg || 0) + '&nbsp;' + acceleration.label;
3775
- }
3928
+ },
3929
+ order: 60
3776
3930
  }
3777
3931
  });
3778
3932
  });