gmapsjs-rails 0.2.30.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2065 @@
1
+ (function(root, factory) {
2
+ if(typeof exports === 'object') {
3
+ module.exports = factory();
4
+ }
5
+ else if(typeof define === 'function' && define.amd) {
6
+ define('GMaps', [], factory);
7
+ }
8
+
9
+ root.GMaps = factory();
10
+
11
+ }(this, function() {
12
+
13
+ /*!
14
+ * GMaps.js v0.4.9
15
+ * http://hpneo.github.com/gmaps/
16
+ *
17
+ * Copyright 2013, Gustavo Leon
18
+ * Released under the MIT License.
19
+ */
20
+
21
+ if (!(typeof window.google === 'object' && window.google.maps)) {
22
+ throw 'Google Maps API is required. Please register the following JavaScript library http://maps.google.com/maps/api/js?sensor=true.'
23
+ }
24
+
25
+ var extend_object = function(obj, new_obj) {
26
+ var name;
27
+
28
+ if (obj === new_obj) {
29
+ return obj;
30
+ }
31
+
32
+ for (name in new_obj) {
33
+ obj[name] = new_obj[name];
34
+ }
35
+
36
+ return obj;
37
+ };
38
+
39
+ var replace_object = function(obj, replace) {
40
+ var name;
41
+
42
+ if (obj === replace) {
43
+ return obj;
44
+ }
45
+
46
+ for (name in replace) {
47
+ if (obj[name] != undefined) {
48
+ obj[name] = replace[name];
49
+ }
50
+ }
51
+
52
+ return obj;
53
+ };
54
+
55
+ var array_map = function(array, callback) {
56
+ var original_callback_params = Array.prototype.slice.call(arguments, 2),
57
+ array_return = [],
58
+ array_length = array.length,
59
+ i;
60
+
61
+ if (Array.prototype.map && array.map === Array.prototype.map) {
62
+ array_return = Array.prototype.map.call(array, function(item) {
63
+ callback_params = original_callback_params;
64
+ callback_params.splice(0, 0, item);
65
+
66
+ return callback.apply(this, callback_params);
67
+ });
68
+ }
69
+ else {
70
+ for (i = 0; i < array_length; i++) {
71
+ callback_params = original_callback_params;
72
+ callback_params.splice(0, 0, array[i]);
73
+ array_return.push(callback.apply(this, callback_params));
74
+ }
75
+ }
76
+
77
+ return array_return;
78
+ };
79
+
80
+ var array_flat = function(array) {
81
+ var new_array = [],
82
+ i;
83
+
84
+ for (i = 0; i < array.length; i++) {
85
+ new_array = new_array.concat(array[i]);
86
+ }
87
+
88
+ return new_array;
89
+ };
90
+
91
+ var coordsToLatLngs = function(coords, useGeoJSON) {
92
+ var first_coord = coords[0],
93
+ second_coord = coords[1];
94
+
95
+ if (useGeoJSON) {
96
+ first_coord = coords[1];
97
+ second_coord = coords[0];
98
+ }
99
+
100
+ return new google.maps.LatLng(first_coord, second_coord);
101
+ };
102
+
103
+ var arrayToLatLng = function(coords, useGeoJSON) {
104
+ var i;
105
+
106
+ for (i = 0; i < coords.length; i++) {
107
+ if (coords[i].length > 0 && typeof(coords[i][0]) == "object") {
108
+ coords[i] = arrayToLatLng(coords[i], useGeoJSON);
109
+ }
110
+ else {
111
+ coords[i] = coordsToLatLngs(coords[i], useGeoJSON);
112
+ }
113
+ }
114
+
115
+ return coords;
116
+ };
117
+
118
+ var getElementById = function(id, context) {
119
+ var element,
120
+ id = id.replace('#', '');
121
+
122
+ if ('jQuery' in this && context) {
123
+ element = $("#" + id, context)[0];
124
+ } else {
125
+ element = document.getElementById(id);
126
+ };
127
+
128
+ return element;
129
+ };
130
+
131
+ var findAbsolutePosition = function(obj) {
132
+ var curleft = 0,
133
+ curtop = 0;
134
+
135
+ if (obj.offsetParent) {
136
+ do {
137
+ curleft += obj.offsetLeft;
138
+ curtop += obj.offsetTop;
139
+ } while (obj = obj.offsetParent);
140
+ }
141
+
142
+ return [curleft, curtop];
143
+ };
144
+
145
+ var GMaps = (function(global) {
146
+ "use strict";
147
+
148
+ var doc = document;
149
+
150
+ var GMaps = function(options) {
151
+ if (!this) return new GMaps(options);
152
+
153
+ options.zoom = options.zoom || 15;
154
+ options.mapType = options.mapType || 'roadmap';
155
+
156
+ var self = this,
157
+ i,
158
+ events_that_hide_context_menu = ['bounds_changed', 'center_changed', 'click', 'dblclick', 'drag', 'dragend', 'dragstart', 'idle', 'maptypeid_changed', 'projection_changed', 'resize', 'tilesloaded', 'zoom_changed'],
159
+ events_that_doesnt_hide_context_menu = ['mousemove', 'mouseout', 'mouseover'],
160
+ options_to_be_deleted = ['el', 'lat', 'lng', 'mapType', 'width', 'height', 'markerClusterer', 'enableNewStyle'],
161
+ container_id = options.el || options.div,
162
+ markerClustererFunction = options.markerClusterer,
163
+ mapType = google.maps.MapTypeId[options.mapType.toUpperCase()],
164
+ map_center = new google.maps.LatLng(options.lat, options.lng),
165
+ zoomControl = options.zoomControl || true,
166
+ zoomControlOpt = options.zoomControlOpt || {
167
+ style: 'DEFAULT',
168
+ position: 'TOP_LEFT'
169
+ },
170
+ zoomControlStyle = zoomControlOpt.style || 'DEFAULT',
171
+ zoomControlPosition = zoomControlOpt.position || 'TOP_LEFT',
172
+ panControl = options.panControl || true,
173
+ mapTypeControl = options.mapTypeControl || true,
174
+ scaleControl = options.scaleControl || true,
175
+ streetViewControl = options.streetViewControl || true,
176
+ overviewMapControl = overviewMapControl || true,
177
+ map_options = {},
178
+ map_base_options = {
179
+ zoom: this.zoom,
180
+ center: map_center,
181
+ mapTypeId: mapType
182
+ },
183
+ map_controls_options = {
184
+ panControl: panControl,
185
+ zoomControl: zoomControl,
186
+ zoomControlOptions: {
187
+ style: google.maps.ZoomControlStyle[zoomControlStyle],
188
+ position: google.maps.ControlPosition[zoomControlPosition]
189
+ },
190
+ mapTypeControl: mapTypeControl,
191
+ scaleControl: scaleControl,
192
+ streetViewControl: streetViewControl,
193
+ overviewMapControl: overviewMapControl
194
+ };
195
+
196
+ if (typeof(options.el) === 'string' || typeof(options.div) === 'string') {
197
+ this.el = getElementById(container_id, options.context);
198
+ } else {
199
+ this.el = container_id;
200
+ }
201
+
202
+ if (typeof(this.el) === 'undefined' || this.el === null) {
203
+ throw 'No element defined.';
204
+ }
205
+
206
+ window.context_menu = window.context_menu || {};
207
+ window.context_menu[self.el.id] = {};
208
+
209
+ this.controls = [];
210
+ this.overlays = [];
211
+ this.layers = []; // array with kml/georss and fusiontables layers, can be as many
212
+ this.singleLayers = {}; // object with the other layers, only one per layer
213
+ this.markers = [];
214
+ this.polylines = [];
215
+ this.routes = [];
216
+ this.polygons = [];
217
+ this.infoWindow = null;
218
+ this.overlay_el = null;
219
+ this.zoom = options.zoom;
220
+ this.registered_events = {};
221
+
222
+ this.el.style.width = options.width || this.el.scrollWidth || this.el.offsetWidth;
223
+ this.el.style.height = options.height || this.el.scrollHeight || this.el.offsetHeight;
224
+
225
+ google.maps.visualRefresh = options.enableNewStyle;
226
+
227
+ for (i = 0; i < options_to_be_deleted.length; i++) {
228
+ delete options[options_to_be_deleted[i]];
229
+ }
230
+
231
+ if(options.disableDefaultUI != true) {
232
+ map_base_options = extend_object(map_base_options, map_controls_options);
233
+ }
234
+
235
+ map_options = extend_object(map_base_options, options);
236
+
237
+ for (i = 0; i < events_that_hide_context_menu.length; i++) {
238
+ delete map_options[events_that_hide_context_menu[i]];
239
+ }
240
+
241
+ for (i = 0; i < events_that_doesnt_hide_context_menu.length; i++) {
242
+ delete map_options[events_that_doesnt_hide_context_menu[i]];
243
+ }
244
+
245
+ this.map = new google.maps.Map(this.el, map_options);
246
+
247
+ if (markerClustererFunction) {
248
+ this.markerClusterer = markerClustererFunction.apply(this, [this.map]);
249
+ }
250
+
251
+ var buildContextMenuHTML = function(control, e) {
252
+ var html = '',
253
+ options = window.context_menu[self.el.id][control];
254
+
255
+ for (var i in options){
256
+ if (options.hasOwnProperty(i)) {
257
+ var option = options[i];
258
+
259
+ html += '<li><a id="' + control + '_' + i + '" href="#">' + option.title + '</a></li>';
260
+ }
261
+ }
262
+
263
+ if (!getElementById('gmaps_context_menu')) return;
264
+
265
+ var context_menu_element = getElementById('gmaps_context_menu');
266
+
267
+ context_menu_element.innerHTML = html;
268
+
269
+ var context_menu_items = context_menu_element.getElementsByTagName('a'),
270
+ context_menu_items_count = context_menu_items.length
271
+ i;
272
+
273
+ for (i = 0; i < context_menu_items_count; i++) {
274
+ var context_menu_item = context_menu_items[i];
275
+
276
+ var assign_menu_item_action = function(ev){
277
+ ev.preventDefault();
278
+
279
+ options[this.id.replace(control + '_', '')].action.apply(self, [e]);
280
+ self.hideContextMenu();
281
+ };
282
+
283
+ google.maps.event.clearListeners(context_menu_item, 'click');
284
+ google.maps.event.addDomListenerOnce(context_menu_item, 'click', assign_menu_item_action, false);
285
+ }
286
+
287
+ var position = findAbsolutePosition.apply(this, [self.el]),
288
+ left = position[0] + e.pixel.x - 15,
289
+ top = position[1] + e.pixel.y- 15;
290
+
291
+ context_menu_element.style.left = left + "px";
292
+ context_menu_element.style.top = top + "px";
293
+
294
+ context_menu_element.style.display = 'block';
295
+ };
296
+
297
+ this.buildContextMenu = function(control, e) {
298
+ if (control === 'marker') {
299
+ e.pixel = {};
300
+
301
+ var overlay = new google.maps.OverlayView();
302
+ overlay.setMap(self.map);
303
+
304
+ overlay.draw = function() {
305
+ var projection = overlay.getProjection(),
306
+ position = e.marker.getPosition();
307
+
308
+ e.pixel = projection.fromLatLngToContainerPixel(position);
309
+
310
+ buildContextMenuHTML(control, e);
311
+ };
312
+ }
313
+ else {
314
+ buildContextMenuHTML(control, e);
315
+ }
316
+ };
317
+
318
+ this.setContextMenu = function(options) {
319
+ window.context_menu[self.el.id][options.control] = {};
320
+
321
+ var i,
322
+ ul = doc.createElement('ul');
323
+
324
+ for (i in options.options) {
325
+ if (options.options.hasOwnProperty(i)) {
326
+ var option = options.options[i];
327
+
328
+ window.context_menu[self.el.id][options.control][option.name] = {
329
+ title: option.title,
330
+ action: option.action
331
+ };
332
+ }
333
+ }
334
+
335
+ ul.id = 'gmaps_context_menu';
336
+ ul.style.display = 'none';
337
+ ul.style.position = 'absolute';
338
+ ul.style.minWidth = '100px';
339
+ ul.style.background = 'white';
340
+ ul.style.listStyle = 'none';
341
+ ul.style.padding = '8px';
342
+ ul.style.boxShadow = '2px 2px 6px #ccc';
343
+
344
+ doc.body.appendChild(ul);
345
+
346
+ var context_menu_element = getElementById('gmaps_context_menu')
347
+
348
+ google.maps.event.addDomListener(context_menu_element, 'mouseout', function(ev) {
349
+ if (!ev.relatedTarget || !this.contains(ev.relatedTarget)) {
350
+ window.setTimeout(function(){
351
+ context_menu_element.style.display = 'none';
352
+ }, 400);
353
+ }
354
+ }, false);
355
+ };
356
+
357
+ this.hideContextMenu = function() {
358
+ var context_menu_element = getElementById('gmaps_context_menu');
359
+
360
+ if (context_menu_element) {
361
+ context_menu_element.style.display = 'none';
362
+ }
363
+ };
364
+
365
+ var setupListener = function(object, name) {
366
+ google.maps.event.addListener(object, name, function(e){
367
+ if (e == undefined) {
368
+ e = this;
369
+ }
370
+
371
+ options[name].apply(this, [e]);
372
+
373
+ self.hideContextMenu();
374
+ });
375
+ };
376
+
377
+ for (var ev = 0; ev < events_that_hide_context_menu.length; ev++) {
378
+ var name = events_that_hide_context_menu[ev];
379
+
380
+ if (name in options) {
381
+ setupListener(this.map, name);
382
+ }
383
+ }
384
+
385
+ for (var ev = 0; ev < events_that_doesnt_hide_context_menu.length; ev++) {
386
+ var name = events_that_doesnt_hide_context_menu[ev];
387
+
388
+ if (name in options) {
389
+ setupListener(this.map, name);
390
+ }
391
+ }
392
+
393
+ google.maps.event.addListener(this.map, 'rightclick', function(e) {
394
+ if (options.rightclick) {
395
+ options.rightclick.apply(this, [e]);
396
+ }
397
+
398
+ if(window.context_menu[self.el.id]['map'] != undefined) {
399
+ self.buildContextMenu('map', e);
400
+ }
401
+ });
402
+
403
+ this.refresh = function() {
404
+ google.maps.event.trigger(this.map, 'resize');
405
+ };
406
+
407
+ this.fitZoom = function() {
408
+ var latLngs = [],
409
+ markers_length = this.markers.length,
410
+ i;
411
+
412
+ for (i = 0; i < markers_length; i++) {
413
+ if(typeof(this.markers[i].visible) === 'boolean' && this.markers[i].visible) {
414
+ latLngs.push(this.markers[i].getPosition());
415
+ }
416
+ }
417
+
418
+ this.fitLatLngBounds(latLngs);
419
+ };
420
+
421
+ this.fitLatLngBounds = function(latLngs) {
422
+ var total = latLngs.length;
423
+ var bounds = new google.maps.LatLngBounds();
424
+
425
+ for(var i=0; i < total; i++) {
426
+ bounds.extend(latLngs[i]);
427
+ }
428
+
429
+ this.map.fitBounds(bounds);
430
+ };
431
+
432
+ this.setCenter = function(lat, lng, callback) {
433
+ this.map.panTo(new google.maps.LatLng(lat, lng));
434
+
435
+ if (callback) {
436
+ callback();
437
+ }
438
+ };
439
+
440
+ this.getElement = function() {
441
+ return this.el;
442
+ };
443
+
444
+ this.zoomIn = function(value) {
445
+ value = value || 1;
446
+
447
+ this.zoom = this.map.getZoom() + value;
448
+ this.map.setZoom(this.zoom);
449
+ };
450
+
451
+ this.zoomOut = function(value) {
452
+ value = value || 1;
453
+
454
+ this.zoom = this.map.getZoom() - value;
455
+ this.map.setZoom(this.zoom);
456
+ };
457
+
458
+ var native_methods = [],
459
+ method;
460
+
461
+ for (method in this.map) {
462
+ if (typeof(this.map[method]) == 'function' && !this[method]) {
463
+ native_methods.push(method);
464
+ }
465
+ }
466
+
467
+ for (i=0; i < native_methods.length; i++) {
468
+ (function(gmaps, scope, method_name) {
469
+ gmaps[method_name] = function(){
470
+ return scope[method_name].apply(scope, arguments);
471
+ };
472
+ })(this, this.map, native_methods[i]);
473
+ }
474
+ };
475
+
476
+ return GMaps;
477
+ })(this);
478
+
479
+ GMaps.prototype.createControl = function(options) {
480
+ var control = document.createElement('div');
481
+
482
+ control.style.cursor = 'pointer';
483
+ control.style.fontFamily = 'Arial, sans-serif';
484
+ control.style.fontSize = '13px';
485
+ control.style.boxShadow = 'rgba(0, 0, 0, 0.398438) 0px 2px 4px';
486
+
487
+ for (var option in options.style) {
488
+ control.style[option] = options.style[option];
489
+ }
490
+
491
+ if (options.id) {
492
+ control.id = options.id;
493
+ }
494
+
495
+ if (options.classes) {
496
+ control.className = options.classes;
497
+ }
498
+
499
+ if (options.content) {
500
+ control.innerHTML = options.content;
501
+ }
502
+
503
+ for (var ev in options.events) {
504
+ (function(object, name) {
505
+ google.maps.event.addDomListener(object, name, function(){
506
+ options.events[name].apply(this, [this]);
507
+ });
508
+ })(control, ev);
509
+ }
510
+
511
+ control.index = 1;
512
+
513
+ return control;
514
+ };
515
+
516
+ GMaps.prototype.addControl = function(options) {
517
+ var position = google.maps.ControlPosition[options.position.toUpperCase()];
518
+
519
+ delete options.position;
520
+
521
+ var control = this.createControl(options);
522
+ this.controls.push(control);
523
+
524
+ this.map.controls[position].push(control);
525
+
526
+ return control;
527
+ };
528
+
529
+ GMaps.prototype.createMarker = function(options) {
530
+ if (options.lat == undefined && options.lng == undefined && options.position == undefined) {
531
+ throw 'No latitude or longitude defined.';
532
+ }
533
+
534
+ var self = this,
535
+ details = options.details,
536
+ fences = options.fences,
537
+ outside = options.outside,
538
+ base_options = {
539
+ position: new google.maps.LatLng(options.lat, options.lng),
540
+ map: null
541
+ };
542
+
543
+ delete options.lat;
544
+ delete options.lng;
545
+ delete options.fences;
546
+ delete options.outside;
547
+
548
+ var marker_options = extend_object(base_options, options),
549
+ marker = new google.maps.Marker(marker_options);
550
+
551
+ marker.fences = fences;
552
+
553
+ if (options.infoWindow) {
554
+ marker.infoWindow = new google.maps.InfoWindow(options.infoWindow);
555
+
556
+ var info_window_events = ['closeclick', 'content_changed', 'domready', 'position_changed', 'zindex_changed'];
557
+
558
+ for (var ev = 0; ev < info_window_events.length; ev++) {
559
+ (function(object, name) {
560
+ if (options.infoWindow[name]) {
561
+ google.maps.event.addListener(object, name, function(e){
562
+ options.infoWindow[name].apply(this, [e]);
563
+ });
564
+ }
565
+ })(marker.infoWindow, info_window_events[ev]);
566
+ }
567
+ }
568
+
569
+ var marker_events = ['animation_changed', 'clickable_changed', 'cursor_changed', 'draggable_changed', 'flat_changed', 'icon_changed', 'position_changed', 'shadow_changed', 'shape_changed', 'title_changed', 'visible_changed', 'zindex_changed'];
570
+
571
+ var marker_events_with_mouse = ['dblclick', 'drag', 'dragend', 'dragstart', 'mousedown', 'mouseout', 'mouseover', 'mouseup'];
572
+
573
+ for (var ev = 0; ev < marker_events.length; ev++) {
574
+ (function(object, name) {
575
+ if (options[name]) {
576
+ google.maps.event.addListener(object, name, function(){
577
+ options[name].apply(this, [this]);
578
+ });
579
+ }
580
+ })(marker, marker_events[ev]);
581
+ }
582
+
583
+ for (var ev = 0; ev < marker_events_with_mouse.length; ev++) {
584
+ (function(map, object, name) {
585
+ if (options[name]) {
586
+ google.maps.event.addListener(object, name, function(me){
587
+ if(!me.pixel){
588
+ me.pixel = map.getProjection().fromLatLngToPoint(me.latLng)
589
+ }
590
+
591
+ options[name].apply(this, [me]);
592
+ });
593
+ }
594
+ })(this.map, marker, marker_events_with_mouse[ev]);
595
+ }
596
+
597
+ google.maps.event.addListener(marker, 'click', function() {
598
+ this.details = details;
599
+
600
+ if (options.click) {
601
+ options.click.apply(this, [this]);
602
+ }
603
+
604
+ if (marker.infoWindow) {
605
+ self.hideInfoWindows();
606
+ marker.infoWindow.open(self.map, marker);
607
+ }
608
+ });
609
+
610
+ google.maps.event.addListener(marker, 'rightclick', function(e) {
611
+ e.marker = this;
612
+
613
+ if (options.rightclick) {
614
+ options.rightclick.apply(this, [e]);
615
+ }
616
+
617
+ if (window.context_menu[self.el.id]['marker'] != undefined) {
618
+ self.buildContextMenu('marker', e);
619
+ }
620
+ });
621
+
622
+ if (marker.fences) {
623
+ google.maps.event.addListener(marker, 'dragend', function() {
624
+ self.checkMarkerGeofence(marker, function(m, f) {
625
+ outside(m, f);
626
+ });
627
+ });
628
+ }
629
+
630
+ return marker;
631
+ };
632
+
633
+ GMaps.prototype.addMarker = function(options) {
634
+ var marker;
635
+ if(options.hasOwnProperty('gm_accessors_')) {
636
+ // Native google.maps.Marker object
637
+ marker = options;
638
+ }
639
+ else {
640
+ if ((options.hasOwnProperty('lat') && options.hasOwnProperty('lng')) || options.position) {
641
+ marker = this.createMarker(options);
642
+ }
643
+ else {
644
+ throw 'No latitude or longitude defined.';
645
+ }
646
+ }
647
+
648
+ marker.setMap(this.map);
649
+
650
+ if(this.markerClusterer) {
651
+ this.markerClusterer.addMarker(marker);
652
+ }
653
+
654
+ this.markers.push(marker);
655
+
656
+ GMaps.fire('marker_added', marker, this);
657
+
658
+ return marker;
659
+ };
660
+
661
+ GMaps.prototype.addMarkers = function(array) {
662
+ for (var i = 0, marker; marker=array[i]; i++) {
663
+ this.addMarker(marker);
664
+ }
665
+
666
+ return this.markers;
667
+ };
668
+
669
+ GMaps.prototype.hideInfoWindows = function() {
670
+ for (var i = 0, marker; marker = this.markers[i]; i++){
671
+ if (marker.infoWindow){
672
+ marker.infoWindow.close();
673
+ }
674
+ }
675
+ };
676
+
677
+ GMaps.prototype.removeMarker = function(marker) {
678
+ for (var i = 0; i < this.markers.length; i++) {
679
+ if (this.markers[i] === marker) {
680
+ this.markers[i].setMap(null);
681
+ this.markers.splice(i, 1);
682
+
683
+ if(this.markerClusterer) {
684
+ this.markerClusterer.removeMarker(marker);
685
+ }
686
+
687
+ GMaps.fire('marker_removed', marker, this);
688
+
689
+ break;
690
+ }
691
+ }
692
+
693
+ return marker;
694
+ };
695
+
696
+ GMaps.prototype.removeMarkers = function(collection) {
697
+ var collection = (collection || this.markers);
698
+
699
+ for (var i = 0;i < this.markers.length; i++) {
700
+ if(this.markers[i] === collection[i]) {
701
+ this.markers[i].setMap(null);
702
+ }
703
+ }
704
+
705
+ var new_markers = [];
706
+
707
+ for (var i = 0;i < this.markers.length; i++) {
708
+ if(this.markers[i].getMap() != null) {
709
+ new_markers.push(this.markers[i]);
710
+ }
711
+ }
712
+
713
+ this.markers = new_markers;
714
+ };
715
+
716
+ GMaps.prototype.drawOverlay = function(options) {
717
+ var overlay = new google.maps.OverlayView(),
718
+ auto_show = true;
719
+
720
+ overlay.setMap(this.map);
721
+
722
+ if (options.auto_show != null) {
723
+ auto_show = options.auto_show;
724
+ }
725
+
726
+ overlay.onAdd = function() {
727
+ var el = document.createElement('div');
728
+
729
+ el.style.borderStyle = "none";
730
+ el.style.borderWidth = "0px";
731
+ el.style.position = "absolute";
732
+ el.style.zIndex = 100;
733
+ el.innerHTML = options.content;
734
+
735
+ overlay.el = el;
736
+
737
+ if (!options.layer) {
738
+ options.layer = 'overlayLayer';
739
+ }
740
+
741
+ var panes = this.getPanes(),
742
+ overlayLayer = panes[options.layer],
743
+ stop_overlay_events = ['contextmenu', 'DOMMouseScroll', 'dblclick', 'mousedown'];
744
+
745
+ overlayLayer.appendChild(el);
746
+
747
+ for (var ev = 0; ev < stop_overlay_events.length; ev++) {
748
+ (function(object, name) {
749
+ google.maps.event.addDomListener(object, name, function(e){
750
+ if (navigator.userAgent.toLowerCase().indexOf('msie') != -1 && document.all) {
751
+ e.cancelBubble = true;
752
+ e.returnValue = false;
753
+ }
754
+ else {
755
+ e.stopPropagation();
756
+ }
757
+ });
758
+ })(el, stop_overlay_events[ev]);
759
+ }
760
+
761
+ google.maps.event.trigger(this, 'ready');
762
+ };
763
+
764
+ overlay.draw = function() {
765
+ var projection = this.getProjection(),
766
+ pixel = projection.fromLatLngToDivPixel(new google.maps.LatLng(options.lat, options.lng));
767
+
768
+ options.horizontalOffset = options.horizontalOffset || 0;
769
+ options.verticalOffset = options.verticalOffset || 0;
770
+
771
+ var el = overlay.el,
772
+ content = el.children[0],
773
+ content_height = content.clientHeight,
774
+ content_width = content.clientWidth;
775
+
776
+ switch (options.verticalAlign) {
777
+ case 'top':
778
+ el.style.top = (pixel.y - content_height + options.verticalOffset) + 'px';
779
+ break;
780
+ default:
781
+ case 'middle':
782
+ el.style.top = (pixel.y - (content_height / 2) + options.verticalOffset) + 'px';
783
+ break;
784
+ case 'bottom':
785
+ el.style.top = (pixel.y + options.verticalOffset) + 'px';
786
+ break;
787
+ }
788
+
789
+ switch (options.horizontalAlign) {
790
+ case 'left':
791
+ el.style.left = (pixel.x - content_width + options.horizontalOffset) + 'px';
792
+ break;
793
+ default:
794
+ case 'center':
795
+ el.style.left = (pixel.x - (content_width / 2) + options.horizontalOffset) + 'px';
796
+ break;
797
+ case 'right':
798
+ el.style.left = (pixel.x + options.horizontalOffset) + 'px';
799
+ break;
800
+ }
801
+
802
+ el.style.display = auto_show ? 'block' : 'none';
803
+
804
+ if (!auto_show) {
805
+ options.show.apply(this, [el]);
806
+ }
807
+ };
808
+
809
+ overlay.onRemove = function() {
810
+ var el = overlay.el;
811
+
812
+ if (options.remove) {
813
+ options.remove.apply(this, [el]);
814
+ }
815
+ else {
816
+ overlay.el.parentNode.removeChild(overlay.el);
817
+ overlay.el = null;
818
+ }
819
+ };
820
+
821
+ this.overlays.push(overlay);
822
+ return overlay;
823
+ };
824
+
825
+ GMaps.prototype.removeOverlay = function(overlay) {
826
+ for (var i = 0; i < this.overlays.length; i++) {
827
+ if (this.overlays[i] === overlay) {
828
+ this.overlays[i].setMap(null);
829
+ this.overlays.splice(i, 1);
830
+
831
+ break;
832
+ }
833
+ }
834
+ };
835
+
836
+ GMaps.prototype.removeOverlays = function() {
837
+ for (var i = 0, item; item = this.overlays[i]; i++) {
838
+ item.setMap(null);
839
+ }
840
+
841
+ this.overlays = [];
842
+ };
843
+
844
+ GMaps.prototype.drawPolyline = function(options) {
845
+ var path = [],
846
+ points = options.path;
847
+
848
+ if (points.length) {
849
+ if (points[0][0] === undefined) {
850
+ path = points;
851
+ }
852
+ else {
853
+ for (var i=0, latlng; latlng=points[i]; i++) {
854
+ path.push(new google.maps.LatLng(latlng[0], latlng[1]));
855
+ }
856
+ }
857
+ }
858
+
859
+ var polyline_options = {
860
+ map: this.map,
861
+ path: path,
862
+ strokeColor: options.strokeColor,
863
+ strokeOpacity: options.strokeOpacity,
864
+ strokeWeight: options.strokeWeight,
865
+ geodesic: options.geodesic,
866
+ clickable: true,
867
+ editable: false,
868
+ visible: true
869
+ };
870
+
871
+ if (options.hasOwnProperty("clickable")) {
872
+ polyline_options.clickable = options.clickable;
873
+ }
874
+
875
+ if (options.hasOwnProperty("editable")) {
876
+ polyline_options.editable = options.editable;
877
+ }
878
+
879
+ if (options.hasOwnProperty("icons")) {
880
+ polyline_options.icons = options.icons;
881
+ }
882
+
883
+ if (options.hasOwnProperty("zIndex")) {
884
+ polyline_options.zIndex = options.zIndex;
885
+ }
886
+
887
+ var polyline = new google.maps.Polyline(polyline_options);
888
+
889
+ var polyline_events = ['click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'rightclick'];
890
+
891
+ for (var ev = 0; ev < polyline_events.length; ev++) {
892
+ (function(object, name) {
893
+ if (options[name]) {
894
+ google.maps.event.addListener(object, name, function(e){
895
+ options[name].apply(this, [e]);
896
+ });
897
+ }
898
+ })(polyline, polyline_events[ev]);
899
+ }
900
+
901
+ this.polylines.push(polyline);
902
+
903
+ GMaps.fire('polyline_added', polyline, this);
904
+
905
+ return polyline;
906
+ };
907
+
908
+ GMaps.prototype.removePolyline = function(polyline) {
909
+ for (var i = 0; i < this.polylines.length; i++) {
910
+ if (this.polylines[i] === polyline) {
911
+ this.polylines[i].setMap(null);
912
+ this.polylines.splice(i, 1);
913
+
914
+ GMaps.fire('polyline_removed', polyline, this);
915
+
916
+ break;
917
+ }
918
+ }
919
+ };
920
+
921
+ GMaps.prototype.removePolylines = function() {
922
+ for (var i = 0, item; item = this.polylines[i]; i++) {
923
+ item.setMap(null);
924
+ }
925
+
926
+ this.polylines = [];
927
+ };
928
+
929
+ GMaps.prototype.drawCircle = function(options) {
930
+ options = extend_object({
931
+ map: this.map,
932
+ center: new google.maps.LatLng(options.lat, options.lng)
933
+ }, options);
934
+
935
+ delete options.lat;
936
+ delete options.lng;
937
+
938
+ var polygon = new google.maps.Circle(options),
939
+ polygon_events = ['click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'rightclick'];
940
+
941
+ for (var ev = 0; ev < polygon_events.length; ev++) {
942
+ (function(object, name) {
943
+ if (options[name]) {
944
+ google.maps.event.addListener(object, name, function(e){
945
+ options[name].apply(this, [e]);
946
+ });
947
+ }
948
+ })(polygon, polygon_events[ev]);
949
+ }
950
+
951
+ this.polygons.push(polygon);
952
+
953
+ return polygon;
954
+ };
955
+
956
+ GMaps.prototype.drawRectangle = function(options) {
957
+ options = extend_object({
958
+ map: this.map
959
+ }, options);
960
+
961
+ var latLngBounds = new google.maps.LatLngBounds(
962
+ new google.maps.LatLng(options.bounds[0][0], options.bounds[0][1]),
963
+ new google.maps.LatLng(options.bounds[1][0], options.bounds[1][1])
964
+ );
965
+
966
+ options.bounds = latLngBounds;
967
+
968
+ var polygon = new google.maps.Rectangle(options),
969
+ polygon_events = ['click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'rightclick'];
970
+
971
+ for (var ev = 0; ev < polygon_events.length; ev++) {
972
+ (function(object, name) {
973
+ if (options[name]) {
974
+ google.maps.event.addListener(object, name, function(e){
975
+ options[name].apply(this, [e]);
976
+ });
977
+ }
978
+ })(polygon, polygon_events[ev]);
979
+ }
980
+
981
+ this.polygons.push(polygon);
982
+
983
+ return polygon;
984
+ };
985
+
986
+ GMaps.prototype.drawPolygon = function(options) {
987
+ var useGeoJSON = false;
988
+
989
+ if(options.hasOwnProperty("useGeoJSON")) {
990
+ useGeoJSON = options.useGeoJSON;
991
+ }
992
+
993
+ delete options.useGeoJSON;
994
+
995
+ options = extend_object({
996
+ map: this.map
997
+ }, options);
998
+
999
+ if (useGeoJSON == false) {
1000
+ options.paths = [options.paths.slice(0)];
1001
+ }
1002
+
1003
+ if (options.paths.length > 0) {
1004
+ if (options.paths[0].length > 0) {
1005
+ options.paths = array_flat(array_map(options.paths, arrayToLatLng, useGeoJSON));
1006
+ }
1007
+ }
1008
+
1009
+ var polygon = new google.maps.Polygon(options),
1010
+ polygon_events = ['click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'rightclick'];
1011
+
1012
+ for (var ev = 0; ev < polygon_events.length; ev++) {
1013
+ (function(object, name) {
1014
+ if (options[name]) {
1015
+ google.maps.event.addListener(object, name, function(e){
1016
+ options[name].apply(this, [e]);
1017
+ });
1018
+ }
1019
+ })(polygon, polygon_events[ev]);
1020
+ }
1021
+
1022
+ this.polygons.push(polygon);
1023
+
1024
+ GMaps.fire('polygon_added', polygon, this);
1025
+
1026
+ return polygon;
1027
+ };
1028
+
1029
+ GMaps.prototype.removePolygon = function(polygon) {
1030
+ for (var i = 0; i < this.polygons.length; i++) {
1031
+ if (this.polygons[i] === polygon) {
1032
+ this.polygons[i].setMap(null);
1033
+ this.polygons.splice(i, 1);
1034
+
1035
+ GMaps.fire('polygon_removed', polygon, this);
1036
+
1037
+ break;
1038
+ }
1039
+ }
1040
+ };
1041
+
1042
+ GMaps.prototype.removePolygons = function() {
1043
+ for (var i = 0, item; item = this.polygons[i]; i++) {
1044
+ item.setMap(null);
1045
+ }
1046
+
1047
+ this.polygons = [];
1048
+ };
1049
+
1050
+ GMaps.prototype.getFromFusionTables = function(options) {
1051
+ var events = options.events;
1052
+
1053
+ delete options.events;
1054
+
1055
+ var fusion_tables_options = options,
1056
+ layer = new google.maps.FusionTablesLayer(fusion_tables_options);
1057
+
1058
+ for (var ev in events) {
1059
+ (function(object, name) {
1060
+ google.maps.event.addListener(object, name, function(e) {
1061
+ events[name].apply(this, [e]);
1062
+ });
1063
+ })(layer, ev);
1064
+ }
1065
+
1066
+ this.layers.push(layer);
1067
+
1068
+ return layer;
1069
+ };
1070
+
1071
+ GMaps.prototype.loadFromFusionTables = function(options) {
1072
+ var layer = this.getFromFusionTables(options);
1073
+ layer.setMap(this.map);
1074
+
1075
+ return layer;
1076
+ };
1077
+
1078
+ GMaps.prototype.getFromKML = function(options) {
1079
+ var url = options.url,
1080
+ events = options.events;
1081
+
1082
+ delete options.url;
1083
+ delete options.events;
1084
+
1085
+ var kml_options = options,
1086
+ layer = new google.maps.KmlLayer(url, kml_options);
1087
+
1088
+ for (var ev in events) {
1089
+ (function(object, name) {
1090
+ google.maps.event.addListener(object, name, function(e) {
1091
+ events[name].apply(this, [e]);
1092
+ });
1093
+ })(layer, ev);
1094
+ }
1095
+
1096
+ this.layers.push(layer);
1097
+
1098
+ return layer;
1099
+ };
1100
+
1101
+ GMaps.prototype.loadFromKML = function(options) {
1102
+ var layer = this.getFromKML(options);
1103
+ layer.setMap(this.map);
1104
+
1105
+ return layer;
1106
+ };
1107
+
1108
+ GMaps.prototype.addLayer = function(layerName, options) {
1109
+ //var default_layers = ['weather', 'clouds', 'traffic', 'transit', 'bicycling', 'panoramio', 'places'];
1110
+ options = options || {};
1111
+ var layer;
1112
+
1113
+ switch(layerName) {
1114
+ case 'weather': this.singleLayers.weather = layer = new google.maps.weather.WeatherLayer();
1115
+ break;
1116
+ case 'clouds': this.singleLayers.clouds = layer = new google.maps.weather.CloudLayer();
1117
+ break;
1118
+ case 'traffic': this.singleLayers.traffic = layer = new google.maps.TrafficLayer();
1119
+ break;
1120
+ case 'transit': this.singleLayers.transit = layer = new google.maps.TransitLayer();
1121
+ break;
1122
+ case 'bicycling': this.singleLayers.bicycling = layer = new google.maps.BicyclingLayer();
1123
+ break;
1124
+ case 'panoramio':
1125
+ this.singleLayers.panoramio = layer = new google.maps.panoramio.PanoramioLayer();
1126
+ layer.setTag(options.filter);
1127
+ delete options.filter;
1128
+
1129
+ //click event
1130
+ if (options.click) {
1131
+ google.maps.event.addListener(layer, 'click', function(event) {
1132
+ options.click(event);
1133
+ delete options.click;
1134
+ });
1135
+ }
1136
+ break;
1137
+ case 'places':
1138
+ this.singleLayers.places = layer = new google.maps.places.PlacesService(this.map);
1139
+
1140
+ //search and nearbySearch callback, Both are the same
1141
+ if (options.search || options.nearbySearch) {
1142
+ var placeSearchRequest = {
1143
+ bounds : options.bounds || null,
1144
+ keyword : options.keyword || null,
1145
+ location : options.location || null,
1146
+ name : options.name || null,
1147
+ radius : options.radius || null,
1148
+ rankBy : options.rankBy || null,
1149
+ types : options.types || null
1150
+ };
1151
+
1152
+ if (options.search) {
1153
+ layer.search(placeSearchRequest, options.search);
1154
+ }
1155
+
1156
+ if (options.nearbySearch) {
1157
+ layer.nearbySearch(placeSearchRequest, options.nearbySearch);
1158
+ }
1159
+ }
1160
+
1161
+ //textSearch callback
1162
+ if (options.textSearch) {
1163
+ var textSearchRequest = {
1164
+ bounds : options.bounds || null,
1165
+ location : options.location || null,
1166
+ query : options.query || null,
1167
+ radius : options.radius || null
1168
+ };
1169
+
1170
+ layer.textSearch(textSearchRequest, options.textSearch);
1171
+ }
1172
+ break;
1173
+ }
1174
+
1175
+ if (layer !== undefined) {
1176
+ if (typeof layer.setOptions == 'function') {
1177
+ layer.setOptions(options);
1178
+ }
1179
+ if (typeof layer.setMap == 'function') {
1180
+ layer.setMap(this.map);
1181
+ }
1182
+
1183
+ return layer;
1184
+ }
1185
+ };
1186
+
1187
+ GMaps.prototype.removeLayer = function(layer) {
1188
+ if (typeof(layer) == "string" && this.singleLayers[layer] !== undefined) {
1189
+ this.singleLayers[layer].setMap(null);
1190
+
1191
+ delete this.singleLayers[layer];
1192
+ }
1193
+ else {
1194
+ for (var i = 0; i < this.layers.length; i++) {
1195
+ if (this.layers[i] === layer) {
1196
+ this.layers[i].setMap(null);
1197
+ this.layers.splice(i, 1);
1198
+
1199
+ break;
1200
+ }
1201
+ }
1202
+ }
1203
+ };
1204
+
1205
+ var travelMode, unitSystem;
1206
+
1207
+ GMaps.prototype.getRoutes = function(options) {
1208
+ switch (options.travelMode) {
1209
+ case 'bicycling':
1210
+ travelMode = google.maps.TravelMode.BICYCLING;
1211
+ break;
1212
+ case 'transit':
1213
+ travelMode = google.maps.TravelMode.TRANSIT;
1214
+ break;
1215
+ case 'driving':
1216
+ travelMode = google.maps.TravelMode.DRIVING;
1217
+ break;
1218
+ default:
1219
+ travelMode = google.maps.TravelMode.WALKING;
1220
+ break;
1221
+ }
1222
+
1223
+ if (options.unitSystem === 'imperial') {
1224
+ unitSystem = google.maps.UnitSystem.IMPERIAL;
1225
+ }
1226
+ else {
1227
+ unitSystem = google.maps.UnitSystem.METRIC;
1228
+ }
1229
+
1230
+ var base_options = {
1231
+ avoidHighways: false,
1232
+ avoidTolls: false,
1233
+ optimizeWaypoints: false,
1234
+ waypoints: []
1235
+ },
1236
+ request_options = extend_object(base_options, options);
1237
+
1238
+ request_options.origin = /string/.test(typeof options.origin) ? options.origin : new google.maps.LatLng(options.origin[0], options.origin[1]);
1239
+ request_options.destination = /string/.test(typeof options.destination) ? options.destination : new google.maps.LatLng(options.destination[0], options.destination[1]);
1240
+ request_options.travelMode = travelMode;
1241
+ request_options.unitSystem = unitSystem;
1242
+
1243
+ delete request_options.callback;
1244
+ delete request_options.error;
1245
+
1246
+ var self = this,
1247
+ service = new google.maps.DirectionsService();
1248
+
1249
+ service.route(request_options, function(result, status) {
1250
+ if (status === google.maps.DirectionsStatus.OK) {
1251
+ for (var r in result.routes) {
1252
+ if (result.routes.hasOwnProperty(r)) {
1253
+ self.routes.push(result.routes[r]);
1254
+ }
1255
+ }
1256
+
1257
+ if (options.callback) {
1258
+ options.callback(self.routes);
1259
+ }
1260
+ }
1261
+ else {
1262
+ if (options.error) {
1263
+ options.error(result, status);
1264
+ }
1265
+ }
1266
+ });
1267
+ };
1268
+
1269
+ GMaps.prototype.removeRoutes = function() {
1270
+ this.routes = [];
1271
+ };
1272
+
1273
+ GMaps.prototype.getElevations = function(options) {
1274
+ options = extend_object({
1275
+ locations: [],
1276
+ path : false,
1277
+ samples : 256
1278
+ }, options);
1279
+
1280
+ if (options.locations.length > 0) {
1281
+ if (options.locations[0].length > 0) {
1282
+ options.locations = array_flat(array_map([options.locations], arrayToLatLng, false));
1283
+ }
1284
+ }
1285
+
1286
+ var callback = options.callback;
1287
+ delete options.callback;
1288
+
1289
+ var service = new google.maps.ElevationService();
1290
+
1291
+ //location request
1292
+ if (!options.path) {
1293
+ delete options.path;
1294
+ delete options.samples;
1295
+
1296
+ service.getElevationForLocations(options, function(result, status) {
1297
+ if (callback && typeof(callback) === "function") {
1298
+ callback(result, status);
1299
+ }
1300
+ });
1301
+ //path request
1302
+ } else {
1303
+ var pathRequest = {
1304
+ path : options.locations,
1305
+ samples : options.samples
1306
+ };
1307
+
1308
+ service.getElevationAlongPath(pathRequest, function(result, status) {
1309
+ if (callback && typeof(callback) === "function") {
1310
+ callback(result, status);
1311
+ }
1312
+ });
1313
+ }
1314
+ };
1315
+
1316
+ GMaps.prototype.cleanRoute = GMaps.prototype.removePolylines;
1317
+
1318
+ GMaps.prototype.drawRoute = function(options) {
1319
+ var self = this;
1320
+
1321
+ this.getRoutes({
1322
+ origin: options.origin,
1323
+ destination: options.destination,
1324
+ travelMode: options.travelMode,
1325
+ waypoints: options.waypoints,
1326
+ unitSystem: options.unitSystem,
1327
+ error: options.error,
1328
+ callback: function(e) {
1329
+ if (e.length > 0) {
1330
+ self.drawPolyline({
1331
+ path: e[e.length - 1].overview_path,
1332
+ strokeColor: options.strokeColor,
1333
+ strokeOpacity: options.strokeOpacity,
1334
+ strokeWeight: options.strokeWeight
1335
+ });
1336
+
1337
+ if (options.callback) {
1338
+ options.callback(e[e.length - 1]);
1339
+ }
1340
+ }
1341
+ }
1342
+ });
1343
+ };
1344
+
1345
+ GMaps.prototype.travelRoute = function(options) {
1346
+ if (options.origin && options.destination) {
1347
+ this.getRoutes({
1348
+ origin: options.origin,
1349
+ destination: options.destination,
1350
+ travelMode: options.travelMode,
1351
+ waypoints : options.waypoints,
1352
+ error: options.error,
1353
+ callback: function(e) {
1354
+ //start callback
1355
+ if (e.length > 0 && options.start) {
1356
+ options.start(e[e.length - 1]);
1357
+ }
1358
+
1359
+ //step callback
1360
+ if (e.length > 0 && options.step) {
1361
+ var route = e[e.length - 1];
1362
+ if (route.legs.length > 0) {
1363
+ var steps = route.legs[0].steps;
1364
+ for (var i=0, step; step=steps[i]; i++) {
1365
+ step.step_number = i;
1366
+ options.step(step, (route.legs[0].steps.length - 1));
1367
+ }
1368
+ }
1369
+ }
1370
+
1371
+ //end callback
1372
+ if (e.length > 0 && options.end) {
1373
+ options.end(e[e.length - 1]);
1374
+ }
1375
+ }
1376
+ });
1377
+ }
1378
+ else if (options.route) {
1379
+ if (options.route.legs.length > 0) {
1380
+ var steps = options.route.legs[0].steps;
1381
+ for (var i=0, step; step=steps[i]; i++) {
1382
+ step.step_number = i;
1383
+ options.step(step);
1384
+ }
1385
+ }
1386
+ }
1387
+ };
1388
+
1389
+ GMaps.prototype.drawSteppedRoute = function(options) {
1390
+ var self = this;
1391
+
1392
+ if (options.origin && options.destination) {
1393
+ this.getRoutes({
1394
+ origin: options.origin,
1395
+ destination: options.destination,
1396
+ travelMode: options.travelMode,
1397
+ waypoints : options.waypoints,
1398
+ error: options.error,
1399
+ callback: function(e) {
1400
+ //start callback
1401
+ if (e.length > 0 && options.start) {
1402
+ options.start(e[e.length - 1]);
1403
+ }
1404
+
1405
+ //step callback
1406
+ if (e.length > 0 && options.step) {
1407
+ var route = e[e.length - 1];
1408
+ if (route.legs.length > 0) {
1409
+ var steps = route.legs[0].steps;
1410
+ for (var i=0, step; step=steps[i]; i++) {
1411
+ step.step_number = i;
1412
+ self.drawPolyline({
1413
+ path: step.path,
1414
+ strokeColor: options.strokeColor,
1415
+ strokeOpacity: options.strokeOpacity,
1416
+ strokeWeight: options.strokeWeight
1417
+ });
1418
+ options.step(step, (route.legs[0].steps.length - 1));
1419
+ }
1420
+ }
1421
+ }
1422
+
1423
+ //end callback
1424
+ if (e.length > 0 && options.end) {
1425
+ options.end(e[e.length - 1]);
1426
+ }
1427
+ }
1428
+ });
1429
+ }
1430
+ else if (options.route) {
1431
+ if (options.route.legs.length > 0) {
1432
+ var steps = options.route.legs[0].steps;
1433
+ for (var i=0, step; step=steps[i]; i++) {
1434
+ step.step_number = i;
1435
+ self.drawPolyline({
1436
+ path: step.path,
1437
+ strokeColor: options.strokeColor,
1438
+ strokeOpacity: options.strokeOpacity,
1439
+ strokeWeight: options.strokeWeight
1440
+ });
1441
+ options.step(step);
1442
+ }
1443
+ }
1444
+ }
1445
+ };
1446
+
1447
+ GMaps.Route = function(options) {
1448
+ this.origin = options.origin;
1449
+ this.destination = options.destination;
1450
+ this.waypoints = options.waypoints;
1451
+
1452
+ this.map = options.map;
1453
+ this.route = options.route;
1454
+ this.step_count = 0;
1455
+ this.steps = this.route.legs[0].steps;
1456
+ this.steps_length = this.steps.length;
1457
+
1458
+ this.polyline = this.map.drawPolyline({
1459
+ path: new google.maps.MVCArray(),
1460
+ strokeColor: options.strokeColor,
1461
+ strokeOpacity: options.strokeOpacity,
1462
+ strokeWeight: options.strokeWeight
1463
+ }).getPath();
1464
+ };
1465
+
1466
+ GMaps.Route.prototype.getRoute = function(options) {
1467
+ var self = this;
1468
+
1469
+ this.map.getRoutes({
1470
+ origin : this.origin,
1471
+ destination : this.destination,
1472
+ travelMode : options.travelMode,
1473
+ waypoints : this.waypoints || [],
1474
+ error: options.error,
1475
+ callback : function() {
1476
+ self.route = e[0];
1477
+
1478
+ if (options.callback) {
1479
+ options.callback.call(self);
1480
+ }
1481
+ }
1482
+ });
1483
+ };
1484
+
1485
+ GMaps.Route.prototype.back = function() {
1486
+ if (this.step_count > 0) {
1487
+ this.step_count--;
1488
+ var path = this.route.legs[0].steps[this.step_count].path;
1489
+
1490
+ for (var p in path){
1491
+ if (path.hasOwnProperty(p)){
1492
+ this.polyline.pop();
1493
+ }
1494
+ }
1495
+ }
1496
+ };
1497
+
1498
+ GMaps.Route.prototype.forward = function() {
1499
+ if (this.step_count < this.steps_length) {
1500
+ var path = this.route.legs[0].steps[this.step_count].path;
1501
+
1502
+ for (var p in path){
1503
+ if (path.hasOwnProperty(p)){
1504
+ this.polyline.push(path[p]);
1505
+ }
1506
+ }
1507
+ this.step_count++;
1508
+ }
1509
+ };
1510
+
1511
+ GMaps.prototype.checkGeofence = function(lat, lng, fence) {
1512
+ return fence.containsLatLng(new google.maps.LatLng(lat, lng));
1513
+ };
1514
+
1515
+ GMaps.prototype.checkMarkerGeofence = function(marker, outside_callback) {
1516
+ if (marker.fences) {
1517
+ for (var i = 0, fence; fence = marker.fences[i]; i++) {
1518
+ var pos = marker.getPosition();
1519
+ if (!this.checkGeofence(pos.lat(), pos.lng(), fence)) {
1520
+ outside_callback(marker, fence);
1521
+ }
1522
+ }
1523
+ }
1524
+ };
1525
+
1526
+ GMaps.prototype.toImage = function(options) {
1527
+ var options = options || {},
1528
+ static_map_options = {};
1529
+
1530
+ static_map_options['size'] = options['size'] || [this.el.clientWidth, this.el.clientHeight];
1531
+ static_map_options['lat'] = this.getCenter().lat();
1532
+ static_map_options['lng'] = this.getCenter().lng();
1533
+
1534
+ if (this.markers.length > 0) {
1535
+ static_map_options['markers'] = [];
1536
+
1537
+ for (var i = 0; i < this.markers.length; i++) {
1538
+ static_map_options['markers'].push({
1539
+ lat: this.markers[i].getPosition().lat(),
1540
+ lng: this.markers[i].getPosition().lng()
1541
+ });
1542
+ }
1543
+ }
1544
+
1545
+ if (this.polylines.length > 0) {
1546
+ var polyline = this.polylines[0];
1547
+
1548
+ static_map_options['polyline'] = {};
1549
+ static_map_options['polyline']['path'] = google.maps.geometry.encoding.encodePath(polyline.getPath());
1550
+ static_map_options['polyline']['strokeColor'] = polyline.strokeColor
1551
+ static_map_options['polyline']['strokeOpacity'] = polyline.strokeOpacity
1552
+ static_map_options['polyline']['strokeWeight'] = polyline.strokeWeight
1553
+ }
1554
+
1555
+ return GMaps.staticMapURL(static_map_options);
1556
+ };
1557
+
1558
+ GMaps.staticMapURL = function(options){
1559
+ var parameters = [],
1560
+ data,
1561
+ static_root = 'http://maps.googleapis.com/maps/api/staticmap';
1562
+
1563
+ if (options.url) {
1564
+ static_root = options.url;
1565
+ delete options.url;
1566
+ }
1567
+
1568
+ static_root += '?';
1569
+
1570
+ var markers = options.markers;
1571
+
1572
+ delete options.markers;
1573
+
1574
+ if (!markers && options.marker) {
1575
+ markers = [options.marker];
1576
+ delete options.marker;
1577
+ }
1578
+
1579
+ var styles = options.styles;
1580
+
1581
+ delete options.styles;
1582
+
1583
+ var polyline = options.polyline;
1584
+ delete options.polyline;
1585
+
1586
+ /** Map options **/
1587
+ if (options.center) {
1588
+ parameters.push('center=' + options.center);
1589
+ delete options.center;
1590
+ }
1591
+ else if (options.address) {
1592
+ parameters.push('center=' + options.address);
1593
+ delete options.address;
1594
+ }
1595
+ else if (options.lat) {
1596
+ parameters.push(['center=', options.lat, ',', options.lng].join(''));
1597
+ delete options.lat;
1598
+ delete options.lng;
1599
+ }
1600
+ else if (options.visible) {
1601
+ var visible = encodeURI(options.visible.join('|'));
1602
+ parameters.push('visible=' + visible);
1603
+ }
1604
+
1605
+ var size = options.size;
1606
+ if (size) {
1607
+ if (size.join) {
1608
+ size = size.join('x');
1609
+ }
1610
+ delete options.size;
1611
+ }
1612
+ else {
1613
+ size = '630x300';
1614
+ }
1615
+ parameters.push('size=' + size);
1616
+
1617
+ if (!options.zoom && options.zoom !== false) {
1618
+ options.zoom = 15;
1619
+ }
1620
+
1621
+ var sensor = options.hasOwnProperty('sensor') ? !!options.sensor : true;
1622
+ delete options.sensor;
1623
+ parameters.push('sensor=' + sensor);
1624
+
1625
+ for (var param in options) {
1626
+ if (options.hasOwnProperty(param)) {
1627
+ parameters.push(param + '=' + options[param]);
1628
+ }
1629
+ }
1630
+
1631
+ /** Markers **/
1632
+ if (markers) {
1633
+ var marker, loc;
1634
+
1635
+ for (var i=0; data=markers[i]; i++) {
1636
+ marker = [];
1637
+
1638
+ if (data.size && data.size !== 'normal') {
1639
+ marker.push('size:' + data.size);
1640
+ delete data.size;
1641
+ }
1642
+ else if (data.icon) {
1643
+ marker.push('icon:' + encodeURI(data.icon));
1644
+ delete data.icon;
1645
+ }
1646
+
1647
+ if (data.color) {
1648
+ marker.push('color:' + data.color.replace('#', '0x'));
1649
+ delete data.color;
1650
+ }
1651
+
1652
+ if (data.label) {
1653
+ marker.push('label:' + data.label[0].toUpperCase());
1654
+ delete data.label;
1655
+ }
1656
+
1657
+ loc = (data.address ? data.address : data.lat + ',' + data.lng);
1658
+ delete data.address;
1659
+ delete data.lat;
1660
+ delete data.lng;
1661
+
1662
+ for(var param in data){
1663
+ if (data.hasOwnProperty(param)) {
1664
+ marker.push(param + ':' + data[param]);
1665
+ }
1666
+ }
1667
+
1668
+ if (marker.length || i === 0) {
1669
+ marker.push(loc);
1670
+ marker = marker.join('|');
1671
+ parameters.push('markers=' + encodeURI(marker));
1672
+ }
1673
+ // New marker without styles
1674
+ else {
1675
+ marker = parameters.pop() + encodeURI('|' + loc);
1676
+ parameters.push(marker);
1677
+ }
1678
+ }
1679
+ }
1680
+
1681
+ /** Map Styles **/
1682
+ if (styles) {
1683
+ for (var i = 0; i < styles.length; i++) {
1684
+ var styleRule = [];
1685
+ if (styles[i].featureType && styles[i].featureType != 'all' ) {
1686
+ styleRule.push('feature:' + styles[i].featureType);
1687
+ }
1688
+
1689
+ if (styles[i].elementType && styles[i].elementType != 'all') {
1690
+ styleRule.push('element:' + styles[i].elementType);
1691
+ }
1692
+
1693
+ for (var j = 0; j < styles[i].stylers.length; j++) {
1694
+ for (var p in styles[i].stylers[j]) {
1695
+ var ruleArg = styles[i].stylers[j][p];
1696
+ if (p == 'hue' || p == 'color') {
1697
+ ruleArg = '0x' + ruleArg.substring(1);
1698
+ }
1699
+ styleRule.push(p + ':' + ruleArg);
1700
+ }
1701
+ }
1702
+
1703
+ var rule = styleRule.join('|');
1704
+ if (rule != '') {
1705
+ parameters.push('style=' + rule);
1706
+ }
1707
+ }
1708
+ }
1709
+
1710
+ /** Polylines **/
1711
+ function parseColor(color, opacity) {
1712
+ if (color[0] === '#'){
1713
+ color = color.replace('#', '0x');
1714
+
1715
+ if (opacity) {
1716
+ opacity = parseFloat(opacity);
1717
+ opacity = Math.min(1, Math.max(opacity, 0));
1718
+ if (opacity === 0) {
1719
+ return '0x00000000';
1720
+ }
1721
+ opacity = (opacity * 255).toString(16);
1722
+ if (opacity.length === 1) {
1723
+ opacity += opacity;
1724
+ }
1725
+
1726
+ color = color.slice(0,8) + opacity;
1727
+ }
1728
+ }
1729
+ return color;
1730
+ }
1731
+
1732
+ if (polyline) {
1733
+ data = polyline;
1734
+ polyline = [];
1735
+
1736
+ if (data.strokeWeight) {
1737
+ polyline.push('weight:' + parseInt(data.strokeWeight, 10));
1738
+ }
1739
+
1740
+ if (data.strokeColor) {
1741
+ var color = parseColor(data.strokeColor, data.strokeOpacity);
1742
+ polyline.push('color:' + color);
1743
+ }
1744
+
1745
+ if (data.fillColor) {
1746
+ var fillcolor = parseColor(data.fillColor, data.fillOpacity);
1747
+ polyline.push('fillcolor:' + fillcolor);
1748
+ }
1749
+
1750
+ var path = data.path;
1751
+ if (path.join) {
1752
+ for (var j=0, pos; pos=path[j]; j++) {
1753
+ polyline.push(pos.join(','));
1754
+ }
1755
+ }
1756
+ else {
1757
+ polyline.push('enc:' + path);
1758
+ }
1759
+
1760
+ polyline = polyline.join('|');
1761
+ parameters.push('path=' + encodeURI(polyline));
1762
+ }
1763
+
1764
+ /** Retina support **/
1765
+ var dpi = window.devicePixelRatio || 1;
1766
+ parameters.push('scale=' + dpi);
1767
+
1768
+ parameters = parameters.join('&');
1769
+ return static_root + parameters;
1770
+ };
1771
+
1772
+ GMaps.prototype.addMapType = function(mapTypeId, options) {
1773
+ if (options.hasOwnProperty("getTileUrl") && typeof(options["getTileUrl"]) == "function") {
1774
+ options.tileSize = options.tileSize || new google.maps.Size(256, 256);
1775
+
1776
+ var mapType = new google.maps.ImageMapType(options);
1777
+
1778
+ this.map.mapTypes.set(mapTypeId, mapType);
1779
+ }
1780
+ else {
1781
+ throw "'getTileUrl' function required.";
1782
+ }
1783
+ };
1784
+
1785
+ GMaps.prototype.addOverlayMapType = function(options) {
1786
+ if (options.hasOwnProperty("getTile") && typeof(options["getTile"]) == "function") {
1787
+ var overlayMapTypeIndex = options.index;
1788
+
1789
+ delete options.index;
1790
+
1791
+ this.map.overlayMapTypes.insertAt(overlayMapTypeIndex, options);
1792
+ }
1793
+ else {
1794
+ throw "'getTile' function required.";
1795
+ }
1796
+ };
1797
+
1798
+ GMaps.prototype.removeOverlayMapType = function(overlayMapTypeIndex) {
1799
+ this.map.overlayMapTypes.removeAt(overlayMapTypeIndex);
1800
+ };
1801
+
1802
+ GMaps.prototype.addStyle = function(options) {
1803
+ var styledMapType = new google.maps.StyledMapType(options.styles, { name: options.styledMapName });
1804
+
1805
+ this.map.mapTypes.set(options.mapTypeId, styledMapType);
1806
+ };
1807
+
1808
+ GMaps.prototype.setStyle = function(mapTypeId) {
1809
+ this.map.setMapTypeId(mapTypeId);
1810
+ };
1811
+
1812
+ GMaps.prototype.createPanorama = function(streetview_options) {
1813
+ if (!streetview_options.hasOwnProperty('lat') || !streetview_options.hasOwnProperty('lng')) {
1814
+ streetview_options.lat = this.getCenter().lat();
1815
+ streetview_options.lng = this.getCenter().lng();
1816
+ }
1817
+
1818
+ this.panorama = GMaps.createPanorama(streetview_options);
1819
+
1820
+ this.map.setStreetView(this.panorama);
1821
+
1822
+ return this.panorama;
1823
+ };
1824
+
1825
+ GMaps.createPanorama = function(options) {
1826
+ var el = getElementById(options.el, options.context);
1827
+
1828
+ options.position = new google.maps.LatLng(options.lat, options.lng);
1829
+
1830
+ delete options.el;
1831
+ delete options.context;
1832
+ delete options.lat;
1833
+ delete options.lng;
1834
+
1835
+ var streetview_events = ['closeclick', 'links_changed', 'pano_changed', 'position_changed', 'pov_changed', 'resize', 'visible_changed'],
1836
+ streetview_options = extend_object({visible : true}, options);
1837
+
1838
+ for (var i = 0; i < streetview_events.length; i++) {
1839
+ delete streetview_options[streetview_events[i]];
1840
+ }
1841
+
1842
+ var panorama = new google.maps.StreetViewPanorama(el, streetview_options);
1843
+
1844
+ for (var i = 0; i < streetview_events.length; i++) {
1845
+ (function(object, name) {
1846
+ if (options[name]) {
1847
+ google.maps.event.addListener(object, name, function(){
1848
+ options[name].apply(this);
1849
+ });
1850
+ }
1851
+ })(panorama, streetview_events[i]);
1852
+ }
1853
+
1854
+ return panorama;
1855
+ };
1856
+
1857
+ GMaps.prototype.on = function(event_name, handler) {
1858
+ return GMaps.on(event_name, this, handler);
1859
+ };
1860
+
1861
+ GMaps.prototype.off = function(event_name) {
1862
+ GMaps.off(event_name, this);
1863
+ };
1864
+
1865
+ GMaps.custom_events = ['marker_added', 'marker_removed', 'polyline_added', 'polyline_removed', 'polygon_added', 'polygon_removed', 'geolocated', 'geolocation_failed'];
1866
+
1867
+ GMaps.on = function(event_name, object, handler) {
1868
+ if (GMaps.custom_events.indexOf(event_name) == -1) {
1869
+ return google.maps.event.addListener(object, event_name, handler);
1870
+ }
1871
+ else {
1872
+ var registered_event = {
1873
+ handler : handler,
1874
+ eventName : event_name
1875
+ };
1876
+
1877
+ object.registered_events[event_name] = object.registered_events[event_name] || [];
1878
+ object.registered_events[event_name].push(registered_event);
1879
+
1880
+ return registered_event;
1881
+ }
1882
+ };
1883
+
1884
+ GMaps.off = function(event_name, object) {
1885
+ if (GMaps.custom_events.indexOf(event_name) == -1) {
1886
+ google.maps.event.clearListeners(object, event_name);
1887
+ }
1888
+ else {
1889
+ object.registered_events[event_name] = [];
1890
+ }
1891
+ };
1892
+
1893
+ GMaps.fire = function(event_name, object, scope) {
1894
+ if (GMaps.custom_events.indexOf(event_name) == -1) {
1895
+ google.maps.event.trigger(object, event_name, Array.prototype.slice.apply(arguments).slice(2));
1896
+ }
1897
+ else {
1898
+ if(event_name in scope.registered_events) {
1899
+ var firing_events = scope.registered_events[event_name];
1900
+
1901
+ for(var i = 0; i < firing_events.length; i++) {
1902
+ (function(handler, scope, object) {
1903
+ handler.apply(scope, [object]);
1904
+ })(firing_events[i]['handler'], scope, object);
1905
+ }
1906
+ }
1907
+ }
1908
+ };
1909
+
1910
+ GMaps.geolocate = function(options) {
1911
+ var complete_callback = options.always || options.complete;
1912
+
1913
+ if (navigator.geolocation) {
1914
+ navigator.geolocation.getCurrentPosition(function(position) {
1915
+ options.success(position);
1916
+
1917
+ if (complete_callback) {
1918
+ complete_callback();
1919
+ }
1920
+ }, function(error) {
1921
+ options.error(error);
1922
+
1923
+ if (complete_callback) {
1924
+ complete_callback();
1925
+ }
1926
+ }, options.options);
1927
+ }
1928
+ else {
1929
+ options.not_supported();
1930
+
1931
+ if (complete_callback) {
1932
+ complete_callback();
1933
+ }
1934
+ }
1935
+ };
1936
+
1937
+ GMaps.geocode = function(options) {
1938
+ this.geocoder = new google.maps.Geocoder();
1939
+ var callback = options.callback;
1940
+ if (options.hasOwnProperty('lat') && options.hasOwnProperty('lng')) {
1941
+ options.latLng = new google.maps.LatLng(options.lat, options.lng);
1942
+ }
1943
+
1944
+ delete options.lat;
1945
+ delete options.lng;
1946
+ delete options.callback;
1947
+
1948
+ this.geocoder.geocode(options, function(results, status) {
1949
+ callback(results, status);
1950
+ });
1951
+ };
1952
+
1953
+ //==========================
1954
+ // Polygon containsLatLng
1955
+ // https://github.com/tparkin/Google-Maps-Point-in-Polygon
1956
+ // Poygon getBounds extension - google-maps-extensions
1957
+ // http://code.google.com/p/google-maps-extensions/source/browse/google.maps.Polygon.getBounds.js
1958
+ if (!google.maps.Polygon.prototype.getBounds) {
1959
+ google.maps.Polygon.prototype.getBounds = function(latLng) {
1960
+ var bounds = new google.maps.LatLngBounds();
1961
+ var paths = this.getPaths();
1962
+ var path;
1963
+
1964
+ for (var p = 0; p < paths.getLength(); p++) {
1965
+ path = paths.getAt(p);
1966
+ for (var i = 0; i < path.getLength(); i++) {
1967
+ bounds.extend(path.getAt(i));
1968
+ }
1969
+ }
1970
+
1971
+ return bounds;
1972
+ };
1973
+ }
1974
+
1975
+ if (!google.maps.Polygon.prototype.containsLatLng) {
1976
+ // Polygon containsLatLng - method to determine if a latLng is within a polygon
1977
+ google.maps.Polygon.prototype.containsLatLng = function(latLng) {
1978
+ // Exclude points outside of bounds as there is no way they are in the poly
1979
+ var bounds = this.getBounds();
1980
+
1981
+ if (bounds !== null && !bounds.contains(latLng)) {
1982
+ return false;
1983
+ }
1984
+
1985
+ // Raycast point in polygon method
1986
+ var inPoly = false;
1987
+
1988
+ var numPaths = this.getPaths().getLength();
1989
+ for (var p = 0; p < numPaths; p++) {
1990
+ var path = this.getPaths().getAt(p);
1991
+ var numPoints = path.getLength();
1992
+ var j = numPoints - 1;
1993
+
1994
+ for (var i = 0; i < numPoints; i++) {
1995
+ var vertex1 = path.getAt(i);
1996
+ var vertex2 = path.getAt(j);
1997
+
1998
+ if (vertex1.lng() < latLng.lng() && vertex2.lng() >= latLng.lng() || vertex2.lng() < latLng.lng() && vertex1.lng() >= latLng.lng()) {
1999
+ if (vertex1.lat() + (latLng.lng() - vertex1.lng()) / (vertex2.lng() - vertex1.lng()) * (vertex2.lat() - vertex1.lat()) < latLng.lat()) {
2000
+ inPoly = !inPoly;
2001
+ }
2002
+ }
2003
+
2004
+ j = i;
2005
+ }
2006
+ }
2007
+
2008
+ return inPoly;
2009
+ };
2010
+ }
2011
+
2012
+ google.maps.LatLngBounds.prototype.containsLatLng = function(latLng) {
2013
+ return this.contains(latLng);
2014
+ };
2015
+
2016
+ google.maps.Marker.prototype.setFences = function(fences) {
2017
+ this.fences = fences;
2018
+ };
2019
+
2020
+ google.maps.Marker.prototype.addFence = function(fence) {
2021
+ this.fences.push(fence);
2022
+ };
2023
+
2024
+ google.maps.Marker.prototype.getId = function() {
2025
+ return this['__gm_id'];
2026
+ };
2027
+
2028
+ //==========================
2029
+ // Array indexOf
2030
+ // https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf
2031
+ if (!Array.prototype.indexOf) {
2032
+ Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
2033
+ "use strict";
2034
+ if (this == null) {
2035
+ throw new TypeError();
2036
+ }
2037
+ var t = Object(this);
2038
+ var len = t.length >>> 0;
2039
+ if (len === 0) {
2040
+ return -1;
2041
+ }
2042
+ var n = 0;
2043
+ if (arguments.length > 1) {
2044
+ n = Number(arguments[1]);
2045
+ if (n != n) { // shortcut for verifying if it's NaN
2046
+ n = 0;
2047
+ } else if (n != 0 && n != Infinity && n != -Infinity) {
2048
+ n = (n > 0 || -1) * Math.floor(Math.abs(n));
2049
+ }
2050
+ }
2051
+ if (n >= len) {
2052
+ return -1;
2053
+ }
2054
+ var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
2055
+ for (; k < len; k++) {
2056
+ if (k in t && t[k] === searchElement) {
2057
+ return k;
2058
+ }
2059
+ }
2060
+ return -1;
2061
+ }
2062
+ }
2063
+
2064
+ return GMaps;
2065
+ }));