Welcome to ESRI Blogs

Find graphics under a mouse click with the ArcGIS API for JavaScript

Dojo filter exampleMapping applications built with the ArcGIS API for JavaScript commonly allow users to click or hover over a map and get information about all the features under the current mouse location. To add this functionality to your application you can listen for the graphics layer's onClick event, however if graphics are stacked on top of each other, only the top one fires an event. So how do you determine how many graphics are under the point?

One approach is to do the following:

  1. Listen for a click event, perhaps onMouseDown or onClick.
  2. Define a search radius by constructing a new extent around the input point.
  3. Use dojo.Filter to create a new array that contains only the features that are within the search radius.

Listen for onClick event

First, we use dojo.connect to listen for the onClick event. The code snippet below connects an event handler to the map's graphics layer that fires whenever a user clicks a graphic.

dojo.connect(map.graphics,"onClick",identifyFeatures);

The event argument provides access to the screen point, map point, and graphic. The map point is the location, in map units, under the mouse cursor. In the handler function identifyFeatures, call a function that builds a search radius around the input mouse location and returns the new extent.We'll examine how to build the pointToExtent function in the next step.

   function identifyFeatures(evt){
var extentGeom = pointToExtent(map,evt.mapPoint,10);
}

Construct an extent around the input point

In this step, we'll construct an extent around the input map point using the following function. This function uses an input point and tolerance to calculate the extent.

function pointToExtent(map, point, toleranceInPixel) {
//calculate map coords represented per pixel
var pixelWidth = map.extent.getWidth() / map.width;
//calculate map coords for tolerance in pixel
var toleraceInMapCoords = toleranceInPixel * pixelWidth;
//calculate & return computed extent
return new esri.geometry.Extent( point.x - toleraceInMapCoords,
point.y - toleraceInMapCoords,
point.x + toleraceInMapCoords,
point.y + toleraceInMapCoords,
map.spatialReference );
}

Filter the graphics collection using dojo.filter and display the results

Dojo.filter takes an input array and a filtering function and returns a new array that contains only the items that met the filter requirement.

Let's look at how to use dojo.Filter to loop through the graphics in our graphics layer and test each graphic against a condition. In this case, we use extent.contains to perform a spatial query to determine which graphics are within the extent. If a graphic is within the extent, the function returns true and the graphic is included in the filteredGraphics output array.

  var filteredGraphics = dojo.filter(map.graphics.graphics, function(graphic) {
return extentGeom.contains(graphic.geometry);
})

Now we have an array that contains only graphics located within the specified tolerance. We can use this array to build a table containing one row for each graphic under the mouse location. In the snippet below, we construct a table, then use dojo.forEach to loop through the filteredGraphics array and add a row that displays the city name and population. Finally we build an info window to display the results.

  var content = "";
content = "<i>Total Features: " + filteredGraphics.length + "<\/i>";
content += "<table><tr><th>City<\/th><th>Population<\/th><\/tr>";

//Build a table containing a row for each feature found
dojo.forEach(filteredGraphics,function(row){
content += ""
+ row.attributes['CITY_NAME'] +
"<\/td><td>" + row.attributes['POP1990'] +
"<\/td><\/tr>";
})
content += "<\/table>";

//display the results in an infow window
map.infoWindow.setContent(content);
map.infoWindow.setTitle("Identify Results");
map.infoWindow.show(evt.screenPoint,map.getInfoWindowAnchor(evt.screenPoint));

Click here to view a live sample that uses dojo.filter to display information about all the graphics under the mouse point.

Contributed by Kelly Hutchins of the ArcGIS API for JavaScript development team.

Posted by Kelly | 0 Comments
Filed under:

Community voting is open for Developer Summit User Presentations

We appreciate the many abstracts that were submitted for the 2010 ESRI Developer Summit User Presentations. The deadline for submission has passed, and now it's up to you to vote on which presentations you'd like to see.

Voting is open now and will end on February 7. You don't have to be registered for the conference in order to vote, because you may still get a chance to experience the presentations through the published conference proceedings. Voting is open to everyone.

Vote here

Posted by sterlingdq | 0 Comments
Filed under:

Synchronizing map and data grid interaction with the ArcGIS API for JavaScript

Highlight row and map graphicSeveral months ago the ArcGIS API for Flex team wrote a post showing how to synchronize map and datagrid interaction. In this post, we'll the take a look at how to accomplish this task using the ArcGIS API for JavaScript.

In a previous post I showed how to display attribute information in a Dojox DataGrid. We'll extend that sample to add the following functionality:

  • Hover over map graphics and highlight the associated row
  • Hover over rows in the table and highlight the associated graphic

Highlighting a row when the user hovers over a graphic

The graphics layer has several mouse events we can use to determine what end users are doing with the application.OnMouseOverfires when the mouse enters a graphic in the graphics layer. We can listen for this event and, when it fires, loop through the rows in the DataGrid until we find the row that matches the input graphic's unique identifier.

Once the row is found we'll use the row's setOverRow method to highlight the associated graphic row. Our DataGrid contains a large set of items, so we'll use scrollToRow to programmatically scroll to the highlighted row.

  dojo.connect(map.graphics,"onMouseOver",function(evt){    
selectionLayer.clear();
//Loop through the rows until you find the row with the ObjectID that matches the graphic
//the selected row
for (var i=0, il=grid.rowCount; i<il; i++){
if((grid.getItem(i)) && grid.getItem(i).ObjectID === evt.graphic.attributes.ObjectID){
grid.rows.setOverRow(i);
grid.scrollToRow(i);
//Add the graphic to the selected graphics layer
var selectedState = new esri.Graphic(evt.graphic.geometry).setAttributes(
evt.graphic.attributes);
selectionLayer.add(selectedState);
break;
}
}
});
If we ran our sample application now, whenever we held the mouse over a graphic, the row in the table would highlight; however, the default highlight symbol isn't very obvious. To make our highlighted rows stand out more, we can listen for the DataGrid's onStyleRow event and modify the row's background color.
  dojo.connect(grid,"onStyleRow",function(row){
if (row.over) {
row.customStyles+='background-color:#FFFF00;';
}
});

