PageSourceSearch

https://rondedesgrangeons.fr/wp-content/plugins/gpx-viewer/js/leaflet-editable-polyline.js

js rondedesgrangeons.fr collected 2026-10-04 02:53:23 UTC 22,838 bytes, 586 lines download raw bytes

1L.Polyline.polylineEditor = L.Polyline.extend({
2    _prepareMapIfNeeded: function() {
3        var that = this;
4        that._changed = false;
5
6        if(this._map._editablePolylines != null) {
7            return
8        }
9
10        // Container for all editable polylines on this map:
11        this._map._editablePolylines = [];
12        this._map._editablePolylinesEnabled = true;
13
14        // Click anywhere on map to add a new point-polyline:
15        if(this._options.newPolylines) {
16            console.log('click na map');
17            that._map.on('dblclick', function(event) {
18                console.log('click, target=' + (event.target == that._map) + ' type=' + event.type);
19                if(that._map.isEditablePolylinesBusy())
20                    return;
21
22                var latLng = event.latlng;
23                if(that._options.newPolylineConfirmMessage)
24                    if(!confirm(that._options.newPolylineConfirmMessage))
25                        return
26
27                var contexts = [{'originalPolylineNo': null, 'originalPointNo': null}];
28                L.Polyline.PolylineEditor([latLng], that._options, contexts).addTo(that._map);
29
30                that._showBoundMarkers();
31                that._changed = true;
32            });
33        }
34
35        /**
36         * Check if there is *any* busy editable polyline on this map.
37         */
38        this._map.isEditablePolylinesBusy = function() {
39            var map = this;
40            for(var i = 0; i < map._editablePolylines.length; i++)
41                if(map._editablePolylines[i]._isBusy())
42                    return true;
43
44            return false;
45        };
46
47        /**
48         * Enable/disable editing.
49         */
50        this._map.setEditablePolylinesEnabled = function(enabled) {
51            var map = this;
52            map._editablePolylinesEnabled = enabled;
53            for(var i = 0; i < map._editablePolylines.length; i++) {
54                var polyline = map._editablePolylines[i];
55                if(enabled) {
56                    polyline._showBoundMarkers();
57                } else {
58                    polyline._hideAll();
59                }
60            }
61        };
62
63        /*
64         * Utility method added to this map to retreive editable 
65         * polylines.
66         */
67        this._map.getEditablePolylines = function() {
68            var map = this;
69            return map._editablePolylines;
70        }
71
72        this._map.fixAroundEditablePoint = function(marker) {
73            var map = this;
74            for(var i = 0; i < map._editablePolylines.length; i++) {
75                var polyline = map._editablePolylines[i];
76                polyline._reloadPolyline(marker);
77            }
78        }
79    },
80    /**
81     * Will add all needed methods to this polyline.
82     */
83    _addMethods: function() {
84        var that = this;
85
86        this._init = function(options, contexts) {
87            this._prepareMapIfNeeded();
88
89            /**
90             * Since all point editing is done by marker events, markers 
91             * will be the main holder of the polyline points locations.
92             * Every marker contains a reference to the newPointMarker 
93             * *before* him (=> the first marker has newPointMarker=null).
94             */
95            this._parseOptions(options);
96
97            this._markers = [];
98            var points = this.getLatLngs();
99            var length = points.length;
100            for(var i = 0; i < length; i++) {
101                var marker = this._addMarkers(i, points[i]);
102                if(! ('context' in marker)) {
103                    marker.context = {}
104                    if(that._contexts != null) {
105                        marker.context = contexts[i];
106                    }
107                }
108
109                if(marker.context && ! ('originalPointNo' in marker.context))
110                    marker.context.originalPointNo = i;
111                if(marker.context && ! ('originalPolylineNo' in marker.context))
112                    marker.context.originalPolylineNo = that._map._editablePolylines.length;
113            }
114
115            // Map move => show different editable markers:
116            var map = this._map;
117            this._map.on("zoomend", function(e) {
118                that._showBoundMarkers();
119            });
120            this._map.on("moveend", function(e) {
121                that._showBoundMarkers();
122            });
123
124            if(this._desiredPolylineNo && this._desiredPolylineNo != null) {
125                this._map._editablePolylines.splice(this._desiredPolylineNo, 0, this);
126            } else {
127                this._map._editablePolylines.push(this);
128            }
129        };
130
131        /**
132         * Check if is busy adding/moving new nodes. Note, there may be 
133         * *other* editable polylines on the same map which *are* busy.
134         */
135        this._isBusy = function() {
136            return that._busy;
137        };
138
139        this._setBusy = function(busy) {
140            that._busy = busy;
141        };
142
143        /**
144         * Get markers for this polyline.
145         */
146        this.getPoints = function() {
147            return this._markers;
148        };
149
150        this.isChanged = function() {
151            return this._changed;
152        }
153
154        this._parseOptions = function(options) {
155            if(!options)
156                options = {};
157
158            // Do not show edit markers if more than maxMarkers would be shown:
159            if(!('maxMarkers' in options))
160                options.maxMarkers = 100;
161            if(!('newPolylines' in options))
162                options.newPolylines = false;
163            if(!('newPolylineConfirmMessage' in options))
164                options.newPolylineConfirmMessage = '';
165            if(!('addFirstLastPointEvent' in options))
166                options.addFirstLastPointEvent = 'click';
167            if(!('customPointListeners' in options))
168                options.customPointListeners = {};
169            if(!('customNewPointListeners' in options))
170                options.customNewPointListeners = {};
171
172            this._options = options;
173        };
174
175        /**
176         * Show only markers in current map bounds *is* there are only a certain 
177         * number of markers. This method is called on eventy that change map 
178         * bounds.
179         */
180        this._showBoundMarkers = function() {
181            if (!that._map) {
182                return;
183            }
184            
185            this._setBusy(false);
186
187            if(!that._map._editablePolylinesEnabled) {
188                console.log('Do not show because editing is disabled');
189                return;
190            }
191
192            var bounds = that._map.getBounds();
193            var found = 0;
194            for(var polylineNo in that._map._editablePolylines) {
195                var polyline = that._map._editablePolylines[polylineNo];
196                for(var markerNo in polyline._markers) {
197                    var marker = polyline._markers[markerNo];
198                    if(bounds.contains(marker.getLatLng()))
199                        found += 1;
200                }
201            }
202
203            for(var polylineNo in that._map._editablePolylines) {
204                var polyline = that._map._editablePolylines[polylineNo];
205                for(var markerNo in polyline._markers) {
206                    var marker = polyline._markers[markerNo];
207                    if(found < that._options.maxMarkers) {
208                        that._setMarkerVisible(marker, bounds.contains(marker.getLatLng()));
209                        that._setMarkerVisible(marker.newPointMarker, markerNo > 0 && bounds.contains(marker.getLatLng()));
210                    } else {
211                        that._setMarkerVisible(marker, false);
212                        that._setMarkerVisible(marker.newPointMarker, false);
213                    }
214                }
215            }
216        };
217
218        /**
219         * Used when adding/moving points in order to disable the user to mess 
220         * with other markers (+ easier to decide where to put the point 
221         * without too many markers).
222         */
223        this._hideAll = function(except) {
224            this._setBusy(true);
225            for(var polylineNo in that._map._editablePolylines) {
226                console.log("hide " + polylineNo + " markers");
227                var polyline = that._map._editablePolylines[polylineNo];
228                for(var markerNo in polyline._markers) {
229                    var marker = polyline._markers[markerNo];
230                    if(except == null || except != marker)
231                        polyline._setMarkerVisible(marker, false);
232                    if(except == null || except != marker.newPointMarker)
233                        polyline._setMarkerVisible(marker.newPointMarker, false);
234                }
235            }
236        }
237
238        /**
239         * Show/hide marker.
240         */
241        this._setMarkerVisible = function(marker, show) {
242            if(!marker)
243                return;
244
245            var map = this._map;
246            if(show) {
247                if(!marker._visible) {
248                    if(!marker._map) { // First show for this marker:
249                        marker.addTo(map);
250                    } else { // Marker was already shown and hidden:
251                        map.addLayer(marker);
252                    }
253                    marker._map = map;
254                }
255                marker._visible = true;
256            } else {
257                if(marker._visible) {
258                    map.removeLayer(marker);
259                }
260                marker._visible = false;
261            }
262        };
263
264        /**
265         * Reload polyline. If it is busy, then the bound markers will not be 
266         * shown. 
267         */
268        this._reloadPolyline = function(fixAroundPointNo) {
269            that.setLatLngs(that._getMarkerLatLngs());
270            if(fixAroundPointNo != null)
271                that._fixAround(fixAroundPointNo);
272            that._showBoundMarkers();
273            that._changed = true;
274        }
275
276        /**
277         * Add two markers (a point marker and his newPointMarker) for a 
278         * single point.
279         *
280         * Markers are not added on the map here, the marker.addTo(map) is called 
281         * only later when needed first time because of performance issues.
282         */
283        this._addMarkers = function(pointNo, latLng, fixNeighbourPositions) {
284            var that = this;
285            var points = this.getLatLngs();
286            var marker = L.marker(latLng, {draggable: true, icon: this._options.pointIcon});
287
288            marker.newPointMarker = null;
289            marker.on('dragstart', function(event) {
290                var pointNo = that._getPointNo(event.target);
291                var previousPoint = pointNo && pointNo > 0 ? that._markers[pointNo - 1].getLatLng() : null;
292                var nextPoint = pointNo < that._markers.length - 1 ? that._markers[pointNo + 1].getLatLng() : null;
293                that._setupDragLines(marker, previousPoint, nextPoint);
294                that._hideAll(marker);
295            });
296            marker.on('dragend', function(event) {
297                var marker = event.target;
298                var pointNo = that._getPointNo(event.target);
299                setTimeout(function() {
300                    that._reloadPolyline(pointNo);
301                }, 25);
302            });
303            marker.on('contextmenu', function(event) {
304                var marker = event.target;
305                var pointNo = that._getPointNo(event.target);
306                that._map.removeLayer(marker);
307                that._map.removeLayer(newPointMarker);
308                that._markers.splice(pointNo, 1);
309                that._reloadPolyline(pointNo);
310            });
311            marker.on(that._options.addFirstLastPointEvent, function(event) {
312
313                console.log('click on marker');
314                var marker = event.target;
315                var pointNo = that._getPointNo(event.target);
316                console.log('pointNo=' + pointNo + ' that._markers.length=' + that._markers.length);
317                event.dont;
318                if(pointNo == 0 || pointNo == that._markers.length - 1) {
319                    console.log('first or last');
320                    that._prepareForNewPoint(marker, pointNo == 0 ? 0 : pointNo + 1);
321                } else {
322                    console.log('not first or last');
323                }
324            });
325
326            var previousPoint = points[pointNo == 0 ? pointNo : pointNo - 1];
327            var newPointMarker = L.marker([(latLng.lat + previousPoint.lat) / 2.,
328                                           (latLng.lng + previousPoint.lng) / 2.],
329                                          {draggable: true, icon: this._options.newPointIcon});
330            marker.newPointMarker = newPointMarker;
331            newPointMarker.on('dragstart', function(event) {
332                var pointNo = that._getPointNo(event.target);
333                var previousPoint = that._markers[pointNo - 1].getLatLng();
334                var nextPoint = that._markers[pointNo].getLatLng();
335                that._setupDragLines(marker.newPointMarker, previousPoint, nextPoint);
336
337                that._hideAll(marker.newPointMarker);
338            });
339            newPointMarker.on('dragend', function(event) {
340                var marker = event.target;
341                var pointNo = that._getPointNo(event.target);
342                that._addMarkers(pointNo, marker.getLatLng(), true);
343                setTimeout(function() {
344                    that._reloadPolyline();
345                }, 25);
346            });
347            newPointMarker.on('contextmenu', function(event) {
348				if (!confirm(edit_translation.slicing))
349					return;
350                // 1. Remove this polyline from map
351                var marker = event.target;
352                var pointNo = that._getPointNo(marker);
353                var markers = that.getPoints();
354                that._hideAll();
355
356                var secondPartMarkers = that._markers.slice(pointNo, pointNo.length);
357                that._markers.splice(pointNo, that._markers.length - pointNo);
358
359                that._reloadPolyline();
360
361                var points = [];
362                var contexts = [];
363                for(var i = 0; i < secondPartMarkers.length; i++) {
364                    var marker = secondPartMarkers[i];
365                    points.push(marker.getLatLng());
366                    contexts.push(marker.context);
367                }
368
369                console.log('points:' + points);
370                console.log('contexts:' + contexts);
371
372                // Need to know the current polyline order numbers, because 
373                // the splitted one need to be inserted immediately after:
374                var originalPolylineNo = that._map._editablePolylines.indexOf(that);
375
376                L.Polyline.PolylineEditor(points, that._options, contexts, originalPolylineNo + 1)
377                                          .addTo(that._map);
378
379                that._showBoundMarkers();
380            });
381
382            this._markers.splice(pointNo, 0, marker);
383
384            // User-defined custom event listeners:
385            if(that._options.customPointListeners)
386                for(var eventName in that._options.customPointListeners)
387                    marker.on(eventName, that._options.customPointListeners[eventName]);
388            if(that._options.customNewPointListeners)
389                for(var eventName in that._options.customNewPointListeners)
390                    newPointMarker.on(eventName, that._options.customNewPointListeners[eventName]);
391
392            if(fixNeighbourPositions) {
393                this._fixAround(pointNo);
394            }
395
396            return marker;
397        };
398
399        /**
400         * Event handlers for first and last point.
401         */
402        this._prepareForNewPoint = function(marker, pointNo) {
403            // This is slightly delayed to prevent the same propagated event 
404            // to be catched here:
405            setTimeout(
406                function() {
407                    that._hideAll();
408                    that._setupDragLines(marker, marker.getLatLng());
409                    that._map.once('click', function(event) {
410                        if(that._markers.length == 1) {
411                            pointNo += 1;
412                        }
413                        console.log('dodajemo na ' + pointNo + ' - ' + event.latlng);
414                        that._addMarkers(pointNo, event.latlng, true);
415                        that._reloadPolyline();
416                    });
417                },
418                100
419            );
420        };
421
422        /**
423         * Fix nearby new point markers when the new point is created.
424         */
425        this._fixAround = function(pointNoOrMarker) {
426            if((typeof pointNoOrMarker) == 'number')
427                var pointNo = pointNoOrMarker;
428            else
429                var pointNo = that._markers.indexOf(pointNoOrMarker);
430
431            if(pointNo < 0)
432                return;
433
434            var previousMarker = pointNo == 0 ? null : that._markers[pointNo - 1];
435            var marker = that._markers[pointNo];
436            var nextMarker = pointNo < that._markers.length - 1 ? that._markers[pointNo + 1] : null;
437            if(marker && previousMarker) {
438                marker.newPointMarker.setLatLng([(previousMarker.getLatLng().lat + marker.getLatLng().lat) / 2.,
439                                                 (previousMarker.getLatLng().lng + marker.getLatLng().lng) / 2.]);
440            }
441            if(marker && nextMarker) {
442                nextMarker.newPointMarker.setLatLng([(marker.getLatLng().lat + nextMarker.getLatLng().lat) / 2.,
443                                                     (marker.getLatLng().lng + nextMarker.getLatLng().lng) / 2.]);
444            }
445        };
446
447        /**
448         * Find the order number of the marker.
449         */
450        this._getPointNo = function(marker) {
451            for(var i = 0; i < this._markers.length; i++) {
452                if(marker == this._markers[i] || marker == this._markers[i].newPointMarker) {
453                    return i;
454                }
455            }
456            return -1;
457        };
458
459        /**
460         * Get polyline latLngs based on marker positions.
461         */
462        this._getMarkerLatLngs = function() {
463            var result = [];
464            for(var i = 0; i < this._markers.length; i++)
465                result.push(this._markers[i].getLatLng());
466            return result;
467        };
468
469        this._setupDragLines = function(marker, point1, point2) {
470            var line1 = null;
471            var line2 = null;
472            if(point1) line1 = L.polyline([marker.getLatLng(), point1], {dasharray: "5,
4721", weight: 1})
473                                .addTo(that._map);
474            if(point2) line2 = L.polyline([marker.getLatLng(), point2], {dasharray: "5,1", weight: 1})
475                                .addTo(that._map);
476
477            var moveHandler = function(event) {
478                if(line1)
479                    line1.setLatLngs([event.latlng, point1]);
480                if(line2)
481                    line2.setLatLngs([event.latlng, point2]);
482            };
483
484            var stopHandler = function(event) {
485                if (that._map) {
486                    that._map.off('mousemove', moveHandler);
487                    marker.off('dragend', stopHandler);
488                    if(line1) that._map.removeLayer(line1);
489                    if(line2) that._map.removeLayer(line2);
490                    console.log('STOPPED');
491                    if(event.target != that._map) {
492                        that._map.fire('click', event);
493                    }
494                }
495            };
496
497            that._map.on('mousemove', moveHandler);
498            marker.on('dragend', stopHandler);
499
500            that._map.once('click', stopHandler);
501            marker.once('click', stopHandler);
502            if(line1) line1.once('click', stopHandler);
503            if(line2) line2.once('click', stopHandler);
504        }
505    }
506});
507
508L.Polyline.polylineEditor.addInitHook(function () {
509    this.on('add', function(event) {
510        this._map = event.target._map;
511        this._addMethods();
512
513        /**
514         * When addint a new point we must disable the user to mess with other 
515         * markers. One way is to check everywhere if the user is busy. The 
516         * other is to just remove other markers when the user is doing 
517         * somethinng.
518         *
519         * TODO: Decide the right way to do this and then leave only _busy or 
520         * _hideAll().
521         */
522        this._busy = false;
523        this._initialized = false;
524
525        this._init(this._options, this._contexts);
526
527        this._initialized = true;
528
529        return this;
530    });
531
532    this.on('remove', function(event) {
533        var polyline = event.target;
534        var map = polyline._map;
535        var polylines = map.getEditablePolylines();
536        var index = polylines.indexOf(polyline);
537        if (index > -1) {
538            polylines[index]._markers.forEach(function(marker) {
539                map.removeLayer(marker);
540                if(marker.newPointMarker)
541                    map.removeLayer(marker.newPointMarker);
542            });
543            polylines.splice(index, 1);
544        }
545    });
546});
547
548/**
549 * Construct a new editable polyline.
550 *
551 * latlngs    ... a list of points (or two-element tuples with coordinates)
552 * options    ... polyline options
553 * contexts   ... custom contexts for every point in the polyline. Must have the 
554 *                same number of elements as latlngs and this data will be 
555 *                preserved when new points are added or polylines splitted.
556 * polylineNo ... insert this polyline in a specific order (used when splitting).
557 *
558 * More about contexts:
559 * This is an array of objects that will be kept as "context" for every 
560 * point. Marker will keep this value as marker.context. New markers will 
561 * have context set to null.
562 *
563 * Contexts must be the same size as the polyline size!
564 *
565 * By default, even without calling this method -- every marker will have 
566 * context with one value: marker.context.originalPointNo with the 
567 * original order number of this point. The order may change if some 
568 * markers before this one are delted or new added.
569 */
570L.Polyline.PolylineEditor = function(latlngs, options, contexts, polylineNo) {
571    // Since the app code may not be able to explicitly call the 
572    // initialization of all editable polylines (if the user created a new 
573    // one by splitting an existing), with this method you can control the 
574    // options for new polylines:
575
576    if(options.prepareOptions) {
577        options.prepareOptions(options);
578    }
579
580    var result = new L.Polyline.polylineEditor(latlngs, options);
581    result._options = options;
582    result._contexts = contexts;
583    result._desiredPolylineNo = polylineNo
584
585    return result;
586};

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.