Google Maps Angular Js - angularjs

I'm working on a page which has a map containing many markers and a list on the side of the marker titles. This example helped me get started. http://jsfiddle.net/svigna/pc7Uu/
I have images and descriptions relative to each marker location that I would like to display in the side list only when the associated marker is clicked.
Any ideas in how I could go about implementing this logic? Thanks.
Here is my HTML
<div ng-app="mapsApp" ng-controller="MapCtrl">
<div id="map"></div>
<div id="class" ng-repeat="marker in markers | orderBy : 'title'">
{{marker.title}}
<img ng-src="{{marker.image}}" alt="\{\{album.album\}\} Cover Image" width="300px;" height="300px;">
</div>
</div>
Here is my angular
//Angular App Module and Controller
angular.module('mapsApp', [])
.controller('MapCtrl', function ($scope) {
var mapOptions = {
zoom: 9,
center: new google.maps.LatLng(10.51, 7.432),
mapTypeId: google.maps.MapTypeId.ROADMAP,
scrollwheel: false
}
$scope.map = new google.maps.Map(document.getElementById('map'), mapOptions);
$scope.markers = [];
var infoWindow = new google.maps.InfoWindow({
maxWidth: 200
});
var createMarker = function (info){
var marker = new google.maps.Marker({
map: $scope.map,
position: new google.maps.LatLng(info.lat, info.long),
title: info.location,
image: info.img
});
marker.content = '<div class="infoWindowContent">' + info.desc + '</div>';
google.maps.event.addListener(marker, 'click', function(){
infoWindow.setContent('<h2>' + marker.title + '</h2>' + marker.content);
infoWindow.open($scope.map, marker);
});
$scope.markers.push(marker);
}
for (i = 0; i < cities.length; i++){
createMarker(cities[i]);
}
$scope.openInfoWindow = function(e, selectedMarker){
e.preventDefault();
google.maps.event.trigger(selectedMarker, 'click');
}
});
Here is my JSON
var cities = [
{
location : 'Unguwar Rimi',
desc : "<div id='hook' class='image'><img src=\"images/wells/KA KAF 001 Unguwar Rimi/IMG_4569.JPG\"><br><strong>Kaduna, Nigeria</strong><br>Village: Unguwar Rimi<br>Completed: 2011<br><p>'This borehole is a good blessing, our labor and stress is reduced.'</p></div>",
img: "images/wells/KA KAF 001 Unguwar Rimi/IMG_4569.JPG",
lat : 10.52,
long : 7.43
},
{
location : 'Gidan Bege Kadarko Kagoro',
desc : "<div id='hook' class='image'><img src=\"images/wells/KA KAU 001 Gidon Bege Kadarko Kagoro/IMG_4556.JPG\"><br><strong>Kaduna, Nigeria</strong><br>Village: Unguwar Rimi<br>Completed: 2008<br><p>'God is great, the village no longer has a water problem and we never run short of water.'</p></div>",
img: "images/wells/KA KAU 001 Gidon Bege Kadarko Kagoro/IMG_4556.JPG",
lat : 10.53,
long : 7.27
},
{
location : 'ECWA Seminary Kagoro',
desc : "<div id='hook' class='image'><img src=\"images/wells/KA KAU 002 ECWA Seminary Kagoro/IMG_8123.JPG\"><br><strong>Kaduna, Nigeria</strong><br>Village: ECWA Seminary Kagoro<br>Completed: 2008<br><p>'God is our Savior. He blessed us with this borehole which provides water to our staff and students'</p></div>",
img: "images/wells/KA KAU 002 ECWA Seminary Kagoro/IMG_8123.JPG",
lat : 9.69,
long : 8.39
}
];

