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.
Related
I have a page to display all markers on a single google map and use map.data.loadGeoJson to achieve this.
The markers link to their respective details page with the following:
map.data.addListener('click', function(event) {
var id = event.feature.getProperty('name');
window.location.href = 'submission-details.php?submission_id='+id;
});
(The property 'name' is a json file property and the ID for each submission).
I would like the details page to also show a map, but only with one marker relevant to that specific details page.
My json type is feature collection, so I think I need a way to target each feature from the collection, rather than just using map.data.loadGeoJson which displays them all.
Not sure where to go from here and struggled to find someone else asking the same question so any help appreciated!
UPDATE
Thanks Duncan.
I added:
map.data.loadGeoJson('../photo_share/upload/file.json', {},function() {
map.data.getFeatureById(53);
map.data.getFeatureById(53).getProperty('name');
console.log(map.data.getFeatureById(53));
console.log(map.data.getFeatureById(53).getProperty('name'));
});
google.maps.event.addDomListener(window, "load", initMap3);
And it does display in console log, but how do I now use this to only display the one marker, because it currently displays all of them still.
The google.maps.Data class has a getFeatureById method. Given you're passing that id into the submission-details.php page, you should be able to use that to get just the single feature.
You still need to use loadGeoJson, and wait until that's loaded before trying to access it; see Google Maps API: getFeatureById for feature collection not working
Update: And then to stop the whole collection displaying, maybe something like this (completely untested)?
map.data.loadGeoJson('../photo_share/upload/file.json', {}, function(features) {
// get the feature you want:
var feature = map.data.getFeatureById(53);
// hide the current set:
map.data.setMap(null);
// wipe out all the current features:
for (var i = 0; i < features.length; i++) {
map.data.remove(features[i]);
}
// add the feature you want back in:
map.data.add(feature);
// display it:
map.data.setMap(map);
});
I am using a simple Mapbox layer control calling MB data layers (below).
I need to add a few more marker layers to this, but not sure how to get a mapbox ID. How can I accomplish this?
L.mapbox.accessToken = 'pk.eyJ1IjoibWFwc3RlciIsImEiOiI3RmFfME5ZIn0.73sdzUFNqSsGQzjlsnimaA';
var map = L.map('map').setView([38.8922,-77.0348], 14);
var layers = document.getElementById('menu-ui');
addLayer(L.mapbox.tileLayer('examples.map-i87786ca'), 'Base Map', 1);
addLayer(L.mapbox.tileLayer('examples.bike-lanes'), 'Bike Lanes', 2);
addLayer(L.mapbox.tileLayer('examples.bike-locations'), 'Bike Stations', 3);
function addLayer(layer, name, zIndex) {
layer
.setZIndex(zIndex)
.addTo(map);
code is from Mapbox toggling layers template
At the moment you're using their example ID and maps. You're not supposed to do that. If you would have read at the bottom of the page you posted it says:
Use this example by copying its source into your own HTML page and replacing the Map ID with one of your own from your projects.
Where "your projects" is linked to https://www.mapbox.com/projects/. When you're not logged in you get a nice dialog which asks you to login or register. Once you've done that you'll get your very own ID and you are able to create projects. When creating a project you'll get a Map ID per project. It's all pretty selfexplanatory.
EDIT: If you want to insert a separate layer with features, you've got to create a project with only a markerlayer. Save it and copy the id. You can include that in another map by using L.mapbox.featureLayer:
var mapId = 'examples.map-zr0njcqy'; // use your feature mapid
var features = L.mapbox.featureLayer(mapId); // declare featureLayer
features.on('ready', function () { // Wait untill features are loaded
addLayer(features); // add it the same your tilelayers
}
You can also use this to load external geojson files by just using an URL instead of a mapid.
See the example: https://www.mapbox.com/mapbox.js/example/v1.0.0/features-from-another-map/
And the reference: https://www.mapbox.com/mapbox.js/api/v2.1.5/l-mapbox-featurelayer/
I have the following test Google Map: http://dev.driz.co.uk/googlemap/
I'm using the design of Foursquare markers as an example to test out my code and so far I have implemented a simple display of where YOU the user is in the world with a small avatar and when you hover it tells you this in the form of a tooltip.
The next part is using some JSON data: http://dev.driz.co.uk/googlemap/data.json
I want to display those 5 posts on the map using the coordinates that are stored in the data and display them in a similar fashion to the current marker. The user will then hover the marker and be able to see a tooltip with the following information as an example:
Cameron asked:
Is Star Wars 3d still on at the cinema?
2012-05-20 02:31:21
The user should be able to click on the marker to be taken to the post.
I've had a look around the Developer section of Google Maps, but don't seem to getting the right stuff and not sure how best to use it with my tooltip function and map implementation.
Can anyone help? Post some code examples?
Thanks
Follow these steps
Pull the data using an AJAX request and store it in a variable.
You can use jQuery for this. http://api.jquery.com/jQuery.getJSON/
$.getJSON('http://dev.driz.co.uk/googlemap/data.json', function(data){
// loop and add markers
});
Or you can use plain javascript and a JSON parser.
http://www.degraeve.com/reference/simple-ajax-example.php
http://www.json.org/
Loop in data and pick each item and add to map
for (var i = 0; i < data.length; i++) {
var item = data[i];
var markerLatlng = new google.maps.LatLng(item.Post.latitude, item.Post.longitude);
var marker = new google.maps.Marker({
position: markerLatlng
});
marker.item = item; // store information of each item in marker
marker.setMap(map); // where `map` is the instance of Google Map
google.maps.event.addListener(marker, "click", function(mark) {
// retrieve information using `this.item` and create dynamic HTML to show it.
// this.item.Post.datetime, this.item.Post.content etc.
});
}
I have JS code with google maps api.
When I click on a marker I display more markers.
When I click on these markers I display more markers...and so on
I connect all these by polylines and the resulting structure looks like a spider map.
When I click on any marker agian, I want to hide the markers and polylines it created.
How do I create and keep a reference to these polylines and markers which are formed inside the recursive calls of the eventlistener for every parent marker, so that I could later on do a setMap(null);
I haven't tested it, but I believe you could add an array of shown markers inside a Marker object. It would look somehow like this:
var originalMarkers = new Array(); //load markers you show at the beginning to some array
function onMarkerClick(event) {
if (marker.childMarkers){
for (child in marker.childMarkers) {
child.setMap(null);
//and so on, e.g remove polylines
marker.childMarkers = null;
}
}
else {
marker.childMarkers = new Array();
//load markers you show after click here
}
}
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.