leaflet_helper 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ff792cd61366c579ade93b826b7fc0102747b683
4
- data.tar.gz: 5a0752f2db7fb3c7e54185f2c6a260a6ac3b731e
3
+ metadata.gz: 488d8a802796c5734cffa8de7c511710eee778bb
4
+ data.tar.gz: 1ad0b5f48e8b9ece129e03fbdfb0330a1c911dbd
5
5
  SHA512:
6
- metadata.gz: bd17fda3735424b865e735903708c2fa5149221927fdc151bce5da526b1e49e5658cda1211f10a0c97811b525f4a83033cde7688c5af87d6930e01fc8f6e8b73
7
- data.tar.gz: 84aaec46fac3bf5d900255a9cf887f0e2e943fb14c6130ee70d27fd4bab3a78ed3e63853bd1dd83bd115e42e10562f4a9d2e31ee215a639cbc38d8c0ffacdbdd
6
+ metadata.gz: fdfc4ee014f893b856320347f885dddeba516ae74c9c73084eeb9c2314e6b3d928d7ed092625727dcd49b85d5cec6b145d4af4b7985d0151b7316d21c130e749
7
+ data.tar.gz: b18c32e4dbd453d0debe4ac1f847bd28caed3db760795150ae16bd035ce6f1ecb2478fdf5d1520d19483274a12bc219dc2e4b9924127b5e979b019bbae5ae34f
data/README.md CHANGED
@@ -8,22 +8,27 @@ do this:
8
8
  gem which leaflet_helper
9
9
  ```
10
10
 
11
- The `cd` to the root directory of the gem. There you will find a subdirectory named `example` in
11
+ Then `cd` to the root directory of the gem. There you will find a subdirectory named `example` in
12
12
  which there is a simple Sinatra-based web application that demonstrates how to use this gem.
13
13
 
14
14
  ## Recent Changes
15
15
 
16
- ### v0.0.7
16
+ ### v0.0.9 - working
17
+
18
+ * working on custom icons and icon coloring and other bells and cat calls
19
+
20
+ ### v0.0.8 - released
21
+
22
+ * Added basic clusters using the leaflet plugin markercluster
23
+ * refactored some code
24
+
25
+ ### v0.0.7 - released
17
26
 
18
27
  * Added StringTemplate class
19
28
  Reused the regex from @redpist easy_template gem
20
29
 
21
30
  * Fixed typo in ManageMarkers#remove - fat fingered a p[ when all I wanted was a [
22
31
 
23
- ### v0.0.6 - released
24
-
25
- * Added ManageMarkers class
26
- A singleton class that manages an array of hash markers to be applied on top of a map
27
32
 
28
33
  ## Installation
29
34
 
@@ -61,17 +66,32 @@ the 'layout.haml' file might look like this:
61
66
  ```ruby
62
67
  %html
63
68
  %head
64
- = LeafletHelper::L.init
69
+ = LeafletHelper::L.init(options)
65
70
  ```
66
71
 
67
72
  #### options
68
73
 
69
- The 'options' is a hash. It is unused.
74
+ The 'options' is a hash. It defaults to:
75
+
76
+ ```ruby
77
+ {
78
+ openstreetmap: true, # either Open Street Maps or
79
+ mapbox: false, # Mapbox.com is used as the map tile provider; not both
80
+ markers: false, # set to true to make use of markers on top of maps
81
+ cluster: false, # set to true to load the markercluster plugin
82
+ latitude: AREA51.latitude, # default map center
83
+ longitude: AREA51.longitude, # default map center
84
+ zoom: 9,
85
+ min_zoom: 2,
86
+ max_zoom: 22
87
+ }
88
+
89
+ ```
70
90
 
71
91
 
72
92
  ### LeafletHelper::L.place_map_here(id='map', options={})
73
93
 
74
- The 'place_map_here' method is used to insert the HTML "<div>" tag into the
94
+ The 'place_map_here' method is used to insert the HTML `<div>` tag into the
75
95
  body of a webpage. This is the HTML container which will host the map image
76
96
  managed by the LeafletJS library. If is possible to have several map images
77
97
  displayed on the same webpage; HOWEVER, each map image MUST have a different
@@ -89,19 +109,19 @@ Defaults:
89
109
 
90
110
  ```ruby
91
111
  o = {
92
- style: "width: 800px; height: 400px"
112
+ style: "width: 1200px; height: 400px"
93
113
  }.merge(options)
94
114
  ```
95
115
 
96
116
  Of course you could just use some CSS to add anything you want. But if you
97
- are an inline kinda programmer then the options are for you.
117
+ are an inline kinda UI/UX newbie then the options are for you.
98
118
 
99
119
  ### LeafletHelper::L.show_map(id="map", options={})
100
120
 
101
121
  This method is used at the end of the body component of the HTML webpage. Why? you
102
122
  ask. Because thats how we did it in the old days to make sure that the entire webpage
103
123
  was loaded before doing stuff on it. You hotshot javascripters know how its done
104
- the "right" way. I'm sure you have a pull-request already to go to help out us
124
+ the "right" way. I'm sure you have a pull-request ready to go to help out us
105
125
  old back-end geezers.
106
126
 
107
127
  This method generates javascript source code that also includes the same javascript that
@@ -118,184 +138,25 @@ library.
118
138
  Defaults:
119
139
 
120
140
  ```ruby
