GoogleMapMarker

http://modxcms.com/extras/package/?package=183からDL。
こちらのサイトを参考に入れました。
まずはダウンロードしたファイルの中身をスニペット名:GoogleMapMarkerとして作成。

<?php
/* Snippet name: [[GoogleMapMarker]]
 * Version: 1.0c for ditto v2+
 * Author: doze <dozebox@gmail.com>
 * 
 * Snippet to generate goolemaps map and place markers 
 * to the maps from documents.
 * 
 * Installation:
 * -------------
 * 1. Create a snippet "phx:slashandstrip" with this content:
 *    return addcslashes(preg_replace("~([\n\r\t\s]+)~"," ",$output), "'");
 *
 * 2. Call the snippet in some document: [[GoogleMapMarker? &apikey=`ABQIA..`]]
 * 
 * How to place markers:
 * ---------------------
 * 1. Create a folder in MODx manager what will keep the marker documents, can be unpublished.
 * 2. Create a new document inside that folder what will be the marker
 *    - Title: Will be used as the marker "sidelink" text (example: My home)
 *    - Description: The coordinates for the marker (example: 63.098332,23.056698)
 *    - Document content: HTML to show in the marker popup. 
 *                        NOTE: You have to escape all ' characters by putting backslash before them, e.g. \'
 * 3. Add the &startID parameter to the snippet call pointing to the folder what has the marker documents
 *    example: [[GoogleMapMarker? &apikey=`ABQIA..` &startID=`52`]]
 *
 * Example GoogleMapMarker template chunk (&tpl)
 * ---------------------------------------------
 * The template must have 2 divs. A div for the map and div for the side links. That's it.
 *
 *  <div id="map" style="float:left; width: 350px; height: 350px;">Loading map...</div>
 *  <div id="maplinks" style="margin-left: 10px; padding-right: 10px; float: left; display: block; height: 350px; overflow: auto;"></div>
 *
 */

////////////////////////////////////////////////////////
// Parameter default values configuration
////////////////////////////////////////////////////////

// [text]
// The Google Maps api key to use (http://www.google.com/apis/maps/signup.html)
$apiKey = (isset($apiKey)) ? $apiKey : "";

// [number]
// The ID number of the top folder that has google marker documents
$startID = (isset($startID)) ? $startID : "";

// [number]
// Number of levels deep to go
$descendentDepth = (isset($descendentDepth)) ? $descendentDepth : 1;

// [text]
// Field to sort by (recommended values include createdon, pub_date, editedon)
$sortBy = (isset($sortBy)) ? $sortBy : "createdon";

// ["DESC" | "ASC"]
// Direction to sort by, either ASC (ascending) or DESC (descending)
$sortDir = (isset($sortDir)) ? $sortDir : "ASC";

// [text]
// Chunk name to use as a template
$tpl = (isset($tpl)) ? $tpl : "";

// [text]
// Id name of the div where the map will be rendered
$mapDiv = (isset($mapDiv)) ? $mapDiv : "map";

// [text]
// Id name of the div where the marker links will be rendered
$linksDiv = (isset($linksDiv)) ? $linksDiv : "maplinks";

// [text]
// Class name to use in the marker links
$linksClass = (isset($linksClass)) ? $linksClass : "maplink";

// ["normal" | "satellite" | "hybrid"]
// Initial type of the map
$mapType = (isset($mapType)) ? $mapType : "normal";

// [latitude,longitude]
// Coordinates to the initial center position of the map
$centerPos = (isset($centerPos)) ? $centerPos : "63.098332,23.056698";

// [number]
// Initial zoomlevel for the map
$defaultZoom = (isset($defaultZoom)) ? $defaultZoom : "8";

// ["large" | "small" | "zoomonly" | "none"]
// Look of the controls to navigate / zoom the map
$mapControl = (isset($mapControl)) ? $mapControl : "large";

