Building a Map Drilldown System

This section describes creating a multi-level map drilldown system. Using dynamic objects, macros, and ITXML, Corda Server™ lets you create a complex, multi-level map drilldown system with just one Web page and one Image Template file.

This tutorial illustrates this process by building a basic drilldown system that drills down from a United States map to a county-based map of each state. The strategies and techniques used in this tutorial can be applied to the creation of any map drilldown system. The tutorial is divided into the following sections:

The sample code in this tutorial is provided in ASP only, but it can be tweaked to other languages fairly easily.

This tutorial assumes that the Web server, Corda Server, and Corda Builder™ are all running on the same machine. If this is not the case, make appropriate adjustments, such as uploading the ITXML file or ASP to the appropriate server, and changing the server address in the ASP).

The ITXML file is <document_root>\image_templates\examples\maps\drilldownUS.itxml. The ASP code is <product_root>\Server\dev_tools\ASP\drilldownUS.asp. Translations of this Web page into other Corda-supported Web application environments are available in their respective <product_root>\Server\dev_tools directories.

Note: A more complicated JSP tutorial is used in Building a Map Drilldown System with Zip Codes.

Prerequisites

Before starting this tutorial, test your environment by publishing a basic map to the Web application server, as described in Publishing the Project in the Corda Builder User Guide.

Review the information about dynamic objects (see Dynamic Objects) and drilldown (see Building Drilldown).

Map Drilldown Tutorial

This tutorial creates a two-level map drilldown system for U.S. states using one Image Template file and one Web page. This tutorial takes approximately 30 minutes.

