AngularJS - загрузить асинхронный скрипт карты Google в директиву для нескольких карт
В настоящее время я пытаюсь загрузить несколько карт Google на одной странице. Я не хочу включать скрипт API Google Map в код HTML, так как я не хочу, чтобы скрипт загружался, если карты не находятся на текущей странице. Я хочу, чтобы мои карты вызывались внутри одной директивы, которая также будет выполнять ленивую загрузку скрипта API карт Google.
Поэтому я искал вокруг инашел решение что я немного подправил, но моя проблема в том, что он будет загружать только одну карту, но не другие.
Мой HTML выглядит так:
<div id="mapParis" class="google-map" lat="48.833" long="2.333"></div>
<div id="mapWashington" class="google-map" lat="38.917" long="-77.000"></div>
<div id="mapTokyo" class="google-map" lat="35.667" long="139.750"></div>
И директива:
// Google Map
app.directive('googleMap', ['$window', '$q', function( $window, $q ) {
function loadScript() {
console.log('loadScript');
// use global document since Angular's $document is weak
var s = document.createElement('script');
s.src = '//maps.googleapis.com/maps/api/js?sensor=false&language=en&callback=initMap';
document.body.appendChild(s);
}
// Lazy loading of the script
function lazyLoadApi(key) {
console.log('lazyLoadApi');
var deferred = $q.defer();
$window.initMap = function () {
deferred.resolve();
};
if ( $window.attachEvent ) {
$window.attachEvent('onload', loadScript);
} else {
$window.addEventListener('load', loadScript, false);
}
return deferred.promise;
}
return {
restrict: 'C', // restrict by class name
scope: {
mapId: '@id', // map ID
lat: '@', // latitude
long: '@' // longitude
},
link: function($scope, elem, attrs) {
// Check if latitude and longitude are specified
if ( angular.isDefined($scope.lat) && angular.isDefined($scope.long) ) {
console.log('-----');
// Initialize the map
$scope.initialize = function() {
console.log($scope.mapId);
$scope.location = new google.maps.LatLng($scope.lat, $scope.long);
$scope.mapOptions = {
zoom: 6,
center: $scope.location
};
$scope.map = new google.maps.Map(document.getElementById($scope.mapId), $scope.mapOptions);
new google.maps.Marker({
position: $scope.location,
map: $scope.map,
});
}
// Check if google map API is ready to run
if ( $window.google && $window.google.maps ) {
console.log('gmaps already loaded');
// Google map already loaded
$scope.initialize();
} else {
lazyLoadApi().then(function () {
// Promised resolved
console.log('promise resolved');
if ( $window.google && $window.google.maps ) {
// Google map loaded
console.log('gmaps loaded');
$scope.initialize();
} else {
// Google map NOT loaded
console.log('gmaps not loaded');
}
}, function () {
// Promise rejected
console.log('promise rejected');
});
}
}
}
};
Вот jsFiddle с 3 картами, вы увидите, что загружена только последняя:
http://jsfiddle.net/5Pk8f/1/
Я предполагаю, что я делаю что-то не так с моим объемом или тем, как выполняется обещание, но пока у меня совсем нет идей ...
Спасибо! (и извините за мойне так хорошо английский)
Обновление (после ответа)В качестве обновления, вот полное решение, которое я придумал:
http://plnkr.co/edit/1NpquJ?p=preview (@maurycy plunker)
// Lazy loading of Google Map API
app.service('loadGoogleMapAPI', ['$window', '$q',
function ( $window, $q ) {
var deferred = $q.defer();
// Load Google map API script
function loadScript() {
// Use global document since Angular's $document is weak
var script = document.createElement('script');
script.src = '//maps.googleapis.com/maps/api/js?sensor=false&language=en&callback=initMap';
document.body.appendChild(script);
}
// Script loaded callback, send resolve
$window.initMap = function () {
deferred.resolve();
}
loadScript();
return deferred.promise;
}]);
Директива Google Map// Google Map
app.directive('googleMap', ['$rootScope', 'loadGoogleMapAPI',
function( $rootScope, loadGoogleMapAPI ) {
return {
restrict: 'C', // restrict by class name
scope: {
mapId: '@id', // map ID
lat: '@', // latitude
long: '@' // longitude
},
link: function( $scope, elem, attrs ) {
// Check if latitude and longitude are specified
if ( angular.isDefined($scope.lat) && angular.isDefined($scope.long) ) {
// Initialize the map
$scope.initialize = function() {
$scope.location = new google.maps.LatLng($scope.lat, $scope.long);
$scope.mapOptions = {
zoom: 12,
center: $scope.location
};
$scope.map = new google.maps.Map(document.getElementById($scope.mapId), $scope.mapOptions);
new google.maps.Marker({
position: $scope.location,
map: $scope.map,
});
}
// Loads google map script
loadGoogleMapAPI.then(function () {
// Promised resolved
$scope.initialize();
}, function () {
// Promise rejected
});
}
}
};
}]);
Пример использования HTML<div id="mapParis" class="google-map" lat="48.833" long="2.333"></div>
<div id="mapWashington" class="google-map" lat="38.917" long="-77.000"></div>
<div id="mapTokyo" class="google-map" lat="35.667" long="139.750"></div>
Еще раз спасибо Мориси