leaflet-ruby 0.3.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. data/CHANGELOG.rdoc +5 -0
  2. data/LICENSE +21 -0
  3. data/README.rdoc +55 -0
  4. data/Rakefile +15 -0
  5. data/leaflet-ruby.gemspec +24 -0
  6. data/lib/leaflet-ruby.rb +18 -0
  7. data/lib/leaflet/CHANGELOG.md +181 -0
  8. data/lib/leaflet/Jakefile.js +65 -0
  9. data/lib/leaflet/LICENSE +22 -0
  10. data/lib/leaflet/README.md +32 -0
  11. data/lib/leaflet/build/build.html +243 -0
  12. data/lib/leaflet/build/build.js +79 -0
  13. data/lib/leaflet/build/deps.js +231 -0
  14. data/lib/leaflet/build/hint.js +30 -0
  15. data/lib/leaflet/build/hintrc.js +44 -0
  16. data/lib/leaflet/debug/control/control-layers.html +47 -0
  17. data/lib/leaflet/debug/control/map-control.html +29 -0
  18. data/lib/leaflet/debug/css/mobile.css +6 -0
  19. data/lib/leaflet/debug/css/screen.css +5 -0
  20. data/lib/leaflet/debug/geojson/geojson-sample.js +53 -0
  21. data/lib/leaflet/debug/geojson/geojson.html +56 -0
  22. data/lib/leaflet/debug/leaflet-include.js +120 -0
  23. data/lib/leaflet/debug/map/canvas.html +46 -0
  24. data/lib/leaflet/debug/map/map-mobile.html +42 -0
  25. data/lib/leaflet/debug/map/map.html +54 -0
  26. data/lib/leaflet/debug/map/max-bounds.html +36 -0
  27. data/lib/leaflet/debug/map/scroll.html +35 -0
  28. data/lib/leaflet/debug/map/wms-marble.html +30 -0
  29. data/lib/leaflet/debug/map/wms.html +37 -0
  30. data/lib/leaflet/debug/vector/editable.html +43 -0
  31. data/lib/leaflet/debug/vector/route.js +1 -0
  32. data/lib/leaflet/debug/vector/vector-bounds.html +69 -0
  33. data/lib/leaflet/debug/vector/vector-canvas.html +92 -0
  34. data/lib/leaflet/debug/vector/vector-mobile.html +38 -0
  35. data/lib/leaflet/debug/vector/vector-simple.html +63 -0
  36. data/lib/leaflet/debug/vector/vector.html +38 -0
  37. data/lib/leaflet/dist/images/layers.png +0 -0
  38. data/lib/leaflet/dist/images/marker-shadow.png +0 -0
  39. data/lib/leaflet/dist/images/marker.png +0 -0
  40. data/lib/leaflet/dist/images/popup-close.png +0 -0
  41. data/lib/leaflet/dist/images/zoom-in.png +0 -0
  42. data/lib/leaflet/dist/images/zoom-out.png +0 -0
  43. data/lib/leaflet/dist/leaflet-src.js +5537 -0
  44. data/lib/leaflet/dist/leaflet.css +323 -0
  45. data/lib/leaflet/dist/leaflet.ie.css +48 -0
  46. data/lib/leaflet/dist/leaflet.js +6 -0
  47. data/lib/leaflet/lib/jasmine/jasmine-html.js +182 -0
  48. data/lib/leaflet/lib/jasmine/jasmine.css +166 -0
  49. data/lib/leaflet/lib/jasmine/jasmine.js +2421 -0
  50. data/lib/leaflet/spec/runner.html +57 -0
  51. data/lib/leaflet/spec/suites/LeafletSpec.js +15 -0
  52. data/lib/leaflet/spec/suites/SpecHelper.js +28 -0
  53. data/lib/leaflet/spec/suites/core/ClassSpec.js +153 -0
  54. data/lib/leaflet/spec/suites/core/EventsSpec.js +110 -0
  55. data/lib/leaflet/spec/suites/core/UtilSpec.js +63 -0
  56. data/lib/leaflet/spec/suites/dom/DomEventSpec.js +102 -0
  57. data/lib/leaflet/spec/suites/dom/DomUtilSpec.js +59 -0
  58. data/lib/leaflet/spec/suites/geo/LatLngBoundsSpec.js +1 -0
  59. data/lib/leaflet/spec/suites/geo/LatLngSpec.js +76 -0
  60. data/lib/leaflet/spec/suites/geo/ProjectionSpec.js +42 -0
  61. data/lib/leaflet/spec/suites/geometry/BoundsSpec.js +53 -0
  62. data/lib/leaflet/spec/suites/geometry/PointSpec.js +45 -0
  63. data/lib/leaflet/spec/suites/geometry/TransformationSpec.js +19 -0
  64. data/lib/leaflet/spec/suites/layer/TileLayerSpec.js +1 -0
  65. data/lib/leaflet/spec/suites/layer/vector/PolylineGeometrySpec.js +35 -0
  66. data/lib/leaflet/spec/suites/map/MapSpec.js +1 -0
  67. data/lib/leaflet/src/Leaflet.js +33 -0
  68. data/lib/leaflet/src/control/Control.Attribution.js +66 -0
  69. data/lib/leaflet/src/control/Control.Layers.js +167 -0
  70. data/lib/leaflet/src/control/Control.Zoom.js +36 -0
  71. data/lib/leaflet/src/control/Control.js +9 -0
  72. data/lib/leaflet/src/core/Browser.js +53 -0
  73. data/lib/leaflet/src/core/Class.js +66 -0
  74. data/lib/leaflet/src/core/Events.js +62 -0
  75. data/lib/leaflet/src/core/Handler.js +29 -0
  76. data/lib/leaflet/src/core/Util.js +108 -0
  77. data/lib/leaflet/src/dom/DomEvent.DoubleTap.js +43 -0
  78. data/lib/leaflet/src/dom/DomEvent.js +154 -0
  79. data/lib/leaflet/src/dom/DomUtil.js +155 -0
  80. data/lib/leaflet/src/dom/Draggable.js +147 -0
  81. data/lib/leaflet/src/dom/transition/Transition.Native.js +102 -0
  82. data/lib/leaflet/src/dom/transition/Transition.Timer.js +126 -0
  83. data/lib/leaflet/src/dom/transition/Transition.js +28 -0
  84. data/lib/leaflet/src/geo/LatLng.js +44 -0
  85. data/lib/leaflet/src/geo/LatLngBounds.js +86 -0
  86. data/lib/leaflet/src/geo/crs/CRS.EPSG3395.js +13 -0
  87. data/lib/leaflet/src/geo/crs/CRS.EPSG3857.js +17 -0
  88. data/lib/leaflet/src/geo/crs/CRS.EPSG4326.js +7 -0
  89. data/lib/leaflet/src/geo/crs/CRS.js +17 -0
  90. data/lib/leaflet/src/geo/projection/Projection.LonLat.js +10 -0
  91. data/lib/leaflet/src/geo/projection/Projection.Mercator.js +51 -0
  92. data/lib/leaflet/src/geo/projection/Projection.SphericalMercator.js +23 -0
  93. data/lib/leaflet/src/geo/projection/Projection.js +5 -0
  94. data/lib/leaflet/src/geometry/Bounds.js +50 -0
  95. data/lib/leaflet/src/geometry/LineUtil.js +194 -0
  96. data/lib/leaflet/src/geometry/Point.js +66 -0
  97. data/lib/leaflet/src/geometry/PolyUtil.js +59 -0
  98. data/lib/leaflet/src/geometry/Transformation.js +31 -0
  99. data/lib/leaflet/src/layer/FeatureGroup.js +40 -0
  100. data/lib/leaflet/src/layer/GeoJSON.js +104 -0
  101. data/lib/leaflet/src/layer/ImageOverlay.js +58 -0
  102. data/lib/leaflet/src/layer/LayerGroup.js +74 -0
  103. data/lib/leaflet/src/layer/Popup.js +179 -0
  104. data/lib/leaflet/src/layer/marker/Icon.js +58 -0
  105. data/lib/leaflet/src/layer/marker/Marker.Drag.js +57 -0
  106. data/lib/leaflet/src/layer/marker/Marker.Popup.js +42 -0
  107. data/lib/leaflet/src/layer/marker/Marker.js +142 -0
  108. data/lib/leaflet/src/layer/tile/TileLayer.Canvas.js +41 -0
  109. data/lib/leaflet/src/layer/tile/TileLayer.WMS.js +47 -0
  110. data/lib/leaflet/src/layer/tile/TileLayer.js +310 -0
  111. data/lib/leaflet/src/layer/vector/Circle.js +68 -0
  112. data/lib/leaflet/src/layer/vector/CircleMarker.js +25 -0
  113. data/lib/leaflet/src/layer/vector/MultiPoly.js +34 -0
  114. data/lib/leaflet/src/layer/vector/Path.Popup.js +24 -0
  115. data/lib/leaflet/src/layer/vector/Path.SVG.js +138 -0
  116. data/lib/leaflet/src/layer/vector/Path.VML.js +93 -0
  117. data/lib/leaflet/src/layer/vector/Path.js +88 -0
  118. data/lib/leaflet/src/layer/vector/Polygon.js +64 -0
  119. data/lib/leaflet/src/layer/vector/Polyline.js +146 -0
  120. data/lib/leaflet/src/layer/vector/canvas/Circle.Canvas.js +18 -0
  121. data/lib/leaflet/src/layer/vector/canvas/Path.Canvas.js +146 -0
  122. data/lib/leaflet/src/layer/vector/canvas/Polygon.Canvas.js +34 -0
  123. data/lib/leaflet/src/layer/vector/canvas/Polyline.Canvas.js +27 -0
  124. data/lib/leaflet/src/map/Map.js +613 -0
  125. data/lib/leaflet/src/map/anim/Map.PanAnimation.js +70 -0
  126. data/lib/leaflet/src/map/anim/Map.ZoomAnimation.js +133 -0
  127. data/lib/leaflet/src/map/ext/Map.Control.js +50 -0
  128. data/lib/leaflet/src/map/ext/Map.Geolocation.js +86 -0
  129. data/lib/leaflet/src/map/ext/Map.Popup.js +20 -0
  130. data/lib/leaflet/src/map/handler/Map.BoxZoom.js +73 -0
  131. data/lib/leaflet/src/map/handler/Map.DoubleClickZoom.js +18 -0
  132. data/lib/leaflet/src/map/handler/Map.Drag.js +81 -0
  133. data/lib/leaflet/src/map/handler/Map.ScrollWheelZoom.js +55 -0
  134. data/lib/leaflet/src/map/handler/Map.TouchZoom.js +93 -0
  135. data/lib/zerista/CRS.Cartesian.js +20 -0
  136. data/lib/zerista/Projection.Identity.js +11 -0
  137. data/lib/zerista/zerista_layer.js +97 -0
  138. data/vendor/assets/javascripts/leaflet.js +139 -0
  139. data/vendor/assets/stylesheets/leaflet.css +1 -0
  140. data/vendor/assets/stylesheets/leaflet.ie.css +1 -0
  141. metadata +185 -0