Next, we'll listen for the graphics layer's onMouseOut event so we can clear the current selection when the mouse exits the graphic.

  dojo.connect(map.graphics,"onMouseOut",function(evt){
selectionLayer.clear();
grid.rows.setOverRow(-1);
});

Highlighting a graphic when the user hovers over a row

The DataGrid has an event that fires when the mouse hovers over a row. We'll use this event to loop throughthe map's graphics and find the graphic with the unique identifier that matches the input row.
  dojo.connect(grid, "onMouseOverRow", function(evt){
var rowId = grid.getItem(evt.rowIndex).ObjectID;
selectionLayer.clear();
//Loop through the graphics until you find the graphic with the ObjectID that matches
//the selected row.
dojo.some(map.graphics.graphics,function(graphic){
if ((graphic.attributes) && graphic.attributes.ObjectID === rowId) {
//add the graphic to the selected graphics layer
var selectedState = new esri.Graphic(graphic.geometry).setAttributes(
graphic.attributes);
selectionLayer.add(selectedState);
return true;
}
});
});
When the mouse leaves the row, we listen for our final event, onMouseOutRow, and when it fires we'll clearthe selection.
  dojo.connect(grid,"onMouseOutRow",function(){
selectionLayer.clear();
});

View a live sample that synchronizes map graphics and data

Contributed by Kelly Hutchins of the ArcGIS API for JavaScript development team

Posted by Kelly | 2 Comments
Filed under:

Present at the 2010 ESRI Developer Summit. Abstracts due soon!

The User Presentations track of last year’s ESRI Developer Summit was such a success that we’re opening the floor to you again this year with twice as many slots available. We hope you’ll consider sharing any projects or research you’ve done that would be of interest to other ArcGIS developers. The deadline to submit your abstract is January 15, 2010.

Posted by sterlingdq | 0 Comments
Filed under:

ArcGIS Online services now available in Google / Bing tiling scheme

The ArcGIS Online team announced today that the ArcGIS Online map services are now available in the same Mercator-based tiling scheme used by Google Maps and Bing Maps. All future updates to ArcGIS Online will occur on the Mercator services.

The current services (based on the WGS 84 geographic coordinate system) will continue to work without any modifications required to your existing applications; however, these services will eventually be retired.

This tiling scheme change allows you to overlay your data with ArcGIS Online, Bing Maps, and/or Google Maps without having to build more than one map cache. In this previous post, you can read more about how the change may affect you and how to design Web map layers that can overlay the new services.

Posted by sterlingdq | 4 Comments
Filed under: ,

Using Bing Maps with the ArcGIS API for Flex

Good-looking basemaps like Bing Maps (formerly known as Microsoft Virtual Earth) are key to providing your Web users with a pleasant user experience and context for your business information. With the ArcGIS API for Flex you can easily access worldwide high quality imagery and street maps from Bing Maps and display information from your own map services on top of them. Bing Maps is also great for supporting the display of advanced GIS analysis from ArcGIS Server services. In this post we will describe some simple steps to add Bing Maps to a Flash-based Web mapping application created with the ArcGIS API for Flex.

Getting Started

To add Bing Maps to your ArcGIS Flex applications, it is not required to directly work with Bing Web services. The API provides classes to add Bing Maps as basemaps and locate places using the Bing Maps geocoding service. Follow the steps below to get started:

  1. Obtain your Bing Maps user name and password from your ArcGIS Server administrator.
  2. Download and configure the "Get Virtual Earth Token" page that matches your development platform.
  3. Specify the "Get Virtual Earth Token" page, or set "serverToken", to access Bing Maps

For more information on these steps refer to the Getting Started documentation.

Adding Bing Maps

The VETiledLayer class allows you to easily add Bing Maps into your Flex applications. Below are MXML and ActionScript code to add Bing Maps to your application.

MXML to use Bing Maps:
        <esri:Map>
<esri:VETiledLayer
environment="production"
tokenURL=http://myserver:8081/ve/vetoken.jsp
mapStyle="road"
/>
</esri:Map>

ActionScript to use Bing Maps:

             var veTiledLayer:VETiledLayer = new VETiledLayer();
veTiledLayer.tokenURL = "http://myserver:8081/ve/vetoken.jsp";
veTiledLayer.environment = "production";
veTiledLayer.mapStyle = VETiledLayer.MAP_STYLE_ROAD;
myMap.addLayer(veTiledLayer);

Now that you have Bing Maps in your map, you can display other information on top. For example you can add the results of a drive time analysis from an ArcGIS Server geoprocessing service. The code flow for the application will look like below. The complete code is here.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:esri="http://www.esri.com/2008/ags">
<mx:Script>
<![CDATA[
...
private function computeServiceArea(mapPoint:MapPoint):void
{
//invoke ArcGIS geoprocessing service
}
private function mapClickHandler(event:MapMouseEvent):void
{
computeServiceArea(event.mapPoint);
}
]]>
</mx:Script>
...
<esri:Geoprocessor id="gp"
url="http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Network/ESRI_DriveTime_US/GPServer/CreateDriveTimePolygons"/>
<esri:Map id="map" mapClick="mapClickHandler(event)">
<esri:VETiledLayer environment="production" tokenURL="http://[MYSERVER/ve/vetoken.cfm]"/>
<esri:GraphicsLayer id="graphicsLayer" renderer="{uniqueValueRenderer}"/>
</esri:Map>
</mx:Application>
Bing Maps example application 