121
- o = {
122
- latitude: AREA51.latitude,
123
- longitude: AREA51.longitude,
124
- zoom: 9,
125
- min_zoom: 2,
126
- max_zoom: 22
127
- }.merge(options)
128
- ```
129
-
130
- These options are primarily for the 'setView' LeafletJS method. That method
131
- establishes the location (latitude, longitude) at which the map is cenered. It
132
- also establishs the current 'zoom' value and the minimum and maximum values for
133
- which the zoom value can take.
134
-
135
-
136
- ### LeafletHelper::L.set_view(id='map', options={})
137
-
138
- The javascript source code that this method generates moves an existing map
139
- image to be centered at a specific latitude and longitude with a given zoom level.
140
-
141
- #### id
142
-
143
- Yep, its a string that uniquely identifies the HTML `<div>` component
144
- that holds the generated map graphic managed by the LeafletJS javascript
145
- library.
146
-
147
- #### options
148
-
149
- Defaults:
150
-
151
- ```ruby
152
- o = {
153
- latitude: AREA51.latitude,
154
- longitude: AREA51.longitude,
155
- zoom: 9
156
- }.merge(options)
157
- ```
158
-
159
- ### LeafletHelper::L.add_openstreetmap_layer(id="map", options={})
160
-
161
- The LeafletJS library by itself has no dataset - no roads, streets features etc. In
162
- order to see that kind of stuff a "tile" layer - a zoomable set of images - needs to be
163
- added. The most common and easiest to use free open source creative commons licensed
164
- dataset is from the Open Street Map project.
165
-
166
- This method adds the Open Street Map dataset tiles as a layer on the LeafletJS-managed
167
- map image.
168
-
169
- Other tile datasets are available such as those from the mapbox.com project. (See bolow)
170
-
171
- #### id
172
-
173
- Yep, its a string that uniquely identifies the HTML `<div>` component
174
- that holds the generated map graphic managed by the LeafletJS javascript
175
- library.
176
-
177
- #### options
178
-
179
- Defaults:
180
-
181
- ```ruby
182
- o = {
183
- latitude: AREA51.latitude,
184
- longitude: AREA51.longitude,
185
- zoom: 9,
186
- min_zoom: 2,
187
- max_zoom: 22
188
- }.merge(options)
141
+ o = @@defaults.merge({
142
+ id: id,
143
+ map_name: get_map_name(id),
144
+ route: "#{id}/markers"
145
+ }.merge(options))
189
146
  ```
190
147
 
191
148
 
192
- ### LeafletHelper::L.add_mapbox_layer(id="map", options={})
193
-
194
- As mentioned above in the discussion about Open Street Map, LeafletJS does not come
195
- with image tiles. These must be provided from somewhere else. The Open Street Map has a
196
- good set of vector-oriented images of streets and areas. It has no actual images
197
- such as provided by satilites. These kinds of images can be obtained via the
198
- Mapbox.com project.
149
+ ## System Environment Variables
199
150
 
200
- In order to use Mapbox images you must have an account on mapbox.com. There is a nice
201
- developer friendly zero dollar plan. Other plans for commerical use are reasoniblity priced.
151
+ If you are going to use `mapbox.com` as a map tile provider you will need an account on that service.
202
152
 
203
- With an account on mapbox.com you have access to their image tiles for use with the LeafletJS
204
- library.
205
-
206
- The following system environment variables can be used with this capability:
207
-
208
- ```
209
- MAPBOX_URL
210
- MAPBOX_USER
211
- MAPBOX_STYLE_ID
212
- MAPBOX_ACCESS_TOKEN
213
- ```
214
-
215
- You can either provide the full URL for you mapbox project's images or you can
216
- provide just the pieces that make up the URL - the user, style_id and access_token.
217
-
218
- #### id
219
-
220
- Yep, its a string that uniquely identifies the HTML `<div>` component
221
- that holds the generated map graphic managed by the LeafletJS javascript
222
- library.
223
-
224
- #### options
225
-
226
- Defaults:
227
-
228
- ```ruby
229
- o = {
230
- url: ENV['MAPBOX_URL'] || "https://api.mapbox.com/styles/v1/{mbUser}/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}",
231
- mapbox_user: ENV['MAPBOX_USER'] || "your.mapbox.user.account",
232
- style_id: ENV['MAPBOX_STYLE_ID'] || "your.mapbox.project.id",
233
- access_token: ENV['MAPBOX_ACCESS_TOKEN'] || "your.mapbox.access.token",
234
- attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com">Mapbox</a>',
235
- zoom: 9,
236
- min_zoom: 2,
237
- max_zoom: 22
238
- }.merge(options)
239
- ```
240
-
241
-
242
- ### LeafletHelper::L.add_support_for_markers(id="map", options={})
243
-
244
- While being able to show a map image on a webpage, zoom it and move it around (called panning),
245
- it is much more fun if you can put actionable markers on top of the map. That is what this
246
- method does. It injects the javascript code that makes the callback to get the "markers"
247
- for display upon the map. The callback is generated everytime the map image changes either by
248
- zoom or by pan.
249
-
250
- The markers are provided as a JSON object. The object is an array of hashes. Each hash defines one marker.
251
-
252
-
253
-
254
- #### id
255
-
256
- Yep, its a string that uniquely identifies the HTML `<div>` component
257
- that holds the generated map graphic managed by the LeafletJS javascript
258
- library.
259
-
260
- The only option that is necessary is the 'route' - the place to do an HTTP GET
261
- to receive a JSON string of markers.
262
-
263
- #### options
264
-
265
- Defaults:
266
-
267
- ```ruby
268
- o = {
269
- route: "#{id}/markers"
270
- }.merge(options)
271
- ```
272
-
273
- Note that the 'route' default is setup to easily match a Sinatra block like:
274
-
275
- ```ruby
276
- get '/:map_id/markers' do |map_id|
277
- content-type :json
278
- $array_of_marker_hashes[map_id].to_json
279
- end
280
- ```
281
-
282
- For now a marker hash looks like this:
283
-
284
- ```ruby
285
- {
286
- "name": "Area 51",
287
- "lon": AREA51.longitude,
288
- "lat": AREA51.latitude,
289
- "details": "A good place to buy used flying saucers."
290
- }
291
- ```
153
+ The following system environment variables are used in loading your sceen from mapbox.com:
292
154
 
293
- The marker when clicked shows a popup window on the map image. The "name" component is at
294
- the top of the popup in an `<h3>` wrapper. The "lat" and "lon" elements allow LeafletJS to
295
- place the marker at the correct location on the map image.
155
+ * MAPBOX_URL
156
+ * MAPBOX_USER
157
+ * MAPBOX_STYLE_ID
158
+ * MAPBOX_ACCESS_TOKEN
296
159
 
297
- The "details" component can be any combination of HTML that you want. In one applicaton I have
298
- that makes use of the LeafletHelper library I show thumbnails of images as part of the popup.
299
160
 
300
161
  ## Development
301
162
 
data/example/Gemfile CHANGED
@@ -12,4 +12,3 @@ gem 'sinatra', require: 'sinatra/base' # Classy web-development dressed in a DS
12
12
  gem 'sinatra-partial' # A sinatra extension for render partials.
13
13
  gem 'haml' # An elegant, structured (X)HTML/XML templating engine.
14
14
  gem 'puma' # Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack application
15
-
data/example/Gemfile.lock CHANGED
@@ -3,7 +3,7 @@ GEM
3
3
  specs:
4
4
  haml (4.0.7)
5
5
  tilt
6
- leaflet_helper (0.0.6)
6
+ leaflet_helper (0.0.8)
7
7
  puma (3.4.0)
8
8
  rack (1.6.4)
9
9
  rack-protection (1.5.3)
data/example/app.rb CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  require 'leaflet_helper'
9
9
 
10
- $markers = Hash.new(LeafletHelper::ManageMarkers.new)
10
+ $markers = LeafletHelper::ManageMarkers.new
11
11
 
12
12
  module TestData
13
13
 
@@ -50,6 +50,19 @@ module TestData
50
50
 
51
51
  end # module TestData
52
52
 
53
+ # Generate a consistent set of test markers
54
+ $markers.clear
55
+ 30.times do |x|
56
+ code_word = TestData.get_random_codeword
57
+ location = TestData.get_random_location
58
+ $markers.add id: code_word,
59
+ lat: location['lat'],
60
+ lon: location['lon'],
61
+ html: <<~EOS
62
+ <h3>Crash ##{x}</h3>
63
+ <p>During #{code_word} rehearsals, programmer error resulted in an unexpected hard landing at this location</p>
64
+ EOS
65
+ end
53
66
 
54
67
 
55
68
  require 'pathname'
@@ -112,19 +125,7 @@ module APP
112
125
  # changed a new set of markers is generated.
113
126
  get '/:map_id/markers' do |map_id|
114
127
  content_type :json
115
- $markers[map_id].clear
116
- (rand(10)+1).times do |x|
117
- code_word = TestData.get_random_codeword
118
- location = TestData.get_random_location
119
- $markers[map_id].add id: code_word,
120
- lat: location['lat'],
121
- lon: location['lon'],
122
- html: <<~EOS
123
- <h3>Crash ##{x}</h3>
124
- <p>During #{code_word} rehearsals, programmer error resulted in an unexpected hard landing at this location</p>
125
- EOS
126
- end
127
- $markers[map_id].to_json
128
+ $markers.to_json
128
129
  end
129
130
 
130
131
 
@@ -3,7 +3,9 @@
3
3
  %html
4
4
  %head
5
5
  %title Application by VanHoozer
6
- = LeafletHelper::L.init
6
+ = LeafletHelper::L.init({ openstreetmap: true, mapbox: false, markers: true, cluster: true })
7
+
8
+
7
9
  %body
8
10
 
9
11
  #logo_header
@@ -18,8 +20,4 @@
18
20
  #footer
19
21
  = partial :footer
20
22
 
21
- - map_id = 'my_wonderful_map'
22
- - map_options = { latitude: 37.235, longitude: -115.811111, min_zoom: 2, max_zoom: 18}
23
- = LeafletHelper::L.show_map(map_id, map_options)
24
- = LeafletHelper::L.add_openstreetmap_layer(map_id, map_options)
25
- = LeafletHelper::L.add_support_for_markers(map_id, route: "#{map_id}/markers")
23
+ = LeafletHelper::L.show_map('my_wonderful_map', { route: "my_wonderful_map/markers" })
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "leaflet_helper"
7
- spec.version = '0.0.7'
7
+ spec.version = '0.0.8'
8
8
  spec.authors = ["Dewayne VanHoozer"]
9
9
  spec.email = ["dvanhoozer@gmail.com"]
10
10
 
@@ -0,0 +1,163 @@
1
+ # l.rb
2
+ # class L wraps the LeafletJS junk. Why L? because in
3
+ # javashit the LeafletJS uses L for its namespace.
4
+
5
+ module LeafletHelper
6
+ class L
7
+ VERSION = '0.7.7' # of leaflet.js
8
+ JS = "http://cdn.leafletjs.com/leaflet/v#{VERSION}/leaflet.js"
9
+ CSS = "http://cdn.leafletjs.com/leaflet/v#{VERSION}/leaflet.css"
10
+
11
+ MarkerClusterJS = "https://raw.githubusercontent.com/Leaflet/Leaflet.markercluster/leaflet-0.7/dist/leaflet.markercluster.js"
12
+ MarkerClusterCSS = "https://raw.githubusercontent.com/Leaflet/Leaflet.markercluster/leaflet-0.7/dist/MarkerCluster.css"
13
+
14
+ # FIXME: Needs to be isolated between maps in a multi-map application.
15
+ # experiments/maps shows the problem
16
+ @@defaults = { # the options from L#init
17
+ openstreetmap: true,
18
+ mapbox: false,
19
+ markers: false,
20
+ cluster: false,
21
+ latitude: AREA51.latitude,
22
+ longitude: AREA51.longitude,
23
+ zoom: 9,
24
+ min_zoom: 2,
25
+ max_zoom: 22
26
+ }
27
+
28
+
29
+ class << self
30
+
31
+ # intended for the the head section of a web page
32
+ def init(options={})
33
+ @@defaults.merge! options
34
+ return U.pull_in 'head.html.erb', @@defaults
35
+ end # def init
36
+
37
+
38
+ # intended for the body of a web page
39
+ # can support multiple maps on a page; each
40
+ # map must have a unique id
41
+ def place_map_here(id='map', options={})
42
+ o = {
43
+ style: "width: 1200px; height: 400px"
44
+ }.merge(options)
45
+
46
+ div_options = ""
47
+
48
+ o.each_pair do |k,v|
49
+ div_options += " #{k.to_s}=" + '"' + v + '"'
50
+ end
51
+
52
+ return U.pull_in 'map_div.html.erb', {id: id, parameters: div_options}
53
+ end # def place_map_here(id='map')
54
+
55
+
56
+ # Intended for the body at the bottom
57
+ # see the example for, er uh, an example
58
+ def show_map(id="map", options={})
59
+ o = @@defaults.merge({
60
+ id: id,
61
+ map_name: get_map_name(id),
62
+ route: "#{id}/markers"
63
+ }.merge(options))
64
+
65
+ script = "<script>\n"
66
+ script += U.pull_in 'show_map.js.erb', o
67
+ script += set_view(id, o)
68
+
69
+ # SMELL: why can't you have both OSM and Mapbox?
70
+ script += add_openstreetmap_layer(id, o) if openstreetmap? && !mapbox?
71
+ script += add_mapbox_layer(id, o) if mapbox? && !openstreetmap?
72
+ script += add_support_for_markers(id, o) if markers?
73
+
74
+ script += "</script>\n"
75
+
76
+ return script
77
+ end # def show_map(id="map", options={})
78
+
79
+
80
+ # Center an existing map to a specific location
81
+ def set_view(id='map', options={})
82
+ o = @@defaults.merge({
83
+ id: id,
84
+ map_name: get_map_name(id)
85
+ }.merge(options))
86
+
87
+ return U.pull_in 'set_view.js.erb', o
88
+ end # def set_view(id='map', options={})
89
+
90
+
91
+ # The default tile provider is Open Street Map project
92
+ def add_openstreetmap_layer(id="map", options={})
93
+ @@defaults[:openstreetmap] = true
94
+ o = @@defaults.merge({
95
+ id: id,
96
+ map_name: get_map_name(id),
97
+ osm_url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
98
+ osm_attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors'
99
+ }.merge(options))
100
+
101
+ return U.pull_in 'add_openstreetmap_layer.js.erb', o
102
+ end # def add_openstreetmap_layer(id="map", options={})
103
+
104
+
105
+ # NOTE: To use mapbox you must have an account
106
+ def add_mapbox_layer(id="map", options={})
107
+ o = @@defaults.merge({
108
+ id: id,
109
+ map_name: get_map_name(id),
110
+ mapbox_url: ENV['MAPBOX_URL'] || "https://api.mapbox.com/styles/v1/{mbUser}/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}",
111
+ mapbox_user: ENV['MAPBOX_USER'] || "your.mapbox.user.account",
112
+ mapbox_style_id: ENV['MAPBOX_STYLE_ID'] || "your.mapbox.project.id",
113
+ mapbox_access_token: ENV['MAPBOX_ACCESS_TOKEN'] || "your.mapbox.access.token",
114
+ mapbox_attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com">Mapbox</a>',
115
+ }.merge(options))
116
+
117
+ return U.pull_in 'add_mapbox_layer.js.erb', o
118
+ end # def add_mapbox_layer(id="map", options={})
119
+
120
+
121
+ # Allows for the generation of markers on top of the map
122
+ def add_support_for_markers(id="map", options={})
123
+ o = @@defaults.merge({
124
+ id: id,
125
+ map_name: get_map_name(id),
126
+ route: "#{id}/markers"
127
+ }.merge(options))
128
+
129
+ return U.pull_in 'marker_support.js.erb', o
130
+ end # def add_support_for_markers(map_id, map_options)
131
+
132
+
133
+ # The Javascript container that has the map for this id
134
+ def get_map_name(id="map")
135
+ return "lh_#{id}"
136
+ end
137
+
138
+
139
+ def openstreetmap?
140
+ @@defaults[:openstreetmap]
141
+ end
142
+
143
+ def mapbox?
144
+ @@defaults[:mapbox]
145
+ end
146
+
147
+ def markers?
148
+ @@defaults[:markers]
149
+ end
150
+
151
+ def cluster?
152
+ @@defaults[:cluster]
153
+ end
154
+
155
+ # LeafletHelper::U needs access to the L's class variable
156
+ def defaults
157
+ @@defaults
158
+ end
159
+
160
+ end # class << self
161
+ end # class L
162
+ end # module LeafletHelper
163
+
@@ -0,0 +1,23 @@
1
+ # u.rb
2
+ # This is a utility class
3
+
4
+ module LeafletHelper
5
+ class U
6
+ class << self
7
+
8
+ # insert HTML/JS or whatever from a file in the lib/templates directory
9
+ # use ERB to pre-process the file using local binding
10
+ def pull_in(template_name, options={})
11
+ options.each { |k,v| instance_variable_set("@#{k}", v) }
12
+ @file_name = LeafletHelper::TEMPLATES + template_name
13
+ return ERB.new(@file_name.read, 0, '>').result(binding)
14
+ end # def pull_in(template_name, options={})
15
+
16
+ # provide ERB in #pull_in with visibility into class L
17
+ def cluster?
18
+ LeafletHelper::L.defaults[:cluster]
19
+ end # def cluster?
20
+
21
+ end # class << self
22
+ end # class U
23
+ end # module LeafletHelper
@@ -2,308 +2,32 @@
2
2
  #
3
3
  # If you are a front-end developer and a Javascript guru this will
4
4
  # make you laught. If you are a back-end big-data AI do-er of amazing
5
- # things then this library might be of some use to you. I allows you
5
+ # things then this library might be of some use to you. It allows you
6
6
  # to but maps onto a web-page using simple frameworks. No more NodeJS
7
7
  # or Rails. Use some simple sinatra-based haml pages and voila you got maps.
8
8
  #
9
9
  # Makes use of these system environment variables when using
10
- # using the method add_mapbox_layer:
10
+ # the method Mapbox.com as a tile provider:
11
11
  #
12
12
  # MAPBOX_URL
13
13
  # MAPBOX_USER
14
14
  # MAPBOX_STYLE_ID
15
15
  # MAPBOX_ACCESS_TOKEN
16
16
 
17
- # TODO: refactor
17
+ require 'erb'
18
+ require 'pathname'
18
19
 
19
20
  # Just as good a default as any other ...
20
21
  AREA51 = Struct.new('Location', :latitude, :longitude).new
21
22
  AREA51.latitude = 37.235
22
23
  AREA51.longitude = -115.811111
23
24
 
24
- require 'leaflet_helper/string_template'
25
- require 'leaflet_helper/manage_markers'
25
+ require 'leaflet_helper/string_template' # Lets do simple string templates
26
+ require 'leaflet_helper/manage_markers' # Lets keep track of some markers
27
+ require 'leaflet_helper/l' # wrapper class for LeafletJS
28
+ require 'leaflet_helper/u' # a utility class
26
29
 
27
30
 
28
31
  module LeafletHelper
29
- class L
30
- VERSION = '0.7.7' # of leaflet.js
31
- JS = "http://cdn.leafletjs.com/leaflet/v#{VERSION}/leaflet.js"
32
- CSS = "http://cdn.leafletjs.com/leaflet/v#{VERSION}/leaflet.css"
33
-
34
- # TODO: Why are these desired?
35
- @@map_ids = [] # the div ids of all of the maps
36
-
37
- class << self
38
-
39
- # intended for the the head section
40
- def init(options={})
41
- o = {
42
- author: "@madbomber"
43
- }.merge(options)
44
-
45
- leaflet_script = <<~EOS
46
- <!-- Leaflet -->
47
- <script src="#{JS}"></script>
48
- <link rel="stylesheet" href="#{CSS}">
49
- EOS
50
-
51
- return leaflet_script
52
- end # def init
53
-
54
-
55
- # intended for the body of a web page
56
- # can support multiple maps on a page; each
57
- # map must have a unique id
58
- def place_map_here(id='map', options={})
59
- @@map_ids << id unless @@map_ids.include?(id)
60
-
61
- o = {
62
- style: "width: 800px; height: 400px"
63
- }.merge(options)
64
-
65
- div_options = ""
66
-
67
- o.each_pair do |k,v|
68
- div_options += " #{k.to_s}=" + '"' + v + '"'
69
- end
70
-
71
- return <<~EOS
72
- <div id="#{id}"#{div_options}></div>
73
- EOS
74
- end # def place_map_here(id='map')
75
-
76
-
77
- # Intended for the body at the bottom
78
- def show_map(id="map", options={})
79
- o = {
80
- latitude: AREA51.latitude,
81
- longitude: AREA51.longitude,
82
- zoom: 9,
83
- min_zoom: 2,
84
- max_zoom: 22
85
- }.merge(options)
86
-
87
- var_name = get_var_name(id)
88
-
89
- leaflet_script = <<~EOS
90
- <script>
91
-
92
- var #{var_name};
93
-
94
- // SMELL: These 3 vars are only used with markers so why are they here?
95
- var ajaxRequestFor#{id};
96
- var plotlistFor#{id};
97
- var plotlayersFor#{id} = [];
98
-
99
- // set up the map
100
- #{var_name} = new L.Map('#{id}');
101
-
102
- // SMELL: Maybe the app is not ready to set the view. There is
103
- // a ruby method #set_view that does this.
104
- // start the map at a given location and zoom level
105
- #{var_name}.setView(new L.LatLng(#{o[:latitude]}, #{o[:longitude]}), #{o[:zoom]});
106
-
107
- </script>
108
- EOS
109
-
110
- return leaflet_script
111
- end # def show_map(id="map", options={})
112
-
113
-
114
- # Center an existing map to a specific location
115
- def set_view(id='map', options={})
116
- o = {
117
- latitude: AREA51.latitude,
118
- longitude: AREA51.longitude,
119
- zoom: 9
120
- }.merge(options)
121
-
122
- var_name = get_var_name(id)
123
-
124
- leaflet_script = <<~EOS
125
- <script>
126
- // center the map to a given location and zoom level
127
- #{var_name}.setView(new L.LatLng(#{o[:latitude]}, #{o[:longitude]}), #{o[:zoom]});
128
- </script>
129
- EOS
130
-
131
- return leaflet_script
132
-
133
- end # def set_view(id='map', options={})
134
-
135
-
136
- # Intended for the body at the bottom
137
- # SMELL: why the bottom? Because that's the way we did it in the old days
138
- # so that the entire web page would have been loaded by then.
139
- def add_openstreetmap_layer(id="map", options={})
140
- o = {
141
- latitude: AREA51.latitude,
142
- longitude: AREA51.longitude,
143
- zoom: 9,
144
- min_zoom: 2,
145
- max_zoom: 22
146
- }.merge(options)
147
-
148
- var_name = get_var_name(id)
149
-
150
- leaflet_script = <<~EOS
151
- <script>
152
-
153
- // create the tile layer with correct attribution
154
- var osmUrl ='http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
155
- var osmAttrib ='Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors';
156
- var osm = new L.TileLayer(osmUrl, {minZoom: #{o[:min_zoom]}, maxZoom: #{o[:max_zoom]}, attribution: osmAttrib});
157
-
158
- osm.addTo(#{var_name});
159
-
160
- </script>
161
- EOS
162
-
163
- return leaflet_script
164
- end # def add_openstreetmap_layer(id="map", options={})
165
-
166
-
167
- # Intended for the body at the bottom
168
- # To use mapbox you must have an account
169
- def add_mapbox_layer(id="map", options={})
170
- o = {
171
- url: ENV['MAPBOX_URL'] || "https://api.mapbox.com/styles/v1/{mbUser}/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}",
172
- mapbox_user: ENV['MAPBOX_USER'] || "your.mapbox.user.account",
173
- style_id: ENV['MAPBOX_STYLE_ID'] || "your.mapbox.project.id",
174
- access_token: ENV['MAPBOX_ACCESS_TOKEN'] || "your.mapbox.access.token",
175
- attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com">Mapbox</a>',
176
- zoom: 9,
177
- min_zoom: 2,
178
- max_zoom: 22
179
- }.merge(options)
180
-
181
- var_name = get_var_name(id)
182
-
183
- leaflet_script = <<~EOS
184
- <script>
185
-
186
- // create the tile layer with correct attribution
187
- L.tileLayer('#{o[:url]}', {
188
- mbUser: '#{o[:mapbox_user]}',
189
- attribution: '#{o[:attribution]}',
190
- minZoom: #{o[:min_zoom]},
191
- maxZoom: #{o[:max_zoom]},
192
- id: '#{o[:style_id]}',
193
- accessToken: '#{o[:access_token]}'
194
- }).addTo(#{var_name});
195
-
196
- </script>
197
- EOS
198
-
199
- return leaflet_script
200
- end # def add_mapbox_layer(id="map", options={})
201
-
202
-
203
- # Allows for the generation of markers on top of the map
204
- def add_support_for_markers(id="map", options={})
205
- o = {
206
- route: "#{id}/markers"
207
- }.merge(options)
208
-
209
- var_name = get_var_name(id)
210
-
211
- leaflet_script = <<~EOS
212
- <script>
213
-
214
- // set up AJAX request
215
- ajaxRequestFor#{id} = getXmlHttpObjectFor#{id}();
216
-
217
- if (ajaxRequestFor#{id} == null) {
218
- alert ("This browser does not support HTTP Request - can not show markers");
219
- // return;
220
- }
221
-
222
- function getXmlHttpObjectFor#{id}() {
223
- if (window.XMLHttpRequest) { return new XMLHttpRequest(); }
224
- if (window.ActiveXObject) { return new ActiveXObject("Microsoft.XMLHTTP"); }
225
- return null;
226
- }
227
-
228
-
229
- getMarkersFor#{id}();
230
- #{var_name}.on('moveend', on#{id}Move);
231
-
232
- function on#{id}Move(e) { getMarkersFor#{id}(); }
233
-
234
-
235
- // request the marker info for the current bounds
236
- function getMarkersFor#{id}() {
237
-
238
- // TODO: Currently the displayed map bounds is not being used
239
- // to get the new set of markers. This could be ugly for
240
- // lots of markers. Need a way to insert the bounds into the route.
241
- var bounds = #{var_name}.getBounds();
242
- var minll = bounds.getSouthWest();
243
- var maxll = bounds.getNorthEast();
244
-
245
- // this is the place from which the markers JSON array is obtained
246
- var route = '#{o[:route]}';
247
-
248
- ajaxRequestFor#{id}.onreadystatechange = stateChangedFor#{id};
249
- ajaxRequestFor#{id}.open('GET', route, true);
250
- ajaxRequestFor#{id}.send(null);
251
- }
252
-
253
-
254
- // The map changed so get new markers
255
- function stateChangedFor#{id}() {
256
-
257
- // if AJAX returned a list of markers, add them to the map
258
- if (ajaxRequestFor#{id}.readyState == 4) {
259
-
260
- // use the info here that was returned
261
- if (ajaxRequestFor#{id}.status == 200) {
262
- plotlist = eval("(" + ajaxRequestFor#{id}.responseText + ")");
263
- removeMarkersFrom#{id}();
264
-
265
- for (i=0; i<plotlist.length; i++) {
266
- var plotll = new L.LatLng(plotlist[i].lat, plotlist[i].lon, true);
267
- var plotmark = new L.Marker(plotll);
268
- plotmark.data = plotlist[i];
269
-
270
- #{var_name}.addLayer(plotmark);
271
- plotmark.bindPopup(plotlist[i].html);
272
- plotlayersFor#{id}.push(plotmark);
273
- } // for
274
-
275
- } // if (ajaxRequestFor#{id}.status == 200)
276
-
277
- } // if (ajaxRequestFor#{id}.readyState == 4)
278
-
279
- } // function stateChangedFor#{id}()
280
-
281
-
282
- // remove all of the markers from the map
283
- function removeMarkersFrom#{id}() {
284
- for (i=0; i<plotlayersFor#{id}.length; i++) {
285
- #{var_name}.removeLayer(plotlayersFor#{id}[i]);
286
- }
287
- plotlayersFor#{id} = [];
288
- }
289
-
290
- </script>
291
- EOS
292
-
293
- return leaflet_script
294
- end # def add_support_for_markers(map_id, map_options)
295
-
296
-
297
- # The "var name" is the Javascript container that has the map
298
- def get_var_name(id="map")
299
- return "lh_#{id}"
300
- end
301
-
302
-
303
- def comment(a_string='####################################################')
304
- return "<!-- #{a_string} -->"
305
- end
306
-
307
- end # class << self
308
- end # class L
32
+ TEMPLATES = Pathname.new(__FILE__).parent + 'templates'
309
33
  end # module LeafletHelper
@@ -0,0 +1,14 @@
1
+ <!-- begin <%= @file_name %> -->
2
+
3
+ L.tileLayer(
4
+ '<%= @url %>',
5
+ {
6
+ mbUser: '<%= @mapbox_user %>',
7
+ attribution: '<%= @mapbox_attribution %>',
8
+ minZoom: <%= @min_zoom %>,
9
+ maxZoom: <%= @max_zoom %>,
10
+ id: '<%= @mapbox_style_id %>',
11
+ accessToken: '<%= @mapbox_access_token %>'
12
+ }).addTo(<%= @map_name %>);
13
+
14
+ <!-- end <%= @file_name %> -->
@@ -0,0 +1,11 @@
1
+ <!-- begin <%= @file_name %> -->
2
+
3
+ L.tileLayer(
4
+ '<%= @osm_url %>',
5
+ {
6
+ minZoom: <%= @min_zoom %>,
7
+ maxZoom: <%= @max_zoom %>,
8
+ attribution: '<%= @osm_attribution %>'
9
+ }).addTo(<%= @map_name %>);
10
+
11
+ <!-- end <%= @file_name %> -->
@@ -0,0 +1,13 @@
1
+ <!-- begin <%= @file_name %> -->
2
+
3
+ <!-- Leaflet -->
4
+ <script src="<%= LeafletHelper::L::JS %>"></script>
5
+ <link rel="stylesheet" href="<%= LeafletHelper::L::CSS %>">
6
+
7
+ <% if @cluster %>
8
+ <!-- Leaflet.markercluster -->
9
+ <script src="<%= LeafletHelper::L::MarkerClusterJS %>"></script>
10
+ <link rel="stylesheet" href="<%= LeafletHelper::L::MarkerClusterCSS %>">
11
+ <% end %>
12
+
13
+ <!-- end <%= @file_name %> -->
@@ -0,0 +1,3 @@
1
+ <!-- begin <%= @file_name %> -->
2
+ <div id="<%= @id %>" <%= @parameters %>></div>
3
+ <!-- end <%= @file_name %> -->
@@ -0,0 +1,100 @@
1
+ <!-- begin <%= @file_name %> -->
2
+
3
+ // set up AJAX request
4
+ ajaxRequestFor<%= @id %> = getXmlHttpObjectFor<%= @id %>();
5
+
6
+ if (ajaxRequestFor<%= @id %> == null) {
7
+ alert ("This browser too old - can not show markers");
8
+ // return;
9
+ }
10
+
11
+ function getXmlHttpObjectFor<%= @id %>() {
12
+ if (window.XMLHttpRequest) { return new XMLHttpRequest(); }
13
+ if (window.ActiveXObject) { return new ActiveXObject("Microsoft.XMLHTTP"); }
14
+ return null;
15
+ }
16
+
17
+
18
+ getMarkersFor<%= @id %>();
19
+ <%= @map_name %>.on('moveend', on<%= @id %>Move);
20
+
21
+ function on<%= @id %>Move(e) { getMarkersFor<%= @id %>(); }
22
+
23
+
24
+ // request the marker info for the current bounds
25
+ function getMarkersFor<%= @id %>() {
26
+
27
+ // TODO: Currently the displayed map bounds is not being used
28
+ // to get the new set of markers. This could be ugly for
29
+ // lots of markers. Need a way to insert the bounds into the route.
30
+
31
+ var bounds = <%= @map_name %>.getBounds();
32
+ var minll = bounds.getSouthWest();
33
+ var maxll = bounds.getNorthEast();
34
+
35
+ // this is the place from which the markers JSON array is obtained
36
+ var route = '<%= @route %>';
37
+
38
+ ajaxRequestFor<%= @id %>.onreadystatechange = stateChangedFor<%= @id %>;
39
+ ajaxRequestFor<%= @id %>.open('GET', route, true);
40
+ ajaxRequestFor<%= @id %>.send(null);
41
+ }
42
+
43
+
44
+ // The map changed so get new markers
45
+ function stateChangedFor<%= @id %>() {
46
+
47
+ // if AJAX returned a list of markers, add them to the map
48
+ if (ajaxRequestFor<%= @id %>.readyState == 4) {
49
+
50
+ <% if cluster? %>
51
+ var markersFor<%= @id %> = L.markerClusterGroup();
52
+ <% end %>
53
+
54
+ // use the info here that was returned
55
+ if (ajaxRequestFor<%= @id %>.status == 200) {
56
+ plotlist = eval("(" + ajaxRequestFor<%= @id %>.responseText + ")");
57
+ removeMarkersFrom<%= @id %>();
58
+
59
+ for (i=0; i<plotlist.length; i++) {
60
+ var plotll = new L.LatLng(plotlist[i].lat, plotlist[i].lon, true);
61
+ var plotmark = new L.Marker(plotll);
62
+ plotmark.data = plotlist[i];
63
+
64
+ // SMELL: Is each marker in a different layer? Wouldn't it
65
+ // be better to have all markers in the same layer?
66
+ // With all markers in the same layer we could then do ...
67
+ // markerLayer.add(markers).addTo(map);
68
+ // map.fitBounds(markerLayer.getBounds());
69
+
70
+ plotmark.bindPopup(plotlist[i].html);
71
+
72
+ <% if cluster? %>
73
+ markersFor<%= @id %>.addLayer(plotmark);
74
+ <% else %>
75
+ <%= @map_name %>.addLayer(plotmark);
76
+ plotlayersFor<%= @id %>.push(plotmark);
77
+ <% end %>
78
+
79
+ } // for
80
+
81
+ <% if cluster? %>
82
+ <%= @map_name %>.addLayer(markersFor<%= @id %>);
83
+ <% end %>
84
+
85
+ } // if (ajaxRequestFor<%= @id %>.status == 200)
86
+
87
+ } // if (ajaxRequestFor<%= @id %>.readyState == 4)
88
+
89
+ } // function stateChangedFor<%= @id %>()
90
+
91
+
92
+ // remove all of the markers from the map
93
+ function removeMarkersFrom<%= @id %>() {
94
+ for (i=0; i<plotlayersFor<%= @id %>.length; i++) {
95
+ <%= @map_name %>.removeLayer(plotlayersFor<%= @id %>[i]);
96
+ }
97
+ plotlayersFor<%= @id %> = [];
98
+ }
99
+
100
+ <!-- end <%= @file_name %> -->
@@ -0,0 +1,11 @@
1
+ <!-- begin <%= @file_name %> -->
2
+
3
+ <%= @map_name %>.setView(new
4
+ L.LatLng(
5
+ <%= @latitude %>,
6
+ <%= @longitude %>
7
+ ),
8
+ <%= @zoom %>
9
+ );
10
+
11
+ <!-- end <%= @file_name %> -->
@@ -0,0 +1,11 @@
1
+ <!-- begin <%= @file_name %> -->
2
+
3
+ var <%= @map_name %> = new L.Map('<%= @id %>');
4
+
5
+ // SMELL: These 3 vars are only used with markers so why are they here?
6
+ var ajaxRequestFor<%= @id %>;
7
+ var plotlistFor<%= @id %>;
8
+ var plotlayersFor<%= @id %> = [];
9
+
10
+ <!-- end <%= @file_name %> -->
11
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leaflet_helper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dewayne VanHoozer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-12 00:00:00.000000000 Z
11
+ date: 2016-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -77,8 +77,17 @@ files:
77
77
  - example/views/layout.haml
78
78
  - leaflet_helper.gemspec
79
79
  - lib/leaflet_helper.rb
80
+ - lib/leaflet_helper/l.rb
80
81
  - lib/leaflet_helper/manage_markers.rb
81
82
  - lib/leaflet_helper/string_template.rb
83
+ - lib/leaflet_helper/u.rb
84
+ - lib/templates/add_mapbox_layer.js.erb
85
+ - lib/templates/add_openstreetmap_layer.js.erb
86
+ - lib/templates/head.html.erb
87
+ - lib/templates/map_div.html.erb
88
+ - lib/templates/marker_support.js.erb
89
+ - lib/templates/set_view.js.erb
90
+ - lib/templates/show_map.js.erb
82
91
  homepage: http://github.com/MadBomber/leaflet_helper
83
92
  licenses:
84
93
  - You want it? Its yours!