radiant-event_map-extension 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,735 @@
1
+ /**
2
+ * @name MarkerClusterer
3
+ * @version 1.0
4
+ * @author Xiaoxi Wu
5
+ * @copyright (c) 2009 Xiaoxi Wu
6
+ * @fileoverview
7
+ * This javascript library creates and manages per-zoom-level
8
+ * clusters for large amounts of markers (hundreds or thousands).
9
+ * This library was inspired by the <a href="http://www.maptimize.com">
10
+ * Maptimize</a> hosted clustering solution.
11
+ * <br /><br/>
12
+ * <b>How it works</b>:<br/>
13
+ * The <code>MarkerClusterer</code> will group markers into clusters according to
14
+ * their distance from a cluster's center. When a marker is added,
15
+ * the marker cluster will find a position in all the clusters, and
16
+ * if it fails to find one, it will create a new cluster with the marker.
17
+ * The number of markers in a cluster will be displayed
18
+ * on the cluster marker. When the map viewport changes,
19
+ * <code>MarkerClusterer</code> will destroy the clusters in the viewport
20
+ * and regroup them into new clusters.
21
+ *
22
+ */
23
+
24
+ /*
25
+ * Licensed under the Apache License, Version 2.0 (the "License");
26
+ * you may not use this file except in compliance with the License.
27
+ * You may obtain a copy of the License at
28
+ *
29
+ * http://www.apache.org/licenses/LICENSE-2.0
30
+ *
31
+ * Unless required by applicable law or agreed to in writing, software
32
+ * distributed under the License is distributed on an "AS IS" BASIS,
33
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34
+ * See the License for the specific language governing permissions and
35
+ * limitations under the License.
36
+ */
37
+
38
+
39
+ /**
40
+ * @name MarkerClustererOptions
41
+ * @class This class represents optional arguments to the {@link MarkerClusterer}
42
+ * constructor.
43
+ * @property {Number} [maxZoom] The max zoom level monitored by a
44
+ * marker cluster. If not given, the marker cluster assumes the maximum map
45
+ * zoom level. When maxZoom is reached or exceeded all markers will be shown
46
+ * without cluster.
47
+ * @property {Number} [gridSize=60] The grid size of a cluster in pixel. Each
48
+ * cluster will be a square. If you want the algorithm to run faster, you can set
49
+ * this value larger.
50
+ * @property {Array of MarkerStyleOptions} [styles]
51
+ * Custom styles for the cluster markers.
52
+ * The array should be ordered according to increasing cluster size,
53
+ * with the style for the smallest clusters first, and the style for the
54
+ * largest clusters last.
55
+ */
56
+
57
+ /**
58
+ * @name MarkerStyleOptions
59
+ * @class An array of these is passed into the {@link MarkerClustererOptions}
60
+ * styles option.
61
+ * @property {String} [url] Image url.
62
+ * @property {Number} [height] Image height.
63
+ * @property {Number} [height] Image width.
64
+ * @property {Array of Number} [opt_anchor] Anchor for label text, like [24, 12].
65
+ * If not set, the text will align center and middle.
66
+ * @property {String} [opt_textColor="black"] Text color.
67
+ */
68
+
69
+ /**
70
+ * Creates a new MarkerClusterer to cluster markers on the map.
71
+ *
72
+ * @constructor
73
+ * @param {GMap2} map The map that the markers should be added to.
74
+ * @param {Array of GMarker} opt_markers Initial set of markers to be clustered.
75
+ * @param {MarkerClustererOptions} opt_opts A container for optional arguments.
76
+ */
77
+ function MarkerClusterer(map, opt_markers, opt_opts) {
78
+ // private members
79
+ var clusters_ = [];
80
+ var map_ = map;
81
+ var maxZoom_ = null;
82
+ var me_ = this;
83
+ var gridSize_ = 60;
84
+ var sizes = [53, 56, 66, 78, 90];
85
+ var styles_ = [];
86
+ var leftMarkers_ = [];
87
+ var mcfn_ = null;
88
+
89
+ var i = 0;
90
+ for (i = 1; i <= 5; ++i) {
91
+ styles_.push({
92
+ 'url': "http://gmaps-utility-library.googlecode.com/svn/trunk/markerclusterer/images/m" + i + ".png",
93
+ 'height': sizes[i - 1],
94
+ 'width': sizes[i - 1]
95
+ });
96
+ }
97
+
98
+ if (typeof opt_opts === "object" && opt_opts !== null) {
99
+ if (typeof opt_opts.gridSize === "number" && opt_opts.gridSize > 0) {
100
+ gridSize_ = opt_opts.gridSize;
101
+ }
102
+ if (typeof opt_opts.maxZoom === "number") {
103
+ maxZoom_ = opt_opts.maxZoom;
104
+ }
105
+ if (typeof opt_opts.styles === "object" && opt_opts.styles !== null && opt_opts.styles.length !== 0) {
106
+ styles_ = opt_opts.styles;
107
+ }
108
+ }
109
+
110
+ /**
111
+ * When we add a marker, the marker may not in the viewport of map, then we don't deal with it, instead
112
+ * we add the marker into a array called leftMarkers_. When we reset MarkerClusterer we should add the
113
+ * leftMarkers_ into MarkerClusterer.
114
+ */
115
+ function addLeftMarkers_() {
116
+ if (leftMarkers_.length === 0) {
117
+ return;
118
+ }
119
+ var leftMarkers = [];
120
+ for (i = 0; i < leftMarkers_.length; ++i) {
121
+ me_.addMarker(leftMarkers_[i], true, null, null, true);
122
+ }
123
+ leftMarkers_ = leftMarkers;
124
+ }
125
+
126
+ /**
127
+ * Get cluster marker images of this marker cluster. Mostly used by {@link Cluster}
128
+ * @private
129
+ * @return {Array of String}
130
+ */
131
+ this.getStyles_ = function () {
132
+ return styles_;
133
+ };
134
+
135
+ /**
136
+ * Remove all markers from MarkerClusterer.
137
+ */
138
+ this.clearMarkers = function () {
139
+ for (var i = 0; i < clusters_.length; ++i) {
140
+ if (typeof clusters_[i] !== "undefined" && clusters_[i] !== null) {
141
+ clusters_[i].clearMarkers();
142
+ }
143
+ }
144
+ clusters_ = [];
145
+ leftMarkers_ = [];
146
+ GEvent.removeListener(mcfn_);
147
+ };
148
+
149
+ /**
150
+ * Check a marker, whether it is in current map viewport.
151
+ * @private
152
+ * @return {Boolean} if it is in current map viewport
153
+ */
154
+ function isMarkerInViewport_(marker) {
155
+ return map_.getBounds().containsLatLng(marker.getLatLng());
156
+ }
157
+
158
+ /**
159
+ * When reset MarkerClusterer, there will be some markers get out of its cluster.
160
+ * These markers should be add to new clusters.
161
+ * @param {Array of GMarker} markers Markers to add.
162
+ */
163
+ function reAddMarkers_(markers) {
164
+ var len = markers.length;
165
+ var clusters = [];
166
+ for (var i = len - 1; i >= 0; --i) {
167
+ me_.addMarker(markers[i].marker, true, markers[i].isAdded, clusters, true);
168
+ }
169
+ addLeftMarkers_();
170
+ }
171
+
172
+ /**
173
+ * Add a marker.
174
+ * @private
175
+ * @param {GMarker} marker Marker you want to add
176
+ * @param {Boolean} opt_isNodraw Whether redraw the cluster contained the marker
177
+ * @param {Boolean} opt_isAdded Whether the marker is added to map. Never use it.
178
+ * @param {Array of Cluster} opt_clusters Provide a list of clusters, the marker
179
+ * cluster will only check these cluster where the marker should join.
180
+ */
181
+ this.addMarker = function (marker, opt_isNodraw, opt_isAdded, opt_clusters, opt_isNoCheck) {
182
+ if (opt_isNoCheck !== true) {
183
+ if (!isMarkerInViewport_(marker)) {
184
+ leftMarkers_.push(marker);
185
+ return;
186
+ }
187
+ }
188
+
189
+ var isAdded = opt_isAdded;
190
+ var clusters = opt_clusters;
191
+ var pos = map_.fromLatLngToDivPixel(marker.getLatLng());
192
+
193
+ if (typeof isAdded !== "boolean") {
194
+ isAdded = false;
195
+ }
196
+ if (typeof clusters !== "object" || clusters === null) {
197
+ clusters = clusters_;
198
+ }
199
+
200
+ var length = clusters.length;
201
+ var cluster = null;
202
+ for (var i = length - 1; i >= 0; i--) {
203
+ cluster = clusters[i];
204
+ var center = cluster.getCenter();
205
+ if (center === null) {
206
+ continue;
207
+ }
208
+ center = map_.fromLatLngToDivPixel(center);
209
+
210
+ // Found a cluster which contains the marker.
211
+ if (pos.x >= center.x - gridSize_ && pos.x <= center.x + gridSize_ &&
212
+ pos.y >= center.y - gridSize_ && pos.y <= center.y + gridSize_) {
213
+ cluster.addMarker({
214
+ 'isAdded': isAdded,
215
+ 'marker': marker
216
+ });
217
+ if (!opt_isNodraw) {
218
+ cluster.redraw_();
219
+ }
220
+ return;
221
+ }
222
+ }
223
+
224
+ // No cluster contain the marker, create a new cluster.
225
+ cluster = new Cluster(this, map);
226
+ cluster.addMarker({
227
+ 'isAdded': isAdded,
228
+ 'marker': marker
229
+ });
230
+ if (!opt_isNodraw) {
231
+ cluster.redraw_();
232
+ }
233
+
234
+ // Add this cluster both in clusters provided and clusters_
235
+ clusters.push(cluster);
236
+ if (clusters !== clusters_) {
237
+ clusters_.push(cluster);
238
+ }
239
+ };
240
+
241
+ /**
242
+ * Remove a marker.
243
+ *
244
+ * @param {GMarker} marker The marker you want to remove.
245
+ */
246
+
247
+ this.removeMarker = function (marker) {
248
+ for (var i = 0; i < clusters_.length; ++i) {
249
+ if (clusters_[i].remove(marker)) {
250
+ clusters_[i].redraw_();
251
+ return;
252
+ }
253
+ }
254
+ };
255
+
256
+ /**
257
+ * Redraw all clusters in viewport.
258
+ */
259
+ this.redraw_ = function () {
260
+ var clusters = this.getClustersInViewport_();
261
+ for (var i = 0; i < clusters.length; ++i) {
262
+ clusters[i].redraw_(true);
263
+ }
264
+ };
265
+
266
+ /**
267
+ * Get all clusters in viewport.
268
+ * @return {Array of Cluster}
269
+ */
270
+ this.getClustersInViewport_ = function () {
271
+ var clusters = [];
272
+ var curBounds = map_.getBounds();
273
+ for (var i = 0; i < clusters_.length; i ++) {
274
+ if (clusters_[i].isInBounds(curBounds)) {
275
+ clusters.push(clusters_[i]);
276
+ }
277
+ }
278
+ return clusters;
279
+ };
280
+
281
+ /**
282
+ * Get max zoom level.
283
+ * @private
284
+ * @return {Number}
285
+ */
286
+ this.getMaxZoom_ = function () {
287
+ return maxZoom_;
288
+ };
289
+
290
+ /**
291
+ * Get map object.
292
+ * @private
293
+ * @return {GMap2}
294
+ */
295
+ this.getMap_ = function () {
296
+ return map_;
297
+ };
298
+
299
+ /**
300
+ * Get grid size
301
+ * @private
302
+ * @return {Number}
303
+ */
304
+ this.getGridSize_ = function () {
305
+ return gridSize_;
306
+ };
307
+
308
+ /**
309
+ * Get total number of markers.
310
+ * @return {Number}
311
+ */
312
+ this.getTotalMarkers = function () {
313
+ var result = 0;
314
+ for (var i = 0; i < clusters_.length; ++i) {
315
+ result += clusters_[i].getTotalMarkers();
316
+ }
317
+ return result;
318
+ };
319
+
320
+ /**
321
+ * Get total number of clusters.
322
+ * @return {int}
323
+ */
324
+ this.getTotalClusters = function () {
325
+ return clusters_.length;
326
+ };
327
+
328
+ /**
329
+ * Collect all markers of clusters in viewport and regroup them.
330
+ */
331
+ this.resetViewport = function () {
332
+ var clusters = this.getClustersInViewport_();
333
+ var tmpMarkers = [];
334
+ var removed = 0;
335
+
336
+ for (var i = 0; i < clusters.length; ++i) {
337
+ var cluster = clusters[i];
338
+ var oldZoom = cluster.getCurrentZoom();
339
+ if (oldZoom === null) {
340
+ continue;
341
+ }
342
+ var curZoom = map_.getZoom();
343
+ if (curZoom !== oldZoom) {
344
+
345
+ // If the cluster zoom level changed then destroy the cluster
346
+ // and collect its markers.
347
+ var mks = cluster.getMarkers();
348
+ for (var j = 0; j < mks.length; ++j) {
349
+ var newMarker = {
350
+ 'isAdded': false,
351
+ 'marker': mks[j].marker
352
+ };
353
+ tmpMarkers.push(newMarker);
354
+ }
355
+ cluster.clearMarkers();
356
+ removed++;
357
+ for (j = 0; j < clusters_.length; ++j) {
358
+ if (cluster === clusters_[j]) {
359
+ clusters_.splice(j, 1);
360
+ }
361
+ }
362
+ }
363
+ }
364
+
365
+ // Add the markers collected into marker cluster to reset
366
+ reAddMarkers_(tmpMarkers);
367
+ this.redraw_();
368
+ };
369
+
370
+
371
+ /**
372
+ * Add a set of markers.
373
+ *
374
+ * @param {Array of GMarker} markers The markers you want to add.
375
+ */
376
+ this.addMarkers = function (markers) {
377
+ for (var i = 0; i < markers.length; ++i) {
378
+ this.addMarker(markers[i], true);
379
+ }
380
+ this.redraw_();
381
+ };
382
+
383
+ // initialize
384
+ if (typeof opt_markers === "object" && opt_markers !== null) {
385
+ this.addMarkers(opt_markers);
386
+ }
387
+
388
+ // when map move end, regroup.
389
+ mcfn_ = GEvent.addListener(map_, "moveend", function () {
390
+ me_.resetViewport();
391
+ });
392
+ }
393
+
394
+ /**
395
+ * Create a cluster to collect markers.
396
+ * A cluster includes some markers which are in a block of area.
397
+ * If there are more than one markers in cluster, the cluster
398
+ * will create a {@link ClusterMarker_} and show the total number
399
+ * of markers in cluster.
400
+ *
401
+ * @constructor
402
+ * @private
403
+ * @param {MarkerClusterer} markerClusterer The marker cluster object
404
+ */
405
+ function Cluster(markerClusterer) {
406
+ var center_ = null;
407
+ var markers_ = [];
408
+ var markerClusterer_ = markerClusterer;
409
+ var map_ = markerClusterer.getMap_();
410
+ var clusterMarker_ = null;
411
+ var zoom_ = map_.getZoom();
412
+
413
+ /**
414
+ * Get markers of this cluster.
415
+ *
416
+ * @return {Array of GMarker}
417
+ */
418
+ this.getMarkers = function () {
419
+ return markers_;
420
+ };
421
+
422
+ /**
423
+ * If this cluster intersects certain bounds.
424
+ *
425
+ * @param {GLatLngBounds} bounds A bounds to test
426
+ * @return {Boolean} Is this cluster intersects the bounds
427
+ */
428
+ this.isInBounds = function (bounds) {
429
+ if (center_ === null) {
430
+ return false;
431
+ }
432
+
433
+ if (!bounds) {
434
+ bounds = map_.getBounds();
435
+ }
436
+ var sw = map_.fromLatLngToDivPixel(bounds.getSouthWest());
437
+ var ne = map_.fromLatLngToDivPixel(bounds.getNorthEast());
438
+
439
+ var centerxy = map_.fromLatLngToDivPixel(center_);
440
+ var inViewport = true;
441
+ var gridSize = markerClusterer.getGridSize_();
442
+ if (zoom_ !== map_.getZoom()) {
443
+ var dl = map_.getZoom() - zoom_;
444
+ gridSize = Math.pow(2, dl) * gridSize;
445
+ }
446
+ if (ne.x !== sw.x && (centerxy.x + gridSize < sw.x || centerxy.x - gridSize > ne.x)) {
447
+ inViewport = false;
448
+ }
449
+ if (inViewport && (centerxy.y + gridSize < ne.y || centerxy.y - gridSize > sw.y)) {
450
+ inViewport = false;
451
+ }
452
+ return inViewport;
453
+ };
454
+
455
+ /**
456
+ * Get cluster center.
457
+ *
458
+ * @return {GLatLng}
459
+ */
460
+ this.getCenter = function () {
461
+ return center_;
462
+ };
463
+
464
+ /**
465
+ * Add a marker.
466
+ *
467
+ * @param {Object} marker An object of marker you want to add:
468
+ * {Boolean} isAdded If the marker is added on map.
469
+ * {GMarker} marker The marker you want to add.
470
+ */
471
+ this.addMarker = function (marker) {
472
+ if (center_ === null) {
473
+ /*var pos = marker['marker'].getLatLng();
474
+ pos = map.fromLatLngToContainerPixel(pos);
475
+ pos.x = parseInt(pos.x - pos.x % (GRIDWIDTH * 2) + GRIDWIDTH);
476
+ pos.y = parseInt(pos.y - pos.y % (GRIDWIDTH * 2) + GRIDWIDTH);
477
+ center = map.fromContainerPixelToLatLng(pos);*/
478
+ center_ = marker.marker.getLatLng();
479
+ }
480
+ markers_.push(marker);
481
+ };
482
+
483
+ /**
484
+ * Remove a marker from cluster.
485
+ *
486
+ * @param {GMarker} marker The marker you want to remove.
487
+ * @return {Boolean} Whether find the marker to be removed.
488
+ */
489
+ this.removeMarker = function (marker) {
490
+ for (var i = 0; i < markers_.length; ++i) {
491
+ if (marker === markers_[i].marker) {
492
+ if (markers_[i].isAdded) {
493
+ map_.removeOverlay(markers_[i].marker);
494
+ }
495
+ markers_.splice(i, 1);
496
+ return true;
497
+ }
498
+ }
499
+ return false;
500
+ };
501
+
502
+ /**
503
+ * Get current zoom level of this cluster.
504
+ * Note: the cluster zoom level and map zoom level not always the same.
505
+ *
506
+ * @return {Number}
507
+ */
508
+ this.getCurrentZoom = function () {
509
+ return zoom_;
510
+ };
511
+
512
+ /**
513
+ * Redraw a cluster.
514
+ * @private
515
+ * @param {Boolean} isForce If redraw by force, no matter if the cluster is
516
+ * in viewport.
517
+ */
518
+ this.redraw_ = function (isForce) {
519
+ if (!isForce && !this.isInBounds()) {
520
+ return;
521
+ }
522
+
523
+ // Set cluster zoom level.
524
+ zoom_ = map_.getZoom();
525
+ var i = 0;
526
+ var mz = markerClusterer.getMaxZoom_();
527
+ if (mz === null) {
528
+ mz = map_.getCurrentMapType().getMaximumResolution();
529
+ }
530
+ if (zoom_ >= mz || this.getTotalMarkers() === 1) {
531
+
532
+ // If current zoom level is beyond the max zoom level or the cluster
533
+ // have only one marker, the marker(s) in cluster will be showed on map.
534
+ for (i = 0; i < markers_.length; ++i) {
535
+ if (markers_[i].isAdded) {
536
+ if (markers_[i].marker.isHidden()) {
537
+ markers_[i].marker.show();
538
+ }
539
+ } else {
540
+ map_.addOverlay(markers_[i].marker);
541
+ markers_[i].isAdded = true;
542
+ }
543
+ }
544
+ if (clusterMarker_ !== null) {
545
+ clusterMarker_.hide();
546
+ }
547
+ } else {
548
+ // Else add a cluster marker on map to show the number of markers in
549
+ // this cluster.
550
+ for (i = 0; i < markers_.length; ++i) {
551
+ if (markers_[i].isAdded && (!markers_[i].marker.isHidden())) {
552
+ markers_[i].marker.hide();
553
+ }
554
+ }
555
+ if (clusterMarker_ === null) {
556
+ clusterMarker_ = new ClusterMarker_(center_, this.getTotalMarkers(), markerClusterer_.getStyles_(), markerClusterer_.getGridSize_());
557
+ map_.addOverlay(clusterMarker_);
558
+ } else {
559
+ if (clusterMarker_.isHidden()) {
560
+ clusterMarker_.show();
561
+ }
562
+ clusterMarker_.redraw(true);
563
+ }
564
+ }
565
+ };
566
+
567
+ /**
568
+ * Remove all the markers from this cluster.
569
+ */
570
+ this.clearMarkers = function () {
571
+ if (clusterMarker_ !== null) {
572
+ map_.removeOverlay(clusterMarker_);
573
+ }
574
+ for (var i = 0; i < markers_.length; ++i) {
575
+ if (markers_[i].isAdded) {
576
+ map_.removeOverlay(markers_[i].marker);
577
+ }
578
+ }
579
+ markers_ = [];
580
+ };
581
+
582
+ /**
583
+ * Get number of markers.
584
+ * @return {Number}
585
+ */
586
+ this.getTotalMarkers = function () {
587
+ return markers_.length;
588
+ };
589
+ }
590
+
591
+ /**
592
+ * ClusterMarker_ creates a marker that shows the number of markers that
593
+ * a cluster contains.
594
+ *
595
+ * @constructor
596
+ * @private
597
+ * @param {GLatLng} latlng Marker's lat and lng.
598
+ * @param {Number} count Number to show.
599
+ * @param {Array of Object} styles The image list to be showed:
600
+ * {String} url Image url.
601
+ * {Number} height Image height.
602
+ * {Number} width Image width.
603
+ * {Array of Number} anchor Text anchor of image left and top.
604
+ * {String} textColor text color.
605
+ * @param {Number} padding Padding of marker center.
606
+ */
607
+ function ClusterMarker_(latlng, count, styles, padding) {
608
+ var index = 0;
609
+ var dv = count;
610
+ while (dv !== 0) {
611
+ dv = parseInt(dv / 10, 10);
612
+ index ++;
613
+ }
614
+
615
+ if (styles.length < index) {
616
+ index = styles.length;
617
+ }
618
+ this.url_ = styles[index - 1].url;
619
+ this.height_ = styles[index - 1].height;
620
+ this.width_ = styles[index - 1].width;
621
+ this.textColor_ = styles[index - 1].opt_textColor;
622
+ this.anchor_ = styles[index - 1].opt_anchor;
623
+ this.latlng_ = latlng;
624
+ this.index_ = index;
625
+ this.styles_ = styles;
626
+ this.text_ = count;
627
+ this.padding_ = padding;
628
+ }
629
+
630
+ ClusterMarker_.prototype = new GOverlay();
631
+
632
+ /**
633
+ * Initialize cluster marker.
634
+ * @private
635
+ */
636
+ ClusterMarker_.prototype.initialize = function (map) {
637
+ this.map_ = map;
638
+ var div = document.createElement("div");
639
+ var latlng = this.latlng_;
640
+ var pos = map.fromLatLngToDivPixel(latlng);
641
+ pos.x -= parseInt(this.width_ / 2, 10);
642
+ pos.y -= parseInt(this.height_ / 2, 10);
643
+ var mstyle = "";
644
+ if (document.all) {
645
+ mstyle = 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale,src="' + this.url_ + '");';
646
+ } else {
647
+ mstyle = "background:url(" + this.url_ + ");";
648
+ }
649
+ if (typeof this.anchor_ === "object") {
650
+ if (typeof this.anchor_[0] === "number" && this.anchor_[0] > 0 && this.anchor_[0] < this.height_) {
651
+ mstyle += 'height:' + (this.height_ - this.anchor_[0]) + 'px;padding-top:' + this.anchor_[0] + 'px;';
652
+ } else {
653
+ mstyle += 'height:' + this.height_ + 'px;line-height:' + this.height_ + 'px;';
654
+ }
655
+ if (typeof this.anchor_[1] === "number" && this.anchor_[1] > 0 && this.anchor_[1] < this.width_) {
656
+ mstyle += 'width:' + (this.width_ - this.anchor_[1]) + 'px;padding-left:' + this.anchor_[1] + 'px;';
657
+ } else {
658
+ mstyle += 'width:' + this.width_ + 'px;text-align:center;';
659
+ }
660
+ } else {
661
+ mstyle += 'height:' + this.height_ + 'px;line-height:' + this.height_ + 'px;';
662
+ mstyle += 'width:' + this.width_ + 'px;text-align:center;';
663
+ }
664
+ var txtColor = this.textColor_ ? this.textColor_ : 'black';
665
+
666
+ div.style.cssText = mstyle + 'cursor:pointer;top:' + pos.y + "px;left:" +
667
+ pos.x + "px;color:" + txtColor + ";position:absolute;font-size:11px;" +
668
+ 'font-family:Arial,sans-serif;font-weight:bold';
669
+ div.innerHTML = this.text_;
670
+ map.getPane(G_MAP_MAP_PANE).appendChild(div);
671
+ var padding = this.padding_;
672
+ GEvent.addDomListener(div, "click", function () {
673
+ var pos = map.fromLatLngToDivPixel(latlng);
674
+ var sw = new GPoint(pos.x - padding, pos.y + padding);
675
+ sw = map.fromDivPixelToLatLng(sw);
676
+ var ne = new GPoint(pos.x + padding, pos.y - padding);
677
+ ne = map.fromDivPixelToLatLng(ne);
678
+ var zoom = map.getBoundsZoomLevel(new GLatLngBounds(sw, ne), map.getSize());
679
+ map.setCenter(latlng, zoom);
680
+ });
681
+ this.div_ = div;
682
+ };
683
+
684
+ /**
685
+ * Remove this overlay.
686
+ * @private
687
+ */
688
+ ClusterMarker_.prototype.remove = function () {
689
+ this.div_.parentNode.removeChild(this.div_);
690
+ };
691
+
692
+ /**
693
+ * Copy this overlay.
694
+ * @private
695
+ */
696
+ ClusterMarker_.prototype.copy = function () {
697
+ return new ClusterMarker_(this.latlng_, this.index_, this.text_, this.styles_, this.padding_);
698
+ };
699
+
700
+ /**
701
+ * Redraw this overlay.
702
+ * @private
703
+ */
704
+ ClusterMarker_.prototype.redraw = function (force) {
705
+ if (!force) {
706
+ return;
707
+ }
708
+ var pos = this.map_.fromLatLngToDivPixel(this.latlng_);
709
+ pos.x -= parseInt(this.width_ / 2, 10);
710
+ pos.y -= parseInt(this.height_ / 2, 10);
711
+ this.div_.style.top = pos.y + "px";
712
+ this.div_.style.left = pos.x + "px";
713
+ };
714
+
715
+ /**
716
+ * Hide this cluster marker.
717
+ */
718
+ ClusterMarker_.prototype.hide = function () {
719
+ this.div_.style.display = "none";
720
+ };
721
+
722
+ /**
723
+ * Show this cluster marker.
724
+ */
725
+ ClusterMarker_.prototype.show = function () {
726
+ this.div_.style.display = "";
727
+ };
728
+
729
+ /**
730
+ * Get whether the cluster marker is hidden.
731
+ * @return {Boolean}
732
+ */
733
+ ClusterMarker_.prototype.isHidden = function () {
734
+ return this.div_.style.display === "none";
735
+ };