@raruto/leaflet-elevation 1.9.4 → 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.
@@ -406,8 +406,10 @@
406
406
  line.attr("class", theme + " height-focus line").attr("x1", xCoord).attr("x2", xCoord).attr("y1", yCoord).attr("y2", length);
407
407
  text.attr("class", theme + " height-focus-label").style("pointer-events", "none").attr("x", xCoord + 5).attr("y", length);
408
408
  var label;
409
-
410
- 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) {
411
413
  label = text.select(".height-focus-" + labels[i].name);
412
414
 
413
415
  if (!label.size()) {
@@ -415,8 +417,7 @@
415
417
  }
416
418
 
417
419
  label.text(typeof labels[i].value !== "function" ? labels[i].value : labels[i].value(item));
418
- }
419
-
420
+ });
420
421
  text.select('tspan').attr("dy", text.selectAll('tspan').size() > 1 ? "-1.5em" : "0em");
421
422
  text.selectAll('tspan').attr("x", xCoord + 5);
422
423
  return g;
@@ -487,8 +488,10 @@
487
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);
488
489
  text.attr("class", "mouse-focus-label-text").style("font-weight", "700").attr("y", yAlign);
489
490
  var label;
490
-
491
- 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) {
492
495
  label = text.select(".mouse-focus-label-" + labels[i].name);
493
496
 
494
497
  if (!label.size()) {
@@ -496,8 +499,7 @@
496
499
  }
497
500
 
498
501
  label.text(typeof labels[i].value !== "function" ? labels[i].value : labels[i].value(item));
499
- }
500
-
502
+ });
501
503
  text.select('tspan').attr("dy", "1em");
502
504
  text.selectAll('tspan').attr("x", xAlign);
503
505
  return g;
@@ -1173,6 +1175,7 @@
1173
1175
  this._y = this._scales.altitude;
1174
1176
  },
1175
1177
  _registerAreaPath: function _registerAreaPath(props) {
1178
+ if (props.scale == 'y') props.scale = this._y;else if (props.scale == 'x') props.scale = this._x;
1176
1179
  var opts = this.options;
1177
1180
  if (!props.xAttr) props.xAttr = opts.xAttr;
1178
1181
  if (!props.yAttr) props.yAttr = opts.yAttr;
@@ -1192,9 +1195,11 @@
1192
1195
  }
1193
1196
  },
1194
1197
  _registerAxisGrid: function _registerAxisGrid(props) {
1198
+ if (props.scale == 'y') props.scale = this._y;else if (props.scale == 'x') props.scale = this._x;
1195
1199
  this._props.grids[props.name || props.axis] = props;
1196
1200
  },
1197
1201
  _registerAxisScale: function _registerAxisScale(props) {
1202
+ if (props.scale == 'y') props.scale = this._y;else if (props.scale == 'x') props.scale = this._x;
1198
1203
  var opts = this.options;
1199
1204
  var scale = props.scale;
1200
1205
 
@@ -1248,6 +1253,9 @@
1248
1253
  }));
1249
1254
  },
1250
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;
1251
1259
  this._props.tooltipItems[props.name] = props;
1252
1260
  },
1253
1261
  _updateArea: function _updateArea() {
@@ -1670,6 +1678,7 @@
1670
1678
  initialize: function initialize(opts, control) {
1671
1679
  this.options = opts;
1672
1680
  this.control = control;
1681
+ this.labels = {};
1673
1682
 
1674
1683
  var summary = this._container = create("div", "elevation-summary " + (opts.summary ? opts.summary + "-summary" : ''));
1675
1684
 
@@ -1691,9 +1700,22 @@
1691
1700
  this._container.innerHTML += "<span class=\"".concat(className, "\"><span class=\"summarylabel\">").concat(label, "</span><span class=\"summaryvalue\">").concat(value, "</span></span>");
1692
1701
  return this;
1693
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
+ },
1694
1713
  _registerSummary: function _registerSummary(data) {
1695
1714
  for (var i in data) {
1696
- 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];
1697
1719
  }
1698
1720
  }
1699
1721
  });
@@ -1710,7 +1732,7 @@
1710
1732
  distanceMarkers: {
1711
1733
  lazy: true,
1712
1734
  distance: true,
1713
- arrow: false
1735
+ direction: true
1714
1736
  },
1715
1737
  decimalsX: 2,
1716
1738
  decimalsY: 0,
@@ -1757,15 +1779,15 @@
1757
1779
  theme: "lightblue-theme",
1758
1780
  summary: 'inline',
1759
1781
  slope: false,
1782
+ slopeDeltaMax: undefined,
1783
+ slopeRange: undefined,
1760
1784
  speed: false,
1761
- sLimit: undefined,
1785
+ speedDeltaMax: undefined,
1786
+ speedRange: undefined,
1762
1787
  time: false,
1763
1788
  timeFactor: 3600,
1764
1789
  timeFormat: false,
1765
1790
  timestamps: false,
1766
- sDeltaMax: undefined,
1767
- sInterpolation: "curveStepAfter",
1768
- sRange: undefined,
1769
1791
  width: 600,
1770
1792
  waypoints: true,
