gmap-rails 3.3.2
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.
- data/.gitignore +1 -0
- data/LICENSE +0 -0
- data/README.md +1 -0
- data/Rakefile +2 -0
- data/gemfile +3 -0
- data/gmap-rails.gemspec +19 -0
- data/lib/gmap-rails.rb +8 -0
- data/lib/gmap-rails/version.rb +5 -0
- data/vendor/assets/javascripts/jquery.gmap.js +872 -0
- metadata +89 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
pkg
|
data/LICENSE
ADDED
File without changes
|
data/README.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
http://www.smashinglabs.pl/gmap
|
data/Rakefile
ADDED
data/gemfile
ADDED
data/gmap-rails.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/gmap-rails/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["bokmann"]
|
6
|
+
gem.email = ["dbock@codesherpas.com"]
|
7
|
+
gem.description = %q{gmap is a helpful little Javascript library by Sebastian Poręba. I'm just turning it into an asset gem for the rails asset pipeline.}
|
8
|
+
gem.summary = %q{A simple asset pipeline bundling of the gmap javascript library.}
|
9
|
+
gem.homepage = "https://github.com/bokmann/fullcalendar-rails"
|
10
|
+
|
11
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
12
|
+
gem.files = `git ls-files`.split("\n")
|
13
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
|
+
gem.name = "gmap-rails"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Gmap::Rails::VERSION
|
17
|
+
|
18
|
+
gem.add_development_dependency "rake"
|
19
|
+
end
|
data/lib/gmap-rails.rb
ADDED
@@ -0,0 +1,872 @@
|
|
1
|
+
/**
|
2
|
+
* jQuery gMap v3
|
3
|
+
*
|
4
|
+
* @url http://www.smashinglabs.pl/gmap
|
5
|
+
* @author Sebastian Poreba <sebastian.poreba@gmail.com>
|
6
|
+
* @version 3.3.2
|
7
|
+
* @date 16.03.2011
|
8
|
+
*/
|
9
|
+
/*jslint white: false, undef: true, regexp: true, plusplus: true, bitwise: true, newcap: true, strict: true, devel: true, maxerr: 50, indent: 4 */
|
10
|
+
/*global window, jQuery, $, google, $googlemaps */
|
11
|
+
(function ($) {
|
12
|
+
"use strict";
|
13
|
+
|
14
|
+
/**
|
15
|
+
* Internals and experimental section
|
16
|
+
*/
|
17
|
+
var Cluster = function () {
|
18
|
+
this.markers = [];
|
19
|
+
this.mainMarker = false;
|
20
|
+
this.icon = "http://www.google.com/mapfiles/marker.png";
|
21
|
+
};
|
22
|
+
|
23
|
+
/**
|
24
|
+
* For iterating over all clusters to find if any is close enough to be merged with marker
|
25
|
+
*
|
26
|
+
* @param marker
|
27
|
+
* @param currentSize - calculated as viewport percentage (opts.clusterSize)
|
28
|
+
* @return bool
|
29
|
+
*/
|
30
|
+
Cluster.prototype.dist = function (marker) {
|
31
|
+
return Math.sqrt(Math.pow(this.markers[0].latitude - marker.latitude, 2) +
|
32
|
+
Math.pow(this.markers[0].longitude - marker.longitude, 2));
|
33
|
+
};
|
34
|
+
|
35
|
+
Cluster.prototype.setIcon = function (icon) {
|
36
|
+
this.icon = icon;
|
37
|
+
};
|
38
|
+
|
39
|
+
Cluster.prototype.addMarker = function (marker) {
|
40
|
+
this.markers[this.markers.length] = marker;
|
41
|
+
};
|
42
|
+
|
43
|
+
/**
|
44
|
+
* returns one marker if there is only one or
|
45
|
+
* returns special cloister marker if there are more
|
46
|
+
*/
|
47
|
+
Cluster.prototype.getMarker = function () {
|
48
|
+
if (this.mainmarker) {return this.mainmarker; }
|
49
|
+
var gicon, title;
|
50
|
+
if (this.markers.length > 1) {
|
51
|
+
gicon = new $googlemaps.MarkerImage("http://thydzik.com/thydzikGoogleMap/markerlink.php?text=" + this.markers.length + "&color=EF9D3F");
|
52
|
+
title = "cluster of " + this.markers.length + " markers";
|
53
|
+
} else {
|
54
|
+
gicon = new $googlemaps.MarkerImage(this.icon);
|
55
|
+
title = this.markers[0].title;
|
56
|
+
}
|
57
|
+
this.mainmarker = new $googlemaps.Marker({
|
58
|
+
position: new $googlemaps.LatLng(this.markers[0].latitude, this.markers[0].longitude),
|
59
|
+
icon: gicon,
|
60
|
+
title: title,
|
61
|
+
map: null
|
62
|
+
});
|
63
|
+
return this.mainmarker;
|
64
|
+
};
|
65
|
+
|
66
|
+
// global google maps objects
|
67
|
+
var $googlemaps = google.maps,
|
68
|
+
$geocoder = new $googlemaps.Geocoder(),
|
69
|
+
$markersToLoad = 0,
|
70
|
+
overQueryLimit = 0,
|
71
|
+
methods = {};
|
72
|
+
methods = {
|
73
|
+
/**
|
74
|
+
* initialisation/internals
|
75
|
+
*/
|
76
|
+
|
77
|
+
init: function (options) {
|
78
|
+
var k,
|
79
|
+
// Build main options before element iteration
|
80
|
+
opts = $.extend({}, $.fn.gMap.defaults, options);
|
81
|
+
|
82
|
+
// recover icon array
|
83
|
+
for (k in $.fn.gMap.defaults.icon) {
|
84
|
+
if(!opts.icon[k]) {
|
85
|
+
opts.icon[k] = $.fn.gMap.defaults.icon[k];
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
// Iterate through each element
|
90
|
+
return this.each(function () {
|
91
|
+
var $this = $(this),
|
92
|
+
center = methods._getMapCenter.apply($this, [opts]),
|
93
|
+
i, $data;
|
94
|
+
|
95
|
+
if (opts.zoom == "fit") {
|
96
|
+
opts.zoomFit = true;
|
97
|
+
opts.zoom = methods._autoZoom.apply($this, [opts]);
|
98
|
+
}
|
99
|
+
|
100
|
+
var mapOptions = {
|
101
|
+
zoom: opts.zoom,
|
102
|
+
center: center,
|
103
|
+
mapTypeControl: opts.mapTypeControl,
|
104
|
+
mapTypeControlOptions: {},
|
105
|
+
zoomControl: opts.zoomControl,
|
106
|
+
zoomControlOptions: {},
|
107
|
+
panControl : opts.panControl,
|
108
|
+
panControlOptions: {},
|
109
|
+
scaleControl : opts.scaleControl,
|
110
|
+
scaleControlOptions: {},
|
111
|
+
streetViewControl: opts.streetViewControl,
|
112
|
+
streetViewControlOptions: {},
|
113
|
+
mapTypeId: opts.maptype,
|
114
|
+
scrollwheel: opts.scrollwheel,
|
115
|
+
maxZoom: opts.maxZoom,
|
116
|
+
minZoom: opts.minZoom
|
117
|
+
};
|
118
|
+
if(opts.controlsPositions.mapType) {mapOptions.mapTypeControlOptions.position = opts.controlsPositions.mapType};
|
119
|
+
if(opts.controlsPositions.zoom) {mapOptions.zoomControlOptions.position = opts.controlsPositions.zoom};
|
120
|
+
if(opts.controlsPositions.pan) {mapOptions.panControlOptions.position = opts.controlsPositions.pan};
|
121
|
+
if(opts.controlsPositions.scale) {mapOptions.scaleControlOptions.position = opts.controlsPositions.scale};
|
122
|
+
if(opts.controlsPositions.streetView) {mapOptions.streetViewControlOptions.position = opts.controlsPositions.streetView};
|
123
|
+
|
124
|
+
mapOptions.mapTypeControlOptions.style = opts.controlsStyle.mapType;
|
125
|
+
mapOptions.zoomControlOptions.style = opts.controlsStyle.zoom;
|
126
|
+
|
127
|
+
// Create map and set initial options
|
128
|
+
var $gmap = new $googlemaps.Map(this, mapOptions);
|
129
|
+
|
130
|
+
if (opts.log) {console.log('map center is:'); }
|
131
|
+
if (opts.log) {console.log(center); }
|
132
|
+
|
133
|
+
// Create map and set initial options
|
134
|
+
|
135
|
+
$this.data("$gmap", $gmap);
|
136
|
+
|
137
|
+
$this.data('gmap', {
|
138
|
+
'opts': opts,
|
139
|
+
'gmap': $gmap,
|
140
|
+
'markers': [],
|
141
|
+
'markerKeys' : {},
|
142
|
+
'infoWindow': null,
|
143
|
+
'clusters': []
|
144
|
+
});
|
145
|
+
|
146
|
+
// Check for map controls
|
147
|
+
if (opts.controls.length !== 0) {
|
148
|
+
// Add custom map controls
|
149
|
+
for (i = 0; i < opts.controls.length; i += 1) {
|
150
|
+
$gmap.controls[opts.controls[i].pos].push(opts.controls[i].div);
|
151
|
+
}
|
152
|
+
}
|
153
|
+
|
154
|
+
if (opts.clustering.enabled) {
|
155
|
+
$data = $this.data('gmap');
|
156
|
+
(function(markers) {$data.markers = markers;}(opts.markers));
|
157
|
+
methods._renderCluster.apply($this, []);
|
158
|
+
|
159
|
+
$googlemaps.event.addListener($gmap, 'bounds_changed', function () {
|
160
|
+
methods._renderCluster.apply($this, []);
|
161
|
+
});
|
162
|
+
} else {
|
163
|
+
if (opts.markers.length !== 0) {
|
164
|
+
methods.addMarkers.apply($this, [opts.markers]);
|
165
|
+
}
|
166
|
+
}
|
167
|
+
|
168
|
+
methods._onComplete.apply($this, []);
|
169
|
+
});
|
170
|
+
},
|
171
|
+
|
172
|
+
|
173
|
+
_delayedMode: false,
|
174
|
+
|
175
|
+
/**
|
176
|
+
* Check every 100ms if all markers were loaded, then call onComplete
|
177
|
+
*/
|
178
|
+
_onComplete: function () {
|
179
|
+
var $data = this.data('gmap'),
|
180
|
+
that = this;
|
181
|
+
if ($markersToLoad !== 0) {
|
182
|
+
window.setTimeout(function () {methods._onComplete.apply(that, []); }, 100);
|
183
|
+
return;
|
184
|
+
}
|
185
|
+
if(methods._delayedMode) {
|
186
|
+
var center = methods._getMapCenter.apply(this, [$data.opts, true]);
|
187
|
+
methods._setMapCenter.apply(this, [center]);
|
188
|
+
if($data.opts.zoomFit) {
|
189
|
+
var zoom = methods._autoZoom.apply(this, [$data.opts, true]);
|
190
|
+
$data.gmap.setZoom(zoom);
|
191
|
+
}
|
192
|
+
}
|
193
|
+
$data.opts.onComplete();
|
194
|
+
},
|
195
|
+
|
196
|
+
/**
|
197
|
+
* set map center when map is loaded (check every 100ms)
|
198
|
+
*/
|
199
|
+
_setMapCenter: function (center) {
|
200
|
+
var $data = this.data('gmap');
|
201
|
+
if ($data.opts.log) {console.log('delayed setMapCenter called'); }
|
202
|
+
if ($data.gmap !== undefined && $markersToLoad == 0) {
|
203
|
+
$data.gmap.setCenter(center);
|
204
|
+
} else {
|
205
|
+
var that = this;
|
206
|
+
window.setTimeout(function () {methods._setMapCenter.apply(that, [center]); }, 100);
|
207
|
+
}
|
208
|
+
},
|
209
|
+
|
210
|
+
/**
|
211
|
+
* calculate boundaries, optimised and independent from Google Maps
|
212
|
+
*/
|
213
|
+
_boundaries: null,
|
214
|
+
_getBoundaries: function (opts) {
|
215
|
+
// if(methods._boundaries) {return methods._boundaries; }
|
216
|
+
var markers = opts.markers, i;
|
217
|
+
var mostN = 1000,
|
218
|
+
mostE = -1000,
|
219
|
+
mostW = 1000,
|
220
|
+
mostS = -1000;
|
221
|
+
if(markers) {
|
222
|
+
for (i = 0; i < markers.length; i += 1) {
|
223
|
+
if(!markers[i].latitude || !markers[i].longitude) continue;
|
224
|
+
|
225
|
+
if(mostN > markers[i].latitude) {mostN = markers[i].latitude; }
|
226
|
+
if(mostE < markers[i].longitude) {mostE = markers[i].longitude; }
|
227
|
+
if(mostW > markers[i].longitude) {mostW = markers[i].longitude; }
|
228
|
+
if(mostS < markers[i].latitude) {mostS = markers[i].latitude; }
|
229
|
+
console.log(markers[i].latitude, markers[i].longitude, mostN, mostE, mostW, mostS);
|
230
|
+
}
|
231
|
+
methods._boundaries = {N: mostN, E: mostE, W: mostW, S: mostS};
|
232
|
+
}
|
233
|
+
|
234
|
+
if(mostN == -1000) methods._boundaries = {N: 0, E: 0, W: 0, S: 0};
|
235
|
+
|
236
|
+
return methods._boundaries;
|
237
|
+
},
|
238
|
+
|
239
|
+
_getBoundariesFromMarkers: function () {
|
240
|
+
|
241
|
+
var markers = this.data('gmap').markers, i;
|
242
|
+
var mostN = 1000,
|
243
|
+
mostE = -1000,
|
244
|
+
mostW = 1000,
|
245
|
+
mostS = -1000;
|
246
|
+
if(markers) {
|
247
|
+
for (i = 0; i < markers.length; i += 1) {
|
248
|
+
if(mostN > markers[i].getPosition().lat()) {mostN = markers[i].getPosition().lat(); }
|
249
|
+
if(mostE < markers[i].getPosition().lng()) {mostE = markers[i].getPosition().lng(); }
|
250
|
+
if(mostW > markers[i].getPosition().lng()) {mostW = markers[i].getPosition().lng(); }
|
251
|
+
if(mostS < markers[i].getPosition().lat()) {mostS = markers[i].getPosition().lat(); }
|
252
|
+
}
|
253
|
+
methods._boundaries = {N: mostN, E: mostE, W: mostW, S: mostS};
|
254
|
+
}
|
255
|
+
|
256
|
+
if(mostN == -1000) methods._boundaries = {N: 0, E: 0, W: 0, S: 0};
|
257
|
+
|
258
|
+
return methods._boundaries;
|
259
|
+
},
|
260
|
+
|
261
|
+
/**
|
262
|
+
* Priorities order:
|
263
|
+
* - latitude & longitude in options
|
264
|
+
* - address in options
|
265
|
+
* - latitude & longitude of first marker having it
|
266
|
+
* - address of first marker having it
|
267
|
+
* - failsafe (0,0)
|
268
|
+
*
|
269
|
+
* Note: with geocoding returned value is (0,0) and callback sets map center. It's not very nice nor efficient.
|
270
|
+
* It is quite good idea to use only first option
|
271
|
+
*/
|
272
|
+
_getMapCenter: function (opts, fromMarkers) {
|
273
|
+
// Create new object to geocode addresses
|
274
|
+
|
275
|
+
var center,
|
276
|
+
that = this, // 'that' scope fix in geocoding
|
277
|
+
i,
|
278
|
+
selectedToCenter,
|
279
|
+
most; //hoisting
|
280
|
+
|
281
|
+
if (opts.markers.length && (opts.latitude == "fit" || opts.longitude == "fit")) {
|
282
|
+
if(fromMarkers) most = methods._getBoundariesFromMarkers.apply(this);
|
283
|
+
else most = methods._getBoundaries(opts);
|
284
|
+
center = new $googlemaps.LatLng((most.N + most.S)/2, (most.E + most.W)/2);
|
285
|
+
console.log(fromMarkers, most, center);
|
286
|
+
return center;
|
287
|
+
}
|
288
|
+
|
289
|
+
if (opts.latitude && opts.longitude) {
|
290
|
+
// lat & lng available, return
|
291
|
+
center = new $googlemaps.LatLng(opts.latitude, opts.longitude);
|
292
|
+
return center;
|
293
|
+
} else {
|
294
|
+
center = new $googlemaps.LatLng(0, 0);
|
295
|
+
}
|
296
|
+
|
297
|
+
// Check for address to center on
|
298
|
+
if (opts.address) {
|
299
|
+
// Get coordinates for given address and center the map
|
300
|
+
$geocoder.geocode(
|
301
|
+
{address: opts.address},
|
302
|
+
function (result, status) {
|
303
|
+
if (status === google.maps.GeocoderStatus.OK) {
|
304
|
+
methods._setMapCenter.apply(that, [result[0].geometry.location]);
|
305
|
+
} else {
|
306
|
+
if (opts.log) {console.log("Geocode was not successful for the following reason: " + status); }
|
307
|
+
}
|
308
|
+
}
|
309
|
+
);
|
310
|
+
return center;
|
311
|
+
}
|
312
|
+
|
313
|
+
// Check for a marker to center on (if no coordinates given)
|
314
|
+
if (opts.markers.length > 0) {
|
315
|
+
selectedToCenter = null;
|
316
|
+
|
317
|
+
for (i = 0; i < opts.markers.length; i += 1) {
|
318
|
+
if(opts.markers[i].setCenter) {
|
319
|
+
selectedToCenter = opts.markers[i];
|
320
|
+
break;
|
321
|
+
}
|
322
|
+
}
|
323
|
+
|
324
|
+
if (selectedToCenter === null) {
|
325
|
+
for (i = 0; i < opts.markers.length; i += 1) {
|
326
|
+
if (opts.markers[i].latitude && opts.markers[i].longitude) {
|
327
|
+
selectedToCenter = opts.markers[i];
|
328
|
+
break;
|
329
|
+
}
|
330
|
+
if (opts.markers[i].address) {
|
331
|
+
selectedToCenter = opts.markers[i];
|
332
|
+
}
|
333
|
+
}
|
334
|
+
}
|
335
|
+
// failed to find any reasonable marker (it's quite impossible BTW)
|
336
|
+
if (selectedToCenter === null) {
|
337
|
+
return center;
|
338
|
+
}
|
339
|
+
|
340
|
+
if (selectedToCenter.latitude && selectedToCenter.longitude) {
|
341
|
+
return new $googlemaps.LatLng(selectedToCenter.latitude, selectedToCenter.longitude);
|
342
|
+
}
|
343
|
+
|
344
|
+
// Check if the marker has an address
|
345
|
+
if (selectedToCenter.address) {
|
346
|
+
// Get the coordinates for given marker address and center
|
347
|
+
$geocoder.geocode(
|
348
|
+
{address: selectedToCenter.address},
|
349
|
+
function (result, status) {
|
350
|
+
if (status === google.maps.GeocoderStatus.OK) {
|
351
|
+
methods._setMapCenter.apply(that, [result[0].geometry.location]);
|
352
|
+
} else {
|
353
|
+
if (opts.log) {console.log("Geocode was not successful for the following reason: " + status); }
|
354
|
+
}
|
355
|
+
}
|
356
|
+
);
|
357
|
+
}
|
358
|
+
}
|
359
|
+
return center;
|
360
|
+
},
|
361
|
+
|
362
|
+
|
363
|
+
/**
|
364
|
+
* clustering
|
365
|
+
*/
|
366
|
+
_renderCluster: function () {
|
367
|
+
var $data = this.data('gmap'),
|
368
|
+
markers = $data.markers,
|
369
|
+
clusters = $data.clusters,
|
370
|
+
opts = $data.opts,
|
371
|
+
i,
|
372
|
+
j,
|
373
|
+
viewport;
|
374
|
+
|
375
|
+
for (i = 0; i < clusters.length; i += 1) {
|
376
|
+
clusters[i].getMarker().setMap(null);
|
377
|
+
}
|
378
|
+
clusters.length = 0;
|
379
|
+
|
380
|
+
viewport = $data.gmap.getBounds();
|
381
|
+
|
382
|
+
if (!viewport) {
|
383
|
+
var that = this;
|
384
|
+
window.setTimeout(function () {methods._renderCluster.apply(that); }, 1000);
|
385
|
+
return;
|
386
|
+
}
|
387
|
+
|
388
|
+
var ne = viewport.getNorthEast(),
|
389
|
+
sw = viewport.getSouthWest(),
|
390
|
+
width = ne.lat() - sw.lat(),
|
391
|
+
// height = ne.lng() - sw.lng(), // unused
|
392
|
+
clusterable = [],
|
393
|
+
best,
|
394
|
+
bestDist,
|
395
|
+
maxSize = width * opts.clustering.clusterSize / 100,
|
396
|
+
dist,
|
397
|
+
newCluster;
|
398
|
+
|
399
|
+
for (i = 0; i < markers.length; i += 1) {
|
400
|
+
if (markers[i].latitude < ne.lat() &&
|
401
|
+
markers[i].latitude > sw.lat() &&
|
402
|
+
markers[i].longitude < ne.lng() &&
|
403
|
+
markers[i].longitude > sw.lng()) {
|
404
|
+
clusterable[clusterable.length] = markers[i];
|
405
|
+
}
|
406
|
+
}
|
407
|
+
|
408
|
+
if (opts.log) {console.log("number of markers " + clusterable.length + "/" + markers.length); }
|
409
|
+
if (opts.log) {console.log('cluster radius: ' + maxSize); }
|
410
|
+
|
411
|
+
for (i = 0; i < clusterable.length; i += 1) {
|
412
|
+
bestDist = 10000;
|
413
|
+
best = -1;
|
414
|
+
for (j = 0; j < clusters.length; j += 1) {
|
415
|
+
dist = clusters[j].dist(clusterable[i]);
|
416
|
+
if (dist < maxSize) {
|
417
|
+
bestDist = dist;
|
418
|
+
best = j;
|
419
|
+
if (opts.clustering.fastClustering) {break; }
|
420
|
+
}
|
421
|
+
}
|
422
|
+
if (best === -1) {
|
423
|
+
newCluster = new Cluster();
|
424
|
+
newCluster.addMarker(clusterable[i]);
|
425
|
+
clusters[clusters.length] = newCluster;
|
426
|
+
} else {
|
427
|
+
clusters[best].addMarker(clusterable[i]);
|
428
|
+
}
|
429
|
+
}
|
430
|
+
|
431
|
+
if (opts.log) {console.log("Total clusters in viewport: " + clusters.length); }
|
432
|
+
|
433
|
+
for (j = 0; j < clusters.length; j += 1) {
|
434
|
+
clusters[j].getMarker().setMap($data.gmap);
|
435
|
+
}
|
436
|
+
},
|
437
|
+
|
438
|
+
_processMarker: function (marker, gicon, gshadow, location) {
|
439
|
+
var $data = this.data('gmap'),
|
440
|
+
$gmap = $data.gmap,
|
441
|
+
opts = $data.opts,
|
442
|
+
gmarker,
|
443
|
+
markeropts;
|
444
|
+
|
445
|
+
if (location === undefined) {
|
446
|
+
location = new $googlemaps.LatLng(marker.latitude, marker.longitude);
|
447
|
+
}
|
448
|
+
|
449
|
+
if (!gicon) {
|
450
|
+
|
451
|
+
// Set icon properties from global options
|
452
|
+
var _gicon = {
|
453
|
+
image: opts.icon.image,
|
454
|
+
iconSize: new $googlemaps.Size(opts.icon.iconsize[0], opts.icon.iconsize[1]),
|
455
|
+
iconAnchor: new $googlemaps.Point(opts.icon.iconanchor[0], opts.icon.iconanchor[1]),
|
456
|
+
infoWindowAnchor: new $googlemaps.Size(opts.icon.infowindowanchor[0], opts.icon.infowindowanchor[1])
|
457
|
+
};
|
458
|
+
gicon = new $googlemaps.MarkerImage(_gicon.image, _gicon.iconSize, null, _gicon.iconAnchor);
|
459
|
+
}
|
460
|
+
|
461
|
+
if (!gshadow) {
|
462
|
+
var _gshadow = {
|
463
|
+
image: opts.icon.shadow,
|
464
|
+
iconSize: new $googlemaps.Size(opts.icon.shadowsize[0], opts.icon.shadowsize[1]),
|
465
|
+
anchor: (_gicon && _gicon.iconAnchor)?_gicon.iconAnchor:new $googlemaps.Point(opts.icon.iconanchor[0], opts.icon.iconanchor[1])
|
466
|
+
};
|
467
|
+
}
|
468
|
+
|
469
|
+
markeropts = {
|
470
|
+
position: location,
|
471
|
+
icon: gicon,
|
472
|
+
title: marker.title,
|
473
|
+
map: null,
|
474
|
+
draggable: ((marker.draggable === true) ? true : false)
|
475
|
+
};
|
476
|
+
|
477
|
+
if (!opts.clustering.enabled) {markeropts.map = $gmap; }
|
478
|
+
|
479
|
+
gmarker = new $googlemaps.Marker(markeropts);
|
480
|
+
gmarker.setShadow(gshadow);
|
481
|
+
$data.markers.push(gmarker);
|
482
|
+
|
483
|
+
if(marker.key) {$data.markerKeys[marker.key] = gmarker; }
|
484
|
+
|
485
|
+
// Set HTML and check if info window should be opened
|
486
|
+
var infoWindow;
|
487
|
+
if (marker.html) {
|
488
|
+
var infoContent = typeof(marker.html) === "string" ? opts.html_prepend + marker.html + opts.html_append : marker.html;
|
489
|
+
var infoOpts = {
|
490
|
+
content: infoContent,
|
491
|
+
pixelOffset: marker.infoWindowAnchor
|
492
|
+
};
|
493
|
+
|
494
|
+
if (opts.log) {console.log('setup popup with data'); }
|
495
|
+
if (opts.log) {console.log(infoOpts); }
|
496
|
+
infoWindow = new $googlemaps.InfoWindow(infoOpts);
|
497
|
+
|
498
|
+
$googlemaps.event.addListener(gmarker, 'click', function () {
|
499
|
+
if (opts.log) {console.log('opening popup ' + marker.html); }
|
500
|
+
if (opts.singleInfoWindow && $data.infoWindow) {$data.infoWindow.close(); }
|
501
|
+
infoWindow.open($gmap, gmarker);
|
502
|
+
$data.infoWindow = infoWindow;
|
503
|
+
});
|
504
|
+
}
|
505
|
+
if (marker.html && marker.popup) {
|
506
|
+
if (opts.log) {console.log('opening popup ' + marker.html); }
|
507
|
+
infoWindow.open($gmap, gmarker);
|
508
|
+
$data.infoWindow = infoWindow;
|
509
|
+
}
|
510
|
+
|
511
|
+
if (marker.onDragEnd){
|
512
|
+
$googlemaps.event.addListener(gmarker, 'dragend', function(event) {
|
513
|
+
if (opts.log) {console.log('drag end');}
|
514
|
+
marker.onDragEnd(event);
|
515
|
+
});
|
516
|
+
}
|
517
|
+
|
518
|
+
},
|
519
|
+
|
520
|
+
_geocodeMarker: function (marker, gicon, gshadow) {
|
521
|
+
var that = this;
|
522
|
+
$geocoder.geocode({'address': marker.address}, function (results, status) {
|
523
|
+
if (status === $googlemaps.GeocoderStatus.OK) {
|
524
|
+
$markersToLoad -= 1;
|
525
|
+
if (that.data('gmap').opts.log) {console.log("Geocode was successful with point: ", results[0].geometry.location); }
|
526
|
+
methods._processMarker.apply(that, [marker, gicon, gshadow, results[0].geometry.location]);
|
527
|
+
} else {
|
528
|
+
if(status === $googlemaps.GeocoderStatus.OVER_QUERY_LIMIT) {
|
529
|
+
if ((!that.data('gmap').opts.noAlerts) && (overQueryLimit === 0)) {alert('Error: too many geocoded addresses! Switching to 1 marker/s mode.'); }
|
530
|
+
|
531
|
+
overQueryLimit+=1000;
|
532
|
+
window.setTimeout(function() {
|
533
|
+
methods._geocodeMarker.apply(that, [marker, gicon, gshadow]);
|
534
|
+
}, overQueryLimit);
|
535
|
+
}
|
536
|
+
if (that.data('gmap').opts.log) {console.log("Geocode was not successful for the following reason: " + status); }
|
537
|
+
}
|
538
|
+
});
|
539
|
+
},
|
540
|
+
|
541
|
+
_autoZoom: function (options, fromMarkers){
|
542
|
+
var data = $(this).data('gmap'),
|
543
|
+
opts = $.extend({}, data?data.opts:{}, options),
|
544
|
+
i, boundaries, resX, resY, baseScale = 39135.758482;
|
545
|
+
if (opts.log) {console.log("autozooming map");}
|
546
|
+
|
547
|
+
if(fromMarkers) boundaries = methods._getBoundariesFromMarkers.apply(this);
|
548
|
+
else boundaries = methods._getBoundaries(opts);
|
549
|
+
|
550
|
+
resX = (boundaries.E - boundaries.W) * 111000 / this.width();
|
551
|
+
resY = (boundaries.S - boundaries.N) * 111000 / this.height();
|
552
|
+
|
553
|
+
for(i = 2; i < 20; i += 1) {
|
554
|
+
if (resX > baseScale || resY > baseScale) {
|
555
|
+
break;
|
556
|
+
}
|
557
|
+
baseScale = baseScale / 2;
|
558
|
+
}
|
559
|
+
return i - 2;
|
560
|
+
},
|
561
|
+
|
562
|
+
/**
|
563
|
+
* public methods section
|
564
|
+
*/
|
565
|
+
|
566
|
+
/**
|
567
|
+
* add array of markers
|
568
|
+
* @param markers
|
569
|
+
*/
|
570
|
+
addMarkers: function (markers){
|
571
|
+
var opts = this.data('gmap').opts;
|
572
|
+
|
573
|
+
if (markers.length !== 0) {
|
574
|
+
if (opts.log) {console.log("adding " + markers.length +" markers");}
|
575
|
+
// Loop through marker array
|
576
|
+
for (var i = 0; i < markers.length; i+= 1) {
|
577
|
+
methods.addMarker.apply(this,[markers[i]]);
|
578
|
+
}
|
579
|
+
}
|
580
|
+
},
|
581
|
+
|
582
|
+
/**
|
583
|
+
* add single marker
|
584
|
+
* @param marker
|
585
|
+
*/
|
586
|
+
addMarker: function (marker) {
|
587
|
+
var opts = this.data('gmap').opts;
|
588
|
+
|
589
|
+
if (opts.log) {console.log("putting marker at " + marker.latitude + ', ' + marker.longitude + " with address " + marker.address + " and html " + marker.html); }
|
590
|
+
|
591
|
+
// Create new icon
|
592
|
+
// Set icon properties from global options
|
593
|
+
var _gicon = {
|
594
|
+
image: opts.icon.image,
|
595
|
+
iconSize: new $googlemaps.Size(opts.icon.iconsize[0], opts.icon.iconsize[1]),
|
596
|
+
iconAnchor: new $googlemaps.Point(opts.icon.iconanchor[0], opts.icon.iconanchor[1]),
|
597
|
+
infoWindowAnchor: new $googlemaps.Size(opts.icon.infowindowanchor[0], opts.icon.infowindowanchor[1])
|
598
|
+
},
|
599
|
+
_gshadow = {
|
600
|
+
image: opts.icon.shadow,
|
601
|
+
iconSize: new $googlemaps.Size(opts.icon.shadowsize[0], opts.icon.shadowsize[1]),
|
602
|
+
anchor: new $googlemaps.Point(opts.icon.shadowanchor[0], opts.icon.shadowanchor[1])
|
603
|
+
};
|
604
|
+
|
605
|
+
// not very nice, but useful
|
606
|
+
marker.infoWindowAnchor = _gicon.infoWindowAnchor;
|
607
|
+
|
608
|
+
if (marker.icon) {
|
609
|
+
// Overwrite global options
|
610
|
+
if (marker.icon.image) { _gicon.image = marker.icon.image; }
|
611
|
+
if (marker.icon.iconsize) { _gicon.iconSize = new $googlemaps.Size(marker.icon.iconsize[0], marker.icon.iconsize[1]); }
|
612
|
+
|
613
|
+
if (marker.icon.iconanchor) { _gicon.iconAnchor = new $googlemaps.Point(marker.icon.iconanchor[0], marker.icon.iconanchor[1]); }
|
614
|
+
if (marker.icon.infowindowanchor) { _gicon.infoWindowAnchor = new $googlemaps.Size(marker.icon.infowindowanchor[0], marker.icon.infowindowanchor[1]); }
|
615
|
+
|
616
|
+
if (marker.icon.shadow) { _gshadow.image = marker.icon.shadow; }
|
617
|
+
if (marker.icon.shadowsize) { _gshadow.iconSize = new $googlemaps.Size(marker.icon.shadowsize[0], marker.icon.shadowsize[1]); }
|
618
|
+
|
619
|
+
if (marker.icon.shadowanchor) { _gshadow.anchor = new $googlemaps.Point(marker.icon.shadowanchor[0], marker.icon.shadowanchor[1]); }
|
620
|
+
}
|
621
|
+
|
622
|
+
var gicon = new $googlemaps.MarkerImage(_gicon.image, _gicon.iconSize, null, _gicon.iconAnchor);
|
623
|
+
var gshadow = new $googlemaps.MarkerImage( _gshadow.image,_gshadow.iconSize, null, _gshadow.anchor);
|
624
|
+
|
625
|
+
// Check if address is available
|
626
|
+
if (marker.address) {
|
627
|
+
// Check for reference to the marker's address
|
628
|
+
if (marker.html === '_address') {
|
629
|
+
marker.html = marker.address;
|
630
|
+
}
|
631
|
+
|
632
|
+
if (marker.title == '_address') {
|
633
|
+
marker.title = marker.address;
|
634
|
+
}
|
635
|
+
|
636
|
+
if (opts.log) {console.log('geocoding marker: ' + marker.address); }
|
637
|
+
// Get the point for given address
|
638
|
+
$markersToLoad += 1;
|
639
|
+
methods._delayedMode = true;
|
640
|
+
methods._geocodeMarker.apply(this, [marker, gicon, gshadow]);
|
641
|
+
} else {
|
642
|
+
// Check for reference to the marker's latitude/longitude
|
643
|
+
if (marker.html === '_latlng') {
|
644
|
+
marker.html = marker.latitude + ', ' + marker.longitude;
|
645
|
+
}
|
646
|
+
|
647
|
+
if (marker.title == '_latlng') {
|
648
|
+
marker.title = marker.latitude + ', ' + marker.longitude;
|
649
|
+
}
|
650
|
+
|
651
|
+
// Create marker
|
652
|
+
var gpoint = new $googlemaps.LatLng(marker.latitude, marker.longitude);
|
653
|
+
methods._processMarker.apply(this, [marker, gicon, gshadow, gpoint]);
|
654
|
+
}
|
655
|
+
},
|
656
|
+
|
657
|
+
/**
|
658
|
+
*
|
659
|
+
*/
|
660
|
+
removeAllMarkers: function () {
|
661
|
+
var markers = this.data('gmap').markers, i;
|
662
|
+
|
663
|
+
for (i = 0; i < markers.length; i += 1) {
|
664
|
+
markers[i].setMap(null);
|
665
|
+
delete markers[i];
|
666
|
+
}
|
667
|
+
markers.length = 0;
|
668
|
+
},
|
669
|
+
|
670
|
+
/**
|
671
|
+
* get marker by key, if set previously
|
672
|
+
* @param key
|
673
|
+
*/
|
674
|
+
getMarker: function (key) {
|
675
|
+
return this.data('gmap').markerKeys[key];
|
676
|
+
},
|
677
|
+
|
678
|
+
/**
|
679
|
+
* should be called if DOM element was resized
|
680
|
+
* @param nasty
|
681
|
+
*/
|
682
|
+
fixAfterResize: function (nasty) {
|
683
|
+
var data = this.data('gmap');
|
684
|
+
$googlemaps.event.trigger(data.gmap, 'resize');
|
685
|
+
|
686
|
+
if(nasty) {
|
687
|
+
data.gmap.panTo(new google.maps.LatLng(0,0));
|
688
|
+
}
|
689
|
+
data.gmap.panTo(this.gMap('_getMapCenter', data.opts));
|
690
|
+
},
|
691
|
+
|
692
|
+
/**
|
693
|
+
* change zoom, works with 'fit' option as well
|
694
|
+
* @param zoom
|
695
|
+
*/
|
696
|
+
setZoom: function (zoom, opts, fromMarkers) {
|
697
|
+
var $map = this.data('gmap').gmap;
|
698
|
+
if (zoom === "fit"){
|
699
|
+
zoom = methods._autoZoom.apply(this, [opts, fromMarkers]);
|
700
|
+
}
|
701
|
+
$map.setZoom(parseInt(zoom));
|
702
|
+
},
|
703
|
+
|
704
|
+
changeSettings: function (options) {
|
705
|
+
var data = this.data('gmap'),
|
706
|
+
markers = [], i;
|
707
|
+
for (i = 0; i < data.markers.length; i += 1) {
|
708
|
+
markers[i] = {
|
709
|
+
latitude: data.markers[i].getPosition().lat(),
|
710
|
+
longitude: data.markers[i].getPosition().lng()
|
711
|
+
}
|
712
|
+
}
|
713
|
+
options.markers = markers;
|
714
|
+
|
715
|
+
if(options.zoom) methods.setZoom.apply(this,[options.zoom, options]);
|
716
|
+
if(options.latitude || options.longitude) {
|
717
|
+
data.gmap.panTo(methods._getMapCenter.apply(this,[options]));
|
718
|
+
}
|
719
|
+
|
720
|
+
// add controls and maptype
|
721
|
+
},
|
722
|
+
|
723
|
+
mapclick: function(callback) {
|
724
|
+
google.maps.event.addListener(this.data('gmap').gmap, 'click', function(event) {
|
725
|
+
callback(event.latLng);
|
726
|
+
});
|
727
|
+
},
|
728
|
+
|
729
|
+
geocode: function(address, callback, errorCallback) {
|
730
|
+
$geocoder.geocode({'address': address}, function (results, status) {
|
731
|
+
if (status === $googlemaps.GeocoderStatus.OK) {
|
732
|
+
callback(results[0].geometry.location);
|
733
|
+
} else if(errorCallback) {
|
734
|
+
errorCallback(results, status);
|
735
|
+
}
|
736
|
+
});
|
737
|
+
},
|
738
|
+
|
739
|
+
getRoute: function (options) {
|
740
|
+
|
741
|
+
var $data = this.data('gmap'),
|
742
|
+
$gmap = $data.gmap,
|
743
|
+
$directionsDisplay = new $googlemaps.DirectionsRenderer(),
|
744
|
+
$directionsService = new $googlemaps.DirectionsService(),
|
745
|
+
$travelModes = { 'BYCAR': $googlemaps.DirectionsTravelMode.DRIVING, 'BYBICYCLE': $googlemaps.DirectionsTravelMode.BICYCLING, 'BYFOOT': $googlemaps.DirectionsTravelMode.WALKING },
|
746
|
+
$travelUnits = { 'MILES': $googlemaps.DirectionsUnitSystem.IMPERIAL, 'KM': $googlemaps.DirectionsUnitSystem.METRIC },
|
747
|
+
displayObj = null,
|
748
|
+
travelMode = null,
|
749
|
+
travelUnit = null,
|
750
|
+
unitSystem = null;
|
751
|
+
|
752
|
+
// look if there is an individual or otherwise a default object for this call to display route text informations
|
753
|
+
if(options.routeDisplay !== undefined){
|
754
|
+
displayObj = (options.routeDisplay instanceof jQuery) ? options.routeDisplay[0] : ((typeof options.routeDisplay == "string") ? $(options.routeDisplay)[0] : null);
|
755
|
+
} else if($data.opts.routeFinder.routeDisplay !== null){
|
756
|
+
displayObj = ($data.opts.routeFinder.routeDisplay instanceof jQuery) ? $data.opts.routeFinder.routeDisplay[0] : ((typeof $data.opts.routeFinder.routeDisplay == "string") ? $($data.opts.routeFinder.routeDisplay)[0] : null);
|
757
|
+
}
|
758
|
+
|
759
|
+
// set route renderer to map
|
760
|
+
$directionsDisplay.setMap($gmap);
|
761
|
+
if(displayObj !== null){
|
762
|
+
$directionsDisplay.setPanel(displayObj);
|
763
|
+
}
|
764
|
+
|
765
|
+
// get travel mode and unit
|
766
|
+
travelMode = ($travelModes[$data.opts.routeFinder.travelMode] !== undefined) ? $travelModes[$data.opts.routeFinder.travelMode] : $travelModes['BYCAR'];
|
767
|
+
travelUnit = ($travelUnits[$data.opts.routeFinder.travelUnit] !== undefined) ? $travelUnits[$data.opts.routeFinder.travelUnit] : $travelUnits['KM'];
|
768
|
+
|
769
|
+
// build request
|
770
|
+
var request = {
|
771
|
+
origin: options.from,
|
772
|
+
destination: options.to,
|
773
|
+
travelMode: travelMode,
|
774
|
+
unitSystem: travelUnit
|
775
|
+
};
|
776
|
+
|
777
|
+
// send request
|
778
|
+
$directionsService.route(request, function(result, status) {
|
779
|
+
// show the rout or otherwise show an error message in a defined container for route text information
|
780
|
+
if (status == $googlemaps.DirectionsStatus.OK) {
|
781
|
+
$directionsDisplay.setDirections(result);
|
782
|
+
} else if(displayObj !== null){
|
783
|
+
$(displayObj).html($data.opts.routeFinder.routeErrors[status]);
|
784
|
+
}
|
785
|
+
});
|
786
|
+
return this;
|
787
|
+
}
|
788
|
+
};
|
789
|
+
|
790
|
+
|
791
|
+
// Main plugin function
|
792
|
+
$.fn.gMap = function (method) {
|
793
|
+
// Method calling logic
|
794
|
+
if (methods[method]) {
|
795
|
+
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
|
796
|
+
} else if (typeof method === 'object' || !method) {
|
797
|
+
return methods.init.apply(this, arguments);
|
798
|
+
} else {
|
799
|
+
$.error('Method ' + method + ' does not exist on jQuery.gmap');
|
800
|
+
}
|
801
|
+
};
|
802
|
+
|
803
|
+
// Default settings
|
804
|
+
$.fn.gMap.defaults = {
|
805
|
+
log: false,
|
806
|
+
address: '',
|
807
|
+
latitude: null,
|
808
|
+
longitude: null,
|
809
|
+
zoom: 3,
|
810
|
+
maxZoom: null,
|
811
|
+
minZoom: null,
|
812
|
+
markers: [],
|
813
|
+
controls: {},
|
814
|
+
scrollwheel: true,
|
815
|
+
maptype: google.maps.MapTypeId.ROADMAP,
|
816
|
+
|
817
|
+
mapTypeControl: true,
|
818
|
+
zoomControl: true,
|
819
|
+
panControl: false,
|
820
|
+
scaleControl: false,
|
821
|
+
streetViewControl: true,
|
822
|
+
|
823
|
+
controlsPositions: {
|
824
|
+
mapType: null,
|
825
|
+
zoom: null,
|
826
|
+
pan: null,
|
827
|
+
scale: null,
|
828
|
+
streetView: null
|
829
|
+
},
|
830
|
+
controlsStyle: {
|
831
|
+
mapType: google.maps.MapTypeControlStyle.DEFAULT,
|
832
|
+
zoom: google.maps.ZoomControlStyle.DEFAULT
|
833
|
+
},
|
834
|
+
|
835
|
+
singleInfoWindow: true,
|
836
|
+
|
837
|
+
html_prepend: '<div class="gmap_marker">',
|
838
|
+
html_append: '</div>',
|
839
|
+
icon: {
|
840
|
+
image: "http://www.google.com/mapfiles/marker.png",
|
841
|
+
iconsize: [20, 34],
|
842
|
+
iconanchor: [9, 34],
|
843
|
+
infowindowanchor: [9, 2],
|
844
|
+
shadow: "http://www.google.com/mapfiles/shadow50.png",
|
845
|
+
shadowsize: [37, 34],
|
846
|
+
shadowanchor: [9, 34]
|
847
|
+
},
|
848
|
+
|
849
|
+
onComplete: function () {},
|
850
|
+
|
851
|
+
routeFinder: {
|
852
|
+
travelMode: 'BYCAR',
|
853
|
+
travelUnit: 'KM',
|
854
|
+
routeDisplay: null,
|
855
|
+
routeErrors: {
|
856
|
+
'INVALID_REQUEST': 'The provided request is invalid.',
|
857
|
+
'NOT_FOUND': 'One or more of the given addresses could not be found.',
|
858
|
+
'OVER_QUERY_LIMIT': 'A temporary error occured. Please try again in a few minutes.',
|
859
|
+
'REQUEST_DENIED': 'An error occured. Please contact us.',
|
860
|
+
'UNKNOWN_ERROR': 'An unknown error occured. Please try again.',
|
861
|
+
'ZERO_RESULTS': 'No route could be found within the given addresses.'
|
862
|
+
}
|
863
|
+
},
|
864
|
+
|
865
|
+
clustering: {
|
866
|
+
enabled: false,
|
867
|
+
fastClustering: false,
|
868
|
+
clusterCount: 10,
|
869
|
+
clusterSize: 40 //radius as % of viewport width
|
870
|
+
}
|
871
|
+
};
|
872
|
+
}(jQuery));
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gmap-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 15
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 3
|
8
|
+
- 3
|
9
|
+
- 2
|
10
|
+
version: 3.3.2
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- bokmann
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-09-07 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rake
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
description: "gmap is a helpful little Javascript library by Sebastian Por\xC4\x99ba. I'm just turning it into an asset gem for the rails asset pipeline."
|
36
|
+
email:
|
37
|
+
- dbock@codesherpas.com
|
38
|
+
executables: []
|
39
|
+
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files: []
|
43
|
+
|
44
|
+
files:
|
45
|
+
- .gitignore
|
46
|
+
- LICENSE
|
47
|
+
- README.md
|
48
|
+
- Rakefile
|
49
|
+
- gemfile
|
50
|
+
- gmap-rails.gemspec
|
51
|
+
- lib/gmap-rails.rb
|
52
|
+
- lib/gmap-rails/version.rb
|
53
|
+
- vendor/assets/javascripts/jquery.gmap.js
|
54
|
+
has_rdoc: true
|
55
|
+
homepage: https://github.com/bokmann/fullcalendar-rails
|
56
|
+
licenses: []
|
57
|
+
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
hash: 3
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
version: "0"
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
hash: 3
|
78
|
+
segments:
|
79
|
+
- 0
|
80
|
+
version: "0"
|
81
|
+
requirements: []
|
82
|
+
|
83
|
+
rubyforge_project:
|
84
|
+
rubygems_version: 1.6.2
|
85
|
+
signing_key:
|
86
|
+
specification_version: 3
|
87
|
+
summary: A simple asset pipeline bundling of the gmap javascript library.
|
88
|
+
test_files: []
|
89
|
+
|