// ["large" | "small" | "none"]
// Look of the controls to change the map type
$mapTypeControl = (isset($mapTypeControl)) ? $mapTypeControl : "large";

// [0 | 1]
// When mouse cursor is moved over the map marker, should the info box open on that marker?
$openMouseOverMarker = (isset($openMouseOverMarker)) ? $openMouseOverMarker : 0;

// [0 | 1]
// When the map marker is clicked, should the info box open on that marker?
$openMouseClickMarker = (isset($openMouseClickMarker)) ? $openMouseClickMarker : 1;

// [0 | 1]
// When mouse cursor is moved over the textual marker link, should the info box open on that marker?
$openMouseOverLink = (isset($openMouseOverLink)) ? $openMouseOverLink : 0;

// [0 | 1]
// When the textual marker link is clicked, should the info box open on that marker?
$openMouseClickLink = (isset($openMouseClickLink)) ? $openMouseClickLink : 1;

// [0 | 1]
// Show overview map in the right bottom corner of the map?
$showOverviewMap = (isset($showOverviewMap)) ? $showOverviewMap : 1;

// [width,heigth]
// Size of the overview map
$overviewMapSize = (isset($overviewMapSize)) ? $overviewMapSize : "150,150";

// [0 | 1]
// Should the overview map be hidden by default? (arrow indicator visible at the bottom right corner)
$hideOverviewMapByDefault = (isset($hideOverviewMapByDefault)) ? $hideOverviewMapByDefault : 1;

// [text]
// Name of the Ditto snippet
$dittoName = (isset($dittoName)) ? $dittoName : "Ditto";

////////////////////////////////////////////////////////
// Start of snippet code
////////////////////////////////////////////////////////

