A script to find the nearest store or what ever, to you, by inputting your address or zip code and a radius in miles.
Please note: I borrowed a lot of this from a tutorial, then took a lot from this forum. I kept working until it ran, but my code is not the best.
1. Set up a table, then make a way for “brokers” to add themselves to the table.
(This requires one to access the table, verify the data, use a geocoder to find the coordinates, and insert them into the record). The nice thing is it will not output blank coordinates, so my intervention is required for all new additions. Oh, and you must get your own google API for your site.
2. Set up a map that would access the table and plot markers and a side bar with info to the nearest point based on the radius and address or zip they input. I also must tell you that the map window covers my menu on the side of the template I will work on this later.
Mysql 5.0.45, modx 9.5
The table created inside modx db
CREATE TABLE `markers` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`name` VARCHAR( 60 ) NOT NULL ,
`address` VARCHAR( 80 ) NOT NULL ,
`citystatezip` VARCHAR( 80 ) NOT NULL ,
`phone` VARCHAR( 12 ) NOT NULL ,
`type` VARCHAR( 80 ) NOT NULL ,
`lat` FLOAT( 10, 6 ) NOT NULL ,
`lng` FLOAT( 10, 6 ) NOT NULL ,
`visable` VARCHAR( 2 ) NOT NULL ,
‘date’ DATETIME
) ;
The fields are pretty straight forward, ‘visable’ was going to be used to not print the record unless I changed it to ‘Y’ but later I found out that blank coordinates will not return a record.
The Form Chunk titled {{AddBroker}}
<p class="error">[+validationmessage+]</p>
Here is where you add your name and address to our map.<br>
Enter your full name, then your street address, then (on one line) your city, state zip.<br>
However you input your phone number is how it will display- so please use an area code.<br>
Your name will not show up until I code your longitude and latitude based on your street address
so please be patient.<br>
<form method="post" action="[~[*id*]~]" id="AddBroker" name="AddBroker">
<table id="Add-a-Broker" cellpadding="0" cellspacing="0" border="0">
<td style="text-align:right">
<label for="sname">Full Name:</label></td>
<td><input name="name" id="sname" class="text" type="text" eform="Full Name::1:"/> *</td>
</tr>
<tr>
<td style="text-align:right"><label for="saddress">Street Address:</label></td>
<td><input name="address" id="saddress" class="text" type="text" eform="Street Address::1:"/> *</td>
</tr>
<tr>
<td style="text-align:right"><label for="scitystatezip">City, State zip:</label></td>
<td><input name="citystatezip" id="scitystatezip" class="text" type="text" eform="City, State zip::1:"/> *</td>
</tr>
<tr>
<td style="text-align:right"><label for="sphone">Phone:</label></td>
<td><input name="phone" id="sphone" class="text" type="text" eform="Phone::1:"/> *</td>
</tr>
<tr>
<td style="text-align:right"><label for="stype">Type:</label></td>
<td>
<select name="type" id="stype" eform="Type::1:">
<option value="" selected="selected">Select Type</option>
<option value="Broker">Broker</option>
<option value="Lender">Lender</option>
<option value="other">other</option>
</select> *
</td>
</tr>
<tr>
<td colspan="2" style="text-align:center"><input type="submit" name="submit" value="Submit"></td>
</tr>
</table>
</form>
The Snippet [[insertbroker]]
<?php
function escape($s){return mysql_escape_string($s);
}
function insertbroker( &$fields )
{
// Bring needed resources into scope
global $modx;
// Init our array
$dbTable = array(); // key = DB Column; Value = Insert/Update value
// Insert field/value pairs to insert/update in our table
$dbTable['ID'] = 'NULL';
$dbTable['name'] = $modx->db->escape($fields['name']);
$dbTable['address'] = $modx->db->escape($fields['address']);
$dbTable['citystatezip'] = $modx->db->escape($fields['citystatezip']);
$dbTable['phone'] = $modx->db->escape($fields['phone']);
$dbTable['type'] = $fields['type'];
$dbTable['lat'] = '';
$dbTable['lng'] = '';
$dbTable['visable'] = 'N';
$dbTable['date'] = date( 'YmdHis', strtotime( $fields[postdate] ) );
// print_r($dbTable);
// Run the db insert query
$dbQuery = $modx->db->insert( $dbTable, 'markers');
return true;
}
?>
The code to call the above was put on a page, name it what ever.
[!insertbroker!]
[!eForm? &noemail=`true` &formid=`AddBroker` &eFormOnBeforeMailSent=`insertbroker` &tpl=`AddBroker` &thankyou=`46`!]
my thank you page on the menu has the (46) after it, put the number of your thank you page in there.
I now know what the s and the cf are used for in the Form, thanks, and I think the ::1 tells eform that the field is mandatory.
The Map page- put your googlemap API after the key=
The API is free from Google
The Chunk {{GoogleMap}}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Find a Broker Near You</title>
<script src="http://maps.google.com/maps?file=api&v=2&key=ABQIAAAA7xs7vzRuaoYKnoxqRadLdBQX-cOEUPOBREUpYXvpOUtYHDbrHBSl9m13vrGrCn_replace all this with your API"
type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
var map;
var geocoder;
<!-- change the center of the map, and the zoom level below -->
function load() {
if (GBrowserIsCompatible()) {
geocoder = new GClientGeocoder();
map = new GMap2(document.getElementById('map'));
map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());
map.setCenter(new GLatLng(41.2, -73.8), 6);
}
}
function searchLocations() {
var address = document.getElementById('addressInput').value;
geocoder.getLatLng(address, function(latlng) {
if (!latlng) {
alert(address + ' not found');
} else {
searchLocationsNear(latlng);
}
});
}
function searchLocationsNear(center) {
var radius = document.getElementById('radiusSelect').value;
var searchUrl = 'locator.php?lat=' + center.lat() + '&lng=' + center.lng() + '&radius=' + radius;
GDownloadUrl(searchUrl, function(data) {
var xml = GXml.parse(data);
var markers = xml.documentElement.getElementsByTagName('marker');
map.clearOverlays();
var sidebar = document.getElementById('sidebar');
sidebar.innerHTML = ''; <!-- markers is the name of the database -->
if (markers.length == 0) {
sidebar.innerHTML = 'No results found.';
map.setCenter(new GLatLng(41.2, -73.8), 6);<!-- Change map center, and zoom level -->
return;
}
var bounds = new GLatLngBounds();
for (var i = 0; i < markers.length; i++) {
var name = markers[i].getAttribute('name');
var address = markers[i].getAttribute('address');
var distance = parseFloat(markers[i].getAttribute('distance'));
var point = new GLatLng(parseFloat(markers[i].getAttribute('lat')),
parseFloat(markers[i].getAttribute('lng')));
var type = markers[i].getAttribute('type');
var marker = createMarker(point, name, address, type); <!-- leave point alone, put fields here -->
map.addOverlay(marker);
var sidebarEntry = createSidebarEntry(marker, name, address, distance, type); <!-- keep distance next to address, then add other fields here -->
sidebar.appendChild(sidebarEntry);
bounds.extend(point);
}
map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
});
}
function createMarker(point, name, address, type) {
var marker = new GMarker(point);
var html = '<b>' + name + '</b> <br/>' + address + '<br/>' + type; <!-- quotes around tags, plus sign to make string longer, don't forget the semicolon -->
GEvent.addListener(marker, 'click', function() {
marker.openInfoWindowHtml(html);
});
return marker;
}
<!-- all names must match database exactly, keep address next to distance add new fields to end -->
function createSidebarEntry(marker, name, address, distance, type) {
var div = document.createElement('div');
var html = '<b>' + name + '</b> (' + distance.toFixed(1) + ')<br/>' + address + '<br/>' + type;
div.innerHTML = html;
div.style.cursor = 'pointer';
div.style.marginBottom = '5px';
GEvent.addDomListener(div, 'click', function() {
GEvent.trigger(marker, 'click');
});
GEvent.addDomListener(div, 'mouseover', function() {
div.style.backgroundColor = '#eee';
});
GEvent.addDomListener(div, 'mouseout', function() {
div.style.backgroundColor = '#fff';
});
return div;
}
//]]>
</script>
</head>
<body onload="load()" onunload="GUnload()">
Find a Broker near you- test page, Downstate NY only<br/>
Simply put your address or Zipcode in the box, and choose a radius<br/>
Your Address, or Zip: <input type="text" id="addressInput"/>
Radius: <select id="radiusSelect">
<option value="25" selected>25</option>
<option value="50">50</option>
<option value="100">100</option>
<option value-"150">150</option>
<option value="200">200</option>
</select>
<input type="button" onclick="searchLocations()" value="Search Locations"/>
<br/>
<br/>
<div style="width:600px; font-family:Arial,
sans-serif; font-size:11px; border:1px solid black">
<table>
<tbody>
<tr id="cm_mapTR">
<td width="200" valign="top"> <div id="sidebar" style="overflow: auto; height: 400px; font-size: 11px; color: #000"></div>
</td>
<td> <div id="map" style="overflow: hidden; width:400px; height:400px"></div> </td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
The snippet called [[GoogleFunction]]
<?php
// 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 the database and gets the fields.
// and does some math that throws a error on ‘AS distance’ when you run while manager is open
$modx->db->select('address', 'name', 'type', 'lat', 'lng', ( 3959 * acos( cos( radians('%s') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('%s') ) + sin( radians('%s') ) * sin( radians( lat ) ) ) ) AS distance FROM markers 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("name", $row['name']);
$newnode->setAttribute("address", $row['address']);
$newnode->setAttribute("type", $row['type']);
$newnode->setAttribute("lat", $row['lat']);
$newnode->setAttribute("lng", $row['lng']);
$newnode->setAttribute("distance", $row['distance']);
}
echo $dom->saveXML();
?>
The page that displays the map and the search box has the following code. continued on next post