1771
1793
  wptIcons: {
@@ -1798,7 +1820,7 @@
1798
1820
  __TOGEOJSON: 'https://unpkg.com/@tmcw/togeojson@4.5.0/dist/togeojson.umd.js',
1799
1821
  __LGEOMUTIL: 'https://unpkg.com/leaflet-geometryutil@0.9.3/src/leaflet.geometryutil.js',
1800
1822
  __LALMOSTOVER: 'https://unpkg.com/leaflet-almostover@1.0.1/src/leaflet.almostover.js',
1801
- __LDISTANCEM: 'https://unpkg.com/@raruto/leaflet-elevation@1.9.4/libs/leaflet-distance-marker.min.js',
1823
+ __LDISTANCEM: 'https://unpkg.com/@raruto/leaflet-elevation@1.9.5/libs/leaflet-distance-marker.min.js',
1802
1824
 
1803
1825
  /*
1804
1826
  * Add data to the diagram either from GPX or GeoJSON and update the axis domain and data
@@ -1889,6 +1911,22 @@
1889
1911
  }
1890
1912
  },
1891
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
+
1892
1930
  /**
1893
1931
  * Disable chart brushing.
1894
1932
  */
@@ -1936,7 +1974,7 @@
1936
1974
  },
1937
1975
 
1938
1976
  /**
1939
- * Get default zoom level when "followMarker" is true.
1977
+ * Get default zoom level (followMarker: true).
1940
1978
  */
1941
1979
  getZFollow: function getZFollow() {
1942
1980
  return this.options.zFollow;
@@ -1958,6 +1996,7 @@
1958
1996
  this._markers = L.featureGroup();
1959
1997
  this._markedSegments = L.polyline([]);
1960
1998
  this._chartEnabled = true, this.track_info = {};
1999
+ this.handlers = [];
1961
2000
  L.setOptions(this, options);
1962
2001
  if (this.options.followMarker) this._setMapView = L.Util.throttle(this._setMapView, 300, this);
1963
2002
  if (this.options.legend) this.options.margins.bottom += 30;
@@ -2017,7 +2056,7 @@
2017
2056
  },
2018
2057
 
2019
2058
  /**
2020
- * Load elevation data (GPX, GeoJSON or KML).
2059
+ * Load elevation data (GPX, GeoJSON, KML or TCX).
2021
2060
  */
2022
2061
  load: function load(data) {
2023
2062
  var _this3 = this;
@@ -2091,7 +2130,7 @@
2091
2130
  },
2092
2131
 
2093
2132
  /**
2094
- * Set default zoom level when "followMarker" is true.
2133
+ * Set default zoom level (followMarker: true).
2095
2134
  */
2096
2135
  setZFollow: function setZFollow(zoom) {
2097
2136
  this.options.zFollow = zoom;
@@ -2170,26 +2209,24 @@
2170
2209
  hr: null,
2171
2210
  cad: null,
2172
2211
  atemp: null
2173
- }; // "alt" property is generated inside "leaflet"
2174
-
2175
- if ("alt" in point) point.meta.ele = point.alt; // "coordinateProperties" property is generated inside "@tmcw/toGeoJSON"
2212
+ }; // "coordinateProperties" property is generated inside "@tmcw/toGeoJSON"
2176
2213
 
2177
2214
  var props = properties && properties.coordinateProperties || properties;
2178
2215
 
2179
- if (props) {
2180
- 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));
2181
- 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
2182
- }
2216
+ _this6.fire("elepoint_init", {
2217
+ point: point,
2218
+ props: props,
2219
+ id: i
2220
+ });
2183
2221
 
2184
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]);
2185
2223
 
2186
- _this6._fireEvt("elepoint_added", {
2224
+ _this6.fire("elepoint_added", {
2187
2225
  point: point,
2188
2226
  index: _this6._data.length - 1
2189
2227
  });
2190
2228
  });
2191
-
2192
- this._fireEvt("eletrack_added", {
2229
+ this.fire("eletrack_added", {
2193
2230
  coords: coords,
2194
2231
  index: this._data.length - 1
2195
2232
  });
@@ -2212,7 +2249,7 @@
2212
2249
  latlng: L.latLng(x, y, z)
2213
2250
  });
2214
2251
 
2215
- this._fireEvt("eledata_updated", {
2252
+ this.fire("eledata_updated", {
2216
2253
  index: this._data.length - 1
2217
2254
  });
2218
2255
  },
@@ -2421,7 +2458,7 @@
2421
2458
  },
2422
2459
 
2423
2460
  /**
2424
- * Generate "svg" chart DOM element.
2461
+ * Generate "svg" chart (DOM element).
2425
2462
  */
2426
2463
  _initChart: function _initChart(container) {
2427
2464
  var opts = this.options;
@@ -2447,13 +2484,10 @@
2447
2484
  this._x = this._chart._x;
2448
2485
  this._y = this._chart._y;
2449
2486
  d3.select(container).call(chart.render());
2450
- 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);
2451
-
2452
- this._fireEvt("elechart_axis");
2453
-
2454
- if (this.options.legend) this._fireEvt("elechart_legend");
2455
-
2456
- 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");
2457
2491
  },
2458
2492
  _initLayer: function _initLayer() {
2459
2493
  var _this10 = this;
@@ -2485,8 +2519,7 @@
2485
2519
  }).addTo(this._map); // default leaflet svg renderer
2486
2520
 
2487
2521
  this._marker = new Marker(this.options);
2488
-
2489
- this._fireEvt("elechart_marker");
2522
+ this.fire("elechart_marker");
2490
2523
  },
2491
2524
 
2492
2525
  /**
@@ -2650,8 +2683,14 @@
2650
2683
  this._hideMarker();
2651
2684
 
2652
2685
  this.fitBounds(L.latLngBounds([e.dragstart.latlng, e.dragend.latlng]));
2686
+ this.fire("elechart_dragged");
2687
+ },
2653
2688
 
2654
- this._fireEvt("elechart_dragged");
2689
+ /**
2690
+ * Trigger mouseenter event
2691
+ */
2692
+ _mouseenterHandler: function _mouseenterHandler(e) {
2693
+ this.fire('elechart_enter');
2655
2694
  },