if($apiKey != "") {

    $script = '
        <script type="text/javascript">
        //<![CDATA[
            
            // addEvent scripts written by Dean Edwards, 2005
            // with input from Tino Zijdel, Matthias Miller, Diego Perini
            // http://dean.edwards.name/weblog/2005/10/add-event/

            function addEvent(element, type, handler) {
                if (element.addEventListener) {
                    element.addEventListener(type, handler, false);
                } else {
                    // assign each event handler a unique ID
                    if (!handler.$$guid) handler.$$guid = addEvent.guid++;
                    // create a hash table of event types for the element
                    if (!element.events) element.events = {};
                    // create a hash table of event handlers for each element/event pair
                    var handlers = element.events[type];
                    if (!handlers) {
                        handlers = element.events[type] = {};
                        // store the existing event handler (if there is one)
                        if (element["on" + type]) {
                            handlers[0] = element["on" + type];
                        }
                    }
                    // store the event handler in the hash table
                    handlers[handler.$$guid] = handler;
                    // assign a global event handler to do all the work
                    element["on" + type] = handleEvent;
                }
            };
            // a counter used to create unique IDs
            addEvent.guid = 1;

            function removeEvent(element, type, handler) {
                if (element.removeEventListener) {
                    element.removeEventListener(type, handler, false);
                } else {
                    // delete the event handler from the hash table
                    if (element.events && element.events[type]) {
                        delete element.events[type][handler.$$guid];
                    }
                }
            };

            function handleEvent(event) {
                var returnValue = true;
                // grab the event object (IE uses a global event object)
                event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
                // get a reference to the hash table of event handlers
                var handlers = this.events[event.type];
                // execute each event handler
                for (var i in handlers) {
                    this.$$handleEvent = handlers[i];
                    if (this.$$handleEvent(event) === false) {
                        returnValue = false;
                    }
                }
                return returnValue;
            };

            function fixEvent(event) {
                // add W3C standard event methods
                event.preventDefault = fixEvent.preventDefault;
                event.stopPropagation = fixEvent.stopPropagation;
                return event;
            };
            fixEvent.preventDefault = function() {
                this.returnValue = false;
            };
            fixEvent.stopPropagation = function() {
                this.cancelBubble = true;
            };
                
            addEvent(window, "unload", GUnload);

            if (GBrowserIsCompatible()) {
                // Display the map, with some controls
                var map = new GMap2(document.getElementById("'.$mapDiv.'"));
                // set initial center position
                map.setCenter(new GLatLng('.$centerPos.'),'.$defaultZoom.');
    
                //add controls to navigate / zoom
                ';

    if ($mapControl == "zoomonly") {
        $script .= '
                map.addControl(new GSmallZoomControl());';
    } else if ($mapControl == "large") {
        $script .= '
                map.addControl(new GLargeMapControl());';
    } else if ($mapControl == "small") {
        $script .= '
                map.addControl(new GSmallMapControl());';
    }

    if ($mapTypeControl == "large") {
        $script .= '
                // add controls to change map type
                map.addControl(new GMapTypeControl(0));';
    } else if ($mapTypeControl == "small") {
        $script .= '
                // add controls to change map type
                map.addControl(new GMapTypeControl(1));';
    }

        $script .= '
                //set initial map type
                ';
    if ($mapType == "normal") {
        $script .= '
                map.setMapType(G_NORMAL_MAP);';
    } else if ($mapType == "satellite") {
        $script .= '
                map.setMapType(G_SATELLITE_MAP);';
    } else if ($mapType == "hybrid") {
        $script .= '
                map.setMapType(G_HYBRID_MAP);';
    }
        $script .= '
                // arrays to hold copies of the markers and html used by the sidebar
                // because the function closure trick doesnt work there
                var sidebar_html = "";
                var gmarkers = [];
                var htmls = [];
                var i = 0;

                // a function to create the marker and set up the event window
                function createMarker(point,name,html) {
                    var marker = new GMarker(point);';

    if($openMouseClickMarker) {
        $script .= '
                    // event listener to open info on click
                    GEvent.addListener(marker, "click", function(){
                        marker.openInfoWindowHtml(html);
                    });';
    }

    if($openMouseOverMarker) {
        $script .= '
                    // The new marker "mouseover" listener
                    GEvent.addListener(marker,"mouseover", function(){
                        marker.openInfoWindowHtml(html);
                    });';
    }

        $script .= '    
                    // save the info we need to use later for the sidebar
                    gmarkers[i] = marker;
                    htmls[i] = html;
                    // add a line to the sidebar html
                    sidebar_html += \'<div class="'.$linksClass.'"><a href="javascript:void(0)" ';

    if($openMouseClickLink) {
        $script .= 'onClick="myclick(\' + i + \')"';
    }

    if($openMouseOverLink) {
        $script .= 'onMouseOver="myclick(\' + i + \')"';
    }

        $script .= '>\' + name + \'</a></div>\';
                    i++;

                    return marker;
                }

                // This function picks up the click and opens the corresponding info window
                function myclick(i) {
                    gmarkers[i].openInfoWindowHtml(htmls[i]);
                }';
    if($startID != "") {

        $script .= $modx->runSnippet($dittoName,array('depth' => $descendentDepth, 'sortBy' => $sortBy, 'sortDir' => $sortDir, 'summarize' => 'all', 'displayArchive' => '0', 'tpl' => '@CODE:var point = new GLatLng([+description+]); var marker = createMarker(point, \'[+title:slashandstrip+]\', \'[+content:slashandstrip+]\'); map.addOverlay(marker);', 'parents' => $startID, 'showPublishedOnly' => '0'));

        $script .= '
                // put the assembled sidebar_html contents into the sidebar div
                document.getElementById("'.$linksDiv.'").innerHTML = sidebar_html;';
    }

    if($showOverviewMap) {
        $script .= '
                // ======== Add a map overview ==========
                var ovcontrol = new GOverviewMapControl(new GSize('.$overviewMapSize.')); 
                map.addControl(ovcontrol,new GControlPosition(G_ANCHOR_BOTTOM_RIGHT, new GSize(10, 10)));';
    }
    if($hideOverviewMapByDefault) {
        $script .= '
                //set hidden by default (without animation)
                ovcontrol.hide(1);';
    }
        $script .= '
            } else { // !GBrowserIsCompatible()
                alert("Sorry, the Google Maps API is not compatible with this browser");
            }
    
            // This Javascript is based on code provided by the
            // Blackpool Community Church Javascript Team
            // http://www.commchurch.freeserve.co.uk/ 
            // http://www.econym.demon.co.uk/googlemaps/

        //]]>
        </script>
        ';

    //register scripts
    $modx->regClientScript($script);
    $modx->regClientStartupScript("http://maps.google.com/maps?file=api&amp;v=2&amp;key=".$apiKey);

    if($tpl == "") {
        $returnstring = '
            <div id="'.$mapDiv.'" style="float:left; width: 350px; height: 350px;">Loading map...</div>
            <div id="'.$linksDiv.'" style="margin-left: 10px; padding-right: 10px; float: left; display: block; height: 350px; overflow: auto;"></div>
            <noscript>
                <b>JavaScript must be enabled in order for you to use Google Maps.</b> 
                However, it seems JavaScript is either disabled or not supported by your browser.
                To view Google Maps, enable JavaScript by changing your browser options, and then
                try again.
            </noscript>
            ';
    } else {
        $returnstring = $modx->getChunk($tpl);
    }
} else {
    if ($apiKey == "") {
        $returnstring = '
                        You have to provide a Google Maps API key to use!<br />
                        If you don\'t have one yet, go <a href="http://www.google.com/apis/maps/signup.html" alt="Sign up for the Google Maps API">here</a> to get it. NOTE: the api key is site/directory specific!<br /><br />
                        ';
    }

}