@@ -0,0 +1,64 @@
1
+ /*
2
+ * L.Polygon is used to display polygons on a map.
3
+ */
4
+
5
+ L.Polygon = L.Polyline.extend({
6
+ options: {
7
+ fill: true
8
+ },
9
+
10
+ initialize: function (latlngs, options) {
11
+ L.Polyline.prototype.initialize.call(this, latlngs, options);
12
+
13
+ if (latlngs && (latlngs[0] instanceof Array)) {
14
+ this._latlngs = latlngs[0];
15
+ this._holes = latlngs.slice(1);
16
+ }
17
+ },
18
+
19
+ projectLatlngs: function () {
20
+ L.Polyline.prototype.projectLatlngs.call(this);
21
+
22
+ // project polygon holes points
23
+ // TODO move this logic to Polyline to get rid of duplication
24
+ this._holePoints = [];
25
+
26
+ if (!this._holes) {
27
+ return;
28
+ }
29
+
30
+ for (var i = 0, len = this._holes.length, hole; i < len; i++) {
31
+ this._holePoints[i] = [];
32
+
33
+ for (var j = 0, len2 = this._holes[i].length; j < len2; j++) {
34
+ this._holePoints[i][j] = this._map.latLngToLayerPoint(this._holes[i][j]);
35
+ }
36
+ }
37
+ },
38
+
39
+ _clipPoints: function () {
40
+ var points = this._originalPoints,
41
+ newParts = [];
42
+
43
+ this._parts = [points].concat(this._holePoints);
44
+
45
+ if (this.options.noClip) {
46
+ return;
47
+ }
48
+
49
+ for (var i = 0, len = this._parts.length; i < len; i++) {
50
+ var clipped = L.PolyUtil.clipPolygon(this._parts[i], this._map._pathViewport);
51
+ if (!clipped.length) {
52
+ continue;
53
+ }
54
+ newParts.push(clipped);
55
+ }
56
+
57
+ this._parts = newParts;
58
+ },
59
+
60
+ _getPathPartStr: function (points) {
61
+ var str = L.Polyline.prototype._getPathPartStr.call(this, points);
62
+ return str + (L.Browser.svg ? 'z' : 'x');
63
+ }
64
+ });
@@ -0,0 +1,146 @@
1
+
2
+ L.Polyline = L.Path.extend({
3
+ initialize: function (latlngs, options) {
4
+ L.Path.prototype.initialize.call(this, options);
5
+ this._latlngs = latlngs;
6
+ },
7
+
8
+ options: {
9
+ // how much to simplify the polyline on each zoom level
10
+ // more = better performance and smoother look, less = more accurate
11
+ smoothFactor: 1.0,
12
+ noClip: false,
13
+
14
+ updateOnMoveEnd: true
15
+ },
16
+
17
+ projectLatlngs: function () {
18
+ this._originalPoints = [];
19
+
20
+ for (var i = 0, len = this._latlngs.length; i < len; i++) {
21
+ this._originalPoints[i] = this._map.latLngToLayerPoint(this._latlngs[i]);
22
+ }
23
+ },
24
+
25
+ getPathString: function () {
26
+ for (var i = 0, len = this._parts.length, str = ''; i < len; i++) {
27
+ str += this._getPathPartStr(this._parts[i]);
28
+ }
29
+ return str;
30
+ },
31
+
32
+ getLatLngs: function () {
33
+ return this._latlngs;
34
+ },
35
+
36
+ setLatLngs: function (latlngs) {
37
+ this._latlngs = latlngs;
38
+ this._redraw();
39
+ return this;
40
+ },
41
+
42
+ addLatLng: function (latlng) {
43
+ this._latlngs.push(latlng);
44
+ this._redraw();
45
+ return this;
46
+ },
47
+
48
+ spliceLatLngs: function (index, howMany) {
49
+ var removed = [].splice.apply(this._latlngs, arguments);
50
+ this._redraw();
51
+ return removed;
52
+ },
53
+
54
+ closestLayerPoint: function (p) {
55
+ var minDistance = Infinity, parts = this._parts, p1, p2, minPoint = null;
56
+
57
+ for (var j = 0, jLen = parts.length; j < jLen; j++) {
58
+ var points = parts[j];
59
+ for (var i = 1, len = points.length; i < len; i++) {
60
+ p1 = points[i - 1];
61
+ p2 = points[i];
62
+ var point = L.LineUtil._sqClosestPointOnSegment(p, p1, p2);
63
+ if (point._sqDist < minDistance) {
64
+ minDistance = point._sqDist;
65
+ minPoint = point;
66
+ }
67
+ }
68
+ }
69
+ if (minPoint) {
70
+ minPoint.distance = Math.sqrt(minDistance);
71
+ }
72
+ return minPoint;
73
+ },
74
+
75
+ getBounds: function () {
76
+ var b = new L.LatLngBounds();
77
+ var latLngs = this.getLatLngs();
78
+ for (var i = 0, len = latLngs.length; i < len; i++) {
79
+ b.extend(latLngs[i]);
80
+ }
81
+ return b;
82
+ },
83
+
84
+ _getPathPartStr: function (points) {
85
+ var round = L.Path.VML;
86
+
87
+ for (var j = 0, len2 = points.length, str = '', p; j < len2; j++) {
88
+ p = points[j];
89
+ if (round) {
90
+ p._round();
91
+ }
92
+ str += (j ? 'L' : 'M') + p.x + ' ' + p.y;
93
+ }
94
+ return str;
95
+ },
96
+
97
+ _clipPoints: function () {
98
+ var points = this._originalPoints,
99
+ len = points.length,
100
+ i, k, segment;
101
+
102
+ if (this.options.noClip) {
103
+ this._parts = [points];
104
+ return;
105
+ }
106
+
107
+ this._parts = [];
108
+
109
+ var parts = this._parts,
110
+ vp = this._map._pathViewport,
111
+ lu = L.LineUtil;
112
+
113
+ for (i = 0, k = 0; i < len - 1; i++) {
114
+ segment = lu.clipSegment(points[i], points[i + 1], vp, i);
115
+ if (!segment) {
116
+ continue;
117
+ }
118
+
119
+ parts[k] = parts[k] || [];
120
+ parts[k].push(segment[0]);
121
+
122
+ // if segment goes out of screen, or it's the last one, it's the end of the line part
123
+ if ((segment[1] !== points[i + 1]) || (i === len - 2)) {
124
+ parts[k].push(segment[1]);
125
+ k++;
126
+ }
127
+ }
128
+ },
129
+
130
+ // simplify each clipped part of the polyline
131
+ _simplifyPoints: function () {
132
+ var parts = this._parts,
133
+ lu = L.LineUtil;
134
+
135
+ for (var i = 0, len = parts.length; i < len; i++) {
136
+ parts[i] = lu.simplify(parts[i], this.options.smoothFactor);
137
+ }
138
+ },
139
+
140
+ _updatePath: function () {
141
+ this._clipPoints();
142
+ this._simplifyPoints();
143
+
144
+ L.Path.prototype._updatePath.call(this);
145
+ }
146
+ });
@@ -0,0 +1,18 @@
1
+ /*
2
+ * Circle canvas specific drawing parts.
3
+ */
4
+
5
+ L.Circle.include(!L.Path.CANVAS ? {} : {
6
+ _drawPath: function () {
7
+ var p = this._point;
8
+ this._ctx.beginPath();
9
+ this._ctx.arc(p.x, p.y, this._radius, 0, Math.PI * 2);
10
+ },
11
+
12
+ _containsPoint: function (p) {
13
+ var center = this._point,
14
+ w2 = this.options.stroke ? this.options.weight / 2 : 0;
15
+
16
+ return (p.distanceTo(center) <= this._radius + w2);
17
+ }
18
+ });
@@ -0,0 +1,146 @@
1
+ /*
2
+ * Vector rendering for all browsers that support canvas.
3
+ */
4
+
5
+ L.Browser.canvas = (function () {
6
+ return !!document.createElement('canvas').getContext;
7
+ }());
8
+
9
+ L.Path = (L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? L.Path : L.Path.extend({
10
+ statics: {
11
+ //CLIP_PADDING: 0.02, // not sure if there's a need to set it to a small value
12
+ CANVAS: true,
13
+ SVG: false
14
+ },
15
+
16
+ options: {
17
+ updateOnMoveEnd: true
18
+ },
19
+
20
+ _initElements: function () {
21
+ this._map._initPathRoot();
22
+ this._ctx = this._map._canvasCtx;
23
+ },
24
+
25
+ _updateStyle: function () {
26
+ if (this.options.stroke) {
27
+ this._ctx.lineWidth = this.options.weight;
28
+ this._ctx.strokeStyle = this.options.color;
29
+ }
30
+ if (this.options.fill) {
31
+ this._ctx.fillStyle = this.options.fillColor || this.options.color;
32
+ }
33
+ },
34
+
35
+ _drawPath: function () {
36
+ var i, j, len, len2, point, drawMethod;
37
+
38
+ this._ctx.beginPath();
39
+
40
+ for (i = 0, len = this._parts.length; i < len; i++) {
41
+ for (j = 0, len2 = this._parts[i].length; j < len2; j++) {
42
+ point = this._parts[i][j];
43
+ drawMethod = (j === 0 ? 'move' : 'line') + 'To';
44
+
45
+ this._ctx[drawMethod](point.x, point.y);
46
+ }
47
+ // TODO refactor ugly hack
48
+ if (this instanceof L.Polygon) {
49
+ this._ctx.closePath();
50
+ }
51
+ }
52
+ },
53
+
54
+ _checkIfEmpty: function () {
55
+ return !this._parts.length;
56
+ },
57
+
58
+ _updatePath: function () {
59
+ if (this._checkIfEmpty()) {
60
+ return;
61
+ }
62
+
63
+ this._drawPath();
64
+
65
+ this._ctx.save();
66
+
67
+ this._updateStyle();
68
+
69
+ var opacity = this.options.opacity,
70
+ fillOpacity = this.options.fillOpacity;
71
+
72
+ if (this.options.fill) {
73
+ if (fillOpacity < 1) {
74
+ this._ctx.globalAlpha = fillOpacity;
75
+ }
76
+ this._ctx.fill();
77
+ }
78
+
79
+ if (this.options.stroke) {
80
+ if (opacity < 1) {
81
+ this._ctx.globalAlpha = opacity;
82
+ }
83
+ this._ctx.stroke();
84
+ }
85
+
86
+ this._ctx.restore();
87
+
88
+ // TODO optimization: 1 fill/stroke for all features with equal style instead of 1 for each feature
89
+ },
90
+
91
+ _initEvents: function () {
92
+ if (this.options.clickable) {
93
+ // TODO hand cursor
94
+ // TODO mouseover, mouseout, dblclick
95
+ this._map.on('click', this._onClick, this);
96
+ }
97
+ },
98
+
99
+ _onClick: function (e) {
100
+ if (this._containsPoint(e.layerPoint)) {
101
+ this.fire('click', e);
102
+ }
103
+ },
104
+
105
+ onRemove: function (map) {
106
+ map.off('viewreset', this._projectLatlngs, this);
107
+ map.off(this._updateTrigger, this._updatePath, this);
108
+ map.fire(this._updateTrigger);
109
+ }
110
+ });
111
+
112
+ L.Map.include((L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? {} : {
113
+ _initPathRoot: function () {
114
+ var root = this._pathRoot,
115
+ ctx;
116
+
117
+ if (!root) {
118
+ root = this._pathRoot = document.createElement("canvas");
119
+ root.style.position = 'absolute';
120
+ ctx = this._canvasCtx = root.getContext('2d');
121
+
122
+ ctx.lineCap = "round";
123
+ ctx.lineJoin = "round";
124
+
125
+ this._panes.overlayPane.appendChild(root);
126
+
127
+ this.on('moveend', this._updateCanvasViewport);
128
+ this._updateCanvasViewport();
129
+ }
130
+ },
131
+
132
+ _updateCanvasViewport: function () {
133
+ this._updatePathViewport();
134
+
135
+ var vp = this._pathViewport,
136
+ min = vp.min,
137
+ size = vp.max.subtract(min),
138
+ root = this._pathRoot;
139
+
140
+ //TODO check if it's works properly on mobile webkit
141
+ L.DomUtil.setPosition(root, min);
142
+ root.width = size.x;
143
+ root.height = size.y;
144
+ root.getContext('2d').translate(-min.x, -min.y);
145
+ }
146
+ });
@@ -0,0 +1,34 @@
1
+
2
+ L.Polygon.include(!L.Path.CANVAS ? {} : {
3
+ _containsPoint: function (p) {
4
+ var inside = false,
5
+ part, p1, p2,
6
+ i, j, k,
7
+ len, len2;
8
+
9
+ // TODO optimization: check if within bounds first
10
+
11
+ if (L.Polyline.prototype._containsPoint.call(this, p, true)) {
12
+ // click on polygon border
13
+ return true;
14
+ }
15
+
16
+ // ray casting algorithm for detecting if point is in polygon
17
+
18
+ for (i = 0, len = this._parts.length; i < len; i++) {
19
+ part = this._parts[i];
20
+
21
+ for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {
22
+ p1 = part[j];
23
+ p2 = part[k];
24
+
25
+ if (((p1.y > p.y) !== (p2.y > p.y)) &&
26
+ (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x)) {
27
+ inside = !inside;
28
+ }
29
+ }
30
+ }
31
+
32
+ return inside;
33
+ }
34
+ });
@@ -0,0 +1,27 @@
1
+
2
+ L.Polyline.include(!L.Path.CANVAS ? {} : {
3
+ _containsPoint: function (p, closed) {
4
+ var i, j, k, len, len2, dist, part,
5
+ w = this.options.weight / 2;
6
+
7
+ if (L.Browser.touch) {
8
+ w += 10; // polyline click tolerance on touch devices
9
+ }
10
+
11
+ for (i = 0, len = this._parts.length; i < len; i++) {
12
+ part = this._parts[i];
13
+ for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {
14
+ if (!closed && (j === 0)) {
15
+ continue;
16
+ }
17
+
18
+ dist = L.LineUtil.pointToSegmentDistance(p, part[k], part[j]);
19
+
20
+ if (dist <= w) {
21
+ return true;
22
+ }
23
+ }
24
+ }
25
+ return false;
26
+ }
27
+ });
@@ -0,0 +1,613 @@
1
+ /*
2
+ * L.Map is the central class of the API - it is used to create a map.
3
+ */
4
+
5
+ L.Map = L.Class.extend({
6
+ includes: L.Mixin.Events,
7
+
8
+ options: {
9
+ // projection
10
+ crs: L.CRS.EPSG3857 || L.CRS.EPSG4326,
11
+ scale: function (zoom) {
12
+ return 256 * Math.pow(2, zoom);
13
+ },
14
+
15
+ // state
16
+ center: null,
17
+ zoom: null,
18
+ layers: [],
19
+
20
+ // interaction
21
+ dragging: true,
22
+ touchZoom: L.Browser.touch && !L.Browser.android,
23
+ scrollWheelZoom: !L.Browser.touch,
24
+ doubleClickZoom: true,
25
+ boxZoom: true,
26
+
27
+ // controls
28
+ zoomControl: true,
29
+ attributionControl: true,
30
+
31
+ // animation
32
+ fadeAnimation: L.DomUtil.TRANSITION && !L.Browser.android,
33
+ zoomAnimation: L.DomUtil.TRANSITION && !L.Browser.android && !L.Browser.mobileOpera,
34
+
35
+ // misc
36
+ trackResize: true,
37
+ closePopupOnClick: true,
38
+ worldCopyJump: true
39
+ },
40
+
41
+
42
+ // constructor
43
+
44
+ initialize: function (id, options) { // (HTMLElement or String, Object)
45
+ L.Util.setOptions(this, options);
46
+
47
+ this._container = L.DomUtil.get(id);
48
+
49
+ if (this._container._leaflet) {
50
+ throw new Error("Map container is already initialized.");
51
+ }
52
+ this._container._leaflet = true;
53
+
54
+ this._initLayout();
55
+
56
+ if (L.DomEvent) {
57
+ this._initEvents();
58
+ if (L.Handler) {
59
+ this._initInteraction();
60
+ }
61
+ if (L.Control) {
62
+ this._initControls();
63
+ }
64
+ }
65
+
66
+ if (this.options.maxBounds) {
67
+ this.setMaxBounds(this.options.maxBounds);
68
+ }
69
+
70
+ var center = this.options.center,
71
+ zoom = this.options.zoom;
72
+
73
+ if (center !== null && zoom !== null) {
74
+ this.setView(center, zoom, true);
75
+ }
76
+
77
+ var layers = this.options.layers;
78
+ layers = (layers instanceof Array ? layers : [layers]);
79
+ this._tileLayersNum = 0;
80
+ this._initLayers(layers);
81
+ },
82
+
83
+
84
+ // public methods that modify map state
85
+
86
+ // replaced by animation-powered implementation in Map.PanAnimation.js
87
+ setView: function (center, zoom) {
88
+ // reset the map view
89
+ this._resetView(center, this._limitZoom(zoom));
90
+ return this;
91
+ },
92
+
93
+ setZoom: function (zoom) { // (Number)
94
+ return this.setView(this.getCenter(), zoom);
95
+ },
96
+
97
+ zoomIn: function () {
98
+ return this.setZoom(this._zoom + 1);
99
+ },
100
+
101
+ zoomOut: function () {
102
+ return this.setZoom(this._zoom - 1);
103
+ },
104
+
105
+ fitBounds: function (bounds) { // (LatLngBounds)
106
+ var zoom = this.getBoundsZoom(bounds);
107
+ return this.setView(bounds.getCenter(), zoom);
108
+ },
109
+
110
+ fitWorld: function () {
111
+ var sw = new L.LatLng(-60, -170),
112
+ ne = new L.LatLng(85, 179);
113
+ return this.fitBounds(new L.LatLngBounds(sw, ne));
114
+ },
115
+
116
+ panTo: function (center) { // (LatLng)
117
+ return this.setView(center, this._zoom);
118
+ },
119
+
120
+ panBy: function (offset) { // (Point)
121
+ // replaced with animated panBy in Map.Animation.js
122
+ this.fire('movestart');
123
+
124
+ this._rawPanBy(offset);
125
+
126
+ this.fire('move');
127
+ this.fire('moveend');
128
+
129
+ return this;
130
+ },
131
+
132
+ setMaxBounds: function (bounds) {
133
+ this.options.maxBounds = bounds;
134
+
135
+ if (!bounds) {
136
+ this._boundsMinZoom = null;
137
+ return this;
138
+ }
139
+
140
+ var minZoom = this.getBoundsZoom(bounds, true);
141
+
142
+ this._boundsMinZoom = minZoom;
143
+
144
+ if (this._loaded) {
145
+ if (this._zoom < minZoom) {
146
+ this.setView(bounds.getCenter(), minZoom);
147
+ } else {
148
+ this.panInsideBounds(bounds);
149
+ }
150
+ }
151
+ return this;
152
+ },
153
+
154
+ panInsideBounds: function (bounds) {
155
+ var viewBounds = this.getBounds(),
156
+ viewSw = this.project(viewBounds.getSouthWest()),
157
+ viewNe = this.project(viewBounds.getNorthEast()),
158
+ sw = this.project(bounds.getSouthWest()),
159
+ ne = this.project(bounds.getNorthEast()),
160
+ dx = 0,
161
+ dy = 0;
162
+
163
+ if (viewNe.y < ne.y) { // north
164
+ dy = ne.y - viewNe.y;
165
+ }
166
+ if (viewNe.x > ne.x) { // east
167
+ dx = ne.x - viewNe.x;
168
+ }
169
+ if (viewSw.y > sw.y) { // south
170
+ dy = sw.y - viewSw.y;
171
+ }
172
+ if (viewSw.x < sw.x) { // west
173
+ dx = sw.x - viewSw.x;
174
+ }
175
+
176
+ return this.panBy(new L.Point(dx, dy, true));
177
+ },
178
+
179
+ addLayer: function (layer, insertAtTheTop) {
180
+ var id = L.Util.stamp(layer);
181
+
182
+ if (this._layers[id]) {
183
+ return this;
184
+ }
185
+
186
+ this._layers[id] = layer;
187
+
188
+ if (layer.options && !isNaN(layer.options.maxZoom)) {
189
+ this._layersMaxZoom = Math.max(this._layersMaxZoom || 0, layer.options.maxZoom);
190
+ }
191
+ if (layer.options && !isNaN(layer.options.minZoom)) {
192
+ this._layersMinZoom = Math.min(this._layersMinZoom || Infinity, layer.options.minZoom);
193
+ }
194
+ //TODO getMaxZoom, getMinZoom in ILayer (instead of options)
195
+
196
+ if (this.options.zoomAnimation && L.TileLayer && (layer instanceof L.TileLayer)) {
197
+ this._tileLayersNum++;
198
+ layer.on('load', this._onTileLayerLoad, this);
199
+ }
200
+ if (this.attributionControl && layer.getAttribution) {
201
+ this.attributionControl.addAttribution(layer.getAttribution());
202
+ }
203
+
204
+ var onMapLoad = function () {
205
+ layer.onAdd(this, insertAtTheTop);
206
+ this.fire('layeradd', {layer: layer});
207
+ };
208
+
209
+ if (this._loaded) {
210
+ onMapLoad.call(this);
211
+ } else {
212
+ this.on('load', onMapLoad, this);
213
+ }
214
+
215
+ return this;
216
+ },
217
+
218
+ removeLayer: function (layer) {
219
+ var id = L.Util.stamp(layer);
220
+
221
+ if (this._layers[id]) {
222
+ layer.onRemove(this);
223
+ delete this._layers[id];
224
+
225
+ if (this.options.zoomAnimation && L.TileLayer && (layer instanceof L.TileLayer)) {
226
+ this._tileLayersNum--;
227
+ layer.off('load', this._onTileLayerLoad, this);
228
+ }
229
+ if (this.attributionControl && layer.getAttribution) {
230
+ this.attributionControl.removeAttribution(layer.getAttribution());
231
+ }
232
+
233
+ this.fire('layerremove', {layer: layer});
234
+ }
235
+ return this;
236
+ },
237
+
238
+ hasLayer: function (layer) {
239
+ var id = L.Util.stamp(layer);
240
+ return this._layers.hasOwnProperty(id);
241
+ },
242
+
243
+ invalidateSize: function () {
244
+ var oldSize = this.getSize();
245
+
246
+ this._sizeChanged = true;
247
+
248
+ if (this.options.maxBounds) {
249
+ this.setMaxBounds(this.options.maxBounds);
250
+ }
251
+
252
+ if (!this._loaded) {
253
+ return this;
254
+ }
255
+
256
+ this._rawPanBy(oldSize.subtract(this.getSize()).divideBy(2));
257
+
258
+ this.fire('move');
259
+
260
+ clearTimeout(this._sizeTimer);
261
+ this._sizeTimer = setTimeout(L.Util.bind(function () {
262
+ this.fire('moveend');
263
+ }, this), 200);
264
+
265
+ return this;
266
+ },
267
+
268
+
269
+ // public methods for getting map state
270
+
271
+ getCenter: function (unbounded) { // (Boolean)
272
+ var viewHalf = this.getSize().divideBy(2),
273
+ centerPoint = this._getTopLeftPoint().add(viewHalf);
274
+ return this.unproject(centerPoint, this._zoom, unbounded);
275
+ },
276
+
277
+ getZoom: function () {
278
+ return this._zoom;
279
+ },
280
+
281
+ getBounds: function () {
282
+ var bounds = this.getPixelBounds(),
283
+ sw = this.unproject(new L.Point(bounds.min.x, bounds.max.y), this._zoom, true),
284
+ ne = this.unproject(new L.Point(bounds.max.x, bounds.min.y), this._zoom, true);
285
+ return new L.LatLngBounds(sw, ne);
286
+ },
287
+
288
+ getMinZoom: function () {
289
+ var z1 = this.options.minZoom || 0,
290
+ z2 = this._layersMinZoom || 0,
291
+ z3 = this._boundsMinZoom || 0;
292
+
293
+ return Math.max(z1, z2, z3);
294
+ },
295
+
296
+ getMaxZoom: function () {
297
+ var z1 = isNaN(this.options.maxZoom) ? Infinity : this.options.maxZoom,
298
+ z2 = this._layersMaxZoom || Infinity;
299
+
300
+ return Math.min(z1, z2);
301
+ },
302
+
303
+ getBoundsZoom: function (bounds, inside) { // (LatLngBounds)
304
+ var size = this.getSize(),
305
+ zoom = this.options.minZoom || 0,
306
+ maxZoom = this.getMaxZoom(),
307
+ ne = bounds.getNorthEast(),
308
+ sw = bounds.getSouthWest(),
309
+ boundsSize,
310
+ nePoint,
311
+ swPoint,
312
+ zoomNotFound = true;
313
+
314
+ if (inside) {
315
+ zoom--;
316
+ }
317
+
318
+ do {
319
+ zoom++;
320
+ nePoint = this.project(ne, zoom);
321
+ swPoint = this.project(sw, zoom);
322
+ boundsSize = new L.Point(nePoint.x - swPoint.x, swPoint.y - nePoint.y);
323
+
324
+ if (!inside) {
325
+ zoomNotFound = (boundsSize.x <= size.x) && (boundsSize.y <= size.y);
326
+ } else {
327
+ zoomNotFound = (boundsSize.x < size.x) || (boundsSize.y < size.y);
328
+ }
329
+ } while (zoomNotFound && (zoom <= maxZoom));
330
+
331
+ if (zoomNotFound && inside) {
332
+ return null;
333
+ }
334
+
335
+ return inside ? zoom : zoom - 1;
336
+ },
337
+
338
+ getSize: function () {
339
+ if (!this._size || this._sizeChanged) {
340
+ this._size = new L.Point(this._container.clientWidth, this._container.clientHeight);
341
+ this._sizeChanged = false;
342
+ }
343
+ return this._size;
344
+ },
345
+
346
+ getPixelBounds: function () {
347
+ var topLeftPoint = this._getTopLeftPoint(),
348
+ size = this.getSize();
349
+ return new L.Bounds(topLeftPoint, topLeftPoint.add(size));
350
+ },
351
+
352
+ getPixelOrigin: function () {
353
+ return this._initialTopLeftPoint;
354
+ },
355
+
356
+ getPanes: function () {
357
+ return this._panes;
358
+ },
359
+
360
+
361
+ // conversion methods
362
+
363
+ mouseEventToContainerPoint: function (e) { // (MouseEvent)
364
+ return L.DomEvent.getMousePosition(e, this._container);
365
+ },
366
+
367
+ mouseEventToLayerPoint: function (e) { // (MouseEvent)
368
+ return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(e));
369
+ },
370
+
371
+ mouseEventToLatLng: function (e) { // (MouseEvent)
372
+ return this.layerPointToLatLng(this.mouseEventToLayerPoint(e));
373
+ },
374
+
375
+ containerPointToLayerPoint: function (point) { // (Point)
376
+ return point.subtract(L.DomUtil.getPosition(this._mapPane));
377
+ },
378
+
379
+ layerPointToContainerPoint: function (point) { // (Point)
380
+ return point.add(L.DomUtil.getPosition(this._mapPane));
381
+ },
382
+
383
+ layerPointToLatLng: function (point) { // (Point)
384
+ return this.unproject(point.add(this._initialTopLeftPoint));
385
+ },
386
+
387
+ latLngToLayerPoint: function (latlng) { // (LatLng)
388
+ return this.project(latlng)._round()._subtract(this._initialTopLeftPoint);
389
+ },
390
+
391
+ project: function (latlng, zoom) { // (LatLng[, Number]) -> Point
392
+ zoom = (typeof zoom === 'undefined' ? this._zoom : zoom);
393
+ return this.options.crs.latLngToPoint(latlng, this.options.scale(zoom));
394
+ },
395
+
396
+ unproject: function (point, zoom, unbounded) { // (Point[, Number, Boolean]) -> LatLng
397
+ zoom = (typeof zoom === 'undefined' ? this._zoom : zoom);
398
+ return this.options.crs.pointToLatLng(point, this.options.scale(zoom), unbounded);
399
+ },
400
+
401
+
402
+ // private methods that modify map state
403
+
404
+ _initLayout: function () {
405
+ var container = this._container;
406
+
407
+ container.innerHTML = '';
408
+
409
+ container.className += ' leaflet-container';
410
+
411
+ if (this.options.fadeAnimation) {
412
+ container.className += ' leaflet-fade-anim';
413
+ }
414
+
415
+ var position = L.DomUtil.getStyle(container, 'position');
416
+ if (position !== 'absolute' && position !== 'relative') {
417
+ container.style.position = 'relative';
418
+ }
419
+
420
+ this._initPanes();
421
+
422
+ if (this._initControlPos) {
423
+ this._initControlPos();
424
+ }
425
+ },
426
+
427
+ _initPanes: function () {
428
+ var panes = this._panes = {};
429
+
430
+ this._mapPane = panes.mapPane = this._createPane('leaflet-map-pane', this._container);
431
+
432
+ this._tilePane = panes.tilePane = this._createPane('leaflet-tile-pane', this._mapPane);
433
+ this._objectsPane = panes.objectsPane = this._createPane('leaflet-objects-pane', this._mapPane);
434
+
435
+ panes.shadowPane = this._createPane('leaflet-shadow-pane');
436
+ panes.overlayPane = this._createPane('leaflet-overlay-pane');
437
+ panes.markerPane = this._createPane('leaflet-marker-pane');
438
+ panes.popupPane = this._createPane('leaflet-popup-pane');
439
+ },
440
+
441
+ _createPane: function (className, container) {
442
+ return L.DomUtil.create('div', className, container || this._objectsPane);
443
+ },
444
+
445
+ _resetView: function (center, zoom, preserveMapOffset, afterZoomAnim) {
446
+ var zoomChanged = (this._zoom !== zoom);
447
+
448
+ if (!afterZoomAnim) {
449
+ this.fire('movestart');
450
+
451
+ if (zoomChanged) {
452
+ this.fire('zoomstart');
453
+ }
454
+ }
455
+
456
+ this._zoom = zoom;
457
+
458
+ this._initialTopLeftPoint = this._getNewTopLeftPoint(center);
459
+
460
+ if (!preserveMapOffset) {
461
+ L.DomUtil.setPosition(this._mapPane, new L.Point(0, 0));
462
+ } else {
463
+ var offset = L.DomUtil.getPosition(this._mapPane);
464
+ this._initialTopLeftPoint._add(offset);
465
+ }
466
+
467
+ this._tileLayersToLoad = this._tileLayersNum;
468
+ this.fire('viewreset', {hard: !preserveMapOffset});
469
+
470
+ this.fire('move');
471
+ if (zoomChanged || afterZoomAnim) {
472
+ this.fire('zoomend');
473
+ }
474
+ this.fire('moveend');
475
+
476
+ if (!this._loaded) {
477
+ this._loaded = true;
478
+ this.fire('load');
479
+ }
480
+ },
481
+
482
+ _initLayers: function (layers) {
483
+ this._layers = {};
484
+
485
+ var i, len;
486
+
487
+ for (i = 0, len = layers.length; i < len; i++) {
488
+ this.addLayer(layers[i]);
489
+ }
490
+ },
491
+
492
+ _initControls: function () {
493
+ if (this.options.zoomControl) {
494
+ this.addControl(new L.Control.Zoom());
495
+ }
496
+ if (this.options.attributionControl) {
497
+ this.attributionControl = new L.Control.Attribution();
498
+ this.addControl(this.attributionControl);
499
+ }
500
+ },
501
+
502
+ _rawPanBy: function (offset) {
503
+ var mapPaneOffset = L.DomUtil.getPosition(this._mapPane);
504
+ L.DomUtil.setPosition(this._mapPane, mapPaneOffset.subtract(offset));
505
+ },
506
+
507
+
508
+ // map events
509
+
510
+ _initEvents: function () {
511
+ L.DomEvent.addListener(this._container, 'click', this._onMouseClick, this);
512
+
513
+ var events = ['dblclick', 'mousedown', 'mouseenter', 'mouseleave', 'mousemove', 'contextmenu'];
514
+
515
+ var i, len;
516
+
517
+ for (i = 0, len = events.length; i < len; i++) {
518
+ L.DomEvent.addListener(this._container, events[i], this._fireMouseEvent, this);
519
+ }
520
+
521
+ if (this.options.trackResize) {
522
+ L.DomEvent.addListener(window, 'resize', this._onResize, this);
523
+ }
524
+ },
525
+
526
+ _onResize: function () {
527
+ L.Util.requestAnimFrame(this.invalidateSize, this, false, this._container);
528
+ },
529
+
530
+ _onMouseClick: function (e) {
531
+ if (!this._loaded || (this.dragging && this.dragging.moved())) {
532
+ return;
533
+ }
534
+
535
+ this.fire('pre' + e.type);
536
+ this._fireMouseEvent(e);
537
+ },
538
+
539
+ _fireMouseEvent: function (e) {
540
+ if (!this._loaded) {
541
+ return;
542
+ }
543
+
544
+ var type = e.type;
545
+ type = (type === 'mouseenter' ? 'mouseover' : (type === 'mouseleave' ? 'mouseout' : type));
546
+
547
+ if (!this.hasEventListeners(type)) {
548
+ return;
549
+ }
550
+
551
+ if (type === 'contextmenu') {
552
+ L.DomEvent.preventDefault(e);
553
+ }
554
+
555
+ this.fire(type, {
556
+ latlng: this.mouseEventToLatLng(e),
557
+ layerPoint: this.mouseEventToLayerPoint(e)
558
+ });
559
+ },
560
+
561
+ _initInteraction: function () {
562
+ var handlers = {
563
+ dragging: L.Map.Drag,
564
+ touchZoom: L.Map.TouchZoom,
565
+ doubleClickZoom: L.Map.DoubleClickZoom,
566
+ scrollWheelZoom: L.Map.ScrollWheelZoom,
567
+ boxZoom: L.Map.BoxZoom
568
+ };
569
+
570
+ var i;
571
+ for (i in handlers) {
572
+ if (handlers.hasOwnProperty(i) && handlers[i]) {
573
+ this[i] = new handlers[i](this);
574
+ if (this.options[i]) {
575
+ this[i].enable();
576
+ }
577
+ // TODO move enabling to handler contructor
578
+ }
579
+ }
580
+ },
581
+
582
+ _onTileLayerLoad: function () {
583
+ // clear scaled tiles after all new tiles are loaded (for performance)
584
+ this._tileLayersToLoad--;
585
+ if (this._tileLayersNum && !this._tileLayersToLoad && this._tileBg) {
586
+ clearTimeout(this._clearTileBgTimer);
587
+ this._clearTileBgTimer = setTimeout(L.Util.bind(this._clearTileBg, this), 500);
588
+ }
589
+ },
590
+
591
+
592
+ // private methods for getting map state
593
+
594
+ _getTopLeftPoint: function () {
595
+ if (!this._loaded) {
596
+ throw new Error('Set map center and zoom first.');
597
+ }
598
+
599
+ var offset = L.DomUtil.getPosition(this._mapPane);
600
+ return this._initialTopLeftPoint.subtract(offset);
601
+ },
602
+
603
+ _getNewTopLeftPoint: function (center) {
604
+ var viewHalf = this.getSize().divideBy(2);
605
+ return this.project(center).subtract(viewHalf).round();
606
+ },
607
+
608
+ _limitZoom: function (zoom) {
609
+ var min = this.getMinZoom();
610
+ var max = this.getMaxZoom();
611
+ return Math.max(min, Math.min(max, zoom));
612
+ }
613
+ });