| OLD | NEW |
| 1 <!-- Copyright (c) 2015 Google Inc. All rights reserved. --> | 1 <!-- Copyright (c) 2015 Google Inc. All rights reserved. --> |
| 2 | 2 |
| 3 <link rel="import" href="../polymer/polymer.html"> | 3 <link rel="import" href="../polymer/polymer.html"> |
| 4 <link rel="import" href="../google-apis/google-maps-api.html"> | 4 <link rel="import" href="../google-apis/google-maps-api.html"> |
| 5 <link rel="import" href="../iron-resizable-behavior/iron-resizable-behavior.html
"> | 5 <link rel="import" href="../iron-resizable-behavior/iron-resizable-behavior.html
"> |
| 6 <link rel="import" href="../iron-selector/iron-selector.html"> |
| 6 <link rel="import" href="google-map-marker.html"> | 7 <link rel="import" href="google-map-marker.html"> |
| 7 <!-- | 8 <!-- |
| 8 The `google-map` element renders a Google Map. | 9 The `google-map` element renders a Google Map. |
| 9 | 10 |
| 10 <b>Example</b>: | 11 <b>Example</b>: |
| 11 | 12 |
| 12 <style> | 13 <style> |
| 13 google-map { | 14 google-map { |
| 14 height: 600px; | 15 height: 600px; |
| 15 } | 16 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 31 var map = document.querySelector('google-map'); | 32 var map = document.querySelector('google-map'); |
| 32 map.latitude = 37.77493; | 33 map.latitude = 37.77493; |
| 33 map.longitude = -122.41942; | 34 map.longitude = -122.41942; |
| 34 map.addEventListener('google-map-ready', function(e) { | 35 map.addEventListener('google-map-ready', function(e) { |
| 35 alert('Map loaded!'); | 36 alert('Map loaded!'); |
| 36 }); | 37 }); |
| 37 </script> | 38 </script> |
| 38 | 39 |
| 39 <b>Example</b> - with Google directions, using data-binding inside another Polym
er element | 40 <b>Example</b> - with Google directions, using data-binding inside another Polym
er element |
| 40 | 41 |
| 41 <google-map map="{{map}}" libraries="places"></google-map> | 42 <google-map map="{{map}}"></google-map> |
| 42 <google-map-directions map="{{map}}" | 43 <google-map-directions map="{{map}}" |
| 43 start-address="San Francisco" end-address="Mountain View"> | 44 start-address="San Francisco" end-address="Mountain View"> |
| 44 </google-map-directions> | 45 </google-map-directions> |
| 45 | 46 |
| 46 @demo | 47 @demo |
| 47 --> | 48 --> |
| 48 | 49 |
| 49 <dom-module id="google-map"> | 50 <dom-module id="google-map"> |
| 50 | 51 |
| 51 <style> | 52 <style> |
| (...skipping 10 matching lines...) Expand all Loading... |
| 62 bottom: 0; | 63 bottom: 0; |
| 63 left: 0; | 64 left: 0; |
| 64 } | 65 } |
| 65 | 66 |
| 66 </style> | 67 </style> |
| 67 <template> | 68 <template> |
| 68 <google-maps-api id="api" | 69 <google-maps-api id="api" |
| 69 api-key="[[apiKey]]" | 70 api-key="[[apiKey]]" |
| 70 client-id="[[clientId]]" | 71 client-id="[[clientId]]" |
| 71 version="[[version]]" | 72 version="[[version]]" |
| 72 libraries="[[libraries]]" | |
| 73 signed-in="[[signedIn]]" | 73 signed-in="[[signedIn]]" |
| 74 language="[[language]]" | 74 language="[[language]]" |
| 75 on-api-load="_mapApiLoaded"></google-maps-api> | 75 on-api-load="_mapApiLoaded"></google-maps-api> |
| 76 | 76 |
| 77 <div id="map"></div> | 77 <div id="map"></div> |
| 78 | 78 |
| 79 <content id="markers" select="google-map-marker"></content> | 79 <iron-selector id="selector" multi="[[!singleInfoWindow]]" selected-attribut
e="open" activate-event="google-map-marker-open" on-google-map-marker-close="_de
selectMarker"> |
| 80 | 80 <content id="markers" select="google-map-marker"></content> |
| 81 </iron-selector> |
| 82 <content id="objects" select="*"></content> |
| 81 </template> | 83 </template> |
| 82 </dom-module> | 84 </dom-module> |
| 83 | 85 |
| 84 <script> | 86 <script> |
| 85 | 87 |
| 86 Polymer({ | 88 Polymer({ |
| 87 | 89 |
| 88 is: 'google-map', | 90 is: 'google-map', |
| 89 | 91 |
| 90 | 92 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 /** | 165 /** |
| 164 * A Maps API object. | 166 * A Maps API object. |
| 165 */ | 167 */ |
| 166 map: { | 168 map: { |
| 167 type: Object, | 169 type: Object, |
| 168 notify: true, | 170 notify: true, |
| 169 value: null | 171 value: null |
| 170 }, | 172 }, |
| 171 | 173 |
| 172 /** | 174 /** |
| 173 * A comma separated list (e.g. "places,geometry") of libraries to load | |
| 174 * with this map. Defaults to "". For more information see | |
| 175 * https://developers.google.com/maps/documentation/javascript/libraries. | |
| 176 */ | |
| 177 libraries: { | |
| 178 type: String, | |
| 179 value: '' | |
| 180 }, | |
| 181 | |
| 182 /** | |
| 183 * A longitude to center the map on. | 175 * A longitude to center the map on. |
| 184 */ | 176 */ |
| 185 longitude: { | 177 longitude: { |
| 186 type: Number, | 178 type: Number, |
| 187 value: -122.41942, | 179 value: -122.41942, |
| 188 notify: true, | 180 notify: true, |
| 189 reflectToAttribute: true | 181 reflectToAttribute: true |
| 190 }, | 182 }, |
| 191 | 183 |
| 192 /** | 184 /** |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 344 value: function() { return {}; } | 336 value: function() { return {}; } |
| 345 }, | 337 }, |
| 346 | 338 |
| 347 /** | 339 /** |
| 348 * The markers on the map. | 340 * The markers on the map. |
| 349 */ | 341 */ |
| 350 markers: { | 342 markers: { |
| 351 type: Array, | 343 type: Array, |
| 352 value: function() { return []; }, | 344 value: function() { return []; }, |
| 353 readOnly: true | 345 readOnly: true |
| 346 }, |
| 347 |
| 348 /** |
| 349 * The non-marker objects on the map. |
| 350 */ |
| 351 objects: { |
| 352 type: Array, |
| 353 value: function() { return []; }, |
| 354 readOnly: true |
| 355 }, |
| 356 |
| 357 /** |
| 358 * If set, all other info windows on markers are closed when opening a new
one. |
| 359 */ |
| 360 singleInfoWindow: { |
| 361 type: Boolean, |
| 362 value: false |
| 354 } | 363 } |
| 355 | |
| 356 }, | 364 }, |
| 357 | 365 |
| 358 behaviors: [ | 366 behaviors: [ |
| 359 Polymer.IronResizableBehavior | 367 Polymer.IronResizableBehavior |
| 360 ], | 368 ], |
| 361 | 369 |
| 362 listeners: { | 370 listeners: { |
| 363 'iron-resize': 'resize' | 371 'iron-resize': 'resize' |
| 364 }, | 372 }, |
| 365 | 373 |
| 366 observers: [ | 374 observers: [ |
| 367 '_debounceUpdateCenter(latitude, longitude)' | 375 '_debounceUpdateCenter(latitude, longitude)' |
| 368 ], | 376 ], |
| 369 | 377 |
| 370 attached: function() { | 378 attached: function() { |
| 371 this._initGMap(); | 379 this._initGMap(); |
| 372 }, | 380 }, |
| 373 | 381 |
| 374 detached: function() { | 382 detached: function() { |
| 375 if (this._mutationObserver) { | 383 if (this._mutationObserver) { |
| 376 this._mutationObserver.disconnect(); | 384 this._mutationObserver.disconnect(); |
| 377 this._mutationObserver = null; | 385 this._mutationObserver = null; |
| 378 } | 386 } |
| 387 if (this._objectsMutationObserver) { |
| 388 this._objectsMutationObserver.disconnect(); |
| 389 this._objectsMutationObserver = null; |
| 390 } |
| 379 }, | 391 }, |
| 380 | 392 |
| 381 _initGMap: function() { | 393 _initGMap: function() { |
| 382 if (this.map) { | 394 if (this.map) { |
| 383 return; // already initialized | 395 return; // already initialized |
| 384 } | 396 } |
| 385 if (this.$.api.libraryLoaded !== true) { | 397 if (this.$.api.libraryLoaded !== true) { |
| 386 return; // api not loaded | 398 return; // api not loaded |
| 387 } | 399 } |
| 388 if (!this.isAttached) { | 400 if (!this.isAttached) { |
| 389 return; // not attached | 401 return; // not attached |
| 390 } | 402 } |
| 391 | 403 |
| 392 this.map = new google.maps.Map(this.$.map, this._getMapOptions()); | 404 this.map = new google.maps.Map(this.$.map, this._getMapOptions()); |
| 393 this._listeners = {}; | 405 this._listeners = {}; |
| 394 this._updateCenter(); | 406 this._updateCenter(); |
| 395 this._loadKml(); | 407 this._loadKml(); |
| 396 this._updateMarkers(); | 408 this._updateMarkers(); |
| 409 this._updateObjects(); |
| 397 this._addMapListeners(); | 410 this._addMapListeners(); |
| 398 this.fire('google-map-ready'); | 411 this.fire('google-map-ready'); |
| 399 }, | 412 }, |
| 400 | 413 |
| 401 _mapApiLoaded: function() { | 414 _mapApiLoaded: function() { |
| 402 this._initGMap(); | 415 this._initGMap(); |
| 403 }, | 416 }, |
| 404 | 417 |
| 405 _getMapOptions: function() { | 418 _getMapOptions: function() { |
| 406 var mapOptions = { | 419 var mapOptions = { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 419 // We use getAttribute here because the default value of this.draggable =
false even when not set. | 432 // We use getAttribute here because the default value of this.draggable =
false even when not set. |
| 420 if (this.getAttribute('draggable') != null) { | 433 if (this.getAttribute('draggable') != null) { |
| 421 mapOptions.draggable = this.draggable | 434 mapOptions.draggable = this.draggable |
| 422 } | 435 } |
| 423 for (var p in this.additionalMapOptions) | 436 for (var p in this.additionalMapOptions) |
| 424 mapOptions[p] = this.additionalMapOptions[p]; | 437 mapOptions[p] = this.additionalMapOptions[p]; |
| 425 | 438 |
| 426 return mapOptions; | 439 return mapOptions; |
| 427 }, | 440 }, |
| 428 | 441 |
| 429 // watch for future updates | 442 _attachChildrenToMap: function(children) { |
| 443 if (this.map) { |
| 444 for (var i = 0, child; child = children[i]; ++i) { |
| 445 child.map = this.map; |
| 446 } |
| 447 } |
| 448 }, |
| 449 |
| 450 // watch for future updates to marker objects |
| 430 _observeMarkers: function() { | 451 _observeMarkers: function() { |
| 431 // Watch for future updates. | 452 // Watch for future updates. |
| 432 if (this._mutationObserver) { | 453 if (this._mutationObserver) { |
| 433 return; | 454 return; |
| 434 } | 455 } |
| 435 this._mutationObserver = new MutationObserver( this._updateMarkers.bind(th
is)); | 456 this._mutationObserver = new MutationObserver(this._updateMarkers.bind(thi
s)); |
| 436 this._mutationObserver.observe(this, { | 457 this._mutationObserver.observe(this.$.selector, { |
| 437 childList: true | 458 childList: true |
| 438 }); | 459 }); |
| 439 }, | 460 }, |
| 440 | 461 |
| 441 _updateMarkers: function() { | 462 _updateMarkers: function() { |
| 442 var newMarkers = Array.prototype.slice.call( | 463 var newMarkers = Array.prototype.slice.call( |
| 443 Polymer.dom(this.$.markers).getDistributedNodes()); | 464 Polymer.dom(this.$.markers).getDistributedNodes()); |
| 444 | 465 |
| 445 // do not recompute if markers have not been added or removed | 466 // do not recompute if markers have not been added or removed |
| 446 if (newMarkers.length === this.markers.length) { | 467 if (newMarkers.length === this.markers.length) { |
| 447 var added = newMarkers.filter(function(m) { | 468 var added = newMarkers.filter(function(m) { |
| 448 return this.markers && this.markers.indexOf(m) === -1; | 469 return this.markers && this.markers.indexOf(m) === -1; |
| 449 }.bind(this)); | 470 }.bind(this)); |
| 450 if (added.length === 0) { | 471 if (added.length === 0) { |
| 451 // set up observer first time around | 472 // set up observer first time around |
| 452 if (!this._mutationObserver) { | 473 if (!this._mutationObserver) { |
| 453 this._observeMarkers(); | 474 this._observeMarkers(); |
| 454 } | 475 } |
| 455 return; | 476 return; |
| 456 } | 477 } |
| 457 } | 478 } |
| 458 | 479 |
| 459 this._observeMarkers(); | 480 this._observeMarkers(); |
| 460 | 481 |
| 461 this.markers = this._setMarkers(newMarkers); | 482 this.markers = this._setMarkers(newMarkers); |
| 462 | 483 |
| 463 // Set the map on each marker and zoom viewport to ensure they're in view. | 484 // Set the map on each marker and zoom viewport to ensure they're in view. |
| 464 if (this.markers.length && this.map) { | 485 this._attachChildrenToMap(this.markers); |
| 465 for (var i = 0, m; m = this.markers[i]; ++i) { | |
| 466 m.map = this.map; | |
| 467 } | |
| 468 } | |
| 469 if (this.fitToMarkers) { | 486 if (this.fitToMarkers) { |
| 470 this._fitToMarkersChanged(); | 487 this._fitToMarkersChanged(); |
| 471 } | 488 } |
| 472 }, | 489 }, |
| 473 | 490 |
| 491 // watch for future updates to non-marker objects |
| 492 _observeObjects: function() { |
| 493 if (this._objectsMutationObserver) { |
| 494 return; |
| 495 } |
| 496 this._objectsMutationObserver = new MutationObserver(this._updateObjects.b
ind(this)); |
| 497 this._objectsMutationObserver.observe(this, { |
| 498 childList: true |
| 499 }); |
| 500 }, |
| 501 |
| 502 _updateObjects: function() { |
| 503 var newObjects = Array.prototype.slice.call( |
| 504 Polymer.dom(this.$.objects).getDistributedNodes()); |
| 505 |
| 506 // Do not recompute if objects have not been added or removed. |
| 507 if (newObjects.length === this.objects.length) { |
| 508 var added = newObjects.filter(function(o) { |
| 509 return this.objects.indexOf(o) === -1; |
| 510 }.bind(this)); |
| 511 if (added.length === 0) { |
| 512 // Set up observer first time around. |
| 513 this._observeObjects(); |
| 514 return; |
| 515 } |
| 516 } |
| 517 |
| 518 this._observeObjects(); |
| 519 this._setObjects(newObjects); |
| 520 this._attachChildrenToMap(this.objects); |
| 521 }, |
| 522 |
| 474 /** | 523 /** |
| 475 * Clears all markers from the map. | 524 * Clears all markers from the map. |
| 476 * | 525 * |
| 477 * @method clear | 526 * @method clear |
| 478 */ | 527 */ |
| 479 clear: function() { | 528 clear: function() { |
| 480 for (var i = 0, m; m = this.markers[i]; ++i) { | 529 for (var i = 0, m; m = this.markers[i]; ++i) { |
| 481 m.marker.setMap(null); | 530 m.marker.setMap(null); |
| 482 } | 531 } |
| 483 }, | 532 }, |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 640 switch (attrName) { | 689 switch (attrName) { |
| 641 case 'draggable': | 690 case 'draggable': |
| 642 this.map.setOptions({draggable: this.draggable}); | 691 this.map.setOptions({draggable: this.draggable}); |
| 643 break; | 692 break; |
| 644 } | 693 } |
| 645 }, | 694 }, |
| 646 | 695 |
| 647 _fitToMarkersChanged: function() { | 696 _fitToMarkersChanged: function() { |
| 648 // TODO(ericbidelman): respect user's zoom level. | 697 // TODO(ericbidelman): respect user's zoom level. |
| 649 | 698 |
| 650 if (this.map && this.fitToMarkers) { | 699 if (this.map && this.fitToMarkers && this.markers.length > 0) { |
| 651 var latLngBounds = new google.maps.LatLngBounds(); | 700 var latLngBounds = new google.maps.LatLngBounds(); |
| 652 for (var i = 0, m; m = this.markers[i]; ++i) { | 701 for (var i = 0, m; m = this.markers[i]; ++i) { |
| 653 latLngBounds.extend( | 702 latLngBounds.extend( |
| 654 new google.maps.LatLng(m.latitude, m.longitude)); | 703 new google.maps.LatLng(m.latitude, m.longitude)); |
| 655 } | 704 } |
| 656 | 705 |
| 657 // For one marker, don't alter zoom, just center it. | 706 // For one marker, don't alter zoom, just center it. |
| 658 if (this.markers.length > 1) { | 707 if (this.markers.length > 1) { |
| 659 this.map.fitBounds(latLngBounds); | 708 this.map.fitBounds(latLngBounds); |
| 660 } | 709 } |
| 661 | 710 |
| 662 this.map.setCenter(latLngBounds.getCenter()); | 711 this.map.setCenter(latLngBounds.getCenter()); |
| 663 } | 712 } |
| 664 }, | 713 }, |
| 665 | 714 |
| 666 _addMapListeners: function() { | 715 _addMapListeners: function() { |
| 667 google.maps.event.addListener(this.map, 'center_changed', function() { | 716 google.maps.event.addListener(this.map, 'center_changed', function() { |
| 668 var center = this.map.getCenter(); | 717 var center = this.map.getCenter(); |
| 669 this.latitude = center.lat(); | 718 this.latitude = center.lat(); |
| 670 this.longitude = center.lng(); | 719 this.longitude = center.lng(); |
| 671 }.bind(this)); | 720 }.bind(this)); |
| 672 | 721 |
| 673 google.maps.event.addListener(this.map, 'zoom_changed', function() { | 722 google.maps.event.addListener(this.map, 'zoom_changed', function() { |
| 674 this.zoom = this.map.getZoom(); | 723 this.zoom = this.map.getZoom(); |
| 675 }.bind(this)); | 724 }.bind(this)); |
| 676 | 725 |
| 677 google.maps.event.addListener(this.map, 'maptypeid_changed', function() { | 726 google.maps.event.addListener(this.map, 'maptypeid_changed', function() { |
| 678 this.mapType = this.map.getMapTypeId(); | 727 this.mapType = this.map.getMapTypeId(); |
| 679 }.bind(this)); | 728 }.bind(this)); |
| 680 | 729 |
| 681 this._clickEventsChanged(); | 730 this._clickEventsChanged(); |
| 682 this._dragEventsChanged(); | 731 this._dragEventsChanged(); |
| 683 this._mouseEventsChanged(); | 732 this._mouseEventsChanged(); |
| 684 }, | 733 }, |
| 685 | 734 |
| 686 _clearListener: function(name) { | 735 _clearListener: function(name) { |
| 687 if (this._listeners[name]) { | 736 if (this._listeners[name]) { |
| 688 google.maps.event.removeListener(this._listeners[name]); | 737 google.maps.event.removeListener(this._listeners[name]); |
| 689 this._listeners[name] = null; | 738 this._listeners[name] = null; |
| 690 } | 739 } |
| 691 }, | 740 }, |
| 692 | 741 |
| 693 _forwardEvent: function(name) { | 742 _forwardEvent: function(name) { |
| 694 this._listeners[name] = google.maps.event.addListener(this.map, name, func
tion(event) { | 743 this._listeners[name] = google.maps.event.addListener(this.map, name, func
tion(event) { |
| 695 this.fire('google-map-' + name, event); | 744 this.fire('google-map-' + name, event); |
| 696 }.bind(this)); | 745 }.bind(this)); |
| 697 } | 746 }, |
| 747 |
| 748 _deselectMarker: function(e, detail) { |
| 749 // If singleInfoWindow is set, update iron-selector's selected attribute to
be null. |
| 750 // Else remove the marker from iron-selector's selected array. |
| 751 var markerIndex = this.$.selector.indexOf(e.target); |
| 752 |
| 753 if (this.singleInfoWindow) { |
| 754 this.$.selector.selected = null; |
| 755 } else if (this.$.selector.selectedValues) { |
| 756 this.$.selector.selectedValues = this.$.selector.selectedValues.filter(fun
ction(i) {return i !== markerIndex}); |
| 757 } |
| 758 } |
| 698 | 759 |
| 699 }); | 760 }); |
| 700 | 761 |
| 701 </script> | 762 </script> |
| OLD | NEW |