MapQuest Developer Blog

  • JavaScript API Updated to 5.2.1

    This morning we released an update to our JavaScript API. Version 5.2.1 uses DOJO 1.0.2, which fixes a bug in the original DOJO 0.9.0 GFX library that could cause line overlays to "jump" at certain zoom levels. If you do not use overlays in the 5.2 version of the JavaScript API, you do not need to make any changes.

    To update, simply change the version parameter to "v=5.2.1":
    <script src="http://btilelog.access.mapquest.com/tilelog/ transaction?
    transaction=script&key=YOUR_KEY_HERE&ipr=true&itk=true& v=5.2.1" type="text/javascript"></script>

  • South By Southwest 2008 Recap

    Thank you Austin!

    We just got back from a great couple of days at SXSW Interactive where we announced our new MapQuest Platform: Free Edition.

    It was great to talk with developers and that people were excited to see us doing our part to rock Austin, TX. We also got to make a lot of new friends at the show and other events around town. We showed off a bunch of demos in the booth and in case you missed your flight or otherwise wanted to check them out further, you can currently find them here: MapQuest Platform: SXSW Demos. You can download the code samples to help you get started on your own applications from that page as well.

    SXSW Demo Screenshot

    We also would like to thank everyone at SXSW Interactive, all of the organizers and sponsors of the SXSW Geeks Love Bowling Event and of course everyone who came by to talk to us. We appreciate all the feedback, support and can't wait to see you all next year.

    One last thing...

    Remember that our Platform is much better than our bowling:

  • Map It! - Building a MapQuest Mac OS X Dashboard Widget - Part 1

    A civilized nation can have no enemies, and one cannot draw a line across a map, a line that doesn't even exist in nature and say that the ugly enemy lives on the one side, and good friends live on the other. - Thor Heyerdahl

    The MapQuest Platform has become the preferred way for developers to integrate rich cartography into their applications. Using the MapQuest Platform, developers can provide street and satellite views. In addition points of interest, navigation, geocoding (converting an address to map coordinates), and routing are all supported. In this series of blogs - I will show developers how to build a Mac OS X Dashboard widget that will eventually provide mapping, point-to-point directions, and integration with the built-in Address book application - all powered by the MapQuest Platform.

    Development Platforms

    The MapQuest Platform APIs are accessible from a wide variety of development platforms and protocols. From the server side this includes: Java, .NET, and C++. From the client side this includes: AS3 (Adobe ActionScript 3), FUJAX, and JavaScript.

    Signing Up

    The MapQuest Developer Network is the place to get started. The site provides an overview of the APIs features, in addition to links providing an online demo, product brochures and more. Before a developer can begin using the APIs in their applications they need to sign up for a Free Edition or Developer license. As shown in Figure 1, you can start that process at - http://developer.mapquest.com/Home/WhyJoin - click on the Register button in the upper right.

    Figure 1

    You'll need to provide basic personal information, and accept the terms and conditions.

    Shortly after you submit your information, you'll receive an email, you'll need to click on the link in the email to confirm your request. Once confirmed, you'll receive a second email in about 20 minutes. This email will contain the URL to the MapQuest Technical Resource Center, your username (which is the email address you used to sign up) and a temporary password, which you will change after your first login. Also included in the message is the authentication information you'll need to access the MapQuest Platform from your application. I'll be using this information later in this series of blogs.

    After you login to the Technical Resource Center and change your password, as shown in Figure 2, you'll have complete access to the documentation, SDK downloads, examples, and your account information. Click on the My Account link to view the information shown in Figure 3.

    Figure 2

    Figure 3

    In addition to your support form user id, you will be able to configure the referrers for your account. The referrer information basically provides information about the domains where you will be accessing the MapQuest Platform. Note at the bottom that there is an option to permit blank referrers. Read the warning note closely if you enable this option. I will discuss the specific referrer issues that occur with a Mac OS X Dashboard widget in the next post in these series.

    Conclusion

    You now know how to get started with the MapQuest APIs. Here are some resources for you to review before I begin to build the Dashboard widget. Dig in!

  • Develop Freely! Introducing: MapQuest Platform: Free Edition.

    Hi! If you're reading this, you've gotten word we have this Developer Blog. A number of thoughts might be running through your mind as you hover over the "next" button on your feed reader or "close" on this browser tab:

    "MapQuest has a blog?"

    "MapQuest has a Developer Blog?"

    "MapQuest has Developers?"

    and if you're a mash-up developer: "MapQuest has APIs?"

    Yeah, yeah, we know. Over the past few years we know it seemed that on the outside MapQuest seemed a bit behind the times, a Web 1.0 giant sitting on the bench of a Web 2.0 Internet. However, inside MapQuest there have been people hard at work trying to change our culture and perspective into something that can thrive in a "Web 2.0" world. We've been changing teams, processes, some developers switched to Macs -- serious, real change.

    While we've been quiet, we've also been building things. More accurately, we've been rebuilding things. Starting with the 5.0 releases, we have rebuilt much of our geospatial web services platform from the ground up. Currently at version 5.2 and with 5.3 in beta, these releases contain lots of practical things, lots of cool things, lots of helpful things. Now we're making them free things.

    Developer Choice

    We're happy to finally introduce the MapQuest Platform: Free Edition. We've taken nearly all the features of our platform and made them freely available to developers. We believe that Free Edition provides developers a comprehensive toolset and flexible APIs so they can build well, whatever they want. Developers can choose the programming language of their choice and the features they need to build the applications they want, the way they want.

    Here's some of the Free Edition features:

    • Six APIs
      • We're giving developers greater flexibility and choice by enabling them to develop in a variety of programming languages and environments, they can even mix and match:
        • Java
        • C++
        • .NET
        • JavaScript
        • AS3 (Adobe ActionScript 3: Flash, Flex, AIR)
        • Our newest API: FUJAX (Flash Under JavaScript and XML), which allows developers to write in JavaScript, yet leverage the power of Flash.
        • and of course LOLcode. Nope, sorry, still no LOLcode suport.
    • A Rich Mapping Interface for creating Rich Internet Applications with our JavaScript, AS3, or FUJAX APIs:
      • Aerial Imagery and Hybrid Views - Satellite imagery and aerial photography.
      • Smart Rollovers - Rollover windows that adapt their size and positioning on the map based on the content placed in the window.
      • Smooth Zoom - Animated transitions between zoom levels.
      • Globe View - A map of the world presented as an interactive globe.
      • "Flickable" Maps - Maps that continue to pan based on speed and friction settings.
      • Advanced Shape Overlays - Build apps that allow users to create and interact with a variety of overlays on maps.
      • Advanced Map Marker Features - With "declutter mode," automatically move collided markers (POIs) to alternate positions on the map with a customizable leader line pointing back to their original location.
    • Unlimited Maps - Worldwide: Standard or Tiled.
    • Unlimited Geocoding - Multi-line and Single-line Geocoding, Real-time Batch Geocoding, Reverse Geocoding, Postal Code and Town Geocoding.
    • Unlimited Routing - Point-to-Point, Multi-point or Optimized.
    • Simplified Data Management - MapQuest offers access to simple tools to upload and manage location information to help keep websites accurate and relevant.

    You'll find more information on all of this on the MapQuest Developer Network, where you can also download the code and give the Free Edition a test drive. You can also find documentation, example applications and how-to articles to reference while checking out our APIs.

    Thanks!

  • FUJAX: Giving JavaScript a Good .SWF Kick in the AS!

    Are you a developer who wishes that you could get rid of a server-side proxy page to bypass cross-domain browser issues?

    Are you a JavaScript developer who longs to create maps that go beyond tiles and want to be entranced by the glitz and glamour that is Flash?

    If you answered "yes" to either of these questions, you need to know about the latest in Internet buzzwords: FUJAX.

    FUJAX is our newest API, released in our 5.2 update. It stands for: "Flash Under JavaScript and XML." Or, as Ant, our Senior Product Manager for our APIs explains (note: please read in your worst British accent):

    "All the visual, performance, and browser-agnostic benefits of Flash; all the knowledge ubiquity of JavaScript."

    The easiest explanation I can provide is: You (or your army of ninja programmers) continue to write JavaScript, when the page loads, it's a Flash map. Yep, JavaScript in; Flash out!

    While we have nothing but respect and adoration for the noble ActionScript 3 language and those who write it, we also know that there's plenty of JavaScript expertise running around AJAXing-up the Web. Now these JavaScript warriors can add Flash maps to their weapons lockers.

    • Enjoy that you can write the code once and have it run identically on all browsers with the Flash 9 plug-in or better.
    • None of the layered transparency issues when printing. Map output in Flash is WYSIWYG.
    • Performance benefits over the browser JavaScript engines. Of course, this will depend on your application; your mileage may vary.
    • Put all of that JavaScript know-how to use. Learn ActionScript later.

    So how do you use it? Well here's a very basic example of replacing a map built on the 5.2 JavaScript API with the 5.2 FUJAX API:

    • Replace "<script src="http://btilelog.access.mapquest.com/tilelog/ transaction?transaction=script&key=YOUR_KEY_HERE&ipr=true&itk=true&v=5.2.0" type="text/javascript"></script>"
      with
      "<script src="http://btilelog.access.mapquest.com/tilelog/ transaction?transaction=script&key=YOUR_KEY_HERE&ipr=true&itk=true&v=5.2.0w type="text/javascript"></script>"
    • Save and reload browser
    • See JS tiled map replaced with Flash

    That's it! Well, that's not it, there's a tons more you could do, but it's the end of this post. You can find the 5.2 FUJAX API bundled with the 5.2 JavaScript API on the MapQuest Developer Network.

  • Creating Points of Interest with Flex and the MapQuest 5.2 APIs

    So, if you read my previous blog post and tried out the example code that I provided, then you should be pretty comfortable using Flex and ActionScript with the MapQuest 5.2 APIs. I'm truly amazed that the MapQuest development team made it so easy for developers to create location-based applications for Flex applications. And for that matter, just in case you didn't know, the MapQuest APIs are available for other languages like Java, .NET, C++, and JavaScript, but since I'm really enthusiastic about using Flex, so I'm going to focus on the Flex side of things.

    So, let's say that there's a couple of "points"on the map that you're "interested" in observing. And let's also say that you want to see the "points of interest" (hence the name) together on the map at the same time. Well, today, I'll show you how to display points of interest (conveniently called POIs) within your mapping application. In the example code provided today, we're going to examine one of the many use cases where using POIs is very useful, meaningful, and convenient: real estate. So, let's say that I'm looking to buy a new home, and my agent wants to give me a customized website with all the homes that match my profile. The image below is the complete running application, from a fictional real estate company named, "The Real Estate Connection", displaying the homes that matched my profile.

    So, as you can see, there are two homes that matched my profile, according to the image shown above. Here's the ActionScript function that plotted the two POIs that you see above:

    public function main(): void{
    
      var zoomControl:ZoomControl = new ZoomControl();
      tilemap.addControl(zoomControl);
    
      // now let's set the points of interest
      var house1_coordinates:PointLL = new PointLL(40.720409,-73.994637);
      var house1_Poi:Poi = new Poi(house1_coordinates);
      house1_Poi.setInfoTitle("18044 Oak Lane");
      house1_Poi.setInfoContent("This a stunning 2 bed, 2 bath condo - $1.2M");
      var house2_coordinates:PointLL = new PointLL(40.720409,-76.994637);
      var house2_Poi:Poi = new Poi(house2_coordinates);
      house2_Poi.setInfoTitle("22365 Miller");
      house2_Poi.setInfoContent("This a great 2 bed, 2 bath condo - $400k");
    
      house1_Poi.setKey("A1");
      house2_Poi.setKey("B1");
      tilemap.addPoi(house1_Poi);
      tilemap.addPoi(house2_Poi);
    
      tilemap.setCenter(house1_coordinates,3);
    
    }
    

    So as you can see, I'm providing the coordinates of the locations that I want to show up on the map as a POI. Additionally, I can also provide a title and description (called the InfoContent) of the POI. You don't need to provide a key for your POI, unless you want to reference them later on. On the last line of the function shown above, I center the map on the first house's coordinates, and then I set the zoom level to 3. Obviously, this stuff is not hard, so take a look full source code below:

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:ns1="com.mapquest.tilemap.*" creationComplete="main();">
    <mx:Canvas x="36" y="10" width="600" height="341" backgroundColor="#ffffff">
    <ns1:TilemapComponent x="138" y="39" width="452" height="302" id="tilemap" key="mjtd%7Clu6y29u2n0%2C7s%3Do5-0ura9"/>
    <mx:Text x="10" y="39" text="Dear Bruce, welcome to your personalized real estate website. Take a look at the properties that I have identified for you. Feel free to contact us if you have any questions." width="120" height="172"/>
    <mx:Label x="183.5" y="10" text="The Real Estate Connection" fontSize="16"/>
    <mx:Image x="10" y="176" source="user-home.png"/>
    </mx:Canvas>

    <mx:Script>
    <![CDATA[
    import com.mapquest.tilemap.pois.*;
    import com.mapquest.PointLL;
    import com.mapquest.tilemap.controls.ZoomControl;


    public function main(): void{

    var zoomControl:ZoomControl = new ZoomControl();
    tilemap.addControl(zoomControl);

    // now let's set the points of interest
    var house1_coordinates:PointLL = new PointLL(40.720409,-73.994637);
    var house1_Poi:Poi = new Poi(house1_coordinates);
    house1_Poi.setInfoTitle("18044 Oak Lane");
    house1_Poi.setInfoContent("This a stunning 2 bed, 2 bath condo - $1.2M");

    var house2_coordinates:PointLL = new PointLL(40.720409,-76.994637);
    var house2_Poi:Poi = new Poi(house2_coordinates);
    house2_Poi.setInfoTitle("22365 Miller");
    house2_Poi.setInfoContent("This a great 2 bed, 2 bath condo - $400k");

    house1_Poi.setKey("A1");
    house2_Poi.setKey("B1");

    tilemap.addPoi(house1_Poi);
    tilemap.addPoi(house2_Poi);

    tilemap.setCenter(house1_coordinates,3);


    }

    ]]>
    </mx:Script>
    </mx:Application>

  • Capture the Flag: Using a JavaScript API to Enable Interactive Drawing in MapQuest

    Introduction

    The MapQuest Platform provides a powerful means for developers to integrate MapQuest technology into their web applications. In this article, I will demonstrate how to add interactive drawing to a map using the JavaScript-based API. In the resulting application, a user can set up a real-life game of Capture the Flag by drawing components of the game on an online map. You can see the application live here, and you can download the source in a .zip file here.

    Regardless of whether they have actually played Capture the Flag, most people can at least picture it in their heads. Traditionally, the game has been played primarily by children, with two teams pitted against each another in a quest to capture the opposing team's flag. Over the years, there have been innumerable variations of this game, in both the computer realm and in real life. In recent years, urban gaming has grown in popularity. Capture the Flag is just one of a number of games that are being played on an ever-increasing scale on the streets of cities throughout North America and Europe. The application that I show you in this article demonstrates how you can use the MapQuest API to facilitate planning this type of game.

    Starting From the Same Place

    Although the application is not overly complicated, I have set it up a bit differently than the introductory applications in the JavaScript API developer guide. To make things easier to understand, I will introduce a couple of the techniques that I used.

    To begin, I have split the application into three separate files: index.html, StyleSheet.css, and jrtmq.js. The focus of this article will be the code, which is contained almost exclusively within the jrtmq.js file. Within this file, I have created a namespace for all of the script, reducing the number of global symbols and allowing the <script> tags in the HTML file to contain just one line of code:

    Listing 1 - Called from the <script> tags
    
    	jrtmq.initMap();
    

    Because namespacing is not natively supported in JavaScript, you can use many different techniques to accomplish it. The approach I use is described in David Flanagan's book, JavaScript, The Definitive Guide. Essentially, this approach uses a JavaScript object to define the namespace. The first two lines of the file create that object.

    Listing 2 - Basics of a JavaScript namespace
    
      var jrtmq;
      if (!jrtmq) jrtmq = {};
    
      (function() {
        // The majority of the code is contained within this function.
        // ******* The Code *********
        // The following declaration assigns the InitMap function to the jrtmq
        // object. This becomes the public portion of the namespace, and is also
        // the only global symbol, reducing the potential for conflicts.
    
      jrtmq.initMap = InitMap;
    
      })();
    

    The majority of the code for this application is contained within the anonymous function which is called immediately after being loaded into the browser. The final line in that function assigns an initialization function, InitMap, to the jrtmq object that was created at the start of the file. When this method is called, using jrtmq.initMap(), it initializes the application. The remainder of the code (apart from some namespace-wide variables and the initialization function, startUp) resides within five separate objects: InfoBarTextChange, Utilities, ToolboxHandler, Draw, and InitFunc. The focus of this article is interactive drawing, and most of that functionality is contained within the Draw object.

    Working with Overlays

    The base class for all overlays within the JavaScript API is MQShapeOverlay. Although this application strictly uses MQLineOverlay and MQPolygonOverlay, most of the functionality is inherited from MQShapeOverlay. This means that most of the techniques and methods are the same, regardless of the type of overlay.

    The methods that actually do the drawing in the Capture the Flag application are Draw.borders and Draw.finish for polygons, and Draw.flags for points of interest (POIs). (Because of the much simpler nature of placing POIs, I won't discuss this method in the article.) Draw.borders allows the user to draw lines on the map using the MQLineOverlay class. These lines remain on the map while the user is drawing the shape. When the user signifies that the shape is complete, Draw.finish is called, placing an MQPolygonOverlay to replace the lines. I've used a simple HTML button to let users indicate that the shape is complete, but in a more complex application this could be done differently. Utilities.cancelDrawing, the final method in the process, cleans everything up and removes the lines.

    Draw.borders is called from an event listener. I will discuss events within the API later in this article. For now, it is sufficient to know that e is the event object that's passed into the method, and that the event we are handling is a click event (note that all events are lowercase). The event object contains a few different pieces of information, but the one we are concerned with is the latitude and longitude (Lat/Long) of the point that was clicked, e.ll.

    Listing 3 - Draw.borders
    
    	borders:function(e){
                var myLine = new MQLineOverlay();
    
                if(startEnd == "start"){
                    startEnd = "end";
                    ProcessLLFirst = e.ll;
                    UltimateLL.add(e.ll);
                } else{
    	      ProcessLLSecond = e.ll;
                    UltimateLL.add(e.ll);
                    var ProcessLL = new MQLatLngCollection();
                    ProcessLL.add(ProcessLLFirst);
                    ProcessLL.add(ProcessLLSecond);
                    myLine.setColor("#000000");
                    myLine.setShapePoints(ProcessLL);
                    myLine.setBorderWidth(1);
                    myMap.addOverlay(myLine);
                    Lines.add(myLine);
                    ProcessLLFirst = ProcessLLSecond;
                }
            },
    

    The main components of Draw.borders are the myLine object, the startEnd variable, two MQLatLng objects and two MQLatLngCollection objects.

    When the method is first called, startEnd is true. (Although I have not declared startEnd within this method, it is not actually a global variable. It is declared in the anonymous function that encloses all of our code, allowing it to act like a global variable for the purpose of this namespace.) The latitude and longitude of the click are added to both an MQLatLng object and an MQLatLngCollection, UltimateLL. The objects ProcessLLFirst and ProcessLLSecond are used for constructing the lines, and UltimateLL is used for constructing the MQPolygonOverlay by which they will eventually be replaced.

    On subsequent clicks, startEnd is false and e.ll is placed into ProcessLLSecond. The two "process" objects are then added to a new MQLatLngCollection, which is passed to myLine. This step is necessary because all of the MQShapeOverlay objects expect an MQLatLngCollection as the argument for their setShapePoints method. Setting the other attributes is fairly straightforward, and a list of all possible attributes can be found in the API developer guide. After the line is added to the map using the addOverlay method, myLine is added to an MQOverlayCollection, Lines, which will eventually be used to remove the lines from the map.

    Listing 4 - Draw.finish
    
    	finish:function(){
                if(UltimateLL.getAt(1)){
                    var myColors =
                      Utilities.colorGen(document.drawMenu.selectColor.value);
                    var myBorders = new MQPolygonOverlay();
                    var LLList = new MQLatLngCollection();
                    for(var i = 0;i<UltimateLL.getSize();i++){
                        LLList.add(UltimateLL.getAt(i));
                    }
                    myBorders.setBorderWidth(3);
                    myBorders.setColor(myColors.a);
                    myBorders.setFillColor(myColors.b);
                    myBorders.setColorAlpha(0.8);
                    myBorders.setFillColorAlpha(0.4);
                    myBorders.setShapePoints(LLList);
                    myMap.addOverlay(myBorders);
                    Utilities.cancelDrawing();
                }
            }
    

    The method that finishes off the drawing is Draw.finish. As I mentioned above, it is called when the user clicks the Finish button in the toolbox. The method first checks to make sure there are at least two objects present in the UltimateLL collection (preventing an accidental button click from messing things up). If the two objects are present, the method goes on to create a polygon using latitude and longitude coordinates that are contained within the collection. Adding properties to the polygon is fairly straightforward, and is the same as for all MQShapeOverlay objects. There are a couple of things in this method that I will point out, however, before I move on. The first is the Utilities.colorGen method. This method takes a string as an argument and returns an object that contains two string properties representing the border color and the fill color of the polygon.

    Listing 5 - Utilities.colorGen
    
            colorGen:function(convertee){
    
       // For the sake of simplicity, I hardcoded a few values
                // to represent the colors. The ColorGen function could
                // easily be modified to implement a more complicated
                // color selection system. Whatever the system, the function
                // should accept a parameter and return an object containing the
                // two color values.
    
                switch(convertee){
                    case 'red':
                        return { a:"#DF374E", b:"#FFCFCF" };
                    case 'green':
                        return { a:"#008F13", b:"#C7AFFF" };
                    case 'grey':
                        return { a:"#999999", b:"#ffffff" };
                }
            }
    
    

    The second thing I will point out is the LLList collection and the for loop. A problem arises when an object with a scope outside of the immediate function is used to populate the ShapePoints of the MQPolygonOverlay. If that object is then cleared (which is necessary to allow drawing multiple overlays) the ShapePoints for the MQPolygonOverlay object are also cleared, causing the overlay to disappear. Assigning the contents of the UltimateLL collection to a new collection one by one seems to eliminate this problem. Other than that, Draw.finish is fairly straightforward. When the polygon has been added to the map, the Utilities.cancelDrawing method is called, which is the universal method within this application for cleaning up loose ends. Before I discuss that method, though, I'm going to take a step back and talk about events within the API.

    The MQEventManager

    All of the events within the MapQuest JavaScript API are handled by the MQEventManager. Within the Capture the Flag application, after the user selects what they want to draw and the color they want to draw it in, they click the Draw button in the toolbar. This button calls Draw.init, passing it a string representing the object the user would like to draw. For the purpose of this application, there are two choices. Draw.init is the method responsible for initiating the drawing process.

    Listing 6 - Draw.init
    
            init:function(draWhat){
                if(!clean){
                    Utilities.cancelDrawing();
                }
                clean = false;
                myMap.enableDragging(false);
                if(draWhat == 'border'){
                    MQEventManager.addListener(myMap, "click", Draw.borders);
                } else if(draWhat == 'flag'){
                    MQEventManager.addListener(myMap, "click", Draw.flag);
                }
            }
    

    The first thing this method does is check the clean variable. This is just an error-checking variable that is set to false while drawing is in progress. If it is false at this point, something is wrong, so the method calls Utilities.cancelDrawing to clean up before it continues. myMap.enableDragging accepts a Boolean argument and is used to prevent the user from dragging the map, making drawing a lot easier.

    The biggest role that Draw.init plays is to add the appropriate event listener, depending on the user's selection. MQEventManager contains four methods, allowing you to add a listener, clear all of the listeners of a certain type, specify a single listener to remove, or trigger a custom event. Each of the first three methods are used at some point in this application. The arguments for the methods are fairly straightforward as well. The first argument is the object to attach the handler to, the second is the event to listen for, and the third is the callback function.

    I have mentioned the Utilities.cancelDrawing method a number of times now, because it is called in a few different situations. Its main purpose is to provide a "clean slate" after an overlay has been drawn, or if something goes wrong. It does this by reenabling drawing, resetting the necessary variables and collections, and removing any outstanding lines from the map. This leaves the application in essentially the place that it started but obviously doesn't touch any polygons or POIs that the user has intentionally added. When Utilities.cancelDrawing has been called, the drawing process is complete. Thus, the minimum functionality to allow interactive drawing is contained within the following methods: Draw.init, Draw.borders, and Draw.finish.

    	Listing 7 - Utilities.cancelDrawing
    
    	cancelDrawing:function(){
                myMap.enableDragging(true);
                MQEventManager.clearListeners(myMap, "click");
                if(Lines.getAt(0)){
                    startEnd = "start";
                    ProcessLLFirst = ProcessLLSecond = null;
                    UltimateLL.removeAll();
                    for(var i = 0; i < Lines.getSize(); i++){
                        myMap.removeOverlay(Lines.getAt(i));
                    }
                    Lines.removeAll();
                }
                if(!clean){
                    clean = true;
                }
            }
    

    Setting Up the Toolbox

    The last thing I will discuss before I bring it all together is the toolbox. The code for the toolbox is contained in two main areas: InitFunc.toolbar and the ToolboxHandler object.

    InitFunc.toolbar performs a simple task. It is called during the application's initialization sequence, and its sole purpose is to add event handlers to the various elements of the toolbox.

    Listing 8 - InitFunc.toolbar
    
            toolbar:function(){
                var boxLinks =
                  document.getElementById('toolBoxProper').getElementsByTagName('a');
                document.drawMenu.drawType[0].checked = true;
                for(var i = 0;i<boxLinks.length;i++){
                    boxLinks[i].onclick = ToolboxHandler.menu;
                }
                document.getElementById('bt1').onclick = ToolboxHandler.menu;
                document.getElementById('bt2').onclick = ToolboxHandler.menu;
                document.getElementById('bt3').onclick = ToolboxHandler.city;
                document.getElementById('rb1').onclick = ToolboxHandler.radio;
                document.getElementById('rb2').onclick = ToolboxHandler.radio;
    
            }
    

    I've used three separate event-handling methods, all of which are properties of the ToolboxHandler object. ToolboxHandler.menu handles all of the links in the toolbox as well as the two drawing buttons. It uses a switch statement and calls a method based on the ID of element that was clicked. The purpose of ToolboxHandler.radio is to discover whether the user has selected the borders or flags radio button. If the user has selected flags, the handler causes the neutral color to be disabled in the menu. It also causes the information section at the bottom to update, displaying help information related to the current selection.

    The following listing shows ToolboxHandler.city. Using hard-coded coordinates, this method allows the user to select a city from a menu and uses MQTilemap.setCenter() to center the map on that location.

    Listing 9 - ToolboxHandler.city
    
            city:function(){
                switch(document.cityMenu.selectCity.value){
                    case 'toronto':
                        var StartCoords = new MQLatLng(43.648366, -79.385019);
                        break;
                    case 'newyork':
                        var StartCoords = new MQLatLng(40.720409, -73.994637);
                        break;
                    case 'seattle':
                        var StartCoords = new MQLatLng(47.60629, -122.330624);
                        break;
                    case 'vancouver':
                        var StartCoords = new MQLatLng(49.260281, -123.113463);
                        break;
                }
                myMap.setCenter(StartCoords,10);
            }
    

    Putting It All Together

    As I said at the beginning of this article, the only thing we call directly from the HTML file is the jrtmq.initMap method. This method's primary responsibility is calling the initialization function, startUp, after the page has loaded and the required libraries are initialized.

    InitFunc.map initializes the map and adds the zoom control and the map view control, all of which are covered thoroughly in the developer guide.

    Listing 10 - Initialization Functions
    
        // Calls methods to initialize the map, the toolbar, and the text area
        // at the bottom of the page.
    
        function StartUp(){
            InitFunc.map();
            InitFunc.toolbar();
            InfoBarTextChange.welcome();
        }
    
        // The public function that is called directly from the page.
        // It waits for the page 'load' event and the anonymous callback
        // function then uses the MQInitDojo method to call the startUp function
        // once the Dojo Library has been initialized.
    
        function InitMap(){
            if(window.addEventListener){
                window.addEventListener('load', function() {
                  MQInitDojo(StartUp);}, true );
            } else{
                window.attachEvent("onload", function() {MQInitDojo(StartUp);});
            }
        }
    
        // Assign the public portion of our namespace to the jrtmq class.
        jrtmq.initMap = InitMap;
    

    I haven't covered every aspect of the Capture the Flag application here. To make it more than just an example, I have included greater functionality than could be explained in a single article. Most of the remaining functionality, however, is complementary to the drawing capabilities of the application, and should be fairly straightforward to figure out. The code is commented and organized into objects that are fairly self-explanatory. If you haven't done so already, now is probably a good time to download the files and take a look inside. To bring this all together and provide a bit of context, I will summarize the initialization process of the application. This is a summary of what happens when a user first navigates to the index.html page:

    The jrtmq.initMap method is called from the HTML document and starts the initialization sequence using the two main initialization methods, InitFunc.map and InitFunc.toolbar). During that sequence, the map is set up and the MQTileMap object is passed to the variable myMap, event listeners are assigned to all of the components in the toolbox, and the information bar is populated with a welcome message. The main elements of the toolbox can be divided into three sections: the drawing section, the utilities section, and the help section. All of the functionality of the application is initiated from the toolbox and handled by ToolboxHandler.menu, ToolboxHandler.radio, and ToolboxHandler.cities. Each section of the toolbox has an object associated with it that contains most of the functionality for that section: InfoBarTextChange (used mostly for the help section), Utilities, and Draw. Drawing is accomplished primarily with three methods: Draw.init, Draw.borders, and Draw.finish.

    Where to Go from Here

    In this application, there are a lot of areas in which you could add functionality: geocoding specific locations, adding a better color selection system, or simply improving the UI. The modularity of this code lets you apply the principles to any number of contexts or add functionality quite painlessly. As an example of this flexibility, I'll be writing a couple of blog posts in coming weeks to demonstrate adding rollover windows to overlays by adding a module to this application.

    And finally, here are a few links on urban gaming to get your imagination going:

  • Beta Update: 5.3 Release Candidate 2 Released!

    Turn Your World Upside Down

    Let's talk briefly about globes. You know, those ones that sit in libraries in period piece movies where some old guy in a leather chair sits next to it, smoking a pipe and calling Shakespeare a hack? Those globes. The ones where when you see them, you can't help but spin it as hard as you can in the slim hope the momentum will send it rolling across the room.

    Well you can now create and spin your own virtual globe. We fixed a bug in the new full-axis globe view so you should now see improved performance when trying to spin it off your web page.

    if (AC_FL_RunContent == 0) { alert("This page requires AC_RunActiveContent.js."); } else { AC_FL_RunContent( 'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0', 'width', '450', 'height', '450', 'src', 'http://globe.mapquest.com/blogfiles/2008-03-03_embedglobe', 'quality', 'high', 'pluginspage', 'http://www.macromedia.com/go/getflashplayer', 'align', 'middle', 'play', 'true', 'loop', 'true', 'scale', 'showall', 'wmode', 'window', 'devicefont', 'false', 'id', 'Untitled-1', 'bgcolor', '#ffffff', 'name', '2008-03-03_embedglobe', 'menu', 'true', 'allowFullScreen', 'false', 'allowScriptAccess','sameDomain', 'movie', 'http://globe.mapquest.com/blogfiles/2008-03-03_embedglobe', 'salign', '' ); //end AC code }

    KML and GeoRSS Support: We got it.

    Create a RemoteCollection, tell it the location of the feed and its format, and watch it get automagically sucked onto the map! And if you have another format, feel free to extend the feed loading classes to create your own loadable formats. Sorry, LOLcode support is still a no-go.

    But wait, there's more!

    Here's the list of other major updates in the just released 5.3rc2 Beta update of the MapQuest Platform:

    • Beta Issues Forum now available - A forum for posting about Beta has been created in the Technical Resource Center.
    • Old POI & Overlay Getters/Setters restored (JavaScript) - We've added back in the 5.2 getters and Setters for POIs and Overlays.
    • POI & Overlay getValue & setValue methods added (JS and FUJAX) - The new getValue and setValue functions have been added to the POI and Overlay objects in FUJAX so that both the old, and the new methods of setting properties on these objects are now available in both JavaScript and FUJAX.
    • Multiple Collections (JS, AS3, FUJAX) - Building on our efforts last month to combine POICollections and OverlayCollections into a single ShapeCollection, you can now add multiple ShapeCollections to a map.

    Check out more information and samples on the MapQuest Developer Network Beta page.

  • Meet Us At SXSW!

    I'm writing about one show while I'm attending another. I'm in the beautiful city of Miami at the Future of Web Apps conference. As this show is winding down from a great day of learning, meeting, networking and demoing, people are already talking about next big migration of developers and technophiles: The South By Southwest Interactive Festival in Austin, Tx.

    I used to live in Austin and I love when I have the opportunity to come back. This year when I visit, my MapQuest colleagues and I are also bringing a cool booth, some swag and most importantly some exciting, ground-breaking, game changing, super fantastic things to share and tell you. (Okay, I may have oversold that last part a little, but you will dig it.)

    Oh yeah, we're also on a Geeks Love Bowling team.

    So if you're heading to South By Southwest, please make sure you swing by our booth between Sunday, March 9th to Tuesday, March 11th. We look forward to meeting and chatting with you! If you're not going, keep reading this blog and the blogs of everyone who is going and having all kinds of fun that you're not.

    See you there (or not)!

  • First Post! - Getting started with Flex and the MapQuest 5.2 APIs

    Back in the day, there was always some glory about getting the first post on a popular topic on Slashdot. The first-poster got the opportunity to lead the discussion (or flame war) on the current topic that was on the site. Well, this is my first post on the AOL developer site, so let me introduce myself. I'm Bruce Hopkins, the author of the book, "Bluetooth for Java" by Apress, and I have have recently fallen in love with Flex and ActionScript programming. I've used Java for over 10 years (way back with JDK 1.0a) and it's great for server-side application development, but lacks in certain areas for client-side applications. Well, unless you've been in a cave for the last 2 years, you probably already know that Flex works extermely well for client-side applications, and plays nicely with integrating with Java EE, .NET, SOAP, and REST backends.

    So, today, I'm going to introduce you to Flex application development, and we'll get our hands dirty with the MapQuest 5.2 APIs. I'm really excited that MapQuest has decided to make the latest version of their API free for developers, and since their mapping APIs support Flex 2 / Flex 3 it's the best choice for Flex developers for mapping APIs. Take a look at the code snippet below:

    <mx:Canvas x="36" y="29" width="571" height="322"
      backgroundColor="#ffffff">
      <mx:Label x="19" y="10" text="Select Map Type:" width="126"/>
      <mx:ComboBox id="mapTypeComboBox" x="19" y="29" width="148"
        dataProvider="{mapTypeComboData}"
        change="changeMapType();"></mx:ComboBox>
      <ns1:TilemapComponent x="175" y="10" width="376" height="302"
      id="tilemap" key="123456754322434"/>
    </mx:Canvas>
    

    It's only 5 lines of XML that allow you to define all the visual layout for a simple application. So, as you can see in the code above, I have a Label, ComboBox, and TilemapComponent wrapped in a Canvas. All the components are a part of the Flex SDK, except for the Map, which is a part of the MapQuest 5.2 APIs. When you signup for a developer account, you'll get a key where you'll insert into the "key" attribute of TilemapComponent. Now, take a look at the rest of the code:

    <mx:Script>
      <![CDATA[
    
      [Bindable]
      public var mapTypeComboData: Array = [ {label:"Map View", data:"map"},
            {label:"Satellite View", data:"sat"},
            {label:"Hybrid View", data:"hyb"} ];
    
      public function changeMapType(): void{
        tilemap.mapType =
        mapTypeComboData[mapTypeComboBox.selectedIndex].data;
     	}
     	]]>
     </mx:Script>
    

    As you can see, I populated a simple Array with the data that feeds the ComboBox, and I defined a function to be called when the ComboBox is changed. And that's it! The image below shows a screenshot of our application:

    So, as you can see, it's pretty easy to use Flex to create mapping applications with the MapQuest 5.2 APIs. Below is the full source code for you to copy.

    <?xml version="1.0" encoding="utf-8"?>
       <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
       layout="absolute" xmlns:ns1="com.mapquest.tilemap.*">
     <mx:Canvas x="36" y="29" width="571" height="322" backgroundColor="#ffffff">
     <mx:Label x="19" y="10" text="Select Map Type:" width="126"/>
     <mx:ComboBox id="mapTypeComboBox" x="19" y="29" width="148"
     dataProvider="{mapTypeComboData}" change="changeMapType();"></mx:ComboBox>
     <ns1:TilemapComponent x="175" y="10" width="376" height="302" id="tilemap"
     key="mjtd%7Clu6y29u2n0%2C7s%3Do5-0ura9"/>
     </mx:Canvas>
    
     <mx:Script>
     <![CDATA[
    
     [Bindable]
     public var mapTypeComboData: Array = [ {label:"Map View", data:"map"},
     {label:"Satellite View", data:"sat"},
     {label:"Hybrid View", data:"hyb"} ];
    
     public function changeMapType(): void{
     tilemap.mapType = mapTypeComboData[mapTypeComboBox.selectedIndex].data;
     }
    
     ]]>
     </mx:Script>
     </mx:Application>