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