I have this controller for AngularJS Framework.
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
var locations =[]; var map; var markers = [];
$scope.mappa = function(){
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 37.507033, lng: 15.080257},
zoom: 8
});
}
$scope.insert = function(){
$http.get("http://localhost:8080/SistemiDistribuiti/rest/Point/Trovati")
.success(function(data)
{locations = data;});
var marker, i;
for (i = 0; i < locations.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i][0], locations[i][1]),
map: map
});
markers.push(marker);
}
for (i = 0; i<markers.length; i++){
markers[i].setVisible(true);
}
};
In html file, i have a button that calls the insert function.
But if I run this code, the button works at the second time only. Instead if the http request is out of the function, the button works immediatly. Why?
$http.get("http://localhost:8080/SistemiDistribuiti/rest/Point/Trovati")
.success(function(data)
{locations = data;});
$scope.insert = function(){
var marker, i;
for (i = 0; i < locations.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i][0], locations[i][1]),
map: map
});
markers.push(marker);
}
for (i = 0; i<markers.length; i++){
markers[i].setVisible(true); }
};
It's asynchronous method. Move the code insert into callback success.
$http.get("http://localhost:8080/SistemiDistribuiti/rest/Point/Trovati")
.success(function(data) {
var marker, i;
for (i = 0; i < data.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(data[i][0], data[i][1]),
map: map
});
markers.push(marker);
}
for (i = 0; i<markers.length; i++){
markers[i].setVisible(true); }
}
});
But if I run this code, the button works at the second time only.
It works at the first time, it's just AJAX request is asynchronous, so the location variable is not populated yet by the time your are trying to use it. When you click next time, it turns out that data has already loaded and location is set and "cached".
You need to do your stuff in callback function:
$scope.insert = function () {
$http.get("http://localhost:8080/SistemiDistribuiti/rest/Point/Trovati").success(function (data) {
var marker, i, locations = data;
for (i = 0; i < locations.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i][0], locations[i][1]),
map: map
});
markers.push(marker);
}
for (i = 0; i < markers.length; i++) {
markers[i].setVisible(true);
}
});
};
And finally, when you make it work, consider moving your request logic into reusable service, making requests in controller is not the best design:
$scope.insert = function () {
locations.get().then(function(data) {
var marker, i, locations = data;
// ...
});
};
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am trying to make google map with filtering. One filter is select box (for now it is working) and other filer is with check boxes. So now my it have behavior as a radio button. You can se example here http://extrol.ellectadigital.com/distributeri/.
When you check it, it shows good pin, but when you click on the second it removes the first pin, and I don't want that.
So here is my code :
`http://codepen.io/PoznanM/pen/VpoZOm`
Problem is here onclick="filterChecker(this.value);" in filterChecker function only single checked item was compared and other marker are cleared.
So you have to compare all the checked items. I added function selectAllChecked() which passes checked values as array to function filterChecker()
var gmarkers1 = [];
var markers1 = [];
var infowindow = new google.maps.InfoWindow({
content: ''
});
var filters = {
shower: false,
vault: false,
flush: false
}
// Our markers
markers1 = [
['0', 'Title', 44.741318, 20.433573, 'Beograd', 'distributer'],
['1', 'Title', 45.823783, 16.024404, 'Zagreb', 'servis'],
['2', 'Title', 44.438350, 17.631215, 'Bosna', 'maloprodaja']
];
/**
* Function to init map
*/
function initialize() {
var center = new google.maps.LatLng(45.662477, 18.022074);
var mapOptions = {
zoom: 5,
center: new google.maps.LatLng(45.662477, 18.022074),
mapTypeId: 'roadmap',
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
for (i = 0; i < markers1.length; i++) {
addMarker(markers1[i]);
}
}
/**
* Function to add marker to map
*/
function addMarker(marker) {
var tip = marker[5];
var category = marker[4];
var title = marker[1];
var pos = new google.maps.LatLng(marker[2], marker[3]);
var content = marker[1];
marker1 = new google.maps.Marker({
title: title,
position: pos,
tip: tip,
category: category,
map: map
});
gmarkers1.push(marker1);
// Marker click listener
google.maps.event.addListener(marker1, 'click', (function(marker1, content) {
return function() {
console.log('Gmarker 1 gets pushed');
infowindow.setContent(content);
infowindow.open(map, marker1);
map.panTo(this.getPosition());
map.setZoom(15);
}
})(marker1, content));
}
/**
* Function to filter markers by category
*/
filterMarkers = function(category) {
for (i = 0; i < markers1.length; i++) {
marker = gmarkers1[i];
// If is same category or category not picked
if (marker.category == category || category.length === 0) {
marker.setVisible(true);
}
// Categories don't match
else {
marker.setVisible(false);
}
}
}
var get_set_options = function() {
ret_array = []
for (option in filters) {
if (filters[option]) {
ret_array.push(option)
}
}
return ret_array;
}
var filter_markers = function() {
set_filters = get_set_options()
// for each marker, check to see if all required options are set
for (i = 0; i < markers.length; i++) {
marker = markers[i];
// start the filter check assuming the marker will be displayed
// if any of the required features are missing, set 'keep' to false
// to discard this marker
keep = true
for (opt = 0; opt < set_filters.length; opt++) {
if (!marker.properties[set_filters[opt]]) {
keep = false;
}
}
marker.setVisible(keep)
}
}
// Fuction for checkboxes
var tipovi = document.getElementsByClassName('chk-btn').value;
var selectAllChecked = function() {
var checkedPlace = []
var allCheckedElem = document.getElementsByName('filter');
for (var i = 0; i < allCheckedElem.length; i++) {
if (allCheckedElem[i].checked == true) {
checkedPlace.push(allCheckedElem[i].value)//creating array of checked items
}
}
filterChecker(checkedPlace) //passing to function for updating markers
}
var filterChecker = function(tip) {
//console.log(tip);
for (i = 0; i < markers1.length; i++) {
marker = gmarkers1[i];
//console.log(marker);
if (in_array(this.marker.tip, tip) != -1) {
marker.setVisible(true);
} else {
marker.setVisible(false);
}
}
}
// Init map
initialize();
function in_array(needle, haystack) {
var found = 0;
for (var i = 0, len = haystack.length; i < len; i++) {
if (haystack[i] == needle) return i;
found++;
}
return -1;
}
#map-canvas {
height: 300px;
}
#iw_container .iw_title {
font-size: 16px;
font-weight: bold;
}
.iw_content {
padding: 15px 15px 15px 0;
}
<div id="map-canvas">
</div>
<select id="type" onchange="filterMarkers(this.value);">
<option value="">Izaberite Mesto</option>
<option value="Beograd">Beograd</option>
<option value="Zagreb">Zagreb</option>
<option value="Bosna">Bosna</option>
</select>
<div id="buttons">
<input type="checkbox" name="filter" value="distributer" class='chk-btn' onclick="selectAllChecked();">
<label for='shower'>Distributer</label>
<input type="checkbox" name="filter" value="maloprodaja" class='chk-btn' onclick="selectAllChecked();">
<label for='flush'>Maloprodaja</label>
<input type="checkbox" name="filter" value="servis" class='chk-btn' onclick="selectAllChecked();">
<label for='vault'>Servis</label>
</div>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCmUfKutqGZ-VgbD4fwjOFd1EGxLXbxcpQ&sCensor=false"></script>
I'm trying to handle mouse over listener for each marker(there are 30 markers) and to show infowindows for these markers. I created listeners for each markers but when my mouse over the some marker it shows always the last marker's infowindows. To sum up I can't listen other markers. any help would be appreciated. thanks in advance and here my code :
var listeners = [];
for(var i = 0; i < markers.length; i++){
var marker = markers[i];
var contentString = contents[i];
listeners[i] = new google.maps.event.addListener(marker, 'mouseover', function() {
var hideInfoWindows = function(){
for (var j = 0; j < util.Common.infowindows.length; j++) {
util.Common.infowindows[j].close();
}
}
var addInfoWindow = function(){
var infowindow = new google.maps.InfoWindow({
content: contentString
});
//hideInfoWindows();
util.Common.infowindows.push(infowindow);
infowindow.open(util.Common.googlemap,marker);
}
addInfoWindow();
});
}
I'm also using js cluster library but I don't think the problem is related with it.
I think your problem might be that you are not using a closure inside the cycle, and when the event listener is fired, the marker and the contentString variables are pointing to the last marker.
Try to rewrite the cycle like this:
var listeners = [];
for(var i = 0; i < markers.length; i++){
(function(index){ //create a closure, variable 'index' will take its value from variable i, but won't be affected by changed i in the outer scope
var marker = markers[index]; //use this scope's index variable instead of i
var contentString = contents[index]; //use this scope's index variable instead of i
listeners[index] = new google.maps.event.addListener(marker, 'mouseover', function() {
var hideInfoWindows = function(){
for (var j = 0; j < util.Common.infowindows.length; j++) {
util.Common.infowindows[j].close();
}
};
var addInfoWindow = function(){
var infowindow = new google.maps.InfoWindow({
content: contentString
});
//hideInfoWindows();
util.Common.infowindows.push(infowindow);
infowindow.open(util.Common.googlemap,marker);
};
addInfoWindow();
});
})(i);
}
This question already has answers here:
Google Maps JS API v3 - Simple Multiple Marker Example
(15 answers)
Closed 8 years ago.
I am trying to add 3 markers to a map and when click on the markers, an info window will be shown. But every array element inside google.maps.event.addListener becomes undefined.
What's the problem?
<div id="map-canvas2" style="width:100%;height:500px"></div>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<script>
var num;
var marker;
var infoWindow;
var infoText;
var lat;
var lng;
var map;
function initialize() {
num = 3;
marker = [];
infoWindow = [];
infoText = [];
lat = [];
lng = [];
infoText[0] = "test1";
lat[0] = 22.420845;
lng[0] = 114.208705;
infoText[1] = "test2";
lat[1] = 22.416026;
lng[1] = 114.209321;
infoText[2] = "test3";
lat[2] = 22.420841;
lng[2] = 114.205188;
for (var i = 0; i < num; i++) {
marker[i]=new google.maps.Marker({
position:new google.maps.LatLng(lat[i], lng[i]),
});
infoWindow[i] = new google.maps.InfoWindow({
content:"<div>"+infoText[i]+"</div>"
});
}
var mapOptions = {
zoom: 17,
center: new google.maps.LatLng(22.420458,114.207482)
};
map = new google.maps.Map(document.getElementById('map-canvas2'), mapOptions);
for (var i = 0; i < num; i++) {
marker[i].setMap(map);
google.maps.event.addListener(marker[i], 'click', function() {
new google.maps.InfoWindow({
content:"<div>"+infoText[i]+"</div>"
}).open(map,marker[i]);
});
}
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
The problem:
Each event listener is referencing the same variable i which gets incremented on each pass of the for loop. So after the loop is finished the value of i is 3, but none of your arrays have an index of 3 so you get undefined. Because each event handler is referencing the same i variable they are all referencing the same undefined array values.
The solution: Create a closure so that the event handler for each marker has a it's own variable instead sharing reference to single variable.
for (var i = 0; i < num; i++) {
marker[i].setMap(map);
google.maps.event.addListener(marker[i], 'click', (function(index) {
return function() {
new google.maps.InfoWindow({
content: "<div>"+infoText[index]+"</div>"
}).open(map, marker[index]);
}
})(i));
}
What we're doing is creating a Immediately-Invoked Function Expression "IIFE". The IIFE has a parameter called index which is set to the value of i. Because variables have function scope, index belongs only to this function. Inside the IIFE we return a function that will do the actual work when the event is triggered, but it will reference index not i.
Don't send indexed parameters to an anonymous function:
for (var i = 0; i < num; i++) {
var mrk = marker[i];
var iwContent = infoText[i];
mrk.setMap(map);
google.maps.event.addListener(mrk, 'click', function() {
new google.maps.InfoWindow({
content:"<div>"+iwContent+"</div>"
}).open(map,mrk);
});
}
The google map i am using does not get centered about the mean point i have calculated.
The code for the initialization is given. The map appears to be zoomed out a lot and its center far off from the center i have calculated. The mean appears in the extreme top left of the map. What is the problem here?
I am displaying the map in Bootstrap modal.
function initializeMap()
{
var xMean = 0.0;
var yMean = 0.0;
for(var i=0;i<points.length;i++)
{
xMean += parseFloat(points[i][0]);
yMean += parseFloat(points[i][1]);
}
xMean /= parseFloat(points.length);
yMean /= parseFloat(points.length);
var myMean = new google.maps.LatLng(xMean, yMean);
var mapOptions = {
zoom:17,
center:myMean
}
map = new google.maps.Map(document.getElementById('map'), mapOptions);
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i<points.length;i++) {
path.push(new google.maps.LatLng(points[i][0],points[i][1]));
bounds.extend(path[i]);
};
map.fitBounds(bounds);
//Displaying the markers
var marker;
for (var i = 0; i < path.length; i++) {
marker = new google.maps.Marker({
position: path[i],
map: map
});
}
//Displaying the path
for (var i = 0; i<path.length-1; i++) {
var start = path[i];
var end = path[i+1];
requestDirections(start,end);
}
}
by using:
map.fitBounds(bounds);
map.setCenter(bounds.getCenter());
you seem to overwrite myMean coordinates
I have put some markers for specific locations in a map, and I have two buttons, one to hide all the markers (clearOverlays) and other to show them again (showOverlays) but it isn't working. In my JavaScript console I am getting this error : Cannot call method 'setMap' of undefined
Here's my code..
// COORDENADAS
var coordenadas = [
['Punto 1', 19.558061,-99.296344, 4],
['Punto 2', 19.55886, -99.296886, 5],
['Punto 3',19.559103, -99.296688, 3],
['Punto 4', 19.560164,-99.297347, 2],
['Punto 5',19.560073,-99.296064, 1]
];
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 16,
center: new google.maps.LatLng( 19.561883, -99.298287),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var ventana = new google.maps.InfoWindow();
var marcador, i;
for (i = 0; i < coordenadas.length; i++) {
marcador = new google.maps.Marker
({
position: new google.maps.LatLng(coordenadas[i][1], coordenadas[i][2]),
animation: google.maps.Animation.DROP,
map: map
});
google.maps.event.addListener(
marcador, 'mouseover', (function(marcador, i) {
return function() {
ventana.setContent(coordenadas[i][0]);
ventana.open(map, marcador);
}
})(marcador, i)
);
}
function clearOverlays(map) {
for (var i = 0; i < coordenadas.length; i++) {
marcador[i].setMap(null);
}
setAllMap(null);
console.log('click Ocultar');
}
function showOverlays(map) {
for (var i = 0; i < coordenadas.length; i++) {
marcador[i].setMap(map);
}
setAllMap(map);
console.log('click Mostar');
}
marcador is not an array. marcador[i] doesn't exist. That gives the error message: Cannot call method 'setMap' of undefined
You need an array of google.maps.Marker objects.
var gmarkers = [];
function clearOverlays(map) {
for (var i = 0; i < gmarkers.length; i++) {
gmarkers[i].setMap(null);
}
}
function showOverlays(map) {
for (var i = 0; i < gmarkers.length; i++) {
gmarkers[i].setMap(map);
}
}
for (i = 0; i < coordenadas.length; i++) {
var marcador = new google.maps.Marker
({
position: new google.maps.LatLng(coordenadas[i][1], coordenadas[i][2]),
animation: google.maps.Animation.DROP,
map: map
});
gmarkers.push(marcador);
google.maps.event.addListener(
marcador, 'mouseover', (function(marcador, i) {
return function() {
ventana.setContent(coordenadas[i][0]);
ventana.open(map, marcador);
}
})(marcador, i)
);
}
working example