return $returnstring;
?>

次にスニペット名:「phx:slashandstrip」としてスニペットを作成。

<?php
return addcslashes(preg_replace("~([\n\r\t\s]+)~"," ",$output), "'");
?>

スニペットコールは

[!GoogleMapMarker? &apiKey=`AAA...`!]

キャッシュ可でも動くそうですが。キャッシュしないほうがいいともあるのでとりあえず。
 
以下パラメータ
apiKey
APIキー。
startID
Dittoのparentsみたいなの。マーカー設定ファイルの親フォルダを指定する。
centerPos
初期マップの中心地を指定。後述のマーカー座標なんかもGeocoding使うと便利です。
defaultZoom
拡大・縮小の値。デフォルトは8。数字が大きくなれば拡大される。
showOverviewMap
オーバービューを表示するかどうか。デフォルトは1(する)。
tpl
出力用テンプレートを指定。
テンプレートの基本形は

<div id="'.$mapDiv.'" style="float:left; width: 350px; height: 350px;">Loading map...</div>
<div id="'.$linksDiv.'" style="margin-left: 10px; padding-right: 10px; float: left; display: block; height: 350px; overflow: auto;"></div>
<noscript>
<b>JavaScript must be enabled in order for you to use Google Maps.</b> 
However, it seems JavaScript is either disabled or not supported by your browser.
To view Google Maps, enable JavaScript by changing your browser options, and then
try again.
</noscript>

$mapDivはマップ出力ボックス、$linkDivはマップリンク出力ボックス。
スタイルシート削っただけでも動かなくなったので、$mapDivと$linksDivはきちんとしたIDで指定する必要があるようです。
mapDiv
マップ出力ボックスのIDを指定。テンプレート内で指定したものと対応していなければ表示されない。
linksDiv
同じくマップリンク出力ボックス。これまたテンプレート内で指定したものと要対応。
テンプレート(map_tpl)で指定したマップ出力ボックスのIDがmaparea、マップリンク出力ボックスのIDがmaplinksareaだった場合、スニペットコールは

