ym4r_gm 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,54 @@
1
+ # coding: utf-8
2
+ require 'rubygems'
3
+ require 'bundler'
4
+ begin
5
+ Bundler.setup(:default, :development)
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle install` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+ require 'rake'
12
+
13
+ require 'jeweler'
14
+ Jeweler::Tasks.new do |gem|
15
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
16
+ gem.name = "ym4r_gm"
17
+ gem.homepage = "http://github.com/grzegorzblaszczyk/ym4r_gm"
18
+ gem.license = "MIT"
19
+ gem.summary = %Q{Fork of YM4R_GM for Rails 3 and Ruby 1.9.2}
20
+ gem.description = %Q{Fork of YM4R_GM for Rails 3 and Ruby 1.9.2}
21
+ gem.email = "grzegorz.blaszczyk@gmail.com"
22
+ gem.authors = ["Grzegorz Błaszczyk"]
23
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
24
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
25
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
26
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
27
+ end
28
+ Jeweler::RubygemsDotOrgTasks.new
29
+
30
+ require 'rake/testtask'
31
+ Rake::TestTask.new(:test) do |test|
32
+ test.libs << 'lib' << 'test'
33
+ test.pattern = 'test/**/test_*.rb'
34
+ test.verbose = true
35
+ end
36
+
37
+ require 'rcov/rcovtask'
38
+ Rcov::RcovTask.new do |test|
39
+ test.libs << 'test'
40
+ test.pattern = 'test/**/test_*.rb'
41
+ test.verbose = true
42
+ end
43
+
44
+ task :default => :test
45
+
46
+ require 'rake/rdoctask'
47
+ Rake::RDocTask.new do |rdoc|
48
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
49
+
50
+ rdoc.rdoc_dir = 'rdoc'
51
+ rdoc.title = "ym4r_gm #{version}"
52
+ rdoc.rdoc_files.include('README*')
53
+ rdoc.rdoc_files.include('lib/**/*.rb')
54
+ end
data/VERSION ADDED
@@ -0,0 +1,2 @@
1
+ 0.2.0
2
+
@@ -0,0 +1,14 @@
1
+ #Fill here the Google Maps API keys for your application
2
+ #In this sample:
3
+ #For development and test, we have only one possible host (localhost:3000), so there is only a single key associated with the mode.
4
+ #In production, the app can be accessed through 2 different hosts: thepochisuperstarmegashow.com and exmaple.com. There then needs a 2-key hash. If you deployed to one host, only the API key would be needed (as in development and test).
5
+
6
+ development:
7
+ ABQIAAAAzMUFFnT9uH0xq39J0Y4kbhTJQa0g3IQ9GZqIMmInSLzwtGDKaBR6j135zrztfTGVOm2QlWnkaidDIQ
8
+
9
+ test:
10
+ ABQIAAAAzMUFFnT9uH0xq39J0Y4kbhTJQa0g3IQ9GZqIMmInSLzwtGDKaBR6j135zrztfTGVOm2QlWnkaidDIQ
11
+
12
+ production:
13
+ thepochisuperstarmegashow.com: ABQIAAAAzMUFFnT9uH0Sfg76Y4kbhTJQa0g3IQ9GZqIMmInSLzwtGDmlRT6e90j135zat56yhJKQlWnkaidDIQ
14
+ example.com: ABQIAAAAzMUFFnT9uH0Sfg98Y4kbhGFJQa0g3IQ9GZqIMmInSLrthJKGDmlRT98f4j135zat56yjRKQlWnkmod3TB
data/init.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'ym4r_gm'
2
+
3
+
@@ -0,0 +1,10 @@
1
+ require 'fileutils'
2
+
3
+ #Copy the Javascript files
4
+ FileUtils.copy(Dir[File.dirname(__FILE__) + '/javascript/*.js'], File.dirname(__FILE__) + '/../../../public/javascripts/')
5
+
6
+ #copy the gmaps_api_key file
7
+ gmaps_config = File.dirname(__FILE__) + '/../../../config/gmaps_api_key.yml'
8
+ unless File.exist?(gmaps_config)
9
+ FileUtils.copy(File.dirname(__FILE__) + '/gmaps_api_key.yml.sample',gmaps_config)
10
+ end
@@ -0,0 +1,444 @@
1
+ // Clusterer.js - marker clustering routines for Google Maps apps
2
+ //
3
+ // The original version of this code is available at:
4
+ // http://www.acme.com/javascript/
5
+ //
6
+ // Copyright � 2005,2006 by Jef Poskanzer <jef@mail.acme.com>.
7
+ // All rights reserved.
8
+ //
9
+ // Modified for inclusion into the YM4R library in accordance with the
10
+ // following license:
11
+ //
12
+ // Redistribution and use in source and binary forms, with or without
13
+ // modification, are permitted provided that the following conditions
14
+ // are met:
15
+ // 1. Redistributions of source code must retain the above copyright
16
+ // notice, this list of conditions and the following disclaimer.
17
+ // 2. Redistributions in binary form must reproduce the above copyright
18
+ // notice, this list of conditions and the following disclaimer in the
19
+ // documentation and/or other materials provided with the distribution.
20
+ //
21
+ // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22
+ // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
+ // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25
+ // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
+ // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
+ // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
+ // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
+ // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
+ // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
+ // SUCH DAMAGE.
32
+ //
33
+ // For commentary on this license please see http://www.acme.com/license.html
34
+
35
+
36
+ // Constructor.
37
+ Clusterer = function(markers,icon,maxVisibleMarkers,gridSize,minMarkersPerCluster,maxLinesPerInfoBox) {
38
+ this.markers = [];
39
+ if(markers){
40
+ for(var i =0 ; i< markers.length ; i++){
41
+ this.addMarker(markers[i]);
42
+ }
43
+ }
44
+ this.clusters = [];
45
+ this.timeout = null;
46
+
47
+ this.maxVisibleMarkers = maxVisibleMarkers || 150;
48
+ this.gridSize = gridSize || 5;
49
+ this.minMarkersPerCluster = minMarkersPerCluster || 5;
50
+ this.maxLinesPerInfoBox = maxLinesPerInfoBox || 10;
51
+
52
+ this.icon = icon || G_DEFAULT_ICON;
53
+ }
54
+
55
+ Clusterer.prototype = new GOverlay();
56
+
57
+ Clusterer.prototype.initialize = function ( map ){
58
+ this.map = map;
59
+ this.currentZoomLevel = map.getZoom();
60
+
61
+ GEvent.addListener( map, 'zoomend', Clusterer.makeCaller( Clusterer.display, this ) );
62
+ GEvent.addListener( map, 'moveend', Clusterer.makeCaller( Clusterer.display, this ) );
63
+ GEvent.addListener( map, 'infowindowclose', Clusterer.makeCaller( Clusterer.popDown, this ) );
64
+ //Set map for each marker
65
+ for(var i = 0,len = this.markers.length ; i < len ; i++){
66
+ this.markers[i].setMap( map );
67
+ }
68
+ this.displayLater();
69
+ }
70
+
71
+ Clusterer.prototype.remove = function(){
72
+ for ( var i = 0; i < this.markers.length; ++i ){
73
+ this.removeMarker(this.markers[i]);
74
+ }
75
+ }
76
+
77
+ Clusterer.prototype.copy = function(){
78
+ return new Clusterer(this.markers,this.icon,this.maxVisibleMarkers,this.gridSize,this.minMarkersPerCluster,this.maxLinesPerInfoBox);
79
+ }
80
+
81
+ Clusterer.prototype.redraw = function(force){
82
+ this.displayLater();
83
+ }
84
+
85
+ // Call this to change the cluster icon.
86
+ Clusterer.prototype.setIcon = function ( icon ){
87
+ this.icon = icon;
88
+ }
89
+
90
+ // Call this to add a marker.
91
+ Clusterer.prototype.addMarker = function ( marker, description){
92
+ marker.onMap = false;
93
+ this.markers.push( marker );
94
+ marker.description = marker.description || description;
95
+ if(this.map != null){
96
+ marker.setMap(this.map);
97
+ this.displayLater();
98
+ }
99
+ };
100
+
101
+
102
+ // Call this to remove a marker.
103
+ Clusterer.prototype.removeMarker = function ( marker ){
104
+ for ( var i = 0; i < this.markers.length; ++i )
105
+ if ( this.markers[i] == marker ){
106
+ if ( marker.onMap )
107
+ this.map.removeOverlay( marker );
108
+ for ( var j = 0; j < this.clusters.length; ++j ){
109
+ var cluster = this.clusters[j];
110
+ if ( cluster != null ){
111
+ for ( var k = 0; k < cluster.markers.length; ++k )
112
+ if ( cluster.markers[k] == marker ){
113
+ cluster.markers[k] = null;
114
+ --cluster.markerCount;
115
+ break;
116
+ }
117
+ if ( cluster.markerCount == 0 ){
118
+ this.clearCluster( cluster );
119
+ this.clusters[j] = null;
120
+ }
121
+ else if ( cluster == this.poppedUpCluster )
122
+ Clusterer.rePop( this );
123
+ }
124
+ }
125
+ this.markers[i] = null;
126
+ break;
127
+ }
128
+ this.displayLater();
129
+ };
130
+
131
+ Clusterer.prototype.displayLater = function (){
132
+ if ( this.timeout != null )
133
+ clearTimeout( this.timeout );
134
+ this.timeout = setTimeout( Clusterer.makeCaller( Clusterer.display, this ), 50 );
135
+ };
136
+
137
+ Clusterer.display = function ( clusterer ){
138
+ var i, j, marker, cluster, len, len2;
139
+
140
+ clearTimeout( clusterer.timeout );
141
+
142
+ var newZoomLevel = clusterer.map.getZoom();
143
+ if ( newZoomLevel != clusterer.currentZoomLevel ){
144
+ // When the zoom level changes, we have to remove all the clusters.
145
+ for ( i = 0 , len = clusterer.clusters.length; i < len; ++i ){
146
+ if ( clusterer.clusters[i] != null ){
147
+ clusterer.clearCluster( clusterer.clusters[i] );
148
+ clusterer.clusters[i] = null;
149
+ }
150
+ }
151
+ clusterer.clusters.length = 0;
152
+ clusterer.currentZoomLevel = newZoomLevel;
153
+ }
154
+
155
+ // Get the current bounds of the visible area.
156
+ var bounds = clusterer.map.getBounds();
157
+
158
+ // Expand the bounds a little, so things look smoother when scrolling
159
+ // by small amounts.
160
+ var sw = bounds.getSouthWest();
161
+ var ne = bounds.getNorthEast();
162
+ var dx = ne.lng() - sw.lng();
163
+ var dy = ne.lat() - sw.lat();
164
+ dx *= 0.10;
165
+ dy *= 0.10;
166
+ bounds = new GLatLngBounds(
167
+ new GLatLng( sw.lat() - dy, sw.lng() - dx ),
168
+ new GLatLng( ne.lat() + dy, ne.lng() + dx )
169
+ );
170
+
171
+ // Partition the markers into visible and non-visible lists.
172
+ var visibleMarkers = [];
173
+ var nonvisibleMarkers = [];
174
+ for ( i = 0, len = clusterer.markers.length ; i < len; ++i ){
175
+ marker = clusterer.markers[i];
176
+ if ( marker != null )
177
+ if ( bounds.contains( marker.getPoint() ) )
178
+ visibleMarkers.push( marker );
179
+ else
180
+ nonvisibleMarkers.push( marker );
181
+ }
182
+
183
+ // Take down the non-visible markers.
184
+ for ( i = 0, len = nonvisibleMarkers.length ; i < len; ++i ){
185
+ marker = nonvisibleMarkers[i];
186
+ if ( marker.onMap ){
187
+ clusterer.map.removeOverlay( marker );
188
+ marker.onMap = false;
189
+ }
190
+ }
191
+
192
+ // Take down the non-visible clusters.
193
+ for ( i = 0, len = clusterer.clusters.length ; i < len ; ++i ){
194
+ cluster = clusterer.clusters[i];
195
+ if ( cluster != null && ! bounds.contains( cluster.marker.getPoint() ) && cluster.onMap ){
196
+ clusterer.map.removeOverlay( cluster.marker );
197
+ cluster.onMap = false;
198
+ }
199
+ }
200
+
201
+ // Clustering! This is some complicated stuff. We have three goals
202
+ // here. One, limit the number of markers & clusters displayed, so the
203
+ // maps code doesn't slow to a crawl. Two, when possible keep existing
204
+ // clusters instead of replacing them with new ones, so that the app pans
205
+ // better. And three, of course, be CPU and memory efficient.
206
+ if ( visibleMarkers.length > clusterer.maxVisibleMarkers ){
207
+ // Add to the list of clusters by splitting up the current bounds
208
+ // into a grid.
209
+ var latRange = bounds.getNorthEast().lat() - bounds.getSouthWest().lat();
210
+ var latInc = latRange / clusterer.gridSize;
211
+ var lngInc = latInc / Math.cos( ( bounds.getNorthEast().lat() + bounds.getSouthWest().lat() ) / 2.0 * Math.PI / 180.0 );
212
+ for ( var lat = bounds.getSouthWest().lat(); lat <= bounds.getNorthEast().lat(); lat += latInc )
213
+ for ( var lng = bounds.getSouthWest().lng(); lng <= bounds.getNorthEast().lng(); lng += lngInc ){
214
+ cluster = new Object();
215
+ cluster.clusterer = clusterer;
216
+ cluster.bounds = new GLatLngBounds( new GLatLng( lat, lng ), new GLatLng( lat + latInc, lng + lngInc ) );
217
+ cluster.markers = [];
218
+ cluster.markerCount = 0;
219
+ cluster.onMap = false;
220
+ cluster.marker = null;
221
+ clusterer.clusters.push( cluster );
222
+ }
223
+
224
+ // Put all the unclustered visible markers into a cluster - the first
225
+ // one it fits in, which favors pre-existing clusters.
226
+ for ( i = 0, len = visibleMarkers.length ; i < len; ++i ){
227
+ marker = visibleMarkers[i];
228
+ if ( marker != null && ! marker.inCluster ){
229
+ for ( j = 0, len2 = clusterer.clusters.length ; j < len2 ; ++j ){
230
+ cluster = clusterer.clusters[j];
231
+ if ( cluster != null && cluster.bounds.contains( marker.getPoint() ) ){
232
+ cluster.markers.push( marker );
233
+ ++cluster.markerCount;
234
+ marker.inCluster = true;
235
+ }
236
+ }
237
+ }
238
+ }
239
+
240
+ // Get rid of any clusters containing only a few markers.
241
+ for ( i = 0, len = clusterer.clusters.length ; i < len ; ++i )
242
+ if ( clusterer.clusters[i] != null && clusterer.clusters[i].markerCount < clusterer.minMarkersPerCluster ){
243
+ clusterer.clearCluster( clusterer.clusters[i] );
244
+ clusterer.clusters[i] = null;
245
+ }
246
+
247
+ // Shrink the clusters list.
248
+ for ( i = clusterer.clusters.length - 1; i >= 0; --i )
249
+ if ( clusterer.clusters[i] != null )
250
+ break;
251
+ else
252
+ --clusterer.clusters.length;
253
+
254
+ // Ok, we have our clusters. Go through the markers in each
255
+ // cluster and remove them from the map if they are currently up.
256
+ for ( i = 0, len = clusterer.clusters.length ; i < len; ++i ){
257
+ cluster = clusterer.clusters[i];
258
+ if ( cluster != null ){
259
+ for ( j = 0 , len2 = cluster.markers.length ; j < len2; ++j ){
260
+ marker = cluster.markers[j];
261
+ if ( marker != null && marker.onMap ){
262
+ clusterer.map.removeOverlay( marker );
263
+ marker.onMap = false;
264
+ }
265
+ }
266
+ }
267
+ }
268
+
269
+ // Now make cluster-markers for any clusters that need one.
270
+ for ( i = 0, len = clusterer.clusters.length; i < len; ++i ){
271
+ cluster = clusterer.clusters[i];
272
+ if ( cluster != null && cluster.marker == null ){
273
+ // Figure out the average coordinates of the markers in this
274
+ // cluster.
275
+ var xTotal = 0.0, yTotal = 0.0;
276
+ for ( j = 0, len2 = cluster.markers.length; j < len2 ; ++j ){
277
+ marker = cluster.markers[j];
278
+ if ( marker != null ){
279
+ xTotal += ( + marker.getPoint().lng() );
280
+ yTotal += ( + marker.getPoint().lat() );
281
+ }
282
+ }
283
+ var location = new GLatLng( yTotal / cluster.markerCount, xTotal / cluster.markerCount );
284
+ marker = new GMarker( location, { icon: clusterer.icon } );
285
+ cluster.marker = marker;
286
+ GEvent.addListener( marker, 'click', Clusterer.makeCaller( Clusterer.popUp, cluster ) );
287
+ }
288
+ }
289
+ }
290
+
291
+ // Display the visible markers not already up and not in clusters.
292
+ for ( i = 0, len = visibleMarkers.length; i < len; ++i ){
293
+ marker = visibleMarkers[i];
294
+ if ( marker != null && ! marker.onMap && ! marker.inCluster )
295
+ {
296
+ clusterer.map.addOverlay( marker );
297
+ marker.addedToMap();
298
+ marker.onMap = true;
299
+ }
300
+ }
301
+
302
+ // Display the visible clusters not already up.
303
+ for ( i = 0, len = clusterer.clusters.length ; i < len; ++i ){
304
+ cluster = clusterer.clusters[i];
305
+ if ( cluster != null && ! cluster.onMap && bounds.contains( cluster.marker.getPoint() )){
306
+ clusterer.map.addOverlay( cluster.marker );
307
+ cluster.onMap = true;
308
+ }
309
+ }
310
+
311
+ // In case a cluster is currently popped-up, re-pop to get any new
312
+ // markers into the infobox.
313
+ Clusterer.rePop( clusterer );
314
+ };
315
+
316
+
317
+ Clusterer.popUp = function ( cluster ){
318
+ var clusterer = cluster.clusterer;
319
+ var html = '<table width="300">';
320
+ var n = 0;
321
+ for ( var i = 0 , len = cluster.markers.length; i < len; ++i )
322
+ {
323
+ var marker = cluster.markers[i];
324
+ if ( marker != null )
325
+ {
326
+ ++n;
327
+ html += '<tr><td>';
328
+ if ( marker.getIcon().smallImage != null )
329
+ html += '<img src="' + marker.getIcon().smallImage + '">';
330
+ else
331
+ html += '<img src="' + marker.getIcon().image + '" width="' + ( marker.getIcon().iconSize.width / 2 ) + '" height="' + ( marker.getIcon().iconSize.height / 2 ) + '">';
332
+ html += '</td><td>' + marker.description + '</td></tr>';
333
+ if ( n == clusterer.maxLinesPerInfoBox - 1 && cluster.markerCount > clusterer.maxLinesPerInfoBox )
334
+ {
335
+ html += '<tr><td colspan="2">...and ' + ( cluster.markerCount - n ) + ' more</td></tr>';
336
+ break;
337
+ }
338
+ }
339
+ }
340
+ html += '</table>';
341
+ clusterer.map.closeInfoWindow();
342
+ cluster.marker.openInfoWindowHtml( html );
343
+ clusterer.poppedUpCluster = cluster;
344
+ };
345
+
346
+ Clusterer.rePop = function ( clusterer ){
347
+ if ( clusterer.poppedUpCluster != null )
348
+ Clusterer.popUp( clusterer.poppedUpCluster );
349
+ };
350
+
351
+ Clusterer.popDown = function ( clusterer ){
352
+ clusterer.poppedUpCluster = null;
353
+ };
354
+
355
+ Clusterer.prototype.clearCluster = function ( cluster ){
356
+ var i, marker;
357
+
358
+ for ( i = 0; i < cluster.markers.length; ++i ){
359
+ if ( cluster.markers[i] != null ){
360
+ cluster.markers[i].inCluster = false;
361
+ cluster.markers[i] = null;
362
+ }
363
+ }
364
+
365
+ cluster.markers.length = 0;
366
+ cluster.markerCount = 0;
367
+
368
+ if ( cluster == this.poppedUpCluster )
369
+ this.map.closeInfoWindow();
370
+
371
+ if ( cluster.onMap )
372
+ {
373
+ this.map.removeOverlay( cluster.marker );
374
+ cluster.onMap = false;
375
+ }
376
+ };
377
+
378
+ // This returns a function closure that calls the given routine with the
379
+ // specified arg.
380
+ Clusterer.makeCaller = function ( func, arg ){
381
+ return function () { func( arg ); };
382
+ };
383
+
384
+
385
+ // Augment GMarker so it handles markers that have been created but
386
+ // not yet addOverlayed.
387
+ GMarker.prototype.setMap = function ( map ){
388
+ this.map = map;
389
+ };
390
+
391
+ GMarker.prototype.getMap = function (){
392
+ return this.map;
393
+ }
394
+
395
+ GMarker.prototype.addedToMap = function (){
396
+ this.map = null;
397
+ };
398
+
399
+
400
+ GMarker.prototype.origOpenInfoWindow = GMarker.prototype.openInfoWindow;
401
+ GMarker.prototype.openInfoWindow = function ( node, opts ){
402
+ if ( this.map != null )
403
+ return this.map.openInfoWindow( this.getPoint(), node, opts );
404
+ else
405
+ return this.origOpenInfoWindow( node, opts );
406
+ };
407
+
408
+ GMarker.prototype.origOpenInfoWindowHtml = GMarker.prototype.openInfoWindowHtml;
409
+ GMarker.prototype.openInfoWindowHtml = function ( html, opts ){
410
+ if ( this.map != null )
411
+ return this.map.openInfoWindowHtml( this.getPoint(), html, opts );
412
+ else
413
+ return this.origOpenInfoWindowHtml( html, opts );
414
+ };
415
+
416
+ GMarker.prototype.origOpenInfoWindowTabs = GMarker.prototype.openInfoWindowTabs;
417
+ GMarker.prototype.openInfoWindowTabs = function ( tabNodes, opts ){
418
+ if ( this.map != null )
419
+ return this.map.openInfoWindowTabs( this.getPoint(), tabNodes, opts );
420
+ else
421
+ return this.origOpenInfoWindowTabs( tabNodes, opts );
422
+ };
423
+
424
+ GMarker.prototype.origOpenInfoWindowTabsHtml = GMarker.prototype.openInfoWindowTabsHtml;
425
+ GMarker.prototype.openInfoWindowTabsHtml = function ( tabHtmls, opts ){
426
+ if ( this.map != null )
427
+ return this.map.openInfoWindowTabsHtml( this.getPoint(), tabHtmls, opts );
428
+ else
429
+ return this.origOpenInfoWindowTabsHtml( tabHtmls, opts );
430
+ };
431
+
432
+ GMarker.prototype.origShowMapBlowup = GMarker.prototype.showMapBlowup;
433
+ GMarker.prototype.showMapBlowup = function ( opts ){
434
+ if ( this.map != null )
435
+ return this.map.showMapBlowup( this.getPoint(), opts );
436
+ else
437
+ return this.origShowMapBlowup( opts );
438
+ };
439
+
440
+
441
+ function addDescriptionToMarker(marker, description){
442
+ marker.description = description;
443
+ return marker;
444
+ }