(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i= 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); var 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; var 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) { var 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) { var 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; var self = this, inplaceDelete = function (latlngs, shape) { // Called when deleting a flat latlngs shape = latlngs.splice(0, Number.MAX_VALUE); return shape; }, 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 (var 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) { var 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) { var 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(); var shapeIndex = this.feature._latlngs.indexOf(shape); if (shapeIndex === -1) return; var first = shape.slice(0, index + 1), 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(); var latlngs = this.feature.shapeAt(latlng); if (!latlngs) return; var 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) { var 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) { var 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) { var parent = this.feature.parentShape(vertex.latlngs), 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) { var index = e.vertex.getIndex(), next = e.vertex.getNext(), previous = e.vertex.getPrevious(), oppositeIndex = (index + 2) % 4, opposite = e.vertex.latlngs[oppositeIndex], 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(); var 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); var 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) { var latlngs = this.getDefaultLatLngs(), newLatlngs = this.feature._boundsToLatLngs(bounds); // Keep references. for (var 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); this._resizeLatLng = this.computeResizeLatLng(); }, computeResizeLatLng: function () { // While circle is not added to the map, _radius is not set. var delta = (this.feature._radius || this.feature._mRadius) * Math.cos(Math.PI / 4), point = this.map.project(this.feature._latlng); return this.map.unproject([point.x + delta, point.y - delta]); }, 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) { var 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.* var EditableMixin = { createEditor: function (map) { map = map || this._map; var tools = (this.options.editOptions || {}).editTools || map.editTools; if (!tools) throw Error('Unable to detect Editable instance.'); var 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(); } }; var 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 var shape = null; latlngs = latlngs || this._latlngs; if (!latlngs.length) return shape; else if (isFlat(latlngs) && this.isInLatLngs(latlng, latlngs)) shape = latlngs; else for (var 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; var i, k, len, part = [], p, 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; } }; var 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 var 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 (var i = 0; i < latlngs.length; i++) if (this.isInLatLngs(latlng, latlngs[i][0])) return latlngs[i]; return shape; }, isInLatLngs: function (l, latlngs) { var inside = false, l1, l2, j, k, 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; var idx = L.Util.indexOf(latlngs, shape); if (idx !== -1) return latlngs; for (var i = 0; i < latlngs.length; i++) { idx = L.Util.indexOf(latlngs[i], shape); if (idx !== -1) return latlngs[i]; } } }; var MarkerMixin = { getEditorClass: function (tools) { return (tools && tools.options.markerEditorClass) ? tools.options.markerEditorClass : L.Editable.MarkerEditor; } }; var RectangleMixin = { getEditorClass: function (tools) { return (tools && tools.options.rectangleEditorClass) ? tools.options.rectangleEditorClass : L.Editable.RectangleEditor; } }; var CircleMixin = { getEditorClass: function (tools) { return (tools && tools.options.circleEditorClass) ? tools.options.circleEditorClass : L.Editable.CircleEditor; } }; var keepEditable = function () { // Make sure you can remove/readd an editable layer. this.on('add', this._onEditableAdd); }; var 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)); }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{}],2:[function(require,module,exports){ 'use strict'; /* A Draggable that does not update the element position and takes care of only bubbling to targetted path in Canvas mode. */ L.PathDraggable = L.Draggable.extend({ initialize: function (path) { this._path = path; this._canvas = (path._map.getRenderer(path) instanceof L.Canvas); var element = this._canvas ? this._path._map.getRenderer(this._path)._container : this._path._path; L.Draggable.prototype.initialize.call(this, element, element, true); }, _updatePosition: function () { var e = {originalEvent: this._lastEvent}; this.fire('drag', e); }, _onDown: function (e) { var first = e.touches ? e.touches[0] : e; this._startPoint = new L.Point(first.clientX, first.clientY); if (this._canvas && !this._path._containsPoint(this._path._map.mouseEventToLayerPoint(first))) { return; } L.Draggable.prototype._onDown.call(this, e); } }); L.Handler.PathDrag = L.Handler.extend({ initialize: function (path) { this._path = path; }, getEvents: function () { return { dragstart: this._onDragStart, drag: this._onDrag, dragend: this._onDragEnd }; }, addHooks: function () { if (!this._draggable) { this._draggable = new L.PathDraggable(this._path); } this._draggable.on(this.getEvents(), this).enable(); L.DomUtil.addClass(this._draggable._element, 'leaflet-path-draggable'); }, removeHooks: function () { this._draggable.off(this.getEvents(), this).disable(); L.DomUtil.removeClass(this._draggable._element, 'leaflet-path-draggable'); }, moved: function () { return this._draggable && this._draggable._moved; }, _onDragStart: function () { this._startPoint = this._draggable._startPoint; this._path .closePopup() .fire('movestart') .fire('dragstart'); }, _onDrag: function (e) { var path = this._path, event = (e.originalEvent.touches && e.originalEvent.touches.length === 1 ? e.originalEvent.touches[0] : e.originalEvent), newPoint = L.point(event.clientX, event.clientY), latlng = path._map.layerPointToLatLng(newPoint); this._offset = newPoint.subtract(this._startPoint); this._startPoint = newPoint; this._path.eachLatLng(this.updateLatLng, this); path.redraw(); e.latlng = latlng; e.offset = this._offset; path.fire('drag', e); e.latlng = this._path.getCenter ? this._path.getCenter() : this._path.getLatLng(); path.fire('move', e); }, _onDragEnd: function (e) { if (this._path._bounds) this.resetBounds(); this._path.fire('moveend') .fire('dragend', e); }, latLngToLayerPoint: function (latlng) { // Same as map.latLngToLayerPoint, but without the round(). var projectedPoint = this._path._map.project(L.latLng(latlng)); return projectedPoint._subtract(this._path._map.getPixelOrigin()); }, updateLatLng: function (latlng) { var oldPoint = this.latLngToLayerPoint(latlng); oldPoint._add(this._offset); var newLatLng = this._path._map.layerPointToLatLng(oldPoint); latlng.lat = newLatLng.lat; latlng.lng = newLatLng.lng; }, resetBounds: function () { this._path._bounds = new L.LatLngBounds(); this._path.eachLatLng(function (latlng) { this._bounds.extend(latlng); }); } }); L.Path.include({ eachLatLng: function (callback, context) { context = context || this; var loop = function (latlngs) { for (var i = 0; i < latlngs.length; i++) { if (L.Util.isArray(latlngs[i])) loop(latlngs[i]); else callback.call(context, latlngs[i]); } }; loop(this.getLatLngs ? this.getLatLngs() : [this.getLatLng()]); } }); L.Path.addInitHook(function () { this.dragging = new L.Handler.PathDrag(this); if (this.options.draggable) { this.once('add', function () { this.dragging.enable(); }); } }); },{}],3:[function(require,module,exports){ (function (global){ /* * leaflet-shades * Leaflet plugin to add transparent overlay within selected region * of Leaflet.Editable and a gray overlay outside selected region * * License: MIT * (c) Mandy Kong */ (function (root, factory) { var L; if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['leaflet'], factory); } else if (typeof module === 'object' && module.exports) { // Node. Does not work with strict CommonJS, but // only CommonJS-like environments that support module.exports, // like Node. L = (typeof window !== "undefined" ? window['L'] : typeof global !== "undefined" ? global['L'] : null); module.exports = factory(L); } else { // Browser globals (root is window) if (typeof root.L === 'undefined') { throw new Error('Leaflet must be loaded first'); } root.LeafletShades = factory(root.L); } }(this, function (L) { 'use strict'; var LeafletShades = require('./leaflet-shades'); // Automatically attach to Leaflet's `L` namespace. L.LeafletShades = LeafletShades; L.leafletShades = function (opts) { return new LeafletShades(opts); } // Return value defines this module's export value. return LeafletShades; })); }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"./leaflet-shades":4}],4:[function(require,module,exports){ (function (global){ var L = (typeof window !== "undefined" ? window['L'] : typeof global !== "undefined" ? global['L'] : null); require('leaflet-editable'); require('leaflet.path.drag'); var LeafletShades = L.Layer.extend({ includes: L.Evented ? L.Evented.prototype : L.Mixin.Events, options: { bounds: null }, initialize: function (options) { L.setOptions(this, options); }, onAdd: function (map) { this._map = map; this._addEventListeners(); this._shadesContainer = L.DomUtil.create('div', 'leaflet-areaselect-container leaflet-zoom-hide'); this._topShade = L.DomUtil.create('div', 'leaflet-areaselect-shade', this._shadesContainer); this._bottomShade = L.DomUtil.create('div', 'leaflet-areaselect-shade', this._shadesContainer); this._leftShade = L.DomUtil.create('div', 'leaflet-areaselect-shade', this._shadesContainer); this._rightShade = L.DomUtil.create('div', 'leaflet-areaselect-shade', this._shadesContainer); map.getPanes().overlayPane.appendChild(this._shadesContainer); if (this.options.bounds) this._updateShades(this.options.bounds) }, _addEventListeners: function () { this._mapEvents = { 'editable:drawing:commit': this._onBoundsChanged.bind(this), 'editable:vertex:dragend': this._onBoundsChanged.bind(this), 'editable:dragend': this._onBoundsChanged.bind(this), 'moveend': this._updatedMapPosition.bind(this) }; for (const type in this._mapEvents) { if (Object.hasOwnProperty.call(this._mapEvents, type)) { this._map.on(type, this._mapEvents[type]); } } }, _onBoundsChanged: function (event) { var _bounds = event.layer.getBounds(); this.fire('shades:bounds-changed', { bounds: _bounds }); this._updateShades(_bounds); }, _updatedMapPosition: function (event) { if (this._bounds) { this.fire('shades:bounds-changed', { bounds: this._bounds }); this._updateShades(this._bounds); } }, _getOffset: function () { // Getting the transformation value through style attributes var transformation = this._map.getPanes().mapPane.style.transform const startIndex = transformation.indexOf('(') const endIndex = transformation.indexOf(')') transformation = transformation.substring(startIndex + 1, endIndex).split(',') const offset = { x: parseInt(transformation[0], 10) * -1, y: parseInt(transformation[1], 10) * -1 } return offset }, _updateShades: function (bounds) { if (bounds !== this._bounds) this._bounds = bounds; const size = this._map.getSize(); const northEastPoint = this._map.latLngToContainerPoint(bounds.getNorthEast()); const southWestPoint = this._map.latLngToContainerPoint(bounds.getSouthWest()); const offset = this._getOffset(); this.setDimensions(this._topShade, { width: size.x, height: (northEastPoint.y < 0) ? 0 : northEastPoint.y, top: offset.y, left: offset.x }) this.setDimensions(this._bottomShade, { width: size.x, height: size.y - southWestPoint.y, top: southWestPoint.y + offset.y, left: offset.x }) this.setDimensions(this._leftShade, { width: (southWestPoint.x < 0) ? 0 : southWestPoint.x, height: southWestPoint.y - northEastPoint.y, top: northEastPoint.y + offset.y, left: offset.x }) this.setDimensions(this._rightShade, { width: size.x - northEastPoint.x, height: southWestPoint.y - northEastPoint.y, top: northEastPoint.y + offset.y, left: northEastPoint.x + offset.x }) }, setDimensions: function (element, dimensions) { element.style.width = dimensions.width + 'px'; element.style.height = dimensions.height + 'px'; element.style.top = dimensions.top + 'px'; element.style.left = dimensions.left + 'px'; }, onRemove: function (map) { map.getPanes().overlayPane.removeChild(this._shadesContainer); for (const type in this._mapEvents) { if (Object.hasOwnProperty.call(this._mapEvents, type)) { this._map.off(type, this._mapEvents[type]); } } } }); module.exports = LeafletShades; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"leaflet-editable":1,"leaflet.path.drag":2}]},{},[3]);