You need to set a scope variable to something in the click event.
In your controller:
$scope.selectedMarker = {};
// etc
google.maps.event.addListener(marker, 'click', function(){
infoWindow.setContent('<h2>' + marker.title + '</h2>' + marker.content);
$scope.selectedMarker = marker;
$scope.$apply();
infoWindow.open($scope.map, marker);
});
On your view you can:
<h1>{{selectedMarker.title}}</h1>
Here is a full demo: http://jsfiddle.net/pc7Uu/194/
Also if you want to display HTML (marker's content) on the version of angular you've included (1.1.1) you will need to include ngSanitize.
http://jsfiddle.net/xVGP5/1/

Related

Writing unit tests with Jasmine for AngularJS controller with Google maps, modals

I have been coding for so many years, but for for the first time I'm about to write test cases for an angularJS app with Jasmine... I went through many Jasmine tutorials, but most of them include simple apps like calculators or doing similar calculations. I did try it with a few tweaks and it worked fine.
But im finding it hard to implement it in some complex cases like the ones below.
for an example. Below angular code generates a map with markers on it
//Data
var cities = [
{
city : 'Toronto',
desc : 'This is the best city in the world!',
lat : 43.7000,
long : -79.4000
},
{
city : 'New York',
desc : 'This city is aiiiiite!',
lat : 40.6700,
long : -73.9400
},
{
city : 'Chicago',
desc : 'This is the second best city in the world!',
lat : 41.8819,
long : -87.6278
},
{
city : 'Los Angeles',
desc : 'This city is live!',
lat : 34.0500,
long : -118.2500
},
{
city : 'Las Vegas',
desc : 'Sin City...\'nuff said!',
lat : 36.0800,
long : -115.1522
}
];
//Angular App Module and Controller
angular.module('mapsApp', [])
.controller('MapCtrl', function ($scope) {
var mapOptions = {
zoom: 4,
center: new google.maps.LatLng(40.0000, -98.0000),
mapTypeId: google.maps.MapTypeId.TERRAIN
}
$scope.map = new google.maps.Map(document.getElementById('map'), mapOptions);
$scope.markers = [];
var infoWindow = new google.maps.InfoWindow();
var createMarker = function (info){
var marker = new google.maps.Marker({
map: $scope.map,
position: new google.maps.LatLng(info.lat, info.long),
title: info.city
});
marker.content = '<div class="infoWindowContent">' + info.desc + '</div>';
google.maps.event.addListener(marker, 'click', function(){
infoWindow.setContent('<h2>' + marker.title + '</h2>' + marker.content);
infoWindow.open($scope.map, marker);
});
$scope.markers.push(marker);
}
for (i = 0; i < cities.length; i++){
createMarker(cities[i]);
}
$scope.openInfoWindow = function(e, selectedMarker){
e.preventDefault();
google.maps.event.trigger(selectedMarker, 'click');
}
});
so when i comes to writing the test case, but it has no user inputs
describe('generate the map', function() {
it('generate the map with the markers', function() {
// how does test start?
});
});
the second controller is where data is where i get values from a php file and open a modal when the user clicks.
angular.module('mapsApp', [])
.controller('userInputs', function ($scope,$modal,$location,$http) {
$scope.fblock= [];
$http.get('grab_from_1.php').success(function(a){
$scope.fblock= a;
}).error(function(data){
$scope.fblock= a;
});
$scope.fblock2= [];
$http.get('grab_from_2.php').success(function(b){
$scope.fblock2= b;
}).error(function(b){
$scope.fblock2 = b;
});
$scope.open = function (_vals) {
var modalInstance = $modal.open({
controller: "popin",
templateUrl: 'get_template.php',
resolve: {
values: function()
{
return _vals;
},
dates: function()
{
return $scope.fblock2.filter(function (vals2) {
return vals2.id == _vals.id;
})
}
}
});
};
}]);
angular.module('mapsApp', []).controller('popin', function ($scope,modalInstance,$location,$http,vals1,vals2) {
$scope.onclicking = function (cid) {
$modalInstance.dismiss('cancel');
$location.path('/information/'+cid);
};
$scope.vals1= vals1;
$scope.vals2= vals2;
});
so the unit testing will be something like
describe('grab users from fblock 1nd fblock 2 and show a popup', function() {
it('grab users from fblock 1', function() {
});
it('grab users from fblock 2', function() {
});
it('open the popup modal', function() {
});
});
Its not that i have not tried, im finding it a bit hard to apply the basics which i know to a bit complex scenario for the test controllers i have written above.
I would really appreciate if some one can help or guide me to write proper test cases using Jasmine

