1"use strict"; 2(function(root, factory) { 3 if(typeof exports === 'object') { 4 module.exports = factory(); 5 } 6 else if(typeof define === 'function' && define.amd) { 7 define('GMaps', [], factory); 8 } 9 10 root.GMaps = factory(); 11 12}(this, function() { 13 14/*! 15 * GMaps.js v0.4.17 16 * http://hpneo.github.com/gmaps/ 17 * 18 * Copyright 2015, Gustavo Leon 19 * Released under the MIT License. 20 */ 21 22if (!(typeof window.google === 'object' && window.google.maps)) { 23 throw 'Google Maps API is required. Please register the following JavaScript library http://maps.google.com/maps/api/js?sensor=true.' 24} 25 26var extend_object = function(obj, new_obj) { 27 var name; 28 29 if (obj === new_obj) { 30 return obj; 31 } 32 33 for (name in new_obj) { 34 obj[name] = new_obj[name]; 35 } 36 37 return obj; 38}; 39 40var replace_object = function(obj, replace) { 41 var name; 42 43 if (obj === replace) { 44 return obj; 45 } 46 47 for (name in replace) { 48 if (obj[name] != undefined) { 49 obj[name] = replace[name]; 50 } 51 } 52 53 return obj; 54}; 55 56var array_map = function(array, callback) { 57 var original_callback_params = Array.prototype.slice.call(arguments, 2), 58 array_return = [], 59 array_length = array.length, 60 i; 61 62 if (Array.prototype.map && array.map === Array.prototype.map) { 63 array_return = Array.prototype.map.call(array, function(item) { 64 callback_params = original_callback_params; 65 callback_params.splice(0, 0, item); 66 67 return callback.apply(this, callback_params); 68 }); 69 } 70 else { 71 for (i = 0; i < array_length; i++) { 72 callback_params = original_callback_params; 73 callback_params.splice(0, 0, array[i]); 74 array_return.push(callback.apply(this, callback_params)); 75 } 76 } 77 78 return array_return; 79}; 80 81var array_flat = function(array) { 82 var new_array = [], 83 i; 84 85 for (i = 0; i < array.length; i++) { 86 new_array = new_array.concat(array[i]); 87 } 88 89 return new_array; 90}; 91 92var coordsToLatLngs = function(coords, useGeoJSON) { 93 var first_coord = coords[0], 94 second_coord = coords[1]; 95 96 if (useGeoJSON) { 97 first_coord = coords[1]; 98 second_coord = coords[0]; 99 } 100 101 return new google.maps.LatLng(first_coord, second_coord); 102}; 103 104var arrayToLatLng = function(coords, useGeoJSON) { 105 var i; 106 107 for (i = 0; i < coords.length; i++) { 108 if (!(coords[i] instanceof google.maps.LatLng)) { 109 if (coords[i].length > 0 && typeof(coords[i][0]) === "object") { 110 coords[i] = arrayToLatLng(coords[i], useGeoJSON); 111 } 112 else {
113 coords[i] = coordsToLatLngs(coords[i], useGeoJSON); 114 } 115 } 116 } 117 118 return coords; 119}; 120 121 122var getElementsByClassName = function (class_name, context) { 123 124 var element, 125 _class = class_name.replace('.', ''); 126 127 if ('jQuery' in this && context) { 128 element = $("." + _class, context)[0]; 129 } else { 130 element = document.getElementsByClassName(_class)[0]; 131 } 132 return element; 133 134}; 135 136var getElementById = function(id, context) { 137 var element, 138 id = id.replace('#', ''); 139 140 if ('jQuery' in window && context) { 141 element = $('#' + id, context)[0]; 142 } else { 143 element = document.getElementById(id); 144 }; 145 146 return element; 147}; 148 149var findAbsolutePosition = function(obj) { 150 var curleft = 0, 151 curtop = 0; 152 153 if (obj.offsetParent) { 154 do { 155 curleft += obj.offsetLeft; 156 curtop += obj.offsetTop; 157 } while (obj = obj.offsetParent); 158 } 159 160 return [curleft, curtop]; 161}; 162 163var GMaps = (function(global) { 164 "use strict"; 165 166 var doc = document; 167 168 var GMaps = function(options) { 169 if (!this) return new GMaps(options); 170 171 options.zoom = options.zoom || 15; 172 options.mapType = options.mapType || 'roadmap'; 173 174 var self = this, 175 i, 176 events_that_hide_context_menu = [ 177 'bounds_changed', 'center_changed', 'click', 'dblclick', 'drag', 178 'dragend', 'dragstart', 'idle', 'maptypeid_changed', 'projection_changed', 179 'resize', 'tilesloaded', 'zoom_changed' 180 ], 181 events_that_doesnt_hide_context_menu = ['mousemove', 'mouseout', 'mouseover'], 182 options_to_be_deleted = ['el', 'lat', 'lng', 'mapType', 'width', 'height', 'markerClusterer', 'enableNewStyle'], 183 identifier = options.el || options.div, 184 markerClustererFunction = options.markerClusterer, 185 mapType = google.maps.MapTypeId[options.mapType.toUpperCase()], 186 map_center = new google.maps.LatLng(options.lat, options.lng), 187 zoomControl = options.zoomControl || true, 188 zoomControlOpt = options.zoomControlOpt || { 189 style: 'DEFAULT', 190 position: 'TOP_LEFT' 191 }, 192 zoomControlStyle = zoomControlOpt.style || 'DEFAULT', 193 zoomControlPosition = zoomControlOpt.position || 'TOP_LEFT', 194 panControl = options.panControl || true, 195 mapTypeControl = options.mapTypeControl || true, 196 scaleControl = options.scaleControl || true, 197 streetViewControl = options.streetViewControl || true, 198 overviewMapControl = overviewMapControl || true, 199 map_options = {}, 200 map_base_options = { 201 zoom: this.zoom, 202 center: map_center, 203 mapTypeId: mapType 204 }, 205 map_controls_options = { 206 panControl: panControl, 207 zoomControl: zoomControl, 208 zoomControlOptions: { 209 style: google.maps.ZoomControlStyle[zoomControlStyle], 210 position: google.maps.ControlPosition[zoomControlPosition] 211 }, 212 mapTypeControl: mapTypeControl, 213 scaleControl: scaleControl, 214 streetViewControl: streetViewControl, 215 overviewMapControl: overviewMapControl 216 }; 217 218 if (typeof(options.el) === 'string' || typeof(options.div) === 'string') { 219 220 if (identifier.indexOf("#") > -1) { 221 this.el = getElementById(identifier, options.context); 222 } else { 223 this.el = getElementsByClassName.apply(this, [identifier, options.context]); 224 } 225 226 } else { 227 this.el = identifier; 228 } 229 230 if (typeof(this.el) === 'undefined' || this.el === null) { 231 throw 'No element defined.'; 232 } 233 234 window.context_menu = window.context_menu || {}; 235 window.context_menu[self.el.id] = {}; 236 237 this.controls = []; 238 this.overlays = []; 239 this.layers = []; // array with kml/georss and fusiontables layers, can be as many 240 this.singleLayers = {}; // object with the other layers, only one per layer 241 this.markers = []; 242 this.polylines = []; 243 this.routes = []; 244 this.polygons = []; 245 this.infoWindow = null; 246 this.overlay_el = null; 247 this.zoom = options.zoom; 248 this.registered_events = {}; 249 250 this.el.style.width = options.width || this.el.scrollWidth || this.el.offsetWidth; 251 this.el.style.height = options.height || this.el.scrollHeight || this.el.offsetHeight; 252 253 google.maps.visualRefresh = options.enableNewStyle; 254 255 for (i = 0; i < options_to_be_deleted.length; i++) { 256 delete options[options_to_be_deleted[i]]; 257 } 258 259 if(options.disableDefaultUI != true) { 260 map_base_options = extend_object(map_base_options, map_controls_options); 261 } 262 263 map_options = extend_object(map_base_options, options); 264 265 for (i = 0; i < events_that_hide_context_menu.length; i++) { 266 delete map_options[events_that_hide_context_menu[i]]; 267 } 268 269 for (i = 0; i < events_that_doesnt_hide_context_menu.length; i++) { 270 delete map_options[events_that_doesnt_hide_context_menu[i]]; 271 } 272 273 this.map = new google.maps.Map(this.el, map_options); 274 275 if (markerClustererFunction) { 276 this.markerClusterer = markerClustererFunction.apply(this, [this.map]); 277 } 278 279 var buildContextMenuHTML = function(control, e) { 280 var html = '', 281 options = window.context_menu[self.el.id][control]; 282 283 for (var i in options){ 284 if (options.hasOwnProperty(i)) { 285 var option = options[i]; 286 287 html += '<li><a id="' + control + '_' + i + '" href="#">
287' + option.title + '</a></li>'; 288 } 289 } 290 291 if (!getElementById('gmaps_context_menu')) return; 292 293 var context_menu_element = getElementById('gmaps_context_menu'); 294 295 context_menu_element.innerHTML = html; 296 297 var context_menu_items = context_menu_element.getElementsByTagName('a'), 298 context_menu_items_count = context_menu_items.length, 299 i; 300 301 for (i = 0; i < context_menu_items_count; i++) { 302 var context_menu_item = context_menu_items[i]; 303 304 var assign_menu_item_action = function(ev){ 305 ev.preventDefault(); 306 307 options[this.id.replace(control + '_', '')].action.apply(self, [e]); 308 self.hideContextMenu(); 309 }; 310 311 google.maps.event.clearListeners(context_menu_item, 'click'); 312 google.maps.event.addDomListenerOnce(context_menu_item, 'click', assign_menu_item_action, false); 313 } 314 315 var position = findAbsolutePosition.apply(this, [self.el]), 316 left = position[0] + e.pixel.x - 15, 317 top = position[1] + e.pixel.y- 15; 318 319 context_menu_element.style.left = left + "px"; 320 context_menu_element.style.top = top + "px"; 321 322 context_menu_element.style.display = 'block'; 323 }; 324 325 this.buildContextMenu = function(control, e) { 326 if (control === 'marker') { 327 e.pixel = {}; 328 329 var overlay = new google.maps.OverlayView(); 330 overlay.setMap(self.map); 331 332 overlay.draw = function() { 333 var projection = overlay.getProjection(), 334 position = e.marker.getPosition(); 335 336 e.pixel = projection.fromLatLngToContainerPixel(position); 337 338 buildContextMenuHTML(control, e); 339 }; 340 } 341 else { 342 buildContextMenuHTML(control, e); 343 } 344 }; 345 346 this.setContextMenu = function(options) { 347 window.context_menu[self.el.id][options.control] = {}; 348 349 var i, 350 ul = doc.createElement('ul'); 351 352 for (i in options.options) { 353 if (options.options.hasOwnProperty(i)) { 354 var option = options.options[i]; 355 356 window.context_menu[self.el.id][options.control][option.name] = { 357 title: option.title, 358 action: option.action 359 }; 360 } 361 } 362 363 ul.id = 'gmaps_context_menu'; 364 ul.style.display = 'none'; 365 ul.style.position = 'absolute'; 366 ul.style.minWidth = '100px'; 367 ul.style.background = 'white'; 368 ul.style.listStyle = 'none'; 369 ul.style.padding = '8px'; 370 ul.style.boxShadow = '2px 2px 6px #ccc'; 371 372 doc.body.appendChild(ul); 373 374 var context_menu_element = getElementById('gmaps_context_menu') 375 376 google.maps.event.addDomListener(context_menu_element, 'mouseout', function(ev) { 377 if (!ev.relatedTarget || !this.contains(ev.relatedTarget)) { 378 window.setTimeout(function(){ 379 context_menu_element.style.display = 'none'; 380 }, 400); 381 } 382 }, false); 383 }; 384 385 this.hideContextMenu = function() { 386 var context_menu_element = getElementById('gmaps_context_menu'); 387 388 if (context_menu_element) { 389 context_menu_element.style.display = 'none'; 390 } 391 }; 392 393 var setupListener = function(object, name) { 394 google.maps.event.addListener(object, name, function(e){ 395 if (e == undefined) { 396 e = this; 397 } 398 399 options[name].apply(this, [e]); 400 401 self.hideContextMenu(); 402 }); 403 }; 404 405 //google.maps.event.addListener(this.map, 'idle', this.hideContextMenu); 406 google.maps.event.addListener(this.map, 'zoom_changed', this.hideContextMenu); 407 408 for (var ev = 0; ev < events_that_hide_context_menu.length; ev++) { 409 var name = events_that_hide_context_menu[ev]; 410 411 if (name in options) { 412 setupListener(this.map, name); 413 } 414 } 415 416 for (var ev = 0; ev < events_that_doesnt_hide_context_menu.length; ev++) { 417 var name = events_that_doesnt_hide_context_menu[ev]; 418 419 if (name in options) { 420 setupListener(this.map, name); 421 } 422 } 423 424 google.maps.event.addListener(this.map, 'rightclick', function(e) { 425 if (options.rightclick) { 426 options.rightclick.apply(this, [e]); 427 } 428 429 if(window.context_menu[self.el.id]['map'] != undefined) { 430 self.buildContextMenu('map', e); 431 } 432 });
433 434 this.refresh = function() { 435 google.maps.event.trigger(this.map, 'resize'); 436 }; 437 438 this.fitZoom = function() { 439 var latLngs = [], 440 markers_length = this.markers.length, 441 i; 442 443 for (i = 0; i < markers_length; i++) { 444 if(typeof(this.markers[i].visible) === 'boolean' && this.markers[i].visible) { 445 latLngs.push(this.markers[i].getPosition()); 446 } 447 } 448 449 this.fitLatLngBounds(latLngs); 450 }; 451 452 this.fitLatLngBounds = function(latLngs) { 453 var total = latLngs.length, 454 bounds = new google.maps.LatLngBounds(), 455 i; 456 457 for(i = 0; i < total; i++) { 458 bounds.extend(latLngs[i]); 459 } 460 461 this.map.fitBounds(bounds); 462 }; 463 464 this.setCenter = function(lat, lng, callback) { 465 this.map.panTo(new google.maps.LatLng(lat, lng)); 466 467 if (callback) { 468 callback(); 469 } 470 }; 471 472 this.getElement = function() { 473 return this.el; 474 }; 475 476 this.zoomIn = function(value) { 477 value = value || 1; 478 479 this.zoom = this.map.getZoom() + value; 480 this.map.setZoom(this.zoom); 481 }; 482 483 this.zoomOut = function(value) { 484 value = value || 1; 485 486 this.zoom = this.map.getZoom() - value; 487 this.map.setZoom(this.zoom); 488 }; 489 490 var native_methods = [], 491 method; 492 493 for (method in this.map) { 494 if (typeof(this.map[method]) == 'function' && !this[method]) { 495 native_methods.push(method); 496 } 497 } 498 499 for (i = 0; i < native_methods.length; i++) { 500 (function(gmaps, scope, method_name) { 501 gmaps[method_name] = function(){ 502 return scope[method_name].apply(scope, arguments); 503 }; 504 })(this, this.map, native_methods[i]); 505 } 506 }; 507 508 return GMaps; 509})(this); 510 511GMaps.prototype.createControl = function(options) { 512 var control = document.createElement('div'); 513 514 control.style.cursor = 'pointer'; 515 516 if (options.disableDefaultStyles !== true) { 517 control.style.fontFamily = 'Roboto, Arial, sans-serif'; 518 control.style.fontSize = '11px'; 519 control.style.boxShadow = 'rgba(0, 0, 0, 0.298039) 0px 1px 4px -1px'; 520 } 521 522 for (var option in options.style) { 523 control.style[option] = options.style[option]; 524 } 525 526 if (options.id) { 527 control.id = options.id; 528 } 529 530 if (options.classes) { 531 control.className = options.classes; 532 } 533 534 if (options.content) { 535 if (typeof options.content === 'string') { 536 control.innerHTML = options.content; 537 } 538 else if (options.content instanceof HTMLElement) { 539 control.appendChild(options.content); 540 } 541 } 542 543 if (options.position) { 544 control.position = google.maps.ControlPosition[options.position.toUpperCase()]; 545 } 546 547 for (var ev in options.events) { 548 (function(object, name) { 549 google.maps.event.addDomListener(object, name, function(){ 550 options.events[name].apply(this, [this]); 551 }); 552 })(control, ev); 553 } 554 555 control.index = 1; 556 557 return control; 558}; 559 560GMaps.prototype.addControl = function(options) { 561 var control = this.createControl(options); 562 563 this.controls.push(control); 564 this.map.controls[control.position].push(control); 565 566 return control; 567}; 568 569GMaps.prototype.removeControl = function(control) { 570 var position = null, 571 i; 572 573 for (i = 0; i < this.controls.length; i++) { 574 if (this.controls[i] == control) { 575 position = this.controls[i].position; 576 this.controls.splice(i, 1); 577 } 578 } 579 580 if (position) { 581 for (i = 0; i < this.map.controls.length; i++) { 582 var controlsForPosition = this.map.controls[control.position]; 583 584 if (controlsForPosition.getAt(i) == control) { 585 controlsForPosition.removeAt(i); 586 587 break; 588 } 589 } 590 } 591 592 return control; 593}; 594 595GMaps.prototype.createMarker = function(options) { 596 if (options.lat == undefined && options.lng == undefined && options.position == undefined) { 597 throw 'No latitude or longitude defined.'; 598 } 599 600 var self = this, 601 details = options.details, 602 fences = options.fences, 603 outside = options.outside, 604 base_options = { 605 position: new google.maps.LatLng(options.lat, options.lng), 606 map: null 607 }, 608 marker_options = extend_object(base_options, options); 609 610 delete marker_options.lat; 611 delete marker_options.lng; 612 delete marker_options.fences; 613 delete marker_options.outside; 614 615 var marker = new google.maps.Marker(marker_options); 616 617 marker.fences = fences; 618 619 if (options.infoWindow) { 620 marker.infoWindow = new google.maps.InfoWindow(options.infoWindow); 621 622 var info_window_events = ['closeclick', 'content_changed', 'domready', 'position_changed', 'zindex_changed']; 623 624 for (var ev = 0; ev < info_window_events.length; ev++) { 625 (function(object, name) { 626 if (options.infoWindow[name]) { 627 google.maps.event.addListener(object, name, function(e){
628 options.infoWindow[name].apply(this, [e]); 629 }); 630 } 631 })(marker.infoWindow, info_window_events[ev]); 632 } 633 } 634 635 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']; 636 637 var marker_events_with_mouse = ['dblclick', 'drag', 'dragend', 'dragstart', 'mousedown', 'mouseout', 'mouseover', 'mouseup']; 638 639 for (var ev = 0; ev < marker_events.length; ev++) { 640 (function(object, name) { 641 if (options[name]) { 642 google.maps.event.addListener(object, name, function(){ 643 options[name].apply(this, [this]); 644 }); 645 } 646 })(marker, marker_events[ev]); 647 } 648 649 for (var ev = 0; ev < marker_events_with_mouse.length; ev++) { 650 (function(map, object, name) { 651 if (options[name]) { 652 google.maps.event.addListener(object, name, function(me){ 653 if(!me.pixel){ 654 me.pixel = map.getProjection().fromLatLngToPoint(me.latLng) 655 } 656 657 options[name].apply(this, [me]); 658 }); 659 } 660 })(this.map, marker, marker_events_with_mouse[ev]); 661 } 662 663 google.maps.event.addListener(marker, 'click', function() { 664 this.details = details; 665 666 if (options.click) { 667 options.click.apply(this, [this]); 668 } 669 670 if (marker.infoWindow) { 671 self.hideInfoWindows(); 672 marker.infoWindow.open(self.map, marker); 673 } 674 }); 675 676 google.maps.event.addListener(marker, 'rightclick', function(e) { 677 e.marker = this; 678 679 if (options.rightclick) { 680 options.rightclick.apply(this, [e]); 681 } 682 683 if (window.context_menu[self.el.id]['marker'] != undefined) { 684 self.buildContextMenu('marker', e); 685 } 686 }); 687 688 if (marker.fences) { 689 google.maps.event.addListener(marker, 'dragend', function() { 690 self.checkMarkerGeofence(marker, function(m, f) { 691 outside(m, f); 692 }); 693 }); 694 } 695 696 return marker; 697}; 698 699GMaps.prototype.addMarker = function(options) { 700 var marker; 701 if(options.hasOwnProperty('gm_accessors_')) { 702 // Native google.maps.Marker object 703 marker = options; 704 } 705 else { 706 if ((options.hasOwnProperty('lat') && options.hasOwnProperty('lng')) || options.position) { 707 marker = this.createMarker(options); 708 } 709 else { 710 throw 'No latitude or longitude defined.'; 711 } 712 } 713 714 marker.setMap(this.map); 715 716 if(this.markerClusterer) { 717 this.markerClusterer.addMarker(marker); 718 } 719 720 this.markers.push(marker); 721 722 GMaps.fire('marker_added', marker, this); 723 724 return marker; 725}; 726 727GMaps.prototype.addMarkers = function(array) { 728 for (var i = 0, marker; marker=array[i]; i++) { 729 this.addMarker(marker); 730 } 731 732 return this.markers; 733}; 734 735GMaps.prototype.hideInfoWindows = function() { 736 for (var i = 0, marker; marker = this.markers[i]; i++){ 737 if (marker.infoWindow) { 738 marker.infoWindow.close(); 739 } 740 } 741}; 742 743GMaps.prototype.removeMarker = function(marker) { 744 for (var i = 0; i < this.markers.length; i++) { 745 if (this.markers[i] === marker) { 746 this.markers[i].setMap(null); 747 this.markers.splice(i, 1); 748 749 if(this.markerClusterer) { 750 this.markerClusterer.removeMarker(marker); 751 } 752 753 GMaps.fire('marker_removed', marker, this); 754 755 break; 756 } 757 } 758 759 return marker; 760}; 761 762GMaps.prototype.removeMarkers = function (collection) { 763 var new_markers = []; 764 765 if (typeof collection == 'undefined') { 766 for (var i = 0; i < this.markers.length; i++) { 767 var marker = this.markers[i]; 768 marker.setMap(null); 769 770 if(this.markerClusterer) { 771 this.markerClusterer.removeMarker(marker); 772 } 773 774 GMaps.fire('marker_removed', marker, this); 775 } 776 777 this.markers = new_markers; 778 } 779 else { 780 for (var i = 0; i < collection.length; i++) { 781 var index = this.markers.indexOf(collection[i]); 782 783 if (index > -1) { 784 var marker = this.markers[index]; 785 marker.setMap(null); 786 787 if(this.markerClusterer) { 788 this.markerClusterer.removeMarker(marker); 789 } 790 791 GMaps.fire('marker_removed', marker, this); 792 } 793 } 794 795 for (var i = 0; i < this.markers.length; i++) { 796 var marker = this.markers[i];
797 if (marker.getMap() != null) { 798 new_markers.push(marker); 799 } 800 } 801 802 this.markers = new_markers; 803 } 804}; 805 806GMaps.prototype.drawOverlay = function(options) { 807 var overlay = new google.maps.OverlayView(), 808 auto_show = true; 809 810 overlay.setMap(this.map); 811 812 if (options.auto_show != null) { 813 auto_show = options.auto_show; 814 } 815 816 overlay.onAdd = function() { 817 var el = document.createElement('div'); 818 819 el.style.borderStyle = "none"; 820 el.style.borderWidth = "0px"; 821 el.style.position = "absolute"; 822 el.style.zIndex = 100; 823 el.innerHTML = options.content; 824 825 overlay.el = el; 826 827 if (!options.layer) { 828 options.layer = 'overlayLayer'; 829 } 830 831 var panes = this.getPanes(), 832 overlayLayer = panes[options.layer], 833 stop_overlay_events = ['contextmenu', 'DOMMouseScroll', 'dblclick', 'mousedown']; 834 835 overlayLayer.appendChild(el); 836 837 for (var ev = 0; ev < stop_overlay_events.length; ev++) { 838 (function(object, name) { 839 google.maps.event.addDomListener(object, name, function(e){ 840 if (navigator.userAgent.toLowerCase().indexOf('msie') != -1 && document.all) { 841 e.cancelBubble = true; 842 e.returnValue = false; 843 } 844 else { 845 e.stopPropagation(); 846 } 847 }); 848 })(el, stop_overlay_events[ev]); 849 } 850 851 if (options.click) { 852 panes.overlayMouseTarget.appendChild(overlay.el); 853 google.maps.event.addDomListener(overlay.el, 'click', function() { 854 options.click.apply(overlay, [overlay]); 855 }); 856 } 857 858 google.maps.event.trigger(this, 'ready'); 859 }; 860 861 overlay.draw = function() { 862 var projection = this.getProjection(), 863 pixel = projection.fromLatLngToDivPixel(new google.maps.LatLng(options.lat, options.lng)); 864 865 options.horizontalOffset = options.horizontalOffset || 0; 866 options.verticalOffset = options.verticalOffset || 0; 867 868 var el = overlay.el, 869 content = el.children[0], 870 content_height = content.clientHeight, 871 content_width = content.clientWidth; 872 873 switch (options.verticalAlign) { 874 case 'top': 875 el.style.top = (pixel.y - content_height + options.verticalOffset) + 'px'; 876 break; 877 default: 878 case 'middle': 879 el.style.top = (pixel.y - (content_height / 2) + options.verticalOffset) + 'px'; 880 break; 881 case 'bottom': 882 el.style.top = (pixel.y + options.verticalOffset) + 'px'; 883 break; 884 } 885 886 switch (options.horizontalAlign) { 887 case 'left': 888 el.style.left = (pixel.x - content_width + options.horizontalOffset) + 'px'; 889 break; 890 default: 891 case 'center': 892 el.style.left = (pixel.x - (content_width / 2) + options.horizontalOffset) + 'px'; 893 break; 894 case 'right': 895 el.style.left = (pixel.x + options.horizontalOffset) + 'px'; 896 break; 897 } 898 899 el.style.display = auto_show ? 'block' : 'none'; 900 901 if (!auto_show) { 902 options.show.apply(this, [el]); 903 } 904 }; 905 906 overlay.onRemove = function() { 907 var el = overlay.el; 908 909 if (options.remove) { 910 options.remove.apply(this, [el]); 911 } 912 else { 913 overlay.el.parentNode.removeChild(overlay.el); 914 overlay.el = null; 915 } 916 }; 917 918 this.overlays.push(overlay); 919 return overlay; 920}; 921 922GMaps.prototype.removeOverlay = function(overlay) { 923 for (var i = 0; i < this.overlays.length; i++) { 924 if (this.overlays[i] === overlay) { 925 this.overlays[i].setMap(null); 926 this.overlays.splice(i, 1); 927 928 break; 929 } 930 } 931}; 932 933GMaps.prototype.removeOverlays = function() { 934 for (var i = 0, item; item = this.overlays[i]; i++) { 935 item.setMap(null); 936 } 937 938 this.overlays = []; 939}; 940 941GMaps.prototype.drawPolyline = function(options) { 942 var path = [], 943 points = options.path; 944 945 if (points.length) { 946 if (points[0][0] === undefined) { 947 path = points; 948 } 949 else { 950 for (var i = 0, latlng; latlng = points[i]; i++) { 951 path.push(new google.maps.LatLng(latlng[0], latlng[1])); 952 } 953 } 954 } 955 956 var polyline_options = { 957 map: this.map, 958 path: path, 959 strokeColor: options.strokeColor, 960 strokeOpacity: options.strokeOpacity, 961 strokeWeight: options.strokeWeight, 962 geodesic: options.geodesic, 963 clickable: true, 964 editable: false, 965 visible: true 966 }; 967 968 if (options.hasOwnProperty("clickable")) { 969 polyline_options.clickable = options.clickable; 970 } 971 972 if (options.hasOwnProperty("editable")) { 973 polyline_options.editable = options.editable; 974 } 975 976 if (options.hasOwnProperty("icons")) { 977 polyline_options.icons = options.icons; 978 } 979 980 if (options.hasOwnProperty("zIndex")) { 981 polyline_options.zIndex = options.zIndex; 982 } 983 984 var polyline = new google.maps.Polyline(polyline_options); 985 986 var polyline_events = ['click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'rightclick']; 987 988 for (var ev = 0; ev < polyline_events.length; ev++) { 989 (function(object, name) { 990 if (options[name]) { 991 google.maps.event.addListener(object, name, function(e){
992 options[name].apply(this, [e]); 993 }); 994 } 995 })(polyline, polyline_events[ev]); 996 } 997 998 this.polylines.push(polyline); 999 1000 GMaps.fire('polyline_added', polyline, this); 1001 1002 return polyline; 1003}; 1004 1005GMaps.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 1018GMaps.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 1026GMaps.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 1053GMaps.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 1083GMaps.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 1126GMaps.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 1139GMaps.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 1147GMaps.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 1168GMaps.prototype.loadFromFusionTables = function(options) { 1169 var layer = this.getFromFusionTables(options); 1170 layer.setMap(this.map); 1171 1172 return layer; 1173}; 1174 1175GMaps.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 1198GMaps.prototype.loadFromKML = function(options) { 1199 var layer = this.getFromKML(options); 1200 layer.setMap(this.map); 1201 1202 return layer; 1203}; 1204 1205GMaps.prototype.addLayer = function(layerName, options) { 1206 //var default_layers = ['weather', 'clouds', 'traffic', 'transit', 'bicycling', 'panoramio', 'places']; 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 //click event 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 //search, nearbySearch, radarSearch callback, Both are the same 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 //textSearch callback 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 1288GMaps.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 1306var travelMode, unitSystem; 1307 1308GMaps.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 1370GMaps.prototype.removeRoutes = function() { 1371 this.routes = []; 1372}; 1373 1374GMaps.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 //location request 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 //path request 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 1417GMaps.prototype.cleanRoute = GMaps.prototype.removePolylines; 1418 1419GMaps.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 1452GMaps.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 //start callback 1463 if (e.length > 0 && options.start) { 1464 options.start(e[e.length - 1]); 1465 } 1466 1467 //step callback 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 //end callback 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 1497GMaps.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 //start callback 1509 if (e.length > 0 && options.start) { 1510 options.start(e[e.length - 1]); 1511 } 1512 1513 //step callback 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 //end callback 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 1567GMaps.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 1592GMaps.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 1611GMaps.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 1624GMaps.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 1637GMaps.prototype.checkGeofence = function(lat, lng, fence) { 1638 return fence.containsLatLng(new google.maps.LatLng(lat, lng)); 1639}; 1640 1641GMaps.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 1652GMaps.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 1684GMaps.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 /** Map options **/ 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 /** Markers **/ 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 // New marker without styles 1800 else { 1801 marker = parameters.pop() + encodeURI('|' + loc); 1802 parameters.push(marker); 1803 } 1804 } 1805 } 1806 1807 /** Map Styles **/ 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 /** Polylines **/ 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 /** Retina support **/ 1891 var dpi = window.devicePixelRatio || 1; 1892 parameters.push('scale=' + dpi); 1893 1894 parameters = parameters.join('&'); 1895 return static_root + parameters; 1896}; 1897 1898GMaps.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 1911GMaps.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 1924GMaps.prototype.removeOverlayMapType = function(overlayMapTypeIndex) { 1925 this.map.overlayMapTypes.removeAt(overlayMapTypeIndex); 1926}; 1927 1928GMaps.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 1934GMaps.prototype.setStyle = function(mapTypeId) { 1935 this.map.setMapTypeId(mapTypeId); 1936}; 1937 1938GMaps.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 1951GMaps.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 1983GMaps.prototype.on = function(event_name, handler) { 1984 return GMaps.on(event_name, this, handler); 1985}; 1986 1987GMaps.prototype.off = function(event_name) { 1988 GMaps.off(event_name, this); 1989}; 1990 1991GMaps.custom_events = ['marker_added', 'marker_removed', 'polyline_added', 'polyline_removed', 'polygon_added', 'polygon_removed', 'geolocated', 'geolocation_failed']; 1992 1993GMaps.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 2011GMaps.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 2021GMaps.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 2038GMaps.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 2065GMaps.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// Polygon containsLatLng 2083// https://github.com/tparkin/Google-Maps-Point-in-Polygon 2084// Poygon getBounds extension - google-maps-extensions 2085// http://code.google.com/p/google-maps-extensions/source/browse/google.maps.Polygon.getBounds.js 2086if (!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 2103if (!google.maps.Polygon.prototype.containsLatLng) { 2104 // Polygon containsLatLng - method to determine if a latLng is within a polygon 2105 google.maps.Polygon.prototype.containsLatLng = function(latLng) { 2106 // Exclude points outside of bounds as there is no way they are in the poly 2107 var bounds = this.getBounds(); 2108 2109 if (bounds !== null && !bounds.contains(latLng)) { 2110 return false; 2111 } 2112 2113 // Raycast point in polygon method 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 2140if (!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 2151google.maps.LatLngBounds.prototype.containsLatLng = function(latLng) { 2152 return this.contains(latLng); 2153}; 2154 2155google.maps.Marker.prototype.setFences = function(fences) { 2156 this.fences = fences; 2157}; 2158 2159google.maps.Marker.prototype.addFence = function(fence) { 2160 this.fences.push(fence); 2161};
2162 2163google.maps.Marker.prototype.getId = function() { 2164 return this['__gm_id']; 2165}; 2166 2167//========================== 2168// Array indexOf 2169// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf 2170if (!Array.prototype.indexOf) { 2171 Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) { 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) { // shortcut for verifying if it's NaN 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 2203return GMaps; 2204}));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.