leaflet-js 0.6.beta4

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 (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));