Saturday, June 9, 2012

Integrating JQuery with Google Maps and finding the nearest locations.

First I am going to describe how to locate a place using Google map in ASP.Net page.

1 . In First step include J-query CDN file in page 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>

2. Then include Google map JavaScript file.


<script src="http://maps.google.com/maps?file=api&v=2&key=ABQIAAAAjU0EJWnWPMv7oQ-jjS7dYxTPZYElJSBeBUeMSX5xXgq6lLjHthSAk20WnZ_iuuzhMt60X_ukms-AUg"
type="text/javascript"></script>

<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script>

3. I am adding a div with Id = "map" in .aspx page to show the map inside it. You can change your design pattern according to your requirement.


<table width="100%">
<tr>
<td align ="right">
<asp:TextBox ID="txtsearchArea" runat="server" AutoCompleteType="Disabled"></asp:TextBox>
</td>
<td align="left">
<input id="btnSearch" type="button" value="Search" />
</td>
</tr>
<tr>
<td colspan="2">
<div id="map" style="width: 100%; height: 450px;">
</div>
</td>
</tr>
</table>


4. Include a java script file as such

<script type="text/javascript">
// Include the image from Google to show Pointer.
var iconBlue = new GIcon();
iconBlue.image = 'http://labs.google.com/ridefinder/images/mm_20_blue.png';
iconBlue.shadow = 'http://labs.google.com/ridefinder/images/mm_20_shadow.png';
iconBlue.iconSize = new GSize(12, 20);
iconBlue.shadowSize = new GSize(22, 20);
iconBlue.iconAnchor = new GPoint(6, 20);
iconBlue.infoWindowAnchor = new GPoint(5, 1);

var iconRed = new GIcon();
iconRed.image = 'http://labs.google.com/ridefinder/images/mm_20_red.png';
iconRed.shadow = 'http://labs.google.com/ridefinder/images/mm_20_shadow.png';
iconRed.iconSize = new GSize(12, 20);
iconRed.shadowSize = new GSize(22, 20);
iconRed.iconAnchor = new GPoint(6, 20);
iconRed.infoWindowAnchor = new GPoint(5, 1);

//In document.ready function add click event for button and calling load method for showing map.
$(document).ready(function () {
$('#btnSearch').click(function () {
var searchText = $("input[id*=txtsearchArea]").val();
load(searchText);
});
});
//It takes the address text and load Map location inside div.
function load(text) {

var address = text;
if (GBrowserIsCompatible()) {
geocoder = new GClientGeocoder(); //creating a object of GClientGeocoder
if (geocoder) {
geocoder.getLatLng(
address,
function (point) {
if (!point) {
alert(address + " not found");
}
else {
$('#tblmap').css('visibility', 'visible');
var map = new GMap2(document.getElementById("map"));
map.setUIToDefault()
map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());
var marker = new GMarker(point, { draggable: true });
var str = marker.getLatLng().toUrlValue(6);
var str1 = str.split(",");
//Get the Latitude and Longitude of the place.
map.setCenter(new GLatLng(str1[0], str1[1]), 9);
//marking search point
var searchPoint = new GLatLng(str1[0], str1[1]);
// Mark the place with red icon
var searchMarker = createSearchCenter(searchPoint, iconRed);
map.addOverlay(marker);

}
}
);
}
}
}

// To Locate the locate the place with Disarable marker icon
function createSearchCenter(searchPoint, type) {
var searchMarker = new GMarker(searchPoint, type);
var html = "<b>Search Marker</b>";
return searchMarker;
}
</script>

The Output of the page will be like this











The above explanation is just for having knowledge regarding Google maps for Beginners.

Now the actual requirement is going to be explained below.






















Here the user typed an address / zip code "Wheaton" and search the nearest restaurant to the user. The right side of the map contains the address and distance of the restaurants near to user.The red color icon represent the user location and blue color represent the restaurants near by him.

The design of page will like bellow.