To create a basic map drilldown system

  1. Start Corda Builder and create a new Image Template file.

  2. Click the Dynamic Object button on the toolbar, or select Edit > Create Dynamic Object to add a dynamic object.

    You may want to resize the dynamic object since the size of the maps you publish are created the same size as the dynamic object in the Image Template file.

  3. Add other objects as needed.

    Add any other objects that you want, including textboxes and shapes.

    Note: To add a legend, make sure you select the dynamic object.

  4. Test the Image Template file using Preview With PCScript.

    Click the Edit PCScript button in the Corda Builder toolbar and enter the following PCScript into the main window:

    dynamic.SetITXMLAttributes(file-name='shared\maps\US\US_State.itxml' object-name='US_State')

    This PCScript tells Corda Server the location (shared\maps\US\US_State.itxml), relative to <document_root>, and name (US_State) of the map with which to replace the dynamic object.

    Click the Preview with PCScript button, which displays a map of the United States.

    Note: Legends aren't displayed until after you specify data.

  5. Save the Image Template file.

  6. Save the Image Template file's ASP Sample Code to the Web server.

    To do this, click the Sample Code button in the Corda Builder toolbar. Select ASP (COM Embedder) from the Sample Code For pull-down menu (or the appropriate scripting technology for your environment). Make any necessary changes to the server address and image type, and click Save Code to File. Specify a file name, and save it to the Web server (for example, C:\InetPub\wwwroot).

  7. Open the file you just saved in a text editor.

  8. Insert ITXML to specify the map to insert in the dynamic object.

    To do this, add two ITXML statements to the file. First, define a variable to hold the ITXML string to send to Corda Server. Add this line of code immediately before the CordaEmbedder object declaration (i.e., the line that begins set myImage...). For example:

    String mapsource="<cit:dynamic-map-object name="dynamic" file-name='shared\maps\US\US_State.itxml' object-name='US_State'/>"

    The variable is mapsource, and the dynamic object's is dynamic. This ITXML string specifies the location and name of the map to insert into the dynamic object. For more information about object names, see Object Names in the Corda Builder User Guide.

    Second, send this string to Corda Server using the addITXML command, as shown in the preceding line of code. Insert this line somewhere before calling getEmbeddingHTML. For example:

    myImage.addITXML mapsource

    Important: Make sure the ASP page does not contain any PCScript definitions. Set the pcScript variable to an empty string (""), or it may interfere with the tutorial.

  9. Save the ASP file, and test it to make sure it loads the map of the United States.

    For example, if you saved the ASP file as C:\Inetpub\wwwroot\drilldownUS.asp, test the ASP by browsing to http://localhost/drilldownUS.asp .

  10. Define variables in the ASP file to represent the map location and map name.

    Place these definitions before the map source ITXML definition in Step 8. For example:

    maplocation = "shared/maps/US/"

    mapname = "US_State"

  11. Rewrite the map source ITXML string to make use of the map location and name variables.

    For the file-name attribute, combine the map location and map name, followed by .itxml . For the object-name attribute, just use the map name. For example:

    String mapsource="<cit:dynamic-map-object name="dynamic" file-name='"& maplocation & mapname &".itxml' object-name='" & mapname & "‘/>"

    Once you have made these changes, save the ASP and test it again to make sure there are no error messages.

  12. Insert an if-then clause that overrides the map name and location based on information from the Web page's query string.

    The query string is passed to the Web page from the drilldown command, and contains two pieces of information: the nameclass, which specifies the current level of the drilldown system (e.g., State); and the map, which specifies the map to show.

    Note: Creating a query string is discussed in Step 13.

    Retrieve this information from the query string using the Request.QuerySting method. The following example returns the nameclass (the current drilldown level):

    Request.QueryString("nameclass")

    Note: The methods for retrieving query string parameters vary greatly by scripting language. Consult the scripting language documentation for more information.

    This tutorial sample has two levels of maps. The top level is the default level (the U.S. map), so it doesn't require an if-then clause. The second level is the State, so an if-then clause checks to see if nameclass is State. If it is, it makes appropriate changes to the map name and location. For example:

    If (Request.QueryString("nameclass") = "State") Then

      mapname = Request.QueryString("map")

      maplocation = maplocation & "State_County/"

    End If

    Note: Place this code after the default map name and map location definitions, but before the map source definition.

    Each line of code does the following:

    The code sample below provides the complete ASP code:

    ASP Code for a Map Drilldown System

    <html>

    <head>

    <title>ASP Example</title>

    </head>

    <body>

    <h1>Your image will appear below</h1>

    <!-- Begin Embedder Code -->

    <%

      Dim pcScript

      pcScript = ""

     

      maplocation = "shared/maps/US/"

      mapname = "US_State"

     

      If (Request.QueryString("nameclass") = "State") Then

        mapname = Request.QueryString("map")

        maplocation = maplocation & "State_County/"

      End If

     

      String mapsource="<cit:dynamic-map-object name="dynamic" file-name='"& maplocation & mapname &".itxml' object-name='" & mapname & "‘/>"

     

      set myImage = Server.CreateObject("Corda.Embedder")

      myImage.externalServerAddress = "http://<server_address>:2001"

      myImage.internalCommPortAddress = "http://localhost:2002"

      myImage.imageTemplate = "examples/maps/drilldownUS.itxml"

      myImage.userAgent = Request.ServerVariables("HTTP_USER_AGENT")

      myImage.width = 540

      myImage.height = 330

      myImage.returnDescriptiveLink = true

      myImage.language = "EN"

      myImage.pcScript = pcScript

      myImage.outputType = "FLASH"

      myImage.fallback = "STRICT"

      myImage.useCache = false

     

      myImage.addITXML mapsource

    %>

    <%= myImage.getEmbeddingHTML%>

    <!-- End Embedder Code -->

    </body>

    </html>

  13. Save the ASP file, and test it by requesting a state map

    To request a state map, request the same Web page from Step 9., adding the appropriate query string.

    The query string syntax is as follows:

    ?parameter1=<value 1>&parameter2=<value 2>...&parametern=<value n>

    For example, to request a map of Texas, enter the following in a Web browser:

    http://localhost/drilldownUS.asp?nameclass=State&map=TX

  14. In Corda Builder, open the Image Template file and access the dynamic object's properties in Object Properties.

  15. From the Object List, expand the Dynamic object and select Areas. In Object Properties, browse to Default Shape > Drilldown > URL.

    Insert the following in the URL attribute:

    Javascript:window.location.replace(window.location.pathname+"?nameclass=%_NAMECLASS&map=%_NAME");%_JS_ENCODE

    In operation, the macros in the URL string are replaced with real values in the map on a state-by-state basis, producing drilldown destinations like that used in Step 13.

  16. Save the Image Template file.

  17. Reload the main Web page (from Step 9). Click any state to drill down to a detailed map of that state.

