As many of you know in my “free” time I manage, direct, and write code for a small company called txtMovieClub.com. It’s a pretty neat idea where we notify our subscribers of up coming movie screenings via SMS messaging.

One of the aspects to the project involves using google maps. Now since the project is written in php and uses symfony (which is flippin’ awesome!) I checked out phoogle. I’ll say this… it’s a good start and I like where Justin was going with it. It’s sexy, it’s abstract, neat. Unfortunately it just didn’t meet the needs for the page I was working on.

I decided to take a different approach. I wanted the map to be AJAX driven. If I wanted to modify the location I didn’t want to have to reload the map, I just wanted the map to clear its markers and recenter.

First things first, add the important keying information for google’s API. In the template that I was working in, let’s say editSuccess.php I added the following:

<?php slot('gmapheader'); ?>
<script type="text/javascript" src="http://www.google.com/jsapi?key=ABCDEFGHIJK_ENTER_YOUR_KEY"></script>
<script type="text/javascript">
google.load("maps", "2.x");
var map;
// Call this function when the page has been loaded
function initialize()
{
map = new google.maps.Map2(document.getElementById("map"));
var mapControl = new GMapTypeControl();
map.addControl(mapControl);

map.addControl(new GSmallMapControl());
map.addControl(new GScaleControl());

map.setCenter( new google.maps.LatLng(33.581411, -111.893215), 14);
map.disableDragging();

}
google.setOnLoadCallback(initialize);
</script>

<?php end_slot();?>

In the layout.php file of the app I added the following between <head> and </head>:

<?php if (has_slot('gmapheader')): ?>
<?php include_slot('gmapheader') ?>
<?php endif; ?>

When editSuccess.php gets loaded it will push all that javascript into the ‘gmapheader’ slot. Later, when layout.php finally gets compiled, it pulls in any content within ‘gmapheader’.

“So now what? Big whoop you’ve got a map.” Yes, but now I have a global ‘map’. Check out that javascript once more… map is declared as a global. This is really handy for me as I can now update that map using a remote_function call ala AJAX.

Here’s an example where I use a drop-down list of theaters that will update the markers on a list:

<?php echo object_select_tag($events,'getTheaterId',
array ('related_class' => 'Theaters',
'include_blank' => true,
'onchange' => remote_function( array('url' => 'events/map',
'with' => "'theater_id=' + value"))
)) ?>

The select tag will have a drop down list of theaters. When a new theater is selected the remote_function call makes a request to the events/map action.

A very basic events/map action would look like this:

public function executeMap()
{
$this->lat = 42.875036;
$this->lon = -78.877772;
}

In the respective view.yml file make sure that you’ve got something like:
mapSuccess:
has_layout: off

The code for updating the location on our map is in mapSuccess.php:

<?php $sf_context->getResponse()->setContentType('text/javascript')?>
map.clearOverlays();
map.addOverlay( new google.maps.Marker( new google.maps.LatLng(<?php echo $lat .','.
$lon; ?>)));
map.setCenter(new google.maps.LatLng(<?php echo $lat .','. $lon; ?>), 13);

Here the template will return javascript as its content type. The script itself wipes the map of overlays/markers, adds a new marker for the lat and lon determined in the action, finally setting the map’s center as the marker.

So that’s it in a nut shell. Eventually I’ll make this into a class and maybe post it here.