<table align="center" id="innertbl" style="width: 100%; height: 500px;">
<tr>
<td>
<table align="left" width="100%">
<tr>
<td style="width: 10%"> City/Zip:</td>
<td style="width: 20%">
<asp:TextBox ID="SearchcityName" runat="server"></asp:TextBox>
</td>
<td> &nbsp;</td>
<td align="left">
<input type="button" id="searchBtn" value="Search" class="ButtonStyle" /></td>
</tr>
</table>
</td>
</tr>
<tr>
<td colspan="3" align="left" valign="top">
<table border="1" id="tblmap" style="width: 100%; visibility: hidden" cellpadding="0">
<tr>
<td valign="top" style="width: 60%;">
<div id="map" style="width: 100%; height: 450px;">
</div>
</td>
<td valign="top" style="width: 35%;">
<div id="divRole" runat="server" style="width: 100%; overflow-y: scroll; overflow-x: hidden;text-align: left; max-height: 450px;">
<table id="tblAddressDispaly" style="width: 100%; color: Black; font-weight: normal;
font-size: 10px">
</table>
</div>
</td>
</tr>
</table>
</td>
</tr>
</table>

The Google map will not be aware of the addresses of the restaurants near by the place searched by user.So    I will store the address of the Restaurants in Database.








Whenever user click on the search button click event will fire and load method will be invoked.
Code Snippet:

var iconBlue = new GIcon();
iconBlue.image = 'http://labs.google.com/ridefinder/images/mm_20_blue.png';
iconBlue.shadow = 'http://labs.google.com/ridefinder/images/mm_20_shadow.png';
iconBlue.iconSize = new GSize(12, 20);
iconBlue.shadowSize = new GSize(22, 20);
iconBlue.iconAnchor = new GPoint(6, 20);
iconBlue.infoWindowAnchor = new GPoint(5, 1);

var iconRed = new GIcon();
iconRed.image = 'http://labs.google.com/ridefinder/images/mm_20_red.png';
iconRed.shadow = 'http://labs.google.com/ridefinder/images/mm_20_shadow.png';
iconRed.iconSize = new GSize(12, 20);
iconRed.shadowSize = new GSize(22, 20);
iconRed.iconAnchor = new GPoint(6, 20);
iconRed.infoWindowAnchor = new GPoint(5, 1);

$(document).ready(function () {
$('#searchBtn').click(function () {
var searchText = $("input[id*=SearchcityName]").val();
load(searchText);
});
});

In the Load method :

function load(text) {

var address = $("input[id*=SearchcityName]").val();
if (GBrowserIsCompatible()) {
geocoder = new GClientGeocoder();
if (geocoder) {
geocoder.getLatLng(
address,
function (point) {
if (!point) {
alert(address + " not found");
}
else {
$('#tblmap').css('visibility', 'visible');
var map = new GMap2(document.getElementById("map"));
map.setUIToDefault()
map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());
var marker = new GMarker(point, { draggable: true });
var str = marker.getLatLng().toUrlValue(6);
var str1 = str.split(",");
map.setCenter(new GLatLng(str1[0], str1[1]), 9); //Lattitude and Longitude.

//marking search point
var searchPoint = new GLatLng(str1[0], str1[1]);
var searchMarker = createSearchCenter(searchPoint, iconRed);
map.addOverlay(marker);

//Now passing the Latitude and Longitude object to fill map points

var glatlng1 = new GLatLng(str1[0], str1[1]);
fillMapPoints(glatlng1, map);
}
}
);
}
}
}

fillMapPoints method is used to get the data from database and calculate the distance and display.

Here I have passed the Latitude and Longitude of user typed location to the fillMapPoints method as arguments , where it will call the web method by JQuery ajax call.

First I am Showing you the web method.

[WebMethod]
public Dictionary<string, object> fillMapPoints()
{
SqlConnection conn = new SqlConnection("Data Source=RBSWIN7\\SQLEXPRESS;Initial Catalog=Dummy;User ID=sa;Password=mindfire");
conn.Open();
string sqlMapPoint = "SELECT ADDRESS,LATITUDES,LONGITUDES,LOCATION_NAME FROM L_LOCATIONS";
SqlCommand cmd = new SqlCommand(sqlMapPoint, conn) { CommandType = CommandType.Text };
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dtMapPoints);
dtMapPoints.TableName = "result";
return JsonMethods.ToJson(dtMapPoints);
}

In the above web method the data is filled in a data table.I am converting the data table value to Json format.I have Used a class JsonMethods and parse it to Json format. This will include in project.

Code Snippet:

