GEOG 863
GIS Mashups for Geospatial Professionals

3.5.3 The JS

PrintPrint

Learn More

At this point, you should familiarize yourself with the syntax of JavaScript (JS). The w3schools site offers a good hands-on JavaScript tutorial that should do the job. Take a couple of hours to work through the topics listed under the JS Tutorial heading and pay particular attention to the following points:

  • Ending statements with a semicolon is optional. (The Esri samples use them.)
  • Note the difference between placing scripts inside the page's head section and its body section.
  • JavaScript is a dynamically typed language; you do not need to specify a data type when declaring a variable.
  • JavaScript variables are case sensitive.
  • Variables can be initialized on the same line that they are declared.
  • Code associated with a conditional statement (if or else statements) or a loop (for or while) must be enclosed in braces.
  • Alert boxes can be used to debug scripts that aren't working properly.
  • JS functions are reusable blocks of code with an optional return value.
  • The backslash (\) can be used to insert special characters in a string (e.g., if you want a string enclosed in double quotes to also contain a double quote).
  • Comments are signaled in JS using two slashes (//).

Now that you've learned a bit about JavaScript, we can examine what’s happening in the main.js file.

AMD

The first thing you should notice is that all of the code is wrapped inside a require() function. This is a result of the fact that Esri’s API is built around a JS toolkit called Dojo. Dojo uses a design pattern called Asynchronous Module Definition (AMD) to load JS resources into memory. By defining their API’s object classes in modules, Esri’s made those classes easier to maintain and re-use. Loading the modules asynchronously (in parallel rather than one at a time) means that apps built on the API will load faster than they would in a non-AMD framework. One of your recurring tasks as an Esri JS developer will be to identify the modules containing the object classes needed by your app.

In the case of the 2D sample, two Esri classes are needed: Map and MapView. These classes are accessed by loading the esri/Map and esri/views/MapView modules, respectively.

The DOM

A third module, called domReady! is also loaded. This module is built into Dojo and is used to specify that none of the code that follows should be executed until the DOM has finished loading. What is the DOM, you might be asking? DOM stands for Document Object Model, which is a tree-like representation of a web page that the browser creates whenever it loads that page. The DOM provides the means for JS developers to manipulate a page’s contents and behavior programmatically. In the case of developing an Esri JS app, the DOM is needed to insert a map or scene onto the page.

Learn More

Once again, the w3schools site offers a good JavaScript HTML DOM tutorial. This short tutorial should only take you 30-60 minutes to complete.

The list of modules at the beginning of the require() function is then followed up by an anonymous callback function. The function is anonymous, in that it has no name. It’s a “callback” function because it’s being used in conjunction with the domReady! module, which tells the browser that it shouldn’t execute the code within the function right away; it should “call back” to it when the DOM is finished loading.

The callback function contains a list of arguments that corresponds to the list of required modules. In the 2D example, only the esri/Map and esri/views/MapView modules are required, so the only arguments to the callback function are Map and MapView. We’ll see other arguments associated with other modules in more complex examples later. Some notes on the callback function arguments:

  • You should not include one to go along with the domReady! plugin.
  • They can be named anything you like, though the accepted practice is to name them the same as their corresponding modules.
  • It is critical that the arguments be listed in the same order as the modules.

Using the API Reference

Earlier in the lesson, we visited the Esri JS API SDK to locate sample code that could be used to create our first apps. Now, let’s have a look at an equally important part of the SDK: the API Reference. The API Reference contains a list of all the API modules down the left side of the page. Each module heading can be expanded to see the classes defined in that module. For example, we’d find the Map class in the esri module and the MapView class in the esri/views module.

Locating the map class in the API Reference

On the right side of the API Reference index page is a list of commonly used classes, generally organized from top to bottom in order of importance. We’ll cover most of these classes over the course of the term.

The first line of JS code in our 2D sample creates an object of the Map class (new Map). We can learn about that class by clicking the Map link on the API Reference index page or by entering Map into the Search API Reference box.

Like the other class description pages in the API Reference, the page for the Map class conveys a lot of useful information:

  • how you’d go about referencing the class in your code’s require() declaration
  • an overview of the class (what it’s used for, a code snippet showing its usage, and links to samples and related classes)
  • the class’s constructors (more on this shortly)
  • the class’s properties (characteristics that uniquely define Map objects)
  • the class’s methods (actions that the Map class is programmed to perform)

The Properties section of the page includes an Overview, listing all of the properties in alphabetical order along with their type (e.g., String, Number, or some object class). The property type is important to know as it tells you what you can expect to get back if you read the property (or conversely, what you need to supply if you’re setting the property). After the Overview, you’ll find a section of Details, providing more specifics on the class’s properties. For example, the details on the basemap property provide a list of acceptable values, along with a thumbnail of each.

The Methods section likewise includes both an Overview and Details section. Method parameters (pieces of information the method uses in performing its action) are listed in parentheses after the name in the Details section. If a parameter is optional, it will be listed with a question mark next to it. If a method returns a value when it is called, the method parameters will be followed by an arrow symbol pointing to the return type. Looking at the Map class methods, the add() method has a required parameter (I believe this should say layer, singular), an optional parameter (index, specifying the position in the Map’s layer collection where you want the layer to appear), and no return value. The findLayerById() method has a required layerId parameter and it returns a reference to a Layer object. Note that when a parameter or return value is an object, it will appear in the documentation as a link. This helps you to navigate through the SDK as you write your code.

The part of the class documentation that we glossed over was the Constructor section. This section is intended to provide guidance on how to create a new object of the class. This is done by using the word new followed by the name of the class and a set of parentheses. In some APIs (including version 3.x of Esri’s JS API), it is possible to set certain properties of the object you’re creating as part of the constructor statement, making it important to consult the Constructor section of the class’s documentation. However, in version 4.x, any of the class’s properties can be set as part of the constructor, which is why you’ll note that the Map class constructor says simply properties? within the parentheses.

Whatever properties you decide to set in the constructor should be expressed as a JS object literal, a term that may seem intimidating, but is actually not too difficult to grasp. Object literals are basically a list of property-value pairs, in which the list is enclosed in curly braces and the property-value pairs are separated by commas. In the case of the 2D sample, the Map was constructed with just a single property-value setting (the basemap), whereas in the 3D sample, it was constructed with two property-value settings (the basemap and the ground).

Note that you need not set all properties as part of the constructor. For example, I could rewrite the 2D sample as follows:

var map = new Map();
map.basemap = "streets";

Or the 3D sample as follows:

var map = new Map({
  basemap: "streets"
});
map.ground = "world-elevation";

One last word on constructors... When creating an object, you’re typically doing so because you need it later in your script. Thus, you will usually store a reference to the object you’re creating in a variable. In the samples, the new Map object was stored in a variable called map. That variable was later used to set the map property of a MapView object. Having multiple entities in a script with the same name can be confusing, especially for beginners, so I like to assign variable names that don’t duplicate the name of a class or property. In this case, I might use myMap or theMap. Keep in mind though that this means updating other statements in which that variable is referenced:

require([
  "esri/Map",
  "esri/views/MapView",
  "dojo/domReady!"
], function(Map, MapView) {
  var myMap = new Map({
    basemap: "streets"
  });
  var myView = new MapView({
    container: "viewDiv",
    map: myMap,
    zoom: 4,
    center: [15, 65]
  });
});