[!GoogleMapMarker &apiKey=`AAA...` &tpl=`map_tpl` &mapDiv=`maparea` &linksDiv=`maplinksarea`!]

みたいな形になる。
 
 
マーカー用ファイル
マーカーはひとつにつきひとつのファイルを用意する形になります。
タイトル:マーカー名
説明:座標
本文:インフォメーションボックス内容
マーカー用ファイルは非公開にしておく必要があります。
また、インフォメーションボックスの内容は、HTMLは使えそうなんですが、Pタグを挿入すると微妙に何かと干渉しているようで、最終行がボックスからはみ出して表示される(Firefoxのみ)というレイアウトずれが発生します。
 
インフォメーションボックスの大きさとかマーカーの画像を変更するとかいろいろやりたいことはあるんだがとりあえず表示できたので良し。
ksgmapは高機能なんだが、MODx内ではどうもXMLファイルをうまく読み込んでくれないようでした。
ソースをまるっとコピーしてMODxの外に置いたらきちんと表示されたので。ただ現在の環境ではMODxの外=テンプレート外というのは大変に不便なので、とりあえずスニペットで動かしてみることに。
 
 
追記:
googlemapmarkerではその仕様上、どうしても樹形図のようになります。つまるところ、複数カテゴリによる絞込みとかが不可能ということです。
一応、Dittoからデータを引っ張る形で整形してるので、頑張ればDittoで使ってるフィルタなども使えるはず。
ということでやってみた。

<?php
/* Snippet name: [[GoogleMapMarker]]
 * Version: 1.0c for ditto v2+
 * Author: doze <dozebox@gmail.com>
 * 
 * Snippet to generate goolemaps map and place markers 
 * to the maps from documents.
 * 
 * Installation:
 * -------------
 * 1. Create a snippet "phx:slashandstrip" with this content:
 *    return addcslashes(preg_replace("~([\n\r\t\s]+)~"," ",$output), "'");
 *
 * 2. Call the snippet in some document: [[GoogleMapMarker? &apikey=`ABQIA..`]]
 * 
 * How to place markers:
 * ---------------------
 * 1. Create a folder in MODx manager what will keep the marker documents, can be unpublished.
 * 2. Create a new document inside that folder what will be the marker
 *    - Title: Will be used as the marker "sidelink" text (example: My home)
 *    - Description: The coordinates for the marker (example: 63.098332,23.056698)
 *    - Document content: HTML to show in the marker popup. 
 *                        NOTE: You have to escape all ' characters by putting backslash before them, e.g. \'
 * 3. Add the &startID parameter to the snippet call pointing to the folder what has the marker documents
 *    example: [[GoogleMapMarker? &apikey=`ABQIA..` &startID=`52`]]
 *
 * Example GoogleMapMarker template chunk (&tpl)
 * ---------------------------------------------
 * The template must have 2 divs. A div for the map and div for the side links. That's it.
 *
 *  <div id="map" style="float:left; width: 350px; height: 350px;">Loading map...</div>
 *  <div id="maplinks" style="margin-left: 10px; padding-right: 10px; float: left; display: block; height: 350px; overflow: auto;"></div>
 *
 */

////////////////////////////////////////////////////////
// Parameter default values configuration
////////////////////////////////////////////////////////

// [text]
// The Google Maps api key to use (http://www.google.com/apis/maps/signup.html)
$apiKey = (isset($apiKey)) ? $apiKey : "";

// [number]
// The ID number of the top folder that has google marker documents
$startID = (isset($startID)) ? $startID : "";

// [number]
// Number of levels deep to go
$descendentDepth = (isset($descendentDepth)) ? $descendentDepth : 1;

// [text]
// Field to sort by (recommended values include createdon, pub_date, editedon)
$sortBy = (isset($sortBy)) ? $sortBy : "createdon";

// ["DESC" | "ASC"]
// Direction to sort by, either ASC (ascending) or DESC (descending)
$sortDir = (isset($sortDir)) ? $sortDir : "ASC";