2656
2695
 
2657
2696
  /*
@@ -2676,12 +2715,11 @@
2676
2715
  addClass(this._map.getContainer(), 'elechart-hover');
2677
2716
  }
2678
2717
 
2679
- this._fireEvt("elechart_change", {
2718
+ this.fire("elechart_change", {
2680
2719
  data: item,
2681
2720
  xCoord: xCoord
2682
2721
  });
2683
-
2684
- this._fireEvt("elechart_hover", {
2722
+ this.fire("elechart_hover", {
2685
2723
  data: item,
2686
2724
  xCoord: xCoord
2687
2725
  });
@@ -2704,7 +2742,7 @@
2704
2742
 
2705
2743
  this._updateMarker(item);
2706
2744
 
2707
- this._fireEvt("elechart_change", {
2745
+ this.fire("elechart_change", {
2708
2746
  data: item,
2709
2747
  xCoord: xCoord
2710
2748
  });
@@ -2725,7 +2763,7 @@
2725
2763
  removeClass(this._map.getContainer(), 'elechart-hover');
2726
2764
  }
2727
2765
 
2728
- this._fireEvt("elechart_leave");
2766
+ this.fire("elechart_leave");
2729
2767
  },
2730
2768
 
2731
2769
  /**
@@ -2831,46 +2869,97 @@
2831
2869
  },
2832
2870
 
2833
2871
  /**
2834
- * Add a point of interest over the diagram
2872
+ * Add chart profile to diagram
2835
2873
  */