Note: Make sure when you create a Flex Builder project, you configure it to run from a Web server's virtual directory. If you run the application as a local file, the Bing Maps token handler will not recognize the referrer added in the token handler page.

You should also know that we are migrating all the ArcGIS Online map services to fit the Bing Maps tiling scheme, so you can combine any layer with Bing Maps. Of course, with the code above you also know how to combine Bing Maps with your own ArcGIS Server services!

Geocoding with Bing Maps

The ArcGIS API for Flex exposes Bing Maps geocoding through the VEGeocoder class. Below is a code snippet for using Bing Maps geocoding in your application.

ActionScript to use Bing Maps geocoder:

            var veGeocoder:VEGeocoder = new VEGeocoder();
veGeocoder.environment = "production";
veGeocoder.tokenURL = "http://[MYSERVER/VE/vetoken.jsp]";
var query:String = "380 New York St, CA";
veGeocoder.addressToLocations(query);
veGeocoder.addEventListener(VEGeocoderEvent.ADDRESS_TO_LOCATIONS_COMPLETE,
function (event:VEGeocoderEvent):void{
var veResult:VEGeocodeResult = event.results[0];
myMap.extent = WebMercatorUtil.geographicToWebMercator(veResult.bestView) as Extent;
}
);

Observe from the code above that the ArcGIS API for Flex also has utility methods to convert the coordinates of the geocoding results between the geographic and Web Mercator coordinate systems. The Bing Maps geocoding service always returns the results in geographic coordinates, and you will need to convert them to the appropriate coordinate system of your basemap.

Click on the links below to view live samples that showcase the use of Bing Maps and the Bing Maps geocoding service.

To get more information on using Bing Maps in your Flex applications, see Getting Started with Bing Maps in the ArcGIS API for Flex.

Contributed by Antony Jayaprakash of the ArcGIS API for Flex development team.

Posted by sterlingdq | 1 Comments
Filed under: ,

Zoom to DataGrid records with the ArcGIS API for JavaScript

State DataGrid with zoom buttonRecently we posted how to display attributes in your ArcGIS JavaScript applications using a Dojo DataGrid. In this post we'll extend that sample to add a zoom button to each record of the grid. Each button is a dijit (Dojo's name for widget) that lets users zoom to the U.S. state associated with the record.

Each field in the DataGrid can define a formatter that returns the value to display in the cell. This value can incorporate HTML and JavaScript, which is the key to allowing you to insert dijits into your DataGrid.

To add the zoom buttons, modify the DataGrid in markup to add a new field and define a formatter function that will create the necessary HTML to display a zoom button. Set the unique identifier (ObjectID) as the data field so we can find the associated graphic on the map.

<th field="ObjectID" formatter="makeZoomButton" width="18px">
    <img alt="+" src="zoom.png"/>
  </th>

The makeZoomButton function creates a new button, defines button properties like width, height and a display image and associates a function with the onClick event.

  function makeZoomButton(id){
var zBtn = "<div dojoType='dijit.form.Button'><img src='zoom.png'";
zBtn = zBtn + " width='18' height='18'";
zBtn = zBtn + " onClick=\"zoomRow('"+id+"')\"></div>";
return zBtn;
}

