ym4r 0.4.1 → 0.5.1

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.
@@ -0,0 +1,28 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'ym4r/google_maps/geocoding'
4
+ require 'test/unit'
5
+
6
+ include Ym4r::GoogleMaps
7
+
8
+ class TestGmGeocoding< Test::Unit::TestCase
9
+ def test_google_maps_geocoding
10
+ placemarks = Ym4r::GoogleMaps::Geocoding.get("Rue Clovis Paris")
11
+ assert_equal(Ym4r::GoogleMaps::Geocoding::GEO_SUCCESS,placemarks.status)
12
+ assert_equal(1,placemarks.length)
13
+ placemark = placemarks[0]
14
+ assert_equal("FR",placemark.country_code)
15
+ assert_equal("Paris",placemark.locality)
16
+ assert_equal("75005",placemark.postal_code)
17
+ end
18
+
19
+ def test_google_maps_pakistan
20
+ placemarks = Ym4r::GoogleMaps::Geocoding.get("Lahore PK")
21
+ assert_equal(Ym4r::GoogleMaps::Geocoding::GEO_SUCCESS,placemarks.status)
22
+ assert_equal(1,placemarks.length)
23
+ placemark = placemarks[0]
24
+ assert_equal("PK",placemark.country_code)
25
+ assert_equal("Lahore",placemark.locality)
26
+ assert_equal("",placemark.thoroughfare)
27
+ end
28
+ end
data/tools/tile_image.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  $:.unshift(File.dirname(__FILE__) + '/../lib')
2
- require 'ym4r/google_maps/tiler/image_tiler'
2
+
3
+ require 'ym4r/google_maps/image_tiler'
3
4
  include Ym4r::GoogleMaps::Tiler
4
5
 
5
6
  require 'optparse'
data/tools/tile_wms.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  $:.unshift(File.dirname(__FILE__) + '/../lib')
2
- require 'ym4r/google_maps/tiler/wms_tiler'
2
+
3
+ require 'ym4r/google_maps/wms_tiler'
3
4
  include Ym4r::GoogleMaps::Tiler
4
5
 
5
6
  require 'optparse'
@@ -45,10 +46,10 @@ opts = OptionParser.new do |opts|
45
46
  opts.on("-g","--gmap-setting SETTING",WmsTiler::FurthestZoom,"Corner coordinates, furthest zoom level, tile width and height") do |fz|
46
47
  options.furthest_zoom = fz
47
48
  end
48
- opts.on("-w","--[no-]geographic","Query the WMS server with LatLon coordinates isntead of using the Mercator projection") do |g|
49
+ opts.on("-w","--[no-]geographic","Query the WMS server with LatLon coordinates instead of using the Mercator projection") do |g|
49
50
  options.geographic = g
50
51
  end
51
- opts.on("-e", "--epsg SRS","SRS to query the WMS server. Should be a the SRS id of a Simple Mercator projection. Can vary between WMS servers. Is 54004 (Simple Mercator for Mapserver) by default") do |srs|
52
+ opts.on("-e", "--epsg SRS","SRS to query the WMS server. Should be a the SRS id of a Simple Mercator projection. Can vary between WMS servers. Is 54004 (Simple Mercator for Mapserver) by default. For GeoServer use 41001.") do |srs|
52
53
  options.srs = srs
53
54
 
54
55
  end
metadata CHANGED
@@ -1,11 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.8.11
2
+ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: ym4r
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.4.1
7
- date: 2006-07-01 00:00:00 +05:00
8
- summary: Using Google Maps and Yahoo! Maps from Ruby and Rails
6
+ version: 0.5.1
7
+ date: 2006-07-09 00:00:00 +05:00
8
+ summary: Helping the use of Google Maps and Yahoo! Maps API's from Ruby and Rails
9
9
  require_paths:
10
10
  - lib
11
11
  email: guilhem.vellut+ym4r@gmail.com
@@ -25,6 +25,7 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
25
25
  platform: ruby
26
26
  signing_key:
27
27
  cert_chain:
28
+ post_install_message:
28
29
  authors:
29
30
  - Guilhem Vellut
30
31
  files:
@@ -32,41 +33,21 @@ files:
32
33
  - lib/ym4r/google_maps.rb
33
34
  - lib/ym4r/yahoo_maps.rb
34
35
  - lib/ym4r/google_maps/api_key.rb
35
- - lib/ym4r/google_maps/control.rb
36
36
  - lib/ym4r/google_maps/geocoding.rb