2836
- _registerCheckPoint: function _registerCheckPoint(props) {
2874
+ _registerAreaPath: function _registerAreaPath(props) {
2837
2875
  var _this13 = this;
2838
2876
 
2839
- this.on("elechart_updated", function () {
2840
- return _this13._chart._registerCheckPoint(props);
2877
+ this.on("elechart_init", function () {
2878
+ return _this13._chart._registerAreaPath(props);
2841
2879
  });
2842
2880
  },
2843
2881
 
2844
2882
  /**
2845
- * Add chart profile to diagram
2883
+ * Add chart grid to diagram
2846
2884
  */
2847
- _registerAreaPath: function _registerAreaPath(props) {
2885
+ _registerAxisGrid: function _registerAxisGrid(props) {
2848
2886
  var _this14 = this;
2849
2887
 
2850
- this.on("elechart_init", function () {
2851
- return _this14._chart._registerAreaPath(props);
2888
+ this.on("elechart_axis", function () {
2889
+ return _this14._chart._registerAxisGrid(props);
2852
2890
  });
2853
2891
  },
2854
2892
 
2855
2893
  /**
2856
- * Add chart grid to diagram
2894
+ * Add chart axis to diagram
2857
2895
  */
2858
- _registerAxisGrid: function _registerAxisGrid(props) {
2896
+ _registerAxisScale: function _registerAxisScale(props) {
2859
2897
  var _this15 = this;
2860
2898
 
2861
2899
  this.on("elechart_axis", function () {
2862
- return _this15._chart._registerAxisGrid(props);
2900
+ return _this15._chart._registerAxisScale(props);
2863
2901
  });
2864
2902
  },
2865
2903
 
2866
2904
  /**
2867
- * Add chart axis to diagram
2905
+ * Add a point of interest over the diagram
2868
2906
  */
2869
- _registerAxisScale: function _registerAxisScale(props) {
2907
+ _registerCheckPoint: function _registerCheckPoint(props) {
2870
2908
  var _this16 = this;
2871
2909
 
2872
- this.on("elechart_axis", function () {
2873
- 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);
2874
2963
  });
2875
2964
  },
2876
2965
 
@@ -2878,14 +2967,14 @@
2878
2967
  * Add chart or marker tooltip info
2879
2968
  */
2880
2969
  _registerTooltip: function _registerTooltip(props) {
2881
- var _this17 = this;
2970
+ var _this18 = this;
2882
2971
 
2883
2972
  if (props.chart) {
2884
2973
  var label = L.extend({}, props, {
2885
2974
  value: props.chart
2886
2975
  });
2887
2976
  this.on("elechart_init", function () {
2888
- return _this17._chart._registerTooltip(label);
2977
+ return _this18._chart._registerTooltip(label);
2889
2978
  });
2890
2979
  }
2891
2980
 
@@ -2895,7 +2984,7 @@
2895
2984
  });
2896
2985
 
2897
2986
  this.on("elechart_marker", function () {
2898
- return _this17._marker._registerTooltip(_label);
2987
+ return _this18._marker._registerTooltip(_label);
2899
2988
  });
2900
2989
  }
2901
2990
  },
@@ -2904,10 +2993,10 @@
2904
2993
  * Add summary info to diagram
2905
2994
  */
2906
2995
  _registerSummary: function _registerSummary(props) {
2907
- var _this18 = this;
2996
+ var _this19 = this;
2908
2997
 
2909
2998
  this.on('elechart_summary', function () {
2910
- return _this18._summary._registerSummary(props);
2999
+ return _this19._summary._registerSummary(props);
2911
3000
  });
2912
3001
  },
2913
3002
 
@@ -2979,14 +3068,14 @@
2979
3068
  },
2980
3069
 
2981
3070
  /**
2982
- * Collapse or Expand current chart control.
3071
+ * Collapse or Expand chart control.
2983
3072
  */
2984
3073
  _toggle: function _toggle() {
2985
3074
  if (hasClass(this._container, "elevation-expanded")) this._collapse();else this._expand();
2986
3075
  },
2987
3076
 
2988
3077
  /**
2989
- * Sets the view of the map (center and zoom). Useful when "followMarker" is true.
3078
+ * Update map center and zoom (followMarker: true)
2990
3079
  */
2991
3080
  _setMapView: function _setMapView(item) {
2992
3081
  if (!this.options.followMarker || !this._map) return;
@@ -3012,14 +3101,14 @@
3012
3101
  * Toggle chart data on legend click
3013
3102
  */
3014
3103
  _toggleChartHandler: function _toggleChartHandler(e) {
3015
- var _this19 = this;
3104
+ var _this20 = this;
3016
3105
 
3017
3106
  var name = e.name,
3018
3107
  enabled = e.enabled;
3019
3108
  this._chartEnabled = this._chart._hasActiveLayers(); // toggle layer visibility on empty chart
3020
3109
 
3021
3110
  this._layers.eachLayer(function (layer) {
3022
- 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);
3023
3112
  }); // toggle option value (eg. altitude = { 'disabled' || 'disabled' })
3024
3113
 
3025
3114
 
@@ -3039,10 +3128,8 @@
3039
3128
  if (
3040
3129
  /*!this._data.length ||*/
3041
3130
  !this._chart || !this._container) return;
3042
-
3043
- this._fireEvt("elechart_axis");
3044
-
3045
- this._fireEvt("elechart_area");
3131
+ this.fire("elechart_axis");
3132
+ this.fire("elechart_area");
3046
3133
 
3047
3134
  this._chart.update({
3048
3135
  data: this._data,
@@ -3051,8 +3138,7 @@
3051
3138
 
3052
3139
  this._x = this._chart._x;
3053
3140
  this._y = this._chart._y;
3054
-
3055
- this._fireEvt('elechart_updated');
3141
+ this.fire('elechart_updated');
3056
3142
  },
3057
3143
 
3058
3144
  /*
@@ -3093,12 +3179,14 @@
3093
3179
  * Update chart summary.
3094
3180
  */
3095
3181
  _updateSummary: function _updateSummary() {
3096
- var _this20 = this;
3182
+ var _this21 = this;
3097
3183
 
3098
3184
  this._summary.reset();
3099
3185
 
3100
3186
  if (this.options.summary) {
3101
- this._fireEvt("elechart_summary");
3187
+ this.fire("elechart_summary");
3188
+
3189
+ this._summary.update();
3102
3190
  }
3103
3191
 
3104
3192
  if (this.options.downloadLink && this._downloadURL) {
@@ -3108,19 +3196,19 @@
3108
3196
  select('.download a', this._summary._container).onclick = function (e) {
3109
3197
  e.preventDefault();
3110
3198
  var event = {
3111
- downloadLink: _this20.options.downloadLink,
3112
- confirm: saveFile.bind(_this20, _this20._downloadURL)
3199
+ downloadLink: _this21.options.downloadLink,
3200
+ confirm: saveFile.bind(_this21, _this21._downloadURL)
3113
3201
  };
3114
3202
 
3115
- if (_this20.options.downloadLink == 'modal' && typeof CustomEvent === "function") {
3203
+ if (_this21.options.downloadLink == 'modal' && typeof CustomEvent === "function") {
3116
3204
  document.dispatchEvent(new CustomEvent("eletrack_download", {
3117
3205
  detail: event
3118
3206
  }));
3119
- } else if (_this20.options.downloadLink == 'link' || _this20.options.downloadLink === true) {
3207
+ } else if (_this21.options.downloadLink == 'link' || _this21.options.downloadLink === true) {
3120
3208
  event.confirm();
3121
3209
  }
3122
3210
 
3123
- _this20._fireEvt('eletrack_download', event);
3211
+ _this21.fire('eletrack_download', event);
3124
3212
  };
3125
3213
  }
3126
3214
  },
@@ -3152,119 +3240,8 @@
3152
3240
  });
3153
3241
 
3154
3242
  Elevation.addInitHook(function () {
3155
- var opts = this.options;
3156
- var altitude = {};
3157
-
3158
- if (opts.imperial) {
3159
- opts.altitudeFactor = this.__footFactor;
3160
- altitude.label = "ft";
3161
- } else {
3162
- opts.altitudeFactor = opts.heightFactor || opts.altitudeFactor || 1;
3163
- altitude.label = opts.yLabel;
3164
- }
3165
-
3166
- this.on("eledata_updated", function (e) {
3167
- var data = this._data;
3168
- var i = e.index;
3169
- var z = data[i].z * opts.altitudeFactor;
3170
- var track = this.track_info;
3171
- var zMax = track.elevation_max || -Infinity;
3172
- var zMin = track.elevation_min || +Infinity; // check and fix missing elevation data on last added point
3173
-
3174
- if (!this.options.skipNullZCoords && i > 0) {
3175
- var prevZ = data[i - 1].z;
3176
-
3177
- if (isNaN(prevZ)) {
3178
- var lastZ = this._lastValidZ;
3179
- var currZ = z;
3180
-
3181
- if (!isNaN(lastZ) && !isNaN(currZ)) {
3182
- prevZ = (lastZ + currZ) / 2;
3183
- } else if (!isNaN(lastZ)) {
3184
- prevZ = lastZ;
3185
- } else if (!isNaN(currZ)) {
3186
- prevZ = currZ;
3187
- }
3188
-
3189
- if (!isNaN(prevZ)) return data.splice(i - 1, 1);
3190
- data[i - 1].z = prevZ;
3191
- }
3192
- } // skip point if it has not elevation
3193
-
3194
-
3195
- if (!isNaN(z)) {
3196
- this._lastValidZ = z;
3197
- }
3198
-
3199
- track.elevation_max = z > zMax ? z : zMax;
3200
- track.elevation_min = z < zMin ? z : zMin;
3201
- data[i].z = z;
3202
- });
3203
- this.on("elechart_axis", function () {
3204
- this._chart._registerAxisGrid({
3205
- axis: "y",
3206
- position: "left",
3207
- scale: this._chart._y
3208
- });
3209
- });
3210
-
3211
- if (this.options.altitude != "summary") {
3212
- this.on("elechart_axis", function () {
3213
- this._chart._registerAxisScale({
3214
- axis: "y",
3215
- position: "left",
3216
- scale: this._chart._y,
3217
- label: altitude.label,
3218
- labelX: -3,
3219
- labelY: -8,
3220
- name: "altitude"
3221
- });
3222
- });
3223
- this.on("elechart_init", function () {
3224
- var theme = this.options.theme.replace('-theme', '');
3225
- var color = Colors[theme] || {};
3226
-
3227
- this._chart._registerAreaPath({
3228
- name: 'altitude',
3229
- label: 'Altitude',
3230
- scaleX: 'distance',
3231
- scaleY: 'altitude',
3232
- color: color.area || theme,
3233
- strokeColor: this.options.detached ? color.stroke : '#000',
3234
- strokeOpacity: "1",
3235
- fillOpacity: this.options.detached ? color.alpha || '0.8' : 1,
3236
- preferCanvas: this.options.preferCanvas
3237
- });
3238
- });
3239
- }
3240
-
3241
- this._registerTooltip({
3242
- name: 'y',
3243
- chart: function chart(item) {
3244
- return L._("y: ") + d3.format("." + opts.decimalsY + "f")(item[opts.yAttr]) + " " + altitude.label;
3245
- },
3246
- marker: function marker(item) {
3247
- return d3.format("." + opts.decimalsY + "f")(item[opts.yAttr]) + " " + altitude.label;
3248
- }
3249
- });
3250
-
3251
- this._registerSummary({
3252
- "maxele": {
3253
- label: "Max Elevation: ",
3254
- value: function value(track) {
3255
- return (track.elevation_max || 0).toFixed(2) + '&nbsp;' + altitude.label;
3256
- }
3257
- },
3258
- "minele": {
3259
- label: "Min Elevation: ",
3260
- value: function value(track) {
3261
- return (track.elevation_min || 0).toFixed(2) + '&nbsp;' + altitude.label;
3262
- }
3263
- }
3264
- });
3265
- });
3243
+ var _this = this;
3266
3244
 
3267
- Elevation.addInitHook(function () {
3268
3245
  var opts = this.options;
3269
3246
  var distance = {};
3270
3247
 
@@ -3276,50 +3253,49 @@
3276
3253
  distance.label = opts.xLabel;
3277
3254
  }
3278
3255
 
3279
- this.on("eledata_updated", function (e) {
3280
- var data = this._data;
3281
- var i = e.index;
3282
- var track = this.track_info;
3283
- var dist = track.distance || 0;
3284
- var curr = data[i].latlng;
3285
- var prev = i > 0 ? data[i - 1].latlng : curr;
3286
- var delta = curr.distanceTo(prev) * opts.distanceFactor;
3287
- dist += Math.round(delta / 1000 * 100000) / 100000; // handles floating points calc
3288
-
3289
- track.distance = dist;
3290
- data[i].dist = dist;
3291
- });
3292
- this.on("elechart_axis", function () {
3293
- this._chart._registerAxisGrid({
3294
- axis: "x",
3295
- position: "bottom",
3296
- scale: this._chart._x
3297
- });
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
+ }
3298
3269
  });
3299
3270
 
3300
3271
  if (this.options.distance != "summary") {
3301
- this.on("elechart_axis", function () {
3302
- var _this = this;
3303
-
3304
- this._chart._registerAxisScale({
3305
- axis: "x",
3306
- position: "bottom",
3307
- scale: this._chart._x,
3308
- label: distance.label,
3309
- labelY: 25,
3310
- labelX: function labelX() {
3311
- return _this._width() + 6;
3312
- },
3313
- name: "distance"
3314
- });
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"
3315
3283
  });
3316
3284
  }
3317
3285
 
3286
+ this._registerAxisGrid({
3287
+ axis: "x",
3288
+ position: "bottom",
3289
+ scale: "x" // this._chart._x,
3290
+
3291
+ });
3292
+
3318
3293
  this._registerTooltip({
3319
3294
  name: 'x',
3320
3295
  chart: function chart(item) {
3321
3296
  return L._("x: ") + d3.format("." + opts.decimalsX + "f")(item[opts.xAttr]) + " " + distance.label;
3322
- }
3297
+ },
3298
+ order: 20
3323
3299
  });
3324
3300
 
3325
3301
  this._registerSummary({
@@ -3327,7 +3303,8 @@
3327
3303
  label: "Total Length: ",
3328
3304
  value: function value(track) {
3329
3305
  return (track.distance || 0).toFixed(2) + '&nbsp;' + distance.label;
3330
- }
3306
+ },
3307
+ order: 10
3331
3308
  }
3332
3309
  });
3333
3310
  });
