public function OnLoadPageData()
    {
        require_once 'stoolball/competition-manager.class.php';
        $manager = new CompetitionManager($this->GetSettings(), $this->GetDataConnection());
        $manager->ReadById(null, array($this->season_id));
        $competition = $manager->GetFirst();
        unset($manager);
        if (!$competition instanceof Competition) {
            return;
        }
        require_once 'stoolball/ground-manager.class.php';
        $manager = new GroundManager($this->GetSettings(), $this->GetDataConnection());
        $manager->FilterBySeason(array($competition->GetWorkingSeason()->GetId()));
        $manager->ReadAll();
        $grounds = $manager->GetItems();
        unset($manager);
        ?>
$(function() {
// Make the placeholder big enough for a map
var mapControl = document.getElementById("map");
mapControl.style.width = '100%';
mapControl.style.height = '500px'; // Create the map var
var bounds = new google.maps.LatLngBounds();
var myOptions = { mapTypeId : google.maps.MapTypeId.ROADMAP };
var map = new google.maps.Map(mapControl, myOptions);
var markers = [];
var info;
		<?php 
        foreach ($grounds as $ground) {
            /* @var $ground Ground */
            if (!$ground->GetAddress()->GetLatitude() or !$ground->GetAddress()->GetLongitude()) {
                continue;
            }
            $content = "'<div class=\"map-info\">' +\n\t'<h2>" . str_replace("'", "\\'", Html::Encode($ground->GetNameAndTown())) . "</h2>' +\n\t'<p>Home to: ";
            $teams = $ground->Teams()->GetItems();
            $length = count($teams);
            for ($i = 0; $i < $length; $i++) {
                if ($i > 0 and $i == $length - 1) {
                    $content .= " and ";
                } else {
                    if ($i > 0) {
                        $content .= ", ";
                    }
                }
                $content .= '<a href="' . Html::Encode($teams[$i]->GetNavigateUrl()) . '">' . str_replace("'", "\\'", Html::Encode($teams[$i]->GetNameAndType())) . '</a>';
            }
            $content .= "</p></div>'";
            # And marker and click event to trigger info window. Wrap info window in function to isolate marker, otherwise the last marker
            # is always used for the position of the info window.
            echo "var marker = new google.maps.Marker({\n\t\t\tposition : new google.maps.LatLng(" . $ground->GetAddress()->GetLatitude() . "," . $ground->GetAddress()->GetLongitude() . "),\n\t\t\tshadow: Stoolball.Maps.WicketShadow(),\n\t\t\ticon: Stoolball.Maps.WicketIcon(),\n\t\t\ttitle : '" . str_replace("'", "\\'", $ground->GetNameAndTown()) . "'\n\t\t  });\n\t\t  markers.push(marker);\n\t\t  bounds.extend(marker.position);\n\n\t\t  (function(marker){\n\t\t\t  google.maps.event.addListener(marker, 'click', function()\n\t\t\t  {\n\t\t\t  \tvar content = {$content};\n\t\t\t  \tif (!info) info = new google.maps.InfoWindow();\n\t\t\t  \tinfo.setContent(content);\n\t\t\t  \tinfo.open(map, marker);\n\t\t\t  });\n\t\t  })(marker);\n\t\t  ";
        }
        ?>
map.fitBounds(bounds);
var style = [{ url: '/images/features/map-markers.gif', height: 67, width: 31, textColor: '#ffffff', textSize: 10 }];
var clusterer = new MarkerClusterer(map, markers, { 'gridSize': 30, styles: style});
});
		<?php 
        exit;
    }