HTML:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<link rel="stylesheet" href="dealers.css">
</head>
<body>
<div class="row mapSection">
<div class="col-xs-12">
<div id="map"></div>
<div id="panel">
<div id="entryRow">
<div><select id="locationSelect" style="width:100%;visibility:hidden"></select></div>
<input type="text" id="addressInput" />
<select id="radiusSelect">
<option value="5" selected>5 miles</option>
<option value="25" selected>25 miles</option>
<option value="100">100 miles</option>
<option value="200">200 miles</option>
<option value="500">500 miles</option>
</select>
<input type="text" id="find" value="Search"/>
<input type="button" id="refresh" value="redo Search"/>
</div>
<ul class="resultDealers">
</ul>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=***YOUR*KEY*HERE***" type="text/javascript"></script>
<script type="text/javascript" src="Maps.js"></script>
</body>
</html>
CSS:
body {
font-family: sans-serif;
margin: 0px;
padding: 0px;
}
#map,
#panel {
height: 500px;
float: left;
}
#map {
width: 60%;
}
#entryRow {
margin: 0 0 0 15px;
}
#panel {
width: 40%;
}
.resultDealers {
padding: 0;
margin: 15px;
overflow: scroll;
height: 420px;
}
.resultDealers li {
list-style-type: none;
border-left: 1px solid;
border-top: 1px solid;
border-right: 1px solid;
padding: 10px;
}
.resultDealers li:last-child {
border-bottom: 1px solid;
}
.highlightDealer {
background: #E8E8E8;
}
.markerBox {
cursor: pointer;
}
.markerBox:hover {
background: #E3F4F9;
}
#panel .feature-filter label {
width: 130px;
}
p.attribution,
p.attribution a {
color: #666;
}
#find {
background: #DEDCDC;
border: 1px solid gray;
width: 65px;
padding: 2px;
text-align: center;
font-weight: bold;
cursor: pointer;
margin-left: 15px;
}
#find:hover {
background: #F9F4F4;
}
#radiusSelect {
margin-left: 15px;
}
#addressInput {
float: left;
margin-left: 5px;
padding-left: 10px;
width: 65px;
}
#locationSelect {
margin: 10px 5px;
width: 95% !important;
}
JavaScript:
/* --------- Start Maps.js --------- */
Maps Module
//Usage: Maps.init();
Maps = (function ( window, google ) {
var map,
markers = [],
infoWindow,
locationSelect;
var load = function load () {
map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(40, -100),
zoom: 4,
mapTypeId: 'roadmap',
// scrollWheel: false,
// zoomControl: false,
streetViewControl: false,
rotateControl: false,
fullscreenControl: false,
navigationControl: false,
scaleControl: false,
// draggable: false,
mapTypeControl: false,
mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU}
});
infoWindow = new google.maps.InfoWindow();
locationSelect = document.getElementById("locationSelect");
locationSelect.onchange = function() {
var markerNum = locationSelect.options[locationSelect.selectedIndex].value;
if (markerNum != "none"){
google.maps.event.trigger(markers[markerNum], 'click');
}
};
refreshMap();
google.maps.event.addListener(map, 'zoom_changed', function() {
//$('#radiusSelect option:selected').next().attr('selected', 'selected');
//console.log(map.getCenter());
//searchLocationsNear (map.getCenter());
});
}
var bindInfoWindow = function bindInfoWindow ( marker, map, infoWindow, html ) {
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
}
var refreshMap = function refreshMap () {
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var latLng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
var geocoder = new google.maps.Geocoder();
geocoder.geocode({ 'latLng': latLng}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
for ( var j = 0; j < results[0].address_components.length; j++ ) {
for ( var k = 0; k < results[0].address_components[j].types.length; k++ ) {
if ( results[0].address_components[j].types[k] == "postal_code" ) {
zipcode = results[0].address_components[j].short_name;
}
}
}
document.getElementById("addressInput").value = zipcode;
searchLocations();
} else {
console.log("Geocoding failed: " + status);
}
});
});
}
}
var downloadUrl = 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.responseText, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
var searchLocations = function searchLocations () {
var address = document.getElementById("addressInput").value;
var geocoder = new google.maps.Geocoder();
geocoder.geocode({address: address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
searchLocationsNear(results[0].geometry.location);
} else {
alert(address + ' not found');
}
});
}
var clearLocations = function clearLocations() {
infoWindow.close();
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(null);
}
markers.length = 0;
locationSelect.innerHTML = "";
var option = document.createElement("option");
option.value = "none";
option.innerHTML = "See all results:";
locationSelect.appendChild(option);
}
var searchLocationsNear = function searchLocationsNear ( center ) {
clearLocations();
var radius = document.getElementById('radiusSelect').value;
var searchUrl = '/dealers.php?lat=' + center.lat() + '&lng=' + center.lng() + '&radius=' + radius;
downloadUrl( searchUrl, function(data) {
var xml = parseXml(data);
var markerNodes = xml.documentElement.getElementsByTagName("marker");
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < markerNodes.length; i++) {
var id = markerNodes[i].getAttribute("id");
var name = markerNodes[i].getAttribute("name");
var address = markerNodes[i].getAttribute("address");
var city = markerNodes[i].getAttribute("city");
var state = markerNodes[i].getAttribute("state");
var zip = markerNodes[i].getAttribute("zip");
var url = markerNodes[i].getAttribute("url");
var email = markerNodes[i].getAttribute("email");
var distance = parseFloat(markerNodes[i].getAttribute("distance"));
var latlng = new google.maps.LatLng(
parseFloat(markerNodes[i].getAttribute("lat")),
parseFloat(markerNodes[i].getAttribute("lng")));
createOption(name, distance, i);
createMarker(id, latlng, name, address, city, state, zip, url, email);
bounds.extend(latlng);
}
map.fitBounds(bounds);
locationSelect.style.visibility = "visible";
locationSelect.onchange = function() {
var markerNum = locationSelect.options[locationSelect.selectedIndex].value;
google.maps.event.trigger(markers[markerNum], 'click');
};
});
}
var createMarker = function createMarker ( id, latlng, name, address, city, state, zip, url, email ) {
var html = "<div class='marker-" + id + "'><b>" + name + "</b> <br/>" + address + "<br/>" + city + " " + state + ", " + zip + "<br />" + url + "<br /><a href='mailto:" + email + "'>" + email + "</a></div>";
var marker = new google.maps.Marker({
map: map,
position: latlng
});
google.maps.event.addListener(marker, 'click', function() {
//infoWindow.setContent(html);
//infoWindow.open(map, marker);
$("li[class*='marker-']").removeClass('highlightDealer');
$("li.marker-" + id).addClass('highlightDealer');
window.location.href = "#marker-"+ id;
window.scrollTo(0, 0);
map.setZoom(16);
map.setCenter(marker.getPosition());
});
markers.push(marker);
$("#panel ul").append("<li class='markerBox marker-" + id + "'><a name='marker-" + id + "'></a><b>" + name + "</b><br/>" + address + "<br/>" + city + " " + state + ", " + zip + "<br />" + url + "<br /><a href='mailto:" + email + "'>" + email + "</a></li>");
$('.marker-' + id).on('click', function() {
$("li[class*='marker-']").removeClass('highlightDealer');
$("li.marker-" + id).addClass('highlightDealer');
map.setZoom(16);
map.setCenter(marker.getPosition());
});
}
var createOption = function createOption ( name, distance, num ) {
var option = document.createElement("option");
option.value = num;
option.innerHTML = name + "(" + distance.toFixed(1) + ")";
locationSelect.appendChild(option);
}
var parseXml = function parseXml(str) {
if (window.ActiveXObject) {
var doc = new ActiveXObject('Microsoft.XMLDOM');
doc.loadXML(str);
return doc;
} else if (window.DOMParser) {
return (new DOMParser).parseFromString(str, 'text/xml');
}
}
function doNothing() {}
$('#find').on('click', function() {
$('#panel ul').empty();
searchLocations();
});
$('#addressInput').on('click', function () {
$(this).val('');
});
$('#radiusSelect').on('change', function () {
$('#panel ul').empty();
searchLocations();
});
$('#refresh').on('click', function () {
var bounds = map.getBounds();
var ne = bounds.getNorthEast(); // LatLng of the north-east corner
var sw = bounds.getSouthWest(); // LatLng of the south-west corder
var nw = new google.maps.LatLng(ne.lat(), sw.lng());
var se = new google.maps.LatLng(sw.lat(), ne.lng());
console.log('nw: ' + nw);
console.log('se: ' + se);
//searchLocationsNear();
//searchLocations();
});
return {
load: load
}
})( window, google );
$(function(){
loadModules.start();
})
var loadModules = loadModules || {};
loadModules.start = function(){
// Maps module init
Maps.load();
};
/* --------- End Maps.js --------- */
PHP:
<?php
header("Access-Control-Allow-Origin: *");
$servername = "***Your*DB*URL***";
$username = "***Your*DB*USERNAME***";
$password = "***Your*DB*PASS***";
$dbname = "***Your*DB*NAME***";
// Get parameters from URL
$center_lat = $_GET["lat"];
$center_lng = $_GET["lng"];
$radius = $_GET["radius"];
// Start XML file, create parent node
$dom = new DOMDocument("1.0");
$node = $dom->createElement("markers");
$parnode = $dom->appendChild($node);
// Opens a connection to a mySQL server
$connection=mysql_connect ($servername, $username, $password);
if (!$connection) {
die("Not connected : " . mysql_error());
}
// Set the active mySQL database
$db_selected = mysql_select_db($dbname, $connection);
if (!$db_selected) {
die ("Can\'t use db : " . mysql_error());
}
// Search the rows in the markers table
$query = sprintf("SELECT id, name, address, city, state, zip, url, email, lat, lng, ( 3959 * acos( cos( radians('%s') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('%s') ) + sin( radians('%s') ) * sin( radians( lat ) ) ) ) AS distance FROM dealers HAVING distance < '%s' ORDER BY distance LIMIT 0 , 20",
mysql_real_escape_string($center_lat),
mysql_real_escape_string($center_lng),
mysql_real_escape_string($center_lat),
mysql_real_escape_string($radius));
$result = mysql_query($query);
$result = mysql_query($query);
if (!$result) {
die("Invalid query: " . mysql_error());
}
header("Content-type: text/xml");
// Iterate through the rows, adding XML nodes for each
while ($row = @mysql_fetch_assoc($result)){
$node = $dom->createElement("marker");
$newnode = $parnode->appendChild($node);
$newnode->setAttribute("id", $row['id']);
$newnode->setAttribute("name", $row['name']);
$newnode->setAttribute("address", $row['address']);
$newnode->setAttribute("city", $row['city']);
$newnode->setAttribute("state", $row['state']);
$newnode->setAttribute("zip", $row['zip']);
$newnode->setAttribute("url", $row['url']);
$newnode->setAttribute("email", $row['email']);
$newnode->setAttribute("lat", $row['lat']);
$newnode->setAttribute("lng", $row['lng']);
$newnode->setAttribute("distance", $row['distance']);
}
echo $dom->saveXML();
?>