1.2. Dissecting Your Map Application¶
As demonstrated in the previous section, a map that fills the whole browser viewport is generated by bringing together a minimal html document, application initialization code, and user interface configuration objects. We’ll look at each of these parts in a bit more detail.
1.2.1. Minimal HTML Document¶
Since the mother of all web browser content is still HTML, every web application needs at least a basic HTML document as container. It does not contain human readable markup, so it has an empty body. But it makes sure that all required style and script resources are loaded. These usually go in the document’s head:
<link rel="stylesheet" type="text/css" href="ext/resources/css/ext-all.css">
<script type="text/javascript" src="ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="ext/ext-all.js"></script>
Ext JS can be used standalone, or together with JavaScript frameworks like
JQuery. Depending on this environment, an appropriate adapter has to be loaded
first. We use Ext JS standalone, so we need the ext-base.js
adapter. In the
second line, we load the main library.
GeoExt not only relies on Ext JS, but also on OpenLayers. So we also have to load OpenLayers. And finally, we can load GeoExt:
<script src="openlayers/lib/OpenLayers.js"></script>
<script type="text/javascript" src="geoext/lib/GeoExt.js"></script>
Note
When using GeoExt, you also benefit from all the functionality that plain Ext JS and OpenLayers provide. You can add GeoExt to your existing Ext JS and OpenLayers applications without breaking anything.
1.2.2. Application Initialization Code¶
Application initialization in this context means code that is executed as early as possible.
Ext.BLANK_IMAGE_URL = "ext/resources/images/default/s.gif";
var app, items = [], controls = [];
items.push({
xtype: "gx_mappanel",
ref: "mapPanel",
region: "center",
map: {
numZoomLevels: 19,
controls: controls
},
extent: OpenLayers.Bounds.fromArray([
-122.911, 42.291,
-122.787,42.398
]),
layers: [new OpenLayers.Layer.WMS(
"Medford",
"/geoserver/wms?SERVICE=WMS",
{layers: "medford"},
{isBaseLayer: false}
)]
});
controls.push(
new OpenLayers.Control.Navigation(),
new OpenLayers.Control.Attribution(),
new OpenLayers.Control.PanPanel(),
new OpenLayers.Control.ZoomPanel()
);
We start with setting a local URL for the blank image that Ext JS uses
frequently, and define some variables. We populate two arrays. items
is the
user interface items of our application, and controls
is our OpenLayers map
controls.
The really interesting part in the snippet above is the one with the
items
that we will add as configuration objects to the viewport. In Ext JS,
we find ourselves creating configuration objects instead of writing code for
most basic tasks, which usually makes application development easier and faster.
The items interact through events and events listeners, the “glue” which we
will talk about later.
Before we look at the items in more detail, let’s find out how to add content to our viewport.
1.2.3. Building the User Interface¶
We already saw that the body
of our HTML document is empty. Everything
that we see on the web page is added by Ext JS, but for this to work we need
to have the DOM of the page ready, so we can append to it. To ensure that we
don’t write to the DOM too early, Ext provides the Ext.onReady()
hook.
In our example, the user interface is simple. We just create a new
Ext.Viewport
with a border layout. This allows us to fill the whole browser
viewport with our application, and we don’t need to add any markup to our page.
Ext.onReady(function() {
app = new Ext.Viewport({
layout: "border",
items: items
});
});
The Ext.Viewport
here uses a “border” layout. It can have items for its
center
, north
, east
, south
and west
regions, but only the
center
region is mandatory. It takes up all the space that is not used by
the other regions, which need to be configured with a width
or height
.
Note
To make our workshop application modular, we will be calling
Ext.onReady()
several times as we add functionality. There is no need
to do this in a real life application, where all DOM dependent code usually
goes into a single Ext.onReady()
block.
1.2.4. The GeoExt.MapPanel Component¶
In Ext JS, all constructors of UI components take a single argument, which we
will be referring to as “configuration object”. Like all JavaScript objects,
this configuration object is wrapped in curly braces, and contains
key: value
pairs. Let’s have a look at the configuration object for our map:
{
xtype: "gx_mappanel",
ref: "mapPanel",
region: "center",
map: {
numZoomLevels: 19,
controls: controls
},
extent: OpenLayers.Bounds.fromArray([
-122.911, 42.291,
-122.787,42.398
]),
layers: [new OpenLayers.Layer.WMS(
"Medford",
"/geoserver/wms?SERVICE=WMS",
{layers: "medford"},
{isBaseLayer: false}
)]
}
The first three properties are not specific to GeoExt. The xtype
tells
Ext JS which constructor to send the configuration object to. ref
defines
a reference relative to the container (in this case the Ext.Viewport
we
add this item to). The region
is the region of the viewport we want to
place our map in.
Note
The following two notations are equivalent:
new GeoExt.MapPanel({region: center, extent: /* ... */});
{xtype: "gx_mappanel", region: center, extent: /* ... */});
Ext JS keeps a registry of available
components,
called “xtypes”. GeoExt adds its components to this registry. To make them
distinguishable from others, their names start with the “gx_” prefix. In
this context, the ref
property is also important: it is used to create
a reference so we can access the component later more easily.
Using xtypes is useful when loading configurations dynamically with AJAX. In that case, the configuration has to be JSON compliant, and may only contain simple types (numbers, strings and boolean values).
The other properties are specific to the GeoExt.MapPanel
: Instead of
creating an OpenLayers.Map instance, we just configure some configuration
options for the map in the map
option. extent
sets the initial extent
of the map, and layers
the initial set of layers. For our simple map, we
just want to show a single WMS layer. As in plain OpenLayers, we do this by
instantiating an OpenLayers.Layer.WMS
object. The only difference here is that we configure the WMS layer with the
{isBaseLayer: false}
option. This is not strictly necessary now, but when
we add a layer tree later, we want to see the tree node for this layer rendered
with a checkbox, not with a radio button.
You’ve successfully dissected your first application! Next let’s learn more about developing with GeoExt.