XML Example: Using the Leaflet.js map library

Using XMLHttpRequest() to configure entire ToolBook pages.

XML Example: Using the Leaflet.js map library

Postby Clifton » Wed Jun 03, 2015 10:29 am

ToolBook pages that use XML are very basic in nature.
They generally include only have to provide a framework of containers. The associated XML file loads and inserts styles the content. The PowerPac implementation of XML also permits execution of JavaScript functions which makes this particularly powerful.

What is Leaflet.js?
This is a JavaScript library which permits displaying maps (an alternative to Google maps) in your DHTML applications. The implementation of leaflet.js discussed in this article shows that it can be easily set up to work with ToolBook.

Snapshot of Leaflet.js used with ToolBook to display a random maps on page load:
To see the actual assessment on our server: http://www.pgsoftwaretools.com/powerpac/assessments/leaflet/

    Image 1.png
    HTML 5 Browser snapshot (Firefox)
    Image 1.png (234.04 KiB) Viewed 4797 times

Here is a snapshot showing just how basic the ToolBook page looked at author mode before export:

    Image 2.png
    ToolBook authoring mode snapshot
    Image 2.png (36.45 KiB) Viewed 4797 times

The XML file which loads with this page contains the following data:

Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<page>
  <config>
    <stylesheet>
      ../leaflet/leaflet.css
    </stylesheet>
   
    <!--Dynamically load leaflet.js in the ToolBook frame. Once loaded, a user event is sent to the first map container.-->
    <pgExtFiles>
      <![CDATA[
         { file_url : "../leaflet/leaflet-src.jsx",
           opt      : "",
           special  : "",
           loadAsScript : true,
           unloadScriptDelay : "",
           notifyOnLoad : "Leaflet_Map_1" }
      ]]>     
    </pgExtFiles>
  </config>
 
  <!--THIS OBJECT GETS USER EVENT AFTER leaflet.js LOADS; USER EVENT CHAINS ALL THE ACTIONS THAT
      LOAD THE MAP AND POPULATE THE SELECT LIST BOX-->
  <Leaflet_Map_1>
    <!--Each map div element must have its own unique id; we've appended myMap_[object name]-->
    <setHTMLContent>
      <![CDATA[
        { myHTML : '<div id="myMap_Leaflet_Map_1" style="height:100%; width:100%;"></div>' }
      ]]>
    </setHTMLContent>
  </Leaflet_Map_1>
 
  <Leaflet_Map_2>
    <!--Each map div element must have its own unique id; we've appended myMap_[object name]-->
    <setHTMLContent>
      <![CDATA[
        { myHTML : '<div id="myMap_Leaflet_Map_2" style="height:100%; width:100%;"></div>' }
      ]]>
    </setHTMLContent>
  </Leaflet_Map_2>
 
  <!--This is the green user event map arrow; setting it to hidden by default.-->
  <EventPath>
    <pgTBObjSet>
      <![CDATA[
        { myProperty : "visible",
          myValue    : false }
      ]]>
    </pgTBObjSet>
  </EventPath>
 
  <!--Handle default button check in map views.-->
  <street_1>
    <pgTBObjSet>
      <![CDATA[
        { myProperty  : "checked",
          myValue     : true }
      ]]>
    </pgTBObjSet>
  </street_1>
  <satellite_1>
    <pgTBObjSet>
      <![CDATA[
        { myProperty  : "checked",
          myValue     : false }
      ]]>     
    </pgTBObjSet>
  </satellite_1>

  <!--Handle default button check in map views.-->
  <street_2>
    <pgTBObjSet>
      <![CDATA[
        { myProperty  : "checked",
          myValue     : true }
      ]]>
    </pgTBObjSet>
  </street_2> 
  <satellite_2>
    <pgTBObjSet>
      <![CDATA[
        { myProperty  : "checked",
          myValue     : false }
      ]]>     
    </pgTBObjSet>
  </satellite_2>
 
  <myBG>
    <!--Apply a border radius and box shadow to the page background element.
        NOTE: For this to work, the background or page must be named.-->
    <pgStyleObject>
      <![CDATA[
        { theStyle  : "borderRadius, boxShadow",
          propVal   : "30px, 0px 0px 36px 12px #FFD300 inset" }
      ]]>
    </pgStyleObject>
  </myBG>

  <!--You must open a free account with mapbox.com to get your free public key.-->
  <accesskey>
    (this data removed deliberately; you provide your own key from mapbox.com to display your maps; sign up is frre)
  </accesskey>
 
  <!--These are the world geo locations used in the select list boxes. See http://www.latlong.net-->
  <locations coords="18.466334, -66.105722" name="San Juan, Puerto Rico USA" />
  <locations coords="-43.532054, 172.636225" name="Christchurch, New Zealand" />
  <locations coords="-27.471011, 153.023449" name="Brisbane, Australia" />
  <locations coords="-33.867487, 151.20699" name="Sydney, Australia" />
  <locations coords="53.408371, -2.991573" name="Liverpool, England UK" />
  <locations coords="53.349805, -6.26031" name="Dublin, Ireland" />
  <locations coords="59.913869, 10.752245" name="Oslo, Norway" />
  <locations coords="52.520007, 13.404954" name="Berlin, Germany" />
  <locations coords="47.497912, 19.040235" name="Budapest, Hungary" />
  <locations coords="52.229676, 21.012229" name="Warsaw, Poland" />
  <locations coords="48.208174, 16.373819" name="Vienna, Austria" />
  <locations coords="50.110922, 8.682127" name="Frankfurt, Germany" />
  <locations coords="52.070498, 4.3007" name="The Hague, Netherlands" />
  <locations coords="51.219448, 4.402464" name="Antwerp, Belgium" />
  <locations coords="45.440847, 12.315515" name="Venice, Italy" />
  <locations coords="38.722252, -9.139337" name="Lisbon, Spain" />
  <locations coords="25.761680, -80.19179" name="Miami, FL USA" />
  <locations coords="29.951066, -90.071532" name="New Orleans, LA USA" />
  <locations coords="47.606210, -122.332071" name="Seattle, WA USA" />
  <locations coords="43.653226, -79.383184" name="Toronto, Canada" />
  <locations coords="42.3600825, -71.0588801" name="Boston, MA USA" />
  <locations coords="41.902784, 12.496366" name="Rome, Italy" />
  <locations coords="44.024706, -88.542614" name="Oshkosh, WI USA" />
  <locations coords="40.712784, -74.005941" name="New York, NY USA" />
  <locations coords="34.052234, -118.243685" name="Los Angeles, CA USA" />
  <locations coords="41.878114, -87.629798" name="Chicago, IL USA" />
  <locations coords="51.507351, -0.127758" name="London, England UK" />
  <locations coords="47.368650, 8.539183" name="Zurich, Switzerland" />
  <locations coords="-26.204103, 28.047305" name="Johannesburg, South Africa" />
  <locations coords="61.218056, -149.900278" name="Anchorage, AK USA" />
  <locations coords="33.448377, -112.074037" name="Phoenix, AZ USA" />
  <locations coords="32.776664, -96.796988" name="Dallas, TX USA" />
  <locations coords="38.627003, -90.199404" name="St. Louis, MO USA" />
  <locations coords="33.748995, -84.387982" name="Atlanta, GA USA" />
  <locations coords="21.306944, -157.858333" name="Honolulu, HI USA" />
  <locations coords="48.856614, 2.352222" name="Paris, France" />
 
  <!--Map view ids from mapbox.com; can add as many views as you have set in mapbox.com-->
  <satellite>
    02clams.d900fe9f
  </satellite>
  <street>
    02clams.ma5mkkl4
  </street>
 
  <!--SCRIPT TO RUN USING exeJavascriptDirect() TO LOAD THE MAPS.-->
  <load>
    <![CDATA[
      try {   
        var tbx = getToolBookFrame().L;
        //Replace %1 with ToolBook container reference
        var obj = gTBo( '%1', 'objRef' );
        //Store map in object property scope so we can modify the map and support multiple maps on a page
        obj.map = tbx.map( obj.firstChild.id ).setView( [%2], 9 );
        tbx.tileLayer( 'https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', {
                        maxZoom: 14,
                        attribution: 'Map © <a href="*" ' +
                                     'onclick="parent.tbfunction_pgGotoURL(\'pgMaps\', \'http://openstreetmap.org\');">OpenStreetMap</a> ' +
                                     'Imagery © <a href="*" ' +
                                     'onclick="parent.tbfunction_pgGotoURL(\'pgMaps\', \'http://mapbox.com\');">Mapbox</a>',
                        id: '%3',
                        accessToken: '%4' } ).addTo(obj.map);
      } catch(e) {
        //alert("Leaflet library not available.");
      }
    ]]>
  </load> 
 
  <!--SCRIPT TO RUN USING exeJavascriptDirect() TO CHANGE VIEW FROM SATELLITE TO STREET VIEW-->
  <view>
    <![CDATA[
      //Script changes from satellite to street view and vice versa
      try {
        //Replace %1 with ToolBook container reference
        var map = gTBo( '%1', 'objRef' ).map;
        for (var x in map._layers) {
          if (map._layers[x].options.id) {
            map._layers[x].options.id = '%3'; //Use same reference as in above for simplicity
            map._layers[x].redraw();
            break;
          }
        }
      } catch(e) {
        //alert(e); //Debugging
      }
    ]]>     
  </view>
 
  <!--Move to different coords based on selection in list boxes. %1 determines which map to change.-->
  <pan>
    <![CDATA[
      try {
        //Replace %1 with ToolBook container reference
        var map = gTBo( '%1', 'objRef' ).map;
        map.panTo( [%2] ); //Set %2 to the new map coords
      } catch(e) {
        //alert(e); //Debugging
      }
    ]]>
  </pan>
