For a website I'm using Google Maps to add polylines to a map to display a route. Some routes consist of multiple legs (stages) and I'm trying to add the polylines 'on request'. So only if a user chooses to show a leg, it will draw the polyline. Also the user might choose a completely different route and this new set of polylines should be drawn on the map as well.
My problem is that I can't seem to figure out or find how to select an existing map. I start out by creating a map using the following code:
qMap = new google.maps.Map(document.getElementById(mP.target), mapOptions);
mP.target contains a string with the canvas id and mapOptions is just a object with some options, nothing special.
So I do all kind of stuff with qMap, like adding markers, drawing polylines etc. And this shouldn't just be done at map initiation, but also when the user wants to add something. qMap isn't a global variable and I rather not have it being a global either.
I've tried qMap = google.maps.Map(document.getElementById(mP.target)) and other similar methods. With no success. I'm hoping you can help me out finding a way to this without global variables! Thanks!
There are a couple of things you could try.
1) Wrap your code in an immediately invoked function. This way any variables are contained within the function's scope and don't escape to pollute the global variable space which I guess is your main concern.
(function () {
var mapGlobal = new google.maps.Map(target, options);
function thatDoesSomething(){
// do something with mapGlobal
}
}());
2) Use a static object which might be handy for organising your code.
var Map = {
map: new google.maps.Map(target, options),
thatDoesSomething: function () {
// do something with this.map
}
};
3) Or combine them.
(function () {
var Map = {
map: new google.maps.Map(target, options),
thatDoesSomething: function () {
// do something with this.map
}
};
}());
Related
Ok, here is my situation. I am using the leaflet map module with drupal. I have the map integrated on my website with views. I have nodes that contain content that I want to be displayed via a popup window. When I click each individual marker, the popup works exactly as I want. however, I want to be able to click an external link to be able to also open the popup. I have viewed and implemented this code from another question:
var markers = [];
var marker1 = L.marker([51.497, -0.09],{title:"marker_1"}).addTo(map).bindPopup("Marker 1");
markers.push(marker1);
var marker2 = L.marker([51.495, -0.083],{title:"marker_2"}).addTo(map).bindPopup("Marker 2");
markers.push(marker2);
var marker3 = L.marker([51.49, -0.097],{title:"marker_3"}).addTo(map).bindPopup("Marker 3");
markers.push(marker3);
function markerFunction(id){
for (var i in markers){
var markerID = markers[i].options.title;
if (markerID == id){
markers[i].openPopup();
};
}
}
$("a").click(function(){
markerFunction($(this)[0].id);
});
by user abenrob, but that doesn't work with markers generated by drupal.
My question has 2 parts, as I can see it.
1: How do I access the map inside my different block? I have set up the links from my menu block to call my function that contains the aforementioned code, and they call it correctly. However, when my Javascript needs to speak to the map, I get nothing.
Currently I have "var map = document.getElementById('leaflet-map');", but that seems to be pulling the div, not the map contained inside the div.
2: How do I access the list of markers generated by my map in drupal. Currently, as a test, I am just generating a marker manually and using the bindPopup function to bind the div containing the popup on the page, but I can't add it to the map (see part 1). Ideally I would not want to recreate the markers in javascript if they are already created in Drupal, but we don't always live in an ideal world, but it seems that if I get the map to connect, I could at least work with that.
In case anyone else stumbles across this with the same question, I figured out the first question. I accessed the map created by Drupal through the Leaflet module by utilizing the following code:
// This accesses the leaflet map created by drupal and sets the map variables so that they can be used with the functions
var map;
$(document).bind('leaflet.map', function(e, settingsLeaflet, lMap)
{
map = lMap;
});
I am still working on the second question. When I figure it out, I will add another update.
Edit: I was able to access the markers in the second question by using the following code:
var markers = {};
var markersList = [];
// This accesses the leaflet map features and pulls the marker variables so that they can be used with the functions
$(document).bind('leaflet.feature', function(e, lFeature, feature)
{
markers[feature.feature_id] = lFeature;
markersList.push(lFeature);
});
from there it was as easy as looping through the markers list, as such:
// This function takes the variable id, which is passed from the HTML call of this function. It then loops through the marker list and compares the id with the value of the title of each marker. If it finds a match, then it opens the popup bound to that specific marker.
function markerPopups(id)
{
// Loops through the markers list
for (var i = 0; i < markersList.length; i++)
{
// Sets a variable to get the title of the marker, which
var markerID = markersList[i].options.title.replace(/[^a-zA-Z0-9]/g, '_');
// Compares the variable passed through the function to the title of the marker. If there is a match, it opens the popup for that marker.
if(markerID == id)
{
markersList[i].openPopup();
}
}
}
Also, it wasn't needed to access the map once you accessed the pre-made markers, so you can ignore the first part, unless you need to use the map for anything else.
I seem to be having some trouble with reinitializing a Leaflet map object. I am running an init() function that starts by initializing a map, adding a tilelayer and layer with polygons, and then adding sublayers which color the polygons according to a ST_Intersects query. The issue is that this function is tied to an AJAX call that is caused by a click event but does not update the data according to the new parameters sent to the map. I don't think I am explaining this very well, so here is a bit of my code:
success: function(data) {
init(data);
}
function init(data){
// initiate leaflet map
alert("start");
var map = L.map('cartodb-map').setView([40.750028, -73.926768], 11);
alert("map made");
//create sublayers, etc
}
What happens is that the first time init is run, both 'start' and 'map made' alerts work, and the map is made according to the data. Any further calls to init simply alerts with "start" and "map made" is never alerted so I believe the problem is with reinitializing the leaflet map. What should I do to fix this?
Not sure the problem without seeing more of your code, but you could try calling map.remove(); the second time around. So:
if (map) {
map.remove();
// add in new map initialization here
} else {
var map = ...
}
I have a Google Maps marker function that successfully creates markers on a map like this:
// A function to create the marker and set up the event window
function createMarker(point,html) {
var marker = new GMarker(point,{title:html});
GEvent.addListener(marker, "click", function() {
marker.openInfoWindowHtml(html);
});
return marker;
}
Here is a tinyurl of the exiting code: http://tinyurl.com/b8f9b4l
Using this solution: Google maps: place number in marker?
I've updated this line of code but it is not numbering. What am I doing wrong?
var marker = new GMarker(point,{title:html,icon:'icon: \'https://chart.googleapis.com/chart?chst=d_map_pin_letter&chld='+ (position) +'|FF776B|000000',});
The icon property just needs to be the url. You don't need the extra "icon:", and you should drop the extra comma at the end (IE seems to throw an exception when it finds a dangling comma). Also, the parenthesis you don't need - but probably aren't hurting anything.
{
title:html,
icon: 'https://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=' + position +'|FF776B|000000'
}
I see where you got the idea. Idk why s/he got a point for that. The extra "icon:" messes it up.
Try this as a test, it should make sure you don't have any problems with the variables inside the url.
{
title:html,
icon: 'https://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=4|FF776B|000000'
}
I'm trying to do something that I gather has been done quite a few times before, although I'm having some difficulty accomplishing it.
I have a webpage that displays three Google Maps.
For each of these google maps, I have a text box that accepts a post code / zip code, and a "get directions" button.
Clicking on each of these buttons uses the google.maps.DirectionsService object to display ONE set of directions in ONE panel centered at the bottom of the page.
My issue arises when I try to find a new route by searching again. As you can see in the image below, both routes are rendered.
I have one marker at the end which is in a markers collection.
I've read a few times now about how you can loop through this array and use marker.setMap(null) to clear this marker.
However, I can't seem to clear the actual routes after each specific search.
Has anybody had any problems with clearing markers from multiple maps?
Do you have to totally reset the map in some way?
If you have to clear markers, at what point in the lifecycle of the process should you do it so that your new journey appears after the search, but the old one is removed?
I use the same google.maps.DirectionsService object for all three Google maps, and they all call the same method to calculate directions, but passing in their own map object as a parameter.
function calcRoute(startPoint, location_arr) {
// Create a renderer for directions and bind it to the map.
var map = location_arr[LOCATION_ARR_MAP_OBJECT];
var rendererOptions = {
map: map
}
if(directionsDisplay != null) {
directionsDisplay.setMap(null);
directionsDisplay = null;
}
directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById("directionsPanel"));
The gist being that if directionsDisplay != null, we not only pass null to setMap, we also nullify the whole object afterweards, and I found this fixed it.
I dont know the answer.... most likely all u need to do is depending on circumstances:
// put the codes after direction service is declared or run directionsService //
directionsDisplay.setMap(null); // clear direction from the map
directionsDisplay.setPanel(null); // clear directionpanel from the map
directionsDisplay = new google.maps.DirectionsRenderer(); // this is to render again, otherwise your route wont show for the second time searching
directionsDisplay.setMap(map); //this is to set up again
This is the only part you need:
// Clear past routes
if (directionsDisplay != null) {
directionsDisplay.setMap(null);
directionsDisplay = null;
}
This works for me
// on initiate map
// this listener is not necessary unless you use listener
google.maps.event.addListener(directionsRenderer, 'directions_changed', function () {
if(directionsRenderer.directions === null){
return;
}
// other codes
});
// on clear method
directionsRenderer.set('directions', null);
I have this code that generates markets I want to be clickable with a pop up info window.
for (i = 0; i < marker_array.length; i++) {
var point = new GLatLng(marker_array[i][0], marker_array[i][1]);
var marker = new GMarker(point, markerOptions);
GEvent.addListener(marker, "click", function() {
marker.openInfoWindowHtml(html_data);
});
map.addOverlay(marker);
}
The problem is that only one market ends up clickable. No matter which one gets clicked, an info window with the one clickable marker's data pops up over that one clickable marker. All of the markers load and are in the correct locations, so the problem is only with getting the pop up window data to appear for each one.
I've checked out the section about "unrolling" the marker function here and it seems like that's probably where I'm going wrong, but I have not been able to get this to work through testing the changes they suggest.
I believe your problem is that the variable html_data is the same for all iterations of this loop. You should update that variable each go-through in the loop for the values to be different.
I'm not quite sure if I follow, but are you saying that all popups have the same data in them?
I think that this is the problem, and that's because the way the event listeners work. When the click function happens it evaluates the listener event. So the HTML you're showing is always the same, as the variable is always being re-written to.
I used an array that matches my marker data for my HTML and it works well:
function createMarker(posn, title, icon, i) {
var marker = new GMarker(posn, {title: title, icon: icon, draggable:false});
GEvent.addListener(marker, 'mouseover', function() {
map.closeInfoWindow()
marker.openInfoWindowHtml(infoText[i])
} );
return marker;
}
I found the same case, and i have a solution for this problem. I suggest you to create a custom class extending Marker class. In this custom class, you should make a constructor that have a parameter(s) for your data, and this class should also have its own info window variable that will be called from your main application. For example:
The custom class:
public class StoreSpot extends Marker
{
public var infoWindow:InfoWindowOptions;
public var store_id:String;
public var address:String;
public var name:String;
...
}
The main application:
tempMarker = new StoreSpot(
tempLatlng,
new MarkerOptions({
icon:new spotStore(),
iconAlignment:MarkerOptions.ALIGN_HORIZONTAL_CENTER,
iconOffset:new Point(0,-50)
}),
temp.store_id,
temp.name,
temp.address,
temp.detail
);
This way you can place different info window for different marker. Hope this works for you. Enter code here.