Hyperlink to open marker infowindow on Google Map - javascript

I have a map, with a side bar div next to it. I'm trying to make it so that each marker on the map has a corresponding hyperlink in the sidebar, and when clicked, the info box for that marker pops up.
function linkClick(){
google.maps.event.trigger(gmarkers[cpid], "click");
}
content += ''+tmpName+"<br>";
$("#cplist").html(content);
cpid is a unique id for every point on the map, a value which is stored in the database with the rest of the information for the markers.
I have my markers on the map, and my links in the side bar, but I'm not sure how to make the connection between to two. I've created the 'linkClick' function to try and achieve this, but I just get the error:
ReferenceError: Can't find variable: linkClick
Currently all of the above code is in the loop which plots the markers on the map. I think i've included enough detail/code.
This is an example of what I want to achieve http://www.geocodezip.com/v3_MW_example_categories.html

I suggest changing your approach - rather than trying to push the click event, just go directly to the InfoWindow and call open. Somewhere else in your code you have a click event listener for each marker that opens an InfoWindow; so maintain reference(s) to your InfoWindow instances and open them, just the same as in the marker click event handler, when the onlick function attached to the link is called.
Or, if you are following a common strategy and working with a single, global InfoWindow, just write a function that accepts the cpid, places the necessary content in the InfoWindow, sets the correct position, and then calls InfoWindow.open( map ).
So if this is your event listener code:
google.maps.event.addListener(marker, 'click', function () {
infowindow.setContent(tmpName+" is "+tmpDist+"km away from you.");
infowindow.open(map, this);
});
Add a new function:
function openInfoWindow( cpidAndWhateverElseParam ) {
infowindow.setContent(tmpName+" is "+tmpDist+"km away from you.");
infowindow.open(map, this);
}
And change your link code to be:
content += '<a href="javascript:openInfoWindow(' + cpidAndWhateverElseParam +
')">'+tmpName+"</a><br>";

For function you are not passing any variable,
thats why it is giving ReferenceError: Can't find variable: linkClick
function linkClick(cpid){
google.maps.event.trigger(gmarkers[cpid], "click");
}
content += <a onClick=linkClick(' + cpid + ')">'+tmpName+"</a><br>";
$("#cplist").html(content);

I made something similar once, but instead of use an element a i used a button and like javascript pure in the event OnClick I put my event handler and it works, so in your case i tried to handle the event like this
<a onClick=linkClick(' + cpid + ')">'+tmpName+"</a>

Related

Pass event and this objects to function in different scope

I am building a google maps application, and I need to pass event specific data to another function in JavaScript.
When I click on part of the map, an InfoWindow pops up with information, for example latLng. It also has a button. When clicked, it opens an overlay with more information, part of that information is from the click event. I need to pass the event and this objects to the button to display information in the overlay.
First I create the event:
// Add a listener for the mouse event.
// In the google maps scope
google.maps.event.addListener(SomeMapArea, 'click', showTB);
Then I have the Text Box function:
// In the google maps scope
function showTB(event) {
var contentString = event.latLng +
'<br>' + '<button onclick="moreInfo(event, this)">More</button>';
infoWindow.setContent(contentString);
infoWindow.setPosition(event.latLng);
infoWindow.open(map);
}
When I click the button the overlay with more information comes up:
// In global scope
function moreInfo(e, t){ //using (event, this) here causes 'missing formal parameter' error
// Overlay code
var overlayContent = e.latLng + t.someAttribute;
document.getElementById("content").innerHTML = overlayContent;
}
However, event and this are not defined in the function moreInfo. How do I pass those two objects into moreInfo so that I can read their attributes?
Try This
var contentString = event.latLng +
'<br>' + '<button onclick="moreInfo('+event+','+this+')">More</button>';

Click link inside Leaflet Popup and do Javascript