</page>

Details regarding above XML:
  • XML files are loaded into ToolBook using the PowerPac function XMLHttpRequest() and setting the loadXMLPage parameter to true.
    NOTE: If this parameter is false (the default), then the data is just loaded into the browser storage and returned to ToolBook which you can set as any named variable you want. In either case the data is returned to ToolBook for this purpose, but in former case, the data will preload into ToolBook page elements first.
  • XML files can only have ONE root element. If the XML is to configure a ToolBook page, then the root element should always be called <page> ... </page>.
  • The <config> ... </config> section handles loading stylesheets and calling PowerPac functions that load the leaflet.js resources.
    Multiple config sections can be used and they will be processed in the order they appear in the XML file.
    Example: The tag <config2> ... </config2> defines an additional configuration section that will be executed when it is encountered in parsing of the XML data.
  • Several sections are named exactly the same as a corresponding ToolBook object on the page.
    Example: The tag <Leaflet_Map_1> ... </Leaflet_Map_1> corresponds with a field on the page called "Leaflet_Map_1"
    All of the sub-items in a section that corresponds to an object on the page or background will target the ToolBook object when styling or inserting content.
    Example: The tag <setHTMLContent> ... </setHTMLContent> will insert the data between the open/closing tags into the field "Leaflet_May_1". In this case, we are inserting a HTML <div> tag which the Leaflet.js library will use to insert its map contents.
  • In the XML file, we have defined other sections which do not correspond to ToolBook objects but when loaded will provide variable data as arrays that can be accessed at any time.
    Example: The tag <locations cords="..." name="..." /> defines a world location and includes it satellite coordinates so the Leaflet.js can navigate to it when it is chosen in a select list box. When the XML loads, we save the entire XML as a variable called [geo] and can call any location by using this syntax:
    geo [ "locations" ] [#] [ "coords" ]
    ... therefore, the following results can be determined in the Actions Editor once the XML file has finished loading:
      You can see from the XML file shown above that <locations /> 2 (counting from zero) defines the city of Brisbane, Australia. So in the Actions Editor we can get this data from the loaded XML data using the following methods.
      Image 3.png
      Getting XML data
      Image 3.png (3.03 KiB) Viewed 4797 times
    We have done something similar with sections like <load> ... </load> and <view> ... </view> and <pan> ... </pan> which each contain a JavaScript boilerplate snippet that is used to manipulate a map once it has loaded.
To add locations to the list boxes, all that need be done is just add them to the XML and they will be instantly available when the ToolBook application is reloaded. Thus, it is not always necessary to re-export your ToolBook applications. Generally, the only time this application needs to be re-exported is when some of the action code on the ToolBook page is modified to handle user interaction in other ways.

What do the tags <![CDATA[ ... ]]> mean?
    These tags are not always necessary, but are required when specifying HTML content inside an XML file. The tags signify that the content of the parent tag is to be treated as RAW character data. If we did not use such tags in the script areas or in the areas which contain HTML code, then the results would have been unexpected and may even have generated an error message when run in a browser.
    As a rule of thumb, if in doubt, wrap your actual data inside these tags to prevent anomalies.
If you would like assistance in setting up this or other XML tasks, please contact us for more information and assistance.
Send message to Clifton at: [email protected] OR [email protected]
Clifton
Site Admin
 
Posts: 732
Joined: Tue Jan 14, 2014 1:04 am

Return to XML Configurations – Plugin Examples

Who is online

Users browsing this forum: No registered users and 2 guests

cron