The onClick event calls the zoomRow function which loops through the graphics in the map, finds the graphic that matches the selected row, then zooms.

    function zoomRow(id){
selectionLayer.clear();
dojo.some(map.graphics.graphics,function(graphic){
if (graphic.attributes.ObjectID.toString() === id) {
var selectedState = new esri.Graphic(graphic.geometry).setAttributes(
graphic.attributes);
selectionLayer.add(selectedState);
var stateExtent = selectedState.geometry.getExtent().expand(5.0);
map.setExtent(stateExtent);
return true;
}
});
A few weeks ago we covered using Dojo.forEach, a Dojo implementation of one of the JavaScript array extras. In the snippet above we use another array extra Dojo.some. Dojo.some checks each item in the array and returns true if some of the items return true from the callback function. In this example we use Dojo.some to break from a loop once we find an item that fits our criteria. In this case, our criteria is finding a graphic that matches the selected row in the DataGrid.

Click here to view a live sample that displays attributes in a zoomable DataGrid

Example application with DataGrid zoom 

Contributed by Kelly Hutchins of the ArcGIS JavaScript API development team.

Posted by Kelly | 0 Comments
Filed under: , ,

White paper gives tips for 9.3.1 cached map service performance on Apache HTTP Server

We've just published a new paper that offers some tips for boosting performance and throughput of cached map services with Apache's HTTP Web Server. By now, we all understand that the caching of static ArcGIS Server maps provides the fastest delivery of maps over the Web and to the enterprise. However, there are ways to take your throughput a step further by tuning the Web server for better load balancing and cache handling. The paper also discusses the results of some test scenarios that involved some of these simple tuning steps.

Performance and Throughput Tips for ArcGIS Server 9.3.1 Cached Map Services and the Apache HTTP Server

Contributed by Eric Bader, ESRI Product Manager for Java/Linux/Solaris.

Posted by sterlingdq | 7 Comments
Filed under: , ,

Displaying attributes in a DojoX DataGrid

In this post we'll show how to populate a DojoX DataGrid with attribute information from the results of a query task. DojoX contains extensions to the Dojo toolkit. Many of these extensions are experimental, but the DojoX library also includes more mature extensions like the DataGrid.

Create the grid

Here's an example of a DataGrid created in markup. Note that the markup is a standard HTML table with the addition of a dojoType attribute that is set to "dojox.grid.DataGrid". In this example, we don't want the grid rows to be selectable so let's set the selectionMode to none.

 <table dojotype="dojox.grid.DataGrid" jsid="grid" id="grid"
       selectionMode="none">
     <thead>
      <tr>
       <th field="STATE_NAME" width="100px">State</th>
       <th field="POP2000" width="100%">Population</th>
      </tr>
     </thead>
    </table>

Format the data

In order to display the attributes in a DataGrid, they need to be in a particular format defined by a data store. A data store reads data and formats it as a collection of name/value items. Dojo.data has several specialized data stores for working with different data formats. In this example, we'll use the dojo.data.ItemFileReadStore, a read-only store designed for working with JSON data.

Here's an example of the format for ItemFileReadStore:

{ identifier: identifier field,
label:label field,
Items: [
{field1: value1 ,field2:value2},
{field1: value1, field2:value2}
]
}
Identifier is an optional item and specifies a field in the data source that contains unique values. Label is also optional and defines an attribute that contains a user-friendly name for the item. Items is required and is an array of name/value JavaScript objects that contain the data to display.

Let's look at how to get our query results into the format required by ItemFileReadStore. Our sample application queries a United States Census data service on load. Once the query is finished, it returns a record for each state containing the state name, population and a unique identifier. We need to build an array containing the field name and values for each item in this result collection. One way to do this is to create a new array, then loop through the items and push each value into the array.

 dojo.connect(queryTask,"onComplete",function(featureSet){
//build an array of attributes
var items=[];
for (var i=0, il=featureSet.features.length;i < il;i++){
items.push(featureSet.features[i].attributes);
}
}})

An alternative approach is to use dojo.map to build the name/value array of attributes. Dojo.map is Dojo's implementation of the JavaScript array extra array.map. Dojo.map creates a new array of elements based on the return value from the callback function. We covered another array extra, dojo.forEach, in an earlier post and discussed the benefits of not having to create and maintain a loop counter. The same benefit applies here. In our sample application we'll use the dojo.map approach:

dojo.connect(queryTask,"onComplete",function(featureSet){
var items = dojo.map(featureSet.features,function(feature){
return feature.attributes;
});
})

The attribute array we created in the last step is in the proper format, so let's assign that to the items. The ObjectID field in the data source contains unique values, so we'll specify it as the identifier.

var data = {
identifier:"ObjectID",
items:items};

Populate the grid with attributes

In this step, we create a new ItemFileReadStore and bind the store to the DataGrid. Optionally, you can use setSortIndex to sort the data based on one of the attribute values. To sort a field, use the grid's setSortIndex method and pass in an integer for the sort field and a boolean value that represents the sort direction. The field integer is determined by the order the fields are specified in the HTML markup. In this case the STATE_NAME is the second field, but since it's a 0-based value, you'll specify 1 for the sort index.

  store = new dojo.data.ItemFileReadStore({data:data});
grid.setStore(store);
grid.setSortIndex(1,"true"); //sort on the state name

If you plan on including a DataGrid in your JavaScript project, stay tuned. In an upcoming post, we'll show how to add a zoom button to each row of the DataGrid.

Click here to view a live sample that displays attributes in a DataGrid

Contributed by Kelly Hutchins of the ArcGIS API for JavaScript development team

Posted by Kelly | 2 Comments
Filed under: , ,

ArcGIS Online moving to Google / Bing tiling scheme: What does this mean for you?

Earlier this year ESRI announced that ArcGIS Online services will be migrating to the Mercator-based tiling scheme used by Google Maps and Bing Maps. The ArcGIS Online engineers have been busy caching tiles for months in anticipation of this switch, which is anticipated to occur by the end of this year. This post is about how the change may affect you. At the end of the post we also provide steps on how to make the change for your services.

Why a tiling scheme change?

Since the release of ArcGIS Online three years ago, the 2D services have used the WGS 1984 geographic coordinate system and a 512 x 512 pixel tile size. Google and Bing, in contrast, use a modified Mercator projection and a 256 x 256 tile size. The scale sets used by both tiling schemes are similar, but not equivalent.

Why didn’t ArcGIS Online originally choose to match Google and Bing? Interestingly enough, the first ArcGIS Online services were designed in 3D for viewing in ArcGlobe and ArcGIS Explorer. Without getting into the technical details, it’s enough to say that the coordinate system and scales used in the 2D ArcGIS Online tiling scheme have their roots in the ESRI globe technology for which ArcGIS Online was originally built.

With the broad uptake of the ArcGIS Web APIs, the 2D ArcGIS Online services have become very widely used. Some organizations struggle with choosing either the ArcGIS Online tiling scheme to match their ESRI software stack, or the Google / Bing tiling scheme to match a better-known standard. With a unified tiling scheme for the three services, the decision gets a lot easier.

A few organizations are required to support mashups with both ArcGIS Online and Google Maps or Bing Maps. After the ArcGIS Online tiling scheme change, these organizations will no longer have to maintain two caches.

What does this mean for you?

If you are getting ready to create a very large cache to overlay ArcGIS Online, it may be best to create the cache in the Google / Bing tiling scheme, anticipating the change.