open a info window with event click on google maps with angular

I have an app that I need that open an infowindow on a google map, to just show it for 1 second when I do click on the panel in the side bar. After this, it need not work anymore.
I have a list of the markers and information in the sidebar, when the user make a click in a some of these markers I need that the infowindow to be open.
(function(){
angular.module('mapCtrl', ['presentacionService'])
.controller('MapController', function($scope, Presentacion) {
var self = this;
function initialize() {
var options = {
googleApiKey: '',
locationColumn: 'geometry',
map_center: [-16.494898, -68.133553],
locationScope: 'La Paz'
};
options = options || {};
self.googleApiKey = options.googleApiKey || "";
self.locationColumn = options.locationColumn || "geometry";
self.locationScope = options.locationScope || "";
self.defaultZoom = options.defaultZoom || 10;
self.map_centroid = new google.maps.LatLng(options.map_center[0], options.map_center[1]);
self.myOptions = {
zoom: self.defaultZoom,
center: self.map_centroid,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
self.map = new google.maps.Map($("#map")[0], self.myOptions);
var infoWindow = new google.maps.InfoWindow();
google.maps.event.addListener(map, 'click', function() {
infowindow.close();
});
$scope.markers = [];
var createMarker = function (info){
var marker = new google.maps.Marker({
map: self.map,
position: new google.maps.LatLng(info.latitud, info.long),
title: info.nombre,
date: info.date,
imagen: info.imagen,
nombre_categoria: info.nombre_categoria
});
marker.content = '<div class="infoWindowContent">' + info.descripcion + '</div>';
google.maps.event.addListener(marker, 'click', function(){
infoWindow.setContent('<h2>' + marker.title + '</h2>' + marker.content);
infoWindow.open(self.map, marker);
});
$scope.markers.push(marker);
};
Presentacion.getAll().success(function (datos) {
for (var i = 0; i < datos.length; i++){
createMarker(datos[i]);
}
});
$scope.openInfoWindow = function(e, selectedMarker){
console.log('show something');
e.preventDefault();
new google.maps.event.trigger(selectedMarker, 'click' );
};
}
google.maps.event.addDomListener(window, 'load', initialize);
});
})();
an in the view:
<div class="row list_special" ng-repeat="marker in markers | orderBy : 'date'">
<div class="panel-google-plus" ng-click="openInfoWindow($event, marker)">
</div>
</div>
I prepared a Plunker to simulate functionalities desired for your project.
Here is the url: http://plnkr.co/edit/gIhNLQgfiiD4QfuQQOi4?p=preview
I have substituted your service Presentacion with a simple array places initialized in the MainCtrl (and also the markers is a property of MainCtrl scope but inherited by MapController):
$scope.markers = [];
$scope.places = [];
$scope.places.push({lat: 44.99758207, lng: 7.140598296999997, ...);
No other editing in your code and it is working as required: you can click on an item and it will open infowindow all the times you want.

Showing google map pinpoints dynamically using angularjs

I am trying to show pin points on google map by matching the location and retreiving list of longitude, latitude saved in the database when user enters location using AngularJS, HTML and Java. Following is my controller code. Please help me achieve my target
app.controller('mapCtrl', function ( $scope, $http) {
var mapOptions = {
zoom: 4,
center: new google.maps.LatLng(25,80),
mapTypeId: google.maps.MapTypeId.ROADMAP
}
$scope.map = new google.maps.Map(document.getElementById('map'), mapOptions);
$scope.markers = [];
$scope.cities = [];
$scope.lati = [];
$scope.longi = [];
$scope.desc = [];
var infoWindow = new google.maps.InfoWindow();
$http.get('http://localhost:8080/acudraStore/getCity').
success(function( data){
for(i = 0;i <=3;i++){
$scope.cities.push(data.countryList[i].city);
$scope.lati.push(data.countryList[i].latitude);
$scope.longi.push(data.countryList[i].longitude);
$scope.desc.push(data.countryList[i].desc);
}
var createMarker = function (){
console.log($scope.cities[0]);
var marker = new google.maps.Marker({
map: $scope.map,
position: new google.maps.LatLng($scope.lati[0], $scope.longi[0]),
title: $scope.cities[0]
});
marker.content = '<div class="infoWindowContent">' + $scope.desc[0] + '</div>';
google.maps.event.addListener(marker, 'click', function(){
infoWindow.setContent('<h2>' + marker.title + '</h2>' + marker.content);
infoWindow.open($scope.map, marker);
});
$scope.markers = [];
$scope.markers.push(marker);
$scope.markers = [];
for (i = 0; i < markers.length; i++){
createMarker(markers[i]);
}}
});
$scope.openInfoWindow = function(e, selectedMarker){
e.preventDefault();
google.maps.event.trigger(selectedMarker, 'click');
}
});
The example (similar to the provide in question) demonstrates how to load locations from external resource and display markers with info window:
var app = angular.module('mapApp', []);
app.controller('mapCtrl', function ($scope, $http) {
var mapOptions = {
zoom: 4,
center: new google.maps.LatLng(-25.5349952, 125.8554386),
mapTypeId: google.maps.MapTypeId.ROADMAP
}
$scope.map = new google.maps.Map(document.getElementById('map'), mapOptions);
$scope.markers = [];
$scope.cities = [];
var infoWindow = new google.maps.InfoWindow();
$http.get('https://gist.githubusercontent.com/vgrem/dd818d266445f1a653c1/raw/e768daf280bab0791c2c27ae0f3d5952490bc2a5/cities.json').
success(function (data) {
$scope.cities = data.countryList;
$scope.cities.forEach(function(city) {
createMarker(city);
});
});
var createMarker = function(city) {
var marker = new google.maps.Marker({
map: $scope.map,
position: new google.maps.LatLng(city.latitude, city.longitude),
title: city.city
});
marker.content = '<div class="infoWindowContent">' + city.desc + '</div>';
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent('<h2>' + marker.title + '</h2>' + marker.content);
infoWindow.open($scope.map, marker);
});
$scope.markers.push(marker);
};
//$scope.openInfoWindow = function (e, selectedMarker) {
// e.preventDefault();
// google.maps.event.trigger(selectedMarker, 'click');
//}
});
#map {
width: 800px;
height: 600px;
}
<script src="https://code.angularjs.org/1.3.14/angular.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=&v=3.0&sensor=true"></script>
<div ng-app="mapApp" ng-controller="mapCtrl">
<div id="map"></div>
</div>
Plunker