I have a leaflet map up and running. It overlays a series of polygons (via GeoJSON) on the map and attaches popups to each polygon. Each of the popups display information about that polygon.
I'd like to have inside the popup a link that, when clicked, runs a javascript function that pulls further smaller polygons via AJAX and shows them.
I can't get the script to catch a click on the link via the normal jQuery/Javascript click events. Here's what I mean by normal (the following doesn't work):
$('a .smallPolygonLink').click(function(e){
console.log("One of the many Small Polygon Links was clicked");
});
The bindPopup part is as follows. It runs on each polygon when made and it pops up correctly on clicking on a polygon. It does show the link, just won't run the above code on click.
var popupContent = "Basic Information..." + '<a class="smallPolygonLink" href="#">Click here to see the smaller polygons</a>';
layer.bindPopup(popupContent);
Here's a JSFiddle illustrating the example, though in a far simpler form. http://jsfiddle.net/2XfVc/4/
The link element inside the popup is being dynamically generated from your markup each time the popup is opened. That means the link doesn't exist when you're trying to bind the handler to it.
The ideal approach here would be to use on to delegate event handling to the popup element or an ancestor of it. Unfortunately, the popup prevents event propagation, which is why delegating event handling to any static elements outside the popup won't work.
What you can do is preconstruct the link, attach the handler, and then pass it to the bindPopup method.
var link = $('TestLink').click(function() {
alert("test");
})[0];
marker.bindPopup(link);
Here is a demonstration: http://jsfiddle.net/2XfVc/7/
In general, to insert any sort of complex markup with multiple event handlers, use the folowing approach:
// Create an element to hold all your text and markup
var container = $('<div />');
// Delegate all event handling for the container itself and its contents to the container
container.on('click', '.smallPolygonLink', function() {
...
});
// Insert whatever you want into the container, using whichever approach you prefer
container.html("This is a link: <a href='#' class='smallPolygonLink'>Click me</a>.");
container.append($('<span class="bold">').text(" :)"))
// Insert the container into the popup
marker.bindPopup(container[0]);
Here is a demo: http://jsfiddle.net/8Lnt4/
See this Git issue for more on event propagation in leaflet popups.
While the Popup content wrapper prevents event propagation, events within the popup inner Markup propagate just fine. You can add events to popup elements when they are displayed on the map (and have become part of the DOM). Just watch for leaflet event popupopen.
var map = L.map('map').setView([51.505, 10], 7); //for example
//the .on() here is part of leaflet
map.on('popupopen', function() {
$('a .smallPolygonLink').click(function(e){
console.log("One of the many Small Polygon Links was clicked");
});
});
http://jsfiddle.net/tJGQ7/2/
This works like a charm for me. If your popup does not have a 'a .smallPolygonLink' the above code does nothing.
This code runs on every startup of a popup. However you don't have to worry that it attaches more than one handler to an element, since when the popup closes, the DOM nodes get thrown away.
There is a much more general way to do this. However, it involves eval(). Use at your own risk. But when AJAXloading partial pages that contain JS you run the same risks, so for your edification I present "executing JS inside your leaflet popups":
map.on('popupopen', function(){
var cont = document.getElementsByClassName('leaflet-popup-content')[0];
var lst = cont.getElementsByTagName('script');
for (var i=0; i<lst.length;i++) {
eval(lst[i].innerText)
}
});
demo: http://jsfiddle.net/tJGQ7/4/
Now you can write:
var popup_content = 'Testing the Link: TestLink<script> $(".speciallink").on("click", function(){alert("hello from inside the popup")});</script>';
marker.bindPopup(popup_content);
That's what I find on the mapbox offical website: Create a click event in a marker popup with Mapbox.js and jQuery. The comment explains why we say $('#map') instead of $('#mybutton').
var marker = L.marker([43.6475, -79.3838], {
icon: L.mapbox.marker.icon({
'marker-color': '#9c89cc'
})
})
.bindPopup('<button class="trigger">Say hi</button>')
.addTo(map);
//The HTML we put in bindPopup doesn't exist yet, so we can't just say
//$('#mybutton'). Instead, we listen for click events on the map element which will bubble up from the tooltip, once it's created and someone clicks on it.
$('#map').on('click', '.trigger', function() {
alert('Hello from Toronto!');});
I came across this problem, tried the solution above. But it didn't worked for me. Found the following pretty basic jquery solution.
// add your marker to the map
var my_marker = new L.marker([51.2323, 4.1231], {icon: my_icon});
var popup = L.popup().setContent('<a class="click" href="#">click</a>');
my_marker.addTo(map).bindPopup(popup);
// later on
jQuery("body").on('click','a.click', function(e){
e.preventDefault();
alert('clicked');
});
You can check inner properties of popup object, including _wrapper etc.
map.on('popupopen', _bindPopupClick);
map.on('popupclose', _unbindPopupClick);
var _bindPopupClick = function (e) {
if (e.popup) {
e.popup._wrapper.addEventListener('click', _bindPopupClickHandler);
}
};
var _unbindPopupClick = function (e) {
if (e.popup) {
e.popup._wrapper.removeEventListener('click', _bindPopupClickHandler);
}
}`
You can use jQuery to select the canvas element, but you'd have to use its own methods within the canvas. A decent start would be https://developer.mozilla.org/en/canvas_tutorial .
mapbox JavaScript library has an event:
bindPopup('<button class="trigger">Say hi</button>');
addTo(map);
$('#map').on('click', '.trigger', function() {
alert('Hello from Toronto!');
});
https://www.mapbox.com/mapbox.js/example/v1.0.0/clicks-in-popups/

Google maps V3 dragend listener adds all markers back onto map

I have a google map using V3 of the API. It has one marker on it which is draggable and then a load of other markers that are static. I have set up a dragend listener for the draggable marker which calls a function called clear_markers() like so:
google.maps.event.addListener(marker_0, "dragend", function() {
clear_markers();
});
function clear_markers()
{
if (markers) {
for (var i = 1; i <= markers.length; i++ ) {
if(typeof markers[i] !== "undefined") {
markers[i].setMap(null);
}
}
}
}
The reason I start the for loop at 1 and not 0 is that my draggable marker is the first marker so I want to clear all markers from the map except this one.
Here is the problem:
If I call clear_markers(); in any other way it works fine and the markers are removed from the map, so something like this works:
$('#mybutton').click(function() {
clear_markers();
});
When you drag and drop the green marker though and it's called from the dragend listener it does not work. The markers do get removed but then they immediately get re added again. I know they do get removed because if I put something in the clear_markers() function just after the for loop that kills the script, the markers get removed. But if the script is allowed to continue they are still there meaning they have been removed and then instantly added back on again.
I'm not calling any other code so it seems like a bug with the api to me. Does anyone have any ideas?
Here is a working example showing the problem:
https://tinker.io/64b68/1
Remove the markerClusterer. It is adding the markers back in and you aren't using it.
Update:
Since you need to keep it, if you want the markers to not be displayed, you need to remove them from the markerClusterer:
markerCluster.clearMarkers();
(but you will need to make it global to use it that way)
Your calling the eventListener the right way, just not in the right place in your code. I added a couple of alerts in your eventListener to see what was going on and if you see on the second alert, the markers are actually cleared - but once the alert box is closed the markers reappear. Try it yourself:
google.maps.event.addListener(marker_0, "dragend", function() {
alert("before calling clear_markers()");
clear_markers();
alert("markers should be cleared");
});
This means that once javascript runs into your "dragend" event listener, it will execute the code inside - but then it will go through the rest of the code as well and hence the markers get populated on the map again. You can fix this issue by adding your event listener to the end of your initialize() function after var markerCluster = new MarkerClusterer(map, markers, clusterOptions);.
text in italics is the wrong explanation, refer to the response below for the correct solution
/---------------------------------------------------------------------------------------------/
Disregarding my previous answer, allow me to re-edit. Again, you are calling the eventListener the right way. You will just need to add the following piece of code in the listener function to make sure the markers do not show up.
google.maps.event.addListener(marker_0, "dragend", function() {
clear_markers();
markerCluster.setMap(null);
});
It seems initiating the markerCluster overrides your clear function on the markers. So you will also need to clear the markerCluster from your map as well. Apologies for misguiding you in my previous response, markerCluster is a new concept to me as well.

Google Maps API v3, how to change marker icon when clicked

How can I change a marker icon when a marker is clicked (on a click event) and return it back to a normal icon when another marker is clicked?
Just in any case anyone wants to see an example of keeping track of the previous marker in a global variable like Kasper mentioned, here is what I did:
google.maps.event.addListener(marker,'click',function() {
if (selectedMarker) {
selectedMarker.setIcon(normalIcon);
}
marker.setIcon(selectedIcon);
selectedMarker = marker;
});
(after setting selectedMarker as a global variable)
I haven't tested this code, so there may be a typos or bugs, but it should give you the idea.
First, define a callback to set all markers to the normal icon (to reset any previously clicked markers) and set the current clicked marker's icon to the selected icon:
var markerCallback = function() {
for (var i=0; i<arrayOfMarkers.length; i++) {
arrayOfMarkers[i].setIcon(normalIcon);
}
this.setIcon(selectedIcon);
}
Then, assign the callback to the click event on each marker like so:
google.maps.event.addListener(marker, 'click', markerCallback);
There are certainly some code improvements that could be made. For example, you might not want normalIcon, selectedIcon, and arrayOfMarkers to be global variables the way the code above assumes they are. And if you have a lot of markers, you probably want to instead keep track of the previously selected marker rather than having a for loop reset the icon on every one of them.
But like I said, this should give you the idea.

add event handler an element inside a info window google maps v3

hi I'm trying to add to button inside an info window an event i tried like this
var infoWindow = new google.maps.InfoWindow({
content: '<div></br><span class="formatText">Ubicacion del Marcador: </span>' + event.latLng.toString()
+ '</br> <input type="button" id="btnPrueba" value="prueba"/></div>'
});
google.maps.event.addListener(marker, 'click', function () {
infoWindow.open(map, this);
google.maps.event.addDomListener(document.getElementById('btnPrueba'), 'click', removeMarker);
});
function removeMarker(){
alert('it works');
}
What am i doing wrong? or it's another way to do this?. Thanks
Edit
I'm also tried with jquery like this but although the event it's get by the function the alert doesn't show. When i do the debug with chrome it's works :(
google.maps.event.addListener(marker, 'click', function () {
infoWindow.open(map, this);
$("#btnPrueba").click(function () {
alert('funciona');
});
});
Try the "onclick" attribute for the button.
'<input type="button" id="btnPrueba" value="prueba" onclick="removeMarker()"/>'
Calling a global function like #DeeV's shown really does seem like the straightest shot at this (except for dirtying the global namespace a smidge which is looked down on these days). jQuery event delegation does work without any additional setTimeout gymnastics but feels like a heavier function call stack to accomplish the same goal. e.g.
$("#myMapContainer").on("click", "#btnPrueba", function() {alert "it works";});
However, sticking with the global approach, on top of #DeeV's answer, often the trick is getting some contextual values that you can act upon in that event handler:
one way is embedding parameter values to the function call in the
InfoWindow content string
along those lines, as you generate each Marker, push
it's reference to an array (also necessarily global) and thereby facilitate
Marker API calls later in the handler (e.g. setIcon(), etc.)
e.g. JS Pseudocode
var myMarkerArray = [];
function removeMarker(markerIndex) {
myMarkerArray[markerIndex].setMap(null);
}
for(int i=0; i<myLocationData.length; i++) {
var marker = new google.maps.Marker({...});
myMarkerArray.push(marker);
var popup = new google.maps.InfoWindow({ content: '<input type="button" id="btnPrueba" value="prueba" onclick="removeMarker('+i+')"/>' });
}
My workaround was to use a short timeout.
var infoWindow = ... (as in your question) ...
infoWindow.open(...);
setTimeout(function(){
$('#btnPrueba').on('click', function(e){
alert("It works at last!");
});
},50); //Wait for 0.05s
When I didn't use the setTimeout wrapper it did not work. Even though setContent() and open() had already been called. I assume this means the creation is done asynchronously.
NOTE: the "50" is a magic number, so potentially brittle.
NOTE: using the following also did not work for me, which I still find strange and cannot explain:
$('#btnPrueba').on('click', document, function(e){
alert("No luck...");
});

Categories

Resources