Google maps, mySQL locations, PHP service
Wednesday, May 4th, 2016HTML:
<!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(); ?>