Highlight ng-repeat element when Google Maps marker is clicked

Please have a look at this demo
I am trying to figure out how to highlight ng-repeat element when corresponding google map marker on the map is clicked. As you can see, it works when you click the ng-repeat element but not when you click the marker.
HTML structure:
<div ng-app="mapsApp" ng-controller="MapCtrl">
<div id="map"></div>
<div ng-repeat="marker in markers"
ng-class="{active: $index == markerId}" >
{{marker.title}}
</div>
Angular code:
angular.module('mapsApp', []).controller('MapCtrl', function ($scope) {
var mapOptions = {
zoom: 4,
center: new google.maps.LatLng(40.0000, -98.0000),
mapTypeId: google.maps.MapTypeId.TERRAIN
}
$scope.map = new google.maps.Map(document.getElementById('map'), mapOptions);
$scope.markers = [];
var infoWindow = new google.maps.InfoWindow();
var createMarker = function (info){
var marker = new google.maps.Marker({
map: $scope.map,
position: new google.maps.LatLng(info.lat, info.long),
title: info.city
});
marker.content = '<div class="infoWindowContent">' + info.desc + '</div>';
google.maps.event.addListener(marker, 'click', function(){
infoWindow.setContent('<h2>' + marker.title + '</h2>' + marker.content);
infoWindow.open($scope.map, marker);
$scope.markerId = $scope.markers.indexOf(marker);
});
$scope.markers.push(marker);
}
for (i = 0; i < cities.length; i++){
createMarker(cities[i]);
}
$scope.openInfoWindow = function(e, selectedMarker){
e.preventDefault();
google.maps.event.trigger(selectedMarker, 'click');
}
});
Data object:
var cities = [
{
city : 'Toronto',
desc : 'This is the best city in the world!',
lat : 43.7000,
long : -79.4000
},
{
city : 'New York',
desc : 'This city is aiiiiite!',
lat : 40.6700,
long : -73.9400
},
{
city : 'Chicago',
desc : 'This is the second best city in the world!',
lat : 41.8819,
long : -87.6278
},
{
city : 'Los Angeles',
desc : 'This city is live!',
lat : 34.0500,
long : -118.2500
},
{
city : 'Las Vegas',
desc : 'Sin City...\'nuff said!',
lat : 36.0800,
long : -115.1522
}
];
Since the click handler is outside the angular scope you need to manually tell it to check for changes. So you must call $scope.$digest() on you own.
But your code triggering of the click will cause a loop of digests.
So you should gather all your infobox code in your $scope.openInfoWindow method
$scope.openInfoWindow = function(e, selectedMarker){
e && e.preventDefault();
infoWindow.setContent('<h2>' + selectedMarker.title + '</h2>' + selectedMarker.content);
infoWindow.open($scope.map, selectedMarker);
$scope.markerId = $scope.markers.indexOf(selectedMarker);
}
and change your click handler to call this method
google.maps.event.addListener(marker, 'click', function(){
$scope.openInfoWindow(null, marker);
$scope.$digest();
});
Demo at http://jsfiddle.net/gaby/19hfoxh8/

