I have used this tutorial from Google to build a web app that finds the closest store from the user entered location:
http://code.google.com/apis/maps/articles/phpsqlsearch_v3.html
I have my app almost working the way I want it, upon page load, the map is loaded, centered and set to zoom level 6 and the user fills out the form with their location.
The app then pulls all the store info from the db and populates the map with a marker for each.
The zoom level seems to decrease aswell but I can't find this in the code anywhere.
What I actually want to do on submit is zoom in to zoom level 6 and center the map to the latitude and longitude of the user entered location and output info on the nearest stores, e.g the nearest 5. I was wondering if anyone here knew how to implement this feature?
index.php
<div>
<input type="text" id="addressInput" size="50"/>
<input type="hidden" id="radiusSelect" value="5"/>
<input type="button" onclick="searchLocations()" value="Search"/>
</div>
<div><select id="locationSelect" style="width:100%;visibility:hidden"></select></div>
<div id="map" style="width:100%; height:50%"></div>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="http://maps.google.com/maps/api/js?sensor=false" type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
var map;
var markers = [];
var infoWindow;
var locationSelect;
function load() {
map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(54.600939134593, -2.399894114594),
zoom: 6,
mapTypeId: 'roadmap',
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');
}
};
}
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');
}
});
}
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);
}
function searchLocationsNear(center) {
clearLocations();
var radius = document.getElementById('radiusSelect').value;
var searchUrl = 'phpsqlsearch_genxml.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 town = markerNodes[i].getAttribute("town");
var postcode = markerNodes[i].getAttribute("postcode");
var name = markerNodes[i].getAttribute("name");
var address = markerNodes[i].getAttribute("address");
var distance = parseFloat(markerNodes[i].getAttribute("distance"));
var latlng = new google.maps.LatLng(
parseFloat(markerNodes[i].getAttribute("lat")),
parseFloat(markerNodes[i].getAttribute("lng")));
var id = markerNodes[i].getAttribute("id");
var fname = markerNodes[i].getAttribute("fname");
var link = '<a href="http://www.domain.co.uk/stores/' + fname + '-' + id + '.html" target="_blank" title="Store: ' + town + '">More info</a>';
createOption(name, distance, i);
createMarker(latlng, name, address, town, postcode, link);
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');
};
});
}
function createMarker(latlng, name, address, town, postcode, link) {
var html = "<b>" + town + "</b> <br/>" + address + "<br/>" + postcode + "<br/>" + link;
var marker = new google.maps.Marker({
map: map,
position: latlng
});
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
markers.push(marker);
}
function createOption(name, distance, num) {
var option = document.createElement("option");
option.value = num;
option.innerHTML = name + "(" + distance.toFixed(1) + ")";
locationSelect.appendChild(option);
}
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);
}
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() {}
//]]>
</script>
<script type="text/javascript">
$(document).ready(function() {
load();
});
</script>
phpsqlsearch_genxml.php
<?php
$db_conn = mysql_connect('xxx.xxx.xx.xx', 'xxxxxxxx', 'xxxxxx') or die('error');
mysql_select_db('uk_db', $db_conn) or die(mysql_error());
// Get parameters from URL
$center_lat = $_GET["lat"];
$center_lng = $_GET["lng"];
$radius = $_GET["radius"];
if(!$_GET['zoom']) {
$_GET['zoom'] = 11;
}
// Start XML file, create parent node
$dom = new DOMDocument("1.0");
$node = $dom->createElement("markers");
$parnode = $dom->appendChild($node);
// Select all the rows in the markers table
$query = 'SELECT address1, address2, address3, longitude, latitude, name, town, store_id, postcode, storenumber
FROM uk_store
WHERE isActive=1 ';
if($_GET["region"] != '') {
$query .= ' AND region = "' . $_GET["region"] . '"';
} else {
$query .= ' AND region in("Scotland", "England", "Wales", "Northern Ireland") ';
}
// lets start to check what has been search on
if($_GET['postcode'] != '') {
//lets make sure postcode only has numbers letter and spaces
$searchparams .= 'postcode=' . $_GET['postcode'] . '&';
$postcode = $_GET['postcode'];
$postcode = verifyInput($postcode);
$query .= " AND postcode = '" . $postcode . "'";
}
if($_GET['town'] != '') {
// make sure town only has letters or spaces.
$searchparams .= 'town=' . $_GET['town'] . '&';
$town = $_GET['town'];
$town = verifyInput($town);
$query .= " AND town = '" . $town . "'";
}
if($_GET['min_lat'] && $_GET['min_long'] && $_GET['max_lat'] && $_GET['max_long'] ) {
$query .= " AND latitude BETWEEN " . $_GET['min_lat'] . " AND " . $_GET['max_lat'] . " AND longitude BETWEEN " . $_GET['min_long'] . " AND " . $_GET['max_long'] ;
$mapsearch = 1;
}
if(!($_GET['postcodeLat'] && $_GET['postcodeLong'])) {
$query .= " ORDER BY Region, Town , Name ";
}
$result = mysql_query($query);
if (!$result) {
die("Invalid query: " . mysql_error());
}
header("Content-type: text/xml");
echo '<markers>';
if($_GET['postcodeLat'] && $_GET['postcodeLong'])
{
$count = 0;
// we need to sort the results by distance
while ($row = @mysql_fetch_array($result, MYSQL_ASSOC))
{
$address = $row['address1'] . ' ' . $row['address2'] . ' ' . $row['address3'];
$distance = distance($_GET['postcodeLat'], $_GET['postcodeLong'], $row['latitude'], $row['longitude']);
$row['distance'] = number_format($distance, 2);
$row['fname'] = $row['town'] . '-' . $row['name'];
$row['fname'] = str_replace("'",'', $row['fname']);
$row['fname'] = ereg_replace(' ','-', $row['fname']);
$row['fname'] = ereg_replace('\/','-', $row['fname']);
$row['fname'] = ereg_replace('\(','', $row['fname']);
$row['fname'] = ereg_replace('\)','', $row['fname']);
$row['fname'] = strtolower($row['fname']);
//get distance and add to $row array
$results[$distance.$row['id']] = $row;
}
ksort($results);
foreach ($results as $key => $row)
{
// ADD TO XML DOCUMENT NODE
$address = $row['address1'] . ' ' . $row['address2'] . ' ' . $row['address3'];
echo '<marker ';
echo 'name="' . parseToXML($row['name']) . '" ';
echo 'fname="' . parseToXML($row['fname']) . '" ';
echo 'town="' . parseToXML($row['town']) . '" ';
echo 'lat="' . $row['latitude'] . '" ';
echo 'lng="' . $row['longitude'] . '" ';
echo 'id="' . $row['store_id'] . '" ';
echo 'address="' . $address . '" ';
echo 'distance="' . $row['distance'] . '" ';
echo 'postcode="' . $row['postcode'] . '" ';
echo 'storenumber="' . $row['storenumber'] . '" ';
echo 'address1="' . parsetoXml($row['address1']). '" ';
echo 'address2="' . parsetoXml($row['address2']). '" ';
echo 'address3="' . parsetoXml($row['address3']). '" ';
echo '/>';
}
}
else
{
// Iterate through the rows, printing XML nodes for each
while ($row = @mysql_fetch_assoc($result))
{
$address = $row['address1'] . ' ' . $row['address2'] . ' ' . $row['address3'];
$row['fname'] = $row['town'] . '-' . $row['name'];
$row['fname'] = ereg_replace(' ','-', $row['fname']);
$row['fname'] = ereg_replace('\/','-', $row['fname']);
$row['fname'] = ereg_replace('\(','', $row['fname']);
$row['fname'] = ereg_replace('\)','', $row['fname']);
// ADD TO XML DOCUMENT NODE
echo '<marker ';
echo 'name="' . parseToXML($row['name']) . '" ';
echo 'fname="' . strtolower(parseToXML($row['fname'])) . '" ';
echo 'town="' . parseToXML($row['town']) . '" ';
echo 'lat="' . $row['latitude'] . '" ';
echo 'lng="' . $row['longitude'] . '" ';
echo 'id="' . $row['store_id'] . '" ';
echo 'isSurg="' . $row['isLaserSurgery'] . '" ';
echo 'isCons="' . $row['isLaserConsult'] . '" ';
echo 'address="' . parsetoXml($address). '" ';
echo 'address1="' . parsetoXml($row['address1']). '" ';
echo 'address2="' . parsetoXml($row['address2']). '" ';
echo 'address3="' . parsetoXml($row['address3']). '" ';
echo 'postcode="' . $row['postcode'] . '" ';
echo 'storenumber="' . $row['storenumber'] . '" ';
echo '/>';
}
}
// End XML file
echo '</markers>';
// make sure the data is xml friendly
function parseToXML($htmlStr)
{
$xmlStr=str_replace('<','<',$htmlStr);
$xmlStr=str_replace('>','>',$xmlStr);
$xmlStr=str_replace('"','"',$xmlStr);
//$xmlStr=str_replace("'",''',$xmlStr);
$xmlStr=str_replace("&",'&',$xmlStr);
return $xmlStr;
}
// calculate the distance in miles or kms between any two points
function distance($lat1, $lon1, $lat2, $lon2, $unit = '') {
$theta = $lon1 - $lon2;
$dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
$dist = acos($dist);
$dist = rad2deg($dist);
$miles = $dist * 60 * 1.1515;
if($unit != '')
{
$unit = strtoupper($unit);
}
if ($unit == "K") {
return ($miles * 1.609344);
} else if ($unit == "N") {
return ($miles * 0.8684);
} else {
return $miles;
}
}
function VerifyInput ($input, $forceInt = false) {
if (is_numeric($input)) {
return $input;
} elseif (!$forceInt) {
if (get_magic_quotes_gpc() && trim(ini_get("magic_quotes_sybase")) == "") {
$input = stripslashes($input);
$input = str_replace("'", "", $input);
$input = str_replace("`", "", $input);
} elseif (!get_magic_quotes_gpc()) {
$input = str_replace("'", "", $input);
$input = str_replace("`", "", $input);
}
return $input;
} elseif ($forceInt) {
return 0;
}
}
?>
Apologies, that's a lot of pasting there but I thought it better to include everything rather than risk someone not being able to answer because there wasn't enough detail.
UPDATE
I have tried inserting this piece of code into the searchLocations
function but it doesn't seem tochange the behaviour in anyway:
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);
/////////////// new code
var myOptions = {
zoom: 11,
center: address.geometry.location,
mapTypeId: google.maps.MapTypeId.TERRAIN
}
map = new google.maps.Map(document.getElementById("map"), myOptions);
////////////////
} else {
alert(address + ' not found');
}
});
}
Found the methods I was looking for in the documentation (surprise, surprise!)
Simply add these two lines under map.fitBounds(bounds);
in the searchLocationsNear
function:
map.setZoom(11);
map.setCenter(center);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With