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/
Related
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).
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 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 have "N" markers on an Openlayers map and I need to "label" these markers (Meaning: Put a text in/on them)
I have tried several ways but still couldn't achieve what I need.
My JS code snippet (Removed some irrevelant stuff from the code):
function getWeatherInfo(){
if(wheatherOfCitiesMarkerLayer == null){
wheatherOfCitiesMarkerLayer = new OpenLayers.Layer.Markers("WeatherMarkerLayer");
map.addLayer(wheatherOfCitiesMarkerLayer);
}
$.getJSON(qryPointResultListForAllCities(), function(data) {
if(data!= null){
var size = new OpenLayers.Size(60,45);
var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
for(var i = 0; i < data.pr.length; i ++){
// Create markers by using the returned data from the server
//...
//... Removed some irrevelant stuff
var lat = data.pr[i].la;
var lon = data.pr[i].lo;
var infos = data.pr[i].info.infos;
var infop = data.pr[i].info.infop;
var infocc = data.pr[i].info.infocc;
var icon = new OpenLayers.Icon('my_marker_img.png',size,offset);
location = new OpenLayers.LonLat(lon, lat);
location = transformFromWGS1984ToSphericalMercator(location.clone());
marker = new OpenLayers.Marker(location,icon.clone());
wheatherOfCitiesMarkerLayer.addMarker(marker);
}
}
}
}
What I need to do is put a label or text in/on each marker on the map.
Since you are taking marker data from server anyway, what you can do is, create a layer in a map file with just the label class defined and add it on your marker layer as a overlay.
Hope this helps.
Instead of adding text (or label) to a marker, you can add a marker to a label.
This is done by creating a new text file with the location, title, description and path to your icon (not required, it will use the default if none is set). For example,
if you want to place two markers on the map, the text file may look like this
point title description icon
10,99 An labeled marker with default image
12,34 Another marker This is my label text http://example.com/marker.png
Please note that there should be tabs between the names and parameters, not spaces. There is also a tab at the end of the second line where no icon is given.
Save this file somewhere on your site and put this code where your layers are being initialized.
var textl = new OpenLayers.Layer.Text("text", {location : "data_dile.txt"});
map.addLayer(textl);
The text file may be created dynamically though server-side languages, such as PHP.
There is an online example here.
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);
}
};
})