// [text]
// Chunk name to use as a template
$tpl = (isset($tpl)) ? $tpl : "";

// [text]
// Id name of the div where the map will be rendered
$mapDiv = (isset($mapDiv)) ? $mapDiv : "map";

// [text]
// Id name of the div where the marker links will be rendered
$linksDiv = (isset($linksDiv)) ? $linksDiv : "maplinks";

// [text]
// Class name to use in the marker links
$linksClass = (isset($linksClass)) ? $linksClass : "maplink";

// ["normal" | "satellite" | "hybrid"]
// Initial type of the map
$mapType = (isset($mapType)) ? $mapType : "normal";

// [latitude,longitude]
// Coordinates to the initial center position of the map
$centerPos = (isset($centerPos)) ? $centerPos : "63.098332,23.056698";

// [number]
// Initial zoomlevel for the map
$defaultZoom = (isset($defaultZoom)) ? $defaultZoom : "8";

// ["large" | "small" | "zoomonly" | "none"]
// Look of the controls to navigate / zoom the map
$mapControl = (isset($mapControl)) ? $mapControl : "large";

// ["large" | "small" | "none"]
// Look of the controls to change the map type
$mapTypeControl = (isset($mapTypeControl)) ? $mapTypeControl : "large";

// [0 | 1]
// When mouse cursor is moved over the map marker, should the info box open on that marker?
$openMouseOverMarker = (isset($openMouseOverMarker)) ? $openMouseOverMarker : 0;

// [0 | 1]
// When the map marker is clicked, should the info box open on that marker?
$openMouseClickMarker = (isset($openMouseClickMarker)) ? $openMouseClickMarker : 1;

// [0 | 1]
// When mouse cursor is moved over the textual marker link, should the info box open on that marker?
$openMouseOverLink = (isset($openMouseOverLink)) ? $openMouseOverLink : 0;

// [0 | 1]
// When the textual marker link is clicked, should the info box open on that marker?
$openMouseClickLink = (isset($openMouseClickLink)) ? $openMouseClickLink : 1;

// [0 | 1]
// Show overview map in the right bottom corner of the map?
$showOverviewMap = (isset($showOverviewMap)) ? $showOverviewMap : 1;

// [width,heigth]
// Size of the overview map
$overviewMapSize = (isset($overviewMapSize)) ? $overviewMapSize : "150,150";

// [0 | 1]
// Should the overview map be hidden by default? (arrow indicator visible at the bottom right corner)
$hideOverviewMapByDefault = (isset($hideOverviewMapByDefault)) ? $hideOverviewMapByDefault : 1;

// [text]
// Name of the Ditto snippet
$dittoName = (isset($dittoName)) ? $dittoName : "Ditto";

// [extenders]
$extenders = (isset($extenders)) ? $extenders : "tagging";
$tagData = (isset($tagData)) ? $tagData : "menutitle";
$tagDelimiter = (isset($tagDelimiter)) ? $tagDelimiter : ",";
$tags = (isset($tags)) ? $tags : "";


////////////////////////////////////////////////////////
// Start of snippet code
////////////////////////////////////////////////////////