@@ -3343,7 +3320,7 @@
3343
3320
  * Common AVG speeds:
3344
3321
  * ----------------------
3345
3322
  * slow walk = 1.8 km/h
3346
- * walking = 3.6 km/h
3323
+ * walking = 3.6 km/h <-- default: 3.6
3347
3324
  * running = 10.8 km/h
3348
3325
  * cycling = 18 km/h
3349
3326
  * driving = 72 km/h
@@ -3370,6 +3347,49 @@
3370
3347
  return formatTime(t).split("'")[0];
3371
3348
  };
3372
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
+
3373
3393
  if (opts.time && opts.time != "summary" && !L.Browser.mobile) {
3374
3394
  this._registerAxisScale({
3375
3395
  axis: "x",
@@ -3395,38 +3415,13 @@
3395
3415
  });
3396
3416
  }
3397
3417
 
3398
- this.on('elepoint_added', function (e) {
3399
- var data = this._data;
3400
- var i = e.index; // Add missing timestamps (see: options.timeAVGSpeed)
3401
-
3402
- if (!e.point.meta || !e.point.meta.time) {
3403
- e.point.meta = e.point.meta || {};
3404
- var delta = data[i].dist - data[i > 0 ? i - 1 : i].dist;
3405
- var speed = this._timeAVGSpeed;
3406
- e.point.meta.time = new Date(i > 0 ? data[i - 1].time.getTime() + delta / speed * opts.timeFactor * 1000 : Date.now());
3407
- }
3408
-
3409
- var time = e.point.meta.time; // Handle timezone offset
3410
-
3411
- if (time.getTime() - time.getTimezoneOffset() * 60 * 1000 === 0) {
3412
- time = 0;
3413
- }
3414
-
3415
- var currT = time;
3416
- var prevT = i > 0 ? data[i - 1].time : currT;
3417
- var deltaT = Math.abs(currT - prevT);
3418
- var duration = (this.track_info.time || 0) + deltaT;
3419
- this.track_info.time = duration;
3420
- data[i].time = time;
3421
- data[i].duration = duration;
3422
- });
3423
-
3424
3418
  if (this.options.timestamps) {
3425
3419
  this._registerTooltip({
3426
3420
  name: 'date',
3427
3421
  chart: function chart(item) {
3428
3422
  return L._("t: ") + _this.options.timeFormat(item.time);
3429
- }
3423
+ },
3424
+ order: 20
3430
3425
  });
