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).
Related
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);
}
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
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.
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.
I'm working on a Map app and I'm having trouble getting marker animated at a time. I'd like to have it so that when a new marker is clicked, the other's animation is removed. I'm a js noob and have been wracking my head. As of now, I have the markers in an array so that I can remove the animation ..but how can I remove the animation of every other marker when setting the animation for another one?..below is the code I've been playing with
for (i in markersArray) {
if (markersArray[i].getAnimation() != null) {
markersArray[i].setAnimation(null);
}
if (marker[i].getAnimation() != null) {
marker[i].setAnimation(null);
} else {
marker[i].setAnimation(google.maps.Animation.BOUNCE);
}
}
The code that you posted seems fine and if it works for you, great. However, if you only want one marker animated at a time, then it might be more efficient, and easier, to just keep a variable of the last animated marker. For example, in your click event or when you add a marker, you could do something like this:
previous_animation.setAnimation(null);
new_marker.setAnimation(google.maps.Animation.BOUNCE);
previous_animation = new_marker;
I ended up coming up with the following code after assigning a unique id to each marker...worked like a charm
for( var i in marker ){
marker[i].setAnimation(null);
if( marker[i].id == item.id ) marker[i].setAnimation(google.maps.Animation.BOUNCE);
}
var new_marker = this;
if(prev_marker) {
if (prev_marker.getAnimation() != null) {
prev_marker.setAnimation(null);
new_marker.setAnimation(google.maps.Animation.BOUNCE);
prev_marker = new_marker;
}
} else {
new_marker.setAnimation(google.maps.Animation.BOUNCE);
prev_marker = new_marker;
}
i prefer #Nick Canzoneri style. Modified it a bit
This is what that i got working, I have my markers in a global variable. Which keeps my markers accessible at all time.
google.maps.event.addListener(marker, 'click', function(event) {
$("input#pickup-"+ marker.id +"").prop('checked', true);
for (var i = window.markers.length - 1; i >= 0; i--) {
window.markers[i].setAnimation();
if(window.markers[i].id === this.id) {
marker.setAnimation(google.maps.Animation.BOUNCE);
}
};
})