Branch/shop/… locator for Umbraco Razor style 7
A while ago I created a locator package for umbraco that made it pretty easy to add find nearest branch/shop/dealer/… functionality to your umbraco site.
To sharpen my razor skills I thought it would be great to try to port this from xslt to razor and turns out this was pretty easy (feel the power of the dark side).
Another update is that it now uses the google maps api v3 so no more need for api keys
It works in combination with the google maps datatype so you’ll need to make sure that your documents have coordinates stored before you are able to search (so a property of the type google maps using the google maps datatype).
Once the documents you want to search through have a long/lat stored you can use the locator macro.
The macro has 4 parameters
- Document type alias of the documents you want to search through
- Property alias of the property containing the coordinates
- If you want the units in miles instead of km
- Number of results to display
If you have the macro on a page/template you’ll need to provide it with a search location. So posting to that page with a querystring variable s will do the trick like ?s=gentbrugge
The default output is pretty simple,
- Search location
- Map with markers
- Unordered list of results ordered by distance from search location
But that can be updated to your needs. There is some stuff going on in the locator assembly but the output can be completely customized by updating the razor script.
@inherits umbraco.MacroEngines.DynamicNodeContext
@using Locator
@using Locator.GeoCoding
@using Locator.GeoCoding.Services.Google
@using umbraco.MacroEngines;
@{
@* Select the nodes you want to search through, defaults to children *@
var nodesToSearchThrough = string.IsNullOrEmpty(Parameter.DocTypeAlias) ?
Model.Children.Where("Visible"): Model.AncestorOrSelf(1).Descendants(Parameter.DocTypeAlias).Where("Visible");
@* Alias of the property containing the long/lat, defaults to location *@
string locationPropAlias = string.IsNullOrEmpty(Parameter.LocationPropAlias) ?
"location" : Parameter.locationPropAlias;
@* Number of results, defaults to 5 *@
int numberOfSearchResults = string.IsNullOrEmpty(Parameter.NumberOfResults)|| Parameter.NumberOfResults == "0" ?
5 : int.Parse(Parameter.NumberOfResults);
@* Distance unit, defaults to km *@
DistanceUnits distanceunit = Parameter.UnitInMiles == "1" ?
DistanceUnits.Miles : DistanceUnits.Kilometers;
List<GeoItem> items = new List<GeoItem>();
Location searchLocation = new Location();
if(string.IsNullOrEmpty(Request["s"]))
{
@* Search term not provided *@
<p>Please provide a search term</p>
}
else
{
@* Lookup search location coordinates *@
GeoResponse r = GoogleGeoCoder.CallGeoWS(Request["s"]);
if(r.Results.Length == 0)
{
@* Location not found *@
<p>Location not found: @Request["s"]</p>
}
else
{
@* build up list of results *@
searchLocation = new Location(r.Results[0].Geometry.Location.Lat, r.Results[0].Geometry.Location.Lng);
foreach (var node in nodesToSearchThrough) {
Location itemLocation = new Location(
Convert.ToDouble(node.GetProperty(locationPropAlias).ToString().Split(‘,’)[0], Utility.NumberFormatInfo),
Convert.ToDouble(node.GetProperty(locationPropAlias).ToString().Split(‘,’)[1], Utility.NumberFormatInfo));
items.Add(new GeoItem(node,itemLocation,searchLocation.DistanceBetween(itemLocation,distanceunit)));
}
@* sort based on distance *@
items.Sort(new GeoItemComparer());
}
}
}
@if(items.Count > 0)
{
@* Output Results *@
<p>Result for: @Request["s"]</p>
@* Output Map *@
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false">
</script>
<div id="map_canvas" style="width:500px; height:500px"></div>
<script type="text/javascript">
function initialize() {
var latlng = new google.maps.LatLng(
@searchLocation.Latitude.ToString(Utility.NumberFormatInfo),
@searchLocation.Longitude.ToString(Utility.NumberFormatInfo));
var myOptions = {
zoom: 8,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"),
myOptions);
@{int c = 1;}
@foreach(GeoItem geo in items.Take(numberOfSearchResults)){
dynamic node = ((DynamicNode)geo.Node);
<text>
var mLatlng@(c) = new google.maps.LatLng(
@geo.Location.Latitude.ToString(Utility.NumberFormatInfo),
@geo.Location.Longitude.ToString(Utility.NumberFormatInfo));
var marker@(c) = new google.maps.Marker({
position: mLatlng@(c) ,
map: map,
title:"@node.Name"
});
</text>
c++;
}
}
initialize();
</script>
@* Output list *@
<ul>
@foreach(GeoItem geo in items.Take(numberOfSearchResults)){
dynamic node = ((DynamicNode)geo.Node);
<li><a href="@node.Url">@node.Name - @geo.Distance.ToString("0.00") km</a></li>
}
</ul>
}
Package can be downloaded on the project page: http://our.umbraco.org/projects/developer-tools/locator-razor-style
