Pass event and this objects to function in different scope - javascript

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>';

Related

Variable Scope in Google Maps API and Angular 1

So I have a Google Maps API event listener for on click the map. But I don't think the variable scope is working.
google.maps.event.addListener(map, 'click', function (event) {
$scope.closeBox();
});
$scope.closeBox = function () {
$scope.showBox = false;
}
If I have $scope.showBox = true on the map and click the map it doesn't close. $scope.showBox is an ng-class that shows/hides the information box.
I just added a $scope.$apply() call and it worked

How to get click location from custom event handler Leaflet

I'm trying to write a custom event handler for CTRL + click in Leaflet. My problem is that the click location given by the map is different from the click location in the event handler, e.g. LatLng(51.49174, -0.11639) from the map click becomes LatLng(51.50938, -0.126) in the handler. The click locations match exactly if the map is the only thing on the page. Adding some other div elements above the map (like an <h1> title) makes the clicks not match. Panning the map also makes the click locations not match.
I'm wondering if I attached my L.DomEvent.on() correctly. Following the Leaflet Handlers tutorial, my code looks like
L.CtrlClickHandler = L.Handler.extend({
addHooks: function() {
L.DomEvent.on(document, 'click', this._captureClick, this);
},
removeHooks: function() {
L.DomEvent.off(document, 'click', this._captureClick, this);
},
_captureClick: function(event) {
if (event.ctrlKey) {
console.log('control click registered at layer '
+ map.layerPointToLatLng(new L.point(event.layerX, event.layerY)));
}
}
});
// add this to all maps
L.Map.addInitHook('addHandler', 'ctrlClick', L.CtrlClickHandler);
Here's a live example on JSFiddle.
I'm using Leaflet 0.7.7 due to some other dependencies in my code. Upgrading to Leaflet 1.0.1 makes it match better (e.g., LatLng(51.49868, -0.1018) vs. LatLng(51.4987, -0.1018)) but the two locations still are not exactly the same.
Am I attaching the L.DomEvent to the correct thing? Should that be attached to the map div somehow, as opposed to document?
Edit: Thanks to #AlexParij for the suggestion. I realized that panning the map also makes the clicks not match, with or without div elements above the map. This happens for Leaflet 1.0.1 as well as 0.7.7. I've tried every combination I can think of, combining different event locations (event.layerX, event.pageX, event.clientX, event.offsetX, event.screenX, and event.x) with projection methods layerPointToLatLng and unproject but none of them match the map click. Now I'm really confused... Fiddle with these different options and Leaflet 1.0.1: https://jsfiddle.net/c4tkyewz/
TL; DR: use map.mouseEventToLatLng() in a custom handler.
#AlexParij was correct; I was not using the correct definition of the layer points and container points. Inside the handler, event is different from Leaflet's internal mouse event (where the location is available from e.latlng).
I looked through Leaflet's core to find the answer. Getting the location from event requires taking the Mouse Event -> Container Point -> Layer Point -> latLng. Thankfully, the Leaflet developers already programmed a nice function for this: mouseEventToLatLng().
/*
* This is a custom handler to check if someone has control clicked
* the map and print the location of the click
*/
L.CtrlClickHandler = L.Handler.extend({
addHooks: function() {
L.DomEvent.on(document, 'click', this._captureClick, this);
},
removeHooks: function() {
L.DomEvent.off(document, 'click', this._captureClick, this);
},
_captureClick: function(event) {
if (event.ctrlKey) {
// translate mouse event to lat/lng (note: `mouseEventToLatLng()`
// calls Leaflet's `mouseEventToContainerPoint()` followed by
// `containerPointToLayerPoint()` and finally `layerPointToLatLng()`)
var latlng = map.mouseEventToLatLng(event);
console.log('Handler detected CTRL + click at ' + latlng);
}
}
});
// add this to all maps
L.Map.addInitHook('addHandler', 'ctrlClick', L.CtrlClickHandler);
Live example with Leaflet 1.0.1: https://jsfiddle.net/c4tkyewz/1/
Also tested with Leaflet 0.7.7.
As a bonus, to access the CTRL key directly from Leaflet's native handling of the click event map.on('click', function(e) {});, use e.originalEvent.ctrlKey.

Hyperlink to open marker infowindow on Google Map

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>

Close Infobox when clicking on the map

I'm using the Infobox plugin for Google Maps V3 API (http://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/docs/reference.html)
Is there anyway too close the infobox when the user clicks outside the infobox like on the map?
it's actually way easier if you have your infowindow as a global variable, or at least hold one variable that represents the single infobox you want to add at a convenient place.
edit: just to clarify: it should not be window.myInfoBox for example. With global I mean a single point where you reference your infobox
google.maps.event.addListener(map, 'click', function() {
if(infowindow){
infowindow.close();
}
});
that's all :-)
You will want to use addListener()
http://code.google.com/apis/maps/documentation/javascript/events.html#EventListeners
You can adapt the code found here:
google.maps.event.addListener(_point.popup, 'domready', function() {
//Have to put this within the domready or else it can't find the div element (it's null until the InfoBox is opened)
$(_point.popup.div_).hover(
function() {
//This is called when the mouse enters the element
},
function() {
//This is called when the mouse leaves the element
_point.popup.close();
}
);
});
Src:
Google Maps API v3 Event mouseover with InfoBox plugin
You can detect a map click with this:
google.maps.event.addListener(map, 'click', function() {
});
Infobox API:
http://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/docs/reference.html
This maybe useful for you..
var inside = false;
$('#foo').live('mouseenter',function(){
inside=true;
}).live('mouseleave', function(){
inside=false;
});
$("body").mouseup(function(){
if(!inside) $('#foo').remove();
});

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