The Web ADF JavaScript Library provides access to Web ADF controls in a
scriptable browser environment. In most cases, Web ADF
applications will be centered around a Map control. As a
scriptable Web control, a Web ADF Map control is represented on both the client
(browser) and server (IIS\ASP.NET process). As a result, the Map controls
can be accessed via JavaScript on the client or .NET on the
server. Merely adding a Map control to an aspx page includes the
Web ADF JavaScript Library content necessary for using JavaScript to interact
with the map. In many cases the same action (e.g. method call or
property change) can be initiated on the map via code on the client
or server. Both the JavaScript and .NET Map class have events, methods,
and properties you can used to interact with the map. In
the page and code behind on the server you have access to the Web ADF
Map control as a .NET class. Accessing the JavaScript Map class on
the client via script in a browser must utilize (and is limited
by) JavaScript capabilities. JavaScript can be added in a
separate file or inline within the aspx page. In most cases, JavaScript
content will reside within the page header, body, or form and be triggered by
an action in the page, such as a key press or mouse click. The
ASP.NET AJAX JavaScript Library provides a framework for event handling
on JavaScript objects, so events can also trigger JavaScript code to
execute. Use the following discussion points and JavaScript code
snippets to get started working with the Web ADF JavaScript Library.
-
Getting the JavaScript Map instance
Assuming the server-side Web ADF Map control has been added to the page, use the ID of the Map control to find and get a client-side JavaScript reference to the Map class. If you need access to the Map class upon initial load of the page, attempt to find the Map control after the form containing it has loaded. Use the shortcut $find method included with the ASP.NET AJAX JavaScript Library.
[JavaScript]
var map = $find('Map1'); -
Navigate the Map
Both the server and client side Map classes maintain a set of methods and properties designed to navigate the map. While both generate the same results, in many cases the client-side JavaScript code offers a simpler solution. For example, to set the JavaScript Map class to a specific extent, set the extent property to a Web ADF JavaScript Envelope. As soon as the property is set, the action to update the Map is triggered.
[JavaScript]
var map = $find('Map1'); map.set_extent(new ESRI.ADF.Geometries.Envelope(-120, 35, -110, 45));
Properties on Web ADF JavaScript classes are prefixed with "set_" or "get_" depending on the accessibility of the property. Note, no server-side code was required to set the map extent in this example. Instead after the state of the JavaScript Map class changed, the Web ADF JavaScript Library synchronized the state with the server-side .NET Map class for you. To perform the same action using a pure .NET server-side solution with a Map control would require you to manage a Web request for a callback or partial postback pattern or use a Web ADF Toolbar and implement a map server command action class. All require considerably more code than a couple lines of JavaScript running within the browser.
Another example is provided by the Zoom method. Both the server and client side Map classes have a method to zoom to an extent defined by a scale factor. Like setting the extent property, as soon as the method is called, a Web request to update the map is generated.
[JavaScript]
var map = $find('Map1'); var scaleFactor = 2; var centerPoint = new ESRI.ADF.Geometries.Point(-110, 45); var useAnimation = true; map.zoom(scaleFactor, centerPoint, useAnimation);
Again, no server-side code was required. Note that the order of Web requests when working with a map via a client-side versus server-side solution is different. The Web ADF includes a .NET HTTP handler (MapHandler.ashx) to support dynamic map drawing on the server without iterating through the page lifecycle. This improves map draw performance, but skips events and methods included in the page (e.g. state maintenance, Web ADF control synchronization). As a result, a complimentary Web request to a page is required. When working with the JavaScript map class, Web requests to retrieve cached map tiles and dynamic maps via the MapHandler.ashx are generated first, then followed with a request to the page in which the map resides. Server-side solutions reverse the order since the action must occur on the .NET Map class first before the client JavaScript can be updated. The following diagram illustrates the client solution using the JavaScript Map class. Note, the map is rendered in the browser before the final Web request is made.
To accomplish the same task using the server-side Map control, a Web request which calls the Map.Zoom() method must be initiated. This means the request is sent to the page first, then upon the response the client-side Map class can do what it needs to update its content.
-
Working with map events
The JavaScript Map class maintains a group of event methods which leverage ASP.NET AJAX JavaScript Library to capture events on JavaScript objects within a browser at runtime. The event handler methods are prefixed with "add_" to add a handler or "remove_" to remove a handler. The handler consists of a JavaScript function which is usually passed two parameters: the sender (Map class) and event arguments associated with the event. Event handler functions can be defined upon initial load of the application by using the init event method of the ASP.NET AJAX Sys.Application object. To make sure the server-side content of the page has loaded (e.g. Map control representation in the browser), call the init method in a script block after the form containing to the Web controls. In the example below, a mouseMove event method on the Map class is configured upon application initialization. As the mouse cursor moves over the map, the current coordinates are updated in the browser status bar.
. . . </form> <script type="text/javascript"> Sys.Application.add_init(initialize); function initialize() { var map = $find('Map1'); map.add_mouseMove(mouseMove); } function mouseMove(sender,eventArgs) { window.status = sender.get_id() + ': ' + eventArgs.coordinate.get_x().toFixed(3) + ', ' + eventArgs.coordinate.get_y().toFixed(3); } </script>
The event argument passed to the mouseMove function is a type of Sys.UI.DomEvent which an additional coordinate property in map units.
See the Map and MapBase classes in the library reference for more information on the event handlers available for use. The following sections will discuss working with event handlers in the context of specific operations.
-
Track pending tiles during map draw
As a Web ADF developer working in an asynchronous communication environment, it is often beneficial to provide an end user with some indication that a user action is being processed. Since most Web ADF applications are centered on working with a map, the ability of an end user to effectively interact with map contents is essential. The ADF has the ability to asynchronously retrieve map images (dynamic or cached tiles) from multiple sources and consolidate it in a map control. In general, data sources often differ in the time it takes to respond to a request. Since the Web ADF map control is capable of rendering map data as it is returned to the browser, it is possible that some portion of data in the map is visible and accessible before another portion. In this case, it will likely be important to let the end user know when the map control has finished loading map data from any and all sources.
The JavaScript Map class maintains an onProgress event method to handle situations where the map is in process of retrieving and displaying map tiles. The Map control contains an integrated progress bar to indicate that a map is working to retrieve map images. This progress bar utilized the map's onProgress event to determine how it should render. Note, the progress bar can be disabled on the control (via the EnableProgressBar property) and replaced with a custom activity indicator.
The example JavaScript code below illustrates how to handle the onProgress event on the map and show\hide a custom activity indicator. The arguments to the onProgress handler are the map object itself (sender) and an integer indicating the number of map images pending retrieval (pendingTiles).
<script type="text/javascript"> var mapID = 'Map1'; Sys.Application.add_init(initialize); function initialize() { var map1 = $find(mapID); map1.add_onProgress(customProgress); } function customProgress(sender, pendingTiles) { if (sender != null){ window.status = "Pending tiles: " + pendingTiles; if (pendingTiles > 0) { // showLayer and hideLayer are part of the Web ADF JS library // in the display_common.js showLayer("BusyIndicator"); } else { hideLayer("BusyIndicator"); } } } </script> -
Modifying arguments in Web requests generated by a map
To add custom content to a Web request generated by a JavaScript Map object, use the onServerRequest method. The method passes a reference to the Map object and the input argument as an array. The array has an argument property which can be used to access the current argument-value pairs in the Web request and modify\add your own custom argument-value pairs. This capability is important for making the most efficient use of Web requests generated by interaction with a Map. In the example below, an HTML select element with a set of options is present within the page. The select element functions as a drop down list from which an end user can select an item. If a specific tool is selected, the selected option will be added to the Web request generated by the Map and available on the server-side. The selected option represents any client side element\property\value you want to send to the server. In this case, it may represent a selected layer, a query parameter, buffer units, etc. used by the selected tool's implementation code on the server.
<script type="text/javascript"> var selectedTool; Sys.Application.add_init(initialize); function initialize() { var map1 = $find('Map1'); map1.add_onServerRequest(mapServerRequest); var toolbar1 = $find('Toolbar1'); toolbar1.add_onToolSelected(toolbarToolSelected); } function toolbarToolSelected(toolbarObject, activeToolInfo) { selectedTool = activeToolInfo.tool; } function mapServerRequest(mapObject, inputArgument) { if (selectedTool && selectedTool.name == "MyTool"){ inputArgument.argument = addCustomArguments(inputArgument.argument); } } function addCustomArguments(args) { // Get value of pure client element (no server-side representation) var optionElement = $get("Select1"); var optionValue = optionElement.item(optionElement.selectedIndex).innerHTML; args += "&inlineArgument=" + optionValue + "&"; return args; } </script>