37
- - lib/ym4r/google_maps/helper.rb
38
- - lib/ym4r/google_maps/layer.rb
39
- - lib/ym4r/google_maps/map.rb
40
- - lib/ym4r/google_maps/mapping.rb
41
- - lib/ym4r/google_maps/overlay.rb
42
- - lib/ym4r/google_maps/point.rb
43
- - lib/ym4r/google_maps/geocoding/geocoding.rb
44
- - lib/ym4r/google_maps/tiler/image_tiler.rb
45
- - lib/ym4r/google_maps/tiler/wms_tiler.rb
37
+ - lib/ym4r/google_maps/image_tiler.rb
38
+ - lib/ym4r/google_maps/wms_tiler.rb
46
39
  - lib/ym4r/yahoo_maps/app_id.rb
47
40
  - lib/ym4r/yahoo_maps/building_block.rb
48
- - lib/ym4r/yahoo_maps/flash.rb
49
41
  - lib/ym4r/yahoo_maps/building_block/exception.rb
50
42
  - lib/ym4r/yahoo_maps/building_block/geocoding.rb
51
43
  - lib/ym4r/yahoo_maps/building_block/local_search.rb
52
44
  - lib/ym4r/yahoo_maps/building_block/map_image.rb
53
45
  - lib/ym4r/yahoo_maps/building_block/traffic.rb
54
- - lib/ym4r/yahoo_maps/flash/latlon.rb
55
- - lib/ym4r/yahoo_maps/flash/map.rb
56
- - lib/ym4r/yahoo_maps/flash/mapping.rb
57
- - lib/ym4r/yahoo_maps/flash/marker.rb
58
- - lib/ym4r/yahoo_maps/flash/overlay.rb
59
- - lib/ym4r/yahoo_maps/flash/tool.rb
60
- - lib/ym4r/yahoo_maps/flash/widget.rb
61
46
  - lib/ym4r/google_maps/config/config.yml
62
- - lib/ym4r/google_maps/javascript/clusterer.js
63
- - lib/ym4r/google_maps/javascript/geoRssOverlay.js
64
- - lib/ym4r/google_maps/javascript/markerGroup.js
65
- - lib/ym4r/google_maps/javascript/wms-gs.js
66
47
  - tools/tile_image.rb
67
48
  - tools/tile_wms.rb
68
49
  - test/test_geocoding.rb
69
- - test/test_google_maps.rb
50
+ - test/test_gm_geocoding.rb
70
51
  - test/test_local_search.rb
71
52
  - test/test_map_image.rb
72
53
  - test/test_traffic.rb
@@ -75,7 +56,7 @@ files:
75
56
  - rakefile.rb
76
57
  test_files:
77
58
  - test/test_geocoding.rb
78
- - test/test_google_maps.rb
59
+ - test/test_gm_geocoding.rb
79
60
  - test/test_local_search.rb
80
61
  - test/test_map_image.rb
81
62
  - test/test_traffic.rb
