events.register is auto-executing the event being registered - javascript

I am trying to attach a Popup for each marker (I am using OpenLayers and OpenStreetMaps for this). Each marker is being registered an event 'click' that will show it's corresponding popup.
However, what it does is to just execute all the popups upon start-up instead of waiting for a given marker click.
There are approximately 1000 markers so I am using this loop to populate the markers and popups (which are hidden when created):
for (var i = 0; i < data.length; i++)
{
if (i == 1) {
var lonLat = new OpenLayers.LonLat(data[i].Lon, data[i].Lat).transform(fromProjection, toProjection);
var zoom = 5;
map.setCenter(lonLat, zoom);
}
var lonLat = new OpenLayers.LonLat(data[i].Lon, data[i].Lat).transform(fromProjection, toProjection);
AddingPopup(lonLat);
AddingMarker(i, lonLat);
And these are my functions for creating both:
function AddingMarker(i, lonLat) {
var marker = new OpenLayers.Marker(lonLat);
markers.addMarker(marker);
marker.events.register('click', marker, PopupsShow(i));
};
function AddingPopup(lonLat) {
var popup = new OpenLayers.Popup("Popup", lonLat, null, "text", true);
map.addPopup(popup);
popup.hide();
};
And this is the function that is being auto-fired for all markers upon execution:
function PopupsShow(i) {
map.popups[i].show();
};
What am I missing here. Why is the PopupsShow function started upon execution and it's not waiting for the marker to be clicked. I've been looking around for answers, but nothing seems to help.
Thanks!

I have figured it out:
We cannot register an event using marker.events.register("click", marker, PopupsShow(i))
Instead we need to call it like this: marker.events.register("click", marker, PopupsShow)
And since we need the i we can call it like this:
marker.events.register("click", marker, function () {
map.popups[i].show();
});

The event handler can actually get an argument (event) which is the idiomatic way of performing this. Also it is considered best to bind the handler to a layer instead of each marker.
markerLayer.events.register('click', marker,
function(event) {
var feature = event.feature;
/* make popup appear */
});
The way to make a popup varies to meet your needs, but usually the popup is created on demand here rather than pregenerating and calling show.

Related

show popups correctly with external hyperlinks in openlayers 4

I have an openlayers map that loads a couple of kml files containing about 120 polygon placemarks each. As they're too many to show a popup for each, I had to create an outside-map menu, so the user can click on any one of these features and see it's info / location.
I use this function to create the outside-map menu, containing all the features:
vEnergeticos.getSource().on('change', function(evt){
var source = evt.target;
if (source.getState() === 'ready') {
var energeticos = source.getFeatures();
for (var i in energeticos) {
var figura = energeticos[i].getGeometry().getExtent();
var myCenter = ol.extent.getCenter(figura);
$("#containerLeft").append("<a href=javascript:showMenuPopup(" + myCenter + "," + energeticos[i].get('ID') + ")>" + energeticos[i].get('name') + "</a><br>");
}
}
});
and then when the user clicks on any of these options, this function is called:
function showMenuPopup(xx, yy, theID){
var myPixel = map.getPixelFromCoordinate([xx, yy]);
var elNombre = "";
var laDescripcion = "";
map.forEachFeatureAtPixel(myPixel, function(feature, layer) {
if (feature.get('ID') == theID){
elNombre = feature.get('name');
laDescripcion = feature.get('description');
}
});
popupTitle.innerHTML = elNombre;
popupContent.innerHTML = laDescripcion;
overlay.setPosition([xx,yy]);
}
This works in some situations, however, when the selected feature is outside of the current map view, the map relocates successfully (overlay.setPosition([xx,yy]);), the popup is shown, but the popup is empty. If the feature is visible when the user clicks from the left menu, then the popup is shown correctly.
Just to be clear enough, imagine you're seeing a map where you can see part of Europe, and then you click on some item located in Canada (using the off-map menu), you'll see the map relocates in Canada, but the popup that is shown is empty. If you click again on that very same off-map link, or any other feature that is visible at that location/zoom view, then the popup is shown correctly.
I tried to use the "moveend (ol.MapEvent)" in order to fix this, so the popup was loaded after the map is relocated, but it didn't work for me. The moveend event is called before the map starts to move using overlay.setPosition([xx,yy]), and I haven't been able to find some other "after-relocation" event that I could use.
I've been struggling with this for many days now, so any help will be really appreciated.
Regards!!
The problem is that the features outside of the current map view are not "AtPixel", so you won't catch them with map.forEachFeatureAtPixel.
I suggest you to avoid passing coordinates to showMenuPopup: you just need the feature id, than you can retrieve the feature's coordinates inside showMenuPopup.
$("#containerLeft").append("<a href=javascript:showMenuPopup('" + energeticos[i].getId() + "')>" + energeticos[i].get('name') + "</a><br>");
Then
function showMenuPopup(featureId){
var feature = vEnergeticos.getSource().getFeatureById(featureId);
var elNombre = feature.get('name');
var laDescripcion = feature.get('description');
var figura = feature.getGeometry().getExtent();
var myCenter = ol.extent.getCenter(figura);
popupTitle.innerHTML = elNombre;
popupContent.innerHTML = laDescripcion;
overlay.setPosition(myCenter);
}

Google Maps V3 - Switching on/off groups of markers

I am currently trying to use Google Maps with a bunch of markers on it (extracted from a JSON data file). I want to be able to group the markers in one of two categories and be able to switch them off or on.
I am up to the point where the map is working, the pointers are showing and the switch buttons are flicking on and off - all that is left now is to add the markers to groups and bind the switch buttons to displaying/hiding the markers on the map.
I know that I can use marker.setVisible(false/true) but I'm not sure how or where to use it.
I am new to using Google Maps API v3 so any direction with this would be much appreciated.
I have setup a fiddle with what I have so far, you can see it here: https://jsfiddle.net/6n25g3n7/4/
You need to make your markers variable been access to your click event.
Code example:
var markers = [];
function addMarkerToMap(map, markerData){
for(var i = 0; i < markerData.length; i++){
// init marker
markers.push(marker); //push to marker's array
}
}
function clickEvent(){
for(var key in markers){
markers[key].setVisible(true/false);
}
}
fiddle: https://jsfiddle.net/6n25g3n7/5/ Sorry about code is a little bit mess.
If you have any question about code, please comment :)
This one has both markers turning on and off. Check the jsfiddle for all the changes. I had to re-structure some of your code.
function createSwitches(markers){
var html = '<div class="switches"><span class="switch-title">Show Me</span></div>';
// ADD YOU SWITCHES HERE!
// Make sure the same order as the google markers
var all_switches = [
{
html: '<span class="whats-on-wrapper"><span data-target="whats-on" class="switch switch-on">Item Group 2</span></span>',
},
{
html: '<span class="stand-wrapper"><span data-target="stand" class="switch switch-on">Item Group 1</span></span>',
}
];
// Add the main bar element
$('.map-container').prepend(html);
// Loop through all your switches and add them
// with the event
for (var i = 0; i < all_switches.length; i++) {
var element = $(all_switches[i]["html"]);
(function(index, element, markers) {
$(element).on('click', function () {
var this_marker = markers[index];
var current = String(this_marker.visible);
var toggle = ( current === "true") ? false : true;
this_marker.setVisible(toggle);
});
})(i, element, markers)
$('.switches').append($(element))
}
// Set the toggle animation
$('.switches .switch').click(function(){
$(this).toggleClass('switch-on');
$(this).toggleClass('switch-off');
});
}
https://jsfiddle.net/6n25g3n7/8/