3431
3426
  }
3432
3427
 
@@ -3435,7 +3430,8 @@
3435
3430
  name: 'time',
3436
3431
  chart: function chart(item) {
3437
3432
  return L._("T: ") + formatTime(item.duration || 0);
3438
- }
3433
+ },
3434
+ order: 20
3439
3435
  });
3440
3436
 
3441
3437
  this._registerSummary({
@@ -3443,7 +3439,8 @@
3443
3439
  label: "Total Time: ",
3444
3440
  value: function value(track) {
3445
3441
  return formatTime(track.time || 0);
3446
- }
3442
+ },
3443
+ order: 20
3447
3444
  }
3448
3445
  });
3449
3446
  }
@@ -3452,80 +3449,208 @@
3452
3449
  Elevation.addInitHook(function () {
3453
3450
  var _this = this;
3454
3451
 
3455
- if (!this.options.slope) return;
3456
3452
  var opts = this.options;
3457
- var slope = {};
3458
- slope.label = opts.slopeLabel || '%';
3453
+ var altitude = {};
3454
+ var theme = opts.theme.replace('-theme', '');
3455
+ var color = Colors[theme] || {};
3459
3456
 
3460
- if (this.options.slope != "summary") {
3461
- this._registerAxisScale({
3462
- axis: "y",
3463
- position: "right",
3464
- scale: {
3465
- min: -1,
3466
- 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;
3467
3551
  },
3468
- tickPadding: 16,
3469
- label: slope.label,
3470
- labelX: 25,
3471
- labelY: -8,
3472
- name: 'slope'
3473
- });
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
+ });
3474
3570
 
3475
- this._registerAreaPath({
3476
- name: 'slope',
3477
- label: 'Slope',
3478
- yAttr: 'slope',
3479
- scaleX: 'distance',
3480
- scaleY: 'slope',
3481
- color: '#F00',
3482
- strokeColor: '#000',
3483
- strokeOpacity: "0.5",
3484
- fillOpacity: "0.25"
3485
- });
3486
- }
3571
+ Elevation.addInitHook(function () {
3572
+ var _this = this;
3487
3573
 
3488
- this.on("eledata_updated", function (e) {
3489
- var data = this._data;
3490
- var i = e.index;
3491
- var z = data[i].z;
3492
- 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 || '%';
3493
3578
 
3494
- var track = this.track_info;
3495
- 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
3496
3596
 
3497
- var tDes = track.descent || 0; // Total Descent
3597
+ _this.track_info.descent = _this.track_info.descent || 0; // Total Descent
3498
3598
 
3499
- var sMax = track.slope_max || 0; // Slope Max
3599
+ _this.track_info.slope_max = _this.track_info.slope_max || -Infinity; // Slope Max
3500
3600
 
3501
- var sMin = track.slope_min || 0; // Slope Min
3601
+ _this.track_info.slope_min = _this.track_info.slope_min || +Infinity; // Slope Min
3502
3602
 
3503
- var slope = 0;
3603
+ _this.track_info.slope_avg = _this.track_info.slope_avg || 0; // Acceleration Avg
3504
3604
 
3505
- if (!isNaN(z)) {
3506
- var deltaZ = i > 0 ? z - data[i - 1].z : 0;
3507
- 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.
3508
3608
 
3509
- if (delta !== 0) slope = deltaZ / delta * 100;
3510
- } // 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;
3511
3612
 
3613
+ if (Math.abs(delta) > deltaMax) {
3614
+ slope = data[i - 1].slope + deltaMax * Math.sign(delta);
3615
+ }
3616
+ } // Range of acceptable slope values.
3512
3617
 
3513
- if (this.options.sDeltaMax) {
3514
- var deltaS = i > 0 ? slope - data[i - 1].slope : 0;
3515
- var maxDeltaS = this.options.sDeltaMax;
3516
3618
 
3517
- if (Math.abs(deltaS) > maxDeltaS) {
3518
- slope = data[i - 1].slope + maxDeltaS * Math.sign(deltaS);
3519
- }
3520
- } // 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
+ });
3521
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
+ });
3522
3642
 