Conceptual Review

Consider the following important concepts when reviewing this tutorial:

  1. With the exception of top level maps (e.g., the world), every Corda® 7 map file is named after the map object it contains. Hence, the map file in Step 11 is a combination of the map location and the map name. For example, the Texas map is named TX.itxml because the main map object is called TX.

  2. Corda 7 map files are organized such that all maps of a certain level are stored in the same directory. For example, many county-based maps are stored at \shared\maps\US\County.

  3. Dynamic objects can store a number of ITXML properties. When the dynamic object is transformed into a map, these properties override the default ITXML in the map. This lets you specify the map's global drilldown effect by overriding the default drilldown effects in the map template. This strategy even lets you define default ranges for a map system, or create global data labels.

  4. Each map shape contains a number of attributes that are used to identify it. These attributes can be retrieved in Drilldown and hover effects using macros that begin with %_. Hence the use of %_NAMECLASS and %_NAME to access these attributes dynamically.

    For example, the U.S.map contains 50 map shapes, each of which is named after the two-digit abbreviation for the state it represents (e.g., the Texas shape is named TX which corresponds to the TX map file named TX.itxml . The %_NAME macro lets you retrieve the name of any state shape in the US map, thereby allowing you to know the drilldown destination of any state just by using one drilldown string.

    NameClass
    , meanwhile, defines the current level of a map drilldown system. Potential values for NameClass include Country, State, County, City, Zip, and so on. Usually, all of the maps for a particular name class can be found in the same directory.

To find additional information about a map shape

  1. In the Object List, select the map shape about which you want more information.

  2. In Object Properties, basic map shape information (such as name, value, name class, code, parent, and long name) are available in the attributes of the Map Shape property.

Adding Multiple Levels

Add another drilldown level to a map system by adding another if-then statement to the map's ASP or JSP. The new statement is very similar to that created in Step 12 of the tutorial, except you check for a different name class, and adjust the map location directory accordingly.

For example, this tutorial causes the counties in each state map to be drilldown-enabled (this is because our global drilldown string in Step 15 applies to all maps, not just the U.S. map). However, clicking on a county causes the map to returns to the top level because there isn't an if-then statement to handle maps with a County name class.

To have each county shape in the State map drilldown to an outline map for that county, add an if-then statement like the following:

If (Request.QueryString("nameclass") = "County") Then

maplocation = maplocation & "County/"

mapname = Request.QueryString("map")

End If

To get rid of drilldown on the second level (so that the counties don't drilldown at all), create a drilldown variable, right after myImage.addITXML (mapsource), to pass as an argument to a myImage.addITXML call. When you reach the bottom level of the map's drilldown system, set this variable to disable drilldown, or as an empty string. For example:

drilldown="<cit:dynamic-map-object name="dynamic">

<cit:layer name="Areas">

<cit:default-shape>

<cit:drilldown url=””/>

</cit:default-shape>

</cit:layer>

</cit:dynamic-map-object>

Connecting to Data

Look back to Step 12 of the tutorial. This step retrieves several parameters from the query string. These parameters specify the map to load, but can also determine the query to perform on the database.

For example, the following query provides data for the state of Texas:

SELECT County,sum(Sales-Expenditures) FROM Revenue WHERE Date between #7/1/2003# and #7/31/2003# AND State = 'TX' GROUP BY County

Make this query dynamic by using the map name variable. Thus, in the if-then statement for the State name class, assign a variable named query to the following value:

query = "SELECT County,sum(Sales-Expenditures) FROM Revenue WHERE Date between #7/1/2003# and #7/31/2003# AND State = '" & mapname & "' GROUP BY County"

Later in the ITXML code, send this query to Corda Server using the Corda Embedder setMapDBQuery method, as follows:

myImage.setMapDBQuery (mapname,"areas","","Revenue","","",query)

Accessing Secondary Information for Map Items

If the information passed in the query string is insufficient for determining the correct query, each map item has a number of extra properties that define secondary information for that item. Reference map shapes using one of three properties: Name, LongName or Code. These properties increase the flexibility of Corda Server's data import by allowing us to reference data in tables and result sets using FIPS codes or long names instead of Corda Server's default names.

In drilldown statements, these properties can also pass information from level to level. Access these properties through the %_LONGNAME and %_CODE macros, which work just like the %_NAME and %_NAMECLASS macros in Step 15 of the tutorial.

For example, to use complete state names (as opposed to abbreviations) for the query statement, pass the LongName property as another parameter in the drilldown statement:

drilldown="<cit:dynamic-map-object name="dynamic">

<cit:layer name="Areas">

<cit:default-shape>

<cit:drilldown url=”drilldownUS.asp?nameclass=%_NAMECLASS&map=%_NAME&longname=%_LONGNAME”/>

</cit:default-shape>

</cit:layer>

</cit:dynamic-map-object>

Access the state name by looking up the longname parameter in the query string, similar to looking up the map and nameclass parameters in Step 12.

Complete Example

The sample code below shows how the drilldownUS.asp example might look connected to sample data.

Map Drilldown System with Data Connectivity

<html>

<head>

<title>ASP Example</title>

</head>

<body>

<h1>The map appears below</h1>

<!-- Begin Embedder Code -->

<%

Dim pcScript

 

Dim mapname, maplocation, mapsource, drilldown, query

maplocation = "shared\maps\US\"

mapname = "US_State"

drilldown = ""

query = "SELECT State,sum(Sales-Expenditures) FROM Revenue WHERE Date between #7/1/2003# and #7/31/2003# GROUP BY State"

 

If (Request.QueryString("nameclass") = "State") Then

maplocation = maplocation & "State_County\"

mapname = Request.QueryString("map")

query = "SELECT County,sum(Sales-Expenditures) FROM Revenue WHERE Date between #7/1/2003# and #7/31/2003# AND State = '" & mapname & "' GROUP BY County"

End If

 

If (Request.QueryString("nameclass") = "County") Then

maplocation = maplocation & "County/"

mapname = Request.QueryString("map")

query = "SELECT County,sum(Sales-Expenditures) FROM Revenue WHERE Date between #7/1/2003# and #7/31/2003# AND County = '" & Request.QueryString("longname") & "' GROUP BY County"

drilldown="<cit:dynamic-map-object name="dynamic">

<cit:layer name="Areas">

<cit:default-shape>

<cit:drilldown url=””/>

</cit:default-shape>

</cit:layer>

</cit:dynamic-map-object>

End If

 

String mapsource="<cit:dynamic-map-object name="dynamic" file-name='"& maplocation & mapname &".itxml' object-name='" & mapname & "‘/>"

 

set myImage = Server.CreateObject("Corda.Embedder")

myImage.externalServerAddress = "http://<server_address>:2001"

myImage.internalCommPortAddress = "http://<server_address>:2002"

myImage.imageTemplate = "examples/maps/drilldownUS.itxml"

myImage.userAgent = Request.ServerVariables("HTTP_USER_AGENT")

myImage.width = 540

myImage.height = 330

myImage.returnDescriptiveLink = true

myImage.language = "EN"

myImage.pcScript = pcScript

myImage.outputType = "FLASH"

 

myImage.addITXML (mapsource)

myImage.addITXML (drilldown)

myImage.setMapDBQuery (mapname, "areas", "", "Revenue", "", "", query)

%>

<%= myImage.getEmbeddingHTML%>

<!-- End Embedder Code -->

</body>

</html>

The above example includes another parameter that specifies a map shapes long name. Because of this, modify the ITXML from Step 15 as follows:

drilldown="<cit:dynamic-map-object name="dynamic">

<cit:layer name="Areas">

<cit:default-shape>

<cit:drilldown url="drilldownUS.asp?nameclass=%_NAMECLASS&map=%_NAME&longname=%_LONGNAME"/>

</cit:default-shape>

</cit:layer>

</cit:dynamic-map-object>

This addition allows you to reference counties by the county name instead of the FIPS code, even though the Corda 7 map templates store counties under FIPS codes. Thus, for the county level, use the FIPS code when specifying the map and file location, but use the actual county name in the where clause of the query.

Fortunately, Corda Server accepts both the county name (i.e., long name) and FIPS code when importing data, meaning the tables produced by the query import properly no matter how the counties are indexed.