Please note that this article is old. Look at the assumptions section to understand what this was written for. The ideas are still relevant, but there may be better ways to accomplish the same things.

A more detailed version of this article, with screenshots, can be found here: http://alanpalazzolo.com/story/drupal-5-custom-gmap-node

Intro

I really enjoy Google Maps. And though they keep a little for themselves, the Google Maps API offers a really easy way to embed these maps into your own personal site. Fortunately for us Drupal users, the swell folks at the Chicago Technology Cooperative and the other wonderful open-source developers have put together an amazing module called GMap that integrates well with Location, Views, and even CCK (sort of).

I have recently set up this site to use the GMAP module. And since this module is still not had a stable release yet, I figured I would explain what I have done with this site to get some custom maps on each node. I will go through setting up CCK fields, custom theming, and some extras.

In Action

First, have a gander at what this will look like once we are done.

Goals

Given that I already have a bunch of nodes to create a Map View with, I want to also display a map on each of the nodes for that location or place. I also want the node maps to be customize for each node.

The main reason I would like this functionality is because I think in the context of a node that is a location, it should have a map with the node itself. Also, I think its a really nice feature to have control how that map looks. There are certain locations that I would like to be zoomed in real close, or that I want a map view, or a satellite view. This will give us that control.

Assumptions

The following is a list of assumptions in this process. If the following are not true, then this tutorial may not work for you.

GMap Bugs

There a couple things to note about this version of the GMap Module:

  • You will need to hack the GMap Module so that it uses the most recent stable version of the Google Maps API. See http://drupal.org/node/231473.
  • There are some inconsistencies between the API.txt file and the actual way to use the GMap API. See http://drupal.org/node/236352 for more information. For our purposes, the following needs to be noted for the associateive array that will be used to create each map:
    • Use controltype instead of control.
    • Use maptype instead of type.

Map Content Type

The first thing we need to do is set up a custom Content Type. This is where CCK and Location are going to come in.

Locative Information

First ensure, that Locative Information is added. When creating the Content Type, it will be at the top of the form. It's kind of hard to notice. Make sure that Maximum number of locations allowed for this type. is at least 1 and Default number of location forms is also at least 1. Plaese note that this tutorial is assuming one location per node. This could easily be changed so that it handled more that one location. Enabling this Location information, will ensure that Latitude and Longitude are collected. Again this could be changed to CCK fields instead.

CCK Map Parameters

Now you will want to create a set of fields to represent your map parameters. You can add or remove the ones you want. You will want to look at the GMap Macro Creator page that comes with GMap. Here is a brief description of my fields:

Map Width - field_cck_txt_map_width - Text - Text Field
Map Height - field_cck_txt_map_height - Text - Text Field
Marker - field_cck_select_marker - Text - Select List
Magnification - field_cck_select_magnification - Text - Select List
Control Type - field_cck_select_map_control - Text - Select List
Map Type - ield_cck_select_map_type - Text - Select List

The Select Lists should be filled appropriately from the GMap Macro Creator page. Hint: changes some values and note the macro at the bottom. Please note that these values are Case Sensitive.

Theming

Now that we have our content type set up, now we just have to determine how it is going to render all this information. Feel free to make a couple nodes with this new content type, as it will help you see what is happening.

Display Function

We will create a function in our template.php file, in our theme directory, so that calling the map in the theme will be simple.

#function to make Gmap macro data into a map
function your_theme_node_map_maker($id, $mark, $lat, $long, $zoom, $width, $height, $control, $map_type) {
    #intialize output
    $output = '';
    
    #put together array
    $arr_map = array(
        'id' => $id
        ,'zoom' => $zoom
        ,'width' => $width
        ,'height' => $height
        ,'latitude' => $lat
        ,'longitude'=> $long
        ,'maptype' => $map_type
        ,'controltype' => $control
        ,'markers' => array(
            array(
                'markername' => $mark
                ,'latitude' => $lat
                ,'longitude' => $long
            )
        )
    );

    #display map through GMap theme function
    $output = theme('gmap', array('#settings' => $arr_map));
    
    #return output
    return $output;
} #end function

