ym4r_gm 0.2.0
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/.document +5 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +22 -0
- data/README.md +467 -0
- data/Rakefile +54 -0
- data/VERSION +2 -0
- data/gmaps_api_key.yml.sample +14 -0
- data/init.rb +3 -0
- data/install.rb +10 -0
- data/javascript/clusterer.js +444 -0
- data/javascript/geoRssOverlay.js +194 -0
- data/javascript/markerGroup.js +114 -0
- data/javascript/wms-gs.js +69 -0
- data/javascript/ym4r-gm.js +117 -0
- data/lib/gm_plugin/control.rb +107 -0
- data/lib/gm_plugin/encoder.rb +395 -0
- data/lib/gm_plugin/geocoding.rb +118 -0
- data/lib/gm_plugin/helper.rb +72 -0
- data/lib/gm_plugin/key.rb +37 -0
- data/lib/gm_plugin/layer.rb +126 -0
- data/lib/gm_plugin/map.rb +301 -0
- data/lib/gm_plugin/mapping.rb +129 -0
- data/lib/gm_plugin/overlay.rb +400 -0
- data/lib/gm_plugin/point.rb +34 -0
- data/lib/tasks/gm_tasks.rake +4 -0
- data/lib/ym4r_gm.rb +12 -0
- data/rakefile.rb +22 -0
- data/test/gm_test.rb +91 -0
- data/ym4r_gm.gemspec +83 -0
- metadata +161 -0
data/Rakefile
ADDED
@@ -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,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
data/install.rb
ADDED
@@ -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
|
+
}
|