PageSourceSearch

https://www.terrainscouts.com/Scripts/WebpageFunctions/StravaMapping.js?version=3.1.0

js terrainscouts.com collected 2026-10-08 10:29:36 UTC 78,257 bytes, 2,147 lines download raw bytes

1//Set API to use - not needed here.  See General Functions for API Selection
2//var apiBaseURL = "https://api.terrainscouts.com";
3
4//var urlBase = new URL(window.location.href);
5//if (urlBase.hostname == 'rc-home.terrainscouts.com' || urlBase.hostname == 'demo1.terrainscouts.com' || urlBase.hostname == 'demo2.terrainscouts.com' || urlBase.hostname == 'demo3.terrainscouts.com' || urlBase.hostname == 'releasecandidate.terrainscouts.com' || urlBase.hostname == 'localhost') {
6//    apiBaseURL = "https://terrainscoutsapi-releasecandidate.azurewebsites.net";
7//    //apiBaseURL = "https://localhost:7214";
8//}
9
10
11//Default Mapbox Map
12var mapboxStylesURL = 'mapbox://styles/soldemeyer/ckr8dpk8k48sh17qy1wacry9m';
13var mapboxAccessToken = 'pk.eyJ1Ijoic29sZGVtZXllciIsImEiOiJja2V5cTl5dDcwNGZmMnlsY25pN25vcWswIn0.EltqR3-Y19cHzy1QYfwRew';
14
15var secondaryMapboxStyleURL = 'mapbox://styles/soldemeyer/ckr8dqr0e0s8017myu5v45j7i';
16var secondaryMapboxAccessToken = 'pk.eyJ1Ijoic29sZGVtZXllciIsImEiOiJja2V5cTl5dDcwNGZmMnlsY25pN25vcWswIn0.EltqR3-Y19cHzy1QYfwRew';
17
18var SecondaryMapEnabled = false;
19
20//Popup variables
21var container = document.getElementById('popup');
22var content = document.getElementById('popup-content');
23var closer = document.getElementById('popup-closer');
24
25/**
26 * Create an overlay to anchor the popup to the map.
27 */
28var overlay = new ol.Overlay({
29    element: container,
30    autoPan: true,
31    autoPanAnimation: {
32        duration: 250,
33    },
34});
35
36/**
37 * Add a click handler to hide the popup.
38 * @return {boolean} Don't follow the href.
39 */
40closer.onclick = function () {
41    overlay.setPosition(undefined);
42    closer.blur();
43    return false;
44};
45
46
47//Full list of features
48var ListOfFeatures = [];
49
50//Get default border color
51var DefaultCSSBorderStyle = $('#map').css('border-left-style');
52var DefaultCSSBorderColor = $('#map').css('border-left-color');
53var DefaultCSSBorderWidth = $('#map').css('border-left-width');
54
55//Set Mapbox Map
56var MapURL = 'https://api.mapbox.com/styles/v1/soldemeyer/ckeyre8yp1i0j19plo89hcbvb/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1Ijoic29sZGVtZXllciIsImEiOiJja2V5cTl5dDcwNGZmMnlsY25pN25vcWswIn0.EltqR3-Y19cHzy1QYfwRew';
57var MapboxStyles = JSON.parse(document.currentScript.getAttribute('mapbox-style'));
58
59SecondaryMapEnabled = MapboxStyles.EnableSecondaryMap;
60
61if (MapboxStyles.MapboxStyleURL && MapboxStyles.MapboxAccessToken) {
62    MapURL = "https://api.mapbox.com/" + MapboxStyles.MapboxStyleURL.replace('mapbox://', '').replace('styles/', 'styles/v1/') + "/tiles/256/{z}/{x}/{y}?access_token=" + MapboxStyles.MapboxAccessToken;
63    mapboxStylesURL = MapboxStyles.MapboxStyleURL;
64    mapboxAccessToken = MapboxStyles.MapboxAccessToken;
65}
66
67//Set Secondary Mapbox Map
68var SecondaryMapURL = '';
69
70if (MapboxStyles.SecondaryMapboxStyleURL && MapboxStyles.SecondaryMapboxAccessToken) {
71    SecondaryMapURL = "https://api.mapbox.com/" + MapboxStyles.SecondaryMapboxStyleURL.replace('mapbox://', '').replace('styles/', 'styles/v1/') + "/tiles/256/{z}/{x}/{y}?access_token=" + MapboxStyles.SecondaryMapboxAccessToken;
72    secondaryMapboxStyleURL = MapboxStyles.SecondaryMapboxStyleURL;
73    secondaryMapboxAccessToken = MapboxStyles.SecondaryMapboxAccessToken;
74}
75
76//Secondary Map Toggle Button
77//secondaryMapToggle = function (opt_options) {
78//    var element = document.createElement('div');
79//    button.innerHTML = 'S';
80//    element.className = 'custom-control ol-unselectable ol-control';
81//    ol.control.Control.call(this, {
82//        element: element
83//    });
84//};
85//ol.inherits(secondaryMapToggle, ol.control.Control);
86
87class SecondaryMap extends ol.control.Control {
88    /**
89     * @param {Object} [opt_options] Control options.
90     */
91    constructor(opt_options) {
92        const options = opt_options || {};
93
94        const button = document.createElement('button');
95        button.innerHTML = '<i class="fas fa-globe-americas"></i>';
96
97        const element = document.createElement('div');
98        element.className = 'ol-secondary-map ol-unselectable ol-control';
99        if (SecondaryMapEnabled == false) {
100            element.classList.add("secondary-map-hidden");
101        }
102
103        element.appendChild(button);
104
105        super({
106            element: element,
107            target: options.target,
108        });
109
110        button.addEventListener('click', this.handleSecondaryMap.bind(this), false);
111    }
112
113    handleSecondaryMap() {
114        if (mbLayerSecondary.getZIndex() == 0) {
115            mbLayer.setZIndex(0);
116            mbLayerSecondary.setZIndex(1);
117            vectorLayer.setZIndex(2);
118
119            raster.setZIndex(0);
120            secondaryRaster.setZIndex(1);
121            vector.setZIndex(2);
122        }
123        else {
124            mbLayer.setZIndex(1);
125            mbLayerSecondary.setZIndex(0);
126            vectorLayer.setZIndex(2);
127
128            raster.setZIndex(1);
129            secondaryRaster.setZIndex(0);
130            vector.setZIndex(2);
131        }
132    }
133}
134
135class SegmentSecondaryMap extends ol.control.Control {
136    /**
137     * @param {Object} [opt_options] Control options.
138     */
139    constructor(opt_options) {
140        const options = opt_options || {};
141
142        const button = document.createElement('button');
143        button.innerHTML = '<i class="fas fa-globe-americas"></i>';
144
145        const element = document.createElement('div');
146        element.className = 'ol-secondary-map ol-unselectable ol-control';
147        if (SecondaryMapEnabled == false) {
148            element.classList.add("secondary-map-hidden");
149        }
150
151        element.appendChild(button);
152
153        super({
154            element: element,
155            target: options.target,
156        });
157
158        button.addEventListener('click', this.handleSegmentSecondaryMap.bind(this), false);
159    }
160
161    handleSegmentSecondaryMap() {
162        if (secondaryRaster.getZIndex() == 0) {
163            raster.setZIndex(0);
164            secondaryRaster.setZIndex(1);
165            vector.setZIndex(2);
166        }
167        else {
168            raster.setZIndex(1);
169            secondaryRaster.setZIndex(0);
170            vector.setZIndex(2);
171        }
172        event.preventDefault()
173    }
174}
175
176//Get all styles from mapping jsons
177var lineStyles = [];
178var lineStyleNames = [];
179var pointStyles = [];
180var pointStylesNames = [];
181var styles = new Object();
182
183$(".map-table .trail-data").each(function () {
184    if ($(this).attr('data-mappingjson') && $(this).attr('data-mappingjson') != null) {
185        var mappingJSON = JSON.parse($(this).attr('data-mappingjson'));
186        if (mappingJSON != null) {
187            mappingJSON.forEach(saveStyleJSON);
188        }
189    }
190});
191
192
193var eventID = "";
194if ($(".map-table").attr('data-eventid') && $(".map-table").attr('data-eventid') != null) {
195    eventID = $(".map-table").attr('data-eventid');
196}
197
198var enableHeatmap = false;
199if ($(".map-table").attr('data-enableheatmap') && $(".map-table").attr('data-enableheatmap') == "True") {
200    enableHeatmap = true;
201}
202
203
204if (document.currentScript.getAttribute('event-styles')) {
205    var eventStyles = JSON.parse(document.currentScript.getAttribute('event-styles'));
206    eventStyles.forEach(addAdditionalEventStyles);
207}
208
209lineStyles.forEach(createLineStyle);
210pointStyles.forEach(createPointStyle);
211
212function saveStyleJSON(item, index) {
213    if (item.PolylineStyle.StyleName && !lineStyleNames.includes(item.PolylineStyle.StyleName)) {
214        lineStyleNames.push(item.PolylineStyle.StyleName);
215        lineStyles.push(item.PolylineStyle);
216    }
217
218    if (item.PolylineHighlightedStyle.StyleName && !lineStyleNames.includes(item.PolylineHighlightedStyle.StyleName)) {
219        lineStyleNames.push(item.PolylineHighlightedStyle.StyleName);
220        lineStyles.push(item.PolylineHighlightedStyle);
221    }
222
223    if (item.PolylineStyle.ShowStartEndPoints == true) {
224        if (item.PolylineStyle.StartPointStyle.StyleName && !pointStylesNames.includes(item.PolylineStyle.StartPointStyle.StyleName)) {
225            pointStylesNames.push(item.PolylineStyle.StartPointStyle.StyleName);
226            pointStyles.push(item.PolylineStyle.StartPointStyle);
227        }
228
229        if (item.PolylineStyle.EndPointStyle.StyleName && !pointStylesNames.includes(item.PolylineStyle.EndPointStyle.StyleName)) {
230            pointStylesNames.push(item.PolylineStyle.EndPointStyle.StyleName);
231            pointStyles.push(item.PolylineStyle.EndPointStyle);
232        }
233    }
234
235    if (item.PolylineHighlightedStyle.ShowStartEndPoints == true) {
236        if (item.PolylineHighlightedStyle.StartPointStyle.StyleName && !pointStylesNames.includes(item.PolylineHighlightedStyle.StartPointStyle.StyleName)) {
237            pointStylesNames.push(item.PolylineHighlightedStyle.StartPointStyle.StyleName);
238            pointStyles.push(item.PolylineHighlightedStyle.StartPointStyle);
239        }
240
241        if (item.PolylineHighlightedStyle.EndPointStyle.StyleName && !pointStylesNames.includes(item.PolylineHighlightedStyle.EndPointStyle.StyleName)) {
242            pointStylesNames.push(item.PolylineHighlightedStyle.EndPointStyle.StyleName);
243            pointStyles.push(item.PolylineHighlightedStyle.EndPointStyle);
244        }
245    }
246};
247
248function addAdditionalEventStyles(item, index) {
249    if (item.StyleName && !lineStyleNames.includes(item.StyleName)) {
250        lineStyleNames.push(item.StyleName);
251        lineStyles.push(item);
252    }
253
254    if (item.ShowStartEndPoints == true) {
255        if (item.StartPointStyle.StyleName && !pointStylesNames.includes(item.StartPointStyle.StyleName)) {
256            pointStylesNames.push(item.StartPointStyle.StyleName);
257            pointStyles.push(item.StartPointStyle);
258        }
259
260        if (item.EndPointStyle.StyleName && !pointStylesNames.includes(item.EndPointStyle.StyleName)) {
261            pointStylesNames.push(item.EndPointStyle.StyleName);
262            pointStyles.push(item.EndPointStyle);
263        }
264    }
265};
266
267function createLineStyle(item, index) {
268    //Color variables for styles
269    var ColorHex = "";
270
271    if (!item.ColorHex.includes('#')) {
272        ColorHex = '#' + item.ColorHex;
273    }
274    else {
275        ColorHex = item.ColorHex;
276    }
277
278    var Opacity = item.Opacity;
279    var Color = ol.color.asArray(ColorHex);
280    Color = Color.slice();
281    Color[3] = Opacity;
282
283    var FillColor = ol.color.asArray(ColorHex);
284    FillColor = FillColor.slice();
285    FillColor[3] = 0.3;
286    //LineDash value
287    var LineDashArray = [4];
288    if (item.LineDash == "null" || item.LineDash == null) {
289        LineDashArray = null;
290    }
291
292    //Create Route Style
293    var route = new ol.style.Style({
294        stroke: new ol.style.Stroke({
295            width: item.LineWidth,
296            color: Color,
297            lineDash: LineDashArray
298        }),
299        fill: new ol.style.Fill({
300            color: FillColor
301        })
302    });
303
304    //Add to style object
305    styles[item.StyleName] = route;
306};
307
308function createPointStyle(item, index) {
309    //Color variables for fill color
310    var FillColorHex = "";
311    if (!item.FillColorHex.includes('#')) {
312        FillColorHex = '#' + item.FillColorHex;
313    }
314    else {
315        FillColorHex = item.FillColorHex;
316    }
317
318    
319    var Opacity = item.Opacity;
320    var FillColor = ol.color.asArray(FillColorHex);
321    FillColor = FillColor.slice();
322    FillColor[3] = Opacity;
323
324    //Color variables for stroke color
325    var StrokeColorHex = "";
326    if (!item.StrokeColorHex.includes('#')) {
327        StrokeColorHex = '#' + item.StrokeColorHex;
328    }
329    else {
330        StrokeColorHex = item.StrokeColorHex;
331    }
332    var Opacity = item.Opacity;
333    var StrokeColor = ol.color.asArray(StrokeColorHex);
334    StrokeColor = StrokeColor.slice();
335    StrokeColor[3] = Opacity;
336
337    //Create point geomarker
338    var geoMarkerCircleFill = new ol.style.Fill({
339        color: FillColor
340    });
341
342    var geoMarkerCircle = new ol.style.Circle({
343        radius: item.Radius,
344        snapToPixel: false,
345        fill: geoMarkerCircleFill,
346        stroke: new ol.style.Stroke({
347            color: StrokeColor,
348            width: item.StrokeWidth
349        })
350    });
351
352    var geoMarker = new ol.style.Style({
353        image: geoMarkerCircle
354    });
355
356    //Add to style object
357    styles[item.StyleName] = geoMarker;
358};
359
360//Get the polylines from the map-table class
361$(".map-table .trail-data").each(function () {
362    if ($(this).attr('data-mappingjson')) {
363        var mappingJSON = JSON.parse($(this).attr('data-mappingjson'));
364        if (mappingJSON != null) {
365            mappingJSON.forEach(function (item, index) {
366                createGeometry(item, index, false)
367            });
368        }
369    }
370
371});
372
373function createGeometry(item, index, highlighted) {
374    var styleName = "";
375    var startPointStyleName = "";
376    var endPointStyleName = "";
377    if (highlighted == true) {
378        styleName = item.PolylineHighlightedStyle.StyleName;
379    }
380    else {
381        styleName = item.PolylineStyle.StyleName;
382    }
383    //Only plot the polyline if it isn't null
384    if (item.Polyline != null) {
385        var route1 = "";
386        if (!item.Polyline.startsWith("MULTIPOLYGON")) {
387            route1 = (new ol.format.Polyline({
388                factor: 1e5
389            }).readGeometry(item.Polyline, {
390                dataProjection: 'EPSG:4326',
391                featureProjection: 'EPSG:3857'
392            }));
393        }
394        else {
395            route1 = (new ol.format.WKT({
396                factor: 1e5
397            }).readGeometry(item.Polyline, {
398                dataProjection: 'EPSG:4326',
399                featureProjection: 'EPSG:3857'
400            }));
401        }
402        var routeCoords1 = route1.getCoordinates();
403        var routeLength1 = routeCoords1.length;
404        var routeFeature1 = new ol.Feature({
405            type: styleName,
406            geometry: route1,
407            name: item.FeatureName,
408            comment: item.FeatureComment
409        });
410
411        if (item.PolylineStyle.ShowStartEndPoints == true) {
412            if (highlighted == true) {
413                startPointStyleName = item.PolylineHighlightedStyle.StartPointStyle.StyleName;
414                endPointStyleName = item.PolylineHighlightedStyle.EndPointStyle.StyleName;
415            }
416            else {
417                startPointStyleName = item.PolylineStyle.StartPointStyle.StyleName;
418                endPointStyleName = item.PolylineHighlightedStyle.EndPointStyle.StyleName;
419            }
420            var geoMarker1 = new ol.Feature({
421                type: startPointStyleName,
422                geometry: new ol.geom.Point(routeCoords1[0])
423            });
424            var geoMarkerEnd1 = new ol.Feature({
425                type: endPointStyleName,
426                geometry: new ol.geom.Point(routeCoords1[routeLength1 - 1])
427            });
428            //Set Feature Ids
429            routeFeature1.setId(item.Polyline + '-route');
430            geoMarker1.setId(item.Polyline + '-start');
431            geoMarkerEnd1.setId(item.Polyline + '-finish');
432
433            ListOfFeatures.push(routeFeature1, geoMarker1, geoMarkerEnd1)
434        }
435        else {
436            //Set Feature Ids
437            routeFeature1.setId(item.Polyline + '-route');
438
439            ListOfFeatures.push(routeFeature1)
440        }
441    }
442    
443}
444
445//Edit Polyline function for unfinished route
446function EditRoute(action, mappingJSON, highlighted = false, customLineStyleName = "", customStartPointStyle = "", customEndPointStyle = "") {
447    if (action == "add" && mappingJSON != null) {
448        mappingJSON.forEach(function (item, index) {
449            redrawGeometry(item, index, highlighted, customLineStyleName, customStartPointStyle, customEndPointStyle)
450        });
451    }
452    else if (action == "remove" && mappingJSON != null) {
453        mappingJSON.forEach(removeGeometry);
454    }
455};
456
457function redrawGeometry(item, index, highlighted = false, customLineStyleName = "", customStartPointStyle = "", customEndPointStyle = "") {
458    var styleName = "";
459    var startPointStyleName = "";
460    var endPointStyleName = "";
461    if (highlighted == true) {
462        styleName = item.PolylineHighlightedStyle.StyleName;
463    }
464    else {
465        styleName = item.PolylineStyle.StyleName;
466    }
467
468    if (customLineStyleName) {
469        styleName = customLineStyleName;
470    }
471
472    //Remove old version of route first if it is already created
473    var Source = vectorLayer.getSource();
474
475    var feature1 = Source.getFeatureById(item.Polyline + '-route');
476    var feature2 = Source.getFeatureById(item.Polyline + '-start');
477    var feature3 = Source.getFeatureById(item.Polyline + '-finish');
478    if (feature1 != null) {
479        Source.removeFeature(feature1);
480    }
481    if (feature2 != null) {
482        Source.removeFeature(feature2);
483    }
484    if (feature3 != null) {
485        Source.removeFeature(feature3);
486    }
487
488    //Add new version of route
489    if (item.Polyline != null) {
490        //var route1 = (new ol.format.Polyline({
491        //    factor: 1e5
492        //}).readGeometry(item.Polyline, {
493        //    dataProjection: 'EPSG:4326',
494        //    featureProjection: 'EPSG:3857'
495        //}));
496        var route1 = "";
497        if (!item.Polyline.startsWith("MULTIPOLYGON")) {
498            route1 = (new ol.format.Polyline({
499                factor: 1e5
500            }).readGeometry(item.Polyline, {
501                dataProjection: 'EPSG:4326',
502                featureProjection: 'EPSG:3857'
503            }));
504        }
505        else {
506            route1 = (new ol.format.WKT({
507                factor: 1e5
508            }).readGeometry(item.Polyline, {
509                dataProjection: 'EPSG:4326',
510                featureProjection: 'EPSG:3857'
511            }));
512        }
513        var routeCoords1 = route1.getCoordinates();
514        var routeLength1 = routeCoords1.length;
515        var featureName1 = item.FeatureName;
516
517        var StartRoutePoint = routeCoords1[0];
518        var EndRoutePoint = routeCoords1[routeLength1 - 1];
519
520        var routeFeature1 = new ol.Feature({
521            type: styleName,
522            geometry: route1,
523            name: featureName1,
524            comment: item.FeatureComment
525        });
526
527
528        //Set Feature Ids
529        routeFeature1.setId(item.Polyline + '-route');
530        Source.addFeature(routeFeature1);
531
532        if (item.PolylineStyle.ShowStartEndPoints == true || customStartPointStyle) {
533            if (highlighted == true) {
534                startPointStyleName = item.PolylineHighlightedStyle.StartPointStyle.StyleName;
535            }
536            else {
537                startPointStyleName = item.PolylineStyle.StartPointStyle.StyleName;
538            }
539            var geoMarker1 = new ol.Feature({
540                type: startPointStyleName,
541                geometry: new ol.geom.Point(StartRoutePoint)
542            });
543
544            if (customStartPointStyle) {
545                styleName = customStartPointStyle;
546            }
547
548            geoMarker1.setId(item.Polyline + '-start');
549            Source.addFeature(geoMarker1);
550        }
551
552        if (item.PolylineStyle.ShowStartEndPoints == true || customEndPointStyle) {
553            if (highlighted == true) {
554                endPointStyleName = item.PolylineHighlightedStyle.EndPointStyle.StyleName;
555            }
556            else {
557                endPointStyleName = item.PolylineHighlightedStyle.EndPointStyle.StyleName;
558            }
559
560            var geoMarkerEnd1 = new ol.Feature({
561                type: endPointStyleName,
562                geometry: new ol.geom.Point(EndRoutePoint)
563
564            });
565
566            if (customStartPointStyle) {
567                styleName = customEndPointStyle;
568            }
569
570            geoMarkerEnd1.setId(item.Polyline + '-finish');
571            Source.addFeature(geoMarkerEnd1);
572        }
573    }
574    
575}
576
577function removeGeometry(item, index) {
578    //Remove old version of route first if it is already created
579    var Source = vectorLayer.getSource();
580
581    var feature1 = Source.getFeatureById(item.Polyline + '-route');
582    var feature2 = Source.getFeatureById(item.Polyline + '-start');
583    var feature3 = Source.getFeatureById(item.Polyline + '-finish');
584    if (feature1 != null) {
585        Source.removeFeature(feature1);
586    }
587    if (feature2 != null) {
588        Source.removeFeature(feature2);
589    }
590    if (feature3 != null) {
591        Source.removeFeature(feature3);
592    }
593}
594
595$('.highlight-on-mouseover').mouseover(function () {
596    if ($(this).find('.trail-data').attr('data-mappingjson')) {
597        var action = "add";
598        var mappingJSON = JSON.parse($(this).find('.trail-data').attr('data-mappingjson'));
599        EditRoute(action, mappingJSON, true);
600    }
601})
602
603$('.highlight-on-mouseover').mouseout(function () {
604    if ($(this).find('.trail-data').attr('data-mappingjson')) {
605        var action = "add";
606        var mappingJSON = JSON.parse($(this).find('.trail-data').attr('data-mappingjson'));
607        EditRoute(action, mappingJSON, false);
608    }
609})
610
611//Zoom that extends to map and the onto new polyline
612$('.zoom-on-click').click(function () {
613    if ($(this).closest('.trail-data').attr('data-mappingjson')) {
614        var mappingJSON = JSON.parse($(this).closest('.trail-data').attr('data-mappingjson'));
615        var Source = vectorLayer.getSource();
616
617        var listOfRoutes = [];
618        mappingJSON.forEach(function (item, index) {
619            if (item.Polyline != null) {
620                //var route1 = new ol.format.Polyline({
621                //    factor: 1e5
622                //}).readGeometry(item.Polyline, {
623                //    dataProjection: 'EPSG:4326',
624                //    featureProjection: 'EPSG:3857'
625                //});
626                var route1 = "";
627                if (!item.Polyline.startsWith("MULTIPOLYGON")) {
628                    route1 = (new ol.format.Polyline({
629                        factor: 1e5
630                    }).readGeometry(item.Polyline, {
631                        dataProjection: 'EPSG:4326',
632                        featureProjection: 'EPSG:3857'
633                    }));
634                }
635                else {
636                    route1 = (new ol.format.WKT({
637                        factor: 1e5
638                    }).readGeometry(item.Polyline, {
639                        dataProjection: 'EPSG:4326',
640                        featureProjection: 'EPSG:3857'
641                    }));
642                }
643                listOfRoutes.push(route1);
644            }
645        });
646
647        //If there aren't any polylines to zoom to don't zoom
648        if (listOfRoutes.length > 0) {
649
650            var listOfViewFeatures = [];
651            listOfRoutes.forEach(function (item, index) {
652                var routeFeature1 = new ol.Feature({
653                    geometry: item,
654                })
655                listOfViewFeatures.push(routeFeature1);
656            });
657
658
659
660            var vectorSourceView = new ol.source.Vector({
661                features: listOfViewFeatures
662            });
663
664            var vectorLayerView = new ol.layer.Vector({
665                source: vectorSourceView,
666            });
667
668
669            var oldCenter = map.getView().getCenter();
670            var oldZoom = map.getView().getZoom();
671
672            map.getView().fit(
673                vectorLayer.getSource().getExtent(),
674                { padding: [30, 30, 30, 30] });
675
676            var fullCenter = view.getCenter();
677            var fullZoom = view.getZoom();
678
679
680            map.getView().fit(
681                vectorLayerView.getSource().getExtent(),
682                { padding: [70, 70, 70, 70] });
683
684            var newCenter = view.getCenter();
685            var newZoom = view.getZoom();
686
687            map.getView().setCenter(oldCenter);
688            map.getView().setZoom(oldZoom);
689
690            if ($(this).hasClass("zoom-out-on-click")) {
691                $('.zoom-on-click').removeClass("zoom-out-on-click");
692                $('.zoom-on-click').css({ "text-shadow": "" });
693
694                view.animate(
695                    {
696                        center: fullCenter,
697                        zoom: fullZoom,
698                        duration: 1000
699                    },
700                );
701
702                if (selected !== null) {
703                    selected.setStyle(undefined);
704                    selected = null;
705                    overlay.setPosition(undefined);
706                    closer.blur();
707                }
708            }
709            else {
710                $('.zoom-on-click').css({ "text-shadow": "" });
711                $('.zoom-on-click').removeClass("zoom-out-on-click");
712
713                function callback(complete) {
714                    if (mappingJSON[0].Polyline) {
715
716                        if (selected !== null) {
717                            selected.setStyle(undefined);
718                            selected = null;
719                            overlay.setPosition(undefined);
720                            closer.blur();
721                        }
722
723                        var feature1 = Source.getFeatureById(mappingJSON[0].Polyline + '-route');
724                        CreateInfoBox(feature1);
725                    }
726                };
727
728
729
730                view.animate(
731                    {
732                        center: fullCenter,
733                        zoom: fullZoom,
734                        duration: 1000
735                    },
736                    {
737                        center: newCenter,
738                        zoom: newZoom,
739                        duration: 1000
740                    },
741                    callback
742                );
743
744
745                var mappingJSON = JSON.parse($(this).closest('.trail-data').attr('data-mappingjson'));
746
747                if (mappingJSON[0]) {
748                    $(this).css({ "textShadow": "0px 0px 10px " + mappingJSON[0].PolylineHighlightedStyle.ColorHex + ", 0px 0px 10px grey" });
749                }
750
751                $(this).addClass("zoom-out-on-click");
752
753            }
754        }
755    }
756})
757
758//Alternative zoom method that doesn't go to the full extent of the map first.
759$('.fit-zoom-on-click').click(function () {
760    var mappingJSON = JSON.parse($(this).closest('.trail-data').attr('data-mappingjson'));
761    var listOfRoutes = [];
762    
763    mappingJSON.forEach(function (item, index) {
764        if (item.Polyline != null) {
765            //var route1 = new ol.format.Polyline({
766            //    factor: 1e5
767            //}).readGeometry(item.Polyline, {
768            //    dataProjection: 'EPSG:4326',
769            //    featureProjection: 'EPSG:3857'
770            //});
771            var route1 = "";
772            if (!item.Polyline.startsWith("MULTIPOLYGON")) {
773                route1 = (new ol.format.Polyline({
774                    factor: 1e5
775                }).readGeometry(item.Polyline, {
776                    dataProjection: 'EPSG:4326',
777                    featureProjection: 'EPSG:3857'
778                }));
779            }
780            else {
781                route1 = (new ol.format.WKT({
782                    factor: 1e5
783                }).readGeometry(item.Polyline, {
784                    dataProjection: 'EPSG:4326',
785                    featureProjection: 'EPSG:3857'
786                }));
787            }
788            listOfRoutes.push(route1);
789        }
790    });
791    //If there aren't any polylines to zoom to don't zoom
792    if (listOfRoutes.length > 0) {
793        var listOfViewFeatures = [];
794        listOfRoutes.forEach(function (item, index) {
795            var routeFeature1 = new ol.Feature({
796                geometry: item,
797            })
798            listOfViewFeatures.push(routeFeature1);
799        });
800
801        var vectorSourceView = new ol.source.Vector({
802            features: listOfViewFeatures
803        });
804
805        var vectorLayerView = new ol.layer.Vector({
806            source: vectorSourceView,
807        });
808
809        map.getView().fit(
810            vectorLayerView.getSource().getExtent(),
811            { padding: [70, 70, 70, 70] });
812    }
813})
814
815//Resets zoom to the full extents of the map on click
816$('.reset-zoom-on-click').click(function () {
817
818    var polyline1 = $(this).closest('.trail-data').attr("data-polyline1");
819    var polylineSplit1 = polyline1.split(',');
820    if (item.Polyline != null) {
821        //var route1 = (new ol.format.Polyline({
822        //    factor: 1e5
823        //}).readGeometry(polylineSplit1[0], {
824        //    dataProjection: 'EPSG:4326',
825        //    featureProjection: 'EPSG:3857'
826        //}));
827        var route1 = "";
828        if (!item.Polyline.startsWith("MULTIPOLYGON")) {
829            route1 = (new ol.format.Polyline({
830                factor: 1e5
831            }).readGeometry(item.Polyline, {
832                dataProjection: 'EPSG:4326',
833                featureProjection: 'EPSG:3857'
834            }));
835        }
836        else {
837            route1 = (new ol.format.WKT({
838                factor: 1e5
839            }).readGeometry(item.Polyline, {
840                dataProjection: 'EPSG:4326',
841                featureProjection: 'EPSG:3857'
842            }));
843        }
844
845        map.getView().fit(
846            route1.getExtent(),
847            {
848                padding: [100, 100, 100, 100],
849                duration: 1000
850            });
851    }
852})
853
854//Change Colors and Map
855$('.map-color-picker').change(function () {
856
857    //Get and set the new line width
858    LineWidth = document.getElementsByClassName('line-width')[0].value;
859
860    //Get and set the new endpoint radius
861    EndpointRadius = document.getElementsByClassName('endpoint-radius')[0].value;
862
863    //Get and set route color
864    var routeColorHex = document.getElementsByClassName('route-color')[0].value;
865    var routeColor = ol.color.asArray(routeColorHex);
866    var routeOpacity = 1;
867    routeColor = routeColor.slice();
868    routeColor[3] = routeOpacity;
869
870    styles["Unfinished"].setStroke(new ol.style.Stroke({
871        width: LineWidth,
872        color: routeColor
873    }))
874
875    //Get and set finished route color
876    var finishedRouteColorHex = document.getElementsByClassName('finish-color')[0].value;
877    var finishedRouteColor = ol.color.asArray(finishedRouteColorHex);
878    var finishedRouteOpacity = 1;
879    finishedRouteColor = finishedRouteColor.slice();
880    finishedRouteColor[3] = finishedRouteOpacity;
881
882    styles["Finished"].setStroke(new ol.style.Stroke({
883        width: LineWidth,
884        color: finishedRouteColor
885    }))
886
887    //Get and set highlighted route color
888    var highlightedRouteColorHex = document.getElementsByClassName('highlight-color')[0].value;
889    var highlightedRouteColor = ol.color.asArray(highlightedRouteColorHex);
890    var highlightedRouteOpacity = 1;
891    highlightedRouteColor = highlightedRouteColor.slice();
892    highlightedRouteColor[3] = highlightedRouteOpacity;
893
894    styles["Highlighted"].setStroke(new ol.style.Stroke({
895        width: LineWidth,
896        color: highlightedRouteColor
897    }))
898
899    //Get and set start dot color
900    var startColorHex = document.getElementsByClassName('start-color')[0].value;
901    var startColor = ol.color.asArray(startColorHex);
902    var startOpacity = 1;
903    startColor = startColor.slice();
904    startColor[3] = startOpacity;
905
906    var newGeoMarkerCircleFill = new ol.style.Fill({
907        color: startColor
908    });
909
910    var newGeoMarkerCircle = new ol.style.Circle({
911        radius: EndpointRadius,
912        snapToPixel: false,
913        fill: newGeoMarkerCircleFill,
914        stroke: new ol.style.Stroke({
915            color: 'white',
916            width: 2
917        })
918    });
919
920    styles["StartPoint"].setImage(newGeoMarkerCircle);
921
922    //Get and set end dot color
923    var endColorHex = document.getElementsByClassName('end-color')[0].value;
924    var endColor = ol.color.asArray(endColorHex);
925    var endOpacity = 1;
926    endColor = endColor.slice();
927    endColor[3] = endOpacity;
928
929    var newGeoMarkerEndCircleFill = new ol.style.Fill({
930        color: endColor
931    });
932
933    var newGeoMarkerEndCircle = new ol.style.Circle({
934        radius: EndpointRadius,
935        snapToPixel: false,
936        fill: newGeoMarkerEndCircleFill,
937        stroke: new ol.style.Stroke({
938            color: 'white',
939            width: 2
940        })
941    });
942
943    styles["EndPoint"].setImage(newGeoMarkerEndCircle);
944
945    //Get and set new Mapbox Map
946    mapboxStylesURL = document.getElementsByClassName('mapbox-style-url')[0].value;
947    mapboxAccessToken = document.getElementsByClassName('mapbox-access-token')[0].value;
948
949    secondaryMapboxStyleURL = document.getElementsByClassName('secondary-mapbox-style-url')[0].value;
950    secondaryMapboxAccessToken = document.getElementsByClassName('secondary-mapbox-access-token')[0].value;
951
952
953    if ((MapboxStyleURL != null && MapboxStyleURL != '') && (MapboxAccessToken != null && MapboxAccessToken != '')) {
954
955        //Remove the original map layer
956        map.getLayers().forEach(layer => {
957            if (layer && layer.get('name') === 'map-layer') {
958                map.removeLayer(layer);
959            }
960        });
961
962        //Remove the original secondary map layer
963        map.getLayers().forEach(layer => {
964            if (layer && layer.get('name') === 'map-layer-secondary') {
965                map.removeLayer(layer);
966            }
967        });
968
969        
970
971        if ($("#EnableSecondaryMap").is(":checked")) {
972            SecondaryMapEnabled = true;
973            $(".ol-secondary-map").removeClass("secondary-map-hidden");
974        }
975        else {
976            SecondaryMapEnabled = false;
977            $(".ol-secondary-map").addClass("secondary-map-hidden");
978        }
979
980        //Build a new map layer
981        var newmbMap = new mapboxgl.Map({
982            style: mapboxStylesURL,
983            attributionControl: false,
984            boxZoom: false,
985            //center: center,
986            container: 'map',
987            doubleClickZoom: false,
988            dragPan: false,
989            dragRotate: false,
990            interactive: false,
991            keyboard: false,
992            pitchWithRotate: false,
993            scrollZoom: false,
994            touchZoomRotate: false,
995        });
996
997        var newmbLayer = new ol.layer.Layer({
998            name: "map-layer",
999            render: function (frameState) {
1000                var canvas = newmbMap.getCanvas();
1001                var viewState = frameState.viewState;
1002
1003                var visible = mbLayer.getVisible();
1004                canvas.style.display = visible ? 'block' : 'none';
1005
1006                var opacity = mbLayer.getOpacity();
1007                canvas.style.opacity = opacity;
1008
1009                // adjust view parameters in mapbox
1010                var rotation = viewState.rotation;
1011                newmbMap.jumpTo({
1012                    center: ol.proj.toLonLat(viewState.center),
1013                    zoom: viewState.zoom - 1,
1014                    bearing: (-rotation * 180) / Math.PI,
1015                    animate: false,
1016                });
1017
1018                // cancel the scheduled update & trigger synchronous redraw
1019                // see https://github.com/mapbox/mapbox-gl-js/issues/7893#issue-408992184
1020                // NOTE: THIS MIGHT BREAK IF UPDATING THE MAPBOX VERSION
1021                if (newmbMap._frame) {
1022                    newmbMap._frame.cancel();
1023                    newmbMap._frame = null;
1024                }
1025                newmbMap._render();
1026
1027                return canvas;
1028            },
1029            source: new ol.source.Source({
1030                attributions: [
1031                    '<a href="https://www.mapbox.com/about/maps/" target="_blank">© Mapbox</a> |',
1032                    '<a href="http://www.openstreetmap.org/about/" target="_blank">© OpenStreetMap</a> |',
1033                    '<a href="https://www.mapbox.com/map-feedback/#/-74.5/40/10" target="_blank">Improve this map</a>'
1034                ]
1035            }),
1036        });
1037
1038        mbLayer = newmbLayer;
1039
1040        map.addLayer(mbLayer);
1041
1042        if (SecondaryMapEnabled) {
1043            var newmbMapSecondary = new mapboxgl.Map({
1044                style: secondaryMapboxStyleURL,
1045                attributionControl: false,
1046                boxZoom: false,
1047                //center: center,
1048                container: 'map',
1049                doubleClickZoom: false,
1050                dragPan: false,
1051                dragRotate: false,
1052                interactive: false,
1053                keyboard: false,
1054                pitchWithRotate: false,
1055                scrollZoom: false,
1056                touchZoomRotate: false,
1057            });
1058
1059            //Viewing Map
1060            var newmbLayerSecondary = new ol.layer.Layer({
1061                name: "map-layer-secondary",
1062                render: function (frameState) {
1063                    var canvas = newmbMapSecondary.getCanvas();
1064                    var viewState = frameState.viewState;
1065
1066                    var visible = mbLayer.getVisible();
1067                    canvas.style.display = visible ? 'block' : 'none';
1068
1069                    var opacity = mbLayer.getOpacity();
1070                    canvas.style.opacity = opacity;
1071
1072                    // adjust view parameters in mapbox
1073                    var rotation = viewState.rotation;
1074                    newmbMapSecondary.jumpTo({
1075                        center: ol.proj.toLonLat(viewState.center),
1076                        zoom: viewState.zoom - 1,
1077                        bearing: (-rotation * 180) / Math.PI,
1078                        animate: false,
1079                    });
1080
1081                    // cancel the scheduled update & trigger synchronous redraw
1082                    // see https://github.com/mapbox/mapbox-gl-js/issues/7893#issue-408992184
1083                    // NOTE: THIS MIGHT BREAK IF UPDATING THE MAPBOX VERSION
1084                    if (newmbMapSecondary._frame) {
1085                        newmbMapSecondary._frame.cancel();
1086                        newmbMapSecondary._frame = null;
1087                    }
1088                    newmbMapSecondary._render();
1089
1090                    return canvas;
1091                },
1092                source: new ol.source.Source({
1093                    attributions: [
1094                        '<a href="https://www.mapbox.com/about/maps/" target="_blank">© Mapbox</a> |',
1095                        '<a href="http://www.openstreetmap.org/about/" target="_blank">© OpenStreetMap</a> |',
1096                        '<a href="https://www.mapbox.com/map-feedback/#/-74.5/40/10" target="_blank">Improve this map</a>'
1097                    ]
1098                }),
1099            });
1100
1101            mbLayerSecondary = newmbLayerSecondary;
1102
1103            map.addLayer(mbLayerSecondary);
1104
1105        }
1106
1107        //Add newly created map layer
1108        
1109        //mbLayer = newmbLayer;
1110    }
1111
1112    //Update the segment map
1113    //Remove the original map layer
1114    segmentMakerMap.getLayers().forEach(layer => {
1115        if (layer && layer.get('name') === 'segment-map-layer') {
1116            segmentMakerMap.removeLayer(layer);
1117        }
1118    });
1119
1120    //Remove the original secondary map layer
1121    segmentMakerMap.getLayers().forEach(layer => {
1122        if (layer && layer.get('name') === 'segment-map-layer-secondary') {
1123            segmentMakerMap.removeLayer(layer);
1124        }
1125    });
1126
1127    var newMapSource = new ol.source.XYZ({
1128        url: MapURL,
1129        projection: 'EPSG:3857',
1130        tilePixelRatio: 2, // THIS IS IMPORTANT
1131        attributions: [
1132            '<a href="https://www.mapbox.com/about/maps/">© Mapbox</a> |',
1133            '<a href="http://www.openstreetmap.org/about/">© OpenStreetMap</a> |',
1134            '<a href="https://www.mapbox.com/map-feedback/#/-74.5/40/10">Improve this map</a>'
1135        ]
1136        //url: 'https://api.mapbox.com/styles/v1/soldemeyer/ckeyqffym2xon19ob1j11txbl?access_token=pk.eyJ1Ijoic29sZGVtZXllciIsImEiOiJja2V5cTl5dDcwNGZmMnlsY25pN25vcWswIn0.EltqR3-Y19cHzy1QYfwRew'
1137        //url: 'https://api.mapbox.com/styles/v1/soldemeyer/ckeyre8yp1i0j19plo89hcbvb/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1Ijoic29sZGVtZXllciIsImEiOiJja2V5cTl5dDcwNGZmMnlsY25pN25vcWswIn0.EltqR3-Y19cHzy1QYfwRew',
1138        //url:'https://api.mapbox.com/styles/v1/soldemeyer/ckeyqdxs31afq19qnaqvzt13o/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1Ijoic29sZGVtZXllciIsImEiOiJja2V5cTl5dDcwNGZmMnlsY25pN25vcWswIn0.EltqR3-Y19cHzy1QYfwRew',
1139        //crossOrigin: 'anonymous'
1140    });
1141
1142    var newRaster = new ol.layer.Tile({
1143        name: "segment-map-layer",
1144        source: newMapSource,
1145    });
1146
1147    raster = newRaster;
1148    segmentMakerMap.addLayer(raster);
1149
1150    if (SecondaryMapEnabled) {
1151        var newSecondaryMapSource = new ol.source.XYZ({
1152            url: SecondaryMapURL,
1153            projection: 'EPSG:3857',
1154            tilePixelRatio: 2, // THIS IS IMPORTANT
1155            attributions: [
1156                '<a href="https://www.mapbox.com/about/maps/">© Mapbox</a> |',
1157                '<a href="http://www.openstreetmap.org/about/">© OpenStreetMap</a> |',
1158                '<a href="https://www.mapbox.com/map-feedback/#/-74.5/40/10">Improve this map</a>'
1159            ]
1160            //url: 'https://api.mapbox.com/styles/v1/soldemeyer/ckeyqffym2xon19ob1j11txbl?access_token=pk.eyJ1Ijoic29sZGVtZXllciIsImEiOiJja2V5cTl5dDcwNGZmMnlsY25pN25vcWswIn0.EltqR3-Y19cHzy1QYfwRew'
1161            //url: 'https://api.mapbox.com/styles/v1/soldemeyer/ckeyre8yp1i0j19plo89hcbvb/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1Ijoic29sZGVtZXllciIsImEiOiJja2V5cTl5dDcwNGZmMnlsY25pN25vcWswIn0.EltqR3-Y19cHzy1QYfwRew',
1162            //url:'https://api.mapbox.com/styles/v1/soldemeyer/ckeyqdxs31afq19qnaqvzt13o/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1Ijoic29sZGVtZXllciIsImEiOiJja2V5cTl5dDcwNGZmMnlsY25pN25vcWswIn0.EltqR3-Y19cHzy1QYfwRew',
1163            //crossOrigin: 'anonymous'
1164        });
1165
1166        var newSecondaryRaster = new ol.layer.Tile({
1167            name: "segment-map-layer-secondary",
1168            source: newSecondaryMapSource,
1169        });
1170
1171        secondaryRaster = newSecondaryRaster;
1172        segmentMakerMap.addLayer(secondaryRaster);
1173    }
1174
1175    if (SecondaryMapEnabled) {
1176        raster.setZIndex(1);
1177        secondaryRaster.setZIndex(0);
1178        vector.setZIndex(2);
1179    }
1180    else {
1181        raster.setZIndex(0);
1182        vector.setZIndex(1);
1183    }
1184
1185
1186
1187    $('.route-circle').css('color', routeColorHex)
1188    $('.finished-circle').css('color', finishedRouteColorHex)
1189
1190    if (SecondaryMapEnabled) {
1191        mbLayer.changed();
1192        mbLayerSecondary.changed();
1193        vectorLayer.changed();
1194
1195        mbLayer.setZIndex(1);
1196        mbLayerSecondary.setZIndex(0);
1197        vectorLayer.setZIndex(2);
1198
1199        raster.changed();
1200        secondaryRaster.changed();
1201        vector.changed();
1202
1203        raster.setZIndex(1);
1204        secondaryRaster.setZIndex(0);
1205        vector.setZIndex(2);
1206    }
1207    else {
1208        mbLayer.changed();
1209        vectorLayer.changed();
1210
1211        mbLayer.setZIndex(0);
1212        vectorLayer.setZIndex(1);
1213
1214        raster.changed();
1215        vector.changed();
1216
1217        raster.setZIndex(0);
1218        vector.setZIndex(1);
1219    }
1220
1221});
1222
1223/////-----------------------------------------------------------------------------------------------------------------------------////
1224/////----------------------------------------------------Setup Viewer Map---------------------------------------------------------////
1225/////-----------------------------------------------------------------------------------------------------------------------------////
1226
1227var vectorSource = new ol.source.Vector({
1228    features: ListOfFeatures
1229});
1230
1231let LayersArray = [];
1232
1233var vectorLayer = new ol.layer.Vector({
1234    source: vectorSource,
1235    style: function (feature) {
1236        return styles[feature.get('type')];
1237    }
1238});
1239
1240LayersArray.push(vectorLayer);
1241
1242
1243mapboxgl.accessToken = mapboxAccessToken;
1244var mbMap = new mapboxgl.Map({
1245    style: mapboxStylesURL,
1246    attributionControl: false,
1247    boxZoom: false,
1248    //center: center,
1249    container: 'map',
1250    doubleClickZoom: false,
1251    dragPan: false,
1252    dragRotate: false,
1253    interactive: false,
1254    keyboard: false,
1255    pitchWithRotate: false,
1256    scrollZoom: false,
1257    touchZoomRotate: false,
1258});
1259
1260
1261//Viewing Map
1262var mbLayer = new ol.layer.Layer({
1263    name: "map-layer",
1264    render: function (frameState) {
1265        var canvas = mbMap.getCanvas();
1266        var viewState = frameState.viewState;
1267
1268        var visible = mbLayer.getVisible();
1269        canvas.style.display = visible ? 'block' : 'none';
1270
1271        var opacity = mbLayer.getOpacity();
1272        canvas.style.opacity = opacity;
1273
1274        // adjust view parameters in mapbox
1275        var rotation = viewState.rotation;
1276        mbMap.jumpTo({
1277            center: ol.proj.toLonLat(viewState.center),
1278            zoom: viewState.zoom - 1,
1279            bearing: (-rotation * 180) / Math.PI,
1280            animate: false,
1281        });
1282
1283        // cancel the scheduled update & trigger synchronous redraw
1284        // see https://github.com/mapbox/mapbox-gl-js/issues/7893#issue-408992184
1285        // NOTE: THIS MIGHT BREAK IF UPDATING THE MAPBOX VERSION
1286        if (mbMap._frame) {
1287            mbMap._frame.cancel();
1288            mbMap._frame = null;
1289        }
1290        mbMap._render();
1291
1292        return canvas;
1293    },
1294    source: new ol.source.Source({
1295        attributions: [
1296            '<a href="https://www.mapbox.com/about/maps/" target="_blank">© Mapbox</a> |',
1297            '<a href="http://www.openstreetmap.org/about/" target="_blank">© OpenStreetMap</a> |',
1298            '<a href="https://www.mapbox.com/map-feedback/#/-74.5/40/10" target="_blank">Improve this map</a>'
1299        ]
1300    }),
1301});
1302
1303LayersArray.push(mbLayer);
1304
1305
1306if (SecondaryMapEnabled) {
1307    var mbMapSecondary = new mapboxgl.Map({
1308        style: secondaryMapboxStyleURL,
1309        attributionControl: false,
1310        boxZoom: false,
1311        //center: center,
1312        container: 'map',
1313        doubleClickZoom: false,
1314        dragPan: false,
1315        dragRotate: false,
1316        interactive: false,
1317        keyboard: false,
1318        pitchWithRotate: false,
1319        scrollZoom: false,
1320        touchZoomRotate: false,
1321    });
1322
1323    //Viewing Map
1324    var mbLayerSecondary = new ol.layer.Layer({
1325        name: "map-layer-secondary",
1326        render: function (frameState) {
1327            var canvas = mbMapSecondary.getCanvas();
1328            var viewState = frameState.viewState;
1329
1330            var visible = mbLayer.getVisible();
1331            canvas.style.display = visible ? 'block' : 'none';
1332
1333            var opacity = mbLayer.getOpacity();
1334            canvas.style.opacity = opacity;
1335
1336            // adjust view parameters in mapbox
1337            var rotation = viewState.rotation;
1338            mbMapSecondary.jumpTo({
1339                center: ol.proj.toLonLat(viewState.center),
1340                zoom: viewState.zoom - 1,
1341                bearing: (-rotation * 180) / Math.PI,
1342                animate: false,
1343            });
1344
1345            // cancel the scheduled update & trigger synchronous redraw
1346            // see https://github.com/mapbox/mapbox-gl-js/issues/7893#issue-408992184
1347            // NOTE: THIS MIGHT BREAK IF UPDATING THE MAPBOX VERSION
1348            if (mbMapSecondary._frame) {
1349                mbMapSecondary._frame.cancel();
1350                mbMapSecondary._frame = null;
1351            }
1352            mbMapSecondary._render();
1353
1354            return canvas;
1355        },
1356        source: new ol.source.Source({
1357            attributions: [
1358                '<a href="https://www.mapbox.com/about/maps/" target="_blank">© Mapbox</a> |',
1359                '<a href="http://www.openstreetmap.org/about/" target="_blank">© OpenStreetMap</a> |',
1360                '<a href="https://www.mapbox.com/map-feedback/#/-74.5/40/10" target="_blank">Improve this map</a>'
1361            ]
1362        }),
1363    });
1364
1365    LayersArray.push(mbLayerSecondary);
1366}
1367
1368//Heat Map
1369
1370var TSToken = refreshToken();
1371
1372var heatmapVectorSource = new ol.source.Vector({
1373    format: new ol.format.GeoJSON(),
1374    loader: function (extent, resolution, projection, success) {
1375        const url = apiBaseURL + '/Event/' + eventID + '/HeatMapCoordinates';
1376        const xhr = new XMLHttpRequest();
1377        xhr.open('GET', url);
1378        xhr.setRequestHeader('Authorization', 'Bearer ' + TSToken);
1379        const onError = function () {
1380        }
1381        xhr.onerror = onError;
1382        xhr.onload = function () {
1383            if (xhr.status == 200) {
1384                const features = heatmapVectorSource.getFormat().readFeatures(xhr.responseText, {
1385                    dataProjection: 'EPSG:4326',
1386                    featureProjection: 'EPSG:3857'
1387                });
1388                heatmapVectorSource.addFeatures(features);
1389            } else {
1390            }
1391        }
1392        xhr.send();
1393    }
1394});
1395
1396const heatmapLayer = new ol.layer.Heatmap({
1397    source: heatmapVectorSource,
1398    radius: 6,
1399    blur: 17,
1400});
1401
1402if (eventID && enableHeatmap) {
1403    LayersArray.push(heatmapLayer);
1404}
1405
1406var view = new ol.View({
1407    center: [0, 0],
1408    zoom: 2,
1409});
1410
1411
1412var map = new ol.Map({
1413    controls: ol.control.defaults().extend([new SecondaryMap()]),
1414    interactions: ol.interaction.defaults({
1415        dragPan: false,
1416        mouseWheelZoom: false,
1417        PinchZoom: false,
1418        doubleClickZoom: false
1419    }),
1420    layers: LayersArray,
1421    overlays: [overlay],
1422    target: 'map',
1423    view: view,
1424});
1425
1426if (SecondaryMapEnabled) {
1427    mbLayer.setZIndex(1);
1428    mbLayerSecondary.setZIndex(0);
1429    vectorLayer.setZIndex(2);
1430    heatmapLayer.setZIndex(3);
1431}
1432else {
1433    mbLayer.setZIndex(0);
1434    vectorLayer.setZIndex(1);
1435    heatmapLayer.setZIndex(2);
1436}
1437
1438
1439/////-----------------------------------------------------------------------------------------------------------------------------////
1440/////------------------------------------------------End viewer map setup---------------------------------------------------------////
1441/////-----------------------------------------------------------------------------------------------------------------------------////
1442
1443
1444/////-----------------------------------------------------------------------------------------------------------------------------////
1445/////-----------------------------------------Start of segement creator map sections----------------------------------------------////
1446/////-----------------------------------------Will probably want to reoganize eventually------------------------------------------////
1447/////-----------------------------------------------------------------------------------------------------------------------------////
1448
1449//Segment Maker Map
1450
1451//This gl mapbox stuff wasn't working with the draw function. I think it had something to do layers being on top of the vector layer... or something?
1452//Anyway, it's not a customer facing things so it's not a big deal for now.
1453//We might wanna get it working eventually but for we'll use the old way.
1454let segmentLayers = [];
1455
1456var mapSource = new ol.source.XYZ({
1457    url: MapURL,
1458    projection: 'EPSG:3857',
1459    tilePixelRatio: 2, // THIS IS IMPORTANT
1460    attributions: [
1461        '<a href="https://www.mapbox.com/about/maps/">© Mapbox</a> |',
1462        '<a href="http://www.openstreetmap.org/about/">© OpenStreetMap</a> |',
1463        '<a href="https://www.mapbox.com/map-feedback/#/-74.5/40/10">Improve this map</a>'
1464    ]
1465    //url: 'https://api.mapbox.com/styles/v1/soldemeyer/ckeyqffym2xon19ob1j11txbl?access_token=pk.eyJ1Ijoic29sZGVtZXllciIsImEiOiJja2V5cTl5dDcwNGZmMnlsY25pN25vcWswIn0.EltqR3-Y19cHzy1QYfwRew'
1466    //url: 'https://api.mapbox.com/styles/v1/soldemeyer/ckeyre8yp1i0j19plo89hcbvb/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1Ijoic29sZGVtZXllciIsImEiOiJja2V5cTl5dDcwNGZmMnlsY25pN25vcWswIn0.EltqR3-Y19cHzy1QYfwRew',
1467    //url:'https://api.mapbox.com/styles/v1/soldemeyer/ckeyqdxs31afq19qnaqvzt13o/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1Ijoic29sZGVtZXllciIsImEiOiJja2V5cTl5dDcwNGZmMnl
1467sY25pN25vcWswIn0.EltqR3-Y19cHzy1QYfwRew',
1468    //crossOrigin: 'anonymous'
1469});
1470
1471var segmentMakerView = new ol.View({
1472    center: [0, 0],
1473    zoom: 2,
1474});
1475
1476var raster = new ol.layer.Tile({
1477    name: "segment-map-layer",
1478    source: mapSource,
1479});
1480
1481segmentLayers.push(raster);
1482
1483var source = new ol.source.Vector ({ wrapX: false });
1484
1485var vector = new ol.layer.Vector({
1486    source: source,
1487});
1488
1489segmentLayers.push(vector);
1490
1491if (SecondaryMapEnabled) {
1492    var secondaryMapSource = new ol.source.XYZ({
1493        url: SecondaryMapURL,
1494        projection: 'EPSG:3857',
1495        tilePixelRatio: 2, // THIS IS IMPORTANT
1496        attributions: [
1497            '<a href="https://www.mapbox.com/about/maps/">© Mapbox</a> |',
1498            '<a href="http://www.openstreetmap.org/about/">© OpenStreetMap</a> |',
1499            '<a href="https://www.mapbox.com/map-feedback/#/-74.5/40/10">Improve this map</a>'
1500        ]
1501        //url: 'https://api.mapbox.com/styles/v1/soldemeyer/ckeyqffym2xon19ob1j11txbl?access_token=pk.eyJ1Ijoic29sZGVtZXllciIsImEiOiJja2V5cTl5dDcwNGZmMnlsY25pN25vcWswIn0.EltqR3-Y19cHzy1QYfwRew'
1502        //url: 'https://api.mapbox.com/styles/v1/soldemeyer/ckeyre8yp1i0j19plo89hcbvb/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1Ijoic29sZGVtZXllciIsImEiOiJja2V5cTl5dDcwNGZmMnlsY25pN25vcWswIn0.EltqR3-Y19cHzy1QYfwRew',
1503        //url:'https://api.mapbox.com/styles/v1/soldemeyer/ckeyqdxs31afq19qnaqvzt13o/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1Ijoic29sZGVtZXllciIsImEiOiJja2V5cTl5dDcwNGZmMnlsY25pN25vcWswIn0.EltqR3-Y19cHzy1QYfwRew',
1504        //crossOrigin: 'anonymous'
1505    });
1506
1507    var secondaryRaster = new ol.layer.Tile({
1508        name: "segment-map-layer-secondary",
1509        source: secondaryMapSource,
1510    });
1511
1512    segmentLayers.push(secondaryRaster);
1513}
1514
1515var segmentMakerMap = new ol.Map({
1516    layers: segmentLayers,
1517    controls: ol.control.defaults().extend([new SegmentSecondaryMap()]),
1518    target: 'segment-maker-map', //the div tag to replace with the map
1519    view: segmentMakerView,
1520});
1521
1522if (SecondaryMapEnabled) {
1523    raster.setZIndex(1);
1524    secondaryRaster.setZIndex(0);
1525    vector.setZIndex(2);
1526}
1527else {
1528    raster.setZIndex(0);
1529    vector.setZIndex(1);
1530}
1531
1532var draw; // global so we can remove it later
1533
1534function addInteraction() {
1535    var segmentType = document.getElementById('map-geometry-type');
1536    //Add draw ability to map
1537    draw = new ol.interaction.Draw({
1538        source: source,
1539        type: segmentType.value,
1540        name: 'newSegment'
1541    });
1542
1543    draw.on('drawstart', function (evt) {
1544        source.clear();
1545    });
1546    
1547    segmentMakerMap.addInteraction(draw);
1548
1549    //When feature is added, create a polyline
1550    if (segmentType.value == 'LineString') {
1551        source.on('addfeature', lineStringAddFeature);
1552    }
1553    else {
1554        source.on('addfeature', multiPolygonAddFeature);
1555    };
1556}
1557
1558function lineStringAddFeature (evt) {
1559    //Remove old line
1560    var polylineGeometry = source.getFeatureById('newSegment');
1561    if (polylineGeometry != null) {
1562        Source.removeFeature(polylineGeometry);
1563    }
1564
1565    var feature = evt.feature;
1566    var coords = feature.getGeometry().getCoordinates();  //Note: Coords do not take into data projection
1567
1568    var polyline = new ol.format.Polyline({
1569        factor: 1e5,
1570    }).writeGeometry(feature.getGeometry(), {
1571        dataProjection: 'EPSG:4326',
1572        featureProjection: 'EPSG:3857'
1573    });
1574    var formatLength = function (line) {
1575        var length = ol.sphere.getLength(line);
1576        var output;
1577        output = Math.round(length * 100) / 100; //length in meters
1578        return output;
1579    };
1580    if (document.getElementById('new-segment-coords')) {
1581        document.getElementById('new-segment-coords').value = coords;
1582    }
1583    if (document.getElementById('new-segment-polyline')) {
1584        document.getElementById('new-segment-polyline').value = polyline;
1585    }
1586    if (document.getElementById('new-segment-length')) {
1587        document.getElementById('new-segment-length').value = formatLength(feature.getGeometry());
1588    }
1589
1590    getElevationData(polyline);
1591};
1592function multiPolygonAddFeature (evt) {
1593    //Remove old line
1594    var polylineGeometry = source.getFeatureById('newSegment');
1595    if (polylineGeometry != null) {
1596        Source.removeFeature(polylineGeometry);
1597    }
1598
1599    var feature = evt.feature;
1600    var coords = feature.getGeometry().getCoordinates();  //Note: Coords do not take into data projection
1601
1602    var polyline = new ol.format.WKT({
1603        factor: 1e5,
1604    }).writeGeometry(feature.getGeometry(), {
1605        dataProjection: 'EPSG:4326',
1606        featureProjection: 'EPSG:3857'
1607    });
1608    //var formatLength = function (line) {
1609    //    var length = ol.sphere.getLength(line);
1610    //    var output;
1611    //    output = Math.round(length * 100) / 100; //length in meters
1612    //    return output;
1613    //};
1614    if (document.getElementById('new-segment-coords')) {
1615        document.getElementById('new-segment-coords').value = coords;
1616    }
1617    if (document.getElementById('new-segment-polyline')) {
1618        document.getElementById('new-segment-polyline').value = polyline;
1619    }
1620    //if (document.getElementById('new-segment-length')) {
1621    //    document.getElementById('new-segment-length').value = formatLength(feature.getGeometry());
1622    //}
1623};
1624function removeMapInteractions() {
1625    source.un('addfeature', lineStringAddFeature);
1626    source.un('addfeature', multiPolygonAddFeature);
1627    segmentMakerMap.removeInteraction(draw);
1628}
1629
1630function getElevationData(polyline) {
1631
1632    //Use Google Elevation to get elevation information (making API call)
1633    let request = new XMLHttpRequest();
1634
1635    request.open('POST', "/api/GoogleElevation");
1636
1637    request.setRequestHeader('Content-Type', 'application/json');
1638
1639    //const body = '{"format_in":"encodedpolyline","format_out":"geojson","geometry":"' + encodeURIComponent(polyline) + '"}';
1640
1641    var data = {};
1642    data.polyline = polyline;
1643    var json = JSON.stringify(data);
1644
1645    //const body = '{"polyline": "' + polyline + '"}';
1646
1647    request.send(json);
1648
1649    request.onreadystatechange = function () {
1650        if (this.readyState === 4) {
1651            console.log('Status:', this.status);
1652            console.log('Headers:', this.getAllResponseHeaders());
1653            console.log('Body:', this.responseText);
1654
1655            var results = JSON.parse(this.responseText);  //get elevation results
1656            var elevationResults = results.Results;  //get elevation results
1657            var newSegmentElevations = [];
1658            for (let i = 0, l = elevationResults.length; i < l; i++) {
1659                newSegmentElevations.push(elevationResults[i].Elevation);
1660            }
1661            //let newSegmentElevations = elevationResults.Elevation;  //get array of elevations without X,Y coords
1662            var maxHeight = Math.max(...newSegmentElevations);  //max height in meters
1663            var minHeight = Math.min(...newSegmentElevations);  //min height in meters
1664            var totalElevationGain = getTotalElevationGain(newSegmentElevations);  //total elevation gain in meters
1665            var totalElevationLoss = getTotalElevationLoss(newSegmentElevations);  //total elevation gain in meters
1666
1667            if (document.getElementById('new-segment-max-height')) {
1668                document.getElementById('new-segment-max-height').value = maxHeight;
1669            }
1670            if (document.getElementById('new-segment-min-height')) {
1671                document.getElementById('new-segment-min-height').value = minHeight;
1672            }
1673            if (document.getElementById('new-segment-total-elevation-gain')) {
1674                document.getElementById('new-segment-total-elevation-gain').value = totalElevationGain;
1675            }
1676            if (document.getElementById('new-segment-total-elevation-loss')) {
1677                document.getElementById('new-segment-total-elevation-loss').value = totalElevationLoss;
1678            }
1679
1680        }
1681    };
1682}
1683
1684//Get Total Elevation Gain
1685function getTotalElevationGain(segmentElevations) {
1686
1687    var i;
1688    var TotalElevationGain = 0;
1689    for (i = 1; i < segmentElevations.length; i++) {
1690        if (segmentElevations[i - 1] < segmentElevations[i]) {
1691            TotalElevationGain = TotalElevationGain + (segmentElevations[i] - segmentElevations[i - 1]);
1692        }
1693    }
1694    segmentElevations
1695    return TotalElevationGain
1696}
1697
1698function getTotalElevationLoss(segmentElevations) {
1699
1700    var i;
1701    var TotalElevationLoss = 0;
1702    for (i = 1; i < segmentElevations.length; i++) {
1703        if (segmentElevations[i - 1] > segmentElevations[i]) {
1704            TotalElevationLoss = TotalElevationLoss + (segmentElevations[i-1] 
1704- segmentElevations[i]);
1705        }
1706    }
1707    segmentElevations
1708    return TotalElevationLoss
1709}
1710
1711if (document.getElementById('undo')) {
1712    document.getElementById('undo').addEventListener('click', function () {
1713        draw.removeLastPoint();
1714    });
1715}
1716
1717if (document.getElementById('refreshElevationData') && document.getElementById('new-segment-polyline')) {
1718    document.getElementById('refreshElevationData').addEventListener('click', function () {
1719        if (document.getElementById('new-segment-polyline').value) {
1720            getElevationData(document.getElementById('new-segment-polyline').value);
1721        }
1722    });
1723}
1724
1725/////-----------------------------------------------------------------------------------------------------------------------------////
1726/////-----------------------------------------End of segment creator map section--------------------------------------------------////
1727/////-----------------------------------------------------------------------------------------------------------------------------////
1728
1729// Geolocation
1730var geolocation = new ol.Geolocation({
1731    // enableHighAccuracy must be set to true to have the heading value.
1732    trackingOptions: {
1733        enableHighAccuracy: true,
1734    },
1735    projection: view.getProjection(),
1736});
1737
1738function el(id) {
1739    return document.getElementById(id);
1740}
1741
1742//el('track').addEventListener('change', function () {
1743//    geolocation.setTracking(this.checked);
1744//});
1745
1746// update the HTML page when the position changes.
1747geolocation.on('change', function () {
1748    //el('accuracy').innerText = geolocation.getAccuracy() + ' [m]';
1749    //el('altitude').innerText = geolocation.getAltitude() + ' [m]';
1750    //el('altitudeAccuracy').innerText = geolocation.getAltitudeAccuracy() + ' [m]';
1751    //el('heading').innerText = geolocation.getHeading() + ' [rad]';
1752    //el('speed').innerText = geolocation.getSpeed() + ' [m/s]';
1753});
1754
1755// handle geolocation error.
1756geolocation.on('error', function (error) {
1757    try {
1758        //var info = document.getElementById('info');
1759        //info.innerHTML = error.message;
1760        //    info.style.display = '';
1761    }
1762    catch (err) {
1763    }
1764});
1765
1766var accuracyFeature = new ol.Feature();
1767geolocation.on('change:accuracyGeometry', function () {
1768    accuracyFeature.setGeometry(geolocation.getAccuracyGeometry());
1769});
1770
1771var positionFeature = new ol.Feature();
1772positionFeature.setStyle(
1773    new ol.style.Style({
1774        image: new ol.style.Circle({
1775            radius: 6,
1776            fill: new ol.style.Fill({
1777                color: '#3399CC',
1778            }),
1779            stroke: new ol.style.Stroke({
1780                color: '#fff',
1781                width: 2,
1782            }),
1783        }),
1784    })
1785);
1786
1787geolocation.on('change:position', function () {
1788    var coordinates = geolocation.getPosition();
1789    positionFeature.setGeometry(coordinates ? new ol.geom.Point(coordinates) : null);
1790});
1791
1792new ol.layer.Vector({
1793    map: map,
1794    source: new ol.source.Vector({
1795        features: [accuracyFeature, positionFeature],
1796    }),
1797});
1798// Geolocation End
1799
1800//Get Default view
1801if (vectorLayer.getSource().getExtent()[0] != "Infinity") {
1802    //If there are trails, display all trails with a padding of 30 on all sides
1803    map.getView().fit(
1804        vectorLayer.getSource().getExtent(),
1805        { padding: [30, 30, 30, 30] });
1806}
1807else {
1808    //If there are no trails , display center on united states
1809    map.setView(
1810        new ol.View({
1811            center: ol.proj.fromLonLat([-95, 40], 'EPSG:3857', ),
1812            zoom: 4
1813        })
1814    );
1815}
1816
1817// //Code to enable/disable mouse wheel zooming by clicking on the map
1818var mouseWheelInt = new ol.interaction.MouseWheelZoom();
1819var pinchInt = new ol.interaction.PinchZoom();
1820var dragPanInt = new ol.interaction.DragPan();
1821
1822//Disable the map initially
1823mouseWheelInt.setActive(!mouseWheelInt.getActive());
1824map.addInteraction(mouseWheelInt);
1825
1826//Disable pinch zoom
1827pinchInt.setActive(!pinchInt.getActive());
1828map.addInteraction(pinchInt);
1829
1830//Disable drag pan
1831dragPanInt.setActive(!dragPanInt.getActive());
1832map.addInteraction(dragPanInt);
1833
1834//Map overlay functions
1835var $mapOverlay = $('.map-overlay');
1836var mapOverlayElements = document.querySelectorAll('.map-overlay');
1837
1838// Check if it's time to start the animation.
1839function checkOverlayHideAnimation() {
1840    var windowHeight = window.innerHeight;
1841
1842    for (var i = 0; i < mapOverlayElements.length; i++) {
1843        var mapOverlayElement = mapOverlayElements[i];
1844        var positionFromTop = mapOverlayElements[i].getBoundingClientRect().top;
1845        var positionFromMiddle = positionFromTop + mapOverlayElement.offsetHeight / 2;
1846
1847        if (positionFromMiddle - windowHeight <= 0) {
1848            mapOverlayElement.classList.add('map-overlay-hide-animation');
1849        }
1850    }
1851}
1852
1853// Capture scroll events
1854$(window).on('scroll scrollstart touchmove orientationchange resize load', function () {
1855    checkOverlayHideAnimation();
1856});
1857
1858//Event listener to hide overlay on on animation end
1859$mapOverlay.on("animationend", function () {
1860    $(this).addClass("hidden");
1861});
1862
1863// //Enable/Disable on click function
1864map.on('dblclick', function () {
1865    mapInteractions();
1866
1867});
1868map.on('touch', function () {
1869    mapInteractions();
1870
1871});
1872
1873
1874var highlightStyle = new ol.style.Style({
1875    fill: new ol.style.Fill({
1876        color: 'rgba(255,255,255,0.7)',
1877    }),
1878    stroke: new ol.style.Stroke({
1879        color: '#3399CC',
1880        width: 9,
1881    }),
1882});
1883
1884var selected = null;
1885var trailName = null;
1886var segment1ID = null;
1887var trailComment = null;
1888
1889//map.on('singleclick', function (e) {
1890//    var coordinate = e.coordinate;
1891//    var hdms = ol.coordinate.toStringHDMS(ol.proj.toLonLat(coordinate));
1892
1893//    if (selected !== null) {
1894//        selected.setStyle(undefined);
1895//        selected = null;
1896//        overlay.setPosition(undefined);
1897//        closer.blur();
1898//    }
1899
1900//    map.forEachFeatureAtPixel(e.pixel, function (f) {
1901//        selected = f;
1902//        var routeCoords1 = f.getGeometry().getCoordinates();
1903//        var routeLength1 = routeCoords1.length;
1904//        var halfRouteLength1 = Math.round((routeLength1 - 1) / 2);
1905//        if (f.get('type') != 'geoMarker' && f.get('type') != 'geoMarkerEnd') {
1906//            f.setStyle(styles["Highlighted"]);
1907//            trailName = f.get('name');
1908//            segment1ID = f.get('forwardSegment');
1909//            segmentComment = f.get('comment');
1910//            var commentText = "";
1911//            if (segmentComment != "" && segmentComment != "undefined" && segmentComment != null) {
1912//                commentText = segmentComment;
1913//            }
1914//            var linkText = "";
1915//            if (segment1ID != "" && segment1ID != "undefined" && segment1ID != null) {
1916//                linkText = '<br/><a href="https://www.strava.com/segments/' + segment1ID + '" target="blank">Segment details</a>';
1917//            }
1918//            content.innerHTML = '<p><b>' + trailName + '</b><br/>' + commentText + linkText + '</p>';
1919//            overlay.setPosition(routeCoords1[halfRouteLength1 - 1]);
1920//        }
1921//        return true;
1922//    });
1923//});
1924
1925map.on('singleclick', function (e) {
1926    var coordinate = e.coordinate;
1927    var hdms = ol.coordinate.toStringHDMS(ol.proj.toLonLat(coordinate));
1928
1929    if (selected !== null) {
1930        selected.setStyle(undefined);
1931        selected = null;
1932        overlay.setPosition(undefined);
1933        closer.blur();
1934    }
1935
1936    map.forEachFeatureAtPixel(e.pixel, function (f) {
1937        selectedFeature = f;
1938        if (selectedFeature.get('type') != 'geoMarker' && selectedFeature.get('type') != 'geoMarkerEnd') {
1939            CreateInfoBox(selectedFeature)
1940        }
1941        return true;
1942    });
1943});
1944
1945//Function to create infobox on map
1946function CreateInfoBox(selectedFeature) {
1947    selected = selectedFeature;
1948    var routeCoords1 = selectedFeature.getGeometry().getCoordinates();
1949    var routeLength1 = routeCoords1.length;
1950    var halfRouteLength1 = Math.round((routeLength1 - 1) / 2);
1951    selectedFeature.setStyle(styles["Highlighted"]);
1952    trailName = selectedFeature.get('name');
1953    segment1ID = selectedFeature.get('forwardSegment');
1954    segmentComment = selectedFeature.get('comment');
1955    var commentText = "";
1956    if (segmentComment != "" && segmentComment != "undefined" && segmentComment != null) {
1957        commentText = segmentComment;
1958    }
1959    var linkText = "";
1960    if (segment1ID != "" && segment1ID != "undefined" && segment1ID != null) {
1961        linkText = '<br/><a href="https://www.strava.com/segments/' + segment1ID + '" target="blank">Segment details</a>';
1962    }
1963    content.innerHTML = '<p><b>' + trailName + '</b><br/>' + commentText + linkText + '</p>';
1964    overlay.setPosition(routeCoords1[halfRouteLength1 - 1]);
1965    return overlay;
1966}
1967
1968function mapInteractions() {
1969    mouseWheelInt.setActive(!mouseWheelInt.getActive())
1970    pinchInt.setActive(!pinchInt.getActive());
1971    dragPanInt.setActive(!dragPanInt.getActive());
1972    $(this).blur();
1973    var thisMap = $('#map')
1974    var CurrentCSSBorderColor = thisMap.css('border-left-color');
1975    var highlightedRGBColor = "";
1976    var Highlighted = styles['Highlighted'].getStroke().getColor();
1977    if (Highlighted) {
1978        var highlightedRGBColor = 'rgb(' + Highlighted[0] + ', ' + Highlighted[1] + ', ' + Highlighted[2] + ')';
1979    }
1980    else {
1981        var highlightedRGBColor = 'rgb(70,130,180)';
1982    }
1983    if (CurrentCSSBorderColor != highlightedRGBColor) {
1984        thisMap.addClass("focused");
1985        thisMap.css('border-color', highlightedRGBColor);
1986        thisMap.css('border-width', '2px');
1987        thisMap.css('border-style', 'solid');
1988    }
1989    else {
1990        thisMap.removeClass("focused");
1991        thisMap.css('border-color', DefaultCSSBorderColor);
1992        thisMap.css('border-width', DefaultCSSBorderWidth);
1993        thisMap.css('border-style', DefaultCSSBorderStyle);
1994    }
1995}
1996
1997geolocation.setTracking(true);
1998
1999//resize segmentMakerMap whem modal opens to ensure it appears
2000if (document.getElementById('new-segment-length')) {
2001    $('#addNewSegmentModal').on('shown.bs.modal', function () {
2002        segmentMakerMap.updateSize();
2003
2004        if (vectorLayer.getSource().getExtent()[0] != "Infinity") {
2005            segmentMakerMap.getView().fit(
2006                vectorLayer.getSource().getExtent(),
2007                { padding: [0, 0, 0, 0] });
2008        }
2009
2010    })
2011}
2012
2013//Update trail status
2014$('.updateTrailStatus').click(function (e) {
2015    var trailstatusinfo = $(this).attr("data-trailstatusinfo");
2016    //$('.delete-donationrecipient-hidden-input').val(donationrecipientid)
2017
2018    $.ajax({
2019        type: "POST", //POST or GET
2020        async: false,
2021        url: '/Admin/TrailUpdate_Action', //my action page
2022        data: JSON.parse(trailstatusinfo), // serializes the form's elements.
2023        success: function (data) {
2024            var JSONValues = JSON.parse(data);
2025            var buttonColor = 'info';
2026            var iconImage = 'fas fa-check-circle  zoom-on-click';
2027            var statusIconImage = 'far fa-dot-circle';
2028            var statusTitle = 'Remove credit for trail';
2029            if (JSONValues.TrailCompleted == false) {
2030                buttonColor = 'warning';
2031                iconImage = 'far fa-eye route-circle  zoom-on-click';
2032                statusIconImage = "far fa-circle";
2033                statusTitle = 'Give credit for trail'
2034            }
2035            var idName = 'StatusButton-' + JSONValues.TrailID;
2036            var idIcon = 'IconImage-' + JSONValues.TrailID;
2037            var idStatusIcon = 'StatusIcon-' + JSONValues.TrailID;
2038            document.getElementById(idName).setAttribute('class', 'btn btn-sm btn-' + buttonColor + ' updateTrailStatus')
2039            document.getElementById(idName).setAttribute('data-trailstatusinfo', data)
2040            document.getElementById(idName).setAttribute('title', statusTitle)
2041            document.getElementById(idName).setAttribute('data-original-title', statusTitle)
2042            document.getElementById(idIcon).setAttribute('class', iconImage)
2043            document.getElementById(idStatusIcon).setAttribute('class', statusIconImage)
2044
2045        },
2046        error: function (data) {
2047            //form.find('.event-info-notification').html('<div><span>Data Not Saved</span></div>')
2048        }
2049    });
2050});
2051
2052$('.event-info-form').submit(function (e) {
2053
2054    e.preventDefault(); // avoid to execute the actual submit of the form.
2055
2056    var form = $(this);
2057    var url = form.attr('action');
2058    var method = form.attr('method');
2059    var UpdateType = form.find('[name ="UpdateType"]').val();
2060
2061    form.find('.event-info-notification').html('<div class="spinner-border spinner-border-sm" role="status"><span class= "sr-only" > Updated...</span></div>')
2062
2063    $.ajax({
2064        type: method,
2065        url: url,
2066        data: form.serialize(), // serializes the form's elements.
2067        success: function (data) {
2068            form.find('.event-info-notification').html('<div><span>Updated</span></div>')
2069
2070            //Update Event Status text
2071            var StartDate = new Date($('#StartDate').val());
2072            var EndDate = new Date($('#EndDate').val());
2073            var Today = new Date();
2074            form.find('.event-status').removeClass('text-success')
2075            form.find('.event-status').removeClass('text-info')
2076            form.find('.event-status').removeClass('text-danger')
2077            if (Today >= StartDate && Today <= EndDate) {
2078                //form.find('.event-status').html('<span class="text-success">Event is in progress</span>')
2079                form.find('.event-status').text('Event is in progress')
2080                form.find('.event-status').addClass('text-success')
2081            }
2082            else if (Today < StartDate) {
2083                //form.find('.event-status').html('<span class="text-info">Event not yet started</span>')
2084                form.find('.event-status').text('Event not yet started')
2085                form.find('.event-status').addClass('text-info')
2086            }
2087            else if (Today > EndDate) {
2088                //form.find('.event-status').html('<span class="text-danger">Event is over</span>')
2089                form.find('.event-status').text('Event is over')
2090                form.find('.event-status').addClass('text-danger')
2091            }
2092
2093            //Refresh the samples page
2094            if (UpdateType == "StyleInfo") {
2095                document.getElementById('SamplePage').contentWindow.location.reload();
2096            }
2097            //Update the preferred domain
2098            if (UpdateType == "BasicInfo") {
2099                form.find('[name="PreferredURL"]').val(form.find('[name="PreferredURL"]').val().toLowerCase().replace('http://', '').replace('https://', ''));
2100            }
2101
2102            //Update Button Colors on Page Update
2103            if (UpdateType = "MapInfo") {
2104                $('.show-unfinished-button').css("background-color", form.find('[name="RouteColor"]').val());
2105                $('.show-finished-button').css("background-color", form.find('[name="FinishedColor"]').val());
2106                $('.show-highlighted-button').css("background-color", form.find('[name="HighlightedColor"]').val());
2107
2108                $('.show-unfinished-button').css("border-color", form.find('[name="RouteColor"]').val());
2109                $('.show-finished-button').css("border-color", form.find('[name="FinishedColor"]').val());
2110                $('.show-highlighted-button').css("border-color", form.find('[name="HighlightedColor"]').val());
2111            }
2112        },
2113        error: function (data) {
2114            form.find('.event-info-notification').html('<div><span>Data Not Saved</span></div>')
2115        }
2116    });
2117
2118});
2119
2120/////-----------------------------------------------------------------------------------------------------------------------------////
2121/////---------------------------------------------------Creat Heat Map------------------------------------------------------------////
2122/////-----------------------------------------------------------------------------------------------------------------------------////
2123
2124
2125
2126//const raster = new TileLayer({
2127//    source: new Stamen({
2128//        layer: 'toner',
2129//    }),
2130//});
2131
2132//new Map({
2133//    layers: [raster, vector],
2134//    target: 'map',
2135//    view: new View({
2136//        center: [0, 0],
2137//        zoom: 2,
2138//    }),
2139//});
2140
2141//blur.addEventListener('input', function () {
2142//    vector.setBlur(parseInt(blur.value, 10));
2143//});
2144
2145//radius.addEventListener('input', function () {
2146//    vector.setRadius(parseInt(radius.value, 10));
2147//});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.