File indexing completed on 2026-04-09 07:58:27
0001 "use strict";
0002 (function(root, factory) {
0003 if(typeof exports === 'object') {
0004 module.exports = factory();
0005 }
0006 else if(typeof define === 'function' && define.amd) {
0007 define('GMaps', [], factory);
0008 }
0009
0010 root.GMaps = factory();
0011
0012 }(this, function() {
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 if (!(typeof window.google === 'object' && window.google.maps)) {
0023 throw 'Google Maps API is required. Please register the following JavaScript library http://maps.google.com/maps/api/js?sensor=true.'
0024 }
0025
0026 var extend_object = function(obj, new_obj) {
0027 var name;
0028
0029 if (obj === new_obj) {
0030 return obj;
0031 }
0032
0033 for (name in new_obj) {
0034 obj[name] = new_obj[name];
0035 }
0036
0037 return obj;
0038 };
0039
0040 var replace_object = function(obj, replace) {
0041 var name;
0042
0043 if (obj === replace) {
0044 return obj;
0045 }
0046
0047 for (name in replace) {
0048 if (obj[name] != undefined) {
0049 obj[name] = replace[name];
0050 }
0051 }
0052
0053 return obj;
0054 };
0055
0056 var array_map = function(array, callback) {
0057 var original_callback_params = Array.prototype.slice.call(arguments, 2),
0058 array_return = [],
0059 array_length = array.length,
0060 i;
0061
0062 if (Array.prototype.map && array.map === Array.prototype.map) {
0063 array_return = Array.prototype.map.call(array, function(item) {
0064 var callback_params = original_callback_params.slice(0);
0065 callback_params.splice(0, 0, item);
0066
0067 return callback.apply(this, callback_params);
0068 });
0069 }
0070 else {
0071 for (i = 0; i < array_length; i++) {
0072 callback_params = original_callback_params;
0073 callback_params.splice(0, 0, array[i]);
0074 array_return.push(callback.apply(this, callback_params));
0075 }
0076 }
0077
0078 return array_return;
0079 };
0080
0081 var array_flat = function(array) {
0082 var new_array = [],
0083 i;
0084
0085 for (i = 0; i < array.length; i++) {
0086 new_array = new_array.concat(array[i]);
0087 }
0088
0089 return new_array;
0090 };
0091
0092 var coordsToLatLngs = function(coords, useGeoJSON) {
0093 var first_coord = coords[0],
0094 second_coord = coords[1];
0095
0096 if (useGeoJSON) {
0097 first_coord = coords[1];
0098 second_coord = coords[0];
0099 }
0100
0101 return new google.maps.LatLng(first_coord, second_coord);
0102 };
0103
0104 var arrayToLatLng = function(coords, useGeoJSON) {
0105 var i;
0106
0107 for (i = 0; i < coords.length; i++) {
0108 if (!(coords[i] instanceof google.maps.LatLng)) {
0109 if (coords[i].length > 0 && typeof(coords[i][0]) === "object") {
0110 coords[i] = arrayToLatLng(coords[i], useGeoJSON);
0111 }
0112 else {
0113 coords[i] = coordsToLatLngs(coords[i], useGeoJSON);
0114 }
0115 }
0116 }
0117
0118 return coords;
0119 };
0120
0121
0122 var getElementsByClassName = function (class_name, context) {
0123
0124 var element,
0125 _class = class_name.replace('.', '');
0126
0127 if ('jQuery' in this && context) {
0128 element = $("." + _class, context)[0];
0129 } else {
0130 element = document.getElementsByClassName(_class)[0];
0131 }
0132 return element;
0133
0134 };
0135
0136 var getElementById = function(id, context) {
0137 var element,
0138 id = id.replace('#', '');
0139
0140 if ('jQuery' in window && context) {
0141 element = $('#' + id, context)[0];
0142 } else {
0143 element = document.getElementById(id);
0144 };
0145
0146 return element;
0147 };
0148
0149 var findAbsolutePosition = function(obj) {
0150 var curleft = 0,
0151 curtop = 0;
0152
0153 if (obj.offsetParent) {
0154 do {
0155 curleft += obj.offsetLeft;
0156 curtop += obj.offsetTop;
0157 } while (obj = obj.offsetParent);
0158 }
0159
0160 return [curleft, curtop];
0161 };
0162
0163 var GMaps = (function(global) {
0164 "use strict";
0165
0166 var doc = document;
0167
0168 var GMaps = function(options) {
0169 if (!this) return new GMaps(options);
0170
0171 options.zoom = options.zoom || 15;
0172 options.mapType = options.mapType || 'roadmap';
0173
0174 var self = this,
0175 i,
0176 events_that_hide_context_menu = [
0177 'bounds_changed', 'center_changed', 'click', 'dblclick', 'drag',
0178 'dragend', 'dragstart', 'idle', 'maptypeid_changed', 'projection_changed',
0179 'resize', 'tilesloaded', 'zoom_changed'
0180 ],
0181 events_that_doesnt_hide_context_menu = ['mousemove', 'mouseout', 'mouseover'],
0182 options_to_be_deleted = ['el', 'lat', 'lng', 'mapType', 'width', 'height', 'markerClusterer', 'enableNewStyle'],
0183 identifier = options.el || options.div,
0184 markerClustererFunction = options.markerClusterer,
0185 mapType = google.maps.MapTypeId[options.mapType.toUpperCase()],
0186 map_center = new google.maps.LatLng(options.lat, options.lng),
0187 zoomControl = options.zoomControl || true,
0188 zoomControlOpt = options.zoomControlOpt || {
0189 style: 'DEFAULT',
0190 position: 'TOP_LEFT'
0191 },
0192 zoomControlStyle = zoomControlOpt.style || 'DEFAULT',
0193 zoomControlPosition = zoomControlOpt.position || 'TOP_LEFT',
0194 panControl = options.panControl || true,
0195 mapTypeControl = options.mapTypeControl || true,
0196 scaleControl = options.scaleControl || true,
0197 streetViewControl = options.streetViewControl || true,
0198 overviewMapControl = overviewMapControl || true,
0199 map_options = {},
0200 map_base_options = {
0201 zoom: this.zoom,
0202 center: map_center,
0203 mapTypeId: mapType
0204 },
0205 map_controls_options = {
0206 panControl: panControl,
0207 zoomControl: zoomControl,
0208 zoomControlOptions: {
0209 style: google.maps.ZoomControlStyle[zoomControlStyle],
0210 position: google.maps.ControlPosition[zoomControlPosition]
0211 },
0212 mapTypeControl: mapTypeControl,
0213 scaleControl: scaleControl,
0214 streetViewControl: streetViewControl,
0215 overviewMapControl: overviewMapControl
0216 };
0217
0218 if (typeof(options.el) === 'string' || typeof(options.div) === 'string') {
0219
0220 if (identifier.indexOf("#") > -1) {
0221 this.el = getElementById(identifier, options.context);
0222 } else {
0223 this.el = getElementsByClassName.apply(this, [identifier, options.context]);
0224 }
0225
0226 } else {
0227 this.el = identifier;
0228 }
0229
0230 if (typeof(this.el) === 'undefined' || this.el === null) {
0231 throw 'No element defined.';
0232 }
0233
0234 window.context_menu = window.context_menu || {};
0235 window.context_menu[self.el.id] = {};
0236
0237 this.controls = [];
0238 this.overlays = [];
0239 this.layers = [];
0240 this.singleLayers = {};
0241 this.markers = [];
0242 this.polylines = [];
0243 this.routes = [];
0244 this.polygons = [];
0245 this.infoWindow = null;
0246 this.overlay_el = null;
0247 this.zoom = options.zoom;
0248 this.registered_events = {};
0249
0250 this.el.style.width = options.width || this.el.scrollWidth || this.el.offsetWidth;
0251 this.el.style.height = options.height || this.el.scrollHeight || this.el.offsetHeight;
0252
0253 google.maps.visualRefresh = options.enableNewStyle;
0254
0255 for (i = 0; i < options_to_be_deleted.length; i++) {
0256 delete options[options_to_be_deleted[i]];
0257 }
0258
0259 if(options.disableDefaultUI != true) {
0260 map_base_options = extend_object(map_base_options, map_controls_options);
0261 }
0262
0263 map_options = extend_object(map_base_options, options);
0264
0265 for (i = 0; i < events_that_hide_context_menu.length; i++) {
0266 delete map_options[events_that_hide_context_menu[i]];
0267 }
0268
0269 for (i = 0; i < events_that_doesnt_hide_context_menu.length; i++) {
0270 delete map_options[events_that_doesnt_hide_context_menu[i]];
0271 }
0272
0273 this.map = new google.maps.Map(this.el, map_options);
0274
0275 if (markerClustererFunction) {
0276 this.markerClusterer = markerClustererFunction.apply(this, [this.map]);
0277 }
0278
0279 var buildContextMenuHTML = function(control, e) {
0280 var html = '',
0281 options = window.context_menu[self.el.id][control];
0282
0283 for (var i in options){
0284 if (options.hasOwnProperty(i)) {
0285 var option = options[i];
0286
0287 html += '<li><a id="' + control + '_' + i + '" href="#">' + option.title + '</a></li>';
0288 }
0289 }
0290
0291 if (!getElementById('gmaps_context_menu')) return;
0292
0293 var context_menu_element = getElementById('gmaps_context_menu');
0294
0295 context_menu_element.innerHTML = html;
0296
0297 var context_menu_items = context_menu_element.getElementsByTagName('a'),
0298 context_menu_items_count = context_menu_items.length,
0299 i;
0300
0301 for (i = 0; i < context_menu_items_count; i++) {
0302 var context_menu_item = context_menu_items[i];
0303
0304 var assign_menu_item_action = function(ev){
0305 ev.preventDefault();
0306
0307 options[this.id.replace(control + '_', '')].action.apply(self, [e]);
0308 self.hideContextMenu();
0309 };
0310
0311 google.maps.event.clearListeners(context_menu_item, 'click');
0312 google.maps.event.addDomListenerOnce(context_menu_item, 'click', assign_menu_item_action, false);
0313 }
0314
0315 var position = findAbsolutePosition.apply(this, [self.el]),
0316 left = position[0] + e.pixel.x - 15,
0317 top = position[1] + e.pixel.y- 15;
0318
0319 context_menu_element.style.left = left + "px";
0320 context_menu_element.style.top = top + "px";
0321
0322 context_menu_element.style.display = 'block';
0323 };
0324
0325 this.buildContextMenu = function(control, e) {
0326 if (control === 'marker') {
0327 e.pixel = {};
0328
0329 var overlay = new google.maps.OverlayView();
0330 overlay.setMap(self.map);
0331
0332 overlay.draw = function() {
0333 var projection = overlay.getProjection(),
0334 position = e.marker.getPosition();
0335
0336 e.pixel = projection.fromLatLngToContainerPixel(position);
0337
0338 buildContextMenuHTML(control, e);
0339 };
0340 }
0341 else {
0342 buildContextMenuHTML(control, e);
0343 }
0344 };
0345
0346 this.setContextMenu = function(options) {
0347 window.context_menu[self.el.id][options.control] = {};
0348
0349 var i,
0350 ul = doc.createElement('ul');
0351
0352 for (i in options.options) {
0353 if (options.options.hasOwnProperty(i)) {
0354 var option = options.options[i];
0355
0356 window.context_menu[self.el.id][options.control][option.name] = {
0357 title: option.title,
0358 action: option.action
0359 };
0360 }
0361 }
0362
0363 ul.id = 'gmaps_context_menu';
0364 ul.style.display = 'none';
0365 ul.style.position = 'absolute';
0366 ul.style.minWidth = '100px';
0367 ul.style.background = 'white';
0368 ul.style.listStyle = 'none';
0369 ul.style.padding = '8px';
0370 ul.style.boxShadow = '2px 2px 6px #ccc';
0371
0372 doc.body.appendChild(ul);
0373
0374 var context_menu_element = getElementById('gmaps_context_menu')
0375
0376 google.maps.event.addDomListener(context_menu_element, 'mouseout', function(ev) {
0377 if (!ev.relatedTarget || !this.contains(ev.relatedTarget)) {
0378 window.setTimeout(function(){
0379 context_menu_element.style.display = 'none';
0380 }, 400);
0381 }
0382 }, false);
0383 };
0384
0385 this.hideContextMenu = function() {
0386 var context_menu_element = getElementById('gmaps_context_menu');
0387
0388 if (context_menu_element) {
0389 context_menu_element.style.display = 'none';
0390 }
0391 };
0392
0393 var setupListener = function(object, name) {
0394 google.maps.event.addListener(object, name, function(e){
0395 if (e == undefined) {
0396 e = this;
0397 }
0398
0399 options[name].apply(this, [e]);
0400
0401 self.hideContextMenu();
0402 });
0403 };
0404
0405
0406 google.maps.event.addListener(this.map, 'zoom_changed', this.hideContextMenu);
0407
0408 for (var ev = 0; ev < events_that_hide_context_menu.length; ev++) {
0409 var name = events_that_hide_context_menu[ev];
0410
0411 if (name in options) {
0412 setupListener(this.map, name);
0413 }
0414 }
0415
0416 for (var ev = 0; ev < events_that_doesnt_hide_context_menu.length; ev++) {
0417 var name = events_that_doesnt_hide_context_menu[ev];
0418
0419 if (name in options) {
0420 setupListener(this.map, name);
0421 }
0422 }
0423
0424 google.maps.event.addListener(this.map, 'rightclick', function(e) {
0425 if (options.rightclick) {
0426 options.rightclick.apply(this, [e]);
0427 }
0428
0429 if(window.context_menu[self.el.id]['map'] != undefined) {
0430 self.buildContextMenu('map', e);
0431 }
0432 });
0433
0434 this.refresh = function() {
0435 google.maps.event.trigger(this.map, 'resize');
0436 };
0437
0438 this.fitZoom = function() {
0439 var latLngs = [],
0440 markers_length = this.markers.length,
0441 i;
0442
0443 for (i = 0; i < markers_length; i++) {
0444 if(typeof(this.markers[i].visible) === 'boolean' && this.markers[i].visible) {
0445 latLngs.push(this.markers[i].getPosition());
0446 }
0447 }
0448
0449 this.fitLatLngBounds(latLngs);
0450 };
0451
0452 this.fitLatLngBounds = function(latLngs) {
0453 var total = latLngs.length,
0454 bounds = new google.maps.LatLngBounds(),
0455 i;
0456
0457 for(i = 0; i < total; i++) {
0458 bounds.extend(latLngs[i]);
0459 }
0460
0461 this.map.fitBounds(bounds);
0462 };
0463
0464 this.setCenter = function(lat, lng, callback) {
0465 this.map.panTo(new google.maps.LatLng(lat, lng));
0466
0467 if (callback) {
0468 callback();
0469 }
0470 };
0471
0472 this.getElement = function() {
0473 return this.el;
0474 };
0475
0476 this.zoomIn = function(value) {
0477 value = value || 1;
0478
0479 this.zoom = this.map.getZoom() + value;
0480 this.map.setZoom(this.zoom);
0481 };
0482
0483 this.zoomOut = function(value) {
0484 value = value || 1;
0485
0486 this.zoom = this.map.getZoom() - value;
0487 this.map.setZoom(this.zoom);
0488 };
0489
0490 var native_methods = [],
0491 method;
0492
0493 for (method in this.map) {
0494 if (typeof(this.map[method]) == 'function' && !this[method]) {
0495 native_methods.push(method);
0496 }
0497 }
0498
0499 for (i = 0; i < native_methods.length; i++) {
0500 (function(gmaps, scope, method_name) {
0501 gmaps[method_name] = function(){
0502 return scope[method_name].apply(scope, arguments);
0503 };
0504 })(this, this.map, native_methods[i]);
0505 }
0506 };
0507
0508 return GMaps;
0509 })(this);
0510
0511 GMaps.prototype.createControl = function(options) {
0512 var control = document.createElement('div');
0513
0514 control.style.cursor = 'pointer';
0515
0516 if (options.disableDefaultStyles !== true) {
0517 control.style.fontFamily = 'Roboto, Arial, sans-serif';
0518 control.style.fontSize = '11px';
0519 control.style.boxShadow = 'rgba(0, 0, 0, 0.298039) 0px 1px 4px -1px';
0520 }
0521
0522 for (var option in options.style) {
0523 control.style[option] = options.style[option];
0524 }
0525
0526 if (options.id) {
0527 control.id = options.id;
0528 }
0529
0530 if (options.classes) {
0531 control.className = options.classes;
0532 }
0533
0534 if (options.content) {
0535 if (typeof options.content === 'string') {
0536 control.innerHTML = options.content;
0537 }
0538 else if (options.content instanceof HTMLElement) {
0539 control.appendChild(options.content);
0540 }
0541 }
0542
0543 if (options.position) {
0544 control.position = google.maps.ControlPosition[options.position.toUpperCase()];
0545 }
0546
0547 for (var ev in options.events) {
0548 (function(object, name) {
0549 google.maps.event.addDomListener(object, name, function(){
0550 options.events[name].apply(this, [this]);
0551 });
0552 })(control, ev);
0553 }
0554
0555 control.index = 1;
0556
0557 return control;
0558 };
0559
0560 GMaps.prototype.addControl = function(options) {
0561 var control = this.createControl(options);
0562
0563 this.controls.push(control);
0564 this.map.controls[control.position].push(control);
0565
0566 return control;
0567 };
0568
0569 GMaps.prototype.removeControl = function(control) {
0570 var position = null,
0571 i;
0572
0573 for (i = 0; i < this.controls.length; i++) {
0574 if (this.controls[i] == control) {
0575 position = this.controls[i].position;
0576 this.controls.splice(i, 1);
0577 }
0578 }
0579
0580 if (position) {
0581 for (i = 0; i < this.map.controls.length; i++) {
0582 var controlsForPosition = this.map.controls[control.position];
0583
0584 if (controlsForPosition.getAt(i) == control) {
0585 controlsForPosition.removeAt(i);
0586
0587 break;
0588 }
0589 }
0590 }
0591
0592 return control;
0593 };
0594
0595 GMaps.prototype.createMarker = function(options) {
0596 if (options.lat == undefined && options.lng == undefined && options.position == undefined) {
0597 throw 'No latitude or longitude defined.';
0598 }
0599
0600 var self = this,
0601 details = options.details,
0602 fences = options.fences,
0603 outside = options.outside,
0604 base_options = {
0605 position: new google.maps.LatLng(options.lat, options.lng),
0606 map: null
0607 },
0608 marker_options = extend_object(base_options, options);
0609
0610 delete marker_options.lat;
0611 delete marker_options.lng;
0612 delete marker_options.fences;
0613 delete marker_options.outside;
0614
0615 var marker = new google.maps.Marker(marker_options);
0616
0617 marker.fences = fences;
0618
0619 if (options.infoWindow) {
0620 marker.infoWindow = new google.maps.InfoWindow(options.infoWindow);
0621
0622 var info_window_events = ['closeclick', 'content_changed', 'domready', 'position_changed', 'zindex_changed'];
0623
0624 for (var ev = 0; ev < info_window_events.length; ev++) {
0625 (function(object, name) {
0626 if (options.infoWindow[name]) {
0627 google.maps.event.addListener(object, name, function(e){
0628 options.infoWindow[name].apply(this, [e]);
0629 });
0630 }
0631 })(marker.infoWindow, info_window_events[ev]);
0632 }
0633 }
0634
0635 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'];
0636
0637 var marker_events_with_mouse = ['dblclick', 'drag', 'dragend', 'dragstart', 'mousedown', 'mouseout', 'mouseover', 'mouseup'];
0638
0639 for (var ev = 0; ev < marker_events.length; ev++) {
0640 (function(object, name) {
0641 if (options[name]) {
0642 google.maps.event.addListener(object, name, function(){
0643 options[name].apply(this, [this]);
0644 });
0645 }
0646 })(marker, marker_events[ev]);
0647 }
0648
0649 for (var ev = 0; ev < marker_events_with_mouse.length; ev++) {
0650 (function(map, object, name) {
0651 if (options[name]) {
0652 google.maps.event.addListener(object, name, function(me){
0653 if(!me.pixel){
0654 me.pixel = map.getProjection().fromLatLngToPoint(me.latLng)
0655 }
0656
0657 options[name].apply(this, [me]);
0658 });
0659 }
0660 })(this.map, marker, marker_events_with_mouse[ev]);
0661 }
0662
0663 google.maps.event.addListener(marker, 'click', function() {
0664 this.details = details;
0665
0666 if (options.click) {
0667 options.click.apply(this, [this]);
0668 }
0669
0670 if (marker.infoWindow) {
0671 self.hideInfoWindows();
0672 marker.infoWindow.open(self.map, marker);
0673 }
0674 });
0675
0676 google.maps.event.addListener(marker, 'rightclick', function(e) {
0677 e.marker = this;
0678
0679 if (options.rightclick) {
0680 options.rightclick.apply(this, [e]);
0681 }
0682
0683 if (window.context_menu[self.el.id]['marker'] != undefined) {
0684 self.buildContextMenu('marker', e);
0685 }
0686 });
0687
0688 if (marker.fences) {
0689 google.maps.event.addListener(marker, 'dragend', function() {
0690 self.checkMarkerGeofence(marker, function(m, f) {
0691 outside(m, f);
0692 });
0693 });
0694 }
0695
0696 return marker;
0697 };
0698
0699 GMaps.prototype.addMarker = function(options) {
0700 var marker;
0701 if(options.hasOwnProperty('gm_accessors_')) {
0702
0703 marker = options;
0704 }
0705 else {
0706 if ((options.hasOwnProperty('lat') && options.hasOwnProperty('lng')) || options.position) {
0707 marker = this.createMarker(options);
0708 }
0709 else {
0710 throw 'No latitude or longitude defined.';
0711 }
0712 }
0713
0714 marker.setMap(this.map);
0715
0716 if(this.markerClusterer) {
0717 this.markerClusterer.addMarker(marker);
0718 }
0719
0720 this.markers.push(marker);
0721
0722 GMaps.fire('marker_added', marker, this);
0723
0724 return marker;
0725 };
0726
0727 GMaps.prototype.addMarkers = function(array) {
0728 for (var i = 0, marker; marker=array[i]; i++) {
0729 this.addMarker(marker);
0730 }
0731
0732 return this.markers;
0733 };
0734
0735 GMaps.prototype.hideInfoWindows = function() {
0736 for (var i = 0, marker; marker = this.markers[i]; i++){
0737 if (marker.infoWindow) {
0738 marker.infoWindow.close();
0739 }
0740 }
0741 };
0742
0743 GMaps.prototype.removeMarker = function(marker) {
0744 for (var i = 0; i < this.markers.length; i++) {
0745 if (this.markers[i] === marker) {
0746 this.markers[i].setMap(null);
0747 this.markers.splice(i, 1);
0748
0749 if(this.markerClusterer) {
0750 this.markerClusterer.removeMarker(marker);
0751 }
0752
0753 GMaps.fire('marker_removed', marker, this);
0754
0755 break;
0756 }
0757 }
0758
0759 return marker;
0760 };
0761
0762 GMaps.prototype.removeMarkers = function (collection) {
0763 var new_markers = [];
0764
0765 if (typeof collection == 'undefined') {
0766 for (var i = 0; i < this.markers.length; i++) {
0767 var marker = this.markers[i];
0768 marker.setMap(null);
0769
0770 if(this.markerClusterer) {
0771 this.markerClusterer.removeMarker(marker);
0772 }
0773
0774 GMaps.fire('marker_removed', marker, this);
0775 }
0776
0777 this.markers = new_markers;
0778 }
0779 else {
0780 for (var i = 0; i < collection.length; i++) {
0781 var index = this.markers.indexOf(collection[i]);
0782
0783 if (index > -1) {
0784 var marker = this.markers[index];
0785 marker.setMap(null);
0786
0787 if(this.markerClusterer) {
0788 this.markerClusterer.removeMarker(marker);
0789 }
0790
0791 GMaps.fire('marker_removed', marker, this);
0792 }
0793 }
0794
0795 for (var i = 0; i < this.markers.length; i++) {
0796 var marker = this.markers[i];
0797 if (marker.getMap() != null) {
0798 new_markers.push(marker);
0799 }
0800 }
0801
0802 this.markers = new_markers;
0803 }
0804 };
0805
0806 GMaps.prototype.drawOverlay = function(options) {
0807 var overlay = new google.maps.OverlayView(),
0808 auto_show = true;
0809
0810 overlay.setMap(this.map);
0811
0812 if (options.auto_show != null) {
0813 auto_show = options.auto_show;
0814 }
0815
0816 overlay.onAdd = function() {
0817 var el = document.createElement('div');
0818
0819 el.style.borderStyle = "none";
0820 el.style.borderWidth = "0px";
0821 el.style.position = "absolute";
0822 el.style.zIndex = 100;
0823 el.innerHTML = options.content;
0824
0825 overlay.el = el;
0826
0827 if (!options.layer) {
0828 options.layer = 'overlayLayer';
0829 }
0830
0831 var panes = this.getPanes(),
0832 overlayLayer = panes[options.layer],
0833 stop_overlay_events = ['contextmenu', 'DOMMouseScroll', 'dblclick', 'mousedown'];
0834
0835 overlayLayer.appendChild(el);
0836
0837 for (var ev = 0; ev < stop_overlay_events.length; ev++) {
0838 (function(object, name) {
0839 google.maps.event.addDomListener(object, name, function(e){
0840 if (navigator.userAgent.toLowerCase().indexOf('msie') != -1 && document.all) {
0841 e.cancelBubble = true;
0842 e.returnValue = false;
0843 }
0844 else {
0845 e.stopPropagation();
0846 }
0847 });
0848 })(el, stop_overlay_events[ev]);
0849 }
0850
0851 if (options.click) {
0852 panes.overlayMouseTarget.appendChild(overlay.el);
0853 google.maps.event.addDomListener(overlay.el, 'click', function() {
0854 options.click.apply(overlay, [overlay]);
0855 });
0856 }
0857
0858 google.maps.event.trigger(this, 'ready');
0859 };
0860
0861 overlay.draw = function() {
0862 var projection = this.getProjection(),
0863 pixel = projection.fromLatLngToDivPixel(new google.maps.LatLng(options.lat, options.lng));
0864
0865 options.horizontalOffset = options.horizontalOffset || 0;
0866 options.verticalOffset = options.verticalOffset || 0;
0867
0868 var el = overlay.el,
0869 content = el.children[0],
0870 content_height = content.clientHeight,
0871 content_width = content.clientWidth;
0872
0873 switch (options.verticalAlign) {
0874 case 'top':
0875 el.style.top = (pixel.y - content_height + options.verticalOffset) + 'px';
0876 break;
0877 default:
0878 case 'middle':
0879 el.style.top = (pixel.y - (content_height / 2) + options.verticalOffset) + 'px';
0880 break;
0881 case 'bottom':
0882 el.style.top = (pixel.y + options.verticalOffset) + 'px';
0883 break;
0884 }
0885
0886 switch (options.horizontalAlign) {
0887 case 'left':
0888 el.style.left = (pixel.x - content_width + options.horizontalOffset) + 'px';
0889 break;
0890 default:
0891 case 'center':
0892 el.style.left = (pixel.x - (content_width / 2) + options.horizontalOffset) + 'px';
0893 break;
0894 case 'right':
0895 el.style.left = (pixel.x + options.horizontalOffset) + 'px';
0896 break;
0897 }
0898
0899 el.style.display = auto_show ? 'block' : 'none';
0900
0901 if (!auto_show) {
0902 options.show.apply(this, [el]);
0903 }
0904 };
0905
0906 overlay.onRemove = function() {
0907 var el = overlay.el;
0908
0909 if (options.remove) {
0910 options.remove.apply(this, [el]);
0911 }
0912 else {
0913 overlay.el.parentNode.removeChild(overlay.el);
0914 overlay.el = null;
0915 }
0916 };
0917
0918 this.overlays.push(overlay);
0919 return overlay;
0920 };
0921
0922 GMaps.prototype.removeOverlay = function(overlay) {
0923 for (var i = 0; i < this.overlays.length; i++) {
0924 if (this.overlays[i] === overlay) {
0925 this.overlays[i].setMap(null);
0926 this.overlays.splice(i, 1);
0927
0928 break;
0929 }
0930 }
0931 };
0932
0933 GMaps.prototype.removeOverlays = function() {
0934 for (var i = 0, item; item = this.overlays[i]; i++) {
0935 item.setMap(null);
0936 }
0937
0938 this.overlays = [];
0939 };
0940
0941 GMaps.prototype.drawPolyline = function(options) {
0942 var path = [],
0943 points = options.path;
0944
0945 if (points.length) {
0946 if (points[0][0] === undefined) {
0947 path = points;
0948 }
0949 else {
0950 for (var i = 0, latlng; latlng = points[i]; i++) {
0951 path.push(new google.maps.LatLng(latlng[0], latlng[1]));
0952 }
0953 }
0954 }
0955
0956 var polyline_options = {
0957 map: this.map,
0958 path: path,
0959 strokeColor: options.strokeColor,
0960 strokeOpacity: options.strokeOpacity,
0961 strokeWeight: options.strokeWeight,
0962 geodesic: options.geodesic,
0963 clickable: true,
0964 editable: false,
0965 visible: true
0966 };
0967
0968 if (options.hasOwnProperty("clickable")) {
0969 polyline_options.clickable = options.clickable;
0970 }
0971
0972 if (options.hasOwnProperty("editable")) {
0973 polyline_options.editable = options.editable;
0974 }
0975
0976 if (options.hasOwnProperty("icons")) {
0977 polyline_options.icons = options.icons;
0978 }
0979
0980 if (options.hasOwnProperty("zIndex")) {
0981 polyline_options.zIndex = options.zIndex;
0982 }
0983
0984 var polyline = new google.maps.Polyline(polyline_options);
0985
0986 var polyline_events = ['click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'rightclick'];
0987
0988 for (var ev = 0; ev < polyline_events.length; ev++) {
0989 (function(object, name) {
0990 if (options[name]) {
0991 google.maps.event.addListener(object, name, function(e){
0992 options[name].apply(this, [e]);
0993 });
0994 }
0995 })(polyline, polyline_events[ev]);
0996 }
0997
0998 this.polylines.push(polyline);
0999
1000 GMaps.fire('polyline_added', polyline, this);
1001
1002 return polyline;
1003 };
1004
1005 GMaps.prototype.removePolyline = function(polyline) {
1006 for (var i = 0; i < this.polylines.length; i++) {
1007 if (this.polylines[i] === polyline) {
1008 this.polylines[i].setMap(null);
1009 this.polylines.splice(i, 1);
1010
1011 GMaps.fire('polyline_removed', polyline, this);
1012
1013 break;
1014 }
1015 }
1016 };
1017
1018 GMaps.prototype.removePolylines = function() {
1019 for (var i = 0, item; item = this.polylines[i]; i++) {
1020 item.setMap(null);
1021 }
1022
1023 this.polylines = [];
1024 };
1025
1026 GMaps.prototype.drawCircle = function(options) {
1027 options = extend_object({
1028 map: this.map,
1029 center: new google.maps.LatLng(options.lat, options.lng)
1030 }, options);
1031
1032 delete options.lat;
1033 delete options.lng;
1034
1035 var polygon = new google.maps.Circle(options),
1036 polygon_events = ['click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'rightclick'];
1037
1038 for (var ev = 0; ev < polygon_events.length; ev++) {
1039 (function(object, name) {
1040 if (options[name]) {
1041 google.maps.event.addListener(object, name, function(e){
1042 options[name].apply(this, [e]);
1043 });
1044 }
1045 })(polygon, polygon_events[ev]);
1046 }
1047
1048 this.polygons.push(polygon);
1049
1050 return polygon;
1051 };
1052
1053 GMaps.prototype.drawRectangle = function(options) {
1054 options = extend_object({
1055 map: this.map
1056 }, options);
1057
1058 var latLngBounds = new google.maps.LatLngBounds(
1059 new google.maps.LatLng(options.bounds[0][0], options.bounds[0][1]),
1060 new google.maps.LatLng(options.bounds[1][0], options.bounds[1][1])
1061 );
1062
1063 options.bounds = latLngBounds;
1064
1065 var polygon = new google.maps.Rectangle(options),
1066 polygon_events = ['click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'rightclick'];
1067
1068 for (var ev = 0; ev < polygon_events.length; ev++) {
1069 (function(object, name) {
1070 if (options[name]) {
1071 google.maps.event.addListener(object, name, function(e){
1072 options[name].apply(this, [e]);
1073 });
1074 }
1075 })(polygon, polygon_events[ev]);
1076 }
1077
1078 this.polygons.push(polygon);
1079
1080 return polygon;
1081 };
1082
1083 GMaps.prototype.drawPolygon = function(options) {
1084 var useGeoJSON = false;
1085
1086 if(options.hasOwnProperty("useGeoJSON")) {
1087 useGeoJSON = options.useGeoJSON;
1088 }
1089
1090 delete options.useGeoJSON;
1091
1092 options = extend_object({
1093 map: this.map
1094 }, options);
1095
1096 if (useGeoJSON == false) {
1097 options.paths = [options.paths.slice(0)];
1098 }
1099
1100 if (options.paths.length > 0) {
1101 if (options.paths[0].length > 0) {
1102 options.paths = array_flat(array_map(options.paths, arrayToLatLng, useGeoJSON));
1103 }
1104 }
1105
1106 var polygon = new google.maps.Polygon(options),
1107 polygon_events = ['click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'rightclick'];
1108
1109 for (var ev = 0; ev < polygon_events.length; ev++) {
1110 (function(object, name) {
1111 if (options[name]) {
1112 google.maps.event.addListener(object, name, function(e){
1113 options[name].apply(this, [e]);
1114 });
1115 }
1116 })(polygon, polygon_events[ev]);
1117 }
1118
1119 this.polygons.push(polygon);
1120
1121 GMaps.fire('polygon_added', polygon, this);
1122
1123 return polygon;
1124 };
1125
1126 GMaps.prototype.removePolygon = function(polygon) {
1127 for (var i = 0; i < this.polygons.length; i++) {
1128 if (this.polygons[i] === polygon) {
1129 this.polygons[i].setMap(null);
1130 this.polygons.splice(i, 1);
1131
1132 GMaps.fire('polygon_removed', polygon, this);
1133
1134 break;
1135 }
1136 }
1137 };
1138
1139 GMaps.prototype.removePolygons = function() {
1140 for (var i = 0, item; item = this.polygons[i]; i++) {
1141 item.setMap(null);
1142 }
1143
1144 this.polygons = [];
1145 };
1146
1147 GMaps.prototype.getFromFusionTables = function(options) {
1148 var events = options.events;
1149
1150 delete options.events;
1151
1152 var fusion_tables_options = options,
1153 layer = new google.maps.FusionTablesLayer(fusion_tables_options);
1154
1155 for (var ev in events) {
1156 (function(object, name) {
1157 google.maps.event.addListener(object, name, function(e) {
1158 events[name].apply(this, [e]);
1159 });
1160 })(layer, ev);
1161 }
1162
1163 this.layers.push(layer);
1164
1165 return layer;
1166 };
1167
1168 GMaps.prototype.loadFromFusionTables = function(options) {
1169 var layer = this.getFromFusionTables(options);
1170 layer.setMap(this.map);
1171
1172 return layer;
1173 };
1174
1175 GMaps.prototype.getFromKML = function(options) {
1176 var url = options.url,
1177 events = options.events;
1178
1179 delete options.url;
1180 delete options.events;
1181
1182 var kml_options = options,
1183 layer = new google.maps.KmlLayer(url, kml_options);
1184
1185 for (var ev in events) {
1186 (function(object, name) {
1187 google.maps.event.addListener(object, name, function(e) {
1188 events[name].apply(this, [e]);
1189 });
1190 })(layer, ev);
1191 }
1192
1193 this.layers.push(layer);
1194
1195 return layer;
1196 };
1197
1198 GMaps.prototype.loadFromKML = function(options) {
1199 var layer = this.getFromKML(options);
1200 layer.setMap(this.map);
1201
1202 return layer;
1203 };
1204
1205 GMaps.prototype.addLayer = function(layerName, options) {
1206
1207 options = options || {};
1208 var layer;
1209
1210 switch(layerName) {
1211 case 'weather': this.singleLayers.weather = layer = new google.maps.weather.WeatherLayer();
1212 break;
1213 case 'clouds': this.singleLayers.clouds = layer = new google.maps.weather.CloudLayer();
1214 break;
1215 case 'traffic': this.singleLayers.traffic = layer = new google.maps.TrafficLayer();
1216 break;
1217 case 'transit': this.singleLayers.transit = layer = new google.maps.TransitLayer();
1218 break;
1219 case 'bicycling': this.singleLayers.bicycling = layer = new google.maps.BicyclingLayer();
1220 break;
1221 case 'panoramio':
1222 this.singleLayers.panoramio = layer = new google.maps.panoramio.PanoramioLayer();
1223 layer.setTag(options.filter);
1224 delete options.filter;
1225
1226
1227 if (options.click) {
1228 google.maps.event.addListener(layer, 'click', function(event) {
1229 options.click(event);
1230 delete options.click;
1231 });
1232 }
1233 break;
1234 case 'places':
1235 this.singleLayers.places = layer = new google.maps.places.PlacesService(this.map);
1236
1237
1238 if (options.search || options.nearbySearch || options.radarSearch) {
1239 var placeSearchRequest = {
1240 bounds : options.bounds || null,
1241 keyword : options.keyword || null,
1242 location : options.location || null,
1243 name : options.name || null,
1244 radius : options.radius || null,
1245 rankBy : options.rankBy || null,
1246 types : options.types || null
1247 };
1248
1249 if (options.radarSearch) {
1250 layer.radarSearch(placeSearchRequest, options.radarSearch);
1251 }
1252
1253 if (options.search) {
1254 layer.search(placeSearchRequest, options.search);
1255 }
1256
1257 if (options.nearbySearch) {
1258 layer.nearbySearch(placeSearchRequest, options.nearbySearch);
1259 }
1260 }
1261
1262
1263 if (options.textSearch) {
1264 var textSearchRequest = {
1265 bounds : options.bounds || null,
1266 location : options.location || null,
1267 query : options.query || null,
1268 radius : options.radius || null
1269 };
1270
1271 layer.textSearch(textSearchRequest, options.textSearch);
1272 }
1273 break;
1274 }
1275
1276 if (layer !== undefined) {
1277 if (typeof layer.setOptions == 'function') {
1278 layer.setOptions(options);
1279 }
1280 if (typeof layer.setMap == 'function') {
1281 layer.setMap(this.map);
1282 }
1283
1284 return layer;
1285 }
1286 };
1287
1288 GMaps.prototype.removeLayer = function(layer) {
1289 if (typeof(layer) == "string" && this.singleLayers[layer] !== undefined) {
1290 this.singleLayers[layer].setMap(null);
1291
1292 delete this.singleLayers[layer];
1293 }
1294 else {
1295 for (var i = 0; i < this.layers.length; i++) {
1296 if (this.layers[i] === layer) {
1297 this.layers[i].setMap(null);
1298 this.layers.splice(i, 1);
1299
1300 break;
1301 }
1302 }
1303 }
1304 };
1305
1306 var travelMode, unitSystem;
1307
1308 GMaps.prototype.getRoutes = function(options) {
1309 switch (options.travelMode) {
1310 case 'bicycling':
1311 travelMode = google.maps.TravelMode.BICYCLING;
1312 break;
1313 case 'transit':
1314 travelMode = google.maps.TravelMode.TRANSIT;
1315 break;
1316 case 'driving':
1317 travelMode = google.maps.TravelMode.DRIVING;
1318 break;
1319 default:
1320 travelMode = google.maps.TravelMode.WALKING;
1321 break;
1322 }
1323
1324 if (options.unitSystem === 'imperial') {
1325 unitSystem = google.maps.UnitSystem.IMPERIAL;
1326 }
1327 else {
1328 unitSystem = google.maps.UnitSystem.METRIC;
1329 }
1330
1331 var base_options = {
1332 avoidHighways: false,
1333 avoidTolls: false,
1334 optimizeWaypoints: false,
1335 waypoints: []
1336 },
1337 request_options = extend_object(base_options, options);
1338
1339 request_options.origin = /string/.test(typeof options.origin) ? options.origin : new google.maps.LatLng(options.origin[0], options.origin[1]);
1340 request_options.destination = /string/.test(typeof options.destination) ? options.destination : new google.maps.LatLng(options.destination[0], options.destination[1]);
1341 request_options.travelMode = travelMode;
1342 request_options.unitSystem = unitSystem;
1343
1344 delete request_options.callback;
1345 delete request_options.error;
1346
1347 var self = this,
1348 service = new google.maps.DirectionsService();
1349
1350 service.route(request_options, function(result, status) {
1351 if (status === google.maps.DirectionsStatus.OK) {
1352 for (var r in result.routes) {
1353 if (result.routes.hasOwnProperty(r)) {
1354 self.routes.push(result.routes[r]);
1355 }
1356 }
1357
1358 if (options.callback) {
1359 options.callback(self.routes);
1360 }
1361 }
1362 else {
1363 if (options.error) {
1364 options.error(result, status);
1365 }
1366 }
1367 });
1368 };
1369
1370 GMaps.prototype.removeRoutes = function() {
1371 this.routes = [];
1372 };
1373
1374 GMaps.prototype.getElevations = function(options) {
1375 options = extend_object({
1376 locations: [],
1377 path : false,
1378 samples : 256
1379 }, options);
1380
1381 if (options.locations.length > 0) {
1382 if (options.locations[0].length > 0) {
1383 options.locations = array_flat(array_map([options.locations], arrayToLatLng, false));
1384 }
1385 }
1386
1387 var callback = options.callback;
1388 delete options.callback;
1389
1390 var service = new google.maps.ElevationService();
1391
1392
1393 if (!options.path) {
1394 delete options.path;
1395 delete options.samples;
1396
1397 service.getElevationForLocations(options, function(result, status) {
1398 if (callback && typeof(callback) === "function") {
1399 callback(result, status);
1400 }
1401 });
1402
1403 } else {
1404 var pathRequest = {
1405 path : options.locations,
1406 samples : options.samples
1407 };
1408
1409 service.getElevationAlongPath(pathRequest, function(result, status) {
1410 if (callback && typeof(callback) === "function") {
1411 callback(result, status);
1412 }
1413 });
1414 }
1415 };
1416
1417 GMaps.prototype.cleanRoute = GMaps.prototype.removePolylines;
1418
1419 GMaps.prototype.drawRoute = function(options) {
1420 var self = this;
1421
1422 this.getRoutes({
1423 origin: options.origin,
1424 destination: options.destination,
1425 travelMode: options.travelMode,
1426 waypoints: options.waypoints,
1427 unitSystem: options.unitSystem,
1428 error: options.error,
1429 callback: function(e) {
1430 if (e.length > 0) {
1431 var polyline_options = {
1432 path: e[e.length - 1].overview_path,
1433 strokeColor: options.strokeColor,
1434 strokeOpacity: options.strokeOpacity,
1435 strokeWeight: options.strokeWeight
1436 };
1437
1438 if (options.hasOwnProperty("icons")) {
1439 polyline_options.icons = options.icons;
1440 }
1441
1442 self.drawPolyline(polyline_options);
1443
1444 if (options.callback) {
1445 options.callback(e[e.length - 1]);
1446 }
1447 }
1448 }
1449 });
1450 };
1451
1452 GMaps.prototype.travelRoute = function(options) {
1453 if (options.origin && options.destination) {
1454 this.getRoutes({
1455 origin: options.origin,
1456 destination: options.destination,
1457 travelMode: options.travelMode,
1458 waypoints : options.waypoints,
1459 unitSystem: options.unitSystem,
1460 error: options.error,
1461 callback: function(e) {
1462
1463 if (e.length > 0 && options.start) {
1464 options.start(e[e.length - 1]);
1465 }
1466
1467
1468 if (e.length > 0 && options.step) {
1469 var route = e[e.length - 1];
1470 if (route.legs.length > 0) {
1471 var steps = route.legs[0].steps;
1472 for (var i = 0, step; step = steps[i]; i++) {
1473 step.step_number = i;
1474 options.step(step, (route.legs[0].steps.length - 1));
1475 }
1476 }
1477 }
1478
1479
1480 if (e.length > 0 && options.end) {
1481 options.end(e[e.length - 1]);
1482 }
1483 }
1484 });
1485 }
1486 else if (options.route) {
1487 if (options.route.legs.length > 0) {
1488 var steps = options.route.legs[0].steps;
1489 for (var i = 0, step; step = steps[i]; i++) {
1490 step.step_number = i;
1491 options.step(step);
1492 }
1493 }
1494 }
1495 };
1496
1497 GMaps.prototype.drawSteppedRoute = function(options) {
1498 var self = this;
1499
1500 if (options.origin && options.destination) {
1501 this.getRoutes({
1502 origin: options.origin,
1503 destination: options.destination,
1504 travelMode: options.travelMode,
1505 waypoints : options.waypoints,
1506 error: options.error,
1507 callback: function(e) {
1508
1509 if (e.length > 0 && options.start) {
1510 options.start(e[e.length - 1]);
1511 }
1512
1513
1514 if (e.length > 0 && options.step) {
1515 var route = e[e.length - 1];
1516 if (route.legs.length > 0) {
1517 var steps = route.legs[0].steps;
1518 for (var i = 0, step; step = steps[i]; i++) {
1519 step.step_number = i;
1520 var polyline_options = {
1521 path: step.path,
1522 strokeColor: options.strokeColor,
1523 strokeOpacity: options.strokeOpacity,
1524 strokeWeight: options.strokeWeight
1525 };
1526
1527 if (options.hasOwnProperty("icons")) {
1528 polyline_options.icons = options.icons;
1529 }
1530
1531 self.drawPolyline(polyline_options);
1532 options.step(step, (route.legs[0].steps.length - 1));
1533 }
1534 }
1535 }
1536
1537
1538 if (e.length > 0 && options.end) {
1539 options.end(e[e.length - 1]);
1540 }
1541 }
1542 });
1543 }
1544 else if (options.route) {
1545 if (options.route.legs.length > 0) {
1546 var steps = options.route.legs[0].steps;
1547 for (var i = 0, step; step = steps[i]; i++) {
1548 step.step_number = i;
1549 var polyline_options = {
1550 path: step.path,
1551 strokeColor: options.strokeColor,
1552 strokeOpacity: options.strokeOpacity,
1553 strokeWeight: options.strokeWeight
1554 };
1555
1556 if (options.hasOwnProperty("icons")) {
1557 polyline_options.icons = options.icons;
1558 }
1559
1560 self.drawPolyline(polyline_options);
1561 options.step(step);
1562 }
1563 }
1564 }
1565 };
1566
1567 GMaps.Route = function(options) {
1568 this.origin = options.origin;
1569 this.destination = options.destination;
1570 this.waypoints = options.waypoints;
1571
1572 this.map = options.map;
1573 this.route = options.route;
1574 this.step_count = 0;
1575 this.steps = this.route.legs[0].steps;
1576 this.steps_length = this.steps.length;
1577
1578 var polyline_options = {
1579 path: new google.maps.MVCArray(),
1580 strokeColor: options.strokeColor,
1581 strokeOpacity: options.strokeOpacity,
1582 strokeWeight: options.strokeWeight
1583 };
1584
1585 if (options.hasOwnProperty("icons")) {
1586 polyline_options.icons = options.icons;
1587 }
1588
1589 this.polyline = this.map.drawPolyline(polyline_options).getPath();
1590 };
1591
1592 GMaps.Route.prototype.getRoute = function(options) {
1593 var self = this;
1594
1595 this.map.getRoutes({
1596 origin : this.origin,
1597 destination : this.destination,
1598 travelMode : options.travelMode,
1599 waypoints : this.waypoints || [],
1600 error: options.error,
1601 callback : function() {
1602 self.route = e[0];
1603
1604 if (options.callback) {
1605 options.callback.call(self);
1606 }
1607 }
1608 });
1609 };
1610
1611 GMaps.Route.prototype.back = function() {
1612 if (this.step_count > 0) {
1613 this.step_count--;
1614 var path = this.route.legs[0].steps[this.step_count].path;
1615
1616 for (var p in path){
1617 if (path.hasOwnProperty(p)){
1618 this.polyline.pop();
1619 }
1620 }
1621 }
1622 };
1623
1624 GMaps.Route.prototype.forward = function() {
1625 if (this.step_count < this.steps_length) {
1626 var path = this.route.legs[0].steps[this.step_count].path;
1627
1628 for (var p in path){
1629 if (path.hasOwnProperty(p)){
1630 this.polyline.push(path[p]);
1631 }
1632 }
1633 this.step_count++;
1634 }
1635 };
1636
1637 GMaps.prototype.checkGeofence = function(lat, lng, fence) {
1638 return fence.containsLatLng(new google.maps.LatLng(lat, lng));
1639 };
1640
1641 GMaps.prototype.checkMarkerGeofence = function(marker, outside_callback) {
1642 if (marker.fences) {
1643 for (var i = 0, fence; fence = marker.fences[i]; i++) {
1644 var pos = marker.getPosition();
1645 if (!this.checkGeofence(pos.lat(), pos.lng(), fence)) {
1646 outside_callback(marker, fence);
1647 }
1648 }
1649 }
1650 };
1651
1652 GMaps.prototype.toImage = function(options) {
1653 var options = options || {},
1654 static_map_options = {};
1655
1656 static_map_options['size'] = options['size'] || [this.el.clientWidth, this.el.clientHeight];
1657 static_map_options['lat'] = this.getCenter().lat();
1658 static_map_options['lng'] = this.getCenter().lng();
1659
1660 if (this.markers.length > 0) {
1661 static_map_options['markers'] = [];
1662
1663 for (var i = 0; i < this.markers.length; i++) {
1664 static_map_options['markers'].push({
1665 lat: this.markers[i].getPosition().lat(),
1666 lng: this.markers[i].getPosition().lng()
1667 });
1668 }
1669 }
1670
1671 if (this.polylines.length > 0) {
1672 var polyline = this.polylines[0];
1673
1674 static_map_options['polyline'] = {};
1675 static_map_options['polyline']['path'] = google.maps.geometry.encoding.encodePath(polyline.getPath());
1676 static_map_options['polyline']['strokeColor'] = polyline.strokeColor
1677 static_map_options['polyline']['strokeOpacity'] = polyline.strokeOpacity
1678 static_map_options['polyline']['strokeWeight'] = polyline.strokeWeight
1679 }
1680
1681 return GMaps.staticMapURL(static_map_options);
1682 };
1683
1684 GMaps.staticMapURL = function(options){
1685 var parameters = [],
1686 data,
1687 static_root = (location.protocol === 'file:' ? 'http:' : location.protocol ) + '//maps.googleapis.com/maps/api/staticmap';
1688
1689 if (options.url) {
1690 static_root = options.url;
1691 delete options.url;
1692 }
1693
1694 static_root += '?';
1695
1696 var markers = options.markers;
1697
1698 delete options.markers;
1699
1700 if (!markers && options.marker) {
1701 markers = [options.marker];
1702 delete options.marker;
1703 }
1704
1705 var styles = options.styles;
1706
1707 delete options.styles;
1708
1709 var polyline = options.polyline;
1710 delete options.polyline;
1711
1712
1713 if (options.center) {
1714 parameters.push('center=' + options.center);
1715 delete options.center;
1716 }
1717 else if (options.address) {
1718 parameters.push('center=' + options.address);
1719 delete options.address;
1720 }
1721 else if (options.lat) {
1722 parameters.push(['center=', options.lat, ',', options.lng].join(''));
1723 delete options.lat;
1724 delete options.lng;
1725 }
1726 else if (options.visible) {
1727 var visible = encodeURI(options.visible.join('|'));
1728 parameters.push('visible=' + visible);
1729 }
1730
1731 var size = options.size;
1732 if (size) {
1733 if (size.join) {
1734 size = size.join('x');
1735 }
1736 delete options.size;
1737 }
1738 else {
1739 size = '630x300';
1740 }
1741 parameters.push('size=' + size);
1742
1743 if (!options.zoom && options.zoom !== false) {
1744 options.zoom = 15;
1745 }
1746
1747 var sensor = options.hasOwnProperty('sensor') ? !!options.sensor : true;
1748 delete options.sensor;
1749 parameters.push('sensor=' + sensor);
1750
1751 for (var param in options) {
1752 if (options.hasOwnProperty(param)) {
1753 parameters.push(param + '=' + options[param]);
1754 }
1755 }
1756
1757
1758 if (markers) {
1759 var marker, loc;
1760
1761 for (var i = 0; data = markers[i]; i++) {
1762 marker = [];
1763
1764 if (data.size && data.size !== 'normal') {
1765 marker.push('size:' + data.size);
1766 delete data.size;
1767 }
1768 else if (data.icon) {
1769 marker.push('icon:' + encodeURI(data.icon));
1770 delete data.icon;
1771 }
1772
1773 if (data.color) {
1774 marker.push('color:' + data.color.replace('#', '0x'));
1775 delete data.color;
1776 }
1777
1778 if (data.label) {
1779 marker.push('label:' + data.label[0].toUpperCase());
1780 delete data.label;
1781 }
1782
1783 loc = (data.address ? data.address : data.lat + ',' + data.lng);
1784 delete data.address;
1785 delete data.lat;
1786 delete data.lng;
1787
1788 for(var param in data){
1789 if (data.hasOwnProperty(param)) {
1790 marker.push(param + ':' + data[param]);
1791 }
1792 }
1793
1794 if (marker.length || i === 0) {
1795 marker.push(loc);
1796 marker = marker.join('|');
1797 parameters.push('markers=' + encodeURI(marker));
1798 }
1799
1800 else {
1801 marker = parameters.pop() + encodeURI('|' + loc);
1802 parameters.push(marker);
1803 }
1804 }
1805 }
1806
1807
1808 if (styles) {
1809 for (var i = 0; i < styles.length; i++) {
1810 var styleRule = [];
1811 if (styles[i].featureType){
1812 styleRule.push('feature:' + styles[i].featureType.toLowerCase());
1813 }
1814
1815 if (styles[i].elementType) {
1816 styleRule.push('element:' + styles[i].elementType.toLowerCase());
1817 }
1818
1819 for (var j = 0; j < styles[i].stylers.length; j++) {
1820 for (var p in styles[i].stylers[j]) {
1821 var ruleArg = styles[i].stylers[j][p];
1822 if (p == 'hue' || p == 'color') {
1823 ruleArg = '0x' + ruleArg.substring(1);
1824 }
1825 styleRule.push(p + ':' + ruleArg);
1826 }
1827 }
1828
1829 var rule = styleRule.join('|');
1830 if (rule != '') {
1831 parameters.push('style=' + rule);
1832 }
1833 }
1834 }
1835
1836
1837 function parseColor(color, opacity) {
1838 if (color[0] === '#'){
1839 color = color.replace('#', '0x');
1840
1841 if (opacity) {
1842 opacity = parseFloat(opacity);
1843 opacity = Math.min(1, Math.max(opacity, 0));
1844 if (opacity === 0) {
1845 return '0x00000000';
1846 }
1847 opacity = (opacity * 255).toString(16);
1848 if (opacity.length === 1) {
1849 opacity += opacity;
1850 }
1851
1852 color = color.slice(0,8) + opacity;
1853 }
1854 }
1855 return color;
1856 }
1857
1858 if (polyline) {
1859 data = polyline;
1860 polyline = [];
1861
1862 if (data.strokeWeight) {
1863 polyline.push('weight:' + parseInt(data.strokeWeight, 10));
1864 }
1865
1866 if (data.strokeColor) {
1867 var color = parseColor(data.strokeColor, data.strokeOpacity);
1868 polyline.push('color:' + color);
1869 }
1870
1871 if (data.fillColor) {
1872 var fillcolor = parseColor(data.fillColor, data.fillOpacity);
1873 polyline.push('fillcolor:' + fillcolor);
1874 }
1875
1876 var path = data.path;
1877 if (path.join) {
1878 for (var j=0, pos; pos=path[j]; j++) {
1879 polyline.push(pos.join(','));
1880 }
1881 }
1882 else {
1883 polyline.push('enc:' + path);
1884 }
1885
1886 polyline = polyline.join('|');
1887 parameters.push('path=' + encodeURI(polyline));
1888 }
1889
1890
1891 var dpi = window.devicePixelRatio || 1;
1892 parameters.push('scale=' + dpi);
1893
1894 parameters = parameters.join('&');
1895 return static_root + parameters;
1896 };
1897
1898 GMaps.prototype.addMapType = function(mapTypeId, options) {
1899 if (options.hasOwnProperty("getTileUrl") && typeof(options["getTileUrl"]) == "function") {
1900 options.tileSize = options.tileSize || new google.maps.Size(256, 256);
1901
1902 var mapType = new google.maps.ImageMapType(options);
1903
1904 this.map.mapTypes.set(mapTypeId, mapType);
1905 }
1906 else {
1907 throw "'getTileUrl' function required.";
1908 }
1909 };
1910
1911 GMaps.prototype.addOverlayMapType = function(options) {
1912 if (options.hasOwnProperty("getTile") && typeof(options["getTile"]) == "function") {
1913 var overlayMapTypeIndex = options.index;
1914
1915 delete options.index;
1916
1917 this.map.overlayMapTypes.insertAt(overlayMapTypeIndex, options);
1918 }
1919 else {
1920 throw "'getTile' function required.";
1921 }
1922 };
1923
1924 GMaps.prototype.removeOverlayMapType = function(overlayMapTypeIndex) {
1925 this.map.overlayMapTypes.removeAt(overlayMapTypeIndex);
1926 };
1927
1928 GMaps.prototype.addStyle = function(options) {
1929 var styledMapType = new google.maps.StyledMapType(options.styles, { name: options.styledMapName });
1930
1931 this.map.mapTypes.set(options.mapTypeId, styledMapType);
1932 };
1933
1934 GMaps.prototype.setStyle = function(mapTypeId) {
1935 this.map.setMapTypeId(mapTypeId);
1936 };
1937
1938 GMaps.prototype.createPanorama = function(streetview_options) {
1939 if (!streetview_options.hasOwnProperty('lat') || !streetview_options.hasOwnProperty('lng')) {
1940 streetview_options.lat = this.getCenter().lat();
1941 streetview_options.lng = this.getCenter().lng();
1942 }
1943
1944 this.panorama = GMaps.createPanorama(streetview_options);
1945
1946 this.map.setStreetView(this.panorama);
1947
1948 return this.panorama;
1949 };
1950
1951 GMaps.createPanorama = function(options) {
1952 var el = getElementById(options.el, options.context);
1953
1954 options.position = new google.maps.LatLng(options.lat, options.lng);
1955
1956 delete options.el;
1957 delete options.context;
1958 delete options.lat;
1959 delete options.lng;
1960
1961 var streetview_events = ['closeclick', 'links_changed', 'pano_changed', 'position_changed', 'pov_changed', 'resize', 'visible_changed'],
1962 streetview_options = extend_object({visible : true}, options);
1963
1964 for (var i = 0; i < streetview_events.length; i++) {
1965 delete streetview_options[streetview_events[i]];
1966 }
1967
1968 var panorama = new google.maps.StreetViewPanorama(el, streetview_options);
1969
1970 for (var i = 0; i < streetview_events.length; i++) {
1971 (function(object, name) {
1972 if (options[name]) {
1973 google.maps.event.addListener(object, name, function(){
1974 options[name].apply(this);
1975 });
1976 }
1977 })(panorama, streetview_events[i]);
1978 }
1979
1980 return panorama;
1981 };
1982
1983 GMaps.prototype.on = function(event_name, handler) {
1984 return GMaps.on(event_name, this, handler);
1985 };
1986
1987 GMaps.prototype.off = function(event_name) {
1988 GMaps.off(event_name, this);
1989 };
1990
1991 GMaps.custom_events = ['marker_added', 'marker_removed', 'polyline_added', 'polyline_removed', 'polygon_added', 'polygon_removed', 'geolocated', 'geolocation_failed'];
1992
1993 GMaps.on = function(event_name, object, handler) {
1994 if (GMaps.custom_events.indexOf(event_name) == -1) {
1995 if(object instanceof GMaps) object = object.map;
1996 return google.maps.event.addListener(object, event_name, handler);
1997 }
1998 else {
1999 var registered_event = {
2000 handler : handler,
2001 eventName : event_name
2002 };
2003
2004 object.registered_events[event_name] = object.registered_events[event_name] || [];
2005 object.registered_events[event_name].push(registered_event);
2006
2007 return registered_event;
2008 }
2009 };
2010
2011 GMaps.off = function(event_name, object) {
2012 if (GMaps.custom_events.indexOf(event_name) == -1) {
2013 if(object instanceof GMaps) object = object.map;
2014 google.maps.event.clearListeners(object, event_name);
2015 }
2016 else {
2017 object.registered_events[event_name] = [];
2018 }
2019 };
2020
2021 GMaps.fire = function(event_name, object, scope) {
2022 if (GMaps.custom_events.indexOf(event_name) == -1) {
2023 google.maps.event.trigger(object, event_name, Array.prototype.slice.apply(arguments).slice(2));
2024 }
2025 else {
2026 if(event_name in scope.registered_events) {
2027 var firing_events = scope.registered_events[event_name];
2028
2029 for(var i = 0; i < firing_events.length; i++) {
2030 (function(handler, scope, object) {
2031 handler.apply(scope, [object]);
2032 })(firing_events[i]['handler'], scope, object);
2033 }
2034 }
2035 }
2036 };
2037
2038 GMaps.geolocate = function(options) {
2039 var complete_callback = options.always || options.complete;
2040
2041 if (navigator.geolocation) {
2042 navigator.geolocation.getCurrentPosition(function(position) {
2043 options.success(position);
2044
2045 if (complete_callback) {
2046 complete_callback();
2047 }
2048 }, function(error) {
2049 options.error(error);
2050
2051 if (complete_callback) {
2052 complete_callback();
2053 }
2054 }, options.options);
2055 }
2056 else {
2057 options.not_supported();
2058
2059 if (complete_callback) {
2060 complete_callback();
2061 }
2062 }
2063 };
2064
2065 GMaps.geocode = function(options) {
2066 this.geocoder = new google.maps.Geocoder();
2067 var callback = options.callback;
2068 if (options.hasOwnProperty('lat') && options.hasOwnProperty('lng')) {
2069 options.latLng = new google.maps.LatLng(options.lat, options.lng);
2070 }
2071
2072 delete options.lat;
2073 delete options.lng;
2074 delete options.callback;
2075
2076 this.geocoder.geocode(options, function(results, status) {
2077 callback(results, status);
2078 });
2079 };
2080
2081
2082
2083
2084
2085
2086 if (!google.maps.Polygon.prototype.getBounds) {
2087 google.maps.Polygon.prototype.getBounds = function(latLng) {
2088 var bounds = new google.maps.LatLngBounds();
2089 var paths = this.getPaths();
2090 var path;
2091
2092 for (var p = 0; p < paths.getLength(); p++) {
2093 path = paths.getAt(p);
2094 for (var i = 0; i < path.getLength(); i++) {
2095 bounds.extend(path.getAt(i));
2096 }
2097 }
2098
2099 return bounds;
2100 };
2101 }
2102
2103 if (!google.maps.Polygon.prototype.containsLatLng) {
2104
2105 google.maps.Polygon.prototype.containsLatLng = function(latLng) {
2106
2107 var bounds = this.getBounds();
2108
2109 if (bounds !== null && !bounds.contains(latLng)) {
2110 return false;
2111 }
2112
2113
2114 var inPoly = false;
2115
2116 var numPaths = this.getPaths().getLength();
2117 for (var p = 0; p < numPaths; p++) {
2118 var path = this.getPaths().getAt(p);
2119 var numPoints = path.getLength();
2120 var j = numPoints - 1;
2121
2122 for (var i = 0; i < numPoints; i++) {
2123 var vertex1 = path.getAt(i);
2124 var vertex2 = path.getAt(j);
2125
2126 if (vertex1.lng() < latLng.lng() && vertex2.lng() >= latLng.lng() || vertex2.lng() < latLng.lng() && vertex1.lng() >= latLng.lng()) {
2127 if (vertex1.lat() + (latLng.lng() - vertex1.lng()) / (vertex2.lng() - vertex1.lng()) * (vertex2.lat() - vertex1.lat()) < latLng.lat()) {
2128 inPoly = !inPoly;
2129 }
2130 }
2131
2132 j = i;
2133 }
2134 }
2135
2136 return inPoly;
2137 };
2138 }
2139
2140 if (!google.maps.Circle.prototype.containsLatLng) {
2141 google.maps.Circle.prototype.containsLatLng = function(latLng) {
2142 if (google.maps.geometry) {
2143 return google.maps.geometry.spherical.computeDistanceBetween(this.getCenter(), latLng) <= this.getRadius();
2144 }
2145 else {
2146 return true;
2147 }
2148 };
2149 }
2150
2151 google.maps.LatLngBounds.prototype.containsLatLng = function(latLng) {
2152 return this.contains(latLng);
2153 };
2154
2155 google.maps.Marker.prototype.setFences = function(fences) {
2156 this.fences = fences;
2157 };
2158
2159 google.maps.Marker.prototype.addFence = function(fence) {
2160 this.fences.push(fence);
2161 };
2162
2163 google.maps.Marker.prototype.getId = function() {
2164 return this['__gm_id'];
2165 };
2166
2167
2168
2169
2170 if (!Array.prototype.indexOf) {
2171 Array.prototype.indexOf = function (searchElement ) {
2172 "use strict";
2173 if (this == null) {
2174 throw new TypeError();
2175 }
2176 var t = Object(this);
2177 var len = t.length >>> 0;
2178 if (len === 0) {
2179 return -1;
2180 }
2181 var n = 0;
2182 if (arguments.length > 1) {
2183 n = Number(arguments[1]);
2184 if (n != n) {
2185 n = 0;
2186 } else if (n != 0 && n != Infinity && n != -Infinity) {
2187 n = (n > 0 || -1) * Math.floor(Math.abs(n));
2188 }
2189 }
2190 if (n >= len) {
2191 return -1;
2192 }
2193 var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
2194 for (; k < len; k++) {
2195 if (k in t && t[k] === searchElement) {
2196 return k;
2197 }
2198 }
2199 return -1;
2200 }
2201 }
2202
2203 return GMaps;
2204 }));