Open InfoWindow using KeyDown/KeyPress

I'm just wondering if there is a way to open Google Map InfoWindow by keyboard. So far, I can only make it open by click.
I found the following: http://www.visionaustralia.org/digital-access-googlemap
but it only handles the controls and navigation.
$(function(){
//use mapselector="div" if you don't know the map id
var mapSelector = "#map_canvas div";
var attemptInterval = 2;
var maxAttempts = 18;
var mA = 0;
var notYet = true;
var titles = {"pan up":1,"pan down":1,"pan right":1,"pan left":1, "zoom in":1,"zoom out":1,"show street map":1,"show satellite imagery":1};
function addKey(){
mA++;
if(mA > maxAttempts){return;}
$(mapSelector).each(function(index){
var title = this.getAttribute("title")
if(title) title=title.toLowerCase().trim();
if(title in titles){
jqel = $(this);
titles[title] = jqel;
jqel.attr("tabindex","0");
jqel.attr("role","button");
jqel.keydown(function(ev){
if(ev.which==13) {
$(this).trigger("click")
}else if(ev.which==40) {
titles["pan down"].trigger("click");
}else if(ev.which==38) {
titles["pan up"].trigger("click");
}else if(ev.which==37) {
titles["pan left"].trigger("click");
}else if(ev.which==39) {
titles["pan right"].trigger("click");
}else if(ev.which==61 || ev.which == 187) {
titles["zoom in"].trigger("click");
}else if(ev.which==173 || ev.which == 189) {
titles["zoom out"].trigger("click");
}else{
return
}
ev.preventDefault();
});
(function(){
var mo = false;
var bo = jqel.css("border");
var ma = jqel.css("margin");
var bc = jqel.css("background-color");
var op = jqel.css("opacity");
jqel.mouseover(function(){mo=true;});
jqel.mouseout(function(){mo=false;});
jqel.focus(function(){
if(mo)return;
$(this).css({"border":"2px solid blue","margin":"-2px","background-color":"transparent","opacity":"1"});
});
jqel.blur(function(){$(this).css({"border":bo,"margin":ma,"background-color":bc,"opacity":op});});
notYet = false;
})();
}
});
if(notYet){setTimeout(addKey,attemptInterval*1000);}
}
addKey();
});
It works by getting the title of the controls so I tried to add a title to the marker and adding it to the titles array but it doesn't work.
I'm quite new with Google Maps API and JavaScript, any suggestions on where to get started? Thanks!
I'm a bit rusty on my Google Maps API knowledge, but if I remember correctly, the API does indeed give a way to attach a listener to your marker. However, it does not work for keypress events, as you have noticed. For completeness, the basic syntax is this:
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
});
The addListener function accepts three parameters:
The item on which to attach the event (the marker in this case)
The type of event to listen for
The lamba or function to execute when the event occurs (opening an infoWindow)
The important bit here is the second parameter, the event for which to listen. These are not actual DOM events, but Google's own abstracted events (for better cross-browser support) and thus only a select amount is available - there is no keypress event.
JavaScript, on the other hand, does recognize several key events. I'm cowardly assuming you have jQuery available (from your posted example code), so you could exploit jQuery's keypress function to capture, well, a key press and opening an infoWindow with that:
$(document).keypress(function (event) {
switch (event.which) {
case 102:
// lowercase f
infowindow.open(map, marker);
break;
}
});
This should open your defined infoWindow on your defined marker position. Note that this example does only contain code to open one infoWindow for one marker. But it should give you a general idea.
See the following Fiddle I made for a very rough and simple example, using the 'f' key to open your infoWindow (after clicking in the "result" frame).