public static class JsonMethods
{
private static List<Dictionary<string, object>>

RowsToDictionary(DataTable table)
{
List<Dictionary<string, object>> objs =
new List<Dictionary<string, object>>();
foreach (DataRow dr in table.Rows)
{
Dictionary<string, object> drow = new Dictionary<string, object>();
for (int i = 0; i < table.Columns.Count; i++)
{
drow.Add(table.Columns[i].ColumnName, dr[i]);
}
objs.Add(drow);
}

return objs;
}

public static Dictionary<string, object> ToJson(DataTable table)
{
Dictionary<string, object> d = new Dictionary<string, object>();
d.Add(table.TableName, RowsToDictionary(table));
return d;
}
}

Now I am returning to Java Script method " fillMapPoints" where I call the above web method.

Code Snippet:

var jsonObj = []; //It contains the JSon values for sorting in ascending order.

function fillMapPoints(glatlng1, map) {

$.ajax({
type: "POST",
url: "WorkerService.asmx/fillMapPoints",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
if (isNaN(data.d)) {
jsonObj = [];
for (var i = 0; i < data.d.result.length; i++) {
var location = data.d.result[i].LOCATION_NAME;
var name = '';
var addr = data.d.result[i].ADDRESS;
var type = iconBlue;
// Here the Latitude and Longitude are coming from database.
// This Can be done by writing code.
var point = new GLatLng(parseFloat(data.d.result[i].LATITUDES),
parseFloat(data.d.result[i].LONGITUDES));

//Here the distance is measured from the user typed place and location present in database.
var miledistance = glatlng1.distanceFrom(point, 3959).toFixed(1);

//Pushing the data into JSon object.
jsonObj.push({ Location: location, Name: name, Addr: addr, Distance: miledistance, Value: i, Point: point });
//var kmdistance = (miledistance * 1.609344).toFixed(1);

//Marking the locations.
var marker = createMarker(point, location, name, addr, type, miledistance, i);
map.addOverlay(marker);
}
//Clearing the Value .
$('#tblAddressDispaly tr').remove();

//Here sorting the values according distance in ascending order.
var sorted = jsonObj.sort(function (a, b) { return parseFloat(a.Distance) - parseFloat(b.Distance) }); //$(jsonObj).sort(sortByDistance);

$.each(sorted, function () {
var address = "";
var dist = this["Distance"];
var lon = this["Point"].x;
var lat = this["Point"].y;
var splitAddr = this["Addr"].split(",");
for (var i = 0; i < splitAddr.length; i++) {
address += splitAddr[i] + "<br />&nbsp";
}
//The objects are appending to the table.
$('#tblAddressDispaly').append(
"<tr style='font-style:normal;color:blue;'><td id='location" + this["Value"] + "'>&nbsp;&nbsp;<b>" + this["Location"] + " </b></td><td valign='top'><b>" + this["Distance"] + " mi</b></td></tr>" +
"<tr id='traddrcalc'><td id='addressTd" + this["Value"] + "' colspan='2' align='left' style='font-style:normal;color:blue;width:50px;'>&nbsp;&nbsp;" + address + "</td></tr>" +
"<tr><td><a href='' style='text-decoranton:none;color:blue' onclick='return getDetailedMap(" + lon + "," + lat + "," + this["Value"] + ")'>Detailed Map</a></td></tr>" +
"<tr id='trsepcalc' style='color:blue;'><td colspan='2'>&nbsp;&nbsp;----------------------------------------------------</td></tr>");
});
}
}
});
}
In this the method where I collect all JSon Objects(Address, Location of restaurants coming from database)
and arrange all in ascending manner by distance calculating from the location searched by user(Wheaton).
Because Google map has no awareness of arranging the locations according to nearest area and can not sort the distances in ascending order..
So I have put all data into JSon format and by using JSon object I have sorted it. Then I put all arranged data  in <tr> <td> format and append it to Table.
Here I am passing the value to mark the location in Google map inside the "fillMapPoints" .

Code Snippet:
//This method marks all location with Blue Icon.

function createMarker(point, location, name, addr, type, miledistance,val) {
var marker = new GMarker(point, type);
var html = "<b>" + location + " </b> <br/>" + addr + "<br />" + "Distance:" + miledistance + "mi";
GEvent.addListener(marker, 'mouseover', function () {
marker.openInfoWindowHtml(html);
});
return marker;
}

This is all methods Described above , Hope it will help you.