views:

188

answers:

4

I'm creating a Google Maps partial view/user control in my project that is passed a strongly typed list of objects containing latitude and longitude values.

Currently, this is the code I have for the partial:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Project.Models.Entities.Location>>" %>
<!-- Place for google to put the map -->
<div id="report_map_canvas" style="width: 100%; height: 728px; margin-bottom: 2px;">
</div>

<script type='text/javascript'>    
google.load("maps", "2");
$(document).ready(initializeMap);

function initializeMap() {
    if (GBrowserIsCompatible()) {
        var map = new GMap2(document.getElementById('report_map_canvas'));
        map.setCenter(new GLatLng(51.5, -0.1167), 2);
        <% foreach (var item in Model) { %>
        map.addOverlay(new GMarker(new GLatLng('<%= Html.Encode(item.latitude)%>','<%= Html.Encode(item.longitude)%>'),{ title: '<%= Html.Encode(String.Format("{0:F}",item.speed)) %> km/h '}));
        <% } %>
        map.setUIToDefault();
    }
}
</script>

Is it right to dynamically create the javascript file this way by looping over the list and emitting javascript?

Is there a better way to do it?

A: 

Theres nothing wrong with preloading your data with the rendering of your page (which is effectivly what you are doing with the loop, perhaps you could output json within your page and write some javascript to eval it (which would cut down on repedative charaters ie map.addOverlay ...) You just have to lookout for unconstrained output from your model, you wouldnt want 1 000 000 records being rendered this way

almog.ori
+1  A: 

i don't prefer this way because if you have many items to add you will make a big document to load for the user. instead I prefer to load the items as JSON and then iterate them and use google functions, eg:

var data = [<%="{x:50.44444,y:30.44444,speed:50},..."  %>] // generate you JSON Here as array

for(var i = 0; i < data.length; i++){
map.addOverlay(new GMarker(new GLatLng(data[i].y,data[i].x),{ title: data[i].speed + 'Km/h'}));
}

so you will not repeat this part

 map.addOverlay(new GMarker(new GLatLng(,),{ title:  + 'Km/h'}));

which will increase the document size and page load

Kronass
Do you think generating the data JSON array in the view is good enough or should I offload this somehow to the controller?
sabbour
in this case I prefer just to keep it in the View.
Kronass
+1  A: 

It's about as pretty as it gets.

Slightly better way IMO would be to do something like this:

var locations = <%= Html.ToJson(Model) %>

at the top, and then your JavaScript would be pure JavaScript without embedded C# stuff.

PS: You would need to extend HtmlHelper with a ToJson method in order to do this.

mookid8000
A: 

ended up mixing both answers of Kronass and mookid.

Here is the final code for reference:

public static class MvcViewExtensions
{
    public static string ToJson(this System.Web.Mvc.HtmlHelper helper, object obj) {
        JavaScriptSerializer serializer = new JavaScriptSerializer();
        return serializer.Serialize(obj);
    }
}

And the javascript in the view:

<script type='text/javascript'>    
google.load("maps", "2");
$(document).ready(initializeReportMap);

function initializeReportMap() {    
    if (GBrowserIsCompatible()) {    
        // Convert the reports to JSON
        var reports = <%= Html.ToJson(Model) %>
        var map = new GMap2(document.getElementById('report_map_canvas'));
        map.setCenter(new GLatLng(51.5, -0.1167), 3);
        for(var i = 0; i < reports.length; i++){
            map.addOverlay(new GMarker(new GLatLng(reports[i].latitude,reports[i].longitude),{ title: reports[i].speed + 'Km/h'}));
        }
        map.setUIToDefault();
    }
}
</script>
sabbour