Tag Archives: JavaScript
Customizing the map progress bar in the 9.3 Web ADF (.NET)
The Web ADF includes a progress bar that displays when the map is loading map images or tiles. It makes the user aware that the site is processing the user’s request. You may wish to customize the progress bar, either to modify it or to replace it with your own progress indicator. An earlier blog post described how to do this at the 9.2 version. Things have changed for the 9.3 version, and this post gives some tips on customizing the progress bar for 9.3.
We will cover two options for customizing the progress indicator. First, you can set some of the properties of the existing progress bar. Second, you can completely replace the progress bar with your own custom progress indicator. The second option involves working with custom progress events, which we will discuss before we get to the actual replacement of the default progress indicator.
Setting progress bar properties
At the 9.3 release, two public properties are exposed that you can set for the standard progress bar. These properties are the alignment, or location, of the progress bar on the map; and whether to enable or disable the progress bar. More properties may be exposed at future service packs or versions. We will use the enable/disable property later in this article, when we replace the progress bar. Let us look now at setting the alignment property, which will introduce a client-side approach we will use throughout this article.
The alignment property may be set using the Web ADF JavaScript Library. The Web ADF contains both code that runs on the server and code that runs on the client. The server-side code uses an ASP.NET language (C# or VB). The client-side code uses JavaScript, so we use that language to customize how the client code works. You can find documentation on the Web ADF JavaScript Library in the ArcGIS Server Developer Help, available either installed on your development computer, or online at the ESRI Resource Center. See the topic Web ADF JavaScript Library under the heading Developing Web applications using the Web ADF.
The progress bar properties are on the Map, since the bar is tied to the Map. Most of the properties and methods for the Map class are actually on the MapBase class, which the Map class extends. If you look on the class properties for MapBase, you will find the progressBarAlignment property. You will notice that, like most other properties, the documentation actually shows two methods associated with this property: get_progressBarAlignment() and set_progressBarAlignment(). As you will see in the code, we use these methods rather than the property per se when setting the propery.
The set_progressBarAlignment() method takes one argument when you call it: a ContentAlignment setting. For information on this enumeration, you can click on the ContentAlignment link on the progressBarAlignment page in the help, or find it under the ESRI.ADF.System namespace in the Web ADF JavaScript Library documentation. The ContentAlignment enumeration has nine values, corresponding to nine positions on the map. They include TopLeft, MiddleCenter, and BottomRight (the default).
Now we have the information we need to set the progress bar’s alignment. To demonstrate, we will set the progress bar alignment to the MiddleCenter of the map. To do this, we add some JavaScript code into the .aspx page for our application, typically the Default.aspx page. Near the bottom of the page, just before the closing </body> tag, add a JavaScript function that will be called when the page starts up. We can do this using the ASP.NET AJAX add_init function, which guarantees our function will run after the page completely loads. We pass to add_init the name of the function (setupProgressIndicator) that will be called on startup.
In the setupProgressIndicator function, we get a reference to the JavaScript component for the map, using the ASP.NET AJAX $find function. Then we set the progress bar alignment using the ContentAlignment value we want. The resulting code would go into your .aspx page, just before the closing </body> tag.
<script language="javascript" type="text/javascript">
// Have our custom function called when the user starts the application
Sys.Application.add_init(setupProgressIndicator);
function setupProgressIndicator() {
// Get the JavaScript map component
var map = $find('Map1');
// Set the location of the progress bar
map.set_progressBarAlignment(ESRI.ADF.System.ContentAlignment.MiddleCenter);
}
</script>
Custom progress events
If you want to do more than set the alignment of the built-in progress bar, you can have custom code that runs when the map is loading images or tiles. You can use this approach to supplement the standard progress bar, or completely replace it with your own indicator. The map’s onProgress event enables us to run custom code. This and other map events are discussed in the Web ADF JavaScript Library section of the Developer Help. In this section, we will use this event to display the number of pending tiles on the progress bar. Later we will replace the progress bar with a custom indicator.
To show custom content when the map is loading images or tiles, we can use the onProgress event on the map client. This event is new at 9.3, and replaces multiple events that were used at 9.2 (onRequestsPending, etc.). When a function is attached to the onProgress event, it gets called each time the number of pending tiles changes. The custom function takes two arguments: the sender of the event, which is the map component; and the number of pending tiles. You can check the second argument to determine what to display to the user.
In the code sample below, we attach to the onProgress event by calling the map’s add_onProgress method. We pass it the function to be called when the number of pending tiles changes. In this function, showProgress, we examine the number of tiles as given in the args value. If the number is greater than zero, then we display the number of tiles in the browser’s status bar. If the number of tiles is zero (i.e., the map is finished loading tiles), then we hide the status bar message.
<script language="javascript" type="text/javascript">
Sys.Application.add_init(setupProgressIndicator);
function setupProgressIndicator() {
// Get the JavaScript map component
var map = $find('Map1');
// Set the location of the progress bar
map.set_progressBarAlignment(ESRI.ADF.System.ContentAlignment.TopLeft);
// Add the custom progress function
map.add_onProgress(showProgress);
}
// Custom progress function
// sender = map component, args = number of pending tiles
function showProgress(sender, args) {
// If tiles pending, display number in status bar
if (args > 0) {
window.status = "Pending map tiles: " + args.toString();
} else {
// All tiles loaded - hide status bar message
window.status = "";
}
}
</script>
Custom progress indicator
Finally, we look at how to completely replace the existing progress bar with a custom indicator. The steps are: (1) turn the standard progress bar off; (2) create our custom progress indicator; and (3) turn on and off our custom indicator using the onProgress event described earlier.
The best way to turn off the standard progress bar is to use the EnableProgressBar property on the ASP.NET Web control. You can set this in Visual Studio by switching the page to Design view, selecting the Map control, and setting EnableProgressBar to False in the Properties window. Or, you can scroll up in the Source view to the Map control and add the EnableProgressBar property there, like this:
<esri:Map ID="Map1" runat="server" Height="423px"
MapResourceManager="MapResourceManager1" Width="554px"
EnableProgressBar="False" >
</esri:Map>
Second, we’ll create our custom progress indicator. This indicator can be as simple or complex as you wish. An animated GIF image is common, but you could write a custom indicator similar to the built-in progress bar, which uses multiple divs and styles to create an animation. For our example, we will use the ajax-loader-circle.gif image, which is included with several samples in the Web ADF developer samples, such as ArcGIS_Spatial_Query_SOE. We copied this gif into our Web application folder and added it into the .aspx page within a div. We set the style position of the div so that it is approximately centered on the map control. Of course you could add code to dynamically position the progress indicator over the map, such as by getting the map’s offsetLeft/offsetTop and setting the progress indicator’s style position (see the zip file for the sample for an example of this).
<div id="progressImageDiv" style="position:absolute;left:250px;top:320px;">
<img id="progressImg" src="ajax-loader-circle.gif" alt="Loading..." />
</div>
Third, to show and hide our custom progress indicator, we use the same approach with the onProgress event as above. If tiles are pending (args > 0), then we show the progress indicator; otherwise we hide the indicator. To show/hide the indicator, we could add code to get the indicator div and set its style.display property. But the Web ADF has built-in functions to show or hide a div section, which we will use instead: showLayer and hideLayer. The complete code, with both the custom progress indicator and status bar text, is shown below.
<div id="progressImageDiv" style="position:absolute;left:250px;top:320px;">
<img id="progressImg" src="ajax-loader-circle.gif" alt="Loading..." />
</div>
<script language="javascript" type="text/javascript">
Sys.Application.add_init(setupProgressIndicator);
function setupProgressIndicator() {
// Get the JavaScript map component
var map = $find('Map1');
// Add the custom progress function
map.add_onProgress(showProgress);
}
// Custom progress function
// sender = map component, args = number of pending tiles
function showProgress(sender, args) {
var progressImageDiv = $get("progressImageDiv");
// If tiles pending, display progress indicator and tile number in status bar
if (args > 0) {
window.status = "Pending map tiles: " + args.toString();
progressImageDiv.style.display = "block";
} else {
// All tiles loaded - hide progress indicator and status bar message
window.status = "";
progressImageDiv.style.display = "none";
}
}
</script>
The code produces something like this when the progress indicator is displaying:

The complete code for this sample is available in this zip file. The code includes a few enhancements to the code above, such as an option to recenter the custom progress indicator if the map is resized, which may occur with the Web Mapping Application template. You can also try out this sample with the link provided.
Conclusion
We have seen how to customize the progress indicator for the map, both by setting properties of the standard progress bar and by adding our own custom event handling to display information or even a custom progress image. The map has other events and properties that you could use for performing custom handling on the client. See the Web ADF JavaScript Library reference in the Developer Help for further information.
Contributed by Bryan Baker of the ArcGIS Server .NET software development team.
Creating a simple map dijit with the ArcGIS JavaScript API
Dojo Widgets or dijits are a great way to build web application UI components that either combine other components or bind data with business logic. Dijits are designed to be easy for users embed within their web applications.
In this post we’ll create a dijit that could allow a large city to share its mapping data with its citizens and allow businesses to integrate other functionality.

The Basics
When creating a dijit or a collection of dijits, it’s recommended that you use a specific folder structure. Each dijit requires a template, some cascading style sheets (CSS) and some images. Correspondingly, there are the templates, css and images folders. It is up to you whether to create these folders for each dijit or share these among several dijits.

The Template
All dijits start off with a layout that puts together the visual components. This dijit will contain a <div> for the map, a <span> with 2 buttons for toggling data layers and finally an <img> with the city seal. Clicking on the image opens a new window and navigates to the city’s home page.
You can optionally use CSS to style the visual components. In this case, since the toggle buttons and image are map overlays, we’ll apply CSS styling appropriately.
templates/MyFirstMapDijit.html
<div class="mapdijit">
<span class="layerbuttons">
<button dojoType="dijit.form.ToggleButton" dojoAttachEvent="onXXX:callback" ID="Button1">Neighborhoods</button>
<button ... checked ID="Button2">Landbase</button>
</span>
<img src="..." class="seal" dojoattachevent="onclick:gotoCityOfPortland" />
</div>
It’s important to note the dojoType, dojoAttachEvent, and dojoattacheevent attributes:
- You will need to specify the dojoType attribute in order to allow the Dojo parser system to parse and apply rendering for appropriate dijits. This attribute value matches the name of a dijit class.
- The dojoAttachEvent attribute connects a specific event onXXX on the dijit and calls the specified callback function.
- The dojoattachevent attribute connects a specific event, say onclick on the HTML element and calls the specified function gotoCityOfPortland.
The Stylesheet
A CSS file is used to style the look and feel of the dijit. A user can potentially change the CSS to change the look and feel of this dijit.
css/MyFirstMapDijit.css
.mapdijit { position:relative; }
.mapdijit .layerbuttons { ...; z-index:100; ... }
.mapdijit .seal { ...; z-index:100; }
The CSS classes are referenced in the class attribute in the template markup. One thing to note is the z-index attribute on all map overlays. It is recommended that you use a z-index of 100 or higher when an element needs to display on top of a map.
The Dijit Class
Each dijit is backed by a JavaScript class which defines the behavior of the dijit. We’ll add the ability to add/toggle data layers and the additional behavior of opening the city’s home page when a user clicks on the seal.
As part of the lifecycle of the dijit, at the last step at startup, we will initialize the map once all the HTML elements have been laid down and presented to the client.
MyFirstMapDijit.js
dojo.provide(...);
//include all dijit dependecies
dojo.require(...);
//declare new dijit class
dojo.declare("mydijits.MyFirstMapDijit", [dijit._Widget, dijit._Templated], {
//dijit template contains other dijits
widgetsInTemplate: true,
//path to template
templatePath: ...,
//dijit startup method to initialize map
startup: function() { ... },
//behavioral functions
toggleLandbase: function(visibility) { ... },
toggleNeighborhoods: function(visibility) { ... },
_toggleLayer: function(layer, visibility) { ... },
gotoCityOfPortland: function() { ... }
}
);
The toggle* and gotoCityOfPortland functions provide the desired custom functionality. The esri.Map is instantiated within the startup function. The widgetsInTemplate property specifies that the template contains other dijits. The templatePath specifies the path to the template file for the dijit. If the template is very simple, you can alternatively use the templateString property and provide the markup in this string and not create a template file.
Note: Specifying a template string reduces the number of server calls to fetch a template from a running application if a web page contains several different dijits.
Testing the Dijit
That’s it! You are now ready to share this dijit with your users. To test it out, we’ll add the dijit to a blank page and verify that it works.
MyFirstMapDijitTest.html
<head>
...
<title>MyFirstMapDijit Test</title>
<!-- include dojo theme -->
<link href=".../tundra.css">
<!-- include dijit css -->
<link href=".../MyFirstMapDijit.css">
<!-- specify dojo configuration -->
<script ...>djConfig = { ... }</script>
<!-- reference ArcGIS JavaScript API -->
<script ...></script>
<!-- reference newly created dijit -->
<script ...></script>
</head>
<body class="tundra">
<!-- create markup -->
<div dojoType="mydijits.MyFirstMapDijit" ...></div>
</body>
Wrapup
You’ve just put together your first mapping dijit using the ArcGIS JavaScript API. In subsequent posts, we’ll show how to add other dijits, that analyze data on the map and others which encapsulate data and behavior that you can easily add to a website.
Download the example from the Code Gallery
Related links
- ArcGIS JavaScript API
- Dojo
- Dojo book: Writing Your Own Widget Class
- The Mojo of Dojo (Creating Your Own Widgets)
- Dissecting Dijit
Contributed by Jayant Sai of the ArcGIS JavaScript API development team.
Creating a DHTML scale bar with the .NET Web ADF
At the 9.3 release, the .Net Web ADF’s JavaScript library exposes a lot of logic to the client side, allowing you to create a more responsive UI without the need for making calls back to the server. You can get the Web ADF JavaScript library help on the ArcGIS Server Resource Center. This post will show you how to use the JavaScript library to create a pure client-side scale bar using the Microsoft AJAX Client Library patterns.
The Web ADF’s scale bar is generated by the primary map resource using a dynamically generated image. Since the scale potentially can change on every pan, the scale bar image has to be updated frequently, adding additional overhead to the server requests for rendering and fetching these images. Furthermore, if the primary map resource doesn’t support rendering a scale bar, no scale bar is available at all. ArcIMS ArcMap Services don’t support rendering a scale bar. The approach described in this post is the recommended pattern for displaying a scale bar for ArcIMS ArcMap Services.
We can scale a standard <div> box dynamically on the client using JavaScript, and completely eliminate the extra callback, because the map control allows you to listen for and get the current extent of the map. We simply add a handler to the Map’s ‘extentChanged’ event. To do this, we first get a reference to the map object using the $find method parsing in the ClientID of the map as a parameter:
var map = $find('Map1');
Next we add the handler which will be executed every time the extent of the map has changed:
map.add_extentChanged(myExtentChangedHandler);
However, we need to ensure that this handler is not created until the Map has been instantiated on the client. The Microsoft AJAX framework also exposes several life-cycle events, for listening when the page has been fully loaded. So we wrap the above code in an application init event handler and place it right before the </body> tag. Notice how the pattern for adding event handlers is similar to adding handlers to the map. The full example could look something like this:
<script type="text/javascript" language="javascript" >
function myExtentChangedHandler(sender, args) {
alert(sender.get_id() + ' changed extent to: ' + args.current.toString());
}
Sys.Application.add_init(function() {
var map = $find('Map1');
map.add_extentChanged(myExtentChangedHandler);
});
</script>
Every time you pan the map, you will see a popup window like this:

This gives us the framework for creating a simple scale bar. The next step is to place a box on the page that we can use as a scale bar by changing the width as the pixel size changes.
<div><div id="scalebar" style="background-color: #000000; width: 200px; height: 10px;"></div><span id="scalebarText">100 units</span></div>
<script type="text/javascript" language="javascript" >
function resizeScalebar(sender, args) { //resize event handler
var pixelSize = sender.get_pixelSize(); //Gets the size on one pixel in map units
var scalebarWidthInMapUnits = 0.001; //The initial size of the scalebar in map units
//width in pixels of a scalebar with the current
//scalebarWidthInMapUnits value and map's pixelsize
var width = scalebarWidthInMapUnits / pixelSize;
while(width<20) {
//keep increasing scalebar size until we have a reasonable and visible size
scalebarWidthInMapUnits *= 10;
width = scalebarWidthInMapUnits / pixelSize;
}
$get('scalebar').style.width = width + 'px';
$get('scalebarText').innerHTML = scalebarWidthInMapUnits + ' units';
}
//Hook up the handlers during init
Sys.Application.add_init(function() {
var map = $find('Map1');
map.add_extentChanged(resizeScalebar); //fired when extent has changed
map.add_extentChanging(resizeScalebar); //fired while map is zooming/panning
resizeScalebar(map,null); //Force initial update of scalebar
});
</script>
This will generate a very simple scale bar that looks something like this:
![]()
It will automatically adjust its width between 20 and 200 px and show the corresponding width in map units next to it.
The next step is to componentize this into a real client side control that can easily be reused. The Microsoft AJAX Client Library already has a framework in place for creating controls that can inherit from each other and be extended.
A component requires a constructor, and a prototype. In the constructor you define the default properties of the control, and in the prototype you define the properties and methods, including initialize and dispose. Lastly you register the control and optionally the type you derive from, in this case Sys.UI.Control.
Type.registerNamespace('ADF.Samples');
ADF.Samples.DhtmlScaleBar = function(element) {
ADF.Samples.DhtmlScaleBar.initializeBase(this, [element]);
this._map = null; //Reference to the map
this._minWidth = 20; //minimum width of the bar before changing units
}
ADF.Samples.DhtmlScaleBar.prototype = {
initialize : function () {
ADF.Samples.DhtmlScaleBar.callBaseMethod(this, 'initialize'); //Call base initialize
if(this._map === null) { throw Error.argumentNull('map'); }
this._extentChangedHandler = Function.createDelegate(this,this._updateScalebar);
//Add listener for when the map is animating its extent
this._map.add_extentChanging(this._extentChangedHandler);
//Add listener for when the map has changed its extent
this._map.add_extentChanged(this._extentChangedHandler);
this._createBars(); // Creates the bar and text elements
this._updateScalebar(this._map); //Update the scalebar now
},
dispose : function() {
ADF.Samples.DhtmlScaleBar.callBaseMethod(this, 'dispose');
if(this._extentChangedHandler && this._map) {
this._map.remove_extentChanging(this._extentChangedHandler);
this._map.remove_extentChanged(this._extentChangedHandler);
}
if(this._scaleBar) { this.get_element().removeNode(this._scaleBar);}
if(this._scaleBarText) { this.get_element().removeNode(this._scaleBarText); }
this._extentChangedHandler = null;
this._map = null;
this._scaleBar = null;
this._scaleBarText = null;
},
_createBars : function() { //Create the bar and text
this._scaleBar = document.createElement('div');
this._scaleBar.style.backgroundColor = '#000000';
this._scaleBar.style.float = 'left';
this.get_element().appendChild(this._scaleBar);
this._scaleBarText = document.createElement('span');
this._scaleBarText.style.float = 'left';
this.get_element().appendChild(this._scaleBarText);
},
_updateScalebar : function(sender,args) {
var pixelSize = sender.get_pixelSize(); //Gets the size of one pixel in map units
var scalebarWidthInMapUnits = 0.001; //The initial size of the scalebar in map units
//width in pixels of a scalebar with the current
//scalebarWidthInMapUnits value and map's pixelsize
var width = scalebarWidthInMapUnits / pixelSize;
while(width<this._minWidth) {
//keep increasing scalebar size until we have a reasonable and visible size
scalebarWidthInMapUnits *= 10;
width = scalebarWidthInMapUnits / pixelSize;
}
this._scaleBar.style.width = width + 'px';
this._scaleBarText.innerHTML = scalebarWidthInMapUnits + ' units';
},
//Properties:
get_map : function() { return this._map; },
set_map : function(value) { this._map = value; },
get_minWidth : function() { return this._minWidth; },
set_minWidth : function(value) { this._minWidth = value; }
}
//Register class:
ADF.Samples.DhtmlScaleBar.registerClass('ADF.Samples.DhtmlScaleBar', Sys.UI.Control);
If we add this script to the page, we can now simply create a scale bar using the $create method. The parameters are:
- Type
- Object list of properties
- Object list of event handlers (we don’t have any events here so we use null)
- Object list of component properties. In our case the map – this ensures that the scale bar is not initialized until the map has been initialized.
Example:
<div id="bar"></div>
<script type="text/javascript" language="javascript" >
Sys.Application.add_init(function() {
$create(ADF.Samples.DhtmlScaleBar,{"minWidth":20},null,{"map":"Map1"},$get('bar'));
});
</script>
At our code gallery you can download the scale bar control. It has been expanded to look a little better than just a black bar, and it also has a server-side web control that renders the above script to the page. It will analyze the primary map resource and fetch the unit of the map, and allow you to convert it to any display unit you would like on the fly. Finally, there’s some extra logic which will get the scale bar to attempt to use some nice rounded intervals. The final result will look something like below, and will even resize while the zoom animation plays or while you pan toward the poles where the scale changes. You can style the control using the web control style properties like background color, border, font-size etc.
![]()
Click here to get the source code from the Code Gallery
Click here to view a demo of the scale bar
Contributed by Morten Nielsen of the ArcGIS Server .NET software development team
Using Dojo dijits with the ArcGIS JavaScript API
A nice thing about the ArcGIS JavaScript API being built on top of the Dojo toolkit is that you can use Dojo widgets, or “dijits”, to add prepackaged user interface components to your applications. Dojo has a bunch of existing dijits you can choose from such as text boxes, buttons, menus, calendars, color pickers, and so on. The online Book of Dojo has a nice overview of the Dijit library that you can use to browse the dijits.
Dijits have been tested to behave consistently in different browsers and comply with accessibility and localization requirements. The dijit framework is extensible, so with a little ambition you can even create your own dijits.
How would you use dijits in an ArcGIS JavaScript API application?
Your Web GIS applications may require the user to interact with the page outside of the map. For example, you might need users to enter some text, click a button, choose a value from a slider, or select an item from a dropdown list. Dijits give you a robust way to provide this functionality without writing the code yourself.
You can also combine several dijits into one for easy re-use. Suppose your company has multiple Web designers that want to embed maps in their pages. You can wrap up a map and some other elements inside a dijit, which the Web designers can then add to their pages without having to learn how to use the ArcGIS JavaScript API.
In the image below, the map, slider, buttons, and city seal have been combined into a dijit that a Web designer could add to the page with a line of code. The slider and the buttons themselves are individual dijits included in the larger dijit.
Dijits can also help users accomplish focused workflows, such as finding nearby dentists, selecting a site for a business, or generating a route. In this way, dijits are similar to “tasks” in the Web ADF.
In the coming weeks we’ll be posting more about how to create dijits that use the ArcGIS JavaScript API.
Contributed by Sterling Quinn of the ArcGIS Server software development team
The Mobile Web
A lot of people have asked us when we will add support for the iPhone, Blackberry and what about Android? Imagine the reaction we receive when we the answer is – we already do! Well, sort of. To explain, lets first discuss the target user of ArcGIS Mobile and then discuss how the Mobile Web fits into the picture…
Enterprise Field Worker
ArcGIS Mobile is designed and engineered to fit the needs and workflows of the enterprise field worker. Viewing and navigating to locations, collecting new spatial and tabular data, and locating/updating existing assets in the field are all common tasks for the enterprise field worker. They demand highly focused, workflow driven applications that are fully functional whether you are connected in the field or not. Where do you find the enterprise field worker? He/she inspects their city infrastructure, performs state or county surveys, responds to incidents when something bad happens, and much more. They leverage the corporate investment in GIS to manage their infrastructure in the field.
The Mobile Consumer
Those local and state agencies that are moving to ArcGIS Server and deploying mobile GIS to their field operations using ArcGIS Mobile are not the only field workforce that consumes corporate spatial data – citizens within a local government, tax payers within a county are as well. The mobile consumer wants to discover corporate information that is managed by their state or local government. For example, why can’t I see all of the recycling centers in my city using my iPhone or Blackberry? How about public transportation routes and schedules?
So how can a local government support so many different devices…
ArcGIS Server and Mobile Web Browsers
Mobile browsers come in a variety of flavors. They range from browsers that support basic or partial HTML rendering to those which support full HTML, JavaScript & CSS. Leading the pack right now is the iPhone Safari with support for all the above plus SVG graphics with JavaScript binding and an on device database. Several other mobile device manufacturers also integrate full fledged browsers, including Opera Mobile/Mini, Mobile Explorer, Blackberry Browser, etc. (A comprehensive list can be found at http://en.wikipedia.org/wiki/Microbrowser).
At the 9.3 release, ArcGIS Server includes REST access to mapping and other geospatial services. These services can be easily accessed through simple HTTP calls, which can be made through any server side scripting language such as Php, Perl, Ruby, Python, etc or languages such as Java & C# or within client applications through JavaScript or FLEX/ActionScript.
Simple Web Mapping
With the rest of this blog posting, we will explain how you can use the new ArcGIS Server REST API to add a map into an HTML page and allow basic map navigation using links on the page and serve your consumers with your corporate data. We will use one of the ArcGIS Online map services as the map to display.The following is the PHP code for building this simple mobile web mapping application.
- Determine what map to show to the end user. In this case, we will use a map that has aerial imagery (http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer)
- Determine the size of the map image to be requested, based on the browser’s USER-AGENT.
$userAgent = $_SERVER["HTTP_USER_AGENT"];if (strstr($userAgent, “iPhone”)) {
…
}else if (…) {
…
}else {
echo $userAgent;
}
- Determine whether there is an extent already passed to it in the url query or initialize the map to a pre-defined extent.
$bbox = $ _ GET["bbox"];
if ($bbox == “”) {
$bbox = “…”;
}$bbox = explode(“,”, $bbox);
$left = (double) $bbox[0];
…
- Create image request to ArcGIS Server REST, passing size, format and extent information in the image url
“<img src=”http://server.arcgisonline.com/…/export?f=image&format=jpg&bbox=” . $left . “,” . $bottom . “,” . $right . “,” . $top . “&” . $size . “” width=”" . $imgWidth . “” height=”" . $imgHeight . “” />”;
- Calculate extents and create links based on navigation operations; zoom in/out and pan north/east/south/west. These links call the page itself and pass the calculated extent.
“<a href=”" . $base . “?” . “bbox=” . expand($left, $bottom, $right, $top, $width, $height, 0.5) . “”>+</a> | “;
“<a …>-</a> || “;
…
“<a href=”" . $base . “?” . “bbox=” . offset($left, $bottom, $right, $top, $width, $height, 0, $panFactor) . “”>N</a> | “;
“<a …>E</a> | “;
“<a …>S</a> | “;
“<a …>W</a> | “;
…
The following are screenshots of this simple mapping application running on different device emulators:
iPhone 2.1
Blackberry Curve (8320)
Android (v1)
This blog post is the first in a series of blog entries that will be published on how you can leverage the Mobile Web. Thanks go to Jayant Sai (lead developer of the Javascript API) for contributing this article.
Mobile Team
ArcGIS Server 9.3 Nationwide Seminar Series occurring now
ESRI has been working on two, half-day
ArcGIS Server 9.3 Seminars. These seminars started September 23rd and
are taking place through November within the U.S. This is a great opportunity
to see how to implement ArcGIS Server to its fullest capabilities.
The first seminar, which takes place during the morning, is “Tips and Tricks”.
It was derived by gathering the most common questions people have when
implementing ArcGIS Server and best practices. There are three main sections:
configuration and management, caching, and geoprocessing. This seminar provides
useful tips for configuring ArcGIS Server and understanding architecture, how
you can set up caching strategies and workflows for high performing web
applications and how to author and publish geoprocessing services for advanced
analysis over the web.
The second seminar, which takes place during the afternoon, is titled “Creating
Mashups Using the ArcGIS API for JavaScript”. The ArcGIS Server API for
JavaScript is new at 9.3 and provides html and JavaScript developers a quick
path for making great web mapping applications. This seminar covers the basics
and getting started with the API for JavaScript. In addition to creating
mashups, discussion on query tasks, geoprocessing, geocoding and other topics
are covered so you can see how GIS analysis can be done over this easy to use
API. You can take a quick glance of the demos that will be discussed by
downloading the sample code from the ArcGIS JavaScript API
Code Gallery.
Both seminars provide a great resource for maximizing the potential of ArcGIS
Server. The seminars also provide workbooks to attendees so they can revisit
the useful tips back in the office. Sign up online to attend an
ArcGIS Server 9.3 Seminar.
The ESRI technical staff hope to see you at a seminar in a city near you!
Contributed by Jeremiah Lindemann, co-designer of the “Creating Mashups Using the
ArcGIS API for JavaScript” seminar.
Video explains "Parcel Notification List" JavaScript example
Currently the most popular download on the
ArcGIS JavaScript API Code Gallery is the
Parcel Notification List application written and submitted by Jeff
Archer from ESRI. In
this video Jeff takes a few minutes to show how the sample works and
gives a quick run-through of the code and components under the hood.
While local governments may be able use the application “as-is”, there is enough
starter material for any Web application that needs to select features based on
a distance from other features and return tabular attributes of the results.
Download it, use it, modify it… it’s up to you. And please leave comments on
the download page if you have any questions or suggestions you think might help.
Contributed by Jim Barry of the EDN team.
How to get IntelliSense with the .NET Web ADF JavaScript Library
In the 9.3 release of the
.NET Web ADF JavaScript Library (not to be confused with the ArcGIS
JavaScript API) we extensively used
JavaScript code summaries not only to automate creation of API
documentation, but also to provide developers with the new JScript IntelliSense
feature in Visual Studio 2008. However a bug in Visual Studio prevented us from
fully exposing this. The good news is that
Service Pack 1 for VS2008 is out which fixes the problem.
To take advantage of the Jscript IntelliSense feature:
-
Install VS2008
SP1. - Open your Web mapping application in VS2008 and add a new JScript file.
-
At the very top of the file add the following line:
/// <reference assembly="ESRI.ArcGIS.ADF.Web.UI.WebControls" name="ESRI.ArcGIS.ADF.Web.UI.WebControls.Runtime.JavaScript.references.js"/>
-
Wait a few seconds for the JScript IntelliSense to update (keep an eye on the
status bar). You can also force it by hitting CTRL+Shift+J. -
Type “ESRI.” and see the IntelliSense dropdown do its magic.

The idea is that the reference tag tells Visual Studio to also include
IntelliSense from the JavaScript file embedded within the Web control assembly.
This “reference” file will automatically reference all other JavaScript files
in the Web ADF.
Note that the reference tag does not work inside an ASP.NET page, but only in
dedicated JavaScript files. In Web pages you only get IntelliSense on
JavaScript files that are specifically included into the page either using a
<script src=…> tag or referenced with the ScriptManager. JavaScript
files emitted by Web controls like the Web ADF controls are not processed for
IntelliSense. This is a known limitation in Visual Studio.
Below are a couple of screenshots of what the IntelliSense looks like in Visual Studio.
Instantiating a new object:

Accessing properties on an object:

Objects returned from methods that specify a specific return type automatically
get IntelliSense too:

There are a few limitations though. Since JavaScript doesn’t have casting, there
is no way to tell Visual Studio the type of an object, so methods that return
super-class objects don’t give you IntelliSense on methods on the subclass.
An example of this is $find which returns a Sys.Component type. In the
following case it returns the map instance, but we don’t get to see all the
methods of the map. We only see those that are on the base Sys.Component type that
the map inherits from:

If you want to browse the properties, events, and methods using IntelliSense, you
will have to temporarily help Visual Studio by re-constructing the map object,
but remember to delete the constructor before you run it:

Alternatively you can go to the SDK and browse all the objects available to you.
Go here and click “Developing Web applications using the Web ADF” –
“Web ADF JavaScript Library” – “Library Reference” – “API”.
You can also
download the object model diagram as PDF.
Contributed by Morten Nielsen of the ArcGIS Server .NET software development team.
Developing ArcGIS JavaScript API portlets with NetBeans
It is quite easy to use the ArcGIS JavaScript API in a portal environment,
although there are some considerations that have to do with portlet development
as opposed to jsp/servlet development. The samples provided in the ArcGIS
JavaScript API Resource Center are not intended to be deployed in a portlet
container but with some minor tweaks we can get any of them up and running.
A Portal page is a single web page that is used to display content collected
from multiple sources. Portlets are individual web applications intended to
display content on a portal page. To the user, a portlet is a single window on
a portal page. To developers, portlets are Java based modules that can be
plugged into a larger portal page. Finally, a portlet application is a
collection of portlet modules that are packaged together for deployment.
Portlets within the same portlet application can share information and context
allowing inter-portlet communication and sharing of resources, property files,
and support classes. Portlets are managed by a portlet container and
consequently they have to be prepared and deployed in a portlet specific manner
according to either vendor or portlet version specifications.
Let’s walk through the steps to create a simple ArcGIS JavaScript API JSR 168
Portlet application. The steps will use NetBeans
6.1 with Portal Pack 2.0 plug-in
installed and we will deploy to GlassFish
server with OpenPortal Portlet
Container installed. Portal Pack is a set of plug-ins for NetBeans IDE which provide portlet development and deployment support. Open Portal Portlet container is an enterprise-class standard Java Portlet Container (Portlet 1.0/2.0).
Create a Portlet Project
-
In NetBeans, select File -> New Project -> Web -> Web Application.

-
Enter the Project Name and location and click Next.

-
Ensure the Portal Server Container is selected and click Next.

-
Under Frameworks, select ‘Portlet Support’ and choose Version 1.0 to build a
JSR 168 portlet project (Version 2.0 is for JSR 286 portlet projects). Check
‘Create Portlet’ and ‘Create Jsps’ and fill in the Package and Portlet Class
Name. Uncheck the Portlet Mode ‘Edit’.
The portlet application is now created with a default portlet class and relevant
jsp files. The portlet configuration file, portlet.xml, is updated with the
portlet we created through the wizard. We will now edit the view mode jsp file
to add a simple
ArcGIS JavaScript API map.
Update source
The new project wizard created the Portlet class and jsps for view and help
modes. Your directory structure should look similar to this:
Open up your view mode jsp file, AgsJsApiPortlet_view.jsp, and delete all
generated content. We will now edit the page to include an ArcGIS JavaScript
simple map sample. Copy and paste the code below into your view mode jsp.
<%@page contentType="text/html; charset=ISO-8859-1"%>
<%@page pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
<div id="esrimap">
<link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/1.1/js/dojo/dijit/themes/tundra/tundra.css">
<script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=1.1"></script>
<script type="text/JavaScript">
dojo.require("esri.map");
function init() {
var map = new esri.Map("<portlet:namespace/>");
map.addLayer(new esri.layers.ArcGISTiledMapServiceLayer("http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer"));
}
dojo.addOnLoad(init);
</script>
<div id="<portlet:namespace/>" class="tundra" style="width:400px; height:300px; border:1px solid #000;"></div>
</div>
The jsp is like any typical jsp with an added
<portlet:defineObjects> tag. The portlet specification mandates the
portlet container to provide an implementation of the portlet tag library. The
portlet tag library enables jsp’s included in portlet projects to have access
to portlet objects. In order to use the tag library we declare it with the
statement:
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
When using the ArcGIS JavaScript API, we typically include at least one style
sheet and required scripts. Our simple map portlet uses the following style
sheet for graphic elements inside our map DIV:
<link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/1.1/js/dojo/dijit/themes/tundra/tundra.css">
And this is a reference to the location of the ArcGIS Server JavaScript API
files:
<script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=1.1"></script>
The next script is where we put our JavaScript code for working with the map.
First we reference a package, initialize a map, and then add an event:
<!-- map package referenced using dojo.require() -->
dojo.require("esri.map");
<!-- initialization function to add a layer to the map -->
function init() {
var map = new esri.Map("<portlet:namespace/>");
map.addLayer(new esri.layers.ArcGISTiledMapServiceLayer("http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer"));
}
<!-- the addOnLoad() event which takes in the init function as a parameter. -->
dojo.addOnLoad(init);
Although we do not need to edit our portlet class file generated by NetBeans,
let’s have a look at the doView() method to inspect what is happening. I added
some comments to help understand the generated code.
public void doView(RenderRequest request,RenderResponse response) throws PortletException,IOException {
// Set the MIME type for the render response
response.setContentType("text/html");
// Invoke the JSP to render and include the response
PortletRequestDispatcher dispatcher =
getPortletContext().getRequestDispatcher("/WEB-INF/jsp/AgsJsApiPortlet_view.jsp");
dispatcher.include(request, response);
}
Deploy and test
To run the portlet, right click on the project and click “Run”. NetBeans will
first deploy the portlet on the portlet container configured with the project.
If deployment is successful, NetBeans will open the configured browser and
display your portlet within the Portlet Container Driver as shown below:
Can I have multiple maps in a single portal page independent of each other?
Yes, in order to have multiple maps in a single portal page, you must make the
same considerations as required in a standard HTML page containing multiple
instances of the same ArcGIS JavaScript API applications. There are two main
requirements to consider, 1. A portal page can only have a single reference to
the ArcGIS JavaScript API from any of the portlets it includes and 2. Use a
unique identifier for each map (the <portlet:namespace/> tag generates a
unique id and is recommended here). Using the example provided above, we could
add another ArcGIS JavaScript Map Portlet with the following code, taking note
of the comments where we remove the ArcGIS JavaScript API reference and ensure
our map has a unique identifier:
<%@page contentType="text/html; charset=ISO-8859-1"%>
<%@page pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>
<div id="esrimap">
<!-- REMOVED JSAPI SCRIPT AND STYLESHEET REFERENCE -->
<script type="text/JavaScript">
dojo.require("esri.map");
function init() {
<!-- UNIQUE IDENTIFIER FOR EACH MAP -->
var map = new esri.Map("<portlet:namespace/>");
map.addLayer(new esri.layers.ArcGISTiledMapServiceLayer("http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer"));
}
dojo.addOnLoad(init);
</script>
<!-- REFERENCE UNIQUE IDENTIFIER FOR EACH MAP -->
<div id="<portlet:namespace/>" class="tundra" style="width:400px; height:300px; border:1px solid #000;"></div>
</div>
Contributed by Dan O’Neill of the ArcGIS Server Java development team.
A quick look at the versatile spatial filters in the ArcGIS JavaScript APIs
Using the Query class geometry property as a spatial filter is one of the most
important and versatile aspects of the ArcGIS JavaScript API and its
extensions for the Google Maps API and Virtual Earth. This functionality lets
you pass a point, line, multi-point line, bounding box, or a polygon to a
QueryTask without having to worry about handling any particular aspects of the
shape. A QueryTask uses the geometry to perform a query operation against a map
service layer resource that has been exposed through an ArcGIS Server REST API
URL. An example of a QueryTask is to return the attributes for all census
blocks that exist inside the geometry with a population greater than 200.
To make this work, all your application needs to do is create a valid shape
either by manually defining its attributes and vertices, or using one of the
built-in drawing tools that comes with the API or extensions. Continuing with
the example mentioned above, you can use a hand-drawn polygon to define a
demographic study area. As soon as the drawing is complete, as detected a the
mouse listener, you can have the code pass the polygon directly to the
QueryTask which then returns the demographic population attributes for the
area.
Below is an JavaScript code excerpt showing how you might use the geometry
property with the extension for the Google Maps API.
function enableDrawing()
{
//create a new polygon and add it to the map
polygon = new GPolygon([], "#DC143C", 2, 1.0, "#00FFFF", 0.5);
map.addOverlay(polygon);
//activate the Google browser drawing functionality
polygon.enableDrawing(options);
//register a listener for "endline" event
GEvent.addListener(polygon, "endline", runQueryTask);
}
function runQueryTask()
{
//Assign the polygon geometry to the queryGeometry property.
//And, define what attribute fields to return in the FeatureSet
query.queryGeometry = polygon;
query.returnGeometry = true;
query.where = “POP2000>200”;
query.outFields = ['POP2000','HOUSEHOLDS','BLOCK'];
//execute the Query Task and then display the results
qtask.execute(query,false,displayStats);
esri.arcgis.gmaps.Config.proxyUrl = "proxy.ashx";
}
The online help
provides a more detailed discussion on how to use Query and QueryTask with the
JavaScript APIs. Or, go here
to see a short (4 min.) video demo.
Contributed by Andy Gup, Technology Lead for the ESRI Developer Network (EDN).