@@ -1,66 +0,0 @@
1
- require 'ym4r/google_maps/mapping'
2
-
3
- module Ym4r
4
- module GoogleMaps
5
- #Small map control. Report to the Google Maps API documentation for details.
6
- class GSmallMapControl
7
- include MappingObject
8
- def create
9
- "new GSmallMapControl()"
10
- end
11
- end
12
- #Large Map control. Report to the Google Maps API documentation for details.
13
- class GLargeMapControl
14
- include MappingObject
15
- def create
16
- "new GLargeMapControl()"
17
- end
18
- end
19
- #Small Zoom control. Report to the Google Maps API documentation for details.
20
- class GSmallZoomControl
21
- include MappingObject
22
- def create
23
- "new GSmallZoomControl()"
24
- end
25
- end
26
- #Scale control. Report to the Google Maps API documentation for details.
27
- class GScaleControl
28
- include MappingObject
29
- def create
30
- "new GScaleControl()"
31
- end
32
- end
33
- #Map type control. Report to the Google Maps API documentation for details.
34
- class GMapTypeControl
35
- include MappingObject
36
- def create
37
- "new GMapTypeControl()"
38
- end
39
- end
40
- #Overview map control. Report to the Google Maps API documentation for details.
41
- class GOverviewMapControl
42
- include MappingObject
43
- def create
44
- "new GOverviewMapControl()"
45
- end
46
- end
47
-
48
- #An object representing a position of a control.
49
- #The first argument of the constructor is one of the following : :top_right, :top_left, :bottom_right, :bottom_left.
50
- class GControlPosition < Struct.new(:anchor,:offset)
51
- include MappingObject
52
- def create
53
- js_anchor = if anchor == :top_right
54
- "G_ANCHOR_TOP_RIGHT"
55
- elsif anchor == :top_left
56
- "G_ANCHOR_TOP_LEFT"
57
- elsif anchor == :bottom_right
58
- "G_ANCHOR_BOTTOM_RIGHT"
59
- else
60
- "G_ANCHOR_BOTTOM_LEFT"
61
- end
62
- "new GControlPosition(#{js_anchor},#{offset})"
63
- end
64
- end
65
- end
66
- end
@@ -1,80 +0,0 @@
1
- require 'ym4r/google_maps/api_key'
2
- require 'open-uri'
3
- require 'rexml/document'
4
-
5
- module Ym4r
6
- module GoogleMaps
7
- module Geocoding
8
-
9
- GEO_SUCCESS = 200
10
- GEO_MISSING_ADDRESS = 601
11
- GEO_UNKNOWN_ADDRESS = 602
12
- GEO_UNAVAILABLE_ADDRESS = 603
13
- GEO_BAD_KEY = 610
14
- GEO_TOO_MANY_QUERIES = 620
15
- GEO_SERVER_ERROR = 500
16
-
17
- #Gets placemarks by querying the Google Maps Geocoding service with the +request+ string
18
- def self.get(request)
19
-
20
- url = "http://maps.google.com/maps/geo?q=#{request}&key=#{API_KEY}&output=xml"
21
- begin
22
- xml = open(URI.encode(url)).read
23
- rescue
24
- raise ConnectionException.new("Unable to connect to Google Maps Geocoding service")
25
- end
26
-
27
- doc = REXML::Document.new(xml)
28
-
29
- response = doc.elements['//Response']
30
- placemarks = Placemarks.new(response.elements['name'].text,response.elements['Status/code'].text.to_i)
31
- response.elements.each("Placemark") do |placemark|
32
- data = placemark.elements
33
- data_country = data['//CountryNameCode']
34
- data_administrative = data['//AdministrativeAreaName']
35
- data_sub_administrative = data['//SubAdministrativeAreaName']
36
- data_locality = data['//LocalityName']
37
- data_dependent_locality = data['//DependentLocalityName']
38
- data_thoroughfare = data['//ThoroughfareName']
39
- data_postal_code = data['//PostalCodeNumber']
40
- placemarks << Geocoding::Placemark.new(data['address'].text,
41
- data_country.nil? ? "" : data_country.text,
42
- data_administrative.nil? ? "" : data_administrative.text,
43
- data_sub_administrative.nil? ? "" : data_sub_administrative.text,
44
- data_locality.nil? ? "" : data_locality.text,
45
- data_dependent_locality.nil? ? "" : data_dependent_locality.text,
46
- data_thoroughfare.nil? ? "" : data_thoroughfare.text,
47
- data_postal_code.nil? ? "" : data_postal_code.text,
48
- *(data['//coordinates'].text.split(",")[0..1].collect {|l| l.to_f }))
49
- end
50
- placemarks
51
- end
52
-
53
- #Group of placemarks returned by the Geocoding service. If the result is valid the +statius+ attribute should be equal to <tt>Geocoding::GEI_SUCCESS</tt>
54
- class Placemarks < Array
55
- attr_accessor :name,:status
56
-
57
- def initialize(name,status)
58
- super(0)
59
- @name = name
60
- @status = status
61
- end
62
- end
63
-
64
- #A result from the Geocoding service.
65
- class Placemark < Struct.new(:address,:country_code,:administrative_area,:sub_administrative_area,:locality,:dependent_locality,:thoroughfare,:postal_code,:longitude,:latitude)
66
- def lonlat
67
- [longitude,latitude]
68
- end
69
-
70
- def latlon
71
- [latitude,longitude]
72
- end
73
- end
74
-
75
- #Raised when the connection to the service is not possible
76
- class ConnectionException < StandardError
77
- end
78
- end
79
- end
80
- end
@@ -1,22 +0,0 @@
1
-
2
- Ym4r::GoogleMaps::GPolyline.class_eval do
3
- #Creates a GPolyline object from a georuby line string. Assumes the points of the line strings are stored in Longitude(x)/Latitude(y) order.
4
- def self.from_georuby(line_string,color = nil,weight = nil,opacity = nil)
5
- GPolyline.new(line_string.points.collect { |point| GLatLng.new([point.y,point.x])},color,weight,opacity)
6
- end
7
- end
8
-
9
- Ym4r::GoogleMaps::GMarker.class_eval do
10
- #Creates a GMarker object from a georuby point. Accepts the same options as the GMarker constructor. Assumes the points of the line strings are stored in Longitude(x)/Latitude(y) order.
11
- def self.from_georuby(point,options = {})
12
- GMarker.new([point.y,point.x],options)
13
- end
14
- end
15
-
16
- Ym4r::GoogleMaps::GLatLng.class_eval do
17
- #Creates a GLatLng object from a georuby point. Assumes the points of the line strings are stored in Longitude(x)/Latitude(y) order.
18
- def self.from_georuby(point,unbounded = nil)
19
- GLatLng.new([point.y,point.x],unbounded)
20
- end
21
- end
22
-
@@ -1,444 +0,0 @@
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( 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
- }