leaflet-js 0.7.9 → 0.8.dev2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.rdoc +0 -10
  3. data/Rakefile +3 -3
  4. data/leaflet-js.gemspec +7 -13
  5. data/lib/leaflet-js.rb +10 -2
  6. data/lib/leaflet.draw/BREAKINGCHANGES.md +54 -0
  7. data/lib/leaflet.draw/CHANGELOG.md +130 -0
  8. data/lib/leaflet.draw/Jakefile.js +48 -0
  9. data/lib/leaflet.draw/MIT-LICENCE.txt +20 -0
  10. data/lib/leaflet.draw/README.md +427 -0
  11. data/lib/leaflet.draw/TODO.md +62 -0
  12. data/lib/leaflet.draw/build/build.html +243 -0
  13. data/lib/leaflet.draw/build/build.js +187 -0
  14. data/lib/leaflet.draw/build/deps.js +76 -0
  15. data/lib/leaflet.draw/build/hintrc.js +39 -0
  16. data/lib/leaflet.draw/build/leaflet.draw-include.js +42 -0
  17. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/dist/images/spritesheet-2x.png +0 -0
  18. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/dist/images/spritesheet.png +0 -0
  19. data/lib/leaflet.draw/dist/leaflet.draw-src.js +2872 -0
  20. data/lib/leaflet.draw/dist/leaflet.draw.css +295 -0
  21. data/lib/leaflet.draw/dist/leaflet.draw.js +10 -0
  22. data/lib/leaflet.draw/examples/basic.html +113 -0
  23. data/lib/leaflet.draw/examples/edithandlers.html +66 -0
  24. data/{vendor/assets/Leaflet/dist → lib/leaflet.draw/examples/libs}/images/layers-2x.png +0 -0
  25. data/{vendor/assets/Leaflet/dist → lib/leaflet.draw/examples/libs}/images/layers.png +0 -0
  26. data/{vendor/assets/Leaflet/dist → lib/leaflet.draw/examples/libs}/images/marker-icon-2x.png +0 -0
  27. data/{vendor/assets/Leaflet/dist → lib/leaflet.draw/examples/libs}/images/marker-icon.png +0 -0
  28. data/lib/leaflet.draw/examples/libs/images/marker-icon@2x.png +0 -0
  29. data/{vendor/assets/Leaflet/dist → lib/leaflet.draw/examples/libs}/images/marker-shadow.png +0 -0
  30. data/lib/leaflet.draw/examples/libs/leaflet-src.js +9191 -0
  31. data/{vendor/assets/leaflet.css.erb → lib/leaflet.draw/examples/libs/leaflet.css} +2 -2
  32. data/lib/leaflet.draw/package.json +40 -0
  33. data/lib/leaflet.draw/spec/after.js +2 -0
  34. data/lib/leaflet.draw/spec/before.js +3 -0
  35. data/lib/leaflet.draw/spec/expect.js +1253 -0
  36. data/lib/leaflet.draw/spec/happen.js +93 -0
  37. data/lib/leaflet.draw/spec/index.html +38 -0
  38. data/lib/leaflet.draw/spec/karma.conf.js +72 -0
  39. data/lib/leaflet.draw/spec/sinon.js +4223 -0
  40. data/lib/leaflet.draw/spec/spec.hintrc.js +25 -0
  41. data/lib/leaflet.draw/spec/suites/DrawControlSpec.js +14 -0
  42. data/lib/leaflet.draw/spec/suites/GeometryUtilSpec.js +25 -0
  43. data/lib/leaflet.draw/spec/suites/LatLngUtilSpec.js +11 -0
  44. data/lib/leaflet.draw/spec/suites/SpecHelper.js +28 -0
  45. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/Control.Draw.js +9 -9
  46. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/Leaflet.draw.js +1 -2
  47. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/Toolbar.js +0 -0
  48. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/Tooltip.js +0 -0
  49. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/copyright.js +0 -0
  50. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/draw/DrawToolbar.js +0 -4
  51. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/draw/handler/Draw.Circle.js +1 -1
  52. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/draw/handler/Draw.Feature.js +2 -2
  53. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/draw/handler/Draw.Marker.js +0 -0
  54. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/draw/handler/Draw.Polygon.js +0 -0
  55. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/draw/handler/Draw.Polyline.js +0 -0
  56. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/draw/handler/Draw.Rectangle.js +1 -19
  57. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/draw/handler/Draw.SimpleShape.js +1 -7
  58. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/edit/EditToolbar.js +2 -9
  59. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/edit/handler/Edit.Circle.js +0 -0
  60. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/edit/handler/Edit.Poly.js +2 -14
  61. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/edit/handler/Edit.Rectangle.js +0 -0
  62. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/edit/handler/Edit.SimpleShape.js +3 -11
  63. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/edit/handler/EditToolbar.Delete.js +1 -4
  64. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/edit/handler/EditToolbar.Edit.js +83 -17
  65. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/ext/GeometryUtil.js +1 -1
  66. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/ext/LatLngUtil.js +0 -0
  67. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/ext/LineUtil.Intersect.js +0 -0
  68. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/ext/Polygon.Intersect.js +0 -0
  69. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/ext/Polyline.Intersect.js +0 -0
  70. data/{vendor/assets/Leaflet.draw → lib/leaflet.draw}/src/images/spritesheet.svg +0 -0
  71. data/lib/leaflet.label/CHANGELOG.md +67 -0
  72. data/lib/leaflet.label/Jakefile.js +21 -0
  73. data/lib/leaflet.label/MIT-LICENCE.txt +20 -0
  74. data/lib/leaflet.label/README.md +103 -0
  75. data/lib/leaflet.label/build/build.js +155 -0
  76. data/lib/leaflet.label/build/deps.js +26 -0
  77. data/lib/leaflet.label/build/hint.js +30 -0
  78. data/lib/leaflet.label/build/hintrc.js +51 -0
  79. data/lib/leaflet.label/dist/images/death.png +0 -0
  80. data/lib/leaflet.label/dist/leaflet.label-src.js +542 -0
  81. data/{vendor/assets → lib/leaflet.label/dist}/leaflet.label.css +0 -0
  82. data/lib/leaflet.label/dist/leaflet.label.js +9 -0
  83. data/lib/leaflet.label/example/label.html +85 -0
  84. data/lib/leaflet.label/libs/leaflet/images/layers-2x.png +0 -0
  85. data/lib/leaflet.label/libs/leaflet/images/layers.png +0 -0
  86. data/lib/leaflet.label/libs/leaflet/images/marker-icon-2x.png +0 -0
  87. data/lib/leaflet.label/libs/leaflet/images/marker-icon.png +0 -0
  88. data/lib/leaflet.label/libs/leaflet/images/marker-icon@2x.png +0 -0
  89. data/lib/leaflet.label/libs/leaflet/images/marker-shadow.png +0 -0
  90. data/lib/leaflet.label/libs/leaflet/leaflet-src.js +9108 -0
  91. data/lib/leaflet.label/libs/leaflet/leaflet.css +478 -0
  92. data/lib/leaflet.label/libs/leaflet/leaflet.js +9 -0
  93. data/lib/leaflet.label/package.json +19 -0
  94. data/{vendor/assets/Leaflet.label → lib/leaflet.label}/src/BaseMarkerMethods.js +0 -0
  95. data/{vendor/assets/Leaflet.label → lib/leaflet.label}/src/CircleMarker.Label.js +0 -0
  96. data/{vendor/assets/Leaflet.label → lib/leaflet.label}/src/FeatureGroup.Label.js +0 -0
  97. data/{vendor/assets/Leaflet.label → lib/leaflet.label}/src/Label.js +2 -5
  98. data/{vendor/assets/Leaflet.label → lib/leaflet.label}/src/Leaflet.label.js +1 -1
  99. data/{vendor/assets/Leaflet.label → lib/leaflet.label}/src/Map.Label.js +0 -0
  100. data/{vendor/assets/Leaflet.label → lib/leaflet.label}/src/Marker.Label.js +0 -0
  101. data/{vendor/assets/Leaflet.label → lib/leaflet.label}/src/Path.Label.js +0 -0
  102. data/{vendor/assets/Leaflet.label → lib/leaflet.label}/src/copyright.js +0 -0
  103. data/lib/leaflet/CHANGELOG.md +1007 -0
  104. data/lib/leaflet/CONTRIBUTING.md +155 -0
  105. data/lib/leaflet/FAQ.md +138 -0
  106. data/lib/leaflet/Jakefile.js +56 -0
  107. data/lib/leaflet/LICENSE +23 -0
  108. data/lib/leaflet/PLUGIN-GUIDE.md +127 -0
  109. data/lib/leaflet/README.md +34 -0
  110. data/lib/leaflet/build/build.html +227 -0
  111. data/lib/leaflet/build/build.js +190 -0
  112. data/lib/leaflet/build/deps.js +258 -0
  113. data/lib/leaflet/build/hintrc.js +40 -0
  114. data/lib/leaflet/debug/css/mobile.css +6 -0
  115. data/lib/leaflet/debug/css/screen.css +5 -0
  116. data/lib/leaflet/debug/hacks/jitter.html +42 -0
  117. data/lib/leaflet/debug/leaflet-include.js +59 -0
  118. data/lib/leaflet/debug/map/canvas.html +49 -0
  119. data/lib/leaflet/debug/map/controls.html +49 -0
  120. data/lib/leaflet/debug/map/geolocation.html +34 -0
  121. data/lib/leaflet/debug/map/grid.html +45 -0
  122. data/lib/leaflet/debug/map/iframe.html +11 -0
  123. data/lib/leaflet/debug/map/image-overlay.html +43 -0
  124. data/lib/leaflet/debug/map/map-mobile.html +34 -0
  125. data/lib/leaflet/debug/map/map.html +61 -0
  126. data/lib/leaflet/debug/map/max-bounds.html +38 -0
  127. data/lib/leaflet/debug/map/opacity.html +223 -0
  128. data/lib/leaflet/debug/map/scroll.html +41 -0
  129. data/lib/leaflet/debug/map/simple-proj.html +59 -0
  130. data/lib/leaflet/debug/map/wms-marble.html +30 -0
  131. data/lib/leaflet/debug/map/wms.html +40 -0
  132. data/lib/leaflet/debug/map/zoomlevels.html +45 -0
  133. data/lib/leaflet/debug/tests/add_remove_layers.html +87 -0
  134. data/lib/leaflet/debug/tests/bringtoback.html +37 -0
  135. data/lib/leaflet/debug/tests/canvasloop.html +47 -0
  136. data/lib/leaflet/debug/tests/click_on_canvas.html +58 -0
  137. data/lib/leaflet/debug/tests/click_on_canvas_broken.html +49 -0
  138. data/lib/leaflet/debug/tests/dragging_and_copyworldjump.html +61 -0
  139. data/lib/leaflet/debug/tests/opacity.html +56 -0
  140. data/lib/leaflet/debug/tests/popupcontextmenuclicks.html +59 -0
  141. data/lib/leaflet/debug/tests/remove_while_dragging.html +28 -0
  142. data/lib/leaflet/debug/tests/removetilewhilepan.html +41 -0
  143. data/lib/leaflet/debug/tests/reuse_popups.html +40 -0
  144. data/lib/leaflet/debug/tests/rtl.html +42 -0
  145. data/lib/leaflet/debug/tests/rtl2.html +27 -0
  146. data/lib/leaflet/debug/tests/set_icon_reuse_dom.html +43 -0
  147. data/lib/leaflet/debug/tests/svg_clicks.html +54 -0
  148. data/lib/leaflet/debug/vector/bounds-extend.html +88 -0
  149. data/lib/leaflet/debug/vector/feature-group-bounds.html +90 -0
  150. data/lib/leaflet/debug/vector/geojson-sample.js +53 -0
  151. data/lib/leaflet/debug/vector/geojson.html +173 -0
  152. data/lib/leaflet/debug/vector/rectangle.html +53 -0
  153. data/lib/leaflet/debug/vector/route.js +1 -0
  154. data/lib/leaflet/debug/vector/touchzoomemu.html +194 -0
  155. data/lib/leaflet/debug/vector/us-states.js +54 -0
  156. data/lib/leaflet/debug/vector/vector-bounds.html +69 -0
  157. data/lib/leaflet/debug/vector/vector-canvas.html +92 -0
  158. data/lib/leaflet/debug/vector/vector-mobile.html +38 -0
  159. data/lib/leaflet/debug/vector/vector-simple.html +47 -0
  160. data/lib/leaflet/debug/vector/vector.html +37 -0
  161. data/lib/leaflet/debug/vector/vector2.html +58 -0
  162. data/lib/leaflet/dist/images/layers-2x.png +0 -0
  163. data/lib/leaflet/dist/images/layers.png +0 -0
  164. data/lib/leaflet/dist/images/marker-icon-2x.png +0 -0
  165. data/lib/leaflet/dist/images/marker-icon.png +0 -0
  166. data/lib/leaflet/dist/images/marker-shadow.png +0 -0
  167. data/lib/leaflet/dist/leaflet.css +494 -0
  168. data/lib/leaflet/package.json +28 -0
  169. data/lib/leaflet/spec/after.js +2 -0
  170. data/lib/leaflet/spec/expect.js +1253 -0
  171. data/lib/leaflet/spec/index.html +87 -0
  172. data/lib/leaflet/spec/karma.conf.js +68 -0
  173. data/lib/leaflet/spec/sinon.js +4223 -0
  174. data/lib/leaflet/spec/spec.hintrc.js +25 -0
  175. data/lib/leaflet/spec/suites/SpecHelper.js +42 -0
  176. data/lib/leaflet/spec/suites/control/Control.AttributionSpec.js +68 -0
  177. data/lib/leaflet/spec/suites/control/Control.LayersSpec.js +67 -0
  178. data/lib/leaflet/spec/suites/control/Control.ScaleSpec.js +6 -0
  179. data/lib/leaflet/spec/suites/core/ClassSpec.js +166 -0
  180. data/lib/leaflet/spec/suites/core/EventsSpec.js +416 -0
  181. data/lib/leaflet/spec/suites/core/UtilSpec.js +237 -0
  182. data/lib/leaflet/spec/suites/dom/DomEventSpec.js +102 -0
  183. data/lib/leaflet/spec/suites/dom/DomUtilSpec.js +59 -0
  184. data/lib/leaflet/spec/suites/dom/PosAnimationSpec.js +27 -0
  185. data/lib/leaflet/spec/suites/geo/CRSSpec.js +151 -0
  186. data/lib/leaflet/spec/suites/geo/LatLngBoundsSpec.js +144 -0
  187. data/lib/leaflet/spec/suites/geo/LatLngSpec.js +102 -0
  188. data/lib/leaflet/spec/suites/geo/ProjectionSpec.js +96 -0
  189. data/lib/leaflet/spec/suites/geometry/BoundsSpec.js +87 -0
  190. data/lib/leaflet/spec/suites/geometry/LineUtilSpec.js +75 -0
  191. data/lib/leaflet/spec/suites/geometry/PointSpec.js +104 -0
  192. data/lib/leaflet/spec/suites/geometry/PolyUtilSpec.js +27 -0
  193. data/lib/leaflet/spec/suites/geometry/TransformationSpec.js +31 -0
  194. data/lib/leaflet/spec/suites/layer/FeatureGroupSpec.js +86 -0
  195. data/lib/leaflet/spec/suites/layer/GeoJSONSpec.js +282 -0
  196. data/lib/leaflet/spec/suites/layer/LayerGroupSpec.js +71 -0
  197. data/lib/leaflet/spec/suites/layer/PopupSpec.js +119 -0
  198. data/lib/leaflet/spec/suites/layer/marker/MarkerSpec.js +117 -0
  199. data/lib/leaflet/spec/suites/layer/tile/GridLayerSpec.js +70 -0
  200. data/lib/leaflet/spec/suites/layer/tile/TileLayerSpec.js +88 -0
  201. data/lib/leaflet/spec/suites/layer/vector/CircleMarkerSpec.js +53 -0
  202. data/lib/leaflet/spec/suites/layer/vector/CircleSpec.js +18 -0
  203. data/lib/leaflet/spec/suites/layer/vector/PolygonSpec.js +96 -0
  204. data/lib/leaflet/spec/suites/layer/vector/PolylineGeometrySpec.js +35 -0
  205. data/lib/leaflet/spec/suites/layer/vector/PolylineSpec.js +55 -0
  206. data/lib/leaflet/spec/suites/map/MapSpec.js +553 -0
  207. data/lib/leaflet/spec/suites/map/handler/Map.DragSpec.js +38 -0
  208. data/{vendor/assets/Leaflet → lib/leaflet}/src/Leaflet.js +16 -11
  209. data/{vendor/assets/Leaflet → lib/leaflet}/src/control/Control.Attribution.js +1 -23
  210. data/{vendor/assets/Leaflet → lib/leaflet}/src/control/Control.Layers.js +42 -57
  211. data/lib/leaflet/src/control/Control.Scale.js +102 -0
  212. data/{vendor/assets/Leaflet → lib/leaflet}/src/control/Control.Zoom.js +11 -18
  213. data/{vendor/assets/Leaflet → lib/leaflet}/src/control/Control.js +7 -9
  214. data/lib/leaflet/src/copyright.js +4 -0
  215. data/lib/leaflet/src/core/Browser.js +65 -0
  216. data/{vendor/assets/Leaflet → lib/leaflet}/src/core/Class.js +8 -13
  217. data/lib/leaflet/src/core/Events.js +226 -0
  218. data/{vendor/assets/Leaflet → lib/leaflet}/src/core/Handler.js +0 -0
  219. data/lib/leaflet/src/core/Util.js +196 -0
  220. data/{vendor/assets/Leaflet → lib/leaflet}/src/dom/DomEvent.DoubleTap.js +20 -27
  221. data/lib/leaflet/src/dom/DomEvent.Pointer.js +107 -0
  222. data/{vendor/assets/Leaflet → lib/leaflet}/src/dom/DomEvent.js +70 -59
  223. data/lib/leaflet/src/dom/DomUtil.js +213 -0
  224. data/{vendor/assets/Leaflet → lib/leaflet}/src/dom/Draggable.js +10 -19
  225. data/{vendor/assets/Leaflet → lib/leaflet}/src/dom/PosAnimation.Timer.js +0 -0
  226. data/{vendor/assets/Leaflet → lib/leaflet}/src/dom/PosAnimation.js +4 -3
  227. data/lib/leaflet/src/geo/LatLng.js +67 -0
  228. data/{vendor/assets/Leaflet → lib/leaflet}/src/geo/LatLngBounds.js +0 -0
  229. data/lib/leaflet/src/geo/crs/CRS.EPSG3395.js +13 -0
  230. data/lib/leaflet/src/geo/crs/CRS.EPSG3857.js +17 -0
  231. data/{vendor/assets/Leaflet → lib/leaflet}/src/geo/crs/CRS.EPSG4326.js +2 -3
  232. data/lib/leaflet/src/geo/crs/CRS.Earth.js +19 -0
  233. data/{vendor/assets/Leaflet → lib/leaflet}/src/geo/crs/CRS.Simple.js +10 -1
  234. data/lib/leaflet/src/geo/crs/CRS.js +63 -0
  235. data/{vendor/assets/Leaflet → lib/leaflet}/src/geo/projection/Projection.LonLat.js +5 -1
  236. data/lib/leaflet/src/geo/projection/Projection.Mercator.js +43 -0
  237. data/lib/leaflet/src/geo/projection/Projection.SphericalMercator.js +31 -0
  238. data/{vendor/assets/Leaflet → lib/leaflet}/src/geometry/Bounds.js +0 -0
  239. data/{vendor/assets/Leaflet → lib/leaflet}/src/geometry/LineUtil.js +16 -5
  240. data/{vendor/assets/Leaflet → lib/leaflet}/src/geometry/Point.js +10 -0
  241. data/{vendor/assets/Leaflet → lib/leaflet}/src/geometry/PolyUtil.js +0 -0
  242. data/{vendor/assets/Leaflet → lib/leaflet}/src/geometry/Transformation.js +0 -0
  243. data/{vendor/assets/Leaflet → lib/leaflet}/src/images/layers.svg +0 -0
  244. data/lib/leaflet/src/images/logo.svg +85 -0
  245. data/{vendor/assets/Leaflet → lib/leaflet}/src/images/marker.svg +0 -0
  246. data/{vendor/assets/Leaflet → lib/leaflet}/src/layer/FeatureGroup.js +3 -20
  247. data/lib/leaflet/src/layer/GeoJSON.js +275 -0
  248. data/lib/leaflet/src/layer/ImageOverlay.js +123 -0
  249. data/lib/leaflet/src/layer/Layer.Popup.js +87 -0
  250. data/lib/leaflet/src/layer/Layer.js +150 -0
  251. data/{vendor/assets/Leaflet → lib/leaflet}/src/layer/LayerGroup.js +12 -14
  252. data/{vendor/assets/Leaflet → lib/leaflet}/src/layer/Popup.js +65 -83
  253. data/{vendor/assets/Leaflet → lib/leaflet}/src/layer/marker/DivIcon.js +3 -8
  254. data/{vendor/assets/Leaflet → lib/leaflet}/src/layer/marker/Icon.Default.js +6 -12
  255. data/{vendor/assets/Leaflet → lib/leaflet}/src/layer/marker/Icon.js +8 -25
  256. data/{vendor/assets/Leaflet → lib/leaflet}/src/layer/marker/Marker.Drag.js +13 -11
  257. data/lib/leaflet/src/layer/marker/Marker.Popup.js +16 -0
  258. data/{vendor/assets/Leaflet → lib/leaflet}/src/layer/marker/Marker.js +52 -103
  259. data/lib/leaflet/src/layer/tile/GridLayer.js +536 -0
  260. data/lib/leaflet/src/layer/tile/TileLayer.WMS.js +79 -0
  261. data/lib/leaflet/src/layer/tile/TileLayer.js +148 -0
  262. data/lib/leaflet/src/layer/vector/Canvas.js +292 -0
  263. data/lib/leaflet/src/layer/vector/Circle.js +67 -0
  264. data/lib/leaflet/src/layer/vector/CircleMarker.js +72 -0
  265. data/lib/leaflet/src/layer/vector/Path.js +79 -0
  266. data/lib/leaflet/src/layer/vector/Polygon.js +75 -0
  267. data/lib/leaflet/src/layer/vector/Polyline.js +223 -0
  268. data/{vendor/assets/Leaflet → lib/leaflet}/src/layer/vector/Rectangle.js +27 -27
  269. data/lib/leaflet/src/layer/vector/Renderer.js +75 -0
  270. data/lib/leaflet/src/layer/vector/SVG.VML.js +134 -0
  271. data/lib/leaflet/src/layer/vector/SVG.js +189 -0
  272. data/{vendor/assets/Leaflet → lib/leaflet}/src/map/Map.js +83 -199
  273. data/{vendor/assets/Leaflet → lib/leaflet}/src/map/anim/Map.PanAnimation.js +0 -0
  274. data/{vendor/assets/Leaflet → lib/leaflet}/src/map/anim/Map.ZoomAnimation.js +30 -38
  275. data/{vendor/assets/Leaflet → lib/leaflet}/src/map/ext/Map.Geolocation.js +8 -8
  276. data/lib/leaflet/src/map/handler/Map.BoxZoom.js +105 -0
  277. data/{vendor/assets/Leaflet → lib/leaflet}/src/map/handler/Map.DoubleClickZoom.js +0 -0
  278. data/{vendor/assets/Leaflet → lib/leaflet}/src/map/handler/Map.Drag.js +12 -10
  279. data/{vendor/assets/Leaflet → lib/leaflet}/src/map/handler/Map.Keyboard.js +19 -17
  280. data/{vendor/assets/Leaflet → lib/leaflet}/src/map/handler/Map.ScrollWheelZoom.js +10 -6
  281. data/{vendor/assets/Leaflet → lib/leaflet}/src/map/handler/Map.Tap.js +8 -6
  282. data/{vendor/assets/Leaflet → lib/leaflet}/src/map/handler/Map.TouchZoom.js +16 -32
  283. data/vendor/assets/images/layers-2x.png +0 -0
  284. data/vendor/assets/images/layers.png +0 -0
  285. data/vendor/assets/images/marker-icon-2x.png +0 -0
  286. data/vendor/assets/images/marker-icon.png +0 -0
  287. data/vendor/assets/images/marker-shadow.png +0 -0
  288. data/vendor/assets/images/spritesheet-2x.png +0 -0
  289. data/vendor/assets/images/spritesheet.png +0 -0
  290. data/vendor/assets/{leaflet-js.js → javascripts/leaflet-js.js} +2 -2
  291. data/vendor/assets/javascripts/leaflet.draw.js +37 -0
  292. data/vendor/assets/javascripts/leaflet.js +149 -0
  293. data/vendor/assets/javascripts/leaflet.label.js +11 -0
  294. data/vendor/assets/{leaflet-js.css → stylesheets/leaflet-js.css} +0 -0
  295. data/vendor/assets/stylesheets/leaflet.css.erb +478 -0
  296. data/vendor/assets/{leaflet.draw.css.erb → stylesheets/leaflet.draw.css.erb} +2 -2
  297. data/vendor/assets/{leaflet.draw.ie.css → stylesheets/leaflet.draw.ie.css} +0 -0
  298. data/vendor/assets/stylesheets/leaflet.label.css +52 -0
  299. metadata +298 -137
  300. data/lib/leaflet-js/engine.rb +0 -7
  301. data/lib/leaflet-js/version.rb +0 -3
  302. data/vendor/assets/Leaflet.draw/src/edit/handler/Edit.Marker.js +0 -75
  303. data/vendor/assets/Leaflet/src/control/Control.Scale.js +0 -112
  304. data/vendor/assets/Leaflet/src/copyright.js +0 -5
  305. data/vendor/assets/Leaflet/src/core/Browser.js +0 -66
  306. data/vendor/assets/Leaflet/src/core/Events.js +0 -178
  307. data/vendor/assets/Leaflet/src/core/Util.js +0 -182
  308. data/vendor/assets/Leaflet/src/dom/DomEvent.Pointer.js +0 -156
  309. data/vendor/assets/Leaflet/src/dom/DomUtil.js +0 -289
  310. data/vendor/assets/Leaflet/src/geo/LatLng.js +0 -99
  311. data/vendor/assets/Leaflet/src/geo/crs/CRS.EPSG3395.js +0 -14
  312. data/vendor/assets/Leaflet/src/geo/crs/CRS.EPSG3857.js +0 -21
  313. data/vendor/assets/Leaflet/src/geo/crs/CRS.js +0 -32
  314. data/vendor/assets/Leaflet/src/geo/projection/Projection.Mercator.js +0 -56
  315. data/vendor/assets/Leaflet/src/geo/projection/Projection.SphericalMercator.js +0 -27
  316. data/vendor/assets/Leaflet/src/geo/projection/Projection.js +0 -5
  317. data/vendor/assets/Leaflet/src/layer/GeoJSON.js +0 -286
  318. data/vendor/assets/Leaflet/src/layer/ImageOverlay.js +0 -141
  319. data/vendor/assets/Leaflet/src/layer/marker/Marker.Popup.js +0 -90
  320. data/vendor/assets/Leaflet/src/layer/tile/TileLayer.Anim.js +0 -110
  321. data/vendor/assets/Leaflet/src/layer/tile/TileLayer.Canvas.js +0 -61
  322. data/vendor/assets/Leaflet/src/layer/tile/TileLayer.WMS.js +0 -87
  323. data/vendor/assets/Leaflet/src/layer/tile/TileLayer.js +0 -597
  324. data/vendor/assets/Leaflet/src/layer/vector/Circle.js +0 -98
  325. data/vendor/assets/Leaflet/src/layer/vector/CircleMarker.js +0 -45
  326. data/vendor/assets/Leaflet/src/layer/vector/MultiPoly.js +0 -57
  327. data/vendor/assets/Leaflet/src/layer/vector/Path.Popup.js +0 -65
  328. data/vendor/assets/Leaflet/src/layer/vector/Path.SVG.js +0 -230
  329. data/vendor/assets/Leaflet/src/layer/vector/Path.VML.js +0 -135
  330. data/vendor/assets/Leaflet/src/layer/vector/Path.js +0 -119
  331. data/vendor/assets/Leaflet/src/layer/vector/Polygon.js +0 -92
  332. data/vendor/assets/Leaflet/src/layer/vector/Polyline.js +0 -164
  333. data/vendor/assets/Leaflet/src/layer/vector/canvas/Circle.Canvas.js +0 -18
  334. data/vendor/assets/Leaflet/src/layer/vector/canvas/CircleMarker.Canvas.js +0 -9
  335. data/vendor/assets/Leaflet/src/layer/vector/canvas/Path.Canvas.js +0 -204
  336. data/vendor/assets/Leaflet/src/layer/vector/canvas/Polygon.Canvas.js +0 -37
  337. data/vendor/assets/Leaflet/src/layer/vector/canvas/Polyline.Canvas.js +0 -30
  338. data/vendor/assets/Leaflet/src/map/handler/Map.BoxZoom.js +0 -118
  339. data/vendor/assets/leaflet.draw.js +0 -38
  340. data/vendor/assets/leaflet.js +0 -155
  341. data/vendor/assets/leaflet.label.js +0 -11
