leaflet-js 0.6.beta4

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