3523
- slope = clamp(slope, this.options.sRange);
3524
- track.ascent = tAsc;
3525
- track.descent = tDes;
3526
- track.slope_max = slope > sMax ? slope : sMax;
3527
- track.slope_min = slope < sMin ? slope : sMin;
3528
- 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"
3529
3654
  });
3530
3655
 
3531
3656
  this._registerTooltip({
@@ -3535,7 +3660,8 @@
3535
3660
  },
3536
3661
  marker: function marker(item) {
3537
3662
  return Math.round(item.slope) + slope.label;
3538
- }
3663
+ },
3664
+ order: 40
3539
3665
  });
3540
3666
 
3541
3667
  this._registerSummary({
@@ -3543,36 +3669,89 @@
3543
3669
  label: "Total Ascent: ",
3544
3670
  value: function value(track) {
3545
3671
  return Math.round(track.ascent || 0) + '&nbsp;' + (_this.options.imperial ? 'ft' : 'm');
3546
- }
3672
+ },
3673
+ order: 40
3547
3674
  },
3548
3675
  "descent": {
3549
3676
  label: "Total Descent: ",
3550
3677
  value: function value(track) {
3551
3678
  return Math.round(track.descent || 0) + '&nbsp;' + (_this.options.imperial ? 'ft' : 'm');
3552
- }
3679
+ },
3680
+ order: 40
3553
3681
  },
3554
3682
  "minslope": {
3555
3683
  label: "Min Slope: ",
3556
3684
  value: function value(track) {
3557
3685
  return Math.round(track.slope_min || 0) + '&nbsp;' + slope.label;
3558
- }
3686
+ },
3687
+ order: 40
3559
3688
  },
3560
3689
  "maxslope": {
3561
3690
  label: "Max Slope: ",
3562
3691
  value: function value(track) {
3563
3692
  return Math.round(track.slope_max || 0) + '&nbsp;' + slope.label;
3564
- }
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
3565
3702
  }
3566
3703
  });
3567
3704
  });
3568
3705
 
3569
3706
  Elevation.addInitHook(function () {
3707
+ var _this = this;
3708
+
3570
3709
  if (!this.options.speed && !this.options.acceleration) return;
3571
3710
  var opts = this.options;
3572
3711
  var speed = {};
3573
3712
  speed.label = opts.speedLabel || L._(opts.imperial ? 'mph' : 'km/h');
3574
3713
  opts.speedFactor = opts.speedFactor || 1;
3575
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
+
3576
3755
  if (this.options.speed && this.options.speed != "summary") {
3577
3756
  this._registerAxisScale({
3578
3757
  axis: "y",
@@ -3601,44 +3780,6 @@
3601
3780
  });
3602
3781
  }
3603
3782
 
3604
- this.on('elepoint_added', function (e) {
3605
- var data = this._data;
3606
- var i = e.index;
3607
- var currT = data[i].time;
3608
- var prevT = i > 0 ? data[i - 1].time : currT;
3609
- var deltaT = currT - prevT;
3610
- var track = this.track_info;
3611
- var sMax = track.speed_max || -Infinity; // Speed Max
3612
-
3613
- var sMin = track.speed_min || +Infinity; // Speed Min
3614
-
3615
- var sAvg = track.speed_avg || 0; // Speed Avg
3616
-
3617
- var speed = 0;
3618
-
3619
- if (deltaT > 0) {
3620
- var delta = (data[i].dist - data[i > 0 ? i - 1 : i].dist) * 1000;
3621
- speed = Math.abs(delta / deltaT * opts.timeFactor) * opts.speedFactor;
3622
- } // Try to smooth "crazy" speed values.
3623
-
3624
-
3625
- if (this.options.speedDeltaMax) {
3626
- var deltaS = i > 0 ? speed - data[i - 1].speed : 0;
3627
- var maxDeltaS = this.options.speedDeltaMax;
3628
-
3629
- if (Math.abs(deltaS) > maxDeltaS) {
3630
- speed = data[i - 1].speed + maxDeltaS * Math.sign(deltaS);
3631
- }
3632
- } // Range of acceptable speed values.
3633
-
3634
-
3635
- speed = clamp(speed, this.options.speedRange);
3636
- track.speed_max = speed > sMax ? speed : sMax;
3637
- track.speed_min = speed < sMin ? speed : sMin;
3638
- track.speed_avg = (speed + sAvg) / 2.0;
3639
- data[i].speed = L.Util.formatNum(speed, 2);
3640
- });
3641
-
3642
3783
  if (this.options.speed) {
3643
3784
  this._registerTooltip({
3644
3785
  name: 'speed',
@@ -3647,7 +3788,8 @@
3647
3788
  },
3648
3789
  marker: function marker(item) {
3649
3790
  return Math.round(item.speed) + " " + speed.label;
3650
- }
3791
+ },
3792
+ order: 50
3651
3793
  });
3652
3794
 
3653
3795
  this._registerSummary({
@@ -3655,31 +3797,76 @@
3655
3797
  label: "Min Speed: ",
3656
3798
  value: function value(track) {
3657
3799
  return Math.round(track.speed_min || 0) + '&nbsp;' + speed.label;
3658
- }
3800
+ },
3801
+ order: 50
3659
3802
  },
3660
3803
  "maxspeed": {
3661
3804
  label: "Max Speed: ",
3662
3805
  value: function value(track) {
3663
3806
  return Math.round(track.speed_max || 0) + '&nbsp;' + speed.label;
3664
- }
3807
+ },
3808
+ order: 50
3665
3809
  },