@@ -0,0 +1,76 @@
1
+ var deps = {
2
+ Core: {
3
+ src: [
4
+ 'Leaflet.draw.js'
5
+ ],
6
+ desc: 'The core of the plugin. Currently only includes the version.'
7
+ },
8
+
9
+ DrawHandlers: {
10
+ src: [
11
+ 'draw/handler/Draw.Feature.js',
12
+ 'draw/handler/Draw.Polyline.js',
13
+ 'draw/handler/Draw.Polygon.js',
14
+ 'draw/handler/Draw.SimpleShape.js',
15
+ 'draw/handler/Draw.Rectangle.js',
16
+ 'draw/handler/Draw.Circle.js',
17
+ 'draw/handler/Draw.Marker.js'
18
+ ],
19
+ desc: 'Drawing handlers for: polylines, polygons, rectangles, circles and markers.',
20
+ deps: ['Core']
21
+ },
22
+
23
+ EditHandlers: {
24
+ src: [
25
+ 'edit/handler/Edit.Poly.js',
26
+ 'edit/handler/Edit.SimpleShape.js',
27
+ 'edit/handler/Edit.Rectangle.js',
28
+ 'edit/handler/Edit.Circle.js'
29
+ ],
30
+ desc: 'Editing handlers for: polylines, polygons, rectangles, and circles.',
31
+ deps: ['Core']
32
+ },
33
+
34
+ Extensions: {
35
+ src: [
36
+ 'ext/LatLngUtil.js',
37
+ 'ext/GeometryUtil.js',
38
+ 'ext/LineUtil.Intersect.js',
39
+ 'ext/Polyline.Intersect.js',
40
+ 'ext/Polygon.Intersect.js'
41
+ ],
42
+ desc: 'Extensions of leaflet classes.'
43
+ },
44
+
45
+ CommonUI: {
46
+ src: [
47
+ 'Control.Draw.js',
48
+ 'Toolbar.js',
49
+ 'Tooltip.js'
50
+ ],
51
+ desc: 'Common UI components used.',
52
+ deps: ['Extensions']
53
+ },
54
+
55
+ DrawUI: {
56
+ src: [
57
+ 'draw/DrawToolbar.js'
58
+ ],
59
+ desc: 'Draw toolbar.',
60
+ deps: ['DrawHandlers', 'CommonUI']
61
+ },
62
+
63
+ EditUI: {
64
+ src: [
65
+ 'edit/EditToolbar.js',
66
+ 'edit/handler/EditToolbar.Edit.js',
67
+ 'edit/handler/EditToolbar.Delete.js'
68
+ ],
69
+ desc: 'Edit toolbar.',
70
+ deps: ['EditHandlers', 'CommonUI']
71
+ }
72
+ };
73
+
74
+ if (typeof exports !== 'undefined') {
75
+ exports.deps = deps;
76
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ // environment
3
+ "browser": true,
4
+ "node": true,
5
+ "globals": {
6
+ "L": true,
7
+ "define": true
8
+ },
9
+ "strict": false,
10
+
11
+ // code style
12
+ "bitwise": true,
13
+ "camelcase": true,
14
+ "curly": true,
15
+ "eqeqeq": true,
16
+ "forin": false,
17
+ "immed": true,
18
+ "latedef": true,
19
+ "newcap": true,
20
+ "noarg": true,
21
+ "noempty": true,
22
+ "nonew": true,
23
+ "undef": true,
24
+ "unused": true,
25
+ "quotmark": "single",
26
+
27
+ // whitespace
28
+ "indent": 4,
29
+ "trailing": true,
30
+ "white": true,
31
+ "smarttabs": true,
32
+ "maxlen": 150
33
+
34
+ // code simplicity - not enforced but nice to check from time to time
35
+ // "maxstatements": 20,
36
+ // "maxcomplexity": 5
37
+ // "maxparams": 4,
38
+ // "maxdepth": 4
39
+ }
@@ -0,0 +1,42 @@
1
+ (function() {
2
+ function getFiles() {
3
+ var memo = {},
4
+ files = [],
5
+ i, src;
6
+
7
+ function addFiles(srcs) {
8
+ for (var j = 0, len = srcs.length; j < len; j++) {
9
+ memo[srcs[j]] = true;
10
+ }
11
+ }
12
+
13
+ for (i in deps) {
14
+ addFiles(deps[i].src);
15
+ }
16
+
17
+ for (src in memo) {
18
+ files.push(src);
19
+ }
20
+
21
+ return files;
22
+ }
23
+ var scripts = getFiles();
24
+
25
+ function getSrcUrl() {
26
+ var scripts = document.getElementsByTagName('script');
27
+ for (var i = 0; i < scripts.length; i++) {
28
+ var src = scripts[i].src;
29
+ if (src) {
30
+ var res = src.match(/^(.*)leaflet.draw-include\.js$/);
31
+ if (res) {
32
+ return res[1] + '../src/';
33
+ }
34
+ }
35
+ }
36
+ }
37
+
38
+ var path = getSrcUrl();
39
+ for (var i = 0; i < scripts.length; i++) {
40
+ document.writeln("<script src='" + path + scripts[i] + "'></script>");
41
+ }
42
+ })();
@@ -0,0 +1,2872 @@
1
+ /*
2
+ Leaflet.draw, a plugin that adds drawing and editing tools to Leaflet powered maps.
3
+ (c) 2012-2013, Jacob Toye, Smartrak
4
+
5
+ https://github.com/Leaflet/Leaflet.draw
6
+ http://leafletjs.com
7
+ https://github.com/jacobtoye
8
+ */
9
+ (function (window, document, undefined) {/*
10
+ * Leaflet.draw assumes that you have already included the Leaflet library.
11
+ */
12
+
13
+ L.drawVersion = '0.2.4-dev';
14
+
15
+ L.drawLocal = {
16
+ draw: {
17
+ toolbar: {
18
+ actions: {
19
+ title: 'Cancel drawing',
20
+ text: 'Cancel'
21
+ },
22
+ undo: {
23
+ title: 'Delete last point drawn',
24
+ text: 'Delete last point'
25
+ },
26
+ buttons: {
27
+ polyline: 'Draw a polyline',
28
+ polygon: 'Draw a polygon',
29
+ rectangle: 'Draw a rectangle',
30
+ circle: 'Draw a circle',
31
+ marker: 'Draw a marker'
32
+ }
33
+ },
34
+ handlers: {
35
+ circle: {
36
+ tooltip: {
37
+ start: 'Click and drag to draw circle.'
38
+ }
39
+ },
40
+ marker: {
41
+ tooltip: {
42
+ start: 'Click map to place marker.'
43
+ }
44
+ },
45
+ polygon: {
46
+ tooltip: {
47
+ start: 'Click to start drawing shape.',
48
+ cont: 'Click to continue drawing shape.',
49
+ end: 'Click first point to close this shape.'
50
+ }
51
+ },
52
+ polyline: {
53
+ error: '<strong>Error:</strong> shape edges cannot cross!',
54
+ tooltip: {
55
+ start: 'Click to start drawing line.',
56
+ cont: 'Click to continue drawing line.',
57
+ end: 'Click last point to finish line.'
58
+ }
59
+ },
60
+ rectangle: {
61
+ tooltip: {
62
+ start: 'Click and drag to draw rectangle.'
63
+ }
64
+ },
65
+ simpleshape: {
66
+ tooltip: {
67
+ end: 'Release mouse to finish drawing.'
68
+ }
69
+ }
70
+ }
71
+ },
72
+ edit: {
73
+ toolbar: {
74
+ actions: {
75
+ save: {
76
+ title: 'Save changes.',
77
+ text: 'Save'
78
+ },
79
+ cancel: {
80
+ title: 'Cancel editing, discards all changes.',
81
+ text: 'Cancel'
82
+ }
83
+ },
84
+ buttons: {
85
+ edit: 'Edit layers.',
86
+ editDisabled: 'No layers to edit.',
87
+ remove: 'Delete layers.',
88
+ removeDisabled: 'No layers to delete.'
89
+ }
90
+ },
91
+ handlers: {
92
+ edit: {
93
+ tooltip: {
94
+ text: 'Drag handles, or marker to edit feature.',
95
+ subtext: 'Click cancel to undo changes.'
96
+ }
97
+ },
98
+ remove: {
99
+ tooltip: {
100
+ text: 'Click on a feature to remove'
101
+ }
102
+ }
103
+ }
104
+ }
105
+ };
106
+
107
+
108
+ L.Draw = {};
109
+
110
+ L.Draw.Feature = L.Handler.extend({
111
+ includes: L.Mixin.Events,
112
+
113
+ initialize: function (map, options) {
114
+ this._map = map;
115
+ this._container = map._container;
116
+ this._overlayPane = map._panes.overlayPane;
117
+ this._popupPane = map._panes.popupPane;
118
+
119
+ // Merge default shapeOptions options with custom shapeOptions
120
+ if (options && options.shapeOptions) {
121
+ options.shapeOptions = L.Util.extend({}, this.options.shapeOptions, options.shapeOptions);
122
+ }
123
+ L.setOptions(this, options);
124
+ },
125
+
126
+ enable: function () {
127
+ if (this._enabled) { return; }
128
+
129
+ this.fire('enabled', { handler: this.type });
130
+
131
+ this._map.fire('draw:drawstart', { layerType: this.type });
132
+
133
+ L.Handler.prototype.enable.call(this);
134
+ },
135
+
136
+ disable: function () {
137
+ if (!this._enabled) { return; }
138
+
139
+ L.Handler.prototype.disable.call(this);
140
+
141
+ this._map.fire('draw:drawstop', { layerType: this.type });
142
+
143
+ this.fire('disabled', { handler: this.type });
144
+ },
145
+
146
+ addHooks: function () {
147
+ var map = this._map;
148
+
149
+ if (map) {
150
+ L.DomUtil.disableTextSelection();
151
+
152
+ map.getContainer().focus();
153
+
154
+ this._tooltip = new L.Tooltip(this._map);
155
+
156
+ L.DomEvent.on(this._container, 'keyup', this._cancelDrawing, this);
157
+ }
158
+ },
159
+
160
+ removeHooks: function () {
161
+ if (this._map) {
162
+ L.DomUtil.enableTextSelection();
163
+
164
+ this._tooltip.dispose();
165
+ this._tooltip = null;
166
+
167
+ L.DomEvent.off(this._container, 'keyup', this._cancelDrawing, this);
168
+ }
169
+ },
170
+
171
+ setOptions: function (options) {
172
+ L.setOptions(this, options);
173
+ },
174
+
175
+ _fireCreatedEvent: function (layer) {
176
+ this._map.fire('draw:created', { layer: layer, layerType: this.type });
177
+ },
178
+
179
+ // Cancel drawing when the escape key is pressed
180
+ _cancelDrawing: function (e) {
181
+ if (e.keyCode === 27) {
182
+ this.disable();
183
+ }
184
+ }
185
+ });
186
+
187
+ L.Draw.Polyline = L.Draw.Feature.extend({
188
+ statics: {
189
+ TYPE: 'polyline'
190
+ },
191
+
192
+ Poly: L.Polyline,
193
+
194
+ options: {
195
+ allowIntersection: true,
196
+ repeatMode: false,
197
+ drawError: {
198
+ color: '#b00b00',
199
+ timeout: 2500
200
+ },
201
+ icon: new L.DivIcon({
202
+ iconSize: new L.Point(8, 8),
203
+ className: 'leaflet-div-icon leaflet-editing-icon'
204
+ }),
205
+ guidelineDistance: 20,
206
+ maxGuideLineLength: 4000,
207
+ shapeOptions: {
208
+ stroke: true,
209
+ color: '#f06eaa',
210
+ weight: 4,
211
+ opacity: 0.5,
212
+ fill: false,
213
+ clickable: true
214
+ },
215
+ metric: true, // Whether to use the metric meaurement system or imperial
216
+ showLength: true, // Whether to display distance in the tooltip
217
+ zIndexOffset: 2000 // This should be > than the highest z-index any map layers
218
+ },
219
+
220
+ initialize: function (map, options) {
221
+ // Need to set this here to ensure the correct message is used.
222
+ this.options.drawError.message = L.drawLocal.draw.handlers.polyline.error;
223
+
224
+ // Merge default drawError options with custom options
225
+ if (options && options.drawError) {
226
+ options.drawError = L.Util.extend({}, this.options.drawError, options.drawError);
227
+ }
228
+
229
+ // Save the type so super can fire, need to do this as cannot do this.TYPE :(
230
+ this.type = L.Draw.Polyline.TYPE;
231
+
232
+ L.Draw.Feature.prototype.initialize.call(this, map, options);
233
+ },
234
+
235
+ addHooks: function () {
236
+ L.Draw.Feature.prototype.addHooks.call(this);
237
+ if (this._map) {
238
+ this._markers = [];
239
+
240
+ this._markerGroup = new L.LayerGroup();
241
+ this._map.addLayer(this._markerGroup);
242
+
243
+ this._poly = new L.Polyline([], this.options.shapeOptions);
244
+
245
+ this._tooltip.updateContent(this._getTooltipText());
246
+
247
+ // Make a transparent marker that will used to catch click events. These click
248
+ // events will create the vertices. We need to do this so we can ensure that
249
+ // we can create vertices over other map layers (markers, vector layers). We
250
+ // also do not want to trigger any click handlers of objects we are clicking on
251
+ // while drawing.
252
+ if (!this._mouseMarker) {
253
+ this._mouseMarker = L.marker(this._map.getCenter(), {
254
+ icon: L.divIcon({
255
+ className: 'leaflet-mouse-marker',
256
+ iconAnchor: [20, 20],
257
+ iconSize: [40, 40]
258
+ }),
259
+ opacity: 0,
260
+ zIndexOffset: this.options.zIndexOffset
261
+ });
262
+ }
263
+
264
+ this._mouseMarker
265
+ .on('mousedown', this._onMouseDown, this)
266
+ .addTo(this._map);
267
+
268
+ this._map
269
+ .on('mousemove', this._onMouseMove, this)
270
+ .on('mouseup', this._onMouseUp, this)
271
+ .on('zoomend', this._onZoomEnd, this);
272
+ }
273
+ },
274
+
275
+ removeHooks: function () {
276
+ L.Draw.Feature.prototype.removeHooks.call(this);
277
+
278
+ this._clearHideErrorTimeout();
279
+
280
+ this._cleanUpShape();
281
+
282
+ // remove markers from map
283
+ this._map.removeLayer(this._markerGroup);
284
+ delete this._markerGroup;
285
+ delete this._markers;
286
+
287
+ this._map.removeLayer(this._poly);
288
+ delete this._poly;
289
+
290
+ this._mouseMarker
291
+ .off('mousedown', this._onMouseDown, this)
292
+ .off('mouseup', this._onMouseUp, this);
293
+ this._map.removeLayer(this._mouseMarker);
294
+ delete this._mouseMarker;
295
+
296
+ // clean up DOM
297
+ this._clearGuides();
298
+
299
+ this._map
300
+ .off('mousemove', this._onMouseMove, this)
301
+ .off('zoomend', this._onZoomEnd, this);
302
+ },
303
+
304
+ deleteLastVertex: function () {
305
+ if (this._markers.length <= 1) {
306
+ return;
307
+ }
308
+
309
+ var lastMarker = this._markers.pop(),
310
+ poly = this._poly,
311
+ latlng = this._poly.spliceLatLngs(poly.getLatLngs().length - 1, 1)[0];
312
+
313
+ this._markerGroup.removeLayer(lastMarker);
314
+
315
+ if (poly.getLatLngs().length < 2) {
316
+ this._map.removeLayer(poly);
317
+ }
318
+
319
+ this._vertexChanged(latlng, false);
320
+ },
321
+
322
+ addVertex: function (latlng) {
323
+ var markersLength = this._markers.length;
324
+
325
+ if (markersLength > 0 && !this.options.allowIntersection && this._poly.newLatLngIntersects(latlng)) {
326
+ this._showErrorTooltip();
327
+ return;
328
+ }
329
+ else if (this._errorShown) {
330
+ this._hideErrorTooltip();
331
+ }
332
+
333
+ this._markers.push(this._createMarker(latlng));
334
+
335
+ this._poly.addLatLng(latlng);
336
+
337
+ if (this._poly.getLatLngs().length === 2) {
338
+ this._map.addLayer(this._poly);
339
+ }
340
+
341
+ this._vertexChanged(latlng, true);
342
+ },
343
+
344
+ _finishShape: function () {
345
+ var intersects = this._poly.newLatLngIntersects(this._poly.getLatLngs()[0], true);
346
+
347
+ if ((!this.options.allowIntersection && intersects) || !this._shapeIsValid()) {
348
+ this._showErrorTooltip();
349
+ return;
350
+ }
351
+
352
+ this._fireCreatedEvent();
353
+ this.disable();
354
+ if (this.options.repeatMode) {
355
+ this.enable();
356
+ }
357
+ },
358
+
359
+ //Called to verify the shape is valid when the user tries to finish it
360
+ //Return false if the shape is not valid
361
+ _shapeIsValid: function () {
362
+ return true;
363
+ },
364
+
365
+ _onZoomEnd: function () {
366
+ this._updateGuide();
367
+ },
368
+
369
+ _onMouseMove: function (e) {
370
+ var newPos = e.layerPoint,
371
+ latlng = e.latlng;
372
+
373
+ // Save latlng
374
+ // should this be moved to _updateGuide() ?
375
+ this._currentLatLng = latlng;
376
+
377
+ this._updateTooltip(latlng);
378
+
379
+ // Update the guide line
380
+ this._updateGuide(newPos);
381
+
382
+ // Update the mouse marker position
383
+ this._mouseMarker.setLatLng(latlng);
384
+
385
+ L.DomEvent.preventDefault(e.originalEvent);
386
+ },
387
+
388
+ _vertexChanged: function (latlng, added) {
389
+ this._updateFinishHandler();
390
+
391
+ this._updateRunningMeasure(latlng, added);
392
+
393
+ this._clearGuides();
394
+
395
+ this._updateTooltip();
396
+ },
397
+
398
+ _onMouseDown: function (e) {
399
+ var originalEvent = e.originalEvent;
400
+ this._mouseDownOrigin = L.point(originalEvent.clientX, originalEvent.clientY);
401
+ },
402
+
403
+ _onMouseUp: function (e) {
404
+ if (this._mouseDownOrigin) {
405
+ // We detect clicks within a certain tolerance, otherwise let it
406
+ // be interpreted as a drag by the map
407
+ var distance = L.point(e.originalEvent.clientX, e.originalEvent.clientY)
408
+ .distanceTo(this._mouseDownOrigin);
409
+ if (Math.abs(distance) < 9 * (window.devicePixelRatio || 1)) {
410
+ this.addVertex(e.latlng);
411
+ }
412
+ }
413
+ this._mouseDownOrigin = null;
414
+ },
415
+
416
+ _updateFinishHandler: function () {
417
+ var markerCount = this._markers.length;
418
+ // The last marker should have a click handler to close the polyline
419
+ if (markerCount > 1) {
420
+ this._markers[markerCount - 1].on('click', this._finishShape, this);
421
+ }
422
+
423
+ // Remove the old marker click handler (as only the last point should close the polyline)
424
+ if (markerCount > 2) {
425
+ this._markers[markerCount - 2].off('click', this._finishShape, this);
426
+ }
427
+ },
428
+
429
+ _createMarker: function (latlng) {
430
+ var marker = new L.Marker(latlng, {
431
+ icon: this.options.icon,
432
+ zIndexOffset: this.options.zIndexOffset * 2
433
+ });
434
+
435
+ this._markerGroup.addLayer(marker);
436
+
437
+ return marker;
438
+ },
439
+
440
+ _updateGuide: function (newPos) {
441
+ var markerCount = this._markers.length;
442
+
443
+ if (markerCount > 0) {
444
+ newPos = newPos || this._map.latLngToLayerPoint(this._currentLatLng);
445
+
446
+ // draw the guide line
447
+ this._clearGuides();
448
+ this._drawGuide(
449
+ this._map.latLngToLayerPoint(this._markers[markerCount - 1].getLatLng()),
450
+ newPos
451
+ );
452
+ }
453
+ },
454
+
455
+ _updateTooltip: function (latLng) {
456
+ var text = this._getTooltipText();
457
+
458
+ if (latLng) {
459
+ this._tooltip.updatePosition(latLng);
460
+ }
461
+
462
+ if (!this._errorShown) {
463
+ this._tooltip.updateContent(text);
464
+ }
465
+ },
466
+
467
+ _drawGuide: function (pointA, pointB) {
468
+ var length = Math.floor(Math.sqrt(Math.pow((pointB.x - pointA.x), 2) + Math.pow((pointB.y - pointA.y), 2))),
469
+ guidelineDistance = this.options.guidelineDistance,
470
+ maxGuideLineLength = this.options.maxGuideLineLength,
471
+ // Only draw a guideline with a max length
472
+ i = length > maxGuideLineLength ? length - maxGuideLineLength : guidelineDistance,
473
+ fraction,
474
+ dashPoint,
475
+ dash;
476
+
477
+ //create the guides container if we haven't yet
478
+ if (!this._guidesContainer) {
479
+ this._guidesContainer = L.DomUtil.create('div', 'leaflet-draw-guides', this._overlayPane);
480
+ }
481
+
482
+ //draw a dash every GuildeLineDistance
483
+ for (; i < length; i += this.options.guidelineDistance) {
484
+ //work out fraction along line we are
485
+ fraction = i / length;
486
+
487
+ //calculate new x,y point
488
+ dashPoint = {
489
+ x: Math.floor((pointA.x * (1 - fraction)) + (fraction * pointB.x)),
490
+ y: Math.floor((pointA.y * (1 - fraction)) + (fraction * pointB.y))
491
+ };
492
+
493
+ //add guide dash to guide container
494
+ dash = L.DomUtil.create('div', 'leaflet-draw-guide-dash', this._guidesContainer);
495
+ dash.style.backgroundColor =
496
+ !this._errorShown ? this.options.shapeOptions.color : this.options.drawError.color;
497
+
498
+ L.DomUtil.setPosition(dash, dashPoint);
499
+ }
500
+ },
501
+
502
+ _updateGuideColor: function (color) {
503
+ if (this._guidesContainer) {
504
+ for (var i = 0, l = this._guidesContainer.childNodes.length; i < l; i++) {
505
+ this._guidesContainer.childNodes[i].style.backgroundColor = color;
506
+ }
507
+ }
508
+ },
509
+
510
+ // removes all child elements (guide dashes) from the guides container
511
+ _clearGuides: function () {
512
+ if (this._guidesContainer) {
513
+ while (this._guidesContainer.firstChild) {
514
+ this._guidesContainer.removeChild(this._guidesContainer.firstChild);
515
+ }
516
+ }
517
+ },
518
+
519
+ _getTooltipText: function () {
520
+ var showLength = this.options.showLength,
521
+ labelText, distanceStr;
522
+
523
+ if (this._markers.length === 0) {
524
+ labelText = {
525
+ text: L.drawLocal.draw.handlers.polyline.tooltip.start
526
+ };
527
+ } else {
528
+ distanceStr = showLength ? this._getMeasurementString() : '';
529
+
530
+ if (this._markers.length === 1) {
531
+ labelText = {
532
+ text: L.drawLocal.draw.handlers.polyline.tooltip.cont,
533
+ subtext: distanceStr
534
+ };
535
+ } else {
536
+ labelText = {
537
+ text: L.drawLocal.draw.handlers.polyline.tooltip.end,
538
+ subtext: distanceStr
539
+ };
540
+ }
541
+ }
542
+ return labelText;
543
+ },
544
+
545
+ _updateRunningMeasure: function (latlng, added) {
546
+ var markersLength = this._markers.length,
547
+ previousMarkerIndex, distance;
548
+
549
+ if (this._markers.length === 1) {
550
+ this._measurementRunningTotal = 0;
551
+ } else {
552
+ previousMarkerIndex = markersLength - (added ? 2 : 1);
553
+ distance = latlng.distanceTo(this._markers[previousMarkerIndex].getLatLng());
554
+
555
+ this._measurementRunningTotal += distance * (added ? 1 : -1);
556
+ }
557
+ },
558
+
559
+ _getMeasurementString: function () {
560
+ var currentLatLng = this._currentLatLng,
561
+ previousLatLng = this._markers[this._markers.length - 1].getLatLng(),
562
+ distance;
563
+
564
+ // calculate the distance from the last fixed point to the mouse position
565
+ distance = this._measurementRunningTotal + currentLatLng.distanceTo(previousLatLng);
566
+
567
+ return L.GeometryUtil.readableDistance(distance, this.options.metric);
568
+ },
569
+
570
+ _showErrorTooltip: function () {
571
+ this._errorShown = true;
572
+
573
+ // Update tooltip
574
+ this._tooltip
575
+ .showAsError()
576
+ .updateContent({ text: this.options.drawError.message });
577
+
578
+ // Update shape
579
+ this._updateGuideColor(this.options.drawError.color);
580
+ this._poly.setStyle({ color: this.options.drawError.color });
581
+
582
+ // Hide the error after 2 seconds
583
+ this._clearHideErrorTimeout();
584
+ this._hideErrorTimeout = setTimeout(L.Util.bind(this._hideErrorTooltip, this), this.options.drawError.timeout);
585
+ },
586
+
587
+ _hideErrorTooltip: function () {
588
+ this._errorShown = false;
589
+
590
+ this._clearHideErrorTimeout();
591
+
592
+ // Revert tooltip
593
+ this._tooltip
594
+ .removeError()
595
+ .updateContent(this._getTooltipText());
596
+
597
+ // Revert shape
598
+ this._updateGuideColor(this.options.shapeOptions.color);
599
+ this._poly.setStyle({ color: this.options.shapeOptions.color });
600
+ },
601
+
602
+ _clearHideErrorTimeout: function () {
603
+ if (this._hideErrorTimeout) {
604
+ clearTimeout(this._hideErrorTimeout);
605
+ this._hideErrorTimeout = null;
606
+ }
607
+ },
608
+
609
+ _cleanUpShape: function () {
610
+ if (this._markers.length > 1) {
611
+ this._markers[this._markers.length - 1].off('click', this._finishShape, this);
612
+ }
613
+ },
614
+
615
+ _fireCreatedEvent: function () {
616
+ var poly = new this.Poly(this._poly.getLatLngs(), this.options.shapeOptions);
617
+ L.Draw.Feature.prototype._fireCreatedEvent.call(this, poly);
618
+ }
619
+ });
620
+
621
+
622
+ L.Draw.Polygon = L.Draw.Polyline.extend({
623
+ statics: {
624
+ TYPE: 'polygon'
625
+ },
626
+
627
+ Poly: L.Polygon,
628
+
629
+ options: {
630
+ showArea: false,
631
+ shapeOptions: {
632
+ stroke: true,
633
+ color: '#f06eaa',
634
+ weight: 4,
635
+ opacity: 0.5,
636
+ fill: true,
637
+ fillColor: null, //same as color by default
638
+ fillOpacity: 0.2,
639
+ clickable: true
640
+ }
641
+ },
642
+
643
+ initialize: function (map, options) {
644
+ L.Draw.Polyline.prototype.initialize.call(this, map, options);
645
+
646
+ // Save the type so super can fire, need to do this as cannot do this.TYPE :(
647
+ this.type = L.Draw.Polygon.TYPE;
648
+ },
649
+
650
+ _updateFinishHandler: function () {
651
+ var markerCount = this._markers.length;
652
+
653
+ // The first marker should have a click handler to close the polygon
654
+ if (markerCount === 1) {
655
+ this._markers[0].on('click', this._finishShape, this);
656
+ }
657
+
658
+ // Add and update the double click handler
659
+ if (markerCount > 2) {
660
+ this._markers[markerCount - 1].on('dblclick', this._finishShape, this);
661
+ // Only need to remove handler if has been added before
662
+ if (markerCount > 3) {
663
+ this._markers[markerCount - 2].off('dblclick', this._finishShape, this);
664
+ }
665
+ }
666
+ },
667
+
668
+ _getTooltipText: function () {
669
+ var text, subtext;
670
+
671
+ if (this._markers.length === 0) {
672
+ text = L.drawLocal.draw.handlers.polygon.tooltip.start;
673
+ } else if (this._markers.length < 3) {
674
+ text = L.drawLocal.draw.handlers.polygon.tooltip.cont;
675
+ } else {
676
+ text = L.drawLocal.draw.handlers.polygon.tooltip.end;
677
+ subtext = this._getMeasurementString();
678
+ }
679
+
680
+ return {
681
+ text: text,
682
+ subtext: subtext
683
+ };
684
+ },
685
+
686
+ _getMeasurementString: function () {
687
+ var area = this._area;
688
+
689
+ if (!area) {
690
+ return null;
691
+ }
692
+
693
+ return L.GeometryUtil.readableArea(area, this.options.metric);
694
+ },
695
+
696
+ _shapeIsValid: function () {
697
+ return this._markers.length >= 3;
698
+ },
699
+
700
+ _vertexChanged: function (latlng, added) {
701
+ var latLngs;
702
+
703
+ // Check to see if we should show the area
704
+ if (!this.options.allowIntersection && this.options.showArea) {
705
+ latLngs = this._poly.getLatLngs();
706
+
707
+ this._area = L.GeometryUtil.geodesicArea(latLngs);
708
+ }
709
+
710
+ L.Draw.Polyline.prototype._vertexChanged.call(this, latlng, added);
711
+ },
712
+
713
+ _cleanUpShape: function () {
714
+ var markerCount = this._markers.length;
715
+
716
+ if (markerCount > 0) {
717
+ this._markers[0].off('click', this._finishShape, this);
718
+
719
+ if (markerCount > 2) {
720
+ this._markers[markerCount - 1].off('dblclick', this._finishShape, this);
721
+ }
722
+ }
723
+ }
724
+ });
725
+
726
+
727
+ L.SimpleShape = {};
728
+
729
+ L.Draw.SimpleShape = L.Draw.Feature.extend({
730
+ options: {
731
+ repeatMode: false
732
+ },
733
+
734
+ initialize: function (map, options) {
735
+ this._endLabelText = L.drawLocal.draw.handlers.simpleshape.tooltip.end;
736
+
737
+ L.Draw.Feature.prototype.initialize.call(this, map, options);
738
+ },
739
+
740
+ addHooks: function () {
741
+ L.Draw.Feature.prototype.addHooks.call(this);
742
+ if (this._map) {
743
+ this._mapDraggable = this._map.dragging.enabled();
744
+
745
+ if (this._mapDraggable) {
746
+ this._map.dragging.disable();
747
+ }
748
+
749
+ //TODO refactor: move cursor to styles
750
+ this._container.style.cursor = 'crosshair';
751
+
752
+ this._tooltip.updateContent({ text: this._initialLabelText });
753
+
754
+ this._map
755
+ .on('mousedown', this._onMouseDown, this)
756
+ .on('mousemove', this._onMouseMove, this);
757
+ }
758
+ },
759
+
760
+ removeHooks: function () {
761
+ L.Draw.Feature.prototype.removeHooks.call(this);
762
+ if (this._map) {
763
+ if (this._mapDraggable) {
764
+ this._map.dragging.enable();
765
+ }
766
+
767
+ //TODO refactor: move cursor to styles
768
+ this._container.style.cursor = '';
769
+
770
+ this._map
771
+ .off('mousedown', this._onMouseDown, this)
772
+ .off('mousemove', this._onMouseMove, this);
773
+
774
+ L.DomEvent.off(document, 'mouseup', this._onMouseUp, this);
775
+
776
+ // If the box element doesn't exist they must not have moved the mouse, so don't need to destroy/return
777
+ if (this._shape) {
778
+ this._map.removeLayer(this._shape);
779
+ delete this._shape;
780
+ }
781
+ }
782
+ this._isDrawing = false;
783
+ },
784
+
785
+ _onMouseDown: function (e) {
786
+ this._isDrawing = true;
787
+ this._startLatLng = e.latlng;
788
+
789
+ L.DomEvent
790
+ .on(document, 'mouseup', this._onMouseUp, this)
791
+ .preventDefault(e.originalEvent);
792
+ },
793
+
794
+ _onMouseMove: function (e) {
795
+ var latlng = e.latlng;
796
+
797
+ this._tooltip.updatePosition(latlng);
798
+ if (this._isDrawing) {
799
+ this._tooltip.updateContent({ text: this._endLabelText });
800
+ this._drawShape(latlng);
801
+ }
802
+ },
803
+
804
+ _onMouseUp: function () {
805
+ if (this._shape) {
806
+ this._fireCreatedEvent();
807
+ }
808
+
809
+ this.disable();
810
+ if (this.options.repeatMode) {
811
+ this.enable();
812
+ }
813
+ }
814
+ });
815
+
816
+ L.Draw.Rectangle = L.Draw.SimpleShape.extend({
817
+ statics: {
818
+ TYPE: 'rectangle'
819
+ },
820
+
821
+ options: {
822
+ shapeOptions: {
823
+ stroke: true,
824
+ color: '#f06eaa',
825
+ weight: 4,
826
+ opacity: 0.5,
827
+ fill: true,
828
+ fillColor: null, //same as color by default
829
+ fillOpacity: 0.2,
830
+ clickable: true
831
+ }
832
+ },
833
+
834
+ initialize: function (map, options) {
835
+ // Save the type so super can fire, need to do this as cannot do this.TYPE :(
836
+ this.type = L.Draw.Rectangle.TYPE;
837
+
838
+ this._initialLabelText = L.drawLocal.draw.handlers.rectangle.tooltip.start;
839
+
840
+ L.Draw.SimpleShape.prototype.initialize.call(this, map, options);
841
+ },
842
+
843
+ _drawShape: function (latlng) {
844
+ if (!this._shape) {
845
+ this._shape = new L.Rectangle(new L.LatLngBounds(this._startLatLng, latlng), this.options.shapeOptions);
846
+ this._map.addLayer(this._shape);
847
+ } else {
848
+ this._shape.setBounds(new L.LatLngBounds(this._startLatLng, latlng));
849
+ }
850
+ },
851
+
852
+ _fireCreatedEvent: function () {
853
+ var rectangle = new L.Rectangle(this._shape.getBounds(), this.options.shapeOptions);
854
+ L.Draw.SimpleShape.prototype._fireCreatedEvent.call(this, rectangle);
855
+ }
856
+ });
857
+
858
+
859
+ L.Draw.Circle = L.Draw.SimpleShape.extend({
860
+ statics: {
861
+ TYPE: 'circle'
862
+ },
863
+
864
+ options: {
865
+ shapeOptions: {
866
+ stroke: true,
867
+ color: '#f06eaa',
868
+ weight: 4,
869
+ opacity: 0.5,
870
+ fill: true,
871
+ fillColor: null, //same as color by default
872
+ fillOpacity: 0.2,
873
+ clickable: true
874
+ },
875
+ showRadius: true,
876
+ metric: true // Whether to use the metric meaurement system or imperial
877
+ },
878
+
879
+ initialize: function (map, options) {
880
+ // Save the type so super can fire, need to do this as cannot do this.TYPE :(
881
+ this.type = L.Draw.Circle.TYPE;
882
+
883
+ this._initialLabelText = L.drawLocal.draw.handlers.circle.tooltip.start;
884
+
885
+ L.Draw.SimpleShape.prototype.initialize.call(this, map, options);
886
+ },
887
+
888
+ _drawShape: function (latlng) {
889
+ if (!this._shape) {
890
+ this._shape = new L.Circle(this._startLatLng, this._startLatLng.distanceTo(latlng), this.options.shapeOptions);
891
+ this._map.addLayer(this._shape);
892
+ } else {
893
+ this._shape.setRadius(this._startLatLng.distanceTo(latlng));
894
+ }
895
+ },
896
+
897
+ _fireCreatedEvent: function () {
898
+ var circle = new L.Circle(this._startLatLng, this._shape.getRadius(), this.options.shapeOptions);
899
+ L.Draw.SimpleShape.prototype._fireCreatedEvent.call(this, circle);
900
+ },
901
+
902
+ _onMouseMove: function (e) {
903
+ var latlng = e.latlng,
904
+ showRadius = this.options.showRadius,
905
+ useMetric = this.options.metric,
906
+ radius;
907
+
908
+ this._tooltip.updatePosition(latlng);
909
+ if (this._isDrawing) {
910
+ this._drawShape(latlng);
911
+
912
+ // Get the new radius (rounded to 1 dp)
913
+ radius = this._shape.getRadius().toFixed(1);
914
+
915
+ this._tooltip.updateContent({
916
+ text: this._endLabelText,
917
+ subtext: showRadius ? 'Radius: ' + L.GeometryUtil.readableDistance(radius, useMetric) : ''
918
+ });
919
+ }
920
+ }
921
+ });
922
+
923
+
924
+ L.Draw.Marker = L.Draw.Feature.extend({
925
+ statics: {
926
+ TYPE: 'marker'
927
+ },
928
+
929
+ options: {
930
+ icon: new L.Icon.Default(),
931
+ repeatMode: false,
932
+ zIndexOffset: 2000 // This should be > than the highest z-index any markers
933
+ },
934
+
935
+ initialize: function (map, options) {
936
+ // Save the type so super can fire, need to do this as cannot do this.TYPE :(
937
+ this.type = L.Draw.Marker.TYPE;
938
+
939
+ L.Draw.Feature.prototype.initialize.call(this, map, options);
940
+ },
941
+
942
+ addHooks: function () {
943
+ L.Draw.Feature.prototype.addHooks.call(this);
944
+
945
+ if (this._map) {
946
+ this._tooltip.updateContent({ text: L.drawLocal.draw.handlers.marker.tooltip.start });
947
+
948
+ // Same mouseMarker as in Draw.Polyline
949
+ if (!this._mouseMarker) {
950
+ this._mouseMarker = L.marker(this._map.getCenter(), {
951
+ icon: L.divIcon({
952
+ className: 'leaflet-mouse-marker',
953
+ iconAnchor: [20, 20],
954
+ iconSize: [40, 40]
955
+ }),
956
+ opacity: 0,
957
+ zIndexOffset: this.options.zIndexOffset
958
+ });
959
+ }
960
+
961
+ this._mouseMarker
962
+ .on('click', this._onClick, this)
963
+ .addTo(this._map);
964
+
965
+ this._map.on('mousemove', this._onMouseMove, this);
966
+ }
967
+ },
968
+
969
+ removeHooks: function () {
970
+ L.Draw.Feature.prototype.removeHooks.call(this);
971
+
972
+ if (this._map) {
973
+ if (this._marker) {
974
+ this._marker.off('click', this._onClick, this);
975
+ this._map
976
+ .off('click', this._onClick, this)
977
+ .removeLayer(this._marker);
978
+ delete this._marker;
979
+ }
980
+
981
+ this._mouseMarker.off('click', this._onClick, this);
982
+ this._map.removeLayer(this._mouseMarker);
983
+ delete this._mouseMarker;
984
+
985
+ this._map.off('mousemove', this._onMouseMove, this);
986
+ }
987
+ },
988
+
989
+ _onMouseMove: function (e) {
990
+ var latlng = e.latlng;
991
+
992
+ this._tooltip.updatePosition(latlng);
993
+ this._mouseMarker.setLatLng(latlng);
994
+
995
+ if (!this._marker) {
996
+ this._marker = new L.Marker(latlng, {
997
+ icon: this.options.icon,
998
+ zIndexOffset: this.options.zIndexOffset
999
+ });
1000
+ // Bind to both marker and map to make sure we get the click event.
1001
+ this._marker.on('click', this._onClick, this);
1002
+ this._map
1003
+ .on('click', this._onClick, this)
1004
+ .addLayer(this._marker);
1005
+ }
1006
+ else {
1007
+ latlng = this._mouseMarker.getLatLng();
1008
+ this._marker.setLatLng(latlng);
1009
+ }
1010
+ },
1011
+
1012
+ _onClick: function () {
1013
+ this._fireCreatedEvent();
1014
+
1015
+ this.disable();
1016
+ if (this.options.repeatMode) {
1017
+ this.enable();
1018
+ }
1019
+ },
1020
+
1021
+ _fireCreatedEvent: function () {
1022
+ var marker = new L.Marker(this._marker.getLatLng(), { icon: this.options.icon });
1023
+ L.Draw.Feature.prototype._fireCreatedEvent.call(this, marker);
1024
+ }
1025
+ });
1026
+
1027
+
1028
+ L.Edit = L.Edit || {};
1029
+
1030
+ /*
1031
+ * L.Edit.Poly is an editing handler for polylines and polygons.
1032
+ */
1033
+
1034
+ L.Edit.Poly = L.Handler.extend({
1035
+ options: {
1036
+ icon: new L.DivIcon({
1037
+ iconSize: new L.Point(8, 8),
1038
+ className: 'leaflet-div-icon leaflet-editing-icon'
1039
+ })
1040
+ },
1041
+
1042
+ initialize: function (poly, options) {
1043
+ this._poly = poly;
1044
+ L.setOptions(this, options);
1045
+ },
1046
+
1047
+ addHooks: function () {
1048
+ if (this._poly._map) {
1049
+ if (!this._markerGroup) {
1050
+ this._initMarkers();
1051
+ }
1052
+ this._poly._map.addLayer(this._markerGroup);
1053
+ }
1054
+ },
1055
+
1056
+ removeHooks: function () {
1057
+ if (this._poly._map) {
1058
+ this._poly._map.removeLayer(this._markerGroup);
1059
+ delete this._markerGroup;
1060
+ delete this._markers;
1061
+ }
1062
+ },
1063
+
1064
+ updateMarkers: function () {
1065
+ this._markerGroup.clearLayers();
1066
+ this._initMarkers();
1067
+ },
1068
+
1069
+ _initMarkers: function () {
1070
+ if (!this._markerGroup) {
1071
+ this._markerGroup = new L.LayerGroup();
1072
+ }
1073
+ this._markers = [];
1074
+
1075
+ var latlngs = this._poly._latlngs,
1076
+ i, j, len, marker;
1077
+
1078
+ // TODO refactor holes implementation in Polygon to support it here
1079
+
1080
+ for (i = 0, len = latlngs.length; i < len; i++) {
1081
+
1082
+ marker = this._createMarker(latlngs[i], i);
1083
+ marker.on('click', this._onMarkerClick, this);
1084
+ this._markers.push(marker);
1085
+ }
1086
+
1087
+ var markerLeft, markerRight;
1088
+
1089
+ for (i = 0, j = len - 1; i < len; j = i++) {
1090
+ if (i === 0 && !(L.Polygon && (this._poly instanceof L.Polygon))) {
1091
+ continue;
1092
+ }
1093
+
1094
+ markerLeft = this._markers[j];
1095
+ markerRight = this._markers[i];
1096
+
1097
+ this._createMiddleMarker(markerLeft, markerRight);
1098
+ this._updatePrevNext(markerLeft, markerRight);
1099
+ }
1100
+ },
1101
+
1102
+ _createMarker: function (latlng, index) {
1103
+ var marker = new L.Marker(latlng, {
1104
+ draggable: true,
1105
+ icon: this.options.icon
1106
+ });
1107
+
1108
+ marker._origLatLng = latlng;
1109
+ marker._index = index;
1110
+
1111
+ marker.on('drag', this._onMarkerDrag, this);
1112
+ marker.on('dragend', this._fireEdit, this);
1113
+
1114
+ this._markerGroup.addLayer(marker);
1115
+
1116
+ return marker;
1117
+ },
1118
+
1119
+ _removeMarker: function (marker) {
1120
+ var i = marker._index;
1121
+
1122
+ this._markerGroup.removeLayer(marker);
1123
+ this._markers.splice(i, 1);
1124
+ this._poly.spliceLatLngs(i, 1);
1125
+ this._updateIndexes(i, -1);
1126
+
1127
+ marker
1128
+ .off('drag', this._onMarkerDrag, this)
1129
+ .off('dragend', this._fireEdit, this)
1130
+ .off('click', this._onMarkerClick, this);
1131
+ },
1132
+
1133
+ _fireEdit: function () {
1134
+ this._poly.edited = true;
1135
+ this._poly.fire('edit');
1136
+ },
1137
+
1138
+ _onMarkerDrag: function (e) {
1139
+ var marker = e.target;
1140
+
1141
+ L.extend(marker._origLatLng, marker._latlng);
1142
+
1143
+ if (marker._middleLeft) {
1144
+ marker._middleLeft.setLatLng(this._getMiddleLatLng(marker._prev, marker));
1145
+ }
1146
+ if (marker._middleRight) {
1147
+ marker._middleRight.setLatLng(this._getMiddleLatLng(marker, marker._next));
1148
+ }
1149
+
1150
+ this._poly.redraw();
1151
+ },
1152
+
1153
+ _onMarkerClick: function (e) {
1154
+ var minPoints = L.Polygon && (this._poly instanceof L.Polygon) ? 4 : 3,
1155
+ marker = e.target;
1156
+
1157
+ // If removing this point would create an invalid polyline/polygon don't remove
1158
+ if (this._poly._latlngs.length < minPoints) {
1159
+ return;
1160
+ }
1161
+
1162
+ // remove the marker
1163
+ this._removeMarker(marker);
1164
+
1165
+ // update prev/next links of adjacent markers
1166
+ this._updatePrevNext(marker._prev, marker._next);
1167
+
1168
+ // remove ghost markers near the removed marker
1169
+ if (marker._middleLeft) {
1170
+ this._markerGroup.removeLayer(marker._middleLeft);
1171
+ }
1172
+ if (marker._middleRight) {
1173
+ this._markerGroup.removeLayer(marker._middleRight);
1174
+ }
1175
+
1176
+ // create a ghost marker in place of the removed one
1177
+ if (marker._prev && marker._next) {
1178
+ this._createMiddleMarker(marker._prev, marker._next);
1179
+
1180
+ } else if (!marker._prev) {
1181
+ marker._next._middleLeft = null;
1182
+
1183
+ } else if (!marker._next) {
1184
+ marker._prev._middleRight = null;
1185
+ }
1186
+
1187
+ this._fireEdit();
1188
+ },
1189
+
1190
+ _updateIndexes: function (index, delta) {
1191
+ this._markerGroup.eachLayer(function (marker) {
1192
+ if (marker._index > index) {
1193
+ marker._index += delta;
1194
+ }
1195
+ });
1196
+ },
1197
+
1198
+ _createMiddleMarker: function (marker1, marker2) {
1199
+ var latlng = this._getMiddleLatLng(marker1, marker2),
1200
+ marker = this._createMarker(latlng),
1201
+ onClick,
1202
+ onDragStart,
1203
+ onDragEnd;
1204
+
1205
+ marker.setOpacity(0.6);
1206
+
1207
+ marker1._middleRight = marker2._middleLeft = marker;
1208
+
1209
+ onDragStart = function () {
1210
+ var i = marker2._index;
1211
+
1212
+ marker._index = i;
1213
+
1214
+ marker
1215
+ .off('click', onClick, this)
1216
+ .on('click', this._onMarkerClick, this);
1217
+
1218
+ latlng.lat = marker.getLatLng().lat;
1219
+ latlng.lng = marker.getLatLng().lng;
1220
+ this._poly.spliceLatLngs(i, 0, latlng);
1221
+ this._markers.splice(i, 0, marker);
1222
+
1223
+ marker.setOpacity(1);
1224
+
1225
+ this._updateIndexes(i, 1);
1226
+ marker2._index++;
1227
+ this._updatePrevNext(marker1, marker);
1228
+ this._updatePrevNext(marker, marker2);
1229
+
1230
+ this._poly.fire('editstart');
1231
+ };
1232
+
1233
+ onDragEnd = function () {
1234
+ marker.off('dragstart', onDragStart, this);
1235
+ marker.off('dragend', onDragEnd, this);
1236
+
1237
+ this._createMiddleMarker(marker1, marker);
1238
+ this._createMiddleMarker(marker, marker2);
1239
+ };
1240
+
1241
+ onClick = function () {
1242
+ onDragStart.call(this);
1243
+ onDragEnd.call(this);
1244
+ this._fireEdit();
1245
+ };
1246
+
1247
+ marker
1248
+ .on('click', onClick, this)
1249
+ .on('dragstart', onDragStart, this)
1250
+ .on('dragend', onDragEnd, this);
1251
+
1252
+ this._markerGroup.addLayer(marker);
1253
+ },
1254
+
1255
+ _updatePrevNext: function (marker1, marker2) {
1256
+ if (marker1) {
1257
+ marker1._next = marker2;
1258
+ }
1259
+ if (marker2) {
1260
+ marker2._prev = marker1;
1261
+ }
1262
+ },
1263
+
1264
+ _getMiddleLatLng: function (marker1, marker2) {
1265
+ var map = this._poly._map,
1266
+ p1 = map.project(marker1.getLatLng()),
1267
+ p2 = map.project(marker2.getLatLng());
1268
+
1269
+ return map.unproject(p1._add(p2)._divideBy(2));
1270
+ }
1271
+ });
1272
+
1273
+ L.Polyline.addInitHook(function () {
1274
+
1275
+ // Check to see if handler has already been initialized. This is to support versions of Leaflet that still have L.Handler.PolyEdit
1276
+ if (this.editing) {
1277
+ return;
1278
+ }
1279
+
1280
+ if (L.Edit.Poly) {
1281
+ this.editing = new L.Edit.Poly(this);
1282
+
1283
+ if (this.options.editable) {
1284
+ this.editing.enable();
1285
+ }
1286
+ }
1287
+
1288
+ this.on('add', function () {
1289
+ if (this.editing && this.editing.enabled()) {
1290
+ this.editing.addHooks();
1291
+ }
1292
+ });
1293
+
1294
+ this.on('remove', function () {
1295
+ if (this.editing && this.editing.enabled()) {
1296
+ this.editing.removeHooks();
1297
+ }
1298
+ });
1299
+ });
1300
+
1301
+
1302
+ L.Edit = L.Edit || {};
1303
+
1304
+ L.Edit.SimpleShape = L.Handler.extend({
1305
+ options: {
1306
+ moveIcon: new L.DivIcon({
1307
+ iconSize: new L.Point(8, 8),
1308
+ className: 'leaflet-div-icon leaflet-editing-icon leaflet-edit-move'
1309
+ }),
1310
+ resizeIcon: new L.DivIcon({
1311
+ iconSize: new L.Point(8, 8),
1312
+ className: 'leaflet-div-icon leaflet-editing-icon leaflet-edit-resize'
1313
+ })
1314
+ },
1315
+
1316
+ initialize: function (shape, options) {
1317
+ this._shape = shape;
1318
+ L.Util.setOptions(this, options);
1319
+ },
1320
+
1321
+ addHooks: function () {
1322
+ if (this._shape._map) {
1323
+ this._map = this._shape._map;
1324
+
1325
+ if (!this._markerGroup) {
1326
+ this._initMarkers();
1327
+ }
1328
+ this._map.addLayer(this._markerGroup);
1329
+ }
1330
+ },
1331
+
1332
+ removeHooks: function () {
1333
+ if (this._shape._map) {
1334
+ this._unbindMarker(this._moveMarker);
1335
+
1336
+ for (var i = 0, l = this._resizeMarkers.length; i < l; i++) {
1337
+ this._unbindMarker(this._resizeMarkers[i]);
1338
+ }
1339
+ this._resizeMarkers = null;
1340
+
1341
+ this._map.removeLayer(this._markerGroup);
1342
+ delete this._markerGroup;
1343
+ }
1344
+
1345
+ this._map = null;
1346
+ },
1347
+
1348
+ updateMarkers: function () {
1349
+ this._markerGroup.clearLayers();
1350
+ this._initMarkers();
1351
+ },
1352
+
1353
+ _initMarkers: function () {
1354
+ if (!this._markerGroup) {
1355
+ this._markerGroup = new L.LayerGroup();
1356
+ }
1357
+
1358
+ // Create center marker
1359
+ this._createMoveMarker();
1360
+
1361
+ // Create edge marker
1362
+ this._createResizeMarker();
1363
+ },
1364
+
1365
+ _createMoveMarker: function () {
1366
+ // Children override
1367
+ },
1368
+
1369
+ _createResizeMarker: function () {
1370
+ // Children override
1371
+ },
1372
+
1373
+ _createMarker: function (latlng, icon) {
1374
+ var marker = new L.Marker(latlng, {
1375
+ draggable: true,
1376
+ icon: icon,
1377
+ zIndexOffset: 10
1378
+ });
1379
+
1380
+ this._bindMarker(marker);
1381
+
1382
+ this._markerGroup.addLayer(marker);
1383
+
1384
+ return marker;
1385
+ },
1386
+
1387
+ _bindMarker: function (marker) {
1388
+ marker
1389
+ .on('dragstart', this._onMarkerDragStart, this)
1390
+ .on('drag', this._onMarkerDrag, this)
1391
+ .on('dragend', this._onMarkerDragEnd, this);
1392
+ },
1393
+
1394
+ _unbindMarker: function (marker) {
1395
+ marker
1396
+ .off('dragstart', this._onMarkerDragStart, this)
1397
+ .off('drag', this._onMarkerDrag, this)
1398
+ .off('dragend', this._onMarkerDragEnd, this);
1399
+ },
1400
+
1401
+ _onMarkerDragStart: function (e) {
1402
+ var marker = e.target;
1403
+ marker.setOpacity(0);
1404
+
1405
+ this._shape.fire('editstart');
1406
+ },
1407
+
1408
+ _fireEdit: function () {
1409
+ this._shape.edited = true;
1410
+ this._shape.fire('edit');
1411
+ },
1412
+
1413
+ _onMarkerDrag: function (e) {
1414
+ var marker = e.target,
1415
+ latlng = marker.getLatLng();
1416
+
1417
+ if (marker === this._moveMarker) {
1418
+ this._move(latlng);
1419
+ } else {
1420
+ this._resize(latlng);
1421
+ }
1422
+
1423
+ this._shape.redraw();
1424
+ },
1425
+
1426
+ _onMarkerDragEnd: function (e) {
1427
+ var marker = e.target;
1428
+ marker.setOpacity(1);
1429
+
1430
+ this._fireEdit();
1431
+ },
1432
+
1433
+ _move: function () {
1434
+ // Children override
1435
+ },
1436
+
1437
+ _resize: function () {
1438
+ // Children override
1439
+ }
1440
+ });
1441
+
1442
+
1443
+ L.Edit = L.Edit || {};
1444
+
1445
+ L.Edit.Rectangle = L.Edit.SimpleShape.extend({
1446
+ _createMoveMarker: function () {
1447
+ var bounds = this._shape.getBounds(),
1448
+ center = bounds.getCenter();
1449
+
1450
+ this._moveMarker = this._createMarker(center, this.options.moveIcon);
1451
+ },
1452
+
1453
+ _createResizeMarker: function () {
1454
+ var corners = this._getCorners();
1455
+
1456
+ this._resizeMarkers = [];
1457
+
1458
+ for (var i = 0, l = corners.length; i < l; i++) {
1459
+ this._resizeMarkers.push(this._createMarker(corners[i], this.options.resizeIcon));
1460
+ // Monkey in the corner index as we will need to know this for dragging
1461
+ this._resizeMarkers[i]._cornerIndex = i;
1462
+ }
1463
+ },
1464
+
1465
+ _onMarkerDragStart: function (e) {
1466
+ L.Edit.SimpleShape.prototype._onMarkerDragStart.call(this, e);
1467
+
1468
+ // Save a reference to the opposite point
1469
+ var corners = this._getCorners(),
1470
+ marker = e.target,
1471
+ currentCornerIndex = marker._cornerIndex;
1472
+
1473
+ this._oppositeCorner = corners[(currentCornerIndex + 2) % 4];
1474
+
1475
+ this._toggleCornerMarkers(0, currentCornerIndex);
1476
+ },
1477
+
1478
+ _onMarkerDragEnd: function (e) {
1479
+ var marker = e.target,
1480
+ bounds, center;
1481
+
1482
+ // Reset move marker position to the center
1483
+ if (marker === this._moveMarker) {
1484
+ bounds = this._shape.getBounds();
1485
+ center = bounds.getCenter();
1486
+
1487
+ marker.setLatLng(center);
1488
+ }
1489
+
1490
+ this._toggleCornerMarkers(1);
1491
+
1492
+ this._repositionCornerMarkers();
1493
+
1494
+ L.Edit.SimpleShape.prototype._onMarkerDragEnd.call(this, e);
1495
+ },
1496
+
1497
+ _move: function (newCenter) {
1498
+ var latlngs = this._shape.getLatLngs(),
1499
+ bounds = this._shape.getBounds(),
1500
+ center = bounds.getCenter(),
1501
+ offset, newLatLngs = [];
1502
+
1503
+ // Offset the latlngs to the new center
1504
+ for (var i = 0, l = latlngs.length; i < l; i++) {
1505
+ offset = [latlngs[i].lat - center.lat, latlngs[i].lng - center.lng];
1506
+ newLatLngs.push([newCenter.lat + offset[0], newCenter.lng + offset[1]]);
1507
+ }
1508
+
1509
+ this._shape.setLatLngs(newLatLngs);
1510
+
1511
+ // Reposition the resize markers
1512
+ this._repositionCornerMarkers();
1513
+ },
1514
+
1515
+ _resize: function (latlng) {
1516
+ var bounds;
1517
+
1518
+ // Update the shape based on the current position of this corner and the opposite point
1519
+ this._shape.setBounds(L.latLngBounds(latlng, this._oppositeCorner));
1520
+
1521
+ // Reposition the move marker
1522
+ bounds = this._shape.getBounds();
1523
+ this._moveMarker.setLatLng(bounds.getCenter());
1524
+ },
1525
+
1526
+ _getCorners: function () {
1527
+ var bounds = this._shape.getBounds(),
1528
+ nw = bounds.getNorthWest(),
1529
+ ne = bounds.getNorthEast(),
1530
+ se = bounds.getSouthEast(),
1531
+ sw = bounds.getSouthWest();
1532
+
1533
+ return [nw, ne, se, sw];
1534
+ },
1535
+
1536
+ _toggleCornerMarkers: function (opacity) {
1537
+ for (var i = 0, l = this._resizeMarkers.length; i < l; i++) {
1538
+ this._resizeMarkers[i].setOpacity(opacity);
1539
+ }
1540
+ },
1541
+
1542
+ _repositionCornerMarkers: function () {
1543
+ var corners = this._getCorners();
1544
+
1545
+ for (var i = 0, l = this._resizeMarkers.length; i < l; i++) {
1546
+ this._resizeMarkers[i].setLatLng(corners[i]);
1547
+ }
1548
+ }
1549
+ });
1550
+
1551
+ L.Rectangle.addInitHook(function () {
1552
+ if (L.Edit.Rectangle) {
1553
+ this.editing = new L.Edit.Rectangle(this);
1554
+
1555
+ if (this.options.editable) {
1556
+ this.editing.enable();
1557
+ }
1558
+ }
1559
+ });
1560
+
1561
+
1562
+ L.Edit = L.Edit || {};
1563
+
1564
+ L.Edit.Circle = L.Edit.SimpleShape.extend({
1565
+ _createMoveMarker: function () {
1566
+ var center = this._shape.getLatLng();
1567
+
1568
+ this._moveMarker = this._createMarker(center, this.options.moveIcon);
1569
+ },
1570
+
1571
+ _createResizeMarker: function () {
1572
+ var center = this._shape.getLatLng(),
1573
+ resizemarkerPoint = this._getResizeMarkerPoint(center);
1574
+
1575
+ this._resizeMarkers = [];
1576
+ this._resizeMarkers.push(this._createMarker(resizemarkerPoint, this.options.resizeIcon));
1577
+ },
1578
+
1579
+ _getResizeMarkerPoint: function (latlng) {
1580
+ // From L.shape.getBounds()
1581
+ var delta = this._shape._radius * Math.cos(Math.PI / 4),
1582
+ point = this._map.project(latlng);
1583
+ return this._map.unproject([point.x + delta, point.y - delta]);
1584
+ },
1585
+
1586
+ _move: function (latlng) {
1587
+ var resizemarkerPoint = this._getResizeMarkerPoint(latlng);
1588
+
1589
+ // Move the resize marker
1590
+ this._resizeMarkers[0].setLatLng(resizemarkerPoint);
1591
+
1592
+ // Move the circle
1593
+ this._shape.setLatLng(latlng);
1594
+ },
1595
+
1596
+ _resize: function (latlng) {
1597
+ var moveLatLng = this._moveMarker.getLatLng(),
1598
+ radius = moveLatLng.distanceTo(latlng);
1599
+
1600
+ this._shape.setRadius(radius);
1601
+ }
1602
+ });
1603
+
1604
+ L.Circle.addInitHook(function () {
1605
+ if (L.Edit.Circle) {
1606
+ this.editing = new L.Edit.Circle(this);
1607
+
1608
+ if (this.options.editable) {
1609
+ this.editing.enable();
1610
+ }
1611
+ }
1612
+
1613
+ this.on('add', function () {
1614
+ if (this.editing && this.editing.enabled()) {
1615
+ this.editing.addHooks();
1616
+ }
1617
+ });
1618
+
1619
+ this.on('remove', function () {
1620
+ if (this.editing && this.editing.enabled()) {
1621
+ this.editing.removeHooks();
1622
+ }
1623
+ });
1624
+ });
1625
+
1626
+ /*
1627
+ * L.LatLngUtil contains different utility functions for LatLngs.
1628
+ */
1629
+
1630
+ L.LatLngUtil = {
1631
+ // Clones a LatLngs[], returns [][]
1632
+ cloneLatLngs: function (latlngs) {
1633
+ var clone = [];
1634
+ for (var i = 0, l = latlngs.length; i < l; i++) {
1635
+ clone.push(this.cloneLatLng(latlngs[i]));
1636
+ }
1637
+ return clone;
1638
+ },
1639
+
1640
+ cloneLatLng: function (latlng) {
1641
+ return L.latLng(latlng.lat, latlng.lng);
1642
+ }
1643
+ };
1644
+
1645
+ L.GeometryUtil = L.extend(L.GeometryUtil || {}, {
1646
+ // Ported from the OpenLayers implementation. See https://github.com/openlayers/openlayers/blob/master/lib/OpenLayers/Geometry/LinearRing.js#L270
1647
+ geodesicArea: function (latLngs) {
1648
+ var pointsCount = latLngs.length,
1649
+ area = 0.0,
1650
+ d2r = L.LatLng.DEG_TO_RAD,
1651
+ p1, p2;
1652
+
1653
+ if (pointsCount > 2) {
1654
+ for (var i = 0; i < pointsCount; i++) {
1655
+ p1 = latLngs[i];
1656
+ p2 = latLngs[(i + 1) % pointsCount];
1657
+ area += ((p2.lng - p1.lng) * d2r) *
1658
+ (2 + Math.sin(p1.lat * d2r) + Math.sin(p2.lat * d2r));
1659
+ }
1660
+ area = area * 6378137.0 * 6378137.0 / 2.0;
1661
+ }
1662
+
1663
+ return Math.abs(area);
1664
+ },
1665
+
1666
+ readableArea: function (area, isMetric) {
1667
+ var areaStr;
1668
+
1669
+ if (isMetric) {
1670
+ if (area >= 10000) {
1671
+ areaStr = (area * 0.0001).toFixed(2) + ' ha';
1672
+ } else {
1673
+ areaStr = area.toFixed(2) + ' m&sup2;';
1674
+ }
1675
+ } else {
1676
+ area *= 0.836127; // Square yards in 1 meter
1677
+
1678
+ if (area >= 3097600) { //3097600 square yards in 1 square mile
1679
+ areaStr = (area / 3097600).toFixed(2) + ' mi&sup2;';
1680
+ } else if (area >= 4840) {//48040 square yards in 1 acre
1681
+ areaStr = (area / 4840).toFixed(2) + ' acres';
1682
+ } else {
1683
+ areaStr = Math.ceil(area) + ' yd&sup2;';
1684
+ }
1685
+ }
1686
+
1687
+ return areaStr;
1688
+ },
1689
+
1690
+ readableDistance: function (distance, isMetric) {
1691
+ var distanceStr;
1692
+
1693
+ if (isMetric) {
1694
+ // show metres when distance is < 1km, then show km
1695
+ if (distance > 1000) {
1696
+ distanceStr = (distance / 1000).toFixed(2) + ' km';
1697
+ } else {
1698
+ distanceStr = Math.ceil(distance) + ' m';
1699
+ }
1700
+ } else {
1701
+ distance *= 1.09361;
1702
+
1703
+ if (distance > 1760) {
1704
+ distanceStr = (distance / 1760).toFixed(2) + ' miles';
1705
+ } else {
1706
+ distanceStr = Math.ceil(distance) + ' yd';
1707
+ }
1708
+ }
1709
+
1710
+ return distanceStr;
1711
+ }
1712
+ });
1713
+
1714
+ L.Util.extend(L.LineUtil, {
1715
+ // Checks to see if two line segments intersect. Does not handle degenerate cases.
1716
+ // http://compgeom.cs.uiuc.edu/~jeffe/teaching/373/notes/x06-sweepline.pdf
1717
+ segmentsIntersect: function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2, /*Point*/ p3) {
1718
+ return this._checkCounterclockwise(p, p2, p3) !==
1719
+ this._checkCounterclockwise(p1, p2, p3) &&
1720
+ this._checkCounterclockwise(p, p1, p2) !==
1721
+ this._checkCounterclockwise(p, p1, p3);
1722
+ },
1723
+
1724
+ // check to see if points are in counterclockwise order
1725
+ _checkCounterclockwise: function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2) {
1726
+ return (p2.y - p.y) * (p1.x - p.x) > (p1.y - p.y) * (p2.x - p.x);
1727
+ }
1728
+ });
1729
+
1730
+ L.Polyline.include({
1731
+ // Check to see if this polyline has any linesegments that intersect.
1732
+ // NOTE: does not support detecting intersection for degenerate cases.
1733
+ intersects: function () {
1734
+ var points = this._originalPoints,
1735
+ len = points ? points.length : 0,
1736
+ i, p, p1;
1737
+
1738
+ if (this._tooFewPointsForIntersection()) {
1739
+ return false;
1740
+ }
1741
+
1742
+ for (i = len - 1; i >= 3; i--) {
1743
+ p = points[i - 1];
1744
+ p1 = points[i];
1745
+
1746
+
1747
+ if (this._lineSegmentsIntersectsRange(p, p1, i - 2)) {
1748
+ return true;
1749
+ }
1750
+ }
1751
+
1752
+ return false;
1753
+ },
1754
+
1755
+ // Check for intersection if new latlng was added to this polyline.
1756
+ // NOTE: does not support detecting intersection for degenerate cases.
1757
+ newLatLngIntersects: function (latlng, skipFirst) {
1758
+ // Cannot check a polyline for intersecting lats/lngs when not added to the map
1759
+ if (!this._map) {
1760
+ return false;
1761
+ }
1762
+
1763
+ return this.newPointIntersects(this._map.latLngToLayerPoint(latlng), skipFirst);
1764
+ },
1765
+
1766
+ // Check for intersection if new point was added to this polyline.
1767
+ // newPoint must be a layer point.
1768
+ // NOTE: does not support detecting intersection for degenerate cases.
1769
+ newPointIntersects: function (newPoint, skipFirst) {
1770
+ var points = this._originalPoints,
1771
+ len = points ? points.length : 0,
1772
+ lastPoint = points ? points[len - 1] : null,
1773
+ // The previous previous line segment. Previous line segment doesn't need testing.
1774
+ maxIndex = len - 2;
1775
+
1776
+ if (this._tooFewPointsForIntersection(1)) {
1777
+ return false;
1778
+ }
1779
+
1780
+ return this._lineSegmentsIntersectsRange(lastPoint, newPoint, maxIndex, skipFirst ? 1 : 0);
1781
+ },
1782
+
1783
+ // Polylines with 2 sides can only intersect in cases where points are collinear (we don't support detecting these).
1784
+ // Cannot have intersection when < 3 line segments (< 4 points)
1785
+ _tooFewPointsForIntersection: function (extraPoints) {
1786
+ var points = this._originalPoints,
1787
+ len = points ? points.length : 0;
1788
+ // Increment length by extraPoints if present
1789
+ len += extraPoints || 0;
1790
+
1791
+ return !this._originalPoints || len <= 3;
1792
+ },
1793
+
1794
+ // Checks a line segment intersections with any line segments before its predecessor.
1795
+ // Don't need to check the predecessor as will never intersect.
1796
+ _lineSegmentsIntersectsRange: function (p, p1, maxIndex, minIndex) {
1797
+ var points = this._originalPoints,
1798
+ p2, p3;
1799
+
1800
+ minIndex = minIndex || 0;
1801
+
1802
+ // Check all previous line segments (beside the immediately previous) for intersections
1803
+ for (var j = maxIndex; j > minIndex; j--) {
1804
+ p2 = points[j - 1];
1805
+ p3 = points[j];
1806
+
1807
+ if (L.LineUtil.segmentsIntersect(p, p1, p2, p3)) {
1808
+ return true;
1809
+ }
1810
+ }
1811
+
1812
+ return false;
1813
+ }
1814
+ });
1815
+
1816
+
1817
+ L.Polygon.include({
1818
+ // Checks a polygon for any intersecting line segments. Ignores holes.
1819
+ intersects: function () {
1820
+ var polylineIntersects,
1821
+ points = this._originalPoints,
1822
+ len, firstPoint, lastPoint, maxIndex;
1823
+
1824
+ if (this._tooFewPointsForIntersection()) {
1825
+ return false;
1826
+ }
1827
+
1828
+ polylineIntersects = L.Polyline.prototype.intersects.call(this);
1829
+
1830
+ // If already found an intersection don't need to check for any more.
1831
+ if (polylineIntersects) {
1832
+ return true;
1833
+ }
1834
+
1835
+ len = points.length;
1836
+ firstPoint = points[0];
1837
+ lastPoint = points[len - 1];
1838
+ maxIndex = len - 2;
1839
+
1840
+ // Check the line segment between last and first point. Don't need to check the first line segment (minIndex = 1)
1841
+ return this._lineSegmentsIntersectsRange(lastPoint, firstPoint, maxIndex, 1);
1842
+ }
1843
+ });
1844
+
1845
+ L.Control.Draw = L.Control.extend({
1846
+
1847
+ options: {
1848
+ position: 'topleft',
1849
+ draw: {},
1850
+ edit: false
1851
+ },
1852
+
1853
+ initialize: function (options) {
1854
+ if (L.version < '0.7') {
1855
+ throw new Error('Leaflet.draw 0.2.3+ requires Leaflet 0.7.0+. Download latest from https://github.com/Leaflet/Leaflet/');
1856
+ }
1857
+
1858
+ L.Control.prototype.initialize.call(this, options);
1859
+
1860
+ var id, toolbar;
1861
+
1862
+ this._toolbars = {};
1863
+
1864
+ // Initialize toolbars
1865
+ if (L.DrawToolbar && this.options.draw) {
1866
+ toolbar = new L.DrawToolbar(this.options.draw);
1867
+ id = L.stamp(toolbar);
1868
+ this._toolbars[id] = toolbar;
1869
+
1870
+ // Listen for when toolbar is enabled
1871
+ this._toolbars[id].on('enable', this._toolbarEnabled, this);
1872
+ }
1873
+
1874
+ if (L.EditToolbar && this.options.edit) {
1875
+ toolbar = new L.EditToolbar(this.options.edit);
1876
+ id = L.stamp(toolbar);
1877
+ this._toolbars[id] = toolbar;
1878
+
1879
+ // Listen for when toolbar is enabled
1880
+ this._toolbars[id].on('enable', this._toolbarEnabled, this);
1881
+ }
1882
+ },
1883
+
1884
+ onAdd: function (map) {
1885
+ var container = L.DomUtil.create('div', 'leaflet-draw'),
1886
+ addedTopClass = false,
1887
+ topClassName = 'leaflet-draw-toolbar-top',
1888
+ toolbarContainer;
1889
+
1890
+ for (var toolbarId in this._toolbars) {
1891
+ if (this._toolbars.hasOwnProperty(toolbarId)) {
1892
+ toolbarContainer = this._toolbars[toolbarId].addToolbar(map);
1893
+
1894
+ if (toolbarContainer) {
1895
+ // Add class to the first toolbar to remove the margin
1896
+ if (!addedTopClass) {
1897
+ if (!L.DomUtil.hasClass(toolbarContainer, topClassName)) {
1898
+ L.DomUtil.addClass(toolbarContainer.childNodes[0], topClassName);
1899
+ }
1900
+ addedTopClass = true;
1901
+ }
1902
+
1903
+ container.appendChild(toolbarContainer);
1904
+ }
1905
+ }
1906
+ }
1907
+
1908
+ return container;
1909
+ },
1910
+
1911
+ onRemove: function () {
1912
+ for (var toolbarId in this._toolbars) {
1913
+ if (this._toolbars.hasOwnProperty(toolbarId)) {
1914
+ this._toolbars[toolbarId].removeToolbar();
1915
+ }
1916
+ }
1917
+ },
1918
+
1919
+ setDrawingOptions: function (options) {
1920
+ for (var toolbarId in this._toolbars) {
1921
+ if (this._toolbars[toolbarId] instanceof L.DrawToolbar) {
1922
+ this._toolbars[toolbarId].setOptions(options);
1923
+ }
1924
+ }
1925
+ },
1926
+
1927
+ _toolbarEnabled: function (e) {
1928
+ var id = '' + L.stamp(e.target);
1929
+
1930
+ for (var toolbarId in this._toolbars) {
1931
+ if (this._toolbars.hasOwnProperty(toolbarId) && toolbarId !== id) {
1932
+ this._toolbars[toolbarId].disable();
1933
+ }
1934
+ }
1935
+ }
1936
+ });
1937
+
1938
+ L.Map.mergeOptions({
1939
+ drawControlTooltips: true,
1940
+ drawControl: false
1941
+ });
1942
+
1943
+ L.Map.addInitHook(function () {
1944
+ if (this.options.drawControl) {
1945
+ this.drawControl = new L.Control.Draw();
1946
+ this.addControl(this.drawControl);
1947
+ }
1948
+ });
1949
+
1950
+
1951
+ L.Toolbar = L.Class.extend({
1952
+ includes: [L.Mixin.Events],
1953
+
1954
+ initialize: function (options) {
1955
+ L.setOptions(this, options);
1956
+
1957
+ this._modes = {};
1958
+ this._actionButtons = [];
1959
+ this._activeMode = null;
1960
+ },
1961
+
1962
+ enabled: function () {
1963
+ return this._activeMode !== null;
1964
+ },
1965
+
1966
+ disable: function () {
1967
+ if (!this.enabled()) { return; }
1968
+
1969
+ this._activeMode.handler.disable();
1970
+ },
1971
+
1972
+ addToolbar: function (map) {
1973
+ var container = L.DomUtil.create('div', 'leaflet-draw-section'),
1974
+ buttonIndex = 0,
1975
+ buttonClassPrefix = this._toolbarClass || '',
1976
+ modeHandlers = this.getModeHandlers(map),
1977
+ i;
1978
+
1979
+ this._toolbarContainer = L.DomUtil.create('div', 'leaflet-draw-toolbar leaflet-bar');
1980
+ this._map = map;
1981
+
1982
+ for (i = 0; i < modeHandlers.length; i++) {
1983
+ if (modeHandlers[i].enabled) {
1984
+ this._initModeHandler(
1985
+ modeHandlers[i].handler,
1986
+ this._toolbarContainer,
1987
+ buttonIndex++,
1988
+ buttonClassPrefix,
1989
+ modeHandlers[i].title
1990
+ );
1991
+ }
1992
+ }
1993
+
1994
+ // if no buttons were added, do not add the toolbar
1995
+ if (!buttonIndex) {
1996
+ return;
1997
+ }
1998
+
1999
+ // Save button index of the last button, -1 as we would have ++ after the last button
2000
+ this._lastButtonIndex = --buttonIndex;
2001
+
2002
+ // Create empty actions part of the toolbar
2003
+ this._actionsContainer = L.DomUtil.create('ul', 'leaflet-draw-actions');
2004
+
2005
+ // Add draw and cancel containers to the control container
2006
+ container.appendChild(this._toolbarContainer);
2007
+ container.appendChild(this._actionsContainer);
2008
+
2009
+ return container;
2010
+ },
2011
+
2012
+ removeToolbar: function () {
2013
+ // Dispose each handler
2014
+ for (var handlerId in this._modes) {
2015
+ if (this._modes.hasOwnProperty(handlerId)) {
2016
+ // Unbind handler button
2017
+ this._disposeButton(
2018
+ this._modes[handlerId].button,
2019
+ this._modes[handlerId].handler.enable,
2020
+ this._modes[handlerId].handler
2021
+ );
2022
+
2023
+ // Make sure is disabled
2024
+ this._modes[handlerId].handler.disable();
2025
+
2026
+ // Unbind handler
2027
+ this._modes[handlerId].handler
2028
+ .off('enabled', this._handlerActivated, this)
2029
+ .off('disabled', this._handlerDeactivated, this);
2030
+ }
2031
+ }
2032
+ this._modes = {};
2033
+
2034
+ // Dispose the actions toolbar
2035
+ for (var i = 0, l = this._actionButtons.length; i < l; i++) {
2036
+ this._disposeButton(
2037
+ this._actionButtons[i].button,
2038
+ this._actionButtons[i].callback,
2039
+ this
2040
+ );
2041
+ }
2042
+ this._actionButtons = [];
2043
+ this._actionsContainer = null;
2044
+ },
2045
+
2046
+ _initModeHandler: function (handler, container, buttonIndex, classNamePredix, buttonTitle) {
2047
+ var type = handler.type;
2048
+
2049
+ this._modes[type] = {};
2050
+
2051
+ this._modes[type].handler = handler;
2052
+
2053
+ this._modes[type].button = this._createButton({
2054
+ title: buttonTitle,
2055
+ className: classNamePredix + '-' + type,
2056
+ container: container,
2057
+ callback: this._modes[type].handler.enable,
2058
+ context: this._modes[type].handler
2059
+ });
2060
+
2061
+ this._modes[type].buttonIndex = buttonIndex;
2062
+
2063
+ this._modes[type].handler
2064
+ .on('enabled', this._handlerActivated, this)
2065
+ .on('disabled', this._handlerDeactivated, this);
2066
+ },
2067
+
2068
+ _createButton: function (options) {
2069
+ var link = L.DomUtil.create('a', options.className || '', options.container);
2070
+ link.href = '#';
2071
+
2072
+ if (options.text) {
2073
+ link.innerHTML = options.text;
2074
+ }
2075
+
2076
+ if (options.title) {
2077
+ link.title = options.title;
2078
+ }
2079
+
2080
+ L.DomEvent
2081
+ .on(link, 'click', L.DomEvent.stopPropagation)
2082
+ .on(link, 'mousedown', L.DomEvent.stopPropagation)
2083
+ .on(link, 'dblclick', L.DomEvent.stopPropagation)
2084
+ .on(link, 'click', L.DomEvent.preventDefault)
2085
+ .on(link, 'click', options.callback, options.context);
2086
+
2087
+ return link;
2088
+ },
2089
+
2090
+ _disposeButton: function (button, callback) {
2091
+ L.DomEvent
2092
+ .off(button, 'click', L.DomEvent.stopPropagation)
2093
+ .off(button, 'mousedown', L.DomEvent.stopPropagation)
2094
+ .off(button, 'dblclick', L.DomEvent.stopPropagation)
2095
+ .off(button, 'click', L.DomEvent.preventDefault)
2096
+ .off(button, 'click', callback);
2097
+ },
2098
+
2099
+ _handlerActivated: function (e) {
2100
+ // Disable active mode (if present)
2101
+ this.disable();
2102
+
2103
+ // Cache new active feature
2104
+ this._activeMode = this._modes[e.handler];
2105
+
2106
+ L.DomUtil.addClass(this._activeMode.button, 'leaflet-draw-toolbar-button-enabled');
2107
+
2108
+ this._showActionsToolbar();
2109
+
2110
+ this.fire('enable');
2111
+ },
2112
+
2113
+ _handlerDeactivated: function () {
2114
+ this._hideActionsToolbar();
2115
+
2116
+ L.DomUtil.removeClass(this._activeMode.button, 'leaflet-draw-toolbar-button-enabled');
2117
+
2118
+ this._activeMode = null;
2119
+
2120
+ this.fire('disable');
2121
+ },
2122
+
2123
+ _createActions: function (handler) {
2124
+ var container = this._actionsContainer,
2125
+ buttons = this.getActions(handler),
2126
+ l = buttons.length,
2127
+ li, di, dl, button;
2128
+
2129
+ // Dispose the actions toolbar (todo: dispose only not used buttons)
2130
+ for (di = 0, dl = this._actionButtons.length; di < dl; di++) {
2131
+ this._disposeButton(this._actionButtons[di].button, this._actionButtons[di].callback);
2132
+ }
2133
+ this._actionButtons = [];
2134
+
2135
+ // Remove all old buttons
2136
+ while (container.firstChild) {
2137
+ container.removeChild(container.firstChild);
2138
+ }
2139
+
2140
+ for (var i = 0; i < l; i++) {
2141
+ if ('enabled' in buttons[i] && !buttons[i].enabled) {
2142
+ continue;
2143
+ }
2144
+
2145
+ li = L.DomUtil.create('li', '', container);
2146
+
2147
+ button = this._createButton({
2148
+ title: buttons[i].title,
2149
+ text: buttons[i].text,
2150
+ container: li,
2151
+ callback: buttons[i].callback,
2152
+ context: buttons[i].context
2153
+ });
2154
+
2155
+ this._actionButtons.push({
2156
+ button: button,
2157
+ callback: buttons[i].callback
2158
+ });
2159
+ }
2160
+ },
2161
+
2162
+ _showActionsToolbar: function () {
2163
+ var buttonIndex = this._activeMode.buttonIndex,
2164
+ lastButtonIndex = this._lastButtonIndex,
2165
+ toolbarPosition = this._activeMode.button.offsetTop - 1;
2166
+
2167
+ // Recreate action buttons on every click
2168
+ this._createActions(this._activeMode.handler);
2169
+
2170
+ // Correctly position the cancel button
2171
+ this._actionsContainer.style.top = toolbarPosition + 'px';
2172
+
2173
+ if (buttonIndex === 0) {
2174
+ L.DomUtil.addClass(this._toolbarContainer, 'leaflet-draw-toolbar-notop');
2175
+ L.DomUtil.addClass(this._actionsContainer, 'leaflet-draw-actions-top');
2176
+ }
2177
+
2178
+ if (buttonIndex === lastButtonIndex) {
2179
+ L.DomUtil.addClass(this._toolbarContainer, 'leaflet-draw-toolbar-nobottom');
2180
+ L.DomUtil.addClass(this._actionsContainer, 'leaflet-draw-actions-bottom');
2181
+ }
2182
+
2183
+ this._actionsContainer.style.display = 'block';
2184
+ },
2185
+
2186
+ _hideActionsToolbar: function () {
2187
+ this._actionsContainer.style.display = 'none';
2188
+
2189
+ L.DomUtil.removeClass(this._toolbarContainer, 'leaflet-draw-toolbar-notop');
2190
+ L.DomUtil.removeClass(this._toolbarContainer, 'leaflet-draw-toolbar-nobottom');
2191
+ L.DomUtil.removeClass(this._actionsContainer, 'leaflet-draw-actions-top');
2192
+ L.DomUtil.removeClass(this._actionsContainer, 'leaflet-draw-actions-bottom');
2193
+ }
2194
+ });
2195
+
2196
+
2197
+ L.Tooltip = L.Class.extend({
2198
+ initialize: function (map) {
2199
+ this._map = map;
2200
+ this._popupPane = map._panes.popupPane;
2201
+
2202
+ this._container = map.options.drawControlTooltips ? L.DomUtil.create('div', 'leaflet-draw-tooltip', this._popupPane) : null;
2203
+ this._singleLineLabel = false;
2204
+ },
2205
+
2206
+ dispose: function () {
2207
+ if (this._container) {
2208
+ this._popupPane.removeChild(this._container);
2209
+ this._container = null;
2210
+ }
2211
+ },
2212
+
2213
+ updateContent: function (labelText) {
2214
+ if (!this._container) {
2215
+ return this;
2216
+ }
2217
+ labelText.subtext = labelText.subtext || '';
2218
+
2219
+ // update the vertical position (only if changed)
2220
+ if (labelText.subtext.length === 0 && !this._singleLineLabel) {
2221
+ L.DomUtil.addClass(this._container, 'leaflet-draw-tooltip-single');
2222
+ this._singleLineLabel = true;
2223
+ }
2224
+ else if (labelText.subtext.length > 0 && this._singleLineLabel) {
2225
+ L.DomUtil.removeClass(this._container, 'leaflet-draw-tooltip-single');
2226
+ this._singleLineLabel = false;
2227
+ }
2228
+
2229
+ this._container.innerHTML =
2230
+ (labelText.subtext.length > 0 ? '<span class="leaflet-draw-tooltip-subtext">' + labelText.subtext + '</span>' + '<br />' : '') +
2231
+ '<span>' + labelText.text + '</span>';
2232
+
2233
+ return this;
2234
+ },
2235
+
2236
+ updatePosition: function (latlng) {
2237
+ var pos = this._map.latLngToLayerPoint(latlng),
2238
+ tooltipContainer = this._container;
2239
+
2240
+ if (this._container) {
2241
+ tooltipContainer.style.visibility = 'inherit';
2242
+ L.DomUtil.setPosition(tooltipContainer, pos);
2243
+ }
2244
+
2245
+ return this;
2246
+ },
2247
+
2248
+ showAsError: function () {
2249
+ if (this._container) {
2250
+ L.DomUtil.addClass(this._container, 'leaflet-error-draw-tooltip');
2251
+ }
2252
+ return this;
2253
+ },
2254
+
2255
+ removeError: function () {
2256
+ if (this._container) {
2257
+ L.DomUtil.removeClass(this._container, 'leaflet-error-draw-tooltip');
2258
+ }
2259
+ return this;
2260
+ }
2261
+ });
2262
+
2263
+ L.DrawToolbar = L.Toolbar.extend({
2264
+
2265
+ options: {
2266
+ polyline: {},
2267
+ polygon: {},
2268
+ rectangle: {},
2269
+ circle: {},
2270
+ marker: {}
2271
+ },
2272
+
2273
+ initialize: function (options) {
2274
+ // Ensure that the options are merged correctly since L.extend is only shallow
2275
+ for (var type in this.options) {
2276
+ if (this.options.hasOwnProperty(type)) {
2277
+ if (options[type]) {
2278
+ options[type] = L.extend({}, this.options[type], options[type]);
2279
+ }
2280
+ }
2281
+ }
2282
+
2283
+ this._toolbarClass = 'leaflet-draw-draw';
2284
+ L.Toolbar.prototype.initialize.call(this, options);
2285
+ },
2286
+
2287
+ getModeHandlers: function (map) {
2288
+ return [
2289
+ {
2290
+ enabled: this.options.polyline,
2291
+ handler: new L.Draw.Polyline(map, this.options.polyline),
2292
+ title: L.drawLocal.draw.toolbar.buttons.polyline
2293
+ },
2294
+ {
2295
+ enabled: this.options.polygon,
2296
+ handler: new L.Draw.Polygon(map, this.options.polygon),
2297
+ title: L.drawLocal.draw.toolbar.buttons.polygon
2298
+ },
2299
+ {
2300
+ enabled: this.options.rectangle,
2301
+ handler: new L.Draw.Rectangle(map, this.options.rectangle),
2302
+ title: L.drawLocal.draw.toolbar.buttons.rectangle
2303
+ },
2304
+ {
2305
+ enabled: this.options.circle,
2306
+ handler: new L.Draw.Circle(map, this.options.circle),
2307
+ title: L.drawLocal.draw.toolbar.buttons.circle
2308
+ },
2309
+ {
2310
+ enabled: this.options.marker,
2311
+ handler: new L.Draw.Marker(map, this.options.marker),
2312
+ title: L.drawLocal.draw.toolbar.buttons.marker
2313
+ }
2314
+ ];
2315
+ },
2316
+
2317
+ // Get the actions part of the toolbar
2318
+ getActions: function (handler) {
2319
+ return [
2320
+ {
2321
+ enabled: handler.deleteLastVertex,
2322
+ title: L.drawLocal.draw.toolbar.undo.title,
2323
+ text: L.drawLocal.draw.toolbar.undo.text,
2324
+ callback: handler.deleteLastVertex,
2325
+ context: handler
2326
+ },
2327
+ {
2328
+ title: L.drawLocal.draw.toolbar.actions.title,
2329
+ text: L.drawLocal.draw.toolbar.actions.text,
2330
+ callback: this.disable,
2331
+ context: this
2332
+ }
2333
+ ];
2334
+ },
2335
+
2336
+ setOptions: function (options) {
2337
+ L.setOptions(this, options);
2338
+
2339
+ for (var type in this._modes) {
2340
+ if (this._modes.hasOwnProperty(type) && options.hasOwnProperty(type)) {
2341
+ this._modes[type].handler.setOptions(options[type]);
2342
+ }
2343
+ }
2344
+ }
2345
+ });
2346
+
2347
+
2348
+ /*L.Map.mergeOptions({
2349
+ editControl: true
2350
+ });*/
2351
+
2352
+ L.EditToolbar = L.Toolbar.extend({
2353
+ options: {
2354
+ edit: {
2355
+ selectedPathOptions: {
2356
+ color: '#fe57a1', /* Hot pink all the things! */
2357
+ opacity: 0.6,
2358
+ dashArray: '10, 10',
2359
+
2360
+ fill: true,
2361
+ fillColor: '#fe57a1',
2362
+ fillOpacity: 0.1
2363
+ }
2364
+ },
2365
+ remove: {},
2366
+ featureGroup: null /* REQUIRED! TODO: perhaps if not set then all layers on the map are selectable? */
2367
+ },
2368
+
2369
+ initialize: function (options) {
2370
+ // Need to set this manually since null is an acceptable value here
2371
+ if (options.edit) {
2372
+ if (typeof options.edit.selectedPathOptions === 'undefined') {
2373
+ options.edit.selectedPathOptions = this.options.edit.selectedPathOptions;
2374
+ }
2375
+ options.edit = L.extend({}, this.options.edit, options.edit);
2376
+ }
2377
+
2378
+ if (options.remove) {
2379
+ options.remove = L.extend({}, this.options.remove, options.remove);
2380
+ }
2381
+
2382
+ this._toolbarClass = 'leaflet-draw-edit';
2383
+ L.Toolbar.prototype.initialize.call(this, options);
2384
+
2385
+ this._selectedFeatureCount = 0;
2386
+ },
2387
+
2388
+ getModeHandlers: function (map) {
2389
+ var featureGroup = this.options.featureGroup;
2390
+ return [
2391
+ {
2392
+ enabled: this.options.edit,
2393
+ handler: new L.EditToolbar.Edit(map, {
2394
+ featureGroup: featureGroup,
2395
+ selectedPathOptions: this.options.edit.selectedPathOptions
2396
+ }),
2397
+ title: L.drawLocal.edit.toolbar.buttons.edit
2398
+ },
2399
+ {
2400
+ enabled: this.options.remove,
2401
+ handler: new L.EditToolbar.Delete(map, {
2402
+ featureGroup: featureGroup
2403
+ }),
2404
+ title: L.drawLocal.edit.toolbar.buttons.remove
2405
+ }
2406
+ ];
2407
+ },
2408
+
2409
+ getActions: function () {
2410
+ return [
2411
+ {
2412
+ title: L.drawLocal.edit.toolbar.actions.save.title,
2413
+ text: L.drawLocal.edit.toolbar.actions.save.text,
2414
+ callback: this._save,
2415
+ context: this
2416
+ },
2417
+ {
2418
+ title: L.drawLocal.edit.toolbar.actions.cancel.title,
2419
+ text: L.drawLocal.edit.toolbar.actions.cancel.text,
2420
+ callback: this.disable,
2421
+ context: this
2422
+ }
2423
+ ];
2424
+ },
2425
+
2426
+ addToolbar: function (map) {
2427
+ var container = L.Toolbar.prototype.addToolbar.call(this, map);
2428
+
2429
+ this._checkDisabled();
2430
+
2431
+ this.options.featureGroup.on('layeradd layerremove', this._checkDisabled, this);
2432
+
2433
+ return container;
2434
+ },
2435
+
2436
+ removeToolbar: function () {
2437
+ this.options.featureGroup.off('layeradd layerremove', this._checkDisabled, this);
2438
+
2439
+ L.Toolbar.prototype.removeToolbar.call(this);
2440
+ },
2441
+
2442
+ disable: function () {
2443
+ if (!this.enabled()) { return; }
2444
+
2445
+ this._activeMode.handler.revertLayers();
2446
+
2447
+ L.Toolbar.prototype.disable.call(this);
2448
+ },
2449
+
2450
+ _save: function () {
2451
+ this._activeMode.handler.save();
2452
+ this._activeMode.handler.disable();
2453
+ },
2454
+
2455
+ _checkDisabled: function () {
2456
+ var featureGroup = this.options.featureGroup,
2457
+ hasLayers = featureGroup.getLayers().length !== 0,
2458
+ button;
2459
+
2460
+ if (this.options.edit) {
2461
+ button = this._modes[L.EditToolbar.Edit.TYPE].button;
2462
+
2463
+ if (hasLayers) {
2464
+ L.DomUtil.removeClass(button, 'leaflet-disabled');
2465
+ } else {
2466
+ L.DomUtil.addClass(button, 'leaflet-disabled');
2467
+ }
2468
+
2469
+ button.setAttribute(
2470
+ 'title',
2471
+ hasLayers ?
2472
+ L.drawLocal.edit.toolbar.buttons.edit
2473
+ : L.drawLocal.edit.toolbar.buttons.editDisabled
2474
+ );
2475
+ }
2476
+
2477
+ if (this.options.remove) {
2478
+ button = this._modes[L.EditToolbar.Delete.TYPE].button;
2479
+
2480
+ if (hasLayers) {
2481
+ L.DomUtil.removeClass(button, 'leaflet-disabled');
2482
+ } else {
2483
+ L.DomUtil.addClass(button, 'leaflet-disabled');
2484
+ }
2485
+
2486
+ button.setAttribute(
2487
+ 'title',
2488
+ hasLayers ?
2489
+ L.drawLocal.edit.toolbar.buttons.remove
2490
+ : L.drawLocal.edit.toolbar.buttons.removeDisabled
2491
+ );
2492
+ }
2493
+ }
2494
+ });
2495
+
2496
+
2497
+ L.EditToolbar.Edit = L.Handler.extend({
2498
+ statics: {
2499
+ TYPE: 'edit'
2500
+ },
2501
+
2502
+ includes: L.Mixin.Events,
2503
+
2504
+ initialize: function (map, options) {
2505
+ L.Handler.prototype.initialize.call(this, map);
2506
+
2507
+ // Set options to the default unless already set
2508
+ this._selectedPathOptions = options.selectedPathOptions;
2509
+
2510
+ // Store the selectable layer group for ease of access
2511
+ this._featureGroup = options.featureGroup;
2512
+
2513
+ if (!(this._featureGroup instanceof L.FeatureGroup)) {
2514
+ throw new Error('options.featureGroup must be a L.FeatureGroup');
2515
+ }
2516
+
2517
+ this._uneditedLayerProps = {};
2518
+
2519
+ // Save the type so super can fire, need to do this as cannot do this.TYPE :(
2520
+ this.type = L.EditToolbar.Edit.TYPE;
2521
+ },
2522
+
2523
+ enable: function () {
2524
+ if (this._enabled || !this._hasAvailableLayers()) {
2525
+ return;
2526
+ }
2527
+ this.fire('enabled', {handler: this.type});
2528
+ //this disable other handlers
2529
+
2530
+ this._map.fire('draw:editstart', { handler: this.type });
2531
+ //allow drawLayer to be updated before beginning edition.
2532
+
2533
+ L.Handler.prototype.enable.call(this);
2534
+ this._featureGroup
2535
+ .on('layeradd', this._enableLayerEdit, this)
2536
+ .on('layerremove', this._disableLayerEdit, this);
2537
+ },
2538
+
2539
+ disable: function () {
2540
+ if (!this._enabled) { return; }
2541
+ this._featureGroup
2542
+ .off('layeradd', this._enableLayerEdit, this)
2543
+ .off('layerremove', this._disableLayerEdit, this);
2544
+ L.Handler.prototype.disable.call(this);
2545
+ this._map.fire('draw:editstop', { handler: this.type });
2546
+ this.fire('disabled', {handler: this.type});
2547
+ },
2548
+
2549
+ addHooks: function () {
2550
+ var map = this._map;
2551
+
2552
+ if (map) {
2553
+ map.getContainer().focus();
2554
+
2555
+ this._featureGroup.eachLayer(this._enableLayerEdit, this);
2556
+
2557
+ this._tooltip = new L.Tooltip(this._map);
2558
+ this._tooltip.updateContent({
2559
+ text: L.drawLocal.edit.handlers.edit.tooltip.text,
2560
+ subtext: L.drawLocal.edit.handlers.edit.tooltip.subtext
2561
+ });
2562
+
2563
+ this._map.on('mousemove', this._onMouseMove, this);
2564
+ }
2565
+ },
2566
+
2567
+ removeHooks: function () {
2568
+ if (this._map) {
2569
+ // Clean up selected layers.
2570
+ this._featureGroup.eachLayer(this._disableLayerEdit, this);
2571
+
2572
+ // Clear the backups of the original layers
2573
+ this._uneditedLayerProps = {};
2574
+
2575
+ this._tooltip.dispose();
2576
+ this._tooltip = null;
2577
+
2578
+ this._map.off('mousemove', this._onMouseMove, this);
2579
+ }
2580
+ },
2581
+
2582
+ revertLayers: function () {
2583
+ this._featureGroup.eachLayer(function (layer) {
2584
+ this._revertLayer(layer);
2585
+ }, this);
2586
+ },
2587
+
2588
+ save: function () {
2589
+ var editedLayers = new L.LayerGroup();
2590
+ this._featureGroup.eachLayer(function (layer) {
2591
+ if (layer.edited) {
2592
+ editedLayers.addLayer(layer);
2593
+ layer.edited = false;
2594
+ }
2595
+ });
2596
+ this._map.fire('draw:edited', {layers: editedLayers});
2597
+ },
2598
+
2599
+ _backupLayer: function (layer) {
2600
+ var id = L.Util.stamp(layer);
2601
+
2602
+ if (!this._uneditedLayerProps[id]) {
2603
+ // Polyline, Polygon or Rectangle
2604
+ if (layer instanceof L.Polyline || layer instanceof L.Polygon || layer instanceof L.Rectangle) {
2605
+ this._uneditedLayerProps[id] = {
2606
+ latlngs: L.LatLngUtil.cloneLatLngs(layer.getLatLngs())
2607
+ };
2608
+ } else if (layer instanceof L.Circle) {
2609
+ this._uneditedLayerProps[id] = {
2610
+ latlng: L.LatLngUtil.cloneLatLng(layer.getLatLng()),
2611
+ radius: layer.getRadius()
2612
+ };
2613
+ } else if (layer instanceof L.Marker) { // Marker
2614
+ this._uneditedLayerProps[id] = {
2615
+ latlng: L.LatLngUtil.cloneLatLng(layer.getLatLng())
2616
+ };
2617
+ }
2618
+ }
2619
+ },
2620
+
2621
+ _revertLayer: function (layer) {
2622
+ var id = L.Util.stamp(layer);
2623
+ layer.edited = false;
2624
+ if (this._uneditedLayerProps.hasOwnProperty(id)) {
2625
+ // Polyline, Polygon or Rectangle
2626
+ if (layer instanceof L.Polyline || layer instanceof L.Polygon || layer instanceof L.Rectangle) {
2627
+ layer.setLatLngs(this._uneditedLayerProps[id].latlngs);
2628
+ } else if (layer instanceof L.Circle) {
2629
+ layer.setLatLng(this._uneditedLayerProps[id].latlng);
2630
+ layer.setRadius(this._uneditedLayerProps[id].radius);
2631
+ } else if (layer instanceof L.Marker) { // Marker
2632
+ layer.setLatLng(this._uneditedLayerProps[id].latlng);
2633
+ }
2634
+ }
2635
+ },
2636
+
2637
+ _toggleMarkerHighlight: function (marker) {
2638
+ if (!marker._icon) {
2639
+ return;
2640
+ }
2641
+ // This is quite naughty, but I don't see another way of doing it. (short of setting a new icon)
2642
+ var icon = marker._icon;
2643
+
2644
+ icon.style.display = 'none';
2645
+
2646
+ if (L.DomUtil.hasClass(icon, 'leaflet-edit-marker-selected')) {
2647
+ L.DomUtil.removeClass(icon, 'leaflet-edit-marker-selected');
2648
+ // Offset as the border will make the icon move.
2649
+ this._offsetMarker(icon, -4);
2650
+
2651
+ } else {
2652
+ L.DomUtil.addClass(icon, 'leaflet-edit-marker-selected');
2653
+ // Offset as the border will make the icon move.
2654
+ this._offsetMarker(icon, 4);
2655
+ }
2656
+
2657
+ icon.style.display = '';
2658
+ },
2659
+
2660
+ _offsetMarker: function (icon, offset) {
2661
+ var iconMarginTop = parseInt(icon.style.marginTop, 10) - offset,
2662
+ iconMarginLeft = parseInt(icon.style.marginLeft, 10) - offset;
2663
+
2664
+ icon.style.marginTop = iconMarginTop + 'px';
2665
+ icon.style.marginLeft = iconMarginLeft + 'px';
2666
+ },
2667
+
2668
+ _enableLayerEdit: function (e) {
2669
+ var layer = e.layer || e.target || e,
2670
+ isMarker = layer instanceof L.Marker,
2671
+ pathOptions;
2672
+
2673
+ // Don't do anything if this layer is a marker but doesn't have an icon. Markers
2674
+ // should usually have icons. If using Leaflet.draw with Leafler.markercluster there
2675
+ // is a chance that a marker doesn't.
2676
+ if (isMarker && !layer._icon) {
2677
+ return;
2678
+ }
2679
+
2680
+ // Back up this layer (if haven't before)
2681
+ this._backupLayer(layer);
2682
+
2683
+ // Update layer style so appears editable
2684
+ if (this._selectedPathOptions) {
2685
+ pathOptions = L.Util.extend({}, this._selectedPathOptions);
2686
+
2687
+ if (isMarker) {
2688
+ this._toggleMarkerHighlight(layer);
2689
+ } else {
2690
+ layer.options.previousOptions = L.Util.extend({ dashArray: null }, layer.options);
2691
+
2692
+ // Make sure that Polylines are not filled
2693
+ if (!(layer instanceof L.Circle) && !(layer instanceof L.Polygon) && !(layer instanceof L.Rectangle)) {
2694
+ pathOptions.fill = false;
2695
+ }
2696
+
2697
+ layer.setStyle(pathOptions);
2698
+ }
2699
+ }
2700
+
2701
+ if (isMarker) {
2702
+ layer.dragging.enable();
2703
+ layer.on('dragend', this._onMarkerDragEnd);
2704
+ } else {
2705
+ layer.editing.enable();
2706
+ }
2707
+ },
2708
+
2709
+ _disableLayerEdit: function (e) {
2710
+ var layer = e.layer || e.target || e;
2711
+ layer.edited = false;
2712
+
2713
+ // Reset layer styles to that of before select
2714
+ if (this._selectedPathOptions) {
2715
+ if (layer instanceof L.Marker) {
2716
+ this._toggleMarkerHighlight(layer);
2717
+ } else {
2718
+ // reset the layer style to what is was before being selected
2719
+ layer.setStyle(layer.options.previousOptions);
2720
+ // remove the cached options for the layer object
2721
+ delete layer.options.previousOptions;
2722
+ }
2723
+ }
2724
+
2725
+ if (layer instanceof L.Marker) {
2726
+ layer.dragging.disable();
2727
+ layer.off('dragend', this._onMarkerDragEnd, this);
2728
+ } else {
2729
+ layer.editing.disable();
2730
+ }
2731
+ },
2732
+
2733
+ _onMarkerDragEnd: function (e) {
2734
+ var layer = e.target;
2735
+ layer.edited = true;
2736
+ },
2737
+
2738
+ _onMouseMove: function (e) {
2739
+ this._tooltip.updatePosition(e.latlng);
2740
+ },
2741
+
2742
+ _hasAvailableLayers: function () {
2743
+ return this._featureGroup.getLayers().length !== 0;
2744
+ }
2745
+ });
2746
+
2747
+
2748
+ L.EditToolbar.Delete = L.Handler.extend({
2749
+ statics: {
2750
+ TYPE: 'remove' // not delete as delete is reserved in js
2751
+ },
2752
+
2753
+ includes: L.Mixin.Events,
2754
+
2755
+ initialize: function (map, options) {
2756
+ L.Handler.prototype.initialize.call(this, map);
2757
+
2758
+ L.Util.setOptions(this, options);
2759
+
2760
+ // Store the selectable layer group for ease of access
2761
+ this._deletableLayers = this.options.featureGroup;
2762
+
2763
+ if (!(this._deletableLayers instanceof L.FeatureGroup)) {
2764
+ throw new Error('options.featureGroup must be a L.FeatureGroup');
2765
+ }
2766
+
2767
+ // Save the type so super can fire, need to do this as cannot do this.TYPE :(
2768
+ this.type = L.EditToolbar.Delete.TYPE;
2769
+ },
2770
+
2771
+ enable: function () {
2772
+ if (this._enabled || !this._hasAvailableLayers()) {
2773
+ return;
2774
+ }
2775
+ this.fire('enabled', { handler: this.type});
2776
+
2777
+ this._map.fire('draw:deletestart', { handler: this.type });
2778
+
2779
+ L.Handler.prototype.enable.call(this);
2780
+
2781
+ this._deletableLayers
2782
+ .on('layeradd', this._enableLayerDelete, this)
2783
+ .on('layerremove', this._disableLayerDelete, this);
2784
+ },
2785
+
2786
+ disable: function () {
2787
+ if (!this._enabled) { return; }
2788
+
2789
+ this._deletableLayers
2790
+ .off('layeradd', this._enableLayerDelete, this)
2791
+ .off('layerremove', this._disableLayerDelete, this);
2792
+
2793
+ L.Handler.prototype.disable.call(this);
2794
+
2795
+ this._map.fire('draw:deletestop', { handler: this.type });
2796
+
2797
+ this.fire('disabled', { handler: this.type});
2798
+ },
2799
+
2800
+ addHooks: function () {
2801
+ var map = this._map;
2802
+
2803
+ if (map) {
2804
+ map.getContainer().focus();
2805
+
2806
+ this._deletableLayers.eachLayer(this._enableLayerDelete, this);
2807
+ this._deletedLayers = new L.layerGroup();
2808
+
2809
+ this._tooltip = new L.Tooltip(this._map);
2810
+ this._tooltip.updateContent({ text: L.drawLocal.edit.handlers.remove.tooltip.text });
2811
+
2812
+ this._map.on('mousemove', this._onMouseMove, this);
2813
+ }
2814
+ },
2815
+
2816
+ removeHooks: function () {
2817
+ if (this._map) {
2818
+ this._deletableLayers.eachLayer(this._disableLayerDelete, this);
2819
+ this._deletedLayers = null;
2820
+
2821
+ this._tooltip.dispose();
2822
+ this._tooltip = null;
2823
+
2824
+ this._map.off('mousemove', this._onMouseMove, this);
2825
+ }
2826
+ },
2827
+
2828
+ revertLayers: function () {
2829
+ // Iterate of the deleted layers and add them back into the featureGroup
2830
+ this._deletedLayers.eachLayer(function (layer) {
2831
+ this._deletableLayers.addLayer(layer);
2832
+ }, this);
2833
+ },
2834
+
2835
+ save: function () {
2836
+ this._map.fire('draw:deleted', { layers: this._deletedLayers });
2837
+ },
2838
+
2839
+ _enableLayerDelete: function (e) {
2840
+ var layer = e.layer || e.target || e;
2841
+
2842
+ layer.on('click', this._removeLayer, this);
2843
+ },
2844
+
2845
+ _disableLayerDelete: function (e) {
2846
+ var layer = e.layer || e.target || e;
2847
+
2848
+ layer.off('click', this._removeLayer, this);
2849
+
2850
+ // Remove from the deleted layers so we can't accidently revert if the user presses cancel
2851
+ this._deletedLayers.removeLayer(layer);
2852
+ },
2853
+
2854
+ _removeLayer: function (e) {
2855
+ var layer = e.layer || e.target || e;
2856
+
2857
+ this._deletableLayers.removeLayer(layer);
2858
+
2859
+ this._deletedLayers.addLayer(layer);
2860
+ },
2861
+
2862
+ _onMouseMove: function (e) {
2863
+ this._tooltip.updatePosition(e.latlng);
2864
+ },
2865
+
2866
+ _hasAvailableLayers: function () {
2867
+ return this._deletableLayers.getLayers().length !== 0;
2868
+ }
2869
+ });
2870
+
2871
+
2872
+ }(window, document));