If you are not able to re-create your cache at this time, the old services will remain available for a minimum of six months. They will be offered “as is” and will not receive any further data or cartography updates.

Advantages of switching to the Google / Bing tiling scheme

The biggest advantage of switching to the Google / Bing tiling scheme is standardization. This tiling scheme is well-known and widely used. Whether you love the Mercator projection or hate it, it is now customary in Web maps designed for mass consumption. In the end, simplicity of math (you can fit the world on a square at the smallest scale) determined the way most Internet users expect to see the world.

There are some subtle performance advantages to the Google / Bing tiling scheme. Because the tiles are only 256 x 256 pixels, less tile area falls outside the periphery of the map. This means you have to send less data across the wire. The smaller tiles also enhance the perception of the map loading faster, compared with waiting for the 512 x 512 “chunks” of map to appear.

Challenges associated with the Google / Bing tiling scheme

If you re-create your caches in the Google / Bing tiling scheme, you need to anticipate a few issues. First, because the tiles are 256 x 256, you’ll be creating roughly four times as many tiles as you had previously in your ArcGIS Online cache. The larger number of files in your cache will increase cache copying time. The smaller tile size also means you have to send more files to the client during a map request.

Your cache size on disk will probably also increase. Some of the 256 x 256 tiles can get very small in size if they contain few features; much smaller than the 4K default minimum cluster size on Windows. Some organizations have saved space by storing their caches on disks or partitions formatted with a smaller minimum cluster size, such as 1K. This reduces the discrepancy between “Size” and “Size on disk”.

Finally, the Mercator projection is going to stretch your map vertically, especially if you work with extreme latitudes. Besides affecting the appearance of the map, this distortion may cause you to create many more tiles than you might otherwise expect. At these latitudes, it is critical to target your cache at just the scales and geographies that you need. You may want to enable on-demand caching for the most isolated regions. The distortion introduced by the Mercator projection also means that before you measure a feature such as a user-drawn polygon, you should project the feature into a more locally-tailored coordinate system such as UTM or State Plane.

How do you create a cache to match the Mercator-based ArcGIS Online services?

Here’s the workflow for caching a map to match the Mercator-based ArcGIS Online services:

  1. Open your source map document in ArcMap and set your data frame coordinate system to WGS 1984 Web Mercator. You don’t have to re-project the source data, although this can make caching go faster. Some people even create a one-way replica of their geodatabase in the WGS 1984 Web Mercator coordinate system and use that replica just for caching.
  2. Publish a map service.
  3. Open the Service Properties and click the Caching tab. Choose to draw the map service Using tiles from a cache you will define below.
  4. Click Load tiling scheme from and select Google Maps / Microsoft Virtual Earth. Once the scales load, do not add or remove scales or change the tile size.
  5. Create tiles for just a small area of your map, using a feature class to constrain the caching extent if necessary.
  6. Test your new cache. There are already a few new ArcGIS Online services that use the Google / Bing tiling scheme, such as the World Topographic Map. Build a simple test application with these maps to evaluate how your cache overlays with ArcGIS Online in the Mercator projection. If your data doesn’t align, see the alternate steps below for creating a cache in WGS 1984 Web Mercator (Auxiliary Sphere).
  7. Once everything looks okay, open the caching tools again and create all the tiles for your cache.

Exceptions and Web Mercator (Auxiliary Sphere)

There are a few scenarios where you will have to follow some alternate steps to get your caches to overlay correctly with the Mercator-based ArcGIS Online services. The conditions are:

  • You’re overlaying a cache with ArcGIS Online in the Web ADF OR
  • Your data did not align correctly when building a test cache with the above steps. This is most often because your source data uses a datum other than WGS 1984 or NAD 83

In the above two scenarios, you need to publish your cache using the WGS 1984 Web Mercator (Auxiliary Sphere) coordinate system which is the exact coordinate system used by ArcGIS Online. The Web ADF requires an exact coordinate system match for cache overlays. Also, this coordinate system makes it easier to perform some datum transformations.

  1. Open your source map document in ArcMap and set your data frame coordinate system to WGS 1984 Web Mercator (Auxiliary Sphere). While you are doing this, apply any datum transformations to WGS 1984 that you require.
  2. Follow the steps in ESRI Knowledge Base Article 37329 to create a cache for the service.

Migrating map tiling schemes in the ArcGIS Online Help has more details about the switch and the WGS 1984 Web Mercator (Auxiliary Sphere) coordinate system used above.

Contributed by Sterling Quinn of the ArcGIS Server development team.

Posted by sterlingdq | 10 Comments
Filed under: ,

Looping through graphics using the ArcGIS API for JavaScript

When working with the ArcGIS API for JavaScript you'll often find yourself looping through arrays, like the collection of graphics stored in a graphics layer or the results of a QueryTask. In this post we'll explore two approaches for looping through arrays; using a standard for loop and working with a dojo implementation of one of the JavaScript Array Extras.

For Loop

