MapGuide Cookbook

This section is a select list of MapGuide code samples. See Trac for more samples.

JavaScript: Hooking to events in the AJAX viewer

This sample will show how to do the following:

  • Checking when the map has been loaded.
  • Handling viewer selection.

It is assumed you know what javascript anonymous functions are and how they work.

Checking when the map has been loaded

Before we can hook on to events in the ajax viewer, we need to check that the DOM for the ajax viewer has been loaded. This sample shows how to do it.

Assume your viewer page looks something as follows:

<html>
<head>
        <title>Viewer Sample Application</title>
</head>
<frameset rows="30,*" frameborder="no" framespacing="0">
        <frame id="titleFrame" frameborder="no" marginwidth="0" marginheight="0" scrolling="no" src="title.html">
        <frame id="viewerFrame" frameborder="no" marginwidth="0" marginheight="0" scrolling="no" src="[URL TO AJAX VIEWER]">
</frameset>
</html>

Insert the following script block in the head of the page:

<script type="text/javascript">

// Map loaded handler
function OnMapInitialized() {
    // Map has been initialized now we're off to the races.
    alert("Map has been initialized");
}

window.onload = function() {
    //Timer variable
    var timer;

    // This is our "watch" function. What we are doing here is
    // repeatedly checking the mapInit value of the Map Frame. When
    // mapInit is true, then the map has been loaded.
    var watch = function() {

        // What we are doing here is attempting to access the mapInit
        // variable of the Map frame. The reason the code is in a try-catch
        // is because chances are that this code access the DOM
        // of the map frame before its DOM has been initialized.
        try {
            var mapFrame = viewerFrame.mapFrame;
            if(mapFrame.mapInit) {

                // Remove the timer so this watch function stops executing
                clearInterval(timer);

                // Call our custom handler
                OnMapInitialized();
            }
        }
        catch(e) {
        }
    };

    // Start the "watching" process. We basically invoke the watch function
    // every 200ms until the map has been loaded.
    timer = setInterval(watch, 200);
};

</script>

Handling viewer selection

This sample will show how to handle the selection in the ajax viewer. This assumes the html is the same as the previous example.

The code “overrides” the OnSelectionChanged function of the map frame (this is called by the map frame when selection changes) and replaces it with our own.

Insert the following script block in the head of the page:

<script type="text/javascript">

//Function variable to store the original OnSelectionChanged
var origOnSelectionChanged = null;

//Our custom selection handler
function MySelectionHandler()
{
    //This is important. We don't want to replace the original function, rather
    //we want to attach our code into the execution sequence. So we call the original
    //function first.
    origOnSelectionChanged();

    //Now our code goes here. For our example, we'll just show the number of objects selected.
    var count = viewerFrame.GetMapFrame().GetSelectedCount();
    alert(count + " features selected");
}
window.onload = function() {
    //Timer variable
    var timer;

    // This is our "watch" function. What we are doing here is
    // repeatedly checking the mapInit value of the Map Frame. When
    // mapInit is true, then the map has been loaded.
    var watch = function() {

        // What we are doing here is attempting to access the mapInit
        // variable of the Map frame. The reason the code is in a try-catch
        // is because chances are that this code access the DOM
        // of the map frame before its DOM has been initialized.
        try {
            var mapFrame = viewerFrame.mapFrame;
            if(mapFrame.mapInit) {

                // Remove the timer so this watch function stops executing
                clearInterval(timer);

                // Replace the OnSelectionChanged function with our own function.
                // It is safe to do this now because the DOM for the map frame is fully initialized.

                // Store old function
                origOnSelectionChanged = mapFrame.OnSelectionChanged;
                // Now replace with our own.
                mapFrame.OnSelectionChanged = MySelectionHandler;
            }
        }
        catch(e) {
        }
    };

    // Start the "watching" process. We basically invoke the watch function
    // every 200ms until the map has been loaded.
    timer = setInterval(watch, 200);
};
</script>

when you make a selection on the map, the code will display a dialog showing how many features were selected.

Note: Our custom handler executes when a selection has changed. So clearing the selection, for example will also call the handler even though we haven’t actually made a selection.

JavaScript: Invoke Viewer Command on startup

This html page can automatically invoke a named viewer command on viewer startup based on the value of a Cmd query string property. This uses the InitialTask property of the Web Layout and requires that the Task Pane is set to be visible

For example setting this initial task pane url in the Web Layout:

http://path/to/autostart.html?Cmd=Measure

Will launch the Measure command on viewer startup.

As you can see from the code below, we need to employ initialization checks just like in the example (JavaScript: Hooking to events in the AJAX viewer), to make sure we can start using the Viewer API when the frames have been fully initialized.

autostart.html