Clicking a polygon using Google Maps API 3 - Need to change to MouseOver (Geoxmlv3 & KML Layer)

I have a Google Maps (API 3) running a custom KML (geoxml3) with polygons containing titles and descriptions.
It all works fine, however I need to change the polygon click which reveals the infowindow to work on hover instead. It is easy enough to create a mouseover listener which runs the click function, however I need the click to run another function, so the click function would get overwritten using this method.
How can I find/copy the code that runs for the polygon click function and apply it to onmouseover instead? Is this possible?
Update: I found this section in the geoxmlv3.js file:
google.maps.event.addListener(gObj, 'click', function (e) {
var iW = this.infoWindow;
iW.close();
iW.setOptions(this.infoWindowOptions);
if (e && e.latLng) iW.setPosition(e.latLng);
else if (this.bounds) iW.setPosition(this.bounds.getCenter());
iW.setContent("<div id='geoxml3_infowindow'>" + iW.getContent() + "</div>");
google.maps.event.addListenerOnce(iW, "domready", function () {
var node = document.getElementById('geoxml3_infowindow');
var imgArray = node.getElementsByTagName('img');
for (var i = 0; i < imgArray.length; i++) {
var imgUrlIE = imgArray[i].getAttribute("src");
var imgUrl = cleanURL(doc.baseDir, imgUrlIE);
if (kmzMetaData[imgUrl]) {
imgArray[i].src = kmzMetaData[imgUrl].dataUrl;
} else if (kmzMetaData[imgUrlIE]) {
imgArray[i].src = kmzMetaData[imgUrlIE].dataUrl;
}
}
});
iW.open(this.map, this.bounds ? null : this);
});
I have tried changing the 'click' event to 'mouseover' but that causes no mouseover or click to work
Here's the solution (after much trial and error!)
google.maps.event.addListener(poly,"mouseover",function(e) {
var iW = this.infoWindow;
iW.close();
iW.setOptions(this.infoWindowOptions);
if (e && e.latLng) iW.setPosition(e.latLng);
else if (this.bounds) iW.setPosition(this.bounds.getCenter());
iW.setContent("<div id='geoxml3_infowindow'>"+iW.getContent()+"</div>");
iW.open(this.map, this.bounds ? null : this);
});
Then just change your click function to something else. Remember to also set your mouseout function to close the infowindow too

How to avoid double click on a marker in google map?

I created a pop up box.When I single click on a marker on google map. The popup shows with a cancel button.Clicking on cancel button just hide this popup box.My problem is when I double clicked on this marker the popup boxes are generating and overlap one by one.So Cancel is not working. How to avoid this ?
Sample Code:
makeInfoWindowEvent(map, marker);
function makeInfoWindowEvent(map, marker) {
google.maps.event.addListener(marker, 'click', function() {
var markerPopup = document.createElement("div");
markerPopup.id = 'markerPopup';
markerPopup.className = 'markerPopup';
markerPopup.innerHTML = "This is a test message";
var cancel = document.createElement("div");
cancel.id = 'cancel';
cancel.className = 'cancel';
markerPopup.appendChild(cancel);
cancel.onclick= function () {
var divbg = document.getElementById('markerPopup');
divbg.style.visibility = "hidden";
}
document.getElementById('map-canvas').appendChild(markerPopup);
});
}
The events won't fire at the same time, so you can check for the presence of a markerPopup and return early if it is already there.
if (document.getElementById("markerPopup")) {
// they must have double clicked, so do nothing
return;
}
If you need more than one popup on the map at a time, then you will need to assign unique ids to each one that get created. You could then attach those ids as a property on the button, which would give a way to know which one to kill.

Categories

Resources