Angular object on page load

I have a map built on angular. https://vineyardcincinnati.com/nigeria-map
I have a field updating based on the google marker clicked. Is there a way to initialize an angular object based on the page load? The content box is currently blank until the user sends JSON data based on a click event.
Here is my angular code:
$scope.map = new google.maps.Map(document.getElementById('map'), mapOptions);
$scope.markers = [];
var infoWindow = new google.maps.InfoWindow({
maxWidth: 200
});
var createMarker = function (info){
var marker = new google.maps.Marker({
map: $scope.map,
position: new google.maps.LatLng(info.lat, info.long),
title: info.location,
image: info.img,
date: info.date,
quote: info.quote
});
marker.content = '<div class="infoWindowContent">' + info.desc + '</div>';
google.maps.event.addListener(marker, 'click', function(){
infoWindow.setContent(marker.content);
$scope.selectedMarker = marker;
$scope.$apply();
infoWindow.open($scope.map, marker);
});
$scope.markers.push(marker);
}
for (i = 0; i < cities.length; i++){
createMarker(cities[i]);
}
$scope.openInfoWindow = function(e, selectedMarker){
e.preventDefault();
google.maps.event.trigger(selectedMarker, 'click');
}
});
Here is my view
<div id="containter" ng-app="mapsApp" ng-controller="MapCtrl">
<div id="map"></div>
<div id="class">
<h1> {{selectedMarker.title}}</h1>
<p>{{selectedMarker.quote}}</p>
<p>Completed {{selectedMarker.date}}</p>
</div>
</div>
Use $timeout from inside your directive's controller:
$timeout(function() {
// initialize plugin on load here...
});
You can use module.run.
angular.module('myModule',[])
.run(function($rootScope){
$rootScope.selected = "foo";
// code runs on module init
}

Resources