if($apiKey != "") {

    $script = '
        <script type="text/javascript">
        //<![CDATA[
            
            // addEvent scripts written by Dean Edwards, 2005
            // with input from Tino Zijdel, Matthias Miller, Diego Perini
            // http://dean.edwards.name/weblog/2005/10/add-event/

            function addEvent(element, type, handler) {
                if (element.addEventListener) {
                    element.addEventListener(type, handler, false);
                } else {
                    // assign each event handler a unique ID
                    if (!handler.$$guid) handler.$$guid = addEvent.guid++;
                    // create a hash table of event types for the element
                    if (!element.events) element.events = {};
                    // create a hash table of event handlers for each element/event pair
                    var handlers = element.events[type];
                    if (!handlers) {
                        handlers = element.events[type] = {};
                        // store the existing event handler (if there is one)
                        if (element["on" + type]) {
                            handlers[0] = element["on" + type];
                        }
                    }
                    // store the event handler in the hash table
                    handlers[handler.$$guid] = handler;
                    // assign a global event handler to do all the work
                    element["on" + type] = handleEvent;
                }
            };
            // a counter used to create unique IDs
            addEvent.guid = 1;

            function removeEvent(element, type, handler) {
                if (element.removeEventListener) {
                    element.removeEventListener(type, handler, false);
                } else {
                    // delete the event handler from the hash table
                    if (element.events && element.events[type]) {
                        delete element.events[type][handler.$$guid];
                    }
                }
            };

            function handleEvent(event) {
                var returnValue = true;
                // grab the event object (IE uses a global event object)
                event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
                // get a reference to the hash table of event handlers
                var handlers = this.events[event.type];
                // execute each event handler
                for (var i in handlers) {
                    this.$$handleEvent = handlers[i];
                    if (this.$$handleEvent(event) === false) {
                        returnValue = false;
                    }
                }
                return returnValue;
            };

            function fixEvent(event) {
                // add W3C standard event methods
                event.preventDefault = fixEvent.preventDefault;
                event.stopPropagation = fixEvent.stopPropagation;
                return event;
            };
            fixEvent.preventDefault = function() {
                this.returnValue = false;
            };
            fixEvent.stopPropagation = function() {
                this.cancelBubble = true;
            };
                
            addEvent(window, "unload", GUnload);

            if (GBrowserIsCompatible()) {
                // Display the map, with some controls
                var map = new GMap2(document.getElementById("'.$mapDiv.'"));
                // set initial center position
                map.setCenter(new GLatLng('.$centerPos.'),'.$defaultZoom.');
    
                //add controls to navigate / zoom
                ';

    if ($mapControl == "zoomonly") {
        $script .= '
                map.addControl(new GSmallZoomControl());';
    } else if ($mapControl == "large") {
        $script .= '
                map.addControl(new GLargeMapControl());';
    } else if ($mapControl == "small") {
        $script .= '
                map.addControl(new GSmallMapControl());';
    }

    if ($mapTypeControl == "large") {
        $script .= '
                // add controls to change map type
                map.addControl(new GMapTypeControl(0));';
    } else if ($mapTypeControl == "small") {
        $script .= '
                // add controls to change map type
                map.addControl(new GMapTypeControl(1));';
    }

        $script .= '
                //set initial map type
                ';
    if ($mapType == "normal") {
        $script .= '
                map.setMapType(G_NORMAL_MAP);';
    } else if ($mapType == "satellite") {
        $script .= '
                map.setMapType(G_SATELLITE_MAP);';
    } else if ($mapType == "hybrid") {
        $script .= '
                map.setMapType(G_HYBRID_MAP);';
    }
        $script .= '
                // arrays to hold copies of the markers and html used by the sidebar
                // because the function closure trick doesnt work there
                var sidebar_html = "";
                var gmarkers = [];
                var htmls = [];
                var i = 0;

                // a function to create the marker and set up the event window
                function createMarker(point,name,html) {
                    var marker = new GMarker(point);';

    if($openMouseClickMarker) {
        $script .= '
                    // event listener to open info on click
                    GEvent.addListener(marker, "click", function(){
                        marker.openInfoWindowHtml(html);
                    });';
    }

    if($openMouseOverMarker) {
        $script .= '
                    // The new marker "mouseover" listener
                    GEvent.addListener(marker,"mouseover", function(){
                        marker.openInfoWindowHtml(html);
                    });';
    }

        $script .= '    
                    // save the info we need to use later for the sidebar
                    gmarkers[i] = marker;
                    htmls[i] = html;
                    // add a line to the sidebar html
                    sidebar_html += \'<div class="'.$linksClass.'"><a href="javascript:void(0)" ';

    if($openMouseClickLink) {
        $script .= 'onClick="myclick(\' + i + \')"';
    }

    if($openMouseOverLink) {
        $script .= 'onMouseOver="myclick(\' + i + \')"';
    }

        $script .= '>\' + name + \'</a></div>\';
                    i++;

                    return marker;
                }

                // This function picks up the click and opens the corresponding info window
                function myclick(i) {
                    gmarkers[i].openInfoWindowHtml(htmls[i]);
                }';
    if($startID != "") {

        $script .= $modx->runSnippet($dittoName,array('depth' => $descendentDepth, 'sortBy' => $sortBy, 'sortDir' => $sortDir, 'summarize' => 'all', 'displayArchive' => '0', 'tpl' => '@CODE:var point = new GLatLng([+description+]); var marker = createMarker(point, \'[+title:slashandstrip+]\', \'[+content:slashandstrip+]\'); map.addOverlay(marker);', 'parents' => $startID, 'showPublishedOnly' => '0', 'extenders' => $extenders, 'tagData' => $tagData, 'tagDelimiter' => $tagDelimiter, 'tags' => $tags));

        $script .= '
                // put the assembled sidebar_html contents into the sidebar div
                document.getElementById("'.$linksDiv.'").innerHTML = sidebar_html;';
    }

    if($showOverviewMap) {
        $script .= '
                // ======== Add a map overview ==========
                var ovcontrol = new GOverviewMapControl(new GSize('.$overviewMapSize.')); 
                map.addControl(ovcontrol,new GControlPosition(G_ANCHOR_BOTTOM_RIGHT, new GSize(10, 10)));';
    }
    if($hideOverviewMapByDefault) {
        $script .= '
                //set hidden by default (without animation)
                ovcontrol.hide(1);';
    }
        $script .= '
            } else { // !GBrowserIsCompatible()
                alert("Sorry, the Google Maps API is not compatible with this browser");
            }
    
            // This Javascript is based on code provided by the
            // Blackpool Community Church Javascript Team
            // http://www.commchurch.freeserve.co.uk/ 
            // http://www.econym.demon.co.uk/googlemaps/

        //]]>
        </script>
        ';

    //register scripts
    $modx->regClientScript($script);
    $modx->regClientStartupScript("http://maps.google.com/maps?file=api&amp;v=2&amp;key=".$apiKey . '" charset="utf-8');

    if($tpl == "") {
        $returnstring = '
            <div id="'.$mapDiv.'" style="float:left; width: 350px; height: 350px;">Loading map...</div>
            <div id="'.$linksDiv.'" style="margin-left: 10px; padding-right: 10px; float: left; display: block; height: 350px; overflow: auto;"></div>
            <noscript>
                <b>JavaScript must be enabled in order for you to use Google Maps.</b> 
                However, it seems JavaScript is either disabled or not supported by your browser.
                To view Google Maps, enable JavaScript by changing your browser options, and then
                try again.
            </noscript>
            ';
    } else {
        $returnstring = $modx->getChunk($tpl);
    }
} else {
    if ($apiKey == "") {
        $returnstring = '
                        You have to provide a Google Maps API key to use!<br />
                        If you don\'t have one yet, go <a href="http://www.google.com/apis/maps/signup.html" alt="Sign up for the Google Maps API">here</a> to get it. NOTE: the api key is site/directory specific!<br /><br />
                        ';
    }

}

return $returnstring;
?>

タグによるフィルタリングは、一応、使えるようでした。
スニペットコールは

[!GoogleMapMarker? &apiKey=`ABQ...` &startID=`1` &descendentDepth=`0` &tpl=`GoogleMapMarker_tpl` &centerPos=`34.686422,135.057335` &showOverviewMap=`0` &mapTypeControl=`none` &extenders=`tagging` &tagData=`menutitle` &tagDelimiter=`,` &tags=`CMS`!]

みたいな感じになる。