3666
3810
  "avgspeed": {
3667
3811
  label: "Avg Speed: ",
3668
3812
  value: function value(track) {
3669
3813
  return Math.round(track.speed_avg || 0) + '&nbsp;' + speed.label;
3670
- }
3814
+ },
3815
+ order: 50
3671
3816
  }
3672
3817
  });
3673
3818
  }
3674
3819
  });
3675
3820
 
3676
3821
  Elevation.addInitHook(function () {
3822
+ var _this = this;
3823
+
3677
3824
  if (!this.options.acceleration) return;
3678
3825
  var opts = this.options;
3679
3826
  var acceleration = {};
3680
3827
  acceleration.label = opts.accelerationLabel || L._(opts.imperial ? 'ft/s²' : 'm/s²');
3681
3828
  opts.accelerationFactor = opts.accelerationFactor || 1;
3682
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
+
3683
3870
  if (this.options.acceleration != "summary") {
3684
3871
  this._registerAxisScale({
3685
3872
  axis: "y",
@@ -3708,46 +3895,6 @@
3708
3895
  });
3709
3896
  }
3710
3897
 
3711
- this.on('elepoint_added', function (e) {
3712
- var data = this._data;
3713
- var i = e.index;
3714
- var currT = data[i].time;
3715
- var prevT = i > 0 ? data[i - 1].time : currT;
3716
- var deltaT = (currT - prevT) / 1000;
3717
- var track = this.track_info;
3718
- var sMax = track.acceleration_max || -Infinity; // Acceleration Max
3719
-
3720
- var sMin = track.acceleration_min || +Infinity; // Acceleration Min
3721
-
3722
- var sAvg = track.acceleration_avg || 0; // Acceleration Avg
3723
-
3724
- var acceleration = 0;
3725
-
3726
- if (deltaT > 0) {
3727
- var curr = data[i].speed;
3728
- var prev = i > 0 ? data[i - 1].speed : curr;
3729
- var delta = (curr - prev) * (1000 / opts.timeFactor);
3730
- acceleration = Math.abs(delta / deltaT) * opts.accelerationFactor;
3731
- } // Try to smooth "crazy" acceleration values.
3732
-
3733
-
3734
- if (this.options.accelerationDeltaMax) {
3735
- var deltaA = i > 0 ? acceleration - data[i - 1].acceleration : 0;
3736
- var maxDeltaS = this.options.accelerationDeltaMax;
3737
-
3738
- if (Math.abs(deltaA) > maxDeltaS) {
3739
- acceleration = data[i - 1].acceleration + maxDeltaS * Math.sign(deltaA);
3740
- }
3741
- } // Range of acceptable acceleration values.
3742
-
3743
-
3744
- acceleration = clamp(acceleration, this.options.accelerationRange);
3745
- track.acceleration_max = acceleration > sMax ? acceleration : sMax;
3746
- track.acceleration_min = acceleration < sMin ? acceleration : sMin;
3747
- track.acceleration_avg = (acceleration + sAvg) / 2.0;
3748
- data[i].acceleration = L.Util.formatNum(acceleration, 2);
3749
- });
3750
-
3751
3898
  this._registerTooltip({
3752
3899
  name: 'acceleration',
3753
3900
  chart: function chart(item) {
@@ -3755,7 +3902,8 @@
3755
3902
  },
3756
3903
  marker: function marker(item) {
3757
3904
  return Math.round(item.acceleration) + " " + acceleration.label;
3758
- }
3905
+ },
3906
+ order: 60
3759
3907
  });
3760
3908
 
3761
3909
  this._registerSummary({
@@ -3763,19 +3911,22 @@
3763
3911
  label: "Min Acceleration: ",
3764
3912
  value: function value(track) {
3765
3913
  return Math.round(track.acceleration_min || 0) + '&nbsp;' + acceleration.label;
3766
- }
3914
+ },
3915
+ order: 60
3767
3916
  },
3768
3917
  "maxacceleration": {
3769
3918
  label: "Max Acceleration: ",
3770
3919
  value: function value(track) {
3771
3920
  return Math.round(track.acceleration_max || 0) + '&nbsp;' + acceleration.label;
3772
- }
3921
+ },
3922
+ order: 60
3773
3923
  },
3774
3924
  "avgacceleration": {
3775
3925
  label: "Avg Acceleration: ",
3776
3926
  value: function value(track) {
3777
3927
  return Math.round(track.acceleration_avg || 0) + '&nbsp;' + acceleration.label;
3778
- }
3928
+ },
3929
+ order: 60
3779
3930
  }
3780
3931
  });
3781
3932
  });