Customising Google Maps Markers pt.2, Graph Overlay

Quick update from the previous post: I decided I wanted to add more detail to my map by showing small pie charts instead of markers.

After trying and failing to use Google’s old Image Charts for the marker images, I found a very neat solution on StackOverflow that solves the problem nicely by rendering Google’s new interactive charts onto a custom overlay above the map:

map3

I then added a piehole to make overlapping charts easier to see:

map2

Passing in the extra data was also a slight pain because I needed to use a Dictionary<string, int> for the values of the pie chart, which csharp can’t serialise to JSON for some reason. Luckily someone has already written a nice serialisable version whcih did the job.

Next on the list is showing more details when clicking on the graph.

Customising Google Maps Markers

Quick delve into the world of Google maps this weekend when trying to map ADSL faults to their location.

My aims were to group the faults by the exchange they connect to, change the image icon, and resize it based on the number of faults at that exchange.

MarkerClusterer groups markers by proximity but doesn’t seem to allow custom grouping, so I decide to DIY it.

After testing the basics with PHP, I set up a simple WebService with C# that would provide the latitude and longitude of the Exchange, its name, and the number of faults. I then call the WebService using ajax:

[sourcecode language=”javascript”]

$.ajax({
type: "POST",
url: "WebService.asmx/GetMarkers",
data: ”,
contentType: "application/json; charset=utf-8", dataType: "json",
success: function (msg) {

[/sourcecode]

I then iterate through each object in the JSON array and use the count value for the number of faults to set the

[sourcecode language=”javascript”]

$.each(msg.d, function (index, item) {
size = 5 + Math.min( (item.Count / 2) * 5, 50);
var image = new google.maps.MarkerImage("disconnect2.png", null, null, null, new google.maps.Size(size, size));

[/sourcecode]

and then generate the marker with a custom image, the calculated size, and the exchange code:

[sourcecode language=”javascript”]

var marker = new google.maps.Marker({
position: new google.maps.LatLng(parseFloat(item.Lat), parseFloat(item.Long)),
map: map,
icon: image,
title: item.CircuitID
});

[/sourcecode]

And then we get this!

map

And the full source of my .aspx file:

[sourcecode language=”javascript”]

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html>
<html>
<head>
<title>Simple Map</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
html, body, #map-canvas {
margin: 0;
padding: 0;
height: 100%;
}
</style>

<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
<script>
var map;
function initialize() {
var mapOptions = {
zoom: 7,
center: new google.maps.LatLng(52.397, -2.244),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById(‘map-canvas’), mapOptions);

$.ajax({
type: "POST",
url: "WebService.asmx/GetMarkers",
data: ”,
contentType: "application/json; charset=utf-8", dataType: "json",
success: function (msg) {

$.each(msg.d, function (index, item) {
size = 5 + Math.min( (item.Count / 2) * 5, 50);
var image = new google.maps.MarkerImage("disconnect2.png", null, null, null, new google.maps.Size(size, size));

var marker = new google.maps.Marker({
position: new google.maps.LatLng(parseFloat(item.Lat), parseFloat(item.Long)),
map: map,
icon: image,
title: item.CircuitID
});
});
},
error: function (request, error, error2) { //alert(request + error + error2 + "failed");
}
});
}
google.maps.event.addDomListener(window, ‘load’, initialize);
</script>
</head>
<body>
<div id="map-canvas"></div>
</body>
</html>

[/sourcecode]

Using Chosen with ASP.net: pre filling and saving multiple selections

The problem
– You want to use Chosen to snazz up your dropdowns.
– You need to store the selected values.
– You need to prefill the selected values when the page is reloaded.
Setting up chosen: Add chosen to the project. The simplest way is to use NuGet Package Manager:

– Right click solution explorer > Manager NuGet Packages > Search for “chosen” > “Install”

Once it has installed you will need to reference it in your .aspx file:

<link href="../Content/chosen.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="../Scripts/chosen.jquery.js">script>

Add the chosen class to your select:
(The data-placeholder is the test shown before you make a selection)

<select class="chosen" data-placeholder="Select Recipients..." multiple="true" id="recipients" name = "recipientselect">select>

Initialise chosen:

<script type="text/javascript">
        $(document).ready(function () {
            //initialise the recipients field with Chosen
            $(".chosen").chosen();    
script>

Reading the selected fields:

In codebehind on postback we access the select using its name, and then split the results and loop through them:

 string recipients = Request.Form["recipientselect"];
        if (recipients != null) {
            string[] recList = recipients.Split(',');
            foreach (string rec in recList) {
                // save the selected recipients
            }
        }



Re-loading the selections into chosen:

Probably not the best way, but it works; I’ve set up a basic service returning the selected recipients and then added that selection to the dropdown:

function FillSelectedRecipients() {
            var docID = $("#<%= hidDocID.ClientID %>").val()

            if (docID.length > 0) {
                $.ajax({
                    type: "POST", url: "EchoService.asmx/GetRecipients",
                    data: '{"DocID": "' + $("#<%= hidDocID.ClientID %>").val() + '"}',
                    contentType: "application/json; charset=utf-8", dataType: "json",
                    success: function (msg) {
                        $("#recipients").val(msg.d).trigger("liszt:updated");
                    },
                    error: function () { 
                    }
                });
            }
        }

The recipients can be loaded in directly as json, but the chosen dropdown needs to be updated using

.trigger("liszt:updated")

in order to display correctly.