<html>
    <head>
        <title>Auto-start command in task pane</title>
        <script type="text/javascript">

            var viewerFrame = parent.parent;

            function GetQueryStringValue(key)
            {
                key = key.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
                var regex = new RegExp("[\\?&]"+key+"=([^&#]*)");
                var qs = regex.exec(window.location.href);
                if(qs == null)
                    return "";
                else
                    return qs[1];
            }

            function GetCommandIndex(name)
            {
                var cmds = viewerFrame.GetCommands();
                for(var i = 0; i < cmds.length; i++)
                {
                    //This command array is not sequential, there may be holes
                    //so we have to test element existence before testing name equality
                    if (cmds[i] && cmds[i].name == name)
                        return i;
                }
                return -1;
            }

            function OnMapInitialized()
            {
                var cmdName = GetQueryStringValue("Cmd");
                var i = GetCommandIndex(cmdName);
                if (i < 0)
                    alert("Command not found: " + cmdName);
                else
                    viewerFrame.ExecuteCommand(i);
            }

            window.onload = function() {
                //Timer variable
                var timer;

                // This is our "watch" function. What we are doing here is
                // repeatedly checking the mapInit value of the Map Frame. When
                // mapInit is true, then the map has been loaded.
                var watch = function() {

                    // What we are doing here is attempting to access the mapInit
                    // variable of the Map frame. The reason the code is in a try-catch
                    // is because chances are that this code access the DOM
                    // of the map frame before its DOM has been initialized.
                    try {
                        var mapFrame = viewerFrame.mapFrame;
                        if(mapFrame.mapInit) {

                            // Remove the timer so this watch function stops executing
                            clearInterval(timer);

                            // Call our custom handler
                            OnMapInitialized();
                        }
                    }
                    catch(e) {
                    }
                };

                // Start the "watching" process. We basically invoke the watch function
                // every 200ms until the map has been loaded.
                timer = setInterval(watch, 200);

            };

        </script>
    </head>
    <body>
    </body>
</html>

PHP: Dynamically setting initial map view and scale

The following script allows us to set the initial x, y and scale attributes of a map using the MapGuide Ajax Viewer. It expects the values to be passed to the script as querystring parameters, e.g.

It works by taking a copy of the WebLayout? stored in the Library repository and changing the <CenterX/>, <CenterY/> and <Scale/> elements. The updated XML is written into the Session and is used as the target when the page is ultimately redirected.

This code could easily be converted to C# (or whatever).

Things to note

  • A side-effect of the code is that it facilitates anonymous connections
  • The parameter-checking could be made a little more robust
  • The $wl variable should be changed to reflect the relevant WebLayout identifier

The code

<?php

//
// Vital includes.
//
$viewerDir = "mapviewerphp\\";
include $viewerDir . "constants.php";
include $viewerDir . "common.php";

//
// Check and get the required parameters.
//
if (!isset($_REQUEST["x"]) || !isset($_REQUEST["y"]) || !isset($_REQUEST["scale"])) {
        echo "<Error>One or more of the required arguments is missing.</Error>";
        exit;
}

$x = $_REQUEST["x"];
$y = $_REQUEST["y"];
$scale = $_REQUEST["scale"];

//
// Usual initialisation step.
//
InitializeWebTier();

//
// Obtain a new session ID for this anonymous user, use it to set up
// a new site connection and use that to create a resource service.
//
$site = new MgSite();
$site->Open(new MgUserInformation("Anonymous", ""));

$sessionId = $site->CreateSession();

$siteConnection = new MgSiteConnection();
$siteConnection->Open(new MgUserInformation($sessionId));

$resourceService = $siteConnection->CreateService(MgServiceType::ResourceService);

//
// Read the web layout into an XML DOM document object.
//
$wl = "Library://WebPID/WebPID_SDF_Static.WebLayout"; // TODO Constant!
$wlResourceId = new MgResourceIdentifier($wl);
$wlReader = $resourceService->GetResourceContent($wlResourceId);
$wlXml = $wlReader->ToString();
$wlDomDoc = DOMDocument::loadXML($wlXml);

//
// Now, update the initial x, y and scale values with the desired values.
//
$nodeCenterX = $wlDomDoc->getElementsByTagName("CenterX")->item(0);
$nodeCenterX->nodeValue = "$x";

$nodeCenterY = $wlDomDoc->getElementsByTagName("CenterY")->item(0);
$nodeCenterY->nodeValue = "$y";

$nodeScale = $wlDomDoc->getElementsByTagName("Scale")->item(0);
$nodeScale->nodeValue = "$scale";

//
// Prepare the updated XML to be written out to the session.
//
$updatedXml = $wlDomDoc->saveXML();
$byteSource = new MgByteSource($updatedXml, strlen($updatedXml));

//
// Create a web layout in the session to hold the updated version
// from the library.
//
$sessionMapName = $wlResourceId->GetName();
$sessionWebLayout = "Session:$sessionId//$sessionMapName.WebLayout";
$sessionResourceId = new MgResourceIdentifier($sessionWebLayout);

//
// Write the updated web layout to the session.
//
$resourceService->SetResource($sessionResourceId, $byteSource->GetReader(), null);

//
// Redirect to the Ajax viewer pointing at the map at the desired coordinates.
//
$redirectTo = "mapguide/mapviewerajax/?SESSION=$sessionId&WEBLAYOUT=$sessionWebLayout";
$host = $_SERVER["HTTP_HOST"];
$url = "http://$host/$redirectTo";

//
// Redirect!
//
header("Location: $url");
exit;

?>