This should be pretty straightforward. It would not be too difficult to actually put this in the theme itself, but this way we could do some processing if necessary.

Calling the Function in the Theme

There is a couple ways to do this depending on how you like to make or edit themes. You can use the Content Template Module. But I like to stick with the traditional file method.

Here is my sample node-ct-map.tpl.php file:

<?php if ($page == 0) { ?><h2 class="title"><a href="<?php print $node_url?>"><?php print $title?></a></h2><?php }; ?>

<div class="entry<?php if ($sticky) { print " sticky"; } ?>">
    <?php if ($picture) { print $picture; }?>

    <div class="ct-map-content"><?php print $node->content['body']['#value'] ?></div>
    
    <fieldset class="fieldgroup group-visits">
        <legend>Visits</legend>
        <?php 
            # this is a custom view of multiple visits
            print custom_visits($node->field_cck_date_location_start, $node->field_cck_txt_visited_descripti) 
        ?>
    </fieldset>

    <?php if ($node->content['field_cck_img_map_images']['#value']) { ?>
    <fieldset class="fieldgroup group-map-pictures">
        <legend>Pictures</legend>
        <?php print $node->content['field_cck_img_map_images']['#value'] ?>
    </fieldset>
    <?php } ?>
    
    <?php 
        # Call Map Function
        # I have separated the parameters so that it easier to see
        print your_theme_node_map_maker(
            $node->nid, $node->field_cck_select_marker[0]['view']
            ,$node->locations[0]['latitude']
            ,$node->locations[0]['longitude']
            ,$node->field_cck_select_magnification[0]['view']
            ,$node->field_cck_txt_map_width[0]['view']
            ,$node->field_cck_txt_map_height[0]['view']
            ,$node->field_cck_select_map_control[0]['view']
            ,$node->field_cck_select_map_type[0]['view']
        ) ?>
    
    <?php print alanpalazzolo_custom_location($node->location) ?>

</div>

<div class="meta">
    <p class="byline"><?php print $submitted?></p>
    <?php if ($terms) { ?><p><span class="taxonomy"><?php print $terms?></span></p><?php }; ?>
    <?php if ($links) { ?><p class="links"><?php print $links?></p><?php }; ?>
</div>

Check Our Work

Now, when going to the nodes that we have created, there should be a map with the parameters we have set on them.

Views

This should be a fairly easy process. Create a new view.

  • Page Section
    • click Provide Page View
    • choose a URL
    • this is where the magic happens; under View Type choose GMap View
  • Fields Section
    • Location: Latitude
    • Location: Longitude (This is where the CCK fields could be substituted.)
    • I would also suggest choosing the Node: Title field so that there is link in each info bubble
  • Filter Section
    • Node: Published is Yes
    • Node: Type is One Of Map Type (This is the type that we defined above)

Zooming In

You can set limits on how far people can zoom in if, for example, you want to show a gmap of all your users but don't want to show the whole world how to get to someone's house.

You can add this code either to your custom module, the header or footer of your view, or wherever.

<?php
$maxresolution = 10;
$minresolution = 2;

$setmapzoomlimit = "
G_PHYSICAL_MAP.getMinimumResolution = function () { return $minresolution };
G_NORMAL_MAP.getMinimumResolution = function () { return $minresolution };
G_SATELLITE_MAP.getMinimumResolution = function () { return $minresolution };
G_HYBRID_MAP.getMinimumResolution = function () { return $minresolution};

G_PHYSICAL_MAP.getMaximumResolution = function () { return $maxresolution };
G_NORMAL_MAP.getMaximumResolution = function () { return $maxresolution };
G_SATELLITE_MAP.getMaximumResolution = function () { return $maxresolution };
G_HYBRID_MAP.getMaximumResolution = function () { return $maxresolution };";

drupal_add_js($setmapzoomlimit, 'inline');
?>

There are other ways of setting these, but this seems to be the easiest.