First lets look at using a for loop to add query task results to a map. The results of QueryTask are returned as an array of Graphic features so we can use a for loop to iterate through the task results and add each graphic to the map.

 dojo.connect(queryTask,"onComplete",function(featureSet){
for(var i=0; i < featureSet.features.length; i++){
map.graphics.add(featureSet.features[i]);
})

We can optimize the code a bit by storing the length of the array in a variable. Then the length of the array doesn't need to be recalculated on each loop. The stored length (il) is just compared to the value of the counter(i).

 for (var i=0; il = featureSet.features.length; i < il; i++){

JavaScript Array Extras

The JavaScript array extras are useful functions for working with arrays and are part of ECMAScript 5th Edition, the next revision of the standards on which JavaScript is based. The revised standard is still under development so not all browsers support this functionality. Thankfully Dojo has implemented similar functions as part of Dojo Core so we can take advantage of one of the array extras, dojo.forEach, to simplify the process of looping through an array of graphics. Dojo.forEach runs a function on each item in the array.

 dojo.connect(queryTask,"onComplete",function(featureSet){
dojo.forEach (featureSet.features, function(feature) {
map.graphics.add(feature);
});
});

Note that we no longer need the counter and array length variable which makes the code easier to read and can help avoid the following problems:

  • Off-by-one errors
  • Overwriting a global variable by forgetting to declare the loop counter as a local variable using the var keyword.
If you do need access to the iterator you can specify an additional argument to the function. This argument provides access to the current position in the array.
 dojo.forEach(featureSet.features,function(feature,index){
//do something with the index here
 }

Links

  • Click here to view a live sample that uses dojo.forEach to add graphics to a map.
  • Information from Dojo on working with array utilities
  • Details on ECMAScript
Contributed by Kelly Hutchins of the ArcGIS JavaScript API development team
Posted by Kelly | 4 Comments
Filed under: , ,

ArcGIS API for Flex: Version 1.3 released today

It’s been just over one year since we released the first version of the ArcGIS API for Flex. Since then we’ve seen an amazing interest in our Flex API. Many users have created great web applications with the API, and the Flex forum is now the most active of all the ArcGIS Server forums.

Today we are pleased to announce the release of ArcGIS API for Flex 1.3. This API release is a minor release but has several useful "goodies".

Here’s a short summary of what’s new in version 1.3:

  • Support for Adobe’s Flex 3.4 SDK. The older versions 3.0 thru 3.3 are still supported.
  • Additional styling options for InfoContainer (used by InfoWindow and InfoSymbol).
  • More miscellaneous API improvements and bug fixes.
  • Well-known ID 102100 (WGS_1984_Web_Mercator_Auxiliary_Sphere) is now a supported projection for Web Mercator-based overlays (including Bing Maps). It is now also used in WebMercatorUtil for projecting coordinates between Geographic and Web Mercator.
  • New and updated samples.

Please read the more complete list of 1.3 API changes in the What's New page in our Resource Center.

Contributed by Bjorn Svensson of the ArcGIS API for Flex development team

Posted by sterlingdq | 0 Comments
Filed under:

Working with info windows in the ArcGIS JavaScript API

An easy way to add interactivity to your ArcGIS JavaScript applications is through info windows that display information in response to a user action. From working with other APIs, you might know info windows as "balloons", "map tips", "callouts", or "popups". The concept is the same: the user clicks or hovers over a location on the map and sees HTML-based information about that particular location.

Basic info window 

How does an info window work in the ArcGIS JavaScript API?

In the ArcGIS JavaScript API, the Map has an InfoWindow that can be shown or hidden in response to events.

Every info window has a title and content. The title is the bold text that appears at the top of the info window. The content is the HTML that appears below. When you work with info windows, you’ll frequently call methods to set the title and content.

The default event when a graphic is clicked is to show an info window. However, in order for this to happen, you need to have defined an InfoTemplate for the graphic. The InfoTemplate specifies the title and content that should be used in any info windows that result from clicking the graphics.

You can use the notation ${<FIELD>} to pull attributes directly into an info template.

var infoTemplate = new esri.InfoTemplate();
infoTemplate.setTitle("${NAME}");
infoTemplate.setContent("<b>2000 Population: </b>${POP2000}<br/>"
+ "<b>2000 Population per Sq. Mi.: </b>${POP00_SQMI}<br/>"
+ "<b>2007 Population: </b>${POP2007}<br/>"
+ "<b>2007 Population per Sq. Mi.: </b>${POP07_SQMI}");

This code would create an info window similar to what you see below.

Info window with attributes 

You can handle a graphics layer’s onClick event yourself to show an info window. This can be useful if you need to use JavaScript in some way to construct what you put in the info window. The following function does some math to calculate the population density when a user clicks the graphics layer. The population density is then reported through an info window using the Map.infoWindow.setTitle() and Map.infoWindow.setContent() methods.

dojo.connect(myGraphicsLayer, "onClick", function(evt) {
var graphicAttributes = evt.graphic.attributes;
var title = graphicAttributes.NAME;
var populationDensity = graphicAttributes.POP2007 / graphicAttributes.SQMI;
var content = "The population density in 2007 is <i>" + populationDensity.toFixed(2); + "</i>.";
map.infoWindow.setTitle(title);
map.infoWindow.setContent(content);
map.infoWindow.show(evt.screenPoint,map.getInfoWindowAnchor(evt.screenPoint));
});

These Map.infoWindow.setTitle() and Map.infoWindow.setContent methods are also handy if you want to show an info window in response to a query or some other action that doesn’t involve a graphic. Here’s a function designed to show an info window with lat/lon coordinates when the user clicks anywhere on the map.

dojo.connect(map, "onClick", addPoint);
function addPoint(evt) {
map.infoWindow.setTitle("Coordinates");
map.infoWindow.setContent("lat/lon : " + evt.mapPoint.y + ", " + evt.mapPoint.x);
map.infoWindow.show(evt.screenPoint,map.getInfoWindowAnchor(evt.screenPoint));
}

What can you do with info windows?

You can put almost anything in an info window because it displays HTML. Images, hyperlinks, tables, dynamically rendered charts, and any other type of element that can be requested or created with HTML can be placed in an info window.

You can take advantage of Dojo libraries to enhance your info windows. This picture shows information organized in a Dojo TabContainer in the info window.

Info window with TabContainer 

Here’s a chart dynamically constructed for an InfoWindow using the Dojo charting library:

Info window with chart 

Just because you can put something in an info window doesn’t always mean that you should. The BorderContainer and other elements in the Dojo layout libraries can help you organize information in sidebars, footers, and accordion containers on your page. (See this post for an introduction to Dojo layouts.) In some scenarios these might be more efficient than an info window.

The application pictured below avoids info windows in favor of a right-hand content pane containing charts and other information. Click the image if you're interested in downloading the code.

Information in an accordion container 

Designing a good info window

Although info windows can display all kinds of content, you should not use info windows as a "dumping ground" for information. A well-designed info window has:

  • A descriptive title – Keep the title short and clear
  • Formatting that is easy on the eyes - A few well-placed spaces, tabs, or line breaks can go a long way toward making the content easy to read.
  • Clear labels for attributes - A non-GIS user looking at your application may not understand raw field names such as "PARCEL_NO". Instead, use clear descriptions or field aliases, such as "Parcel number". Avoid the ${*} shortcut that lists all field/value pairs.
  • Attributes that are important to the end user – Many GIS datasets contain fields that are only of interest to a GIS analyst, not end users. "OBJECTID" is one example of a field that should probably never appear in a public-facing application.
  • A manageable amount of information - Use tabs, sidebars, data grids, or links to other HTML pages if your info windows are getting too crowded and require the user to scroll.

Contributed by Sterling Quinn of the ArcGIS Server development team

Posted by sterlingdq | 4 Comments
Filed under: , ,

Working with TextSymbol in the ArcGIS JavaScript API

This post discusses how you can add text to your map using the ArcGIS JavaScript API. Your map service probably already has some labeling in it, but you may want to add descriptive information about graphics that you add on top of your map through tasks or queries. The ArcGIS JavaScript API does not have a built-in labeling engine with conflict detection and label placement algorithims, but you can use the TextSymbol class to add text at a specific point location on the map.

The TextSymbol class has several properties that you can use to fine-tune the position and content of the text element such as angle, offset, font, and kerning (spacing between the letters).

Use the TextSymbol.setFont() method to specify a font for the text. You can use the Font class to set properties like text size, style and weight.

Creating a text graphic

Let's look at a code snippet that uses several of the Font and TextSymbol properties to create a new TextSymbol and add it to our map as a text graphic. This graphic will denote an unexplored area on our map using an old cartographic phrase "Here be dragons". First, we'll create the Font object and specify the font weight and size.

    
         var font  = new esri.symbol.Font();
         font.setSize("12pt");
         font.setWeight(esri.symbol.Font.WEIGHT_BOLD);       

Now we need to create a new TextSymbol and specify that it should be maroon, set at a 15-degree angle and be aligned to the start of our input point.Next, we use the setFont() method to assign the font we just created to the TextSymbol. Finally, we create a new graphic, assign it the newly created TextSymbol, then add the graphic to the map.

         var textSymbol = new esri.symbol.TextSymbol("Here be dragons");
         textSymbol.setColor( new dojo.Color([128, 0, 0]));
         textSymbol.setAlign(esri.symbol.Font.ALIGN_START);
         textSymbol.setAngle(15);
         
         textSymbol.setFont(font);      
        
         var pt=  new esri.geometry.Point(x,y,map.spatialReference)
         var gra = new esri.Graphic(pt,textSymbol);      
         map.graphics.add(gra);

Simplifying the code

The code above is written in a verbose style to make it easier to examine the values we set for the TextSymbol and Font properties. We can reduce the length of the code snippet by using object constructors and chaining method calls. Let's explore this approach a bit:

  • First, use map.graphics to get access to the map's default graphics layer.
  • The GraphicsLayer has an add method that takes a Graphic object as a parameter, we'll create a new graphic within the method call using the Graphic constructor.
  • Graphics consist of geometry, symbol, attributes and an infoTemplate. In our example, we don't need attributes or an infoTemplate so we'll use the Graphic constructor and provide only a geometry (Point) and symbol (TextSymbol)
  • Let's examine the TextSymbol section a bit more closely. Many of the JavaScript objects, like Graphic and TextSymbol, have setter methods that return the object. Because of this we can chain method calls. In the snippet below, we create a new TextSymbol, define the text in the constructor, then chain setColor, setAlign, setAngle and setFont to reduce the amount of code we have to write.
     map.graphics.add(
            new esri.Graphic(
            new esri.geometry.Point(x,y, map.spatialReference),
            new esri.symbol.TextSymbol("Here be dragons").setColor(
                    new dojo.Color([128,0,0])).setAlign(esri.symbol.Font.ALIGN_START).setAngle(45).setFont(
                    new esri.symbol.Font("12pt").setWeight(esri.symbol.Font.WEIGHT_BOLD))          
            )
        )

One caveat to this approach is that it can make the code more difficult to read; however, with a bit of practice it becomes second nature.

Samples

  • Click here to see a live sample that generates text graphics
  • The Graphic Symbology Code Generator on the Code Gallery generates JavaScript code for symbols and is a great tool to explore various symbol properties.
  • To label polygon graphics, use the GeometryService.labelPoints() method to generate a point inside the polygon. You can then designamte this point as the label position. View the Create points for labeling sample for details on how to use this method.
  • Some text information may be better suited to display in an info window. The Show an info window sample shows how to display text in an info window at a specific location

Notes

There are several browser-specific issues to be aware of when working with fonts and text symbols. These issues are well documented in the dojox.gfx documentation. Some of the more common issues are:

  • The font family property does not work in Internet Explorer 7; Arial is always used.
  • Several browsers including Internet Explorer 7, Firefox and Opera 9 do not support the rotated and decoration properties for text symbols.

Contributed by Kelly Hutchins of the ArcGIS JavaScript API development team.

Posted by sterlingdq | 2 Comments
Filed under: ,

Which ESRI Web mapping API should I choose?

Since the release of ArcGIS Server, ESRI has offered Web application developer frameworks (ADFs) for .Net, and Java. Last year, ESRI also released Web mapping APIs for JavaScript, Flex, and Silverlight, further expanding the choices for developers.

One of the most common questions we’ve received at the ESRI User Conference and other recent seminars is: “Which API should I use?” When presented with this question, I like to respond with some questions of my own.

Which platform are your developers most comfortable with?

The APIs are functionally very similar, and often the most important question is not “What do you want to do?” but rather “Which platform are your developers most comfortable with?” If you’ve been working with the Microsoft stack and your developers are inclined in that direction, .Net and Silverlight look like good choices for you. Using similar logic, if your developers have spent the past 10 years adding custom scripts to your ArcIMS applications, they’ll probably find the JavaScript API to be a nice fit.

Choosing a platform that your developers already know and enjoy can save you ramp-up costs and keep morale high. This is where the variety of APIs offered becomes a benefit instead of a burden.

What’s the experience level of your developers?

Many beginning developers find the JavaScript, Flex, and Silverlight APIs to be easier to learn than the Web ADFs because they have a more basic architecture. These APIs also have online Resource Centers, where you can watch videos, read tutorials, and examine working samples that are designed for beginners. ESRI has made sample ArcGIS Server deployments available so that you can practice with the APIs. In fact, you can get a JavaScript mapping application running on your machine with just Notepad and an Internet connection.

In contrast, some developers like the deep functionality and familiar coding patterns of the .Net and Java ADFs; especially developers who have already worked with a lot of .Net, Java, or ArcObjects in the past.

Are browser plug-ins an option?

The ArcGIS APIs for Flex and Silverlight require browser plug-ins. If your application absolutely cannot require a plug-in, the JavaScript API or one of the ADFs will need to be your choice.

The ArcGIS API for Flex requires the Flash plug-in, which Adobe asserts is present in “99% of Internet-enabled desktops in mature markets”. The Silverlight plug-in has not yet reached the same level of ubiquity, but can be expected to gain ground.

Plug-ins come in different versions, which may also present a hurdle in getting end users to experience your Web site in the way you expect. If you choose to use Flex or Silverlight, it’s wise to consider how flexible your clients are in their ability to upgrade plug-in versions. The ArcGIS API for Flex requires Flash Player 9 or above, or Adobe AIR. The 1.0 release of the ArcGIS API for Silverlight requires Silverlight 2 or above.

Future editions of these APIs may require higher versions of the plug-ins. Also, any functionality that you add that is not native to the ESRI APIs may require higher versions.

Do you want to use an IDE? If so, which one?

When you choose an API, you are also making choices about the environment where you’ll spend your time coding. Flex users are probably going to need Flex Builder. .Net and Silverlight users will be doing work in Visual Studio or Visual Web Developer Express. Expression Blend is another option for Silverlight developers. Java developers can use Eclipse or NetBeans. JavaScript programmers probably have the most choices, including the option to just write code in a text editor.

The pros and cons of these IDEs are beyond the scope of this post. Some IDEs cost money, but the time they save you in designing and debugging applications may help you recuperate the cost. If funds are tight, you may be able to get by without an IDE, especially if you are using JavaScript. Many commercial IDEs offer trial versions or free development versions that can help you decide if you want to make the purchase.

Do you need to edit features over the Web?

The .Net and Java ADFs offer access to fine-grained ArcObjects, which can be used to edit feature geometries. The ADFs contain out-of-the-box tasks (widgets) for basic Web editing operations. If you need to build an application with Web editing right now, one of the ADFs is your most likely option.

Web editing is planned for the JavaScript, Flex, and Silverlight APIs at the release of ArcGIS Server 9.4 in 2010.

Do you need to overlay basemaps from Microsoft or Google?

Your organization may require you to use base data from Microsoft’s Bing Maps (formerly Virtual Earth), or Google Maps in your application. This can affect your decision of API.

  • Bing Maps is supported as a layer in the ArcGIS APIs for JavaScript, Flex, and Silverlight, as well as the .Net ADF. There is also an ArcGIS JavaScript Extension for the Virtual Earth API.
  • Google Maps is available in the ArcGIS JavaScript Extension for the Google Maps API.

Are you more comfortable with established technologies or emerging technologies?

Some organizations approach new technologies with caution, whereas others jump at the chance to develop with the newest thing. Your organization’s attitude toward emerging technologies is important to consider, especially if you’re choosing between something like JavaScript, which has been around “forever”, and Silverlight, which just came on the scene in late 2007. This question is largely a matter of opinion, but can tip the balance in organizations where opinions run strong.

Have you talked with others who have made this decision?

ESRI conferences, forums, user groups, and blogs are a good place to learn from people who may have gone through a similar decision process. In fact, many of you who are reading this post may have additional advice, insight, or opinions on this question to share with others who are making the decision. Have you gone through this process before? Did you make a good choice? Is there anything you would have done differently? Leave a comment here.

Contributed by Sterling Quinn of the ArcGIS Server software development team.

Posted by sterlingdq | 14 Comments
More Posts Next page »