Mastering ArcGIS Server Development With JavaScript - Sample Chapter
Mastering ArcGIS Server Development With JavaScript - Sample Chapter
E x p e r i e n c e
D i s t i l l e d
"Community
Experience
Distilled"
C o m m u n i t y
Ken Doman
Mastering ArcGIS
Server Development
with JavaScript
Ken Doman
In his first GIS job, he was given a stack of maps, some AutoCAD data, and a shoe
box full of address notes and was told to make a web-accessible GIS application out
of them. Since then, he has strived to make geographic data available and easily
accessible over the Internet. He is an ESRI certified web application developer and
has created many public web applications using ArcGIS software.
Currently, Ken works for Bruce Harris & Associates, Inc., a mapping and custom
development company that specializes in land records and ESRI software solutions.
There, he creates custom web, desktop, and mobile applications using JavaScript,
.NET, and ArcGIS software.
He has also been a book reviewer for Building Web and Mobile ArcGIS Server
Applications with JavaScript, Packt Publishing by Eric Pimpler and ArcGIS for
Desktop Cookbook, Packt Publishing by Daniela Cristiana Docan. You can learn
more about Ken at http://raykendo.com.
Preface
In this digital age, we expect maps to be available wherever we are. We search
for driving directions on our phone. We look for business locations and nearby
restaurants using apps. Maintenance personnel use digital maps to locate assets
several feet underground. Government officials and C-level executives need
up-to-date location data to make important decisions that affect many lives.
ESRI has been an industry leader for 30 years in the realm of digital mapping.
Through products such as ArcGIS Server, they empower companies, government
agencies, and digital cartographers to publish maps and geographic data on the
Web. Websites and applications written with the ArcGIS API for JavaScript make
those maps available on both desktop and mobile browsers. The API also provides
the building blocks needed to create powerful applications for data presentation,
collection, and analysis.
While there are plenty of examples, blog posts, and books to get you started in
developing apps with the ArcGIS API for JavaScript, they don't often go that
deep. They don't discuss the pitfalls, limitations, and best practices for developing
applications with their tools. That next step is what this book tries to accomplish.
Preface
Chapter 3, The Dojo Widget System, explores the Dojo framework, the comprehensive
JavaScript framework the ArcGIS API for JavaScript is built in. This chapter explores
the inner workings of Asynchronous Module Design (AMD) and how to build
custom widgets for our mapping applications.
Chapter 4, Finding Peace in REST, examines the ArcGIS REST API, which defines how
ArcGIS Server communicates with the application in the browser.
Chapter 5, Editing Map Data, covers how to edit geographic data stored in ArcGIS
Server. This chapter examines the modules, widgets, and user controls provided
by the ArcGIS JavaScript API.
Chapter 6, Charting Your Progress, looks at how you can convey map feature
information through charts and graphs. The chapter not only discusses charts and
graphs made with the Dojo Framework, but also looks at how to integrate other
charting libraries, such as D3.js and HighCharts.js.
Chapter 7, Plays Well with Others, discusses ways to integrate other popular libraries
into an application written with the ArcGIS API for JavaScript. This chapter also
explores combining the framework with jQuery, Backbone.js, Angular.js,
and Knockout.js.
Chapter 8, Styling Your Map, covers the use of CSS styling in the mapping application.
This chapter examines how the Dojo framework lays out elements, and explores
adding the Bootstrap framework to style the mapping application.
Chapter 9, Mobile Development, looks at the need to develop with mobile in mind and
discusses the pitfalls of attempting to make your app "mobile-friendly". This chapter
implements the dojox/mobile framework, provided by the Dojo framework, as a
way to style elements for mobile use.
Chapter 10, Testing, discusses the need for test-driven and behavior-driven
development. This chapter discusses how to test applications using the Intern
and Jasmine testing frameworks.
Chapter 11, The Future of ArcGIS Development, looks at new mapping and application
services such as ArcGIS Online and Web AppBuilder. You will learn how to develop
an application around an ArcGIS Online webmap.
Look at the data editing capabilities ArcGIS Server provides with the ArcGIS
JavaScript API
Learn about the editing controls in the API, and how they create a helpful
editing experience
Create an editing application that uses the tools in the ArcGIS JavaScript API
[ 121 ]
Feature services
A feature service provides a web interface between data stored on the server and
an application on the browser created to use it. They can be accessed through URL
endpoints similar to map services. However, they produce very different results.
They can be loaded on a map and queried much like dynamic or tiled services, but
there is more. Feature services return graphics instead of tiles. These graphics can be
queried, and even edited, if the service allows.
[ 122 ]
Chapter 5
Feature templates
With ArcGIS Server 10.1, feature services can be published with the added
functionality of feature templates. Feature templates give the user preconfigured
features to add to the map. Feature templates are created in ArcMap, and define
the symbology and predefined attributes. These templates make it easier to edit
service data.
One example of Feature templates can be found on an animal sighting map. The
points on the map designate where animal sightings take place. Feature templates
could be created to show pictures of each major type of animal (cat, dog, bird, rabbit,
deer, and so on). Values in some of the fields could be defined ahead of time. For
instance, you could say that all cats are warm-blooded.
How do you, as the developer, take advantage of feature templates? Apart from
demonstrating what each symbol means, there are template pickers in the ArcGIS
JavaScript API's tools that not only show the feature templates, but also let you click
on them and add them to your map.
Feature layer
The feature layer provides access to graphics within a feature class. The user can
thus both query and edit the shapes and attributes of the graphics. We reviewed
their REST service profile in Chapter 4, Finding Peace in REST. We load feature layers
in much the same way we load dynamic and tiled services. However, their options
often require more parameters, due to the editable nature of the content.
Snapshot mode
Sometimes, if there is not a lot of data, it's better to download it all at once. That's
what snapshot mode does. Snapshot mode downloads feature data based on time
definitions and definition expressions, but it is limited by the maximum download
limit. The visibility of the data is then determined by time extent.
[ 123 ]
On demand mode
Sometimes, you're only interested in downloading the data in front of you. In that
case, on demand mode is the best option. On demand mode only downloads features
within the map extent. They too are affected by time definitions and definition
expressions. Unlike snapshot mode, data requests are made every time the map
extent changes. On demand mode is the default mode for any FeatureLayer.
On demand mode is typically used when there is a lot of data in the feature layer,
but the user is only expected to view a small portion of it. It's very good for focussed
editing tasks. It's not as good for mobile applications with lots of map navigation and
connectivity issues, since some graphics will fail to load.
Selection mode
Loading features by selection is more constraining because it only shows those
features that have been selected. Feature selection is handled using the feature layer's
selectFeatures() method, in a manner similar to querying from a map service
layer. In this case, the graphics returned are considered "selected". Selection methods
include clicking on the map and sending a query with specific parameters. This
method is very helpful if there are lots of features, and you only want to download
specific ones, whether it's by area or attributes.
Editing tools
The ArcGIS JavaScript API comes with a set of widgets and modules designed
specifically for editing. With the editing widgets, the user can add features to the
map, change their shape, edit their attributes, and even delete them, if the services
allow. Let's look at some of the tools available in the API.
Why are the editing tools in your application not working? It
may be the CSS. Editing widgets are created with Dojo user
controls, or dijits. These controls require the Dojo stylesheets,
such as claro.css or nihilo.css. Without them, buttons
stop working, and other unexpected behaviors may arise.
[ 124 ]
Chapter 5
Edit toolbar
The edit toolbar, loaded with the esri/toolbars/edit module, lets the user change
the shape, orientation, scale, and position of graphics on a map. We discussed it in
Chapter 2, Digging into the API, in relation to the other toolbars. Separate controls are
required to save the changes made with the edit toolbar. You can see an image of a
triangle selected for the edit toolbar here:
The edit toolbar requires a map in its constructor. The constructor also needs a
number of optional parameters to modify its appearance and behavior. Many of
the options depend on the geometry type of the data being manipulated. As of API
version 3.13, here are some of the available options for the edit toolbar:
or polygon.
[ 125 ]
You can see an example of loading the edit toolbar in the following snippet:
require([, "esri/toolbars/edit",
"esri/symbols/SimpleMarkerSymbol",
"esri/symbols/SimpleLineSymbol", ],
function ( , EditToolbar, MarkerSymbol, Linesymbol, ) {
var editTB = new EditToolbar(map, {
allowAddVertices: true,
allowDeleteVertices: true,
ghostLineSymbol: new LineSymbol(),
ghostMarkerSymbol: new MarkerSymbol(),
uniformScaling: false,
vertexSymbol: new MarkerSymbol()
});
});
When you want to use the edit toolbar to edit a feature, you call the activate()
method. The activate() method requires two arguments, and has the option for
a third. Firstly, the method requires a tool, which is made by joining a combination
of the edit toolbar constants with the pipe | symbol. The constants include EDIT_
TEXT, EDIT_VERTICES, MOVE, ROTATE, and SCALE. Secondly, the activate() method
requires a graphic to edit. The final optional argument is an object similar to the one
used to create the edit toolbar. In the following code snippet, we have a graphic that
is added to the map, and a click event is assigned to it that activates the edit toolbar
to edit the graphic when it is double-clicked:
var editTB = new EditToolbar();
map.graphics.add(myGraphic);
dojoOn(myGraphic, "dblclick", function () {
editTB.activate(EditToolbar.EDIT_VERTICES | EditToolbar.MOVE |
EditToolbar.ROTATE | EditToolbar.SCALE, myGraphic);
dojoOn.once(myGraphic, "dblclick", function () {
editTB.deactivate();
});
});
[ 126 ]
Chapter 5
Attribute inspector
Sometimes, you don't care where things are, you just care about the content.
That's where the attribute inspector comes in. The attachment inspector provides
a form with a list of editable fields and the appropriate blanks to edit them. The
attachment inspector is bound to a feature layer, and displays the editable values
for the selected layer. The fields in the attribute inspector respond to the field types
of the attributes. Date fields show a calendar when editing. Fields with coded value
domains show a drop-down list instead of a text blank. Below, you can see an
example of an attribute inspector loaded in the popup, though it could be added
to a separate HTML element.
When initializing an attribute inspector, you need to define how the inspector will
handle the different fields within the graphic attributes. The attribute inspector
constructor accepts an options object, and either an HTML element or an id string
reference to the element. The options object has one parameter called layerInfos,
which accepts an array of layerInfo objects. Each layerInfo object contains one or
more of the following parameters:
[ 127 ]
shows a delete button that lets you delete the selected feature. Setting this to
false removes it.
editable. This doesn't override whether the features are editable server-side.
It's just an extra way to block someone without proper credentials from
editing data they shouldn't.
format (object, optional): An object that lets you edit time when
editing dates. When set, add the following object: {time: true}
label (string, optional): When set, this lets you override the name
tooltip (string, optional): When set, this shows a text tool tip
[ 128 ]
Chapter 5
You can see an example of an attribute inspector being loaded with a single
feature layer here:
var layerInfos = [{
'featureLayer': bananaStandFL,
'showAttachments': false,
'isEditable': true,
'format': {'time': true },
'fieldInfos': [
{'fieldName': 'address', 'isEditable':true, 'tooltip':
'Where is it?', 'label':'Address:'},
{'fieldName': 'time_open', 'isEditable':true,
'tooltip': 'Time the Banana Stand opens.',
'label':'Open:'},
{'fieldName': 'time_closed', 'isEditable':true,
'tooltip': 'Time the Banana Stand closes.',
'label':'Closed:'},
{'fieldName': 'is_money_here', 'isEditable':false,
'label':'Is Money Here:', 'tooltip': 'There\'s money in
the Banana Stand.'}
]
}];
var attInspector = new AttributeInspector({
layerInfos: layerInfos
}, "edit-attributes-here");
attInspector.startup();
While the attribute inspector allows you to edit the attributes of graphics on a map,
it doesn't provide an immediate way to save the edits. It is up to the developer to
determine when changes to attributes are saved to the server. The developer could
add a save button, or save whenever the feature is no longer selected.
[ 129 ]
Template picker
The template picker lets the user select from a list of feature templates to add
features to the map. It displays a grid of feature templates from connected feature
layers. These templates include feature names, geometry types, and preset styles.
The user can click on any of the template buttons, and then draw them on the map.
You can load more than one feature layer, and switch between them with ease. You
can see an example in the following screenshot:
The template picker, like most dijits, requires a parameter object and, either an
HTML element or a string reference to the element's id, in order to load. In the
options, the template picker accepts an array of featureLayers. It also accepts the
number of rows or columns it will create. If you don't use featureLayers with
their own feature templates, you can define your own using configured items in the
items array. You can also set the CSS style directly. Finally, you can control whether
tooltips show when you hover over the symbols. In the following snippet, you can
see an example of a template picker initialized:
var widget = new TemplatePicker({
featureLayers: layers,
rows: "auto",
columns: 9,
showTooltip: true,
style: "height: 100%; width: 900px;"
}, "templatePickerDiv");
The preceding code shows a template picker with nine columns with tooltips to
show data about the layers loaded in its featureLayers attribute. The size is
900 pixels wide, and as tall as it needs to be.
[ 130 ]
Chapter 5
Attachment editor
There's an old saying that a picture is worth a thousand words. Sometimes, you need
that picture to explain what data you're submitting. The attachment editor can help.
The attachment editor allows the application to upload a file, usually an image, and
connect it to the feature on the map. You can view other attachments, and possibly
edit them or delete them, if permissions allow. Attachment editors can be loaded
as part of the attribute inspector by setting the showAttachments property in the
attribute editor options to true, when constructing the editor:
Editor dijit
The editor dijit provides an all-in-one editing tool to create, update, and delete map
features. The editor dijit includes the template picker, attribute inspector, and an
editing toolbar with numerous tools. It lets you draw new features on a map, edit
existing features, and also delete features.
The tools that the editor dijit provides are as follows:
Feature selection tools, either to add new selections, add to them further,
or to remove from existing selections
Feature drawing tools, including a tool to delete features from the map
Tools that let you cut, merge, and clip parts of polylines and polygons
[ 131 ]
Snapping manager
Here's a common request you might receive when creating an editing tool: "I'd like
a tool that lets me edit this feature based on the lines of this other feature". You
could try to code your own tool to select a feature and go through each phase of
the feature. Or, with a few additional settings, you could implement the map's
snapping manager.
The snapping manager imitates ArcMap snapping controls in the browser . As
your mouse pointer approaches the corner or edge of a graphic feature, perhaps in
a GraphicsLayer or a FeatureLayer, a new pointer moves over the point on the
feature. This shows where you would add a point if you clicked on the map. You can
click along a set of points, line vertices, or polygon corners to draw something that
lines up perfectly with existing features with this tool.
When loading the snapping manager, there are a few important options that need to
be set. Every snapping manager requires a map to snap to. It also requires a graphics
layer or a feature layer to load, along with information about its snapping behavior.
It should know whether to snap to the edge or vertex of a line or polygon, as well
as whether to snap to points of a point feature class. All this information is added
in a layerInfo array in its constructor options, or can be added later by using the
setLayerInfos() method.
There are other optional configurable items in the snapping manager. You can tell
the snapping manager to always snap to a graphic, or whether you want to control
snapping by holding down a key on the keyboard while clicking. You can also
configure which keyboard key is the snapKey, by loading that property with the
appropriate dojo/keys constant. Finally, the tolerance of a snapping manager
refers to the maximum number of pixels the pointer should be from the feature
before it snaps to it.
You can see an example of a snapping manager loaded in a JavaScript API in the
following code:
require([, "esri/SnappingManager", "dojo/keys", ],
function (, SnappingManager, dojoKeys ) {
var propertyLayer = new FeatureLayer({});
var sm = new SnappingManager({
alwaysSnap: false, // default: false
map: map,
snapKey: dojoKeys.CTRL, // default: dojoKeys.copyKey
tolerance: 10, // default: 15
layerInfo: [{
[ 132 ]
Chapter 5
layer: propertyLayer, // this is a featureLayer,
snapToEdge: false, // default: true
snapToVertex: true //default: true
}]
});
});
The preceding example shows a snapping manager that turns on when the user
holds down the Ctrl key on a PC (the Command key on a Mac). It only snaps to the
corners of a line or polygon in the propertyLayer feature layer. The tolerance for
snapping was set to 10 pixels.
[ 133 ]
Identity manager
The identity manager (esri/IdentityManager) is used to handle logins and
the security of ArcGIS Server and ArcGIS Online services. The identity manager
displays a username and password prompt when you attempt to load tokenprotected services in the browser. Its user interface uses Dojo UI controls,
so loading the appropriate Dojo style sheet is necessary to make the identity
manager work properly.
Now that we've reviewed some of the editing capabilities ArcGIS Server offers,
let's apply what we've learned to an application.
[ 134 ]
Chapter 5
The le setup
We don't need to create any custom packages because we're going to use the
out-of-the-box ArcGIS JavaScript API editing tools,. Instead, we'll create a simple file
setup with a css and a js folder, We'll add our custom style.css style sheet in the
css folder, We'll add our app.js file in the js folder. We'll also add a folder named
proxy to handle our proxy service. The file structure should look something like
the following:
[ 135 ]
We'll add some basic styling for the HTML and the body on the style.css page.
Let's add the following style:
html, body {
width: 100%;
height: 100%;
border: 0;
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: Helvetica, Arial, sans-serif;
}
*, *:before, *:after { box-sizing: inherit;}
[ 136 ]
Chapter 5
We've set the width and height of the HTML and body to 100%, with no border,
margin, or padding. We've also changed the font to a common sans-serif font,
such as Helvetica, Arial, or just plain sans-serif. Finally, we set the elements on
the page to be sized using border-box box-sizing which makes it easier to work
with sizing boxes on the page.
In the preceding code, we've loaded the necessary modules and used the dojo/
parser to parse them. We've added a map with the OpenStreetMap based basemap,
and we've created a maxExtent to simulate the city boundaries.
[ 137 ]
], function (,
FeatureLayer, ArcGISDynamicMapServiceLayer,
MarkerSymbol,
) {
var maxExtent = ,
map, incidentLayer, visibleIncidentLayer;
incidentLayer = new
FeatureLayer("http://sampleserver3.arcgisonline.com/
ArcGIS/rest/services/SanFrancisco/311Incidents/FeatureServer/0",
{
mode: FeatureLayer.MODE_SELECTION,
outFields:
["req_type","req_date","req_time","address","district",
"status"],
id: "incidentLayer"
});
visibleIncidentLayer = new
ArcGISDynamicMapServiceLayer(
"http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/
SanFrancisco/311Incidents/MapServer");
map.addLayers([visibleIncidentLayer, incidentLayer]);
[ 138 ]
Chapter 5
When the map layers are added, we can finally interact with them, both as a user
and as a developer. We'll add an event listener called startEditing() to the map's
layers-add-result event. We'll set up the editing events for the feature layer there.
We'll add a map click event that draws a feature if something has been selected from
the menu on the side of the page. Be sure to add this after the layers are defined, but
before they are added to the map.
var , incidentLayer, visibleIncidentLayer, selected;
visibleIncidentLayer = ;
function startEditing () {
var incidentLayer = map.getLayer("incidentLayer");
// add map click event to create the new editable feature
map.on("click", function(evt) {
// if a feature template has been selected.
if (selected) {
var currentDate = new Date();
var incidentAttributes = {
req_type: selected.template.name,
req_date:(currentDate.getMonth() + 1) + "/" +
currenDate.getDate() + "/" + currentDate.getFullYear(),
req_time: currentDate.toLocaleTimeString(),
address: "",
district: "",
status: 1
};
var incidentGraphic = new Graphic(evt.mapPoint,
selected.symbol, incidentAttributes);
incidentLayer.applyEdits([incidentGraphic],null,null)
}
});
incidentLayer.setSelectionSymbol(
new MarkerSymbol({color:[255,0,0]})
);
map.infoWindow.on("hide", function() {
incidentLayer.clearSelection();
});
}
[ 139 ]
], function (, esriConfig, ) {
[ 140 ]
Chapter 5
function startEditing() {
// add the Locate button
var locator = new LocateButton({map: map}, "locatebutton");
}
});
[ 141 ]
function startEditing () {
var incidentLayer = map.getLayer("incidentLayer");
generateTemplatePicker(incidentLayer);
function generateAttributeInspector(layer) {
var layerInfos = [{
featureLayer: layer,
showAttachments: true,
isEditable: true,
}];
attInspector = new AttributeInspector({
layerInfos: layerInfos
}, domConstruct.create("div", null, document.body));
[ 142 ]
Chapter 5
attInspector.startup();
//add a save button next to the delete button
var saveButton = new Button({ label: "Save", "class":
"saveButton"});
domConstruct.place(saveButton.domNode,
attInspector.deleteBtn.domNode, "after");
saveButton.on("click", function(){
updateFeature.getLayer().applyEdits(
null, [updateFeature], null
);
});
attInspector.on("attribute-change", function(evt) {
//store the updates to apply when the save button is clicked
updateFeature.attributes[evt.fieldName] = evt.fieldValue;
});
attInspector.on("next", function(evt) {
updateFeature = evt.feature;
console.log("Next " + updateFeature.attributes.objectid);
});
attInspector.on("delete", function(evt){
evt.feature.getLayer().applyEdits(
null, null, [updateFeature]
);
map.infoWindow.hide();
});
if (attInspector.domNode) {
map.infoWindow.setContent(attInspector.domNode);
map.infoWindow.resize(350, 240);
}
}
function startEditing () {
var incidentLayer = map.getLayer("incidentLayer");
generateTemplatePicker(incidentLayer);
generateAttributeInspector(incidentLayer);
[ 143 ]
We'll need to add a little positioning style to the save button on the attribute
inspector. We'll add this entry to position the save button in the style.css
sheet so that it doesn't overlap the delete button.
.saveButton {
margin: 0 0 0 48px;
}
Now that the attribute inspector is loaded, we can incorporate it into the click events
for both the map layer and the incident layer. We'll create a showInspector()
function that accepts a map click event. It will query the incidentLayer for any
features in that location, and pull up a map infoWindow with the attribute inspector
inside. It will also assign the selected graphic (if any) to:
function showInspector(evt) {
var selectQuery = new Query(),
point = evt.mapPoint,
mapScale = map.getScale();
selectQuery.geometry = evt.mapPoint;
incidentLayer.selectFeatures(selectQuery,
FeatureLayer.SELECTION_NEW, function (features) {
if (!features.length) {
map.infoWindow.hide();
return;
}
updateFeature = features[0];
map.infoWindow.setTitle(updateFeature.getLayer().name);
map.infoWindow.show(evt.screenPoint,
map.getInfoWindowAnchor(evt.screenPoint));
});
}
function startEditing() {
if (selected) {
incidentLayer.applyEdits([incidentGraphic],null,null)
.then(function () {
[ 144 ]
Chapter 5
showInspector(evt);
});
} else {
showInspector(evt);
}
});
incidentLayer.on("click", showInspector);
[ 145 ]
Speaking of working with extents, we could also lock the selection buttons when
navigating outside the city area. This would alert the user that we aren't accepting
complaints outside the city proper. Of course, we should notify the user why they
are locked out.
We'll start by adding blocking content and notifications in the HTML. We'll add two
divs to the page, a <div> with the id outsidemessage in the map, and a div with
the id blockerdiv next to the editor div. We'll leave the two of them hidden by
default, by adding the inline style display: none. It should look like the following:
[ 146 ]
Chapter 5
data-dojo-props="region:'leading'">
<div id="editordiv"></div>
<div id="blockerdiv" style="display:none;"></div>
</div>
We'll add the following styling to the style.css file to style these items. The outside
message will be gray block floating in the lower middle portion of the map, with text
big enough to read, and with rounded corners (because lots of people like rounded
corners). The blocking div will be positioned directly on top of the template picker
buttons. The blocking div will be light gray, semi-transparent, and cover the entire
template picker when visible.
#blockerdiv {
width: 100%;
background: rgba(188, 188, 188, 0.6);
position: absolute;
top: 0;
left: 0;
bottom: 0;
z-index: 500;
}
#outsidemessage {
position: absolute;
bottom: 40px;
left: 50%;
width: 200px;
height: auto;
margin: 0 0 0 -100px;
background: rgba(255,255,255,0.8);
padding: 8px;
z-index: 500;
border-radius: 8px;
text-align: center;
font-weight: bold;
}
[ 147 ]
We'll add some code to our app.js file to handle the visibility of these two nodes.
We can listen for changes in the map's extent. When the map's extent is outside the
city extent, and they no longer intersect, both the message div and the blocker div
will be made visible (display: block;). If the user can see some of the extent of the
viewing area, the div objects will be hidden again (display: none;). It should look
like this:
require([, "dojo/dom-style",
], function (, domStyle, ) {
function onMapExtentChange (response) {
if (!response.extent.intersects(maxExtent)) {
// show these blocks if the map extent is outside the
// city extent
domStyle.set("blockerdiv", "display", "block");
domStyle.set("outsidemessage", "display", "block");
} else {
// hide these blocks if the max Extent is visible within
// the view.
domStyle.set("blockerdiv", "display", "none");
domStyle.set("outsidemessage", "display", "none");
}
}
map.on("extent-change", onMapExtentChange);
We'll also add an event handler to the outside message div that lets the user click to
go back to the starting location for the map. We'll load the dojo/on event to handle
the click event:
require([, "dojo/dom", "dojo/on",
], function (, dojoDom, dojoOn, ) {
});
Now, when we load our application and pan our way outside the city limits,
the following message should appear:
[ 148 ]
Chapter 5
[ 149 ]
These are a few of the simple things we can do to help secure our application
against unwanted results, and yet still make the application user-friendly to the
general public.
Summary
In this chapter, we've examined the tools and processes that ArcGIS Server and the
ArcGIS API for JavaScript provide to make web editing possible. We looked at what
goes into an editable feature service. We also looked into the various widgets that
come with the ArcGIS JavaScript API for adding new features, editing geometries,
and editing property attributes. We finished by creating an application that uses the
editing tools to create an incident reporting application, with which users can report
problems in the city on the map.
In the next chapter, we'll take the existing data and add a graphical twist.
[ 150 ]
www.PacktPub.com
Stay Connected: