From 1820aef3fb5c926664de1d4d484f64a5c9ba7099 Mon Sep 17 00:00:00 2001
From: YANGDL <114714267@qq.com>
Date: 星期二, 05 一月 2021 17:06:08 +0800
Subject: [PATCH] 优化逻辑

---
 src/components/plugin/Editable.js | 3845 +++++++++++++++++++++++++++++-----------------------------
 1 files changed, 1,922 insertions(+), 1,923 deletions(-)

diff --git a/src/components/plugin/Editable.js b/src/components/plugin/Editable.js
index c2ae865..d86dbc0 100644
--- a/src/components/plugin/Editable.js
+++ b/src/components/plugin/Editable.js
@@ -1,1963 +1,1962 @@
 'use strict'
 const init = (L) => {
-    (function(factory, window) {
-        // define an AMD module that relies on 'leaflet'
-        if (typeof define === 'function' && window.define.amd) {
-            window.define(['leaflet'], factory)
+  (function (factory, window) {
+    // define an AMD module that relies on 'leaflet'
+    if (typeof define === 'function' && window.define.amd) {
+      window.define(['leaflet'], factory)
 
-            // define a Common JS module that relies on 'leaflet'
-        } else if (typeof exports === 'object') {
-            module.exports = factory(require('leaflet'))
+      // define a Common JS module that relies on 'leaflet'
+    } else if (typeof exports === 'object') {
+      module.exports = factory(require('leaflet'))
+    }
+
+    // attach your plugin to the global 'L' variable
+    if (typeof window !== 'undefined' && L) {
+      factory(L)
+    }
+  }(function (L) {
+    // 馃崅miniclass CancelableEvent (Event objects)
+    // 馃崅method cancel()
+    // Cancel any subsequent action.
+
+    // 馃崅miniclass VertexEvent (Event objects)
+    // 馃崅property vertex: VertexMarker
+    // The vertex that fires the event.
+
+    // 馃崅miniclass ShapeEvent (Event objects)
+    // 馃崅property shape: Array
+    // The shape (LatLngs array) subject of the action.
+
+    // 馃崅miniclass CancelableVertexEvent (Event objects)
+    // 馃崅inherits VertexEvent
+    // 馃崅inherits CancelableEvent
+
+    // 馃崅miniclass CancelableShapeEvent (Event objects)
+    // 馃崅inherits ShapeEvent
+    // 馃崅inherits CancelableEvent
+
+    // 馃崅miniclass LayerEvent (Event objects)
+    // 馃崅property layer: object
+    // The Layer (Marker, Polyline鈥�) subject of the action.
+
+    // 馃崅namespace Editable; 馃崅class Editable; 馃崅aka L.Editable
+    // Main edition handler. By default, it is attached to the map
+    // as `map.editTools` property.
+    // Leaflet.Editable is made to be fully extendable. You have three ways to customize
+    // the behaviour: using options, listening to events, or extending.
+    L.Editable = L.Evented.extend({
+
+      statics: {
+        FORWARD: 1,
+        BACKWARD: -1
+      },
+
+      options: {
+
+        // You can pass them when creating a map using the `editOptions` key.
+        // 馃崅option zIndex: int = 1000
+        // The default zIndex of the editing tools.
+        zIndex: 1000,
+
+        // 馃崅option polygonClass: class = L.Polygon
+        // Class to be used when creating a new Polygon.
+        polygonClass: L.Polygon,
+
+        // 馃崅option polylineClass: class = L.Polyline
+        // Class to be used when creating a new Polyline.
+        polylineClass: L.Polyline,
+
+        // 馃崅option markerClass: class = L.Marker
+        // Class to be used when creating a new Marker.
+        markerClass: L.Marker,
+
+        // 馃崅option rectangleClass: class = L.Rectangle
+        // Class to be used when creating a new Rectangle.
+        rectangleClass: L.Rectangle,
+
+        // 馃崅option circleClass: class = L.Circle
+        // Class to be used when creating a new Circle.
+        circleClass: L.Circle,
+
+        // 馃崅option drawingCSSClass: string = 'leaflet-editable-drawing'
+        // CSS class to be added to the map container while drawing.
+        drawingCSSClass: 'leaflet-editable-drawing',
+
+        // 馃崅option drawingCursor: const = 'crosshair'
+        // Cursor mode set to the map while drawing.
+        drawingCursor: 'crosshair',
+
+        // 馃崅option editLayer: Layer = new L.LayerGroup()
+        // Layer used to store edit tools (vertex, line guide鈥�).
+        editLayer: undefined,
+
+        // 馃崅option featuresLayer: Layer = new L.LayerGroup()
+        // Default layer used to store drawn features (Marker, Polyline鈥�).
+        featuresLayer: undefined,
+
+        // 馃崅option polylineEditorClass: class = PolylineEditor
+        // Class to be used as Polyline editor.
+        polylineEditorClass: undefined,
+
+        // 馃崅option polygonEditorClass: class = PolygonEditor
+        // Class to be used as Polygon editor.
+        polygonEditorClass: undefined,
+
+        // 馃崅option markerEditorClass: class = MarkerEditor
+        // Class to be used as Marker editor.
+        markerEditorClass: undefined,
+
+        // 馃崅option rectangleEditorClass: class = RectangleEditor
+        // Class to be used as Rectangle editor.
+        rectangleEditorClass: undefined,
+
+        // 馃崅option circleEditorClass: class = CircleEditor
+        // Class to be used as Circle editor.
+        circleEditorClass: undefined,
+
+        // 馃崅option lineGuideOptions: hash = {}
+        // Options to be passed to the line guides.
+        lineGuideOptions: {},
+
+        // 馃崅option skipMiddleMarkers: boolean = false
+        // Set this to true if you don't want middle markers.
+        skipMiddleMarkers: false
+
+      },
+
+      initialize: function (map, options) {
+        L.setOptions(this, options)
+        this._lastZIndex = this.options.zIndex
+        this.map = map
+        this.editLayer = this.createEditLayer()
+        this.featuresLayer = this.createFeaturesLayer()
+        this.forwardLineGuide = this.createLineGuide()
+        this.backwardLineGuide = this.createLineGuide()
+      },
+
+      fireAndForward: function (type, e) {
+        e = e || {}
+        e.editTools = this
+        this.fire(type, e)
+        this.map.fire(type, e)
+      },
+
+      createLineGuide: function () {
+        const options = L.extend({
+          dashArray: '5,10',
+          weight: 1,
+          interactive: false
+        }, this.options.lineGuideOptions)
+        return L.polyline([], options)
+      },
+
+      createVertexIcon: function (options) {
+        return L.Browser.mobile && L.Browser.touch ? new L.Editable.TouchVertexIcon(options) : new L.Editable.VertexIcon(options)
+      },
+
+      createEditLayer: function () {
+        return this.options.editLayer || new L.LayerGroup().addTo(this.map)
+      },
+
+      createFeaturesLayer: function () {
+        return this.options.featuresLayer || new L.LayerGroup().addTo(this.map)
+      },
+
+      moveForwardLineGuide: function (latlng) {
+        if (this.forwardLineGuide._latlngs.length) {
+          this.forwardLineGuide._latlngs[1] = latlng
+          this.forwardLineGuide._bounds.extend(latlng)
+          this.forwardLineGuide.redraw()
         }
+      },
 
-        // attach your plugin to the global 'L' variable
-        if (typeof window !== 'undefined' && L) {
-            factory(L)
+      moveBackwardLineGuide: function (latlng) {
+        if (this.backwardLineGuide._latlngs.length) {
+          this.backwardLineGuide._latlngs[1] = latlng
+          this.backwardLineGuide._bounds.extend(latlng)
+          this.backwardLineGuide.redraw()
         }
-    }(function(L) {
-        // 馃崅miniclass CancelableEvent (Event objects)
-        // 馃崅method cancel()
-        // Cancel any subsequent action.
+      },
 
-        // 馃崅miniclass VertexEvent (Event objects)
-        // 馃崅property vertex: VertexMarker
-        // The vertex that fires the event.
+      anchorForwardLineGuide: function (latlng) {
+        this.forwardLineGuide._latlngs[0] = latlng
+        this.forwardLineGuide._bounds.extend(latlng)
+        this.forwardLineGuide.redraw()
+      },
 
-        // 馃崅miniclass ShapeEvent (Event objects)
-        // 馃崅property shape: Array
-        // The shape (LatLngs array) subject of the action.
+      anchorBackwardLineGuide: function (latlng) {
+        this.backwardLineGuide._latlngs[0] = latlng
+        this.backwardLineGuide._bounds.extend(latlng)
+        this.backwardLineGuide.redraw()
+      },
 
-        // 馃崅miniclass CancelableVertexEvent (Event objects)
-        // 馃崅inherits VertexEvent
-        // 馃崅inherits CancelableEvent
+      attachForwardLineGuide: function () {
+        this.editLayer.addLayer(this.forwardLineGuide)
+      },
 
-        // 馃崅miniclass CancelableShapeEvent (Event objects)
-        // 馃崅inherits ShapeEvent
-        // 馃崅inherits CancelableEvent
+      attachBackwardLineGuide: function () {
+        this.editLayer.addLayer(this.backwardLineGuide)
+      },
 
-        // 馃崅miniclass LayerEvent (Event objects)
-        // 馃崅property layer: object
-        // The Layer (Marker, Polyline鈥�) subject of the action.
+      detachForwardLineGuide: function () {
+        this.forwardLineGuide.setLatLngs([])
+        this.editLayer.removeLayer(this.forwardLineGuide)
+      },
 
-        // 馃崅namespace Editable; 馃崅class Editable; 馃崅aka L.Editable
-        // Main edition handler. By default, it is attached to the map
-        // as `map.editTools` property.
-        // Leaflet.Editable is made to be fully extendable. You have three ways to customize
-        // the behaviour: using options, listening to events, or extending.
-        L.Editable = L.Evented.extend({
+      detachBackwardLineGuide: function () {
+        this.backwardLineGuide.setLatLngs([])
+        this.editLayer.removeLayer(this.backwardLineGuide)
+      },
 
-            statics: {
-                FORWARD: 1,
-                BACKWARD: -1
-            },
-
-            options: {
-
-                // You can pass them when creating a map using the `editOptions` key.
-                // 馃崅option zIndex: int = 1000
-                // The default zIndex of the editing tools.
-                zIndex: 1000,
-
-                // 馃崅option polygonClass: class = L.Polygon
-                // Class to be used when creating a new Polygon.
-                polygonClass: L.Polygon,
-
-                // 馃崅option polylineClass: class = L.Polyline
-                // Class to be used when creating a new Polyline.
-                polylineClass: L.Polyline,
-
-                // 馃崅option markerClass: class = L.Marker
-                // Class to be used when creating a new Marker.
-                markerClass: L.Marker,
-
-                // 馃崅option rectangleClass: class = L.Rectangle
-                // Class to be used when creating a new Rectangle.
-                rectangleClass: L.Rectangle,
-
-                // 馃崅option circleClass: class = L.Circle
-                // Class to be used when creating a new Circle.
-                circleClass: L.Circle,
-
-                // 馃崅option drawingCSSClass: string = 'leaflet-editable-drawing'
-                // CSS class to be added to the map container while drawing.
-                drawingCSSClass: 'leaflet-editable-drawing',
-
-                // 馃崅option drawingCursor: const = 'crosshair'
-                // Cursor mode set to the map while drawing.
-                drawingCursor: 'crosshair',
-
-                // 馃崅option editLayer: Layer = new L.LayerGroup()
-                // Layer used to store edit tools (vertex, line guide鈥�).
-                editLayer: undefined,
-
-                // 馃崅option featuresLayer: Layer = new L.LayerGroup()
-                // Default layer used to store drawn features (Marker, Polyline鈥�).
-                featuresLayer: undefined,
-
-                // 馃崅option polylineEditorClass: class = PolylineEditor
-                // Class to be used as Polyline editor.
-                polylineEditorClass: undefined,
-
-                // 馃崅option polygonEditorClass: class = PolygonEditor
-                // Class to be used as Polygon editor.
-                polygonEditorClass: undefined,
-
-                // 馃崅option markerEditorClass: class = MarkerEditor
-                // Class to be used as Marker editor.
-                markerEditorClass: undefined,
-
-                // 馃崅option rectangleEditorClass: class = RectangleEditor
-                // Class to be used as Rectangle editor.
-                rectangleEditorClass: undefined,
-
-                // 馃崅option circleEditorClass: class = CircleEditor
-                // Class to be used as Circle editor.
-                circleEditorClass: undefined,
-
-                // 馃崅option lineGuideOptions: hash = {}
-                // Options to be passed to the line guides.
-                lineGuideOptions: {},
-
-                // 馃崅option skipMiddleMarkers: boolean = false
-                // Set this to true if you don't want middle markers.
-                skipMiddleMarkers: false
-
-            },
-
-            initialize: function(map, options) {
-                L.setOptions(this, options)
-                this._lastZIndex = this.options.zIndex
-                this.map = map
-                this.editLayer = this.createEditLayer()
-                this.featuresLayer = this.createFeaturesLayer()
-                this.forwardLineGuide = this.createLineGuide()
-                this.backwardLineGuide = this.createLineGuide()
-            },
-
-            fireAndForward: function(type, e) {
-                e = e || {}
-                e.editTools = this
-                this.fire(type, e)
-                this.map.fire(type, e)
-            },
-
-            createLineGuide: function() {
-                let options = L.extend({
-                    dashArray: '5,10',
-                    weight: 1,
-                    interactive: false
-                }, this.options.lineGuideOptions)
-                return L.polyline([], options)
-            },
-
-            createVertexIcon: function(options) {
-                return L.Browser.mobile && L.Browser.touch ? new L.Editable.TouchVertexIcon(options) : new L.Editable.VertexIcon(options)
-            },
-
-            createEditLayer: function() {
-                return this.options.editLayer || new L.LayerGroup().addTo(this.map)
-            },
-
-            createFeaturesLayer: function() {
-                return this.options.featuresLayer || new L.LayerGroup().addTo(this.map)
-            },
-
-            moveForwardLineGuide: function(latlng) {
-                if (this.forwardLineGuide._latlngs.length) {
-                    this.forwardLineGuide._latlngs[1] = latlng
-                    this.forwardLineGuide._bounds.extend(latlng)
-                    this.forwardLineGuide.redraw()
-                }
-            },
-
-            moveBackwardLineGuide: function(latlng) {
-                if (this.backwardLineGuide._latlngs.length) {
-                    this.backwardLineGuide._latlngs[1] = latlng
-                    this.backwardLineGuide._bounds.extend(latlng)
-                    this.backwardLineGuide.redraw()
-                }
-            },
-
-            anchorForwardLineGuide: function(latlng) {
-                this.forwardLineGuide._latlngs[0] = latlng
-                this.forwardLineGuide._bounds.extend(latlng)
-                this.forwardLineGuide.redraw()
-            },
-
-            anchorBackwardLineGuide: function(latlng) {
-                this.backwardLineGuide._latlngs[0] = latlng
-                this.backwardLineGuide._bounds.extend(latlng)
-                this.backwardLineGuide.redraw()
-            },
-
-            attachForwardLineGuide: function() {
-                this.editLayer.addLayer(this.forwardLineGuide)
-            },
-
-            attachBackwardLineGuide: function() {
-                this.editLayer.addLayer(this.backwardLineGuide)
-            },
-
-            detachForwardLineGuide: function() {
-                this.forwardLineGuide.setLatLngs([])
-                this.editLayer.removeLayer(this.forwardLineGuide)
-            },
-
-            detachBackwardLineGuide: function() {
-                this.backwardLineGuide.setLatLngs([])
-                this.editLayer.removeLayer(this.backwardLineGuide)
-            },
-
-            blockEvents: function() {
-                // Hack: force map not to listen to other layers events while drawing.
-                if (!this._oldTargets) {
-                    this._oldTargets = this.map._targets
-                    this.map._targets = {}
-                }
-            },
-
-            unblockEvents: function() {
-                if (this._oldTargets) {
-                    // Reset, but keep targets created while drawing.
-                    this.map._targets = L.extend(this.map._targets, this._oldTargets)
-                    delete this._oldTargets
-                }
-            },
-
-            registerForDrawing: function(editor) {
-                if (this._drawingEditor) this.unregisterForDrawing(this._drawingEditor)
-                this.blockEvents()
-                editor.reset() // Make sure editor tools still receive events.
-                this._drawingEditor = editor
-                this.map.on('mousemove touchmove', editor.onDrawingMouseMove, editor)
-                this.map.on('mousedown', this.onMousedown, this)
-                this.map.on('mouseup', this.onMouseup, this)
-                L.DomUtil.addClass(this.map._container, this.options.drawingCSSClass)
-                this.defaultMapCursor = this.map._container.style.cursor
-                this.map._container.style.cursor = this.options.drawingCursor
-            },
-
-            unregisterForDrawing: function(editor) {
-                this.unblockEvents()
-                L.DomUtil.removeClass(this.map._container, this.options.drawingCSSClass)
-                this.map._container.style.cursor = this.defaultMapCursor
-                editor = editor || this._drawingEditor
-                if (!editor) return
-                this.map.off('mousemove touchmove', editor.onDrawingMouseMove, editor)
-                this.map.off('mousedown', this.onMousedown, this)
-                this.map.off('mouseup', this.onMouseup, this)
-                if (editor !== this._drawingEditor) return
-                delete this._drawingEditor
-                if (editor._drawing) editor.cancelDrawing()
-            },
-
-            onMousedown: function(e) {
-                if (e.originalEvent.which !== 1) return
-                this._mouseDown = e
-                this._drawingEditor.onDrawingMouseDown(e)
-            },
-
-            onMouseup: function(e) {
-                if (this._mouseDown) {
-                    let editor = this._drawingEditor
-                    let mouseDown = this._mouseDown
-                    this._mouseDown = null
-                    editor.onDrawingMouseUp(e)
-                    if (this._drawingEditor !== editor) return // onDrawingMouseUp may call unregisterFromDrawing.
-                    let origin = L.point(mouseDown.originalEvent.clientX, mouseDown.originalEvent.clientY)
-                    let distance = L.point(e.originalEvent.clientX, e.originalEvent.clientY).distanceTo(origin)
-                    if (Math.abs(distance) < 9 * (window.devicePixelRatio || 1)) this._drawingEditor.onDrawingClick(e)
-                }
-            },
-
-            // 馃崅section Public methods
-            // You will generally access them by the `map.editTools`
-            // instance:
-            //
-            // `map.editTools.startPolyline();`
-
-            // 馃崅method drawing(): boolean
-            // Return true if any drawing action is ongoing.
-            drawing: function() {
-                return this._drawingEditor && this._drawingEditor.drawing()
-            },
-
-            // 馃崅method stopDrawing()
-            // When you need to stop any ongoing drawing, without needing to know which editor is active.
-            stopDrawing: function() {
-                this.unregisterForDrawing()
-            },
-
-            // 馃崅method commitDrawing()
-            // When you need to commit any ongoing drawing, without needing to know which editor is active.
-            commitDrawing: function(e) {
-                if (!this._drawingEditor) return
-                this._drawingEditor.commitDrawing(e)
-            },
-
-            connectCreatedToMap: function(layer) {
-                return this.featuresLayer.addLayer(layer)
-            },
-
-            // 馃崅method startPolyline(latlng: L.LatLng, options: hash): L.Polyline
-            // Start drawing a Polyline. If `latlng` is given, a first point will be added. In any case, continuing on user click.
-            // If `options` is given, it will be passed to the Polyline class constructor.
-            startPolyline: function(latlng, options) {
-                let line = this.createPolyline([], options)
-                line.enableEdit(this.map).newShape(latlng)
-                return line
-            },
-
-            // 馃崅method startPolygon(latlng: L.LatLng, options: hash): L.Polygon
-            // Start drawing a Polygon. If `latlng` is given, a first point will be added. In any case, continuing on user click.
-            // If `options` is given, it will be passed to the Polygon class constructor.
-            startPolygon: function(latlng, options) {
-                let polygon = this.createPolygon([], options)
-                polygon.enableEdit(this.map).newShape(latlng)
-                return polygon
-            },
-
-            // 馃崅method startMarker(latlng: L.LatLng, options: hash): L.Marker
-            // Start adding a Marker. If `latlng` is given, the Marker will be shown first at this point.
-            // In any case, it will follow the user mouse, and will have a final `latlng` on next click (or touch).
-            // If `options` is given, it will be passed to the Marker class constructor.
-            startMarker: function(latlng, options) {
-                latlng = latlng || this.map.getCenter().clone()
-                let marker = this.createMarker(latlng, options)
-                marker.enableEdit(this.map).startDrawing()
-                return marker
-            },
-
-            // 馃崅method startRectangle(latlng: L.LatLng, options: hash): L.Rectangle
-            // Start drawing a Rectangle. If `latlng` is given, the Rectangle anchor will be added. In any case, continuing on user drag.
-            // If `options` is given, it will be passed to the Rectangle class constructor.
-            startRectangle: function(latlng, options) {
-                let corner = latlng || L.latLng([0, 0])
-                let bounds = new L.LatLngBounds(corner, corner)
-                let rectangle = this.createRectangle(bounds, options)
-                rectangle.enableEdit(this.map).startDrawing()
-                return rectangle
-            },
-
-            // 馃崅method startCircle(latlng: L.LatLng, options: hash): L.Circle
-            // Start drawing a Circle. If `latlng` is given, the Circle anchor will be added. In any case, continuing on user drag.
-            // If `options` is given, it will be passed to the Circle class constructor.
-            startCircle: function(latlng, options) {
-                latlng = latlng || this.map.getCenter().clone()
-                let circle = this.createCircle(latlng, options)
-                circle.enableEdit(this.map).startDrawing()
-                return circle
-            },
-
-            startHole: function(editor, latlng) {
-                editor.newHole(latlng)
-            },
-
-            createLayer: function(Klass, latlngs, options) {
-                options = L.Util.extend({ editOptions: { editTools: this } }, options)
-                let layer = new Klass(latlngs, options)
-                // 馃崅namespace Editable
-                // 馃崅event editable:created: LayerEvent
-                // Fired when a new feature (Marker, Polyline鈥�) is created.
-                this.fireAndForward('editable:created', { layer: layer })
-                return layer
-            },
-
-            createPolyline: function(latlngs, options) {
-                return this.createLayer((options && options.polylineClass) || this.options.polylineClass, latlngs, options)
-            },
-
-            createPolygon: function(latlngs, options) {
-                return this.createLayer((options && options.polygonClass) || this.options.polygonClass, latlngs, options)
-            },
-
-            createMarker: function(latlng, options) {
-                return this.createLayer((options && options.markerClass) || this.options.markerClass, latlng, options)
-            },
-
-            createRectangle: function(bounds, options) {
-                return this.createLayer((options && options.rectangleClass) || this.options.rectangleClass, bounds, options)
-            },
-
-            createCircle: function(latlng, options) {
-                return this.createLayer((options && options.circleClass) || this.options.circleClass, latlng, options)
-            }
-
-        })
-
-        L.extend(L.Editable, {
-
-            makeCancellable: function(e) {
-                e.cancel = function() {
-                    e._cancelled = true
-                }
-            }
-
-        })
-
-        // 馃崅namespace Map; 馃崅class Map
-        // Leaflet.Editable add options and events to the `L.Map` object.
-        // See `Editable` events for the list of events fired on the Map.
-        // 馃崅example
-        //
-        // ```js
-        // let map = L.map('map', {
-        //  editable: true,
-        //  editOptions: {
-        //    鈥�
-        // }
-        // });
-        // ```
-        // 馃崅section Editable Map Options
-        L.Map.mergeOptions({
-
-            // 馃崅namespace Map
-            // 馃崅section Map Options
-            // 馃崅option EditToolsClass: class = L.Editable
-            // Class to be used as vertex, for path editing.
-            EditToolsClass: L.Editable,
-
-            // 馃崅option editable: boolean = false
-            // Whether to create a L.Editable instance at map init.
-            editable: false,
-
-            // 馃崅option editOptions: hash = {}
-            // Options to pass to L.Editable when instantiating.
-            editOptions: {}
-
-        })
-
-        L.Map.addInitHook(function() {
-            this.whenReady(function() {
-                if (this.options.editable) {
-                    this.editTools = new this.options.EditToolsClass(this, this.options.editOptions)
-                }
-            })
-        })
-
-        L.Editable.VertexIcon = L.DivIcon.extend({
-
-            options: {
-                iconSize: new L.Point(8, 8)
-            }
-
-        })
-
-        L.Editable.TouchVertexIcon = L.Editable.VertexIcon.extend({
-
-            options: {
-                iconSize: new L.Point(20, 20)
-            }
-
-        })
-
-        // 馃崅namespace Editable; 馃崅class VertexMarker; Handler for dragging path vertices.
-        L.Editable.VertexMarker = L.Marker.extend({
-
-            options: {
-                draggable: true,
-                className: 'leaflet-vertex-icon leaflet-custom-icon'
-            },
-
-            // 馃崅section Public methods
-            // The marker used to handle path vertex. You will usually interact with a `VertexMarker`
-            // instance when listening for events like `editable:vertex:ctrlclick`.
-
-            initialize: function(latlng, latlngs, editor, options) {
-                // We don't use this._latlng, because on drag Leaflet replace it while
-                // we want to keep reference.
-                this.latlng = latlng
-                this.latlngs = latlngs
-                this.editor = editor
-                L.Marker.prototype.initialize.call(this, latlng, options)
-                this.options.icon = this.editor.tools.createVertexIcon({ className: this.options.className })
-                this.latlng.__vertex = this
-                this.editor.editLayer.addLayer(this)
-                this.setZIndexOffset(editor.tools._lastZIndex + 1)
-            },
-
-            onAdd: function(map) {
-                L.Marker.prototype.onAdd.call(this, map)
-                this.on('drag', this.onDrag)
-                this.on('dragstart', this.onDragStart)
-                this.on('dragend', this.onDragEnd)
-                this.on('mouseup', this.onMouseup)
-                this.on('click', this.onClick)
-                this.on('contextmenu', this.onContextMenu)
-                this.on('mousedown touchstart', this.onMouseDown)
-                this.on('mouseover', this.onMouseOver)
-                this.on('mouseout', this.onMouseOut)
-                this.addMiddleMarkers()
-            },
-
-            onRemove: function(map) {
-                if (this.middleMarker) this.middleMarker.delete()
-                delete this.latlng.__vertex
-                this.off('drag', this.onDrag)
-                this.off('dragstart', this.onDragStart)
-                this.off('dragend', this.onDragEnd)
-                this.off('mouseup', this.onMouseup)
-                this.off('click', this.onClick)
-                this.off('contextmenu', this.onContextMenu)
-                this.off('mousedown touchstart', this.onMouseDown)
-                this.off('mouseover', this.onMouseOver)
-                this.off('mouseout', this.onMouseOut)
-                L.Marker.prototype.onRemove.call(this, map)
-            },
-
-            onDrag: function(e) {
-                e.vertex = this
-                this.editor.onVertexMarkerDrag(e)
-                let iconPos = L.DomUtil.getPosition(this._icon)
-                let latlng = this._map.layerPointToLatLng(iconPos)
-                this.latlng.update(latlng)
-                this._latlng = this.latlng // Push back to Leaflet our reference.
-                this.editor.refresh()
-                if (this.middleMarker) this.middleMarker.updateLatLng()
-                let next = this.getNext()
-                if (next && next.middleMarker) next.middleMarker.updateLatLng()
-            },
-
-            onDragStart: function(e) {
-                e.vertex = this
-                this.editor.onVertexMarkerDragStart(e)
-            },
-
-            onDragEnd: function(e) {
-                e.vertex = this
-                this.editor.onVertexMarkerDragEnd(e)
-            },
-
-            onClick: function(e) {
-                e.vertex = this
-                this.editor.onVertexMarkerClick(e)
-            },
-
-            onMouseup: function(e) {
-                L.DomEvent.stop(e)
-                e.vertex = this
-                this.editor.map.fire('mouseup', e)
-            },
-
-            onContextMenu: function(e) {
-                e.vertex = this
-                this.editor.onVertexMarkerContextMenu(e)
-            },
-
-            onMouseDown: function(e) {
-                e.vertex = this
-                this.editor.onVertexMarkerMouseDown(e)
-            },
-
-            onMouseOver: function(e) {
-                e.vertex = this
-                this.editor.onVertexMarkerMouseOver(e)
-            },
-
-            onMouseOut: function(e) {
-                e.vertex = this
-                this.editor.onVertexMarkerMouseOut(e)
-            },
-
-            // 馃崅method delete()
-            // Delete a vertex and the related LatLng.
-            delete: function() {
-                let next = this.getNext() // Compute before changing latlng
-                this.latlngs.splice(this.getIndex(), 1)
-                this.editor.editLayer.removeLayer(this)
-                this.editor.onVertexDeleted({ latlng: this.latlng, vertex: this })
-                if (!this.latlngs.length) this.editor.deleteShape(this.latlngs)
-                if (next) next.resetMiddleMarker()
-                this.editor.refresh()
-            },
-
-            // 馃崅method getIndex(): int
-            // Get the index of the current vertex among others of the same LatLngs group.
-            getIndex: function() {
-                return this.latlngs.indexOf(this.latlng)
-            },
-
-            // 馃崅method getLastIndex(): int
-            // Get last vertex index of the LatLngs group of the current vertex.
-            getLastIndex: function() {
-                return this.latlngs.length - 1
-            },
-
-            // 馃崅method getPrevious(): VertexMarker
-            // Get the previous VertexMarker in the same LatLngs group.
-            getPrevious: function() {
-                if (this.latlngs.length < 2) return
-                let index = this.getIndex()
-                let previousIndex = index - 1
-                if (index === 0 && this.editor.CLOSED) previousIndex = this.getLastIndex()
-                let previous = this.latlngs[previousIndex]
-                if (previous) return previous.__vertex
-            },
-
-            // 馃崅method getNext(): VertexMarker
-            // Get the next VertexMarker in the same LatLngs group.
-            getNext: function() {
-                if (this.latlngs.length < 2) return
-                let index = this.getIndex()
-                let nextIndex = index + 1
-                if (index === this.getLastIndex() && this.editor.CLOSED) nextIndex = 0
-                let next = this.latlngs[nextIndex]
-                if (next) return next.__vertex
-            },
-
-            addMiddleMarker: function(previous) {
-                if (!this.editor.hasMiddleMarkers()) return
-                previous = previous || this.getPrevious()
-                if (previous && !this.middleMarker) this.middleMarker = this.editor.addMiddleMarker(previous, this, this.latlngs, this.editor)
-            },
-
-            addMiddleMarkers: function() {
-                if (!this.editor.hasMiddleMarkers()) return
-                let previous = this.getPrevious()
-                if (previous) this.addMiddleMarker(previous)
-                let next = this.getNext()
-                if (next) next.resetMiddleMarker()
-            },
-
-            resetMiddleMarker: function() {
-                if (this.middleMarker) this.middleMarker.delete()
-                this.addMiddleMarker()
-            },
-
-            // 馃崅method split()
-            // Split the vertex LatLngs group at its index, if possible.
-            split: function() {
-                if (!this.editor.splitShape) return // Only for PolylineEditor
-                this.editor.splitShape(this.latlngs, this.getIndex())
-            },
-
-            // 馃崅method continue()
-            // Continue the vertex LatLngs from this vertex. Only active for first and last vertices of a Polyline.
-            continue: function() {
-                if (!this.editor.continueBackward) return // Only for PolylineEditor
-                let index = this.getIndex()
-                if (index === 0) this.editor.continueBackward(this.latlngs)
-                else if (index === this.getLastIndex()) this.editor.continueForward(this.latlngs)
-            }
-
-        })
-
-        L.Editable.mergeOptions({
-
-            // 馃崅namespace Editable
-            // 馃崅option VertexMarkerClass: class = VertexMarker
-            // Class to be used as vertex, for path editing.
-            VertexMarkerClass: L.Editable.VertexMarker
-
-        })
-
-        L.Editable.MiddleMarker = L.Marker.extend({
-
-            options: {
-                opacity: 0.5,
-                className: 'leaflet-div-icon leaflet-middle-icon',
-                draggable: true
-            },
-
-            initialize: function(left, right, latlngs, editor, options) {
-                this.left = left
-                this.right = right
-                this.editor = editor
-                this.latlngs = latlngs
-                L.Marker.prototype.initialize.call(this, this.computeLatLng(), options)
-                this._opacity = this.options.opacity
-                this.options.icon = this.editor.tools.createVertexIcon({ className: this.options.className })
-                this.editor.editLayer.addLayer(this)
-                this.setVisibility()
-            },
-
-            setVisibility: function() {
-                let leftPoint = this._map.latLngToContainerPoint(this.left.latlng)
-                let rightPoint = this._map.latLngToContainerPoint(this.right.latlng)
-                let size = L.point(this.options.icon.options.iconSize)
-                if (leftPoint.distanceTo(rightPoint) < size.x * 3) this.hide()
-                else this.show()
-            },
-
-            show: function() {
-                this.setOpacity(this._opacity)
-            },
-
-            hide: function() {
-                this.setOpacity(0)
-            },
-
-            updateLatLng: function() {
-                this.setLatLng(this.computeLatLng())
-                this.setVisibility()
-            },
-
-            computeLatLng: function() {
-                let leftPoint = this.editor.map.latLngToContainerPoint(this.left.latlng)
-                let rightPoint = this.editor.map.latLngToContainerPoint(this.right.latlng)
-                let y = (leftPoint.y + rightPoint.y) / 2
-                let x = (leftPoint.x + rightPoint.x) / 2
-                return this.editor.map.containerPointToLatLng([x, y])
-            },
-
-            onAdd: function(map) {
-                L.Marker.prototype.onAdd.call(this, map)
-                L.DomEvent.on(this._icon, 'mousedown touchstart', this.onMouseDown, this)
-                map.on('zoomend', this.setVisibility, this)
-            },
-
-            onRemove: function(map) {
-                delete this.right.middleMarker
-                L.DomEvent.off(this._icon, 'mousedown touchstart', this.onMouseDown, this)
-                map.off('zoomend', this.setVisibility, this)
-                L.Marker.prototype.onRemove.call(this, map)
-            },
-
-            onMouseDown: function(e) {
-                let iconPos = L.DomUtil.getPosition(this._icon)
-                let latlng = this.editor.map.layerPointToLatLng(iconPos)
-                e = {
-                    originalEvent: e,
-                    latlng: latlng
-                }
-                if (this.options.opacity === 0) return
-                L.Editable.makeCancellable(e)
-                this.editor.onMiddleMarkerMouseDown(e)
-                if (e._cancelled) return
-                this.latlngs.splice(this.index(), 0, e.latlng)
-                this.editor.refresh()
-                let icon = this._icon
-                let marker = this.editor.addVertexMarker(e.latlng, this.latlngs)
-                this.editor.onNewVertex(marker)
-                /* Hack to workaround browser not firing touchend when element is no more on DOM */
-                let parent = marker._icon.parentNode
-                parent.removeChild(marker._icon)
-                marker._icon = icon
-                parent.appendChild(marker._icon)
-                marker._initIcon()
-                marker._initInteraction()
-                marker.setOpacity(1)
-                /* End hack */
-                // Transfer ongoing dragging to real marker
-                L.Draggable._dragging = false
-                marker.dragging._draggable._onDown(e.originalEvent)
-                this.delete()
-            },
-
-            delete: function() {
-                this.editor.editLayer.removeLayer(this)
-            },
-
-            index: function() {
-                return this.latlngs.indexOf(this.right.latlng)
-            }
-
-        })
-
-        L.Editable.mergeOptions({
-
-            // 馃崅namespace Editable
-            // 馃崅option MiddleMarkerClass: class = VertexMarker
-            // Class to be used as middle vertex, pulled by the user to create a new point in the middle of a path.
-            MiddleMarkerClass: L.Editable.MiddleMarker
-
-        })
-
-        // 馃崅namespace Editable; 馃崅class BaseEditor; 馃崅aka L.Editable.BaseEditor
-        // When editing a feature (Marker, Polyline鈥�), an editor is attached to it. This
-        // editor basically knows how to handle the edition.
-        L.Editable.BaseEditor = L.Handler.extend({
-
-            initialize: function(map, feature, options) {
-                L.setOptions(this, options)
-                this.map = map
-                this.feature = feature
-                this.feature.editor = this
-                this.editLayer = new L.LayerGroup()
-                this.tools = this.options.editTools || map.editTools
-            },
-
-            // 馃崅method enable(): this
-            // Set up the drawing tools for the feature to be editable.
-            addHooks: function() {
-                if (this.isConnected()) this.onFeatureAdd()
-                else this.feature.once('add', this.onFeatureAdd, this)
-                this.onEnable()
-                this.feature.on(this._getEvents(), this)
-            },
-
-            // 馃崅method disable(): this
-            // Remove the drawing tools for the feature.
-            removeHooks: function() {
-                this.feature.off(this._getEvents(), this)
-                if (this.feature.dragging) this.feature.dragging.disable()
-                this.editLayer.clearLayers()
-                this.tools.editLayer.removeLayer(this.editLayer)
-                this.onDisable()
-                if (this._drawing) this.cancelDrawing()
-            },
-
-            // 馃崅method drawing(): boolean
-            // Return true if any drawing action is ongoing with this editor.
-            drawing: function() {
-                return !!this._drawing
-            },
-
-            reset: function() {
-            },
-
-            onFeatureAdd: function() {
-                this.tools.editLayer.addLayer(this.editLayer)
-                if (this.feature.dragging) this.feature.dragging.enable()
-            },
-
-            hasMiddleMarkers: function() {
-                return !this.options.skipMiddleMarkers && !this.tools.options.skipMiddleMarkers
-            },
-
-            fireAndForward: function(type, e) {
-                e = e || {}
-                e.layer = this.feature
-                this.feature.fire(type, e)
-                this.tools.fireAndForward(type, e)
-            },
-
-            onEnable: function() {
-                // 馃崅namespace Editable
-                // 馃崅event editable:enable: Event
-                // Fired when an existing feature is ready to be edited.
-                this.fireAndForward('editable:enable')
-            },
-
-            onDisable: function() {
-                // 馃崅namespace Editable
-                // 馃崅event editable:disable: Event
-                // Fired when an existing feature is not ready anymore to be edited.
-                this.fireAndForward('editable:disable')
-            },
-
-            onEditing: function() {
-                // 馃崅namespace Editable
-                // 馃崅event editable:editing: Event
-                // Fired as soon as any change is made to the feature geometry.
-                this.fireAndForward('editable:editing')
-            },
-
-            onStartDrawing: function() {
-                // 馃崅namespace Editable
-                // 馃崅section Drawing events
-                // 馃崅event editable:drawing:start: Event
-                // Fired when a feature is to be drawn.
-                this.fireAndForward('editable:drawing:start')
-            },
-
-            onEndDrawing: function() {
-                // 馃崅namespace Editable
-                // 馃崅section Drawing events
-                // 馃崅event editable:drawing:end: Event
-                // Fired when a feature is not drawn anymore.
-                this.fireAndForward('editable:drawing:end')
-            },
-
-            onCancelDrawing: function() {
-                // 馃崅namespace Editable
-                // 馃崅section Drawing events
-                // 馃崅event editable:drawing:cancel: Event
-                // Fired when user cancel drawing while a feature is being drawn.
-                this.fireAndForward('editable:drawing:cancel')
-            },
-
-            onCommitDrawing: function(e) {
-                // 馃崅namespace Editable
-                // 馃崅section Drawing events
-                // 馃崅event editable:drawing:commit: Event
-                // Fired when user finish drawing a feature.
-                this.fireAndForward('editable:drawing:commit', e)
-            },
-
-            onDrawingMouseDown: function(e) {
-                // 馃崅namespace Editable
-                // 馃崅section Drawing events
-                // 馃崅event editable:drawing:mousedown: Event
-                // Fired when user `mousedown` while drawing.
-                this.fireAndForward('editable:drawing:mousedown', e)
-            },
-
-            onDrawingMouseUp: function(e) {
-                // 馃崅namespace Editable
-                // 馃崅section Drawing events
-                // 馃崅event editable:drawing:mouseup: Event
-                // Fired when user `mouseup` while drawing.
-                this.fireAndForward('editable:drawing:mouseup', e)
-            },
-
-            startDrawing: function() {
-                if (!this._drawing) this._drawing = L.Editable.FORWARD
-                this.tools.registerForDrawing(this)
-                this.onStartDrawing()
-            },
-
-            commitDrawing: function(e) {
-                this.onCommitDrawing(e)
-                this.endDrawing()
-            },
-
-            cancelDrawing: function() {
-                // If called during a vertex drag, the vertex will be removed before
-                // the mouseup fires on it. This is a workaround. Maybe better fix is
-                // To have L.Draggable reset it's status on disable (Leaflet side).
-                L.Draggable._dragging = false
-                this.onCancelDrawing()
-                this.endDrawing()
-            },
-
-            endDrawing: function() {
-                this._drawing = false
-                this.tools.unregisterForDrawing(this)
-                this.onEndDrawing()
-            },
-
-            onDrawingClick: function(e) {
-                if (!this.drawing()) return
-                L.Editable.makeCancellable(e)
-                // 馃崅namespace Editable
-                // 馃崅section Drawing events
-                // 馃崅event editable:drawing:click: CancelableEvent
-                // Fired when user `click` while drawing, before any internal action is being processed.
-                this.fireAndForward('editable:drawing:click', e)
-                if (e._cancelled) return
-                if (!this.isConnected()) this.connect(e)
-                this.processDrawingClick(e)
-            },
-
-            isConnected: function() {
-                return this.map.hasLayer(this.feature)
-            },
-
-            connect: function() {
-                this.tools.connectCreatedToMap(this.feature)
-                this.tools.editLayer.addLayer(this.editLayer)
-            },
-
-            onMove: function(e) {
-                // 馃崅namespace Editable
-                // 馃崅section Drawing events
-                // 馃崅event editable:drawing:move: Event
-                // Fired when `move` mouse while drawing, while dragging a marker, and while dragging a vertex.
-                this.fireAndForward('editable:drawing:move', e)
-            },
-
-            onDrawingMouseMove: function(e) {
-                this.onMove(e)
-            },
-
-            _getEvents: function() {
-                return {
-                    dragstart: this.onDragStart,
-                    drag: this.onDrag,
-                    dragend: this.onDragEnd,
-                    remove: this.disable
-                }
-            },
-
-            onDragStart: function(e) {
-                this.onEditing()
-                // 馃崅namespace Editable
-                // 馃崅event editable:dragstart: Event
-                // Fired before a path feature is dragged.
-                this.fireAndForward('editable:dragstart', e)
-            },
-
-            onDrag: function(e) {
-                this.onMove(e)
-                // 馃崅namespace Editable
-                // 馃崅event editable:drag: Event
-                // Fired when a path feature is being dragged.
-                this.fireAndForward('editable:drag', e)
-            },
-
-            onDragEnd: function(e) {
-                // 馃崅namespace Editable
-                // 馃崅event editable:dragend: Event
-                // Fired after a path feature has been dragged.
-                this.fireAndForward('editable:dragend', e)
-            }
-
-        })
-
-        // 馃崅namespace Editable; 馃崅class MarkerEditor; 馃崅aka L.Editable.MarkerEditor
-        // 馃崅inherits BaseEditor
-        // Editor for Marker.
-        L.Editable.MarkerEditor = L.Editable.BaseEditor.extend({
-
-            onDrawingMouseMove: function(e) {
-                L.Editable.BaseEditor.prototype.onDrawingMouseMove.call(this, e)
-                if (this._drawing) this.feature.setLatLng(e.latlng)
-            },
-
-            processDrawingClick: function(e) {
-                // 馃崅namespace Editable
-                // 馃崅section Drawing events
-                // 馃崅event editable:drawing:clicked: Event
-                // Fired when user `click` while drawing, after all internal actions.
-                this.fireAndForward('editable:drawing:clicked', e)
-                this.commitDrawing(e)
-            },
-
-            connect: function(e) {
-                // On touch, the latlng has not been updated because there is
-                // no mousemove.
-                if (e) this.feature._latlng = e.latlng
-                L.Editable.BaseEditor.prototype.connect.call(this, e)
-            }
-
-        })
-
-        // 馃崅namespace Editable; 馃崅class PathEditor; 馃崅aka L.Editable.PathEditor
-        // 馃崅inherits BaseEditor
-        // Base class for all path editors.
-        L.Editable.PathEditor = L.Editable.BaseEditor.extend({
-
-            CLOSED: false,
-            MIN_VERTEX: 2,
-
-            addHooks: function() {
-                L.Editable.BaseEditor.prototype.addHooks.call(this)
-                if (this.feature) this.initVertexMarkers()
-                return this
-            },
-
-            initVertexMarkers: function(latlngs) {
-                if (!this.enabled()) return
-                latlngs = latlngs || this.getLatLngs()
-                if (isFlat(latlngs)) this.addVertexMarkers(latlngs)
-                else for (let i = 0; i < latlngs.length; i++) this.initVertexMarkers(latlngs[i])
-            },
-
-            getLatLngs: function() {
-                return this.feature.getLatLngs()
-            },
-
-            // 馃崅method reset()
-            // Rebuild edit elements (Vertex, MiddleMarker, etc.).
-            reset: function() {
-                this.editLayer.clearLayers()
-                this.initVertexMarkers()
-            },
-
-            addVertexMarker: function(latlng, latlngs) {
-                return new this.tools.options.VertexMarkerClass(latlng, latlngs, this)
-            },
-
-            onNewVertex: function(vertex) {
-                // 馃崅namespace Editable
-                // 馃崅section Vertex events
-                // 馃崅event editable:vertex:new: VertexEvent
-                // Fired when a new vertex is created.
-                this.fireAndForward('editable:vertex:new', { latlng: vertex.latlng, vertex: vertex })
-            },
-
-            addVertexMarkers: function(latlngs) {
-                for (let i = 0; i < latlngs.length; i++) {
-                    this.addVertexMarker(latlngs[i], latlngs)
-                }
-            },
-
-            refreshVertexMarkers: function(latlngs) {
-                latlngs = latlngs || this.getDefaultLatLngs()
-                for (let i = 0; i < latlngs.length; i++) {
-                    latlngs[i].__vertex.update()
-                }
-            },
-
-            addMiddleMarker: function(left, right, latlngs) {
-                return new this.tools.options.MiddleMarkerClass(left, right, latlngs, this)
-            },
-
-            onVertexMarkerClick: function(e) {
-                L.Editable.makeCancellable(e)
-                // 馃崅namespace Editable
-                // 馃崅section Vertex events
-                // 馃崅event editable:vertex:click: CancelableVertexEvent
-                // Fired when a `click` is issued on a vertex, before any internal action is being processed.
-                this.fireAndForward('editable:vertex:click', e)
-                if (e._cancelled) return
-                if (this.tools.drawing() && this.tools._drawingEditor !== this) return
-                let index = e.vertex.getIndex()
-                let commit
-                if (e.originalEvent.ctrlKey) {
-                    this.onVertexMarkerCtrlClick(e)
-                } else if (e.originalEvent.altKey) {
-                    this.onVertexMarkerAltClick(e)
-                } else if (e.originalEvent.shiftKey) {
-                    this.onVertexMarkerShiftClick(e)
-                } else if (e.originalEvent.metaKey) {
-                    this.onVertexMarkerMetaKeyClick(e)
-                } else if (index === e.vertex.getLastIndex() && this._drawing === L.Editable.FORWARD) {
-                    if (index >= this.MIN_VERTEX - 1) commit = true
-                } else if (index === 0 && this._drawing === L.Editable.BACKWARD && this._drawnLatLngs.length >= this.MIN_VERTEX) {
-                    commit = true
-                } else if (index === 0 && this._drawing === L.Editable.FORWARD && this._drawnLatLngs.length >= this.MIN_VERTEX && this.CLOSED) {
-                    commit = true // Allow to close on first point also for polygons
-                } else {
-                    this.onVertexRawMarkerClick(e)
-                }
-                // 馃崅namespace Editable
-                // 馃崅section Vertex events
-                // 馃崅event editable:vertex:clicked: VertexEvent
-                // Fired when a `click` is issued on a vertex, after all internal actions.
-                this.fireAndForward('editable:vertex:clicked', e)
-                if (commit) this.commitDrawing(e)
-            },
-
-            onVertexRawMarkerClick: function(e) {
-                // 馃崅namespace Editable
-                // 馃崅section Vertex events
-                // 馃崅event editable:vertex:rawclick: CancelableVertexEvent
-                // Fired when a `click` is issued on a vertex without any special key and without being in drawing mode.
-                this.fireAndForward('editable:vertex:rawclick', e)
-                if (e._cancelled) return
-                if (!this.vertexCanBeDeleted(e.vertex)) return
-                e.vertex.delete()
-            },
-
-            vertexCanBeDeleted: function(vertex) {
-                return vertex.latlngs.length > this.MIN_VERTEX
-            },
-
-            onVertexDeleted: function(e) {
-                // 馃崅namespace Editable
-                // 馃崅section Vertex events
-                // 馃崅event editable:vertex:deleted: VertexEvent
-                // Fired after a vertex has been deleted by user.
-                this.fireAndForward('editable:vertex:deleted', e)
-            },
-
-            onVertexMarkerCtrlClick: function(e) {
-                // 馃崅namespace Editable
-                // 馃崅section Vertex events
-                // 馃崅event editable:vertex:ctrlclick: VertexEvent
-                // Fired when a `click` with `ctrlKey` is issued on a vertex.
-                this.fireAndForward('editable:vertex:ctrlclick', e)
-            },
-
-            onVertexMarkerShiftClick: function(e) {
-                // 馃崅namespace Editable
-                // 馃崅section Vertex events
-                // 馃崅event editable:vertex:shiftclick: VertexEvent
-                // Fired when a `click` with `shiftKey` is issued on a vertex.
-                this.fireAndForward('editable:vertex:shiftclick', e)
-            },
-
-            onVertexMarkerMetaKeyClick: function(e) {
-                // 馃崅namespace Editable
-                // 馃崅section Vertex events
-                // 馃崅event editable:vertex:metakeyclick: VertexEvent
-                // Fired when a `click` with `metaKey` is issued on a vertex.
-                this.fireAndForward('editable:vertex:metakeyclick', e)
-            },
-
-            onVertexMarkerAltClick: function(e) {
-                // 馃崅namespace Editable
-                // 馃崅section Vertex events
-                // 馃崅event editable:vertex:altclick: VertexEvent
-                // Fired when a `click` with `altKey` is issued on a vertex.
-                this.fireAndForward('editable:vertex:altclick', e)
-            },
-
-            onVertexMarkerContextMenu: function(e) {
-                // 馃崅namespace Editable
-                // 馃崅section Vertex events
-                // 馃崅event editable:vertex:contextmenu: VertexEvent
-                // Fired when a `contextmenu` is issued on a vertex.
-                this.fireAndForward('editable:vertex:contextmenu', e)
-            },
-
-            onVertexMarkerMouseDown: function(e) {
-                // 馃崅namespace Editable
-                // 馃崅section Vertex events
-                // 馃崅event editable:vertex:mousedown: VertexEvent
-                // Fired when user `mousedown` a vertex.
-                this.fireAndForward('editable:vertex:mousedown', e)
-            },
-
-            onVertexMarkerMouseOver: function(e) {
-                // 馃崅namespace Editable
-                // 馃崅section Vertex events
-                // 馃崅event editable:vertex:mouseover: VertexEvent
-                // Fired when a user's mouse enters the vertex
-                this.fireAndForward('editable:vertex:mouseover', e)
-            },
-
-            onVertexMarkerMouseOut: function(e) {
-                // 馃崅namespace Editable
-                // 馃崅section Vertex events
-                // 馃崅event editable:vertex:mouseout: VertexEvent
-                // Fired when a user's mouse leaves the vertex
-                this.fireAndForward('editable:vertex:mouseout', e)
-            },
-
-            onMiddleMarkerMouseDown: function(e) {
-                // 馃崅namespace Editable
-                // 馃崅section MiddleMarker events
-                // 馃崅event editable:middlemarker:mousedown: VertexEvent
-                // Fired when user `mousedown` a middle marker.
-                this.fireAndForward('editable:middlemarker:mousedown', e)
-            },
-
-            onVertexMarkerDrag: function(e) {
-                this.onMove(e)
-                if (this.feature._bounds) this.extendBounds(e)
-                // 馃崅namespace Editable
-                // 馃崅section Vertex events
-                // 馃崅event editable:vertex:drag: VertexEvent
-                // Fired when a vertex is dragged by user.
-                this.fireAndForward('editable:vertex:drag', e)
-            },
-
-            onVertexMarkerDragStart: function(e) {
-                // 馃崅namespace Editable
-                // 馃崅section Vertex events
-                // 馃崅event editable:vertex:dragstart: VertexEvent
-                // Fired before a vertex is dragged by user.
-                this.fireAndForward('editable:vertex:dragstart', e)
-            },
-
-            onVertexMarkerDragEnd: function(e) {
-                // 馃崅namespace Editable
-                // 馃崅section Vertex events
-                // 馃崅event editable:vertex:dragend: VertexEvent
-                // Fired after a vertex is dragged by user.
-                this.fireAndForward('editable:vertex:dragend', e)
-            },
-
-            setDrawnLatLngs: function(latlngs) {
-                this._drawnLatLngs = latlngs || this.getDefaultLatLngs()
-            },
-
-            startDrawing: function() {
-                if (!this._drawnLatLngs) this.setDrawnLatLngs()
-                L.Editable.BaseEditor.prototype.startDrawing.call(this)
-            },
-
-            startDrawingForward: function() {
-                this.startDrawing()
-            },
-
-            endDrawing: function() {
-                this.tools.detachForwardLineGuide()
-                this.tools.detachBackwardLineGuide()
-                if (this._drawnLatLngs && this._drawnLatLngs.length < this.MIN_VERTEX) this.deleteShape(this._drawnLatLngs)
-                L.Editable.BaseEditor.prototype.endDrawing.call(this)
-                delete this._drawnLatLngs
-            },
-
-            addLatLng: function(latlng) {
-                if (this._drawing === L.Editable.FORWARD) this._drawnLatLngs.push(latlng)
-                else this._drawnLatLngs.unshift(latlng)
-                this.feature._bounds.extend(latlng)
-                let vertex = this.addVertexMarker(latlng, this._drawnLatLngs)
-                this.onNewVertex(vertex)
-                this.refresh()
-            },
-
-            newPointForward: function(latlng) {
-                this.addLatLng(latlng)
-                this.tools.attachForwardLineGuide()
-                this.tools.anchorForwardLineGuide(latlng)
-            },
-
-            newPointBackward: function(latlng) {
-                this.addLatLng(latlng)
-                this.tools.anchorBackwardLineGuide(latlng)
-            },
-
-            // 馃崅namespace PathEditor
-            // 馃崅method push()
-            // Programmatically add a point while drawing.
-            push: function(latlng) {
-                if (!latlng) return console.error('L.Editable.PathEditor.push expect a valid latlng as parameter')
-                if (this._drawing === L.Editable.FORWARD) this.newPointForward(latlng)
-                else this.newPointBackward(latlng)
-            },
-
-            removeLatLng: function(latlng) {
-                latlng.__vertex.delete()
-                this.refresh()
-            },
-
-            // 馃崅method pop(): L.LatLng or null
-            // Programmatically remove last point (if any) while drawing.
-            pop: function() {
-                if (this._drawnLatLngs.length <= 1) return
-                let latlng
-                if (this._drawing === L.Editable.FORWARD) latlng = this._drawnLatLngs[this._drawnLatLngs.length - 1]
-                else latlng = this._drawnLatLngs[0]
-                this.removeLatLng(latlng)
-                if (this._drawing === L.Editable.FORWARD) this.tools.anchorForwardLineGuide(this._drawnLatLngs[this._drawnLatLngs.length - 1])
-                else this.tools.anchorForwardLineGuide(this._drawnLatLngs[0])
-                return latlng
-            },
-
-            processDrawingClick: function(e) {
-                if (e.vertex && e.vertex.editor === this) return
-                if (this._drawing === L.Editable.FORWARD) this.newPointForward(e.latlng)
-                else this.newPointBackward(e.latlng)
-                this.fireAndForward('editable:drawing:clicked', e)
-            },
-
-            onDrawingMouseMove: function(e) {
-                L.Editable.BaseEditor.prototype.onDrawingMouseMove.call(this, e)
-                if (this._drawing) {
-                    this.tools.moveForwardLineGuide(e.latlng)
-                    this.tools.moveBackwardLineGuide(e.latlng)
-                }
-            },
-
-            refresh: function() {
-                this.feature.redraw()
-                this.onEditing()
-            },
-
-            // 馃崅namespace PathEditor
-            // 馃崅method newShape(latlng?: L.LatLng)
-            // Add a new shape (Polyline, Polygon) in a multi, and setup up drawing tools to draw it;
-            // if optional `latlng` is given, start a path at this point.
-            newShape: function(latlng) {
-                let shape = this.addNewEmptyShape()
-                if (!shape) return
-                this.setDrawnLatLngs(shape[0] || shape) // Polygon or polyline
-                this.startDrawingForward()
-                // 馃崅namespace Editable
-                // 馃崅section Shape events
-                // 馃崅event editable:shape:new: ShapeEvent
-                // Fired when a new shape is created in a multi (Polygon or Polyline).
-                this.fireAndForward('editable:shape:new', { shape: shape })
-                if (latlng) this.newPointForward(latlng)
-            },
-
-            deleteShape: function(shape, latlngs) {
-                let e = { shape: shape }
-                L.Editable.makeCancellable(e)
-                // 馃崅namespace Editable
-                // 馃崅section Shape events
-                // 馃崅event editable:shape:delete: CancelableShapeEvent
-                // Fired before a new shape is deleted in a multi (Polygon or Polyline).
-                this.fireAndForward('editable:shape:delete', e)
-                if (e._cancelled) return
-                shape = this._deleteShape(shape, latlngs)
-                if (this.ensureNotFlat) this.ensureNotFlat() // Polygon.
-                this.feature.setLatLngs(this.getLatLngs()) // Force bounds reset.
-                this.refresh()
-                this.reset()
-                // 馃崅namespace Editable
-                // 馃崅section Shape events
-                // 馃崅event editable:shape:deleted: ShapeEvent
-                // Fired after a new shape is deleted in a multi (Polygon or Polyline).
-                this.fireAndForward('editable:shape:deleted', { shape: shape })
-                return shape
-            },
-
-            _deleteShape: function(shape, latlngs) {
-                latlngs = latlngs || this.getLatLngs()
-                if (!latlngs.length) return
-                let self = this
-                let inplaceDelete = function(latlngs, shape) {
-                    // Called when deleting a flat latlngs
-                    shape = latlngs.splice(0, Number.MAX_VALUE)
-                    return shape
-                }
-                let spliceDelete = function(latlngs, shape) {
-                    // Called when removing a latlngs inside an array
-                    latlngs.splice(latlngs.indexOf(shape), 1)
-                    if (!latlngs.length) self._deleteShape(latlngs)
-                    return shape
-                }
-                if (latlngs === shape) return inplaceDelete(latlngs, shape)
-                for (let i = 0; i < latlngs.length; i++) {
-                    if (latlngs[i] === shape) return spliceDelete(latlngs, shape)
-                    else if (latlngs[i].indexOf(shape) !== -1) return spliceDelete(latlngs[i], shape)
-                }
-            },
-
-            // 馃崅namespace PathEditor
-            // 馃崅method deleteShapeAt(latlng: L.LatLng): Array
-            // Remove a path shape at the given `latlng`.
-            deleteShapeAt: function(latlng) {
-                let shape = this.feature.shapeAt(latlng)
-                if (shape) return this.deleteShape(shape)
-            },
-
-            // 馃崅method appendShape(shape: Array)
-            // Append a new shape to the Polygon or Polyline.
-            appendShape: function(shape) {
-                this.insertShape(shape)
-            },
-
-            // 馃崅method prependShape(shape: Array)
-            // Prepend a new shape to the Polygon or Polyline.
-            prependShape: function(shape) {
-                this.insertShape(shape, 0)
-            },
-
-            // 馃崅method insertShape(shape: Array, index: int)
-            // Insert a new shape to the Polygon or Polyline at given index (default is to append).
-            insertShape: function(shape, index) {
-                this.ensureMulti()
-                shape = this.formatShape(shape)
-                if (typeof index === 'undefined') index = this.feature._latlngs.length
-                this.feature._latlngs.splice(index, 0, shape)
-                this.feature.redraw()
-                if (this._enabled) this.reset()
-            },
-
-            extendBounds: function(e) {
-                this.feature._bounds.extend(e.vertex.latlng)
-            },
-
-            onDragStart: function(e) {
-                this.editLayer.clearLayers()
-                L.Editable.BaseEditor.prototype.onDragStart.call(this, e)
-            },
-
-            onDragEnd: function(e) {
-                this.initVertexMarkers()
-                L.Editable.BaseEditor.prototype.onDragEnd.call(this, e)
-            }
-
-        })
-
-        // 馃崅namespace Editable; 馃崅class PolylineEditor; 馃崅aka L.Editable.PolylineEditor
-        // 馃崅inherits PathEditor
-        L.Editable.PolylineEditor = L.Editable.PathEditor.extend({
-
-            startDrawingBackward: function() {
-                this._drawing = L.Editable.BACKWARD
-                this.startDrawing()
-            },
-
-            // 馃崅method continueBackward(latlngs?: Array)
-            // Set up drawing tools to continue the line backward.
-            continueBackward: function(latlngs) {
-                if (this.drawing()) return
-                latlngs = latlngs || this.getDefaultLatLngs()
-                this.setDrawnLatLngs(latlngs)
-                if (latlngs.length > 0) {
-                    this.tools.attachBackwardLineGuide()
-                    this.tools.anchorBackwardLineGuide(latlngs[0])
-                }
-                this.startDrawingBackward()
-            },
-
-            // 馃崅method continueForward(latlngs?: Array)
-            // Set up drawing tools to continue the line forward.
-            continueForward: function(latlngs) {
-                if (this.drawing()) return
-                latlngs = latlngs || this.getDefaultLatLngs()
-                this.setDrawnLatLngs(latlngs)
-                if (latlngs.length > 0) {
-                    this.tools.attachForwardLineGuide()
-                    this.tools.anchorForwardLineGuide(latlngs[latlngs.length - 1])
-                }
-                this.startDrawingForward()
-            },
-
-            getDefaultLatLngs: function(latlngs) {
-                latlngs = latlngs || this.feature._latlngs
-                if (!latlngs.length || latlngs[0] instanceof L.LatLng) return latlngs
-                else return this.getDefaultLatLngs(latlngs[0])
-            },
-
-            ensureMulti: function() {
-                if (this.feature._latlngs.length && isFlat(this.feature._latlngs)) {
-                    this.feature._latlngs = [this.feature._latlngs]
-                }
-            },
-
-            addNewEmptyShape: function() {
-                if (this.feature._latlngs.length) {
-                    let shape = []
-                    this.appendShape(shape)
-                    return shape
-                } else {
-                    return this.feature._latlngs
-                }
-            },
-
-            formatShape: function(shape) {
-                if (isFlat(shape)) return shape
-                else if (shape[0]) return this.formatShape(shape[0])
-            },
-
-            // 馃崅method splitShape(latlngs?: Array, index: int)
-            // Split the given `latlngs` shape at index `index` and integrate new shape in instance `latlngs`.
-            splitShape: function(shape, index) {
-                if (!index || index >= shape.length - 1) return
-                this.ensureMulti()
-                let shapeIndex = this.feature._latlngs.indexOf(shape)
-                if (shapeIndex === -1) return
-                let first = shape.slice(0, index + 1)
-                let second = shape.slice(index)
-                // We deal with reference, we don't want twice the same latlng around.
-                second[0] = L.latLng(second[0].lat, second[0].lng, second[0].alt)
-                this.feature._latlngs.splice(shapeIndex, 1, first, second)
-                this.refresh()
-                this.reset()
-            }
-
-        })
-
-        // 馃崅namespace Editable; 馃崅class PolygonEditor; 馃崅aka L.Editable.PolygonEditor
-        // 馃崅inherits PathEditor
-        L.Editable.PolygonEditor = L.Editable.PathEditor.extend({
-
-            CLOSED: true,
-            MIN_VERTEX: 3,
-
-            newPointForward: function(latlng) {
-                L.Editable.PathEditor.prototype.newPointForward.call(this, latlng)
-                if (!this.tools.backwardLineGuide._latlngs.length) this.tools.anchorBackwardLineGuide(latlng)
-                if (this._drawnLatLngs.length === 2) this.tools.attachBackwardLineGuide()
-            },
-
-            addNewEmptyHole: function(latlng) {
-                this.ensureNotFlat()
-                let latlngs = this.feature.shapeAt(latlng)
-                if (!latlngs) return
-                let holes = []
-                latlngs.push(holes)
-                return holes
-            },
-
-            // 馃崅method newHole(latlng?: L.LatLng, index: int)
-            // Set up drawing tools for creating a new hole on the Polygon. If the `latlng` param is given, a first point is created.
-            newHole: function(latlng) {
-                let holes = this.addNewEmptyHole(latlng)
-                if (!holes) return
-                this.setDrawnLatLngs(holes)
-                this.startDrawingForward()
-                if (latlng) this.newPointForward(latlng)
-            },
-
-            addNewEmptyShape: function() {
-                if (this.feature._latlngs.length && this.feature._latlngs[0].length) {
-                    let shape = []
-                    this.appendShape(shape)
-                    return shape
-                } else {
-                    return this.feature._latlngs
-                }
-            },
-
-            ensureMulti: function() {
-                if (this.feature._latlngs.length && isFlat(this.feature._latlngs[0])) {
-                    this.feature._latlngs = [this.feature._latlngs]
-                }
-            },
-
-            ensureNotFlat: function() {
-                if (!this.feature._latlngs.length || isFlat(this.feature._latlngs)) this.feature._latlngs = [this.feature._latlngs]
-            },
-
-            vertexCanBeDeleted: function(vertex) {
-                let parent = this.feature.parentShape(vertex.latlngs)
-                let idx = L.Util.indexOf(parent, vertex.latlngs)
-                if (idx > 0) return true // Holes can be totally deleted without removing the layer itself.
-                return L.Editable.PathEditor.prototype.vertexCanBeDeleted.call(this, vertex)
-            },
-
-            getDefaultLatLngs: function() {
-                if (!this.feature._latlngs.length) this.feature._latlngs.push([])
-                return this.feature._latlngs[0]
-            },
-
-            formatShape: function(shape) {
-                // [[1, 2], [3, 4]] => must be nested
-                // [] => must be nested
-                // [[]] => is already nested
-                if (isFlat(shape) && (!shape[0] || shape[0].length !== 0)) return [shape]
-                else return shape
-            }
-
-        })
-
-        // 馃崅namespace Editable; 馃崅class RectangleEditor; 馃崅aka L.Editable.RectangleEditor
-        // 馃崅inherits PathEditor
-        L.Editable.RectangleEditor = L.Editable.PathEditor.extend({
-
-            CLOSED: true,
-            MIN_VERTEX: 4,
-
-            options: {
-                skipMiddleMarkers: true
-            },
-
-            extendBounds: function(e) {
-                let index = e.vertex.getIndex()
-                let next = e.vertex.getNext()
-                let previous = e.vertex.getPrevious()
-                let oppositeIndex = (index + 2) % 4
-                let opposite = e.vertex.latlngs[oppositeIndex]
-                let bounds = new L.LatLngBounds(e.latlng, opposite)
-                // Update latlngs by hand to preserve order.
-                previous.latlng.update([e.latlng.lat, opposite.lng])
-                next.latlng.update([opposite.lat, e.latlng.lng])
-                this.updateBounds(bounds)
-                this.refreshVertexMarkers()
-            },
-
-            onDrawingMouseDown: function(e) {
-                L.Editable.PathEditor.prototype.onDrawingMouseDown.call(this, e)
-                this.connect()
-                let latlngs = this.getDefaultLatLngs()
-                // L.Polygon._convertLatLngs removes last latlng if it equals first point,
-                // which is the case here as all latlngs are [0, 0]
-                if (latlngs.length === 3) latlngs.push(e.latlng)
-                let bounds = new L.LatLngBounds(e.latlng, e.latlng)
-                this.updateBounds(bounds)
-                this.updateLatLngs(bounds)
-                this.refresh()
-                this.reset()
-                // Stop dragging map.
-                // L.Draggable has two workflows:
-                // - mousedown => mousemove => mouseup
-                // - touchstart => touchmove => touchend
-                // Problem: L.Map.Tap does not allow us to listen to touchstart, so we only
-                // can deal with mousedown, but then when in a touch device, we are dealing with
-                // simulated events (actually simulated by L.Map.Tap), which are no more taken
-                // into account by L.Draggable.
-                // Ref.: https://github.com/Leaflet/Leaflet.Editable/issues/103
-                e.originalEvent._simulated = false
-                this.map.dragging._draggable._onUp(e.originalEvent)
-                // Now transfer ongoing drag action to the bottom right corner.
-                // Should we refine which corner will handle the drag according to
-                // drag direction?
-                latlngs[3].__vertex.dragging._draggable._onDown(e.originalEvent)
-            },
-
-            onDrawingMouseUp: function(e) {
-                this.commitDrawing(e)
-                e.originalEvent._simulated = false
-                L.Editable.PathEditor.prototype.onDrawingMouseUp.call(this, e)
-            },
-
-            onDrawingMouseMove: function(e) {
-                e.originalEvent._simulated = false
-                L.Editable.PathEditor.prototype.onDrawingMouseMove.call(this, e)
-            },
-
-            getDefaultLatLngs: function(latlngs) {
-                return latlngs || this.feature._latlngs[0]
-            },
-
-            updateBounds: function(bounds) {
-                this.feature._bounds = bounds
-            },
-
-            updateLatLngs: function(bounds) {
-                let latlngs = this.getDefaultLatLngs()
-                let newLatlngs = this.feature._boundsToLatLngs(bounds)
-                // Keep references.
-                for (let i = 0; i < latlngs.length; i++) {
-                    latlngs[i].update(newLatlngs[i])
-                }
-            }
-
-        })
-
-        // 馃崅namespace Editable; 馃崅class CircleEditor; 馃崅aka L.Editable.CircleEditor
-        // 馃崅inherits PathEditor
-        L.Editable.CircleEditor = L.Editable.PathEditor.extend({
-
-            MIN_VERTEX: 2,
-
-            options: {
-                skipMiddleMarkers: true
-            },
-
-            initialize: function(map, feature, options) {
-                L.Editable.PathEditor.prototype.initialize.call(this, map, feature, options)
-                // C.Y.B Modify
-
-                let latlng = this.computeResizeLatLng()
-
-                // latlng.lat = latlng.lat-0.007855;
-                // latlng.lng= latlng.lng-0.1;
-                this._resizeLatLng = latlng
-                // 鍘熷鏂规硶
-                // this._resizeLatLng = this.computeResizeLatLng();
-            },
-
-            computeResizeLatLng: function() {
-                // While circle is not added to the map, _radius is not set.
-                // let delta = (this.feature._radius || this.feature._mRadius) * Math.cos(Math.PI / 4)
-                let delta = (this.feature._radius || this.feature._mRadius)
-                let point = this.map.project(this.feature._latlng)
-                // return this.map.unproject([point.x + delta, point.y - delta])
-                return this.map.unproject([point.x + delta, point.y])
-            },
-
-            updateResizeLatLng: function() {
-                this._resizeLatLng.update(this.computeResizeLatLng())
-                this._resizeLatLng.__vertex.update()
-            },
-
-            getLatLngs: function() {
-                return [this.feature._latlng, this._resizeLatLng]
-            },
-
-            getDefaultLatLngs: function() {
-                return this.getLatLngs()
-            },
-
-            onVertexMarkerDrag: function(e) {
-                if (e.vertex.getIndex() === 1) this.resize(e)
-                else this.updateResizeLatLng(e)
-                L.Editable.PathEditor.prototype.onVertexMarkerDrag.call(this, e)
-            },
-
-            resize: function(e) {
-                let radius = this.feature._latlng.distanceTo(e.latlng)
-                this.feature.setRadius(radius)
-            },
-
-            onDrawingMouseDown: function(e) {
-                L.Editable.PathEditor.prototype.onDrawingMouseDown.call(this, e)
-                this._resizeLatLng.update(e.latlng)
-                this.feature._latlng.update(e.latlng)
-                this.connect()
-                // Stop dragging map.
-                e.originalEvent._simulated = false
-                this.map.dragging._draggable._onUp(e.originalEvent)
-                // Now transfer ongoing drag action to the radius handler.
-                this._resizeLatLng.__vertex.dragging._draggable._onDown(e.originalEvent)
-            },
-
-            onDrawingMouseUp: function(e) {
-                this.commitDrawing(e)
-                e.originalEvent._simulated = false
-                L.Editable.PathEditor.prototype.onDrawingMouseUp.call(this, e)
-            },
-
-            onDrawingMouseMove: function(e) {
-                e.originalEvent._simulated = false
-                L.Editable.PathEditor.prototype.onDrawingMouseMove.call(this, e)
-            },
-
-            onDrag: function(e) {
-                L.Editable.PathEditor.prototype.onDrag.call(this, e)
-                this.feature.dragging.updateLatLng(this._resizeLatLng)
-            }
-
-        })
-
-        // 馃崅namespace Editable; 馃崅class EditableMixin
-        // `EditableMixin` is included to `L.Polyline`, `L.Polygon`, `L.Rectangle`, `L.Circle`
-        // and `L.Marker`. It adds some methods to them.
-        // *When editing is enabled, the editor is accessible on the instance with the
-        // `editor` property.*
-        let EditableMixin = {
-
-            createEditor: function(map) {
-                map = map || this._map
-                let tools = (this.options.editOptions || {}).editTools || map.editTools
-                if (!tools) throw Error('Unable to detect Editable instance.')
-                let Klass = this.options.editorClass || this.getEditorClass(tools)
-                return new Klass(map, this, this.options.editOptions)
-            },
-
-            // 馃崅method enableEdit(map?: L.Map): this.editor
-            // Enable editing, by creating an editor if not existing, and then calling `enable` on it.
-            enableEdit: function(map) {
-                if (!this.editor) this.createEditor(map)
-                this.editor.enable()
-                return this.editor
-            },
-
-            // 馃崅method editEnabled(): boolean
-            // Return true if current instance has an editor attached, and this editor is enabled.
-            editEnabled: function() {
-                return this.editor && this.editor.enabled()
-            },
-
-            // 馃崅method disableEdit()
-            // Disable editing, also remove the editor property reference.
-            disableEdit: function() {
-                if (this.editor) {
-                    this.editor.disable()
-                    delete this.editor
-                }
-            },
-
-            // 馃崅method toggleEdit()
-            // Enable or disable editing, according to current status.
-            toggleEdit: function() {
-                if (this.editEnabled()) this.disableEdit()
-                else this.enableEdit()
-            },
-
-            _onEditableAdd: function() {
-                if (this.editor) this.enableEdit()
-            }
-
+      blockEvents: function () {
+        // Hack: force map not to listen to other layers events while drawing.
+        if (!this._oldTargets) {
+          this._oldTargets = this.map._targets
+          this.map._targets = {}
         }
+      },
 
-        let PolylineMixin = {
-
-            getEditorClass: function(tools) {
-                return (tools && tools.options.polylineEditorClass) ? tools.options.polylineEditorClass : L.Editable.PolylineEditor
-            },
-
-            shapeAt: function(latlng, latlngs) {
-                // We can have those cases:
-                // - latlngs are just a flat array of latlngs, use this
-                // - latlngs is an array of arrays of latlngs, loop over
-                let shape = null
-                latlngs = latlngs || this._latlngs
-                if (!latlngs.length) return shape
-                else if (isFlat(latlngs) && this.isInLatLngs(latlng, latlngs)) shape = latlngs
-                else for (let i = 0; i < latlngs.length; i++) if (this.isInLatLngs(latlng, latlngs[i])) return latlngs[i]
-                return shape
-            },
-
-            isInLatLngs: function(l, latlngs) {
-                if (!latlngs) return false
-                let i, k, len
-                let part = []
-                let p
-                let w = this._clickTolerance()
-                this._projectLatlngs(latlngs, part, this._pxBounds)
-                part = part[0]
-                p = this._map.latLngToLayerPoint(l)
-
-                if (!this._pxBounds.contains(p)) {
-                    return false
-                }
-                for (i = 1, len = part.length, k = 0; i < len; k = i++) {
-                    if (L.LineUtil.pointToSegmentDistance(p, part[k], part[i]) <= w) {
-                        return true
-                    }
-                }
-                return false
-            }
-
+      unblockEvents: function () {
+        if (this._oldTargets) {
+          // Reset, but keep targets created while drawing.
+          this.map._targets = L.extend(this.map._targets, this._oldTargets)
+          delete this._oldTargets
         }
+      },
 
-        let PolygonMixin = {
+      registerForDrawing: function (editor) {
+        if (this._drawingEditor) this.unregisterForDrawing(this._drawingEditor)
+        this.blockEvents()
+        editor.reset() // Make sure editor tools still receive events.
+        this._drawingEditor = editor
+        this.map.on('mousemove touchmove', editor.onDrawingMouseMove, editor)
+        this.map.on('mousedown', this.onMousedown, this)
+        this.map.on('mouseup', this.onMouseup, this)
+        L.DomUtil.addClass(this.map._container, this.options.drawingCSSClass)
+        this.defaultMapCursor = this.map._container.style.cursor
+        this.map._container.style.cursor = this.options.drawingCursor
+      },
 
-            getEditorClass: function(tools) {
-                return (tools && tools.options.polygonEditorClass) ? tools.options.polygonEditorClass : L.Editable.PolygonEditor
-            },
+      unregisterForDrawing: function (editor) {
+        this.unblockEvents()
+        L.DomUtil.removeClass(this.map._container, this.options.drawingCSSClass)
+        this.map._container.style.cursor = this.defaultMapCursor
+        editor = editor || this._drawingEditor
+        if (!editor) return
+        this.map.off('mousemove touchmove', editor.onDrawingMouseMove, editor)
+        this.map.off('mousedown', this.onMousedown, this)
+        this.map.off('mouseup', this.onMouseup, this)
+        if (editor !== this._drawingEditor) return
+        delete this._drawingEditor
+        if (editor._drawing) editor.cancelDrawing()
+      },
 
-            shapeAt: function(latlng, latlngs) {
-                // We can have those cases:
-                // - latlngs are just a flat array of latlngs, use this
-                // - latlngs is an array of arrays of latlngs, this is a simple polygon (maybe with holes), use the first
-                // - latlngs is an array of arrays of arrays, this is a multi, loop over
-                let shape = null
-                latlngs = latlngs || this._latlngs
-                if (!latlngs.length) return shape
-                else if (isFlat(latlngs) && this.isInLatLngs(latlng, latlngs)) shape = latlngs
-                else if (isFlat(latlngs[0]) && this.isInLatLngs(latlng, latlngs[0])) shape = latlngs
-                else for (let i = 0; i < latlngs.length; i++) if (this.isInLatLngs(latlng, latlngs[i][0])) return latlngs[i]
-                return shape
-            },
+      onMousedown: function (e) {
+        if (e.originalEvent.which !== 1) return
+        this._mouseDown = e
+        this._drawingEditor.onDrawingMouseDown(e)
+      },
 
-            isInLatLngs: function(l, latlngs) {
-                let inside = false
-                let l1
-                let l2
-                let j
-                let k
-                let len2
-                for (j = 0, len2 = latlngs.length, k = len2 - 1; j < len2; k = j++) {
-                    l1 = latlngs[j]
-                    l2 = latlngs[k]
+      onMouseup: function (e) {
+        if (this._mouseDown) {
+          const editor = this._drawingEditor
+          const mouseDown = this._mouseDown
+          this._mouseDown = null
+          editor.onDrawingMouseUp(e)
+          if (this._drawingEditor !== editor) return // onDrawingMouseUp may call unregisterFromDrawing.
+          const origin = L.point(mouseDown.originalEvent.clientX, mouseDown.originalEvent.clientY)
+          const distance = L.point(e.originalEvent.clientX, e.originalEvent.clientY).distanceTo(origin)
+          if (Math.abs(distance) < 9 * (window.devicePixelRatio || 1)) this._drawingEditor.onDrawingClick(e)
+        }
+      },
 
-                    if (((l1.lat > l.lat) !== (l2.lat > l.lat)) &&
+      // 馃崅section Public methods
+      // You will generally access them by the `map.editTools`
+      // instance:
+      //
+      // `map.editTools.startPolyline();`
+
+      // 馃崅method drawing(): boolean
+      // Return true if any drawing action is ongoing.
+      drawing: function () {
+        return this._drawingEditor && this._drawingEditor.drawing()
+      },
+
+      // 馃崅method stopDrawing()
+      // When you need to stop any ongoing drawing, without needing to know which editor is active.
+      stopDrawing: function () {
+        this.unregisterForDrawing()
+      },
+
+      // 馃崅method commitDrawing()
+      // When you need to commit any ongoing drawing, without needing to know which editor is active.
+      commitDrawing: function (e) {
+        if (!this._drawingEditor) return
+        this._drawingEditor.commitDrawing(e)
+      },
+
+      connectCreatedToMap: function (layer) {
+        return this.featuresLayer.addLayer(layer)
+      },
+
+      // 馃崅method startPolyline(latlng: L.LatLng, options: hash): L.Polyline
+      // Start drawing a Polyline. If `latlng` is given, a first point will be added. In any case, continuing on user click.
+      // If `options` is given, it will be passed to the Polyline class constructor.
+      startPolyline: function (latlng, options) {
+        const line = this.createPolyline([], options)
+        line.enableEdit(this.map).newShape(latlng)
+        return line
+      },
+
+      // 馃崅method startPolygon(latlng: L.LatLng, options: hash): L.Polygon
+      // Start drawing a Polygon. If `latlng` is given, a first point will be added. In any case, continuing on user click.
+      // If `options` is given, it will be passed to the Polygon class constructor.
+      startPolygon: function (latlng, options) {
+        const polygon = this.createPolygon([], options)
+        polygon.enableEdit(this.map).newShape(latlng)
+        return polygon
+      },
+
+      // 馃崅method startMarker(latlng: L.LatLng, options: hash): L.Marker
+      // Start adding a Marker. If `latlng` is given, the Marker will be shown first at this point.
+      // In any case, it will follow the user mouse, and will have a final `latlng` on next click (or touch).
+      // If `options` is given, it will be passed to the Marker class constructor.
+      startMarker: function (latlng, options) {
+        latlng = latlng || this.map.getCenter().clone()
+        const marker = this.createMarker(latlng, options)
+        marker.enableEdit(this.map).startDrawing()
+        return marker
+      },
+
+      // 馃崅method startRectangle(latlng: L.LatLng, options: hash): L.Rectangle
+      // Start drawing a Rectangle. If `latlng` is given, the Rectangle anchor will be added. In any case, continuing on user drag.
+      // If `options` is given, it will be passed to the Rectangle class constructor.
+      startRectangle: function (latlng, options) {
+        const corner = latlng || L.latLng([0, 0])
+        const bounds = new L.LatLngBounds(corner, corner)
+        const rectangle = this.createRectangle(bounds, options)
+        rectangle.enableEdit(this.map).startDrawing()
+        return rectangle
+      },
+
+      // 馃崅method startCircle(latlng: L.LatLng, options: hash): L.Circle
+      // Start drawing a Circle. If `latlng` is given, the Circle anchor will be added. In any case, continuing on user drag.
+      // If `options` is given, it will be passed to the Circle class constructor.
+      startCircle: function (latlng, options) {
+        latlng = latlng || this.map.getCenter().clone()
+        const circle = this.createCircle(latlng, options)
+        circle.enableEdit(this.map).startDrawing()
+        return circle
+      },
+
+      startHole: function (editor, latlng) {
+        editor.newHole(latlng)
+      },
+
+      createLayer: function (Klass, latlngs, options) {
+        options = L.Util.extend({ editOptions: { editTools: this } }, options)
+        const layer = new Klass(latlngs, options)
+        // 馃崅namespace Editable
+        // 馃崅event editable:created: LayerEvent
+        // Fired when a new feature (Marker, Polyline鈥�) is created.
+        this.fireAndForward('editable:created', { layer: layer })
+        return layer
+      },
+
+      createPolyline: function (latlngs, options) {
+        return this.createLayer((options && options.polylineClass) || this.options.polylineClass, latlngs, options)
+      },
+
+      createPolygon: function (latlngs, options) {
+        return this.createLayer((options && options.polygonClass) || this.options.polygonClass, latlngs, options)
+      },
+
+      createMarker: function (latlng, options) {
+        return this.createLayer((options && options.markerClass) || this.options.markerClass, latlng, options)
+      },
+
+      createRectangle: function (bounds, options) {
+        return this.createLayer((options && options.rectangleClass) || this.options.rectangleClass, bounds, options)
+      },
+
+      createCircle: function (latlng, options) {
+        return this.createLayer((options && options.circleClass) || this.options.circleClass, latlng, options)
+      }
+
+    })
+
+    L.extend(L.Editable, {
+
+      makeCancellable: function (e) {
+        e.cancel = function () {
+          e._cancelled = true
+        }
+      }
+
+    })
+
+    // 馃崅namespace Map; 馃崅class Map
+    // Leaflet.Editable add options and events to the `L.Map` object.
+    // See `Editable` events for the list of events fired on the Map.
+    // 馃崅example
+    //
+    // ```js
+    // let map = L.map('map', {
+    //  editable: true,
+    //  editOptions: {
+    //    鈥�
+    // }
+    // });
+    // ```
+    // 馃崅section Editable Map Options
+    L.Map.mergeOptions({
+
+      // 馃崅namespace Map
+      // 馃崅section Map Options
+      // 馃崅option EditToolsClass: class = L.Editable
+      // Class to be used as vertex, for path editing.
+      EditToolsClass: L.Editable,
+
+      // 馃崅option editable: boolean = false
+      // Whether to create a L.Editable instance at map init.
+      editable: false,
+
+      // 馃崅option editOptions: hash = {}
+      // Options to pass to L.Editable when instantiating.
+      editOptions: {}
+
+    })
+
+    L.Map.addInitHook(function () {
+      this.whenReady(function () {
+        if (this.options.editable) {
+          this.editTools = new this.options.EditToolsClass(this, this.options.editOptions)
+        }
+      })
+    })
+
+    L.Editable.VertexIcon = L.DivIcon.extend({
+
+      options: {
+        iconSize: new L.Point(8, 8)
+      }
+
+    })
+
+    L.Editable.TouchVertexIcon = L.Editable.VertexIcon.extend({
+
+      options: {
+        iconSize: new L.Point(20, 20)
+      }
+
+    })
+
+    // 馃崅namespace Editable; 馃崅class VertexMarker; Handler for dragging path vertices.
+    L.Editable.VertexMarker = L.Marker.extend({
+
+      options: {
+        draggable: true,
+        className: 'leaflet-vertex-icon leaflet-custom-icon'
+      },
+
+      // 馃崅section Public methods
+      // The marker used to handle path vertex. You will usually interact with a `VertexMarker`
+      // instance when listening for events like `editable:vertex:ctrlclick`.
+
+      initialize: function (latlng, latlngs, editor, options) {
+        // We don't use this._latlng, because on drag Leaflet replace it while
+        // we want to keep reference.
+        this.latlng = latlng
+        this.latlngs = latlngs
+        this.editor = editor
+        L.Marker.prototype.initialize.call(this, latlng, options)
+        this.options.icon = this.editor.tools.createVertexIcon({ className: this.options.className })
+        this.latlng.__vertex = this
+        this.editor.editLayer.addLayer(this)
+        this.setZIndexOffset(editor.tools._lastZIndex + 1)
+      },
+
+      onAdd: function (map) {
+        L.Marker.prototype.onAdd.call(this, map)
+        this.on('drag', this.onDrag)
+        this.on('dragstart', this.onDragStart)
+        this.on('dragend', this.onDragEnd)
+        this.on('mouseup', this.onMouseup)
+        this.on('click', this.onClick)
+        this.on('contextmenu', this.onContextMenu)
+        this.on('mousedown touchstart', this.onMouseDown)
+        this.on('mouseover', this.onMouseOver)
+        this.on('mouseout', this.onMouseOut)
+        this.addMiddleMarkers()
+      },
+
+      onRemove: function (map) {
+        if (this.middleMarker) this.middleMarker.delete()
+        delete this.latlng.__vertex
+        this.off('drag', this.onDrag)
+        this.off('dragstart', this.onDragStart)
+        this.off('dragend', this.onDragEnd)
+        this.off('mouseup', this.onMouseup)
+        this.off('click', this.onClick)
+        this.off('contextmenu', this.onContextMenu)
+        this.off('mousedown touchstart', this.onMouseDown)
+        this.off('mouseover', this.onMouseOver)
+        this.off('mouseout', this.onMouseOut)
+        L.Marker.prototype.onRemove.call(this, map)
+      },
+
+      onDrag: function (e) {
+        e.vertex = this
+        this.editor.onVertexMarkerDrag(e)
+        const iconPos = L.DomUtil.getPosition(this._icon)
+        const latlng = this._map.layerPointToLatLng(iconPos)
+        this.latlng.update(latlng)
+        this._latlng = this.latlng // Push back to Leaflet our reference.
+        this.editor.refresh()
+        if (this.middleMarker) this.middleMarker.updateLatLng()
+        const next = this.getNext()
+        if (next && next.middleMarker) next.middleMarker.updateLatLng()
+      },
+
+      onDragStart: function (e) {
+        e.vertex = this
+        this.editor.onVertexMarkerDragStart(e)
+      },
+
+      onDragEnd: function (e) {
+        e.vertex = this
+        this.editor.onVertexMarkerDragEnd(e)
+      },
+
+      onClick: function (e) {
+        e.vertex = this
+        this.editor.onVertexMarkerClick(e)
+      },
+
+      onMouseup: function (e) {
+        L.DomEvent.stop(e)
+        e.vertex = this
+        this.editor.map.fire('mouseup', e)
+      },
+
+      onContextMenu: function (e) {
+        e.vertex = this
+        this.editor.onVertexMarkerContextMenu(e)
+      },
+
+      onMouseDown: function (e) {
+        e.vertex = this
+        this.editor.onVertexMarkerMouseDown(e)
+      },
+
+      onMouseOver: function (e) {
+        e.vertex = this
+        this.editor.onVertexMarkerMouseOver(e)
+      },
+
+      onMouseOut: function (e) {
+        e.vertex = this
+        this.editor.onVertexMarkerMouseOut(e)
+      },
+
+      // 馃崅method delete()
+      // Delete a vertex and the related LatLng.
+      delete: function () {
+        const next = this.getNext() // Compute before changing latlng
+        this.latlngs.splice(this.getIndex(), 1)
+        this.editor.editLayer.removeLayer(this)
+        this.editor.onVertexDeleted({ latlng: this.latlng, vertex: this })
+        if (!this.latlngs.length) this.editor.deleteShape(this.latlngs)
+        if (next) next.resetMiddleMarker()
+        this.editor.refresh()
+      },
+
+      // 馃崅method getIndex(): int
+      // Get the index of the current vertex among others of the same LatLngs group.
+      getIndex: function () {
+        return this.latlngs.indexOf(this.latlng)
+      },
+
+      // 馃崅method getLastIndex(): int
+      // Get last vertex index of the LatLngs group of the current vertex.
+      getLastIndex: function () {
+        return this.latlngs.length - 1
+      },
+
+      // 馃崅method getPrevious(): VertexMarker
+      // Get the previous VertexMarker in the same LatLngs group.
+      getPrevious: function () {
+        if (this.latlngs.length < 2) return
+        const index = this.getIndex()
+        let previousIndex = index - 1
+        if (index === 0 && this.editor.CLOSED) previousIndex = this.getLastIndex()
+        const previous = this.latlngs[previousIndex]
+        if (previous) return previous.__vertex
+      },
+
+      // 馃崅method getNext(): VertexMarker
+      // Get the next VertexMarker in the same LatLngs group.
+      getNext: function () {
+        if (this.latlngs.length < 2) return
+        const index = this.getIndex()
+        let nextIndex = index + 1
+        if (index === this.getLastIndex() && this.editor.CLOSED) nextIndex = 0
+        const next = this.latlngs[nextIndex]
+        if (next) return next.__vertex
+      },
+
+      addMiddleMarker: function (previous) {
+        if (!this.editor.hasMiddleMarkers()) return
+        previous = previous || this.getPrevious()
+        if (previous && !this.middleMarker) this.middleMarker = this.editor.addMiddleMarker(previous, this, this.latlngs, this.editor)
+      },
+
+      addMiddleMarkers: function () {
+        if (!this.editor.hasMiddleMarkers()) return
+        const previous = this.getPrevious()
+        if (previous) this.addMiddleMarker(previous)
+        const next = this.getNext()
+        if (next) next.resetMiddleMarker()
+      },
+
+      resetMiddleMarker: function () {
+        if (this.middleMarker) this.middleMarker.delete()
+        this.addMiddleMarker()
+      },
+
+      // 馃崅method split()
+      // Split the vertex LatLngs group at its index, if possible.
+      split: function () {
+        if (!this.editor.splitShape) return // Only for PolylineEditor
+        this.editor.splitShape(this.latlngs, this.getIndex())
+      },
+
+      // 馃崅method continue()
+      // Continue the vertex LatLngs from this vertex. Only active for first and last vertices of a Polyline.
+      continue: function () {
+        if (!this.editor.continueBackward) return // Only for PolylineEditor
+        const index = this.getIndex()
+        if (index === 0) this.editor.continueBackward(this.latlngs)
+        else if (index === this.getLastIndex()) this.editor.continueForward(this.latlngs)
+      }
+
+    })
+
+    L.Editable.mergeOptions({
+
+      // 馃崅namespace Editable
+      // 馃崅option VertexMarkerClass: class = VertexMarker
+      // Class to be used as vertex, for path editing.
+      VertexMarkerClass: L.Editable.VertexMarker
+
+    })
+
+    L.Editable.MiddleMarker = L.Marker.extend({
+
+      options: {
+        opacity: 0.5,
+        className: 'leaflet-div-icon leaflet-middle-icon',
+        draggable: true
+      },
+
+      initialize: function (left, right, latlngs, editor, options) {
+        this.left = left
+        this.right = right
+        this.editor = editor
+        this.latlngs = latlngs
+        L.Marker.prototype.initialize.call(this, this.computeLatLng(), options)
+        this._opacity = this.options.opacity
+        this.options.icon = this.editor.tools.createVertexIcon({ className: this.options.className })
+        this.editor.editLayer.addLayer(this)
+        this.setVisibility()
+      },
+
+      setVisibility: function () {
+        const leftPoint = this._map.latLngToContainerPoint(this.left.latlng)
+        const rightPoint = this._map.latLngToContainerPoint(this.right.latlng)
+        const size = L.point(this.options.icon.options.iconSize)
+        if (leftPoint.distanceTo(rightPoint) < size.x * 3) this.hide()
+        else this.show()
+      },
+
+      show: function () {
+        this.setOpacity(this._opacity)
+      },
+
+      hide: function () {
+        this.setOpacity(0)
+      },
+
+      updateLatLng: function () {
+        this.setLatLng(this.computeLatLng())
+        this.setVisibility()
+      },
+
+      computeLatLng: function () {
+        const leftPoint = this.editor.map.latLngToContainerPoint(this.left.latlng)
+        const rightPoint = this.editor.map.latLngToContainerPoint(this.right.latlng)
+        const y = (leftPoint.y + rightPoint.y) / 2
+        const x = (leftPoint.x + rightPoint.x) / 2
+        return this.editor.map.containerPointToLatLng([x, y])
+      },
+
+      onAdd: function (map) {
+        L.Marker.prototype.onAdd.call(this, map)
+        L.DomEvent.on(this._icon, 'mousedown touchstart', this.onMouseDown, this)
+        map.on('zoomend', this.setVisibility, this)
+      },
+
+      onRemove: function (map) {
+        delete this.right.middleMarker
+        L.DomEvent.off(this._icon, 'mousedown touchstart', this.onMouseDown, this)
+        map.off('zoomend', this.setVisibility, this)
+        L.Marker.prototype.onRemove.call(this, map)
+      },
+
+      onMouseDown: function (e) {
+        const iconPos = L.DomUtil.getPosition(this._icon)
+        const latlng = this.editor.map.layerPointToLatLng(iconPos)
+        e = {
+          originalEvent: e,
+          latlng: latlng
+        }
+        if (this.options.opacity === 0) return
+        L.Editable.makeCancellable(e)
+        this.editor.onMiddleMarkerMouseDown(e)
+        if (e._cancelled) return
+        this.latlngs.splice(this.index(), 0, e.latlng)
+        this.editor.refresh()
+        const icon = this._icon
+        const marker = this.editor.addVertexMarker(e.latlng, this.latlngs)
+        this.editor.onNewVertex(marker)
+        /* Hack to workaround browser not firing touchend when element is no more on DOM */
+        const parent = marker._icon.parentNode
+        parent.removeChild(marker._icon)
+        marker._icon = icon
+        parent.appendChild(marker._icon)
+        marker._initIcon()
+        marker._initInteraction()
+        marker.setOpacity(1)
+        /* End hack */
+        // Transfer ongoing dragging to real marker
+        L.Draggable._dragging = false
+        marker.dragging._draggable._onDown(e.originalEvent)
+        this.delete()
+      },
+
+      delete: function () {
+        this.editor.editLayer.removeLayer(this)
+      },
+
+      index: function () {
+        return this.latlngs.indexOf(this.right.latlng)
+      }
+
+    })
+
+    L.Editable.mergeOptions({
+
+      // 馃崅namespace Editable
+      // 馃崅option MiddleMarkerClass: class = VertexMarker
+      // Class to be used as middle vertex, pulled by the user to create a new point in the middle of a path.
+      MiddleMarkerClass: L.Editable.MiddleMarker
+
+    })
+
+    // 馃崅namespace Editable; 馃崅class BaseEditor; 馃崅aka L.Editable.BaseEditor
+    // When editing a feature (Marker, Polyline鈥�), an editor is attached to it. This
+    // editor basically knows how to handle the edition.
+    L.Editable.BaseEditor = L.Handler.extend({
+
+      initialize: function (map, feature, options) {
+        L.setOptions(this, options)
+        this.map = map
+        this.feature = feature
+        this.feature.editor = this
+        this.editLayer = new L.LayerGroup()
+        this.tools = this.options.editTools || map.editTools
+      },
+
+      // 馃崅method enable(): this
+      // Set up the drawing tools for the feature to be editable.
+      addHooks: function () {
+        if (this.isConnected()) this.onFeatureAdd()
+        else this.feature.once('add', this.onFeatureAdd, this)
+        this.onEnable()
+        this.feature.on(this._getEvents(), this)
+      },
+
+      // 馃崅method disable(): this
+      // Remove the drawing tools for the feature.
+      removeHooks: function () {
+        this.feature.off(this._getEvents(), this)
+        if (this.feature.dragging) this.feature.dragging.disable()
+        this.editLayer.clearLayers()
+        this.tools.editLayer.removeLayer(this.editLayer)
+        this.onDisable()
+        if (this._drawing) this.cancelDrawing()
+      },
+
+      // 馃崅method drawing(): boolean
+      // Return true if any drawing action is ongoing with this editor.
+      drawing: function () {
+        return !!this._drawing
+      },
+
+      reset: function () {
+      },
+
+      onFeatureAdd: function () {
+        this.tools.editLayer.addLayer(this.editLayer)
+        if (this.feature.dragging) this.feature.dragging.enable()
+      },
+
+      hasMiddleMarkers: function () {
+        return !this.options.skipMiddleMarkers && !this.tools.options.skipMiddleMarkers
+      },
+
+      fireAndForward: function (type, e) {
+        e = e || {}
+        e.layer = this.feature
+        this.feature.fire(type, e)
+        this.tools.fireAndForward(type, e)
+      },
+
+      onEnable: function () {
+        // 馃崅namespace Editable
+        // 馃崅event editable:enable: Event
+        // Fired when an existing feature is ready to be edited.
+        this.fireAndForward('editable:enable')
+      },
+
+      onDisable: function () {
+        // 馃崅namespace Editable
+        // 馃崅event editable:disable: Event
+        // Fired when an existing feature is not ready anymore to be edited.
+        this.fireAndForward('editable:disable')
+      },
+
+      onEditing: function () {
+        // 馃崅namespace Editable
+        // 馃崅event editable:editing: Event
+        // Fired as soon as any change is made to the feature geometry.
+        this.fireAndForward('editable:editing')
+      },
+
+      onStartDrawing: function () {
+        // 馃崅namespace Editable
+        // 馃崅section Drawing events
+        // 馃崅event editable:drawing:start: Event
+        // Fired when a feature is to be drawn.
+        this.fireAndForward('editable:drawing:start')
+      },
+
+      onEndDrawing: function () {
+        // 馃崅namespace Editable
+        // 馃崅section Drawing events
+        // 馃崅event editable:drawing:end: Event
+        // Fired when a feature is not drawn anymore.
+        this.fireAndForward('editable:drawing:end')
+      },
+
+      onCancelDrawing: function () {
+        // 馃崅namespace Editable
+        // 馃崅section Drawing events
+        // 馃崅event editable:drawing:cancel: Event
+        // Fired when user cancel drawing while a feature is being drawn.
+        this.fireAndForward('editable:drawing:cancel')
+      },
+
+      onCommitDrawing: function (e) {
+        // 馃崅namespace Editable
+        // 馃崅section Drawing events
+        // 馃崅event editable:drawing:commit: Event
+        // Fired when user finish drawing a feature.
+        this.fireAndForward('editable:drawing:commit', e)
+      },
+
+      onDrawingMouseDown: function (e) {
+        // 馃崅namespace Editable
+        // 馃崅section Drawing events
+        // 馃崅event editable:drawing:mousedown: Event
+        // Fired when user `mousedown` while drawing.
+        this.fireAndForward('editable:drawing:mousedown', e)
+      },
+
+      onDrawingMouseUp: function (e) {
+        // 馃崅namespace Editable
+        // 馃崅section Drawing events
+        // 馃崅event editable:drawing:mouseup: Event
+        // Fired when user `mouseup` while drawing.
+        this.fireAndForward('editable:drawing:mouseup', e)
+      },
+
+      startDrawing: function () {
+        if (!this._drawing) this._drawing = L.Editable.FORWARD
+        this.tools.registerForDrawing(this)
+        this.onStartDrawing()
+      },
+
+      commitDrawing: function (e) {
+        this.onCommitDrawing(e)
+        this.endDrawing()
+      },
+
+      cancelDrawing: function () {
+        // If called during a vertex drag, the vertex will be removed before
+        // the mouseup fires on it. This is a workaround. Maybe better fix is
+        // To have L.Draggable reset it's status on disable (Leaflet side).
+        L.Draggable._dragging = false
+        this.onCancelDrawing()
+        this.endDrawing()
+      },
+
+      endDrawing: function () {
+        this._drawing = false
+        this.tools.unregisterForDrawing(this)
+        this.onEndDrawing()
+      },
+
+      onDrawingClick: function (e) {
+        if (!this.drawing()) return
+        L.Editable.makeCancellable(e)
+        // 馃崅namespace Editable
+        // 馃崅section Drawing events
+        // 馃崅event editable:drawing:click: CancelableEvent
+        // Fired when user `click` while drawing, before any internal action is being processed.
+        this.fireAndForward('editable:drawing:click', e)
+        if (e._cancelled) return
+        if (!this.isConnected()) this.connect(e)
+        this.processDrawingClick(e)
+      },
+
+      isConnected: function () {
+        return this.map.hasLayer(this.feature)
+      },
+
+      connect: function () {
+        this.tools.connectCreatedToMap(this.feature)
+        this.tools.editLayer.addLayer(this.editLayer)
+      },
+
+      onMove: function (e) {
+        // 馃崅namespace Editable
+        // 馃崅section Drawing events
+        // 馃崅event editable:drawing:move: Event
+        // Fired when `move` mouse while drawing, while dragging a marker, and while dragging a vertex.
+        this.fireAndForward('editable:drawing:move', e)
+      },
+
+      onDrawingMouseMove: function (e) {
+        this.onMove(e)
+      },
+
+      _getEvents: function () {
+        return {
+          dragstart: this.onDragStart,
+          drag: this.onDrag,
+          dragend: this.onDragEnd,
+          remove: this.disable
+        }
+      },
+
+      onDragStart: function (e) {
+        this.onEditing()
+        // 馃崅namespace Editable
+        // 馃崅event editable:dragstart: Event
+        // Fired before a path feature is dragged.
+        this.fireAndForward('editable:dragstart', e)
+      },
+
+      onDrag: function (e) {
+        this.onMove(e)
+        // 馃崅namespace Editable
+        // 馃崅event editable:drag: Event
+        // Fired when a path feature is being dragged.
+        this.fireAndForward('editable:drag', e)
+      },
+
+      onDragEnd: function (e) {
+        // 馃崅namespace Editable
+        // 馃崅event editable:dragend: Event
+        // Fired after a path feature has been dragged.
+        this.fireAndForward('editable:dragend', e)
+      }
+
+    })
+
+    // 馃崅namespace Editable; 馃崅class MarkerEditor; 馃崅aka L.Editable.MarkerEditor
+    // 馃崅inherits BaseEditor
+    // Editor for Marker.
+    L.Editable.MarkerEditor = L.Editable.BaseEditor.extend({
+
+      onDrawingMouseMove: function (e) {
+        L.Editable.BaseEditor.prototype.onDrawingMouseMove.call(this, e)
+        if (this._drawing) this.feature.setLatLng(e.latlng)
+      },
+
+      processDrawingClick: function (e) {
+        // 馃崅namespace Editable
+        // 馃崅section Drawing events
+        // 馃崅event editable:drawing:clicked: Event
+        // Fired when user `click` while drawing, after all internal actions.
+        this.fireAndForward('editable:drawing:clicked', e)
+        this.commitDrawing(e)
+      },
+
+      connect: function (e) {
+        // On touch, the latlng has not been updated because there is
+        // no mousemove.
+        if (e) this.feature._latlng = e.latlng
+        L.Editable.BaseEditor.prototype.connect.call(this, e)
+      }
+
+    })
+
+    // 馃崅namespace Editable; 馃崅class PathEditor; 馃崅aka L.Editable.PathEditor
+    // 馃崅inherits BaseEditor
+    // Base class for all path editors.
+    L.Editable.PathEditor = L.Editable.BaseEditor.extend({
+
+      CLOSED: false,
+      MIN_VERTEX: 2,
+
+      addHooks: function () {
+        L.Editable.BaseEditor.prototype.addHooks.call(this)
+        if (this.feature) this.initVertexMarkers()
+        return this
+      },
+
+      initVertexMarkers: function (latlngs) {
+        if (!this.enabled()) return
+        latlngs = latlngs || this.getLatLngs()
+        if (isFlat(latlngs)) this.addVertexMarkers(latlngs)
+        else for (let i = 0; i < latlngs.length; i++) this.initVertexMarkers(latlngs[i])
+      },
+
+      getLatLngs: function () {
+        return this.feature.getLatLngs()
+      },
+
+      // 馃崅method reset()
+      // Rebuild edit elements (Vertex, MiddleMarker, etc.).
+      reset: function () {
+        this.editLayer.clearLayers()
+        this.initVertexMarkers()
+      },
+
+      addVertexMarker: function (latlng, latlngs) {
+        return new this.tools.options.VertexMarkerClass(latlng, latlngs, this)
+      },
+
+      onNewVertex: function (vertex) {
+        // 馃崅namespace Editable
+        // 馃崅section Vertex events
+        // 馃崅event editable:vertex:new: VertexEvent
+        // Fired when a new vertex is created.
+        this.fireAndForward('editable:vertex:new', { latlng: vertex.latlng, vertex: vertex })
+      },
+
+      addVertexMarkers: function (latlngs) {
+        for (let i = 0; i < latlngs.length; i++) {
+          this.addVertexMarker(latlngs[i], latlngs)
+        }
+      },
+
+      refreshVertexMarkers: function (latlngs) {
+        latlngs = latlngs || this.getDefaultLatLngs()
+        for (let i = 0; i < latlngs.length; i++) {
+          latlngs[i].__vertex.update()
+        }
+      },
+
+      addMiddleMarker: function (left, right, latlngs) {
+        return new this.tools.options.MiddleMarkerClass(left, right, latlngs, this)
+      },
+
+      onVertexMarkerClick: function (e) {
+        L.Editable.makeCancellable(e)
+        // 馃崅namespace Editable
+        // 馃崅section Vertex events
+        // 馃崅event editable:vertex:click: CancelableVertexEvent
+        // Fired when a `click` is issued on a vertex, before any internal action is being processed.
+        this.fireAndForward('editable:vertex:click', e)
+        if (e._cancelled) return
+        if (this.tools.drawing() && this.tools._drawingEditor !== this) return
+        const index = e.vertex.getIndex()
+        let commit
+        if (e.originalEvent.ctrlKey) {
+          this.onVertexMarkerCtrlClick(e)
+        } else if (e.originalEvent.altKey) {
+          this.onVertexMarkerAltClick(e)
+        } else if (e.originalEvent.shiftKey) {
+          this.onVertexMarkerShiftClick(e)
+        } else if (e.originalEvent.metaKey) {
+          this.onVertexMarkerMetaKeyClick(e)
+        } else if (index === e.vertex.getLastIndex() && this._drawing === L.Editable.FORWARD) {
+          if (index >= this.MIN_VERTEX - 1) commit = true
+        } else if (index === 0 && this._drawing === L.Editable.BACKWARD && this._drawnLatLngs.length >= this.MIN_VERTEX) {
+          commit = true
+        } else if (index === 0 && this._drawing === L.Editable.FORWARD && this._drawnLatLngs.length >= this.MIN_VERTEX && this.CLOSED) {
+          commit = true // Allow to close on first point also for polygons
+        } else {
+          this.onVertexRawMarkerClick(e)
+        }
+        // 馃崅namespace Editable
+        // 馃崅section Vertex events
+        // 馃崅event editable:vertex:clicked: VertexEvent
+        // Fired when a `click` is issued on a vertex, after all internal actions.
+        this.fireAndForward('editable:vertex:clicked', e)
+        if (commit) this.commitDrawing(e)
+      },
+
+      onVertexRawMarkerClick: function (e) {
+        // 馃崅namespace Editable
+        // 馃崅section Vertex events
+        // 馃崅event editable:vertex:rawclick: CancelableVertexEvent
+        // Fired when a `click` is issued on a vertex without any special key and without being in drawing mode.
+        this.fireAndForward('editable:vertex:rawclick', e)
+        if (e._cancelled) return
+        if (!this.vertexCanBeDeleted(e.vertex)) return
+        e.vertex.delete()
+      },
+
+      vertexCanBeDeleted: function (vertex) {
+        return vertex.latlngs.length > this.MIN_VERTEX
+      },
+
+      onVertexDeleted: function (e) {
+        // 馃崅namespace Editable
+        // 馃崅section Vertex events
+        // 馃崅event editable:vertex:deleted: VertexEvent
+        // Fired after a vertex has been deleted by user.
+        this.fireAndForward('editable:vertex:deleted', e)
+      },
+
+      onVertexMarkerCtrlClick: function (e) {
+        // 馃崅namespace Editable
+        // 馃崅section Vertex events
+        // 馃崅event editable:vertex:ctrlclick: VertexEvent
+        // Fired when a `click` with `ctrlKey` is issued on a vertex.
+        this.fireAndForward('editable:vertex:ctrlclick', e)
+      },
+
+      onVertexMarkerShiftClick: function (e) {
+        // 馃崅namespace Editable
+        // 馃崅section Vertex events
+        // 馃崅event editable:vertex:shiftclick: VertexEvent
+        // Fired when a `click` with `shiftKey` is issued on a vertex.
+        this.fireAndForward('editable:vertex:shiftclick', e)
+      },
+
+      onVertexMarkerMetaKeyClick: function (e) {
+        // 馃崅namespace Editable
+        // 馃崅section Vertex events
+        // 馃崅event editable:vertex:metakeyclick: VertexEvent
+        // Fired when a `click` with `metaKey` is issued on a vertex.
+        this.fireAndForward('editable:vertex:metakeyclick', e)
+      },
+
+      onVertexMarkerAltClick: function (e) {
+        // 馃崅namespace Editable
+        // 馃崅section Vertex events
+        // 馃崅event editable:vertex:altclick: VertexEvent
+        // Fired when a `click` with `altKey` is issued on a vertex.
+        this.fireAndForward('editable:vertex:altclick', e)
+      },
+
+      onVertexMarkerContextMenu: function (e) {
+        // 馃崅namespace Editable
+        // 馃崅section Vertex events
+        // 馃崅event editable:vertex:contextmenu: VertexEvent
+        // Fired when a `contextmenu` is issued on a vertex.
+        this.fireAndForward('editable:vertex:contextmenu', e)
+      },
+
+      onVertexMarkerMouseDown: function (e) {
+        // 馃崅namespace Editable
+        // 馃崅section Vertex events
+        // 馃崅event editable:vertex:mousedown: VertexEvent
+        // Fired when user `mousedown` a vertex.
+        this.fireAndForward('editable:vertex:mousedown', e)
+      },
+
+      onVertexMarkerMouseOver: function (e) {
+        // 馃崅namespace Editable
+        // 馃崅section Vertex events
+        // 馃崅event editable:vertex:mouseover: VertexEvent
+        // Fired when a user's mouse enters the vertex
+        this.fireAndForward('editable:vertex:mouseover', e)
+      },
+
+      onVertexMarkerMouseOut: function (e) {
+        // 馃崅namespace Editable
+        // 馃崅section Vertex events
+        // 馃崅event editable:vertex:mouseout: VertexEvent
+        // Fired when a user's mouse leaves the vertex
+        this.fireAndForward('editable:vertex:mouseout', e)
+      },
+
+      onMiddleMarkerMouseDown: function (e) {
+        // 馃崅namespace Editable
+        // 馃崅section MiddleMarker events
+        // 馃崅event editable:middlemarker:mousedown: VertexEvent
+        // Fired when user `mousedown` a middle marker.
+        this.fireAndForward('editable:middlemarker:mousedown', e)
+      },
+
+      onVertexMarkerDrag: function (e) {
+        this.onMove(e)
+        if (this.feature._bounds) this.extendBounds(e)
+        // 馃崅namespace Editable
+        // 馃崅section Vertex events
+        // 馃崅event editable:vertex:drag: VertexEvent
+        // Fired when a vertex is dragged by user.
+        this.fireAndForward('editable:vertex:drag', e)
+      },
+
+      onVertexMarkerDragStart: function (e) {
+        // 馃崅namespace Editable
+        // 馃崅section Vertex events
+        // 馃崅event editable:vertex:dragstart: VertexEvent
+        // Fired before a vertex is dragged by user.
+        this.fireAndForward('editable:vertex:dragstart', e)
+      },
+
+      onVertexMarkerDragEnd: function (e) {
+        // 馃崅namespace Editable
+        // 馃崅section Vertex events
+        // 馃崅event editable:vertex:dragend: VertexEvent
+        // Fired after a vertex is dragged by user.
+        this.fireAndForward('editable:vertex:dragend', e)
+      },
+
+      setDrawnLatLngs: function (latlngs) {
+        this._drawnLatLngs = latlngs || this.getDefaultLatLngs()
+      },
+
+      startDrawing: function () {
+        if (!this._drawnLatLngs) this.setDrawnLatLngs()
+        L.Editable.BaseEditor.prototype.startDrawing.call(this)
+      },
+
+      startDrawingForward: function () {
+        this.startDrawing()
+      },
+
+      endDrawing: function () {
+        this.tools.detachForwardLineGuide()
+        this.tools.detachBackwardLineGuide()
+        if (this._drawnLatLngs && this._drawnLatLngs.length < this.MIN_VERTEX) this.deleteShape(this._drawnLatLngs)
+        L.Editable.BaseEditor.prototype.endDrawing.call(this)
+        delete this._drawnLatLngs
+      },
+
+      addLatLng: function (latlng) {
+        if (this._drawing === L.Editable.FORWARD) this._drawnLatLngs.push(latlng)
+        else this._drawnLatLngs.unshift(latlng)
+        this.feature._bounds.extend(latlng)
+        const vertex = this.addVertexMarker(latlng, this._drawnLatLngs)
+        this.onNewVertex(vertex)
+        this.refresh()
+      },
+
+      newPointForward: function (latlng) {
+        this.addLatLng(latlng)
+        this.tools.attachForwardLineGuide()
+        this.tools.anchorForwardLineGuide(latlng)
+      },
+
+      newPointBackward: function (latlng) {
+        this.addLatLng(latlng)
+        this.tools.anchorBackwardLineGuide(latlng)
+      },
+
+      // 馃崅namespace PathEditor
+      // 馃崅method push()
+      // Programmatically add a point while drawing.
+      push: function (latlng) {
+        if (!latlng) return console.error('L.Editable.PathEditor.push expect a valid latlng as parameter')
+        if (this._drawing === L.Editable.FORWARD) this.newPointForward(latlng)
+        else this.newPointBackward(latlng)
+      },
+
+      removeLatLng: function (latlng) {
+        latlng.__vertex.delete()
+        this.refresh()
+      },
+
+      // 馃崅method pop(): L.LatLng or null
+      // Programmatically remove last point (if any) while drawing.
+      pop: function () {
+        if (this._drawnLatLngs.length <= 1) return
+        let latlng
+        if (this._drawing === L.Editable.FORWARD) latlng = this._drawnLatLngs[this._drawnLatLngs.length - 1]
+        else latlng = this._drawnLatLngs[0]
+        this.removeLatLng(latlng)
+        if (this._drawing === L.Editable.FORWARD) this.tools.anchorForwardLineGuide(this._drawnLatLngs[this._drawnLatLngs.length - 1])
+        else this.tools.anchorForwardLineGuide(this._drawnLatLngs[0])
+        return latlng
+      },
+
+      processDrawingClick: function (e) {
+        if (e.vertex && e.vertex.editor === this) return
+        if (this._drawing === L.Editable.FORWARD) this.newPointForward(e.latlng)
+        else this.newPointBackward(e.latlng)
+        this.fireAndForward('editable:drawing:clicked', e)
+      },
+
+      onDrawingMouseMove: function (e) {
+        L.Editable.BaseEditor.prototype.onDrawingMouseMove.call(this, e)
+        if (this._drawing) {
+          this.tools.moveForwardLineGuide(e.latlng)
+          this.tools.moveBackwardLineGuide(e.latlng)
+        }
+      },
+
+      refresh: function () {
+        this.feature.redraw()
+        this.onEditing()
+      },
+
+      // 馃崅namespace PathEditor
+      // 馃崅method newShape(latlng?: L.LatLng)
+      // Add a new shape (Polyline, Polygon) in a multi, and setup up drawing tools to draw it;
+      // if optional `latlng` is given, start a path at this point.
+      newShape: function (latlng) {
+        const shape = this.addNewEmptyShape()
+        if (!shape) return
+        this.setDrawnLatLngs(shape[0] || shape) // Polygon or polyline
+        this.startDrawingForward()
+        // 馃崅namespace Editable
+        // 馃崅section Shape events
+        // 馃崅event editable:shape:new: ShapeEvent
+        // Fired when a new shape is created in a multi (Polygon or Polyline).
+        this.fireAndForward('editable:shape:new', { shape: shape })
+        if (latlng) this.newPointForward(latlng)
+      },
+
+      deleteShape: function (shape, latlngs) {
+        const e = { shape: shape }
+        L.Editable.makeCancellable(e)
+        // 馃崅namespace Editable
+        // 馃崅section Shape events
+        // 馃崅event editable:shape:delete: CancelableShapeEvent
+        // Fired before a new shape is deleted in a multi (Polygon or Polyline).
+        this.fireAndForward('editable:shape:delete', e)
+        if (e._cancelled) return
+        shape = this._deleteShape(shape, latlngs)
+        if (this.ensureNotFlat) this.ensureNotFlat() // Polygon.
+        this.feature.setLatLngs(this.getLatLngs()) // Force bounds reset.
+        this.refresh()
+        this.reset()
+        // 馃崅namespace Editable
+        // 馃崅section Shape events
+        // 馃崅event editable:shape:deleted: ShapeEvent
+        // Fired after a new shape is deleted in a multi (Polygon or Polyline).
+        this.fireAndForward('editable:shape:deleted', { shape: shape })
+        return shape
+      },
+
+      _deleteShape: function (shape, latlngs) {
+        latlngs = latlngs || this.getLatLngs()
+        if (!latlngs.length) return
+        const self = this
+        const inplaceDelete = function (latlngs, shape) {
+          // Called when deleting a flat latlngs
+          shape = latlngs.splice(0, Number.MAX_VALUE)
+          return shape
+        }
+        const spliceDelete = function (latlngs, shape) {
+          // Called when removing a latlngs inside an array
+          latlngs.splice(latlngs.indexOf(shape), 1)
+          if (!latlngs.length) self._deleteShape(latlngs)
+          return shape
+        }
+        if (latlngs === shape) return inplaceDelete(latlngs, shape)
+        for (let i = 0; i < latlngs.length; i++) {
+          if (latlngs[i] === shape) return spliceDelete(latlngs, shape)
+          else if (latlngs[i].indexOf(shape) !== -1) return spliceDelete(latlngs[i], shape)
+        }
+      },
+
+      // 馃崅namespace PathEditor
+      // 馃崅method deleteShapeAt(latlng: L.LatLng): Array
+      // Remove a path shape at the given `latlng`.
+      deleteShapeAt: function (latlng) {
+        const shape = this.feature.shapeAt(latlng)
+        if (shape) return this.deleteShape(shape)
+      },
+
+      // 馃崅method appendShape(shape: Array)
+      // Append a new shape to the Polygon or Polyline.
+      appendShape: function (shape) {
+        this.insertShape(shape)
+      },
+
+      // 馃崅method prependShape(shape: Array)
+      // Prepend a new shape to the Polygon or Polyline.
+      prependShape: function (shape) {
+        this.insertShape(shape, 0)
+      },
+
+      // 馃崅method insertShape(shape: Array, index: int)
+      // Insert a new shape to the Polygon or Polyline at given index (default is to append).
+      insertShape: function (shape, index) {
+        this.ensureMulti()
+        shape = this.formatShape(shape)
+        if (typeof index === 'undefined') index = this.feature._latlngs.length
+        this.feature._latlngs.splice(index, 0, shape)
+        this.feature.redraw()
+        if (this._enabled) this.reset()
+      },
+
+      extendBounds: function (e) {
+        this.feature._bounds.extend(e.vertex.latlng)
+      },
+
+      onDragStart: function (e) {
+        this.editLayer.clearLayers()
+        L.Editable.BaseEditor.prototype.onDragStart.call(this, e)
+      },
+
+      onDragEnd: function (e) {
+        this.initVertexMarkers()
+        L.Editable.BaseEditor.prototype.onDragEnd.call(this, e)
+      }
+
+    })
+
+    // 馃崅namespace Editable; 馃崅class PolylineEditor; 馃崅aka L.Editable.PolylineEditor
+    // 馃崅inherits PathEditor
+    L.Editable.PolylineEditor = L.Editable.PathEditor.extend({
+
+      startDrawingBackward: function () {
+        this._drawing = L.Editable.BACKWARD
+        this.startDrawing()
+      },
+
+      // 馃崅method continueBackward(latlngs?: Array)
+      // Set up drawing tools to continue the line backward.
+      continueBackward: function (latlngs) {
+        if (this.drawing()) return
+        latlngs = latlngs || this.getDefaultLatLngs()
+        this.setDrawnLatLngs(latlngs)
+        if (latlngs.length > 0) {
+          this.tools.attachBackwardLineGuide()
+          this.tools.anchorBackwardLineGuide(latlngs[0])
+        }
+        this.startDrawingBackward()
+      },
+
+      // 馃崅method continueForward(latlngs?: Array)
+      // Set up drawing tools to continue the line forward.
+      continueForward: function (latlngs) {
+        if (this.drawing()) return
+        latlngs = latlngs || this.getDefaultLatLngs()
+        this.setDrawnLatLngs(latlngs)
+        if (latlngs.length > 0) {
+          this.tools.attachForwardLineGuide()
+          this.tools.anchorForwardLineGuide(latlngs[latlngs.length - 1])
+        }
+        this.startDrawingForward()
+      },
+
+      getDefaultLatLngs: function (latlngs) {
+        latlngs = latlngs || this.feature._latlngs
+        if (!latlngs.length || latlngs[0] instanceof L.LatLng) return latlngs
+        else return this.getDefaultLatLngs(latlngs[0])
+      },
+
+      ensureMulti: function () {
+        if (this.feature._latlngs.length && isFlat(this.feature._latlngs)) {
+          this.feature._latlngs = [this.feature._latlngs]
+        }
+      },
+
+      addNewEmptyShape: function () {
+        if (this.feature._latlngs.length) {
+          const shape = []
+          this.appendShape(shape)
+          return shape
+        } else {
+          return this.feature._latlngs
+        }
+      },
+
+      formatShape: function (shape) {
+        if (isFlat(shape)) return shape
+        else if (shape[0]) return this.formatShape(shape[0])
+      },
+
+      // 馃崅method splitShape(latlngs?: Array, index: int)
+      // Split the given `latlngs` shape at index `index` and integrate new shape in instance `latlngs`.
+      splitShape: function (shape, index) {
+        if (!index || index >= shape.length - 1) return
+        this.ensureMulti()
+        const shapeIndex = this.feature._latlngs.indexOf(shape)
+        if (shapeIndex === -1) return
+        const first = shape.slice(0, index + 1)
+        const second = shape.slice(index)
+        // We deal with reference, we don't want twice the same latlng around.
+        second[0] = L.latLng(second[0].lat, second[0].lng, second[0].alt)
+        this.feature._latlngs.splice(shapeIndex, 1, first, second)
+        this.refresh()
+        this.reset()
+      }
+
+    })
+
+    // 馃崅namespace Editable; 馃崅class PolygonEditor; 馃崅aka L.Editable.PolygonEditor
+    // 馃崅inherits PathEditor
+    L.Editable.PolygonEditor = L.Editable.PathEditor.extend({
+
+      CLOSED: true,
+      MIN_VERTEX: 3,
+
+      newPointForward: function (latlng) {
+        L.Editable.PathEditor.prototype.newPointForward.call(this, latlng)
+        if (!this.tools.backwardLineGuide._latlngs.length) this.tools.anchorBackwardLineGuide(latlng)
+        if (this._drawnLatLngs.length === 2) this.tools.attachBackwardLineGuide()
+      },
+
+      addNewEmptyHole: function (latlng) {
+        this.ensureNotFlat()
+        const latlngs = this.feature.shapeAt(latlng)
+        if (!latlngs) return
+        const holes = []
+        latlngs.push(holes)
+        return holes
+      },
+
+      // 馃崅method newHole(latlng?: L.LatLng, index: int)
+      // Set up drawing tools for creating a new hole on the Polygon. If the `latlng` param is given, a first point is created.
+      newHole: function (latlng) {
+        const holes = this.addNewEmptyHole(latlng)
+        if (!holes) return
+        this.setDrawnLatLngs(holes)
+        this.startDrawingForward()
+        if (latlng) this.newPointForward(latlng)
+      },
+
+      addNewEmptyShape: function () {
+        if (this.feature._latlngs.length && this.feature._latlngs[0].length) {
+          const shape = []
+          this.appendShape(shape)
+          return shape
+        } else {
+          return this.feature._latlngs
+        }
+      },
+
+      ensureMulti: function () {
+        if (this.feature._latlngs.length && isFlat(this.feature._latlngs[0])) {
+          this.feature._latlngs = [this.feature._latlngs]
+        }
+      },
+
+      ensureNotFlat: function () {
+        if (!this.feature._latlngs.length || isFlat(this.feature._latlngs)) this.feature._latlngs = [this.feature._latlngs]
+      },
+
+      vertexCanBeDeleted: function (vertex) {
+        const parent = this.feature.parentShape(vertex.latlngs)
+        const idx = L.Util.indexOf(parent, vertex.latlngs)
+        if (idx > 0) return true // Holes can be totally deleted without removing the layer itself.
+        return L.Editable.PathEditor.prototype.vertexCanBeDeleted.call(this, vertex)
+      },
+
+      getDefaultLatLngs: function () {
+        if (!this.feature._latlngs.length) this.feature._latlngs.push([])
+        return this.feature._latlngs[0]
+      },
+
+      formatShape: function (shape) {
+        // [[1, 2], [3, 4]] => must be nested
+        // [] => must be nested
+        // [[]] => is already nested
+        if (isFlat(shape) && (!shape[0] || shape[0].length !== 0)) return [shape]
+        else return shape
+      }
+
+    })
+
+    // 馃崅namespace Editable; 馃崅class RectangleEditor; 馃崅aka L.Editable.RectangleEditor
+    // 馃崅inherits PathEditor
+    L.Editable.RectangleEditor = L.Editable.PathEditor.extend({
+
+      CLOSED: true,
+      MIN_VERTEX: 4,
+
+      options: {
+        skipMiddleMarkers: true
+      },
+
+      extendBounds: function (e) {
+        const index = e.vertex.getIndex()
+        const next = e.vertex.getNext()
+        const previous = e.vertex.getPrevious()
+        const oppositeIndex = (index + 2) % 4
+        const opposite = e.vertex.latlngs[oppositeIndex]
+        const bounds = new L.LatLngBounds(e.latlng, opposite)
+        // Update latlngs by hand to preserve order.
+        previous.latlng.update([e.latlng.lat, opposite.lng])
+        next.latlng.update([opposite.lat, e.latlng.lng])
+        this.updateBounds(bounds)
+        this.refreshVertexMarkers()
+      },
+
+      onDrawingMouseDown: function (e) {
+        L.Editable.PathEditor.prototype.onDrawingMouseDown.call(this, e)
+        this.connect()
+        const latlngs = this.getDefaultLatLngs()
+        // L.Polygon._convertLatLngs removes last latlng if it equals first point,
+        // which is the case here as all latlngs are [0, 0]
+        if (latlngs.length === 3) latlngs.push(e.latlng)
+        const bounds = new L.LatLngBounds(e.latlng, e.latlng)
+        this.updateBounds(bounds)
+        this.updateLatLngs(bounds)
+        this.refresh()
+        this.reset()
+        // Stop dragging map.
+        // L.Draggable has two workflows:
+        // - mousedown => mousemove => mouseup
+        // - touchstart => touchmove => touchend
+        // Problem: L.Map.Tap does not allow us to listen to touchstart, so we only
+        // can deal with mousedown, but then when in a touch device, we are dealing with
+        // simulated events (actually simulated by L.Map.Tap), which are no more taken
+        // into account by L.Draggable.
+        // Ref.: https://github.com/Leaflet/Leaflet.Editable/issues/103
+        e.originalEvent._simulated = false
+        this.map.dragging._draggable._onUp(e.originalEvent)
+        // Now transfer ongoing drag action to the bottom right corner.
+        // Should we refine which corner will handle the drag according to
+        // drag direction?
+        latlngs[3].__vertex.dragging._draggable._onDown(e.originalEvent)
+      },
+
+      onDrawingMouseUp: function (e) {
+        this.commitDrawing(e)
+        e.originalEvent._simulated = false
+        L.Editable.PathEditor.prototype.onDrawingMouseUp.call(this, e)
+      },
+
+      onDrawingMouseMove: function (e) {
+        e.originalEvent._simulated = false
+        L.Editable.PathEditor.prototype.onDrawingMouseMove.call(this, e)
+      },
+
+      getDefaultLatLngs: function (latlngs) {
+        return latlngs || this.feature._latlngs[0]
+      },
+
+      updateBounds: function (bounds) {
+        this.feature._bounds = bounds
+      },
+
+      updateLatLngs: function (bounds) {
+        const latlngs = this.getDefaultLatLngs()
+        const newLatlngs = this.feature._boundsToLatLngs(bounds)
+        // Keep references.
+        for (let i = 0; i < latlngs.length; i++) {
+          latlngs[i].update(newLatlngs[i])
+        }
+      }
+
+    })
+
+    // 馃崅namespace Editable; 馃崅class CircleEditor; 馃崅aka L.Editable.CircleEditor
+    // 馃崅inherits PathEditor
+    L.Editable.CircleEditor = L.Editable.PathEditor.extend({
+
+      MIN_VERTEX: 2,
+
+      options: {
+        skipMiddleMarkers: true
+      },
+
+      initialize: function (map, feature, options) {
+        L.Editable.PathEditor.prototype.initialize.call(this, map, feature, options)
+        // C.Y.B Modify
+
+        const latlng = this.computeResizeLatLng()
+
+        // latlng.lat = latlng.lat-0.007855;
+        // latlng.lng= latlng.lng-0.1;
+        this._resizeLatLng = latlng
+        // 鍘熷鏂规硶
+        // this._resizeLatLng = this.computeResizeLatLng();
+      },
+
+      computeResizeLatLng: function () {
+        // While circle is not added to the map, _radius is not set.
+        // let delta = (this.feature._radius || this.feature._mRadius) * Math.cos(Math.PI / 4)
+        const delta = (this.feature._radius || this.feature._mRadius)
+        const point = this.map.project(this.feature._latlng)
+        // return this.map.unproject([point.x + delta, point.y - delta])
+        return this.map.unproject([point.x + delta, point.y])
+      },
+
+      updateResizeLatLng: function () {
+        this._resizeLatLng.update(this.computeResizeLatLng())
+        this._resizeLatLng.__vertex.update()
+      },
+
+      getLatLngs: function () {
+        return [this.feature._latlng, this._resizeLatLng]
+      },
+
+      getDefaultLatLngs: function () {
+        return this.getLatLngs()
+      },
+
+      onVertexMarkerDrag: function (e) {
+        if (e.vertex.getIndex() === 1) this.resize(e)
+        else this.updateResizeLatLng(e)
+        L.Editable.PathEditor.prototype.onVertexMarkerDrag.call(this, e)
+      },
+
+      resize: function (e) {
+        const radius = this.feature._latlng.distanceTo(e.latlng)
+        this.feature.setRadius(radius)
+      },
+
+      onDrawingMouseDown: function (e) {
+        L.Editable.PathEditor.prototype.onDrawingMouseDown.call(this, e)
+        this._resizeLatLng.update(e.latlng)
+        this.feature._latlng.update(e.latlng)
+        this.connect()
+        // Stop dragging map.
+        e.originalEvent._simulated = false
+        this.map.dragging._draggable._onUp(e.originalEvent)
+        // Now transfer ongoing drag action to the radius handler.
+        this._resizeLatLng.__vertex.dragging._draggable._onDown(e.originalEvent)
+      },
+
+      onDrawingMouseUp: function (e) {
+        this.commitDrawing(e)
+        e.originalEvent._simulated = false
+        L.Editable.PathEditor.prototype.onDrawingMouseUp.call(this, e)
+      },
+
+      onDrawingMouseMove: function (e) {
+        e.originalEvent._simulated = false
+        L.Editable.PathEditor.prototype.onDrawingMouseMove.call(this, e)
+      },
+
+      onDrag: function (e) {
+        L.Editable.PathEditor.prototype.onDrag.call(this, e)
+        this.feature.dragging.updateLatLng(this._resizeLatLng)
+      }
+
+    })
+
+    // 馃崅namespace Editable; 馃崅class EditableMixin
+    // `EditableMixin` is included to `L.Polyline`, `L.Polygon`, `L.Rectangle`, `L.Circle`
+    // and `L.Marker`. It adds some methods to them.
+    // *When editing is enabled, the editor is accessible on the instance with the
+    // `editor` property.*
+    const EditableMixin = {
+
+      createEditor: function (map) {
+        map = map || this._map
+        const tools = (this.options.editOptions || {}).editTools || map.editTools
+        if (!tools) throw Error('Unable to detect Editable instance.')
+        const Klass = this.options.editorClass || this.getEditorClass(tools)
+        return new Klass(map, this, this.options.editOptions)
+      },
+
+      // 馃崅method enableEdit(map?: L.Map): this.editor
+      // Enable editing, by creating an editor if not existing, and then calling `enable` on it.
+      enableEdit: function (map) {
+        if (!this.editor) this.createEditor(map)
+        this.editor.enable()
+        return this.editor
+      },
+
+      // 馃崅method editEnabled(): boolean
+      // Return true if current instance has an editor attached, and this editor is enabled.
+      editEnabled: function () {
+        return this.editor && this.editor.enabled()
+      },
+
+      // 馃崅method disableEdit()
+      // Disable editing, also remove the editor property reference.
+      disableEdit: function () {
+        if (this.editor) {
+          this.editor.disable()
+          delete this.editor
+        }
+      },
+
+      // 馃崅method toggleEdit()
+      // Enable or disable editing, according to current status.
+      toggleEdit: function () {
+        if (this.editEnabled()) this.disableEdit()
+        else this.enableEdit()
+      },
+
+      _onEditableAdd: function () {
+        if (this.editor) this.enableEdit()
+      }
+
+    }
+
+    const PolylineMixin = {
+
+      getEditorClass: function (tools) {
+        return (tools && tools.options.polylineEditorClass) ? tools.options.polylineEditorClass : L.Editable.PolylineEditor
+      },
+
+      shapeAt: function (latlng, latlngs) {
+        // We can have those cases:
+        // - latlngs are just a flat array of latlngs, use this
+        // - latlngs is an array of arrays of latlngs, loop over
+        let shape = null
+        latlngs = latlngs || this._latlngs
+        if (!latlngs.length) return shape
+        else if (isFlat(latlngs) && this.isInLatLngs(latlng, latlngs)) shape = latlngs
+        else for (let i = 0; i < latlngs.length; i++) if (this.isInLatLngs(latlng, latlngs[i])) return latlngs[i]
+        return shape
+      },
+
+      isInLatLngs: function (l, latlngs) {
+        if (!latlngs) return false
+        let i, k, len
+        let part = []
+        const w = this._clickTolerance()
+        this._projectLatlngs(latlngs, part, this._pxBounds)
+        part = part[0]
+        const p = this._map.latLngToLayerPoint(l)
+
+        if (!this._pxBounds.contains(p)) {
+          return false
+        }
+        for (i = 1, len = part.length, k = 0; i < len; k = i++) {
+          if (L.LineUtil.pointToSegmentDistance(p, part[k], part[i]) <= w) {
+            return true
+          }
+        }
+        return false
+      }
+
+    }
+
+    const PolygonMixin = {
+
+      getEditorClass: function (tools) {
+        return (tools && tools.options.polygonEditorClass) ? tools.options.polygonEditorClass : L.Editable.PolygonEditor
+      },
+
+      shapeAt: function (latlng, latlngs) {
+        // We can have those cases:
+        // - latlngs are just a flat array of latlngs, use this
+        // - latlngs is an array of arrays of latlngs, this is a simple polygon (maybe with holes), use the first
+        // - latlngs is an array of arrays of arrays, this is a multi, loop over
+        let shape = null
+        latlngs = latlngs || this._latlngs
+        if (!latlngs.length) return shape
+        else if (isFlat(latlngs) && this.isInLatLngs(latlng, latlngs)) shape = latlngs
+        else if (isFlat(latlngs[0]) && this.isInLatLngs(latlng, latlngs[0])) shape = latlngs
+        else for (let i = 0; i < latlngs.length; i++) if (this.isInLatLngs(latlng, latlngs[i][0])) return latlngs[i]
+        return shape
+      },
+
+      isInLatLngs: function (l, latlngs) {
+        let inside = false
+        let l1
+        let l2
+        let j
+        let k
+        let len2
+        for (j = 0, len2 = latlngs.length, k = len2 - 1; j < len2; k = j++) {
+          l1 = latlngs[j]
+          l2 = latlngs[k]
+
+          if (((l1.lat > l.lat) !== (l2.lat > l.lat)) &&
                         (l.lng < (l2.lng - l1.lng) * (l.lat - l1.lat) / (l2.lat - l1.lat) + l1.lng)) {
-                        inside = !inside
-                    }
-                }
-
-                return inside
-            },
-
-            parentShape: function(shape, latlngs) {
-                latlngs = latlngs || this._latlngs
-                if (!latlngs) return
-                let idx = L.Util.indexOf(latlngs, shape)
-                if (idx !== -1) return latlngs
-                for (let i = 0; i < latlngs.length; i++) {
-                    idx = L.Util.indexOf(latlngs[i], shape)
-                    if (idx !== -1) return latlngs[i]
-                }
-            }
-
+            inside = !inside
+          }
         }
 
-        let MarkerMixin = {
+        return inside
+      },
 
-            getEditorClass: function(tools) {
-                return (tools && tools.options.markerEditorClass) ? tools.options.markerEditorClass : L.Editable.MarkerEditor
-            }
-
+      parentShape: function (shape, latlngs) {
+        latlngs = latlngs || this._latlngs
+        if (!latlngs) return
+        let idx = L.Util.indexOf(latlngs, shape)
+        if (idx !== -1) return latlngs
+        for (let i = 0; i < latlngs.length; i++) {
+          idx = L.Util.indexOf(latlngs[i], shape)
+          if (idx !== -1) return latlngs[i]
         }
+      }
 
-        let RectangleMixin = {
+    }
 
-            getEditorClass: function(tools) {
-                return (tools && tools.options.rectangleEditorClass) ? tools.options.rectangleEditorClass : L.Editable.RectangleEditor
-            }
+    const MarkerMixin = {
 
-        }
+      getEditorClass: function (tools) {
+        return (tools && tools.options.markerEditorClass) ? tools.options.markerEditorClass : L.Editable.MarkerEditor
+      }
 
-        let CircleMixin = {
+    }
 
-            getEditorClass: function(tools) {
-                return (tools && tools.options.circleEditorClass) ? tools.options.circleEditorClass : L.Editable.CircleEditor
-            }
+    const RectangleMixin = {
 
-        }
+      getEditorClass: function (tools) {
+        return (tools && tools.options.rectangleEditorClass) ? tools.options.rectangleEditorClass : L.Editable.RectangleEditor
+      }
 
-        let keepEditable = function() {
-            // Make sure you can remove/readd an editable layer.
-            this.on('add', this._onEditableAdd)
-        }
+    }
 
-        let isFlat = L.LineUtil.isFlat || L.LineUtil._flat || L.Polyline._flat // <=> 1.1 compat.
+    const CircleMixin = {
 
-        if (L.Polyline) {
-            L.Polyline.include(EditableMixin)
-            L.Polyline.include(PolylineMixin)
-            L.Polyline.addInitHook(keepEditable)
-        }
-        if (L.Polygon) {
-            L.Polygon.include(EditableMixin)
-            L.Polygon.include(PolygonMixin)
-        }
-        if (L.Marker) {
-            L.Marker.include(EditableMixin)
-            L.Marker.include(MarkerMixin)
-            L.Marker.addInitHook(keepEditable)
-        }
-        if (L.Rectangle) {
-            L.Rectangle.include(EditableMixin)
-            L.Rectangle.include(RectangleMixin)
-        }
-        if (L.Circle) {
-            L.Circle.include(EditableMixin)
-            L.Circle.include(CircleMixin)
-        }
+      getEditorClass: function (tools) {
+        return (tools && tools.options.circleEditorClass) ? tools.options.circleEditorClass : L.Editable.CircleEditor
+      }
 
-        L.LatLng.prototype.update = function(latlng) {
-            latlng = L.latLng(latlng)
-            this.lat = latlng.lat
-            this.lng = latlng.lng
-        }
-    }, window))
+    }
+
+    const keepEditable = function () {
+      // Make sure you can remove/readd an editable layer.
+      this.on('add', this._onEditableAdd)
+    }
+
+    const isFlat = L.LineUtil.isFlat || L.LineUtil._flat || L.Polyline._flat // <=> 1.1 compat.
+
+    if (L.Polyline) {
+      L.Polyline.include(EditableMixin)
+      L.Polyline.include(PolylineMixin)
+      L.Polyline.addInitHook(keepEditable)
+    }
+    if (L.Polygon) {
+      L.Polygon.include(EditableMixin)
+      L.Polygon.include(PolygonMixin)
+    }
+    if (L.Marker) {
+      L.Marker.include(EditableMixin)
+      L.Marker.include(MarkerMixin)
+      L.Marker.addInitHook(keepEditable)
+    }
+    if (L.Rectangle) {
+      L.Rectangle.include(EditableMixin)
+      L.Rectangle.include(RectangleMixin)
+    }
+    if (L.Circle) {
+      L.Circle.include(EditableMixin)
+      L.Circle.include(CircleMixin)
+    }
+
+    L.LatLng.prototype.update = function (latlng) {
+      latlng = L.latLng(latlng)
+      this.lat = latlng.lat
+      this.lng = latlng.lng
+    }
+  }, window))
 }
 
 export default {
-    init
+  init
 }

--
Gitblit v1.8.0