A wee bit out of my depth here, I hope someone can help me resolve this...
I have a Google map which loads data from an array and also populates a sidebar list of the items.
A click on the sidebar item opens the corresponding infowindow as expected o.k.
When I mouseenter a sidebar item it pans to if necessary and highlights the corresponding marker (and closes any infowindow currently open ).
(.locs is the sidebar container, .loc is an item)
$(document).on("mouseenter",".loc",function() {
var thisloc = $(this).data("locid");
for(var i=0; i<markers.length; i++) {
if(markers[i].locid == thisloc) { //get the latlong
if(lastinfowindow instanceof google.maps.InfoWindow) lastinfowindow.close();
map.panTo(markers[i].getPosition());
markers[i].setIcon('../mapIcons/mini-white.png');
}
}
});
This bit works fine as I'm just setting a fixed image.
However, when I mouseleave the marker fails to revert back to its original state.
If I use the setIcon for a specic image it works fine, but I want to refer back to the original icon from the dataset item.
markers[i].setIcon("currmark");
currmark is the var I used to hold the original icon.
$(document).on("mouseleave",".loc",function() {
var thisloc = $(this).data("locid");
var currmark = getIcon("mapData.type");
for(var i=0; i<markers.length; i++) {
if(markers[i].locid == thisloc) { //get the latlong
map.panTo(markers[i].getPosition());
markers[i].setIcon("currmark");
}
}
});
An alert set on 'currmark', the var I used to hold the original icon, shows only the last icon set by the mouseenter setIcon.
This seems to idicate to me that the original icon from the dataset (mapdata.type) has been forgotten / replaced by the last setting applied to markers[i].
I think I need to reaccess the dataset to remind the var of the original state when I set
var currmark = getIcon("mapData.type");
Some added info....
I'm using a utility function that translates a given 'type' in the dataset to an icon, hence the getIcon(type) function.
function getIcon(type) {
switch(type) {
case "bar": return "../mapIcons/mini-blue.png";
case "restaurant": return "../mapIcons/mini-red.png";
case "cafe": return "../mapIcons/mini-yellow.png";
default: return "../mapIcons/mini-white.png";
}
}
An example of a data entry...
var data = [
{address:'Rua Calheta',detail:'Restaurant',title:'Dolphin',type:'restaurant',ico:'red',lat:"37.08570947136275",long:"-8.731633722782135"}
];
I hope I've explained this half sensibly. Can anyone assist me, as I was dead chuffed I'd got this far.
2nd Additional Info for Beetroot showing how my marker and sidebar are initially setup....
data.forEach(function(mapData,idx) {
var marker = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(mapData.lat,mapData.long),
title: mapData.title,
icon: getIcon(mapData.type)
});
var link=('<a href="#"' + mapData.title +'">');
var contentHtml = "<div id='iw' class='iw2'><h3>" + link + mapData.title+"</a></h3>" + mapData.detail+"<br>"+mapData.address+"</div>";
var infowindow = new google.maps.InfoWindow({
content: contentHtml
});
google.maps.event.addListener(marker, 'click', function() {
if(lastinfowindow instanceof google.maps.InfoWindow) lastinfowindow.close();
marker.infowindow.open(map, marker);
lastinfowindow = marker.infowindow;
});
marker.locid = idx+1;
marker.infowindow = infowindow;
markers[markers.length] = marker;
var spot=('<img src="' + (getIcon(mapData.type)) + '" />');
var sideHtml = '<p class="loc" data-locid="'+marker.locid+'">'+spot+mapData.title+'</p>';
$("#locs").append(sideHtml);
if(markers.length == data.length) doFilter();
});
EDIT 02/07
The complete source after incorporating Beetroot-Beetroot's slick changes. Here in its entirety as I'm now vary aware that he can only help if he has the whole picture!
Now attempting to debug after learning I'm not such a smartass.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false& style=feature:all|element:labels|visibility:off">
</script>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript">
var map;
var markers = [];
var lastinfowindow;
var locIndex;
//Credit: MDN
if ( !Array.prototype.forEach ) {
Array.prototype.forEach = function(fn, scope) {
for(var i = 0, len = this.length; i < len; ++i) {
fn.call(scope, this[i], i, this);
}
}
}
//my data ~ cutdown and local for testing
var data = [
{address:'Rua Calheta',detail:'Restaurant',title:'Dolphin',type:'restaurant',icotyp:'red',lat:"37.08570947136275",long:"-8.731633722782135"},
{address:'Rua Calheta',detail:'Cafe',title:'Cafe Calheta',type:'cafe',icotyp:'yellow',lat:"37.0858150589029",long:"-8.731550574302673"},
{address:'Rua Calheta',detail:'Bar',title:'Kellys',type:'bar',icotyp:'red',lat:"37.08583217639933",long:"-8.731239438056945"},
{address:'Rua 2nd Abril',detail:'Bar',title:'Godots',type:'bar',icotyp:'blue',lat:"37.08602046860496",long:"-8.731470108032226"}
];
// translate data type: to icon
function getIcon(type) {
switch(type) {
case "bar": return "../mapIcons/mini-blue.png";
case "restaurant": return "../mapIcons/mini-red.png";
case "cafe": return "../mapIcons/mini-yellow.png";
default: return "../mapIcons/mini-white.png";
}
}
function initialize() {
var latlng = new google.maps.LatLng(37.08597981464561, -8.730670809745788);
var myOptions = {
zoom: 18,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"),myOptions);
// revised beetroot-beetroot 'loop' function to set markers and sidebar at the same time
var $locs = $("#locs");//Used repeatedly inside the loop.
$.each(data, function(idx, mapData) {
//Note: critical assignment of the new marker as a property of `mapData`.
mapData.marker = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(mapData.lat,mapData.long),
title: mapData.title,
icon: getIcon(mapData.type)
});
var link = '' + mapData.title + '';
var contentHtml = "<div id='iw' class='iw2'><h3>" + link + "</h3>" + mapData.detail + "<br>" + mapData.address + "</div>";
//What was `marker` must now be referred to as `mapData.marker`
mapData.marker.infowindow = new google.maps.InfoWindow({
content: contentHtml
});
google.maps.event.addListener(mapData.marker, 'click', function() {
if(lastinfowindow && lastinfowindow.close) lastinfowindow.close();
//`this` refers back to the clicked element; the appropriate marker
this.infowindow.open(map, this);
lastinfowindow = this.infowindow;
});
var spot = '<img src="' + (getIcon(mapData.type)) + '" />';
//Here, it's convenient to create what was `sideitem` as a jQuery object, so we can apply several jquery methods (without making an assignment).
$('<p class="loc" />')
.html(spot + mapData.title)
.appendTo($locs)
.data('mapData', mapData);//<<<<<<<< critical
});
doFilter(); //It should be possible to execute this statement when the loop is finished.
$(document).on("mouseenter", ".loc", function() {
if(lastinfowindow && lastinfowindow.close) lastinfowindow.close();
var mapData = $(this).data("mapData");
map.panTo(mapData.marker.getPosition());//<<<< direct reference to the marker avoids the need to loop.
mapData.marker.setIcon(getIcon(''));//get the default icon.
}).on("mouseleave", ".loc", function() {
var mapData = $(this).data("mapData");
mapData.marker.setIcon(getIcon(mapData.type));
}).on("click",".loc",function() {
var mapData = $(this).data("mapData");
mapData.marker.infowindow.open(map, mapData.marker);
lastinfowindow = mapData.marker.infowindow;
});
/*
Run on every change to any of the checkboxes
*/
function doFilter() {
if(lastinfowindow && lastinfowindow.close) lastinfowindow.close(); //Close last info windows if still open and new filter applied
if(!locIndex) {
locIndex = {};
//I reverse index markers to figure out the position of loc to marker index
for(var x=0, len=markers.length; x<len; x++) {
locIndex[markers[x].locid] = x;
}
}
//what's checked?
var checked = $("input[type=checkbox]:checked");
var selTypes = [];
for(var i=0, len=checked.length; i<len; i++) {
selTypes.push($(checked[i]).val());
}
for(var i=0, len=data.length; i<len; i++) {
var sideDom = "p.loc[data-locid="+(i+1)+"]";
//Only hide if length != 0
if(checked.length !=0 && selTypes.indexOf(data[i].type) < 0) {
$(sideDom).hide();
markers[locIndex[i+1]].setVisible(false);
} else {
$(sideDom).show();
markers[locIndex[i+1]].setVisible(true);
}
}
}
$(document).on("click", "input[type=checkbox]", doFilter);
}
</script>
<style type="text/css">
#container {width:920px;height:500px; margin-left:auto;margin-right:auto;}
#map_canvas {width: 700px; height: 500px;float:left;border:1px gray solid;margin-right:10px;}
/* sidebar styling */
#locs {margin-top: 0px;padding-top: 0px;margin-left: 5px;height: 500px;width:200px;overflow-y: auto;overflow-x: hidden;}
#locs img {float:left;padding-right:5px;}
.loc {border: 0;width: 200px;padding: 2px;cursor: pointer;margin:0;text-transform:uppercase;font-family:Arial, Helvetica, sans-serif;font-size:0.90em;}
/* checkbox styling */
#form {margin-top: 0px;padding-top: 0px;height: 29px;}
.label {width: 32.5%;margin: 0;padding: 4px 0 4px 4px;display: inline-block;font-family: "Trebuchet MS", Verdana, Arial, sans-serif;text-transform: uppercase;font-size: 0.75em;font-weight: bold;}
.red {color:white;background-color:red;}
.yellow {color:yellow;background-color:black;}
.blue {color:white;background-color:blue;}
/* Map info styling */
#map_canvas div#iw {width:250px;height:65px;overflow:hidden;}
#map_canvas h3 {font-size:1em; margin:0; padding:3px;}
#map_canvas .iw2 a {text-decoration:none;border-bottom:thin blue dashed;}
#map_canvas .iw2 a:hover {text-decoration:none;border-bottom:thin red solid;}
</style>
</head>
<body onLoad="initialize()">
<div id="container">
<div id="map_canvas"></div> <!-- map //-->
<div id="locs"></div> <!-- sidebar //-->
<div id="form" style="margin:0;padding:0;border:thin gray solid;width:910px">
<span class="label blue"><input type="checkbox" name="bars" value="bar">Bars</span>
<span class="label yellow"><input type="checkbox" name="cafes" value="cafe">Cafes</span>
<span class="label red"><input type="checkbox" name="restaurants" value="restaurant">Restaurants</span>
</div>
</div> <!-- end of container //-->
</body>
</html>
EDIT 3 - 03/07 - Revised initialise marker / sidebar
// BB - revised each loop function to set markers and sidebar at the same time
var $locs = $("#locs");//Used repeatedly inside the loop.
$.each(data, function(idx, mapData) {
//BB - Note: critical assignment of the new marker as a property of `mapData`.
mapData.marker = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(mapData.lat,mapData.long),
title: mapData.title,
icon: getIcon(mapData.type)
});
var link = '' + mapData.title + '';
var contentHtml = "<div id='iw' class='iw2'><h3>" + link + "</h3>" + mapData.detail + "<br>" + mapData.address + "</div>";
//What was `marker` must now be referred to as `mapData.marker`
mapData.marker.infowindow = new google.maps.InfoWindow({
content: contentHtml
});
google.maps.event.addListener(mapData.marker, 'click', function() {
if(lastinfowindow && lastinfowindow.close) lastinfowindow.close();
//BB - `this` refers back to the clicked element; the appropriate marker
this.infowindow.open(map, this);
lastinfowindow = this.infowindow;
});
//BB - Here, it's convenient to create what was `sideitem` as a jQuery object, so we can apply several jquery methods (without making an assignment).
var spot = '<img src="' + (getIcon(mapData.type)) + '" />';
$('<p class="loc" />')
.html(spot + mapData.title)
.appendTo($locs)
.data('mapData', mapData);//<<<<<<<< critical
//BB - At the bottom of the $.each() loop in initialize(), create and populate one array per category, as properties of markers ://
if(!markers[mapData.type]) markers[mapData.type] = [];
markers[mapData.type].push(mapData.marker);
});
// End of for/each loop
EDIT 4 - 07/07 - Revised full script for comment
<script type="text/javascript">
var map;
//var markers = [];
//object, not array. BB
var markers = {};
var lastinfowindow;
//var locIndex;
//Credit: MDN
if ( !Array.prototype.forEach ) {
Array.prototype.forEach = function(fn, scope) {
for(var i = 0, len = this.length; i < len; ++i) {
fn.call(scope, this[i], i, this);
}
}
}
//my data ~ cutdown and local for testing
var data = [
{address:'Rua Calheta',detail:'South African & Portuguese Restaurant',title:'Dolphin',type:'restaurant',lat:"37.08570947136275",long:"-8.731633722782135"},
{address:'Rua Calheta',detail:'Poruguese Cafe / Bar',title:'Cafe Calheta',type:'cafe',lat:"37.0858150589029",long:"-8.731550574302673"},
{address:'Rua Calheta',detail:'English Bar',title:'Kellys',type:'bar',lat:"37.08583217639933",long:"-8.731239438056945"},
{address:'Rua 2nd Abril',detail:'English Bar',title:'Godots',type:'bar',lat:"37.08602046860496",long:"-8.731470108032226"},
{address:'Rua 2nd Abril',detail:'Chinese Restaurant',title:'Royal Garden',type:'restaurant',lat:"37.086164896968405",long:"-8.731738328933715"},
{address:'Rua 2nd Abril',detail:'English Bar',title:'Clives',type:'bar',lat:"37.086125",long:"-8.731374"},
{address:'Rua 2nd Abril',detail:'English Restaurant',title:'The Lime Tree',type:'restaurant',lat:"37.086125877750365",long:"-8.731588125228881"},
{address:'Praia da Luz',detail:'Portuguese Restaurant',title:'Alloro',type:'restaurant',lat:"37.09158",long:"-8.724850"},
{address:'Rua Calheta',detail:'English Cafe / Bistro',title:'Jakes',type:'cafe',lat:"37.0862601125538",long:"-8.732671737670898"},
{address:'Av dos Pescadores',detail:'English & Portuguese Restaurant',title:'Chaplins',type:'restaurant',lat:"37.08550480361006",long:"-8.730005621910095"},
{address:'Av dos Pescadores',detail:'English & Portuguese Restaurant',title:'Atlantico',type:'restaurant',lat:"37.085425634814705",long:"-8.729941248893737"},
{address:'Av dos Pescadores',detail:'Indian Restaurant',title:'Saffron',type:'restaurant',lat:"37.08534432623613",long:"-8.729884922504425"},
{address:'Av dos Pescadores',detail:'Indian Restaurant',title:'Pashmina',type:'restaurant',lat:"37.08526729697597",long:"-8.729839324951171"},
{address:'Rua Calheta',detail:'English Bar',title:'The Bull',type:'bar',lat:"37.085652442494",long:"-8.73089075088501"},
{address:'Av dos Pescadores',detail:'English & Portuguese Restaurant',title:'Galley',type:'restaurant',lat:"37.08571577732778",long:"-8.729227781295776"},
{address:'Av dos Pescadores',detail:'English & Portuguese Bar',title:'Carlos',type:'bar',lat:"37.0856306176238",long:"-8.729227781295776"}
];
// translate data.type: to icon
function getIcon(type) {
switch(type) {
case "bar": return "../mapIcons/mini-blue.png";
case "restaurant": return "../mapIcons/mini-red.png";
case "cafe": return "../mapIcons/mini-green.png";
default: return "../mapIcons/mini-white.png"; // used as current selection indicator
//default: return "../mapIcons/marker-yellow-dot.png"; // will use instead of white later
}
}
function initialize() {
var latlng = new google.maps.LatLng(37.08597981464561, -8.730670809745788);
var myOptions = {
zoom: 17,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"),myOptions);
//-----------------------------------------------------------------------------------------
/*
Start of for/each loop
*/
var $locs = $("#locs");//Used repeatedly inside the loop.
$.each(data, function(idx, mapData) {
//BB - Note: critical assignment of the new marker as a property of `mapData`.
// section 1 - Marker construct
mapData.marker = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(mapData.lat,mapData.long),
title: mapData.title,
icon: getIcon(mapData.type)
});
// section 1 end
// section 2 - Infowindow construct
var link = '' + mapData.title + ''; // make a link of name
var contentHtml = "<div id='iw' class='iw2'><h3>" + link + "</h3>" + mapData.detail + "</div>"; // style info window and add detail
// What was `marker` must now be referred to as `mapData.marker`
mapData.marker.infowindow = new google.maps.InfoWindow({
content: contentHtml,
});
// section 2 end
// section 3 - Map marker click function
google.maps.event.addListener(mapData.marker, 'click', function() {
if(lastinfowindow && lastinfowindow.close) lastinfowindow.close(); // close any open infowindows
map.setZoom(18); // zoom in
map.setCenter(mapData.marker.getPosition());// centre on selection
//BB - `this` refers back to the clicked element; the appropriate marker
this.infowindow.open(map, this); // open infowindow
lastinfowindow = this.infowindow; // remember for closing this infowindow, if still open when selection changes
});
// section 3 end
// section 4 - Display Map marker and sidebar item
// BB - Here, it's convenient to create what was `sideitem` as a jQuery object, so we can apply several jquery methods (without making an assignment).
var spot = '<img src="' + (getIcon(mapData.type)) + '" />'; // sidebar copy of marker for display
$('<p class="loc" />')
.html(spot + mapData.title) // sidebar icon and name
.appendTo($locs) // add to sidebar container
.data('mapData', mapData); //<<<<<<<< critical
// BB Remove non matching from sidebar
marker.loc = $('<p class="loc" />').addClass(mapData.type).html(spot + mapData.title).data('marker', {m:marker, type:mapData.type}).appendTo($locs).get(0);
// BB - At the bottom of the $.each() loop in initialize(), create and populate one array per category, as properties of markers ://
if(!markers[mapData.type]) markers[mapData.type] = [];
markers[mapData.type].push(marker);
});
// End of for/each loop
//-----------------------------------------------------------------------------------------
} // end of initialise (?)
//-----------------------------------------------------------------------------------------
/*
Sidebar Functions
*/
$(document).on("mouseenter", ".loc", function() {
//if(lastinfowindow && lastinfowindow.close) lastinfowindow.close(); // moved to on click, avoids closing when accidently moving mouse
var mapData = $(this).data("mapData");
map.setZoom(18); // zoom in a bit
map.setCenter(mapData.marker.getPosition());// centre on selection
//map.panTo(mapData.marker.getPosition());// direct reference to the marker avoids the need to loop.
mapData.marker.setIcon(getIcon(''));//get the default icon ie. larger yellow spot.
}).on("mouseleave", ".loc", function() {
var mapData = $(this).data("mapData");
mapData.marker.setIcon(getIcon(mapData.type));//reset marker to correct type
map.setZoom(17); //rest zoom to default
map.setCenter(marker.getPosition()); // centre on map middle
}).on("click", ".loc", function() { // opens corresponding info window on map
if(lastinfowindow && lastinfowindow.close) lastinfowindow.close();
var mapData = $(this).data("mapData");
//map.setZoom(19); // zoom in more maybe
mapData.marker.infowindow.open(map, mapData.marker); // open infowindow
lastinfowindow = mapData.marker.infowindow; // remember for closing this infowindow, if still open when selection changes
})
//-----------------------------------------------------------------------------------------
/*
Run on every change to any of the checkboxes
*/
function doFilter() {
if(lastinfowindow && lastinfowindow.close) lastinfowindow.close(); // close last infowindow if still open
alert ("filter triggered");
$("input[type=checkbox]").each(function(i, checkbox) {
var markersArr = markers[checkbox.value];
if(markersArr) {
$.each(markersArr, function(i, marker) {
marker.loc.style.display = ['none', 'block'][Number(checkbox.checked)]; // don't display non selected types
marker.setVisible(checkbox.checked); // display selected type(s)
});
};
});
}
//-----------------------------------------------------------------------------------------
/*
Run on initial setup
*/
doFilter();
//-----------------------------------------------------------------------------------------
/*
fires on every checkbox change
*/
$("#form").on("click", ".cat", doFilter)
</script>
If, in the loop where the markers are created, you give each sidebar item a reference to its marker instead of the locid, then there's no need to loop to rediscover the marker on mouseenter/mouseleave.
ie, instead of setting :
//My best guess at what the statement must be.
thisloc.data("locid", id);
//Keep this line if thisloc.data("locid") is used elsewhere.
set (within the sidebar item/marker creation loop) :
var marker = ....;
var thisloc = ...;
...
data[i].marker = marker;//add a .marker property to the original dataset.
thisloc.data("itemData", data[i]);//associate the original dataset with the sidebar item
Now the mouseenter/mouseleave handlers should simplify as follows:
$(document).on("mouseenter", ".loc", function() {
if(lastinfowindow && lastinfowindow.close) lastinfowindow.close();
var data = $(this).data("itemData");
map.panTo(data.marker.getPosition());//<<<< direct reference to the marker avoids the need to loop.
data.marker.setIcon(getIcon(''));//get the default icon.
}).on("mouseleave", ".loc", function() {
var data = $(this).data("itemData");
data.marker.setIcon(getIcon(data.type));
});
Note: You shouldn't need to pan to the marker again on mouseleave.
This should answer the question posed plus other advantages.
EDIT:
OK, now I've seen the main loop, it can be revised something like this, with various mods all through :
var $locs = $("#locs");//Used repeatedly inside the loop.
$.each(data, function(idx, mapData) {
//Note: critical assignment of the new marker as a property of `mapData`.
mapData.marker = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(mapData.lat,mapData.long),
title: mapData.title,
icon: getIcon(mapData.type)
});
var link = '' + mapData.title + '';
var contentHtml = "<div id='iw' class='iw2'><h3>" + link + "</h3>" + mapData.detail + "<br>" + mapData.address + "</div>";
//What was `marker` must now be referred to as `mapData.marker`
mapData.marker.infowindow = new google.maps.InfoWindow({
content: contentHtml
});
google.maps.event.addListener(mapData.marker, 'click', function() {
if(lastinfowindow && lastinfowindow.close) lastinfowindow.close();
//`this` refers back to the clicked element; the appropriate marker
this.infowindow.open(map, this);
lastinfowindow = this.infowindow;
});
var spot = '<img src="' + (getIcon(mapData.type)) + '" />';
//Here, it's convenient to create what was `sideitem` as a jQuery object, so we can apply several jquery methods (without making an assignment).
$('<p class="loc" />')
.html(spot + mapData.title)
.appendTo($locs)
.data('mapData', mapData);//<<<<<<<< critical
});
doFilter();//It should be possible to execute this statement when the loop is finished.
And the corresponding mouseenter/mouseleave handlers would be :
$(document).on("mouseenter", ".loc", function() {
if(lastinfowindow && lastinfowindow.close) lastinfowindow.close();
var mapData = $(this).data("mapData");
map.panTo(mapData.marker.getPosition());//<<<< direct reference to the marker avoids the need to loop.
mapData.marker.setIcon(getIcon(''));//get the default icon.
}).on("mouseleave", ".loc", function() {
var mapData = $(this).data("mapData");
mapData.marker.setIcon(getIcon(mapData.type));
});
All untested, so may well need debugging.
EDIT2 :
The way I left it above, the array markers wasn't being populated. Now I have seen the function doFilter() I can see that markers should be populated, however it is more convenient for it to be an object rather than an array.
markers = {};//in the same scope as before
At the bottom of the $.each() loop in initialize(), create and populate one array per category, as properties of markers :
if(!markers[mapData.type]) markers[mapData.type] = [];
markers[mapData.type].push(mapData.marker);
With the markers populated in this way, you have a very simple means of identifying all markers in each category, and doFilter() will simplify enormously to :
function doFilter() {
if(lastinfowindow && lastinfowindow.close) lastinfowindow.close();
$("input[type=checkbox]").each(function(i, checkbox) {
var markersArr = markers[checkbox.value];
if(markersArr) {
$.each(markersArr, function(i, marker) {
marker.setVisible(checkbox.checked);
});
}
});
}
EDIT3
To get the sidebar entries to show/hide in sympathy with the category controls, initialize() should be as follows :
function initialize() {
var latlng = new google.maps.LatLng(37.08597981464561, -8.730670809745788);
var myOptions = {
zoom: 18,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var $locs = $("#locs");//Used repeatedly inside the loop.
var marker;
$.each(data, function(idx, mapData) {
//Note: critical assignment of the new marker as a property of `mapData`.
marker = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(mapData.lat, mapData.long),
title: mapData.title,
icon: getIcon(mapData.type)
});
var link = '' + mapData.title + '';
var contentHtml = "<div id='iw' class='iw2'><h3>" + link + "</h3>" + mapData.detail + "<br>" + mapData.address + "</div>";
marker.infowindow = new google.maps.InfoWindow({
content: contentHtml
});
google.maps.event.addListener(marker, 'click', function() {
closeLastInfoWindow();
//`this` refers back to the clicked element; the appropriate marker
this.infowindow.open(map, this);
lastinfowindow = this.infowindow;
});
var spot = '<img src="' + (getIcon(mapData.type)) + '" />';
//Here, it's convenient to create what was `sideitem` as a jQuery object, so we can apply several jquery methods.
marker.loc = $('<p class="loc" />')
.addClass(mapData.type)
.html(spot + mapData.title)
.data('marker', {m:marker, type:mapData.type})
.appendTo($locs).get(0);
if(!markers[mapData.type]) markers[mapData.type] = [];
markers[mapData.type].push(marker);
});
$(document).on("mouseenter", ".loc", function() {
closeLastInfoWindow();
var m = $(this).data("marker").m;
map.panTo(m.getPosition());//<<<< direct reference to the marker avoids the need to loop.
m.setIcon(getIcon(''));//get the default icon.
}).on("mouseleave", ".loc", function() {
var data = $(this).data("marker");
data.m.setIcon(getIcon(data.type));
}).on("click",".loc",function() {
var m = $(this).data("marker").m;
m.infowindow.open(map, m);
lastinfowindow = m.infowindow;
});
$("#form").on("click", ".cat", doFilter);
doFilter();
}
markers[i].setIcon("currmark") won't work (sets the icon to the string "currmark"). Use the variable: markers[i].setIcon(currmark).
$(document).on("mouseleave",".loc",function() {
var thisloc = $(this).data("locid");
var currmark = getIcon("mapData.type");
for(var i=0; i<markers.length; i++) {
if(markers[i].locid == thisloc) { //get the latlong
map.panTo(markers[i].getPosition());
markers[i].setIcon(currmark);
}
}
});
I have a map populating with markers taken from an xml file that are stored in a database. Below the map I am pulling the same info from each marker and displaying them as listings. What I'm trying to to is create a <a href=""> type link that will open the corresponding marker and infowindow beside each listing. Here is my page, it might better explain what I mean: http://poultry.ie/plugin/page/breeders
Here is my code:
<script type="text/javascript">
//<![CDATA[
var redpin = new google.maps.MarkerImage('http://labs.google.com/ridefinder/images/mm_20_red.png',
new google.maps.Size(20,32),
new google.maps.Point(0,0),
new google.maps.Point(0,32)
);
var redpinshadow = new google.maps.MarkerImage('http://labs.google.com/ridefinder/images/mm_20_shadow.png',
new google.maps.Size(37,32),
new google.maps.Point(0,0),
new google.maps.Point(0, 32)
);
function load() {
var gmarkers = [];
var map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(53.5076512854544, -7.701416015625),
zoom: 7,
mapTypeId: 'roadmap'
});
var infoWindow = new google.maps.InfoWindow;
// Change this depending on the name of your PHP file
downloadUrl("http://poultry.ie/plugins/CustomPages/pages/phpsqlajax_genxml3.php", function(data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
var name = markers[i].getAttribute("name");
var address = markers[i].getAttribute("address");
var phone = markers[i].getAttribute("phone");
var breeds = markers[i].getAttribute("breeds");
var point = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("lat")),
parseFloat(markers[i].getAttribute("lng")));
var html = "<b>" + name + "</b><br />" + address + "<br/>" + phone + "<br/>" + breeds;
var marker = new google.maps.Marker({
map: map,
shadow: redpinshadow,
icon: redpin,
position: point
});
bindInfoWindow(marker, map, infoWindow, html);
}
});
}
function bindInfoWindow(marker, map, infoWindow, html) {
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function() {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
function doNothing() {}
//]]>
</script>
And the php that is dynamically displaying the listings (for this one county):
//Armagh
$data = mysql_query("SELECT * FROM markers WHERE address='Armagh'")
or die(mysql_error());
while($info = mysql_fetch_array( $data ))
{
Print '<div class="county all armagh">';
Print "<h4>".$info['name'] . "</h4> ";
Print "<em>".$info['address'] . "</em><br /> ";
Print "".$info['phone'] . "<br /> ";
Print 'See on Map<br />';
Print "<em>Breeds:</em> ".$info['breeds'] . "<hr/></div>";
}
The <a href="javascript:myclick( is from a previous attempt at creating this, it doesn't actually have a function at the moment.
I have tried to apply many examples to my code without success as my knowledge of javascript is fairly limited to say the least. My above code might also not be the cleanest as it is my putting together from a lot of examples.
Here is an example (ported from Mike Williams' v2 tutorial) which loads markers from an xml file and has a clickable sidebar