Using GeoServer, Openlayers, and CQL Filters
I received a request this week to put Census Questionnaire Centers (QAC) on a web app ASAP. In case you don’t follow the Census’ every move:
Questionnaire Assistance Centers (QACs) are spaces, donated by community partners, where staff from the Local Census Office or the partner organization are available to answer questions about completing the questionnaire, provide special language assistance and answer general questions.
This is a short term thing - the QACs are only open for 4 weeks or so - and the only initial requirement was dumping the points on the map and showing information when you click on them. So I dumped the shape file into Postgres, published the layer with GeoServer, and added it to an app as a vector layer (KML).
For the most part this code was proudly pilfered from one of the OpenLayers samples. Here we’ll add the layer to the map and set some select events. I made the census_qac_layers a global variable so I could get at it later. Note I took out the enormous URL so the page wouldn’t explode, but this was it (it will probably ask you to pull it up in Google Earth).
[sourcecode language=’javascript’]
// QAC Centers for Census
census_qac_centers = new OpenLayers.Layer.Vector(“Census QAC Centers”, {
projection: map.displayProjection,
strategies: [new OpenLayers.Strategy.Fixed()],
protocol: new OpenLayers.Protocol.HTTP({
url: “http://enormous-url",
format: new OpenLayers.Format.KML({
extractStyles: true,
extractAttributes: true
})
})
});
census_qac_centers.setVisibility(false);
map.addLayer(census_qac_centers);
select = new OpenLayers.Control.SelectFeature(census_qac_centers);
census_qac_centers.events.on({
“featureselected”: onFeatureSelect,
“featureunselected”: onFeatureUnselect,
“stopClick”: true
});
map.addControl(select);
select.activate();
1 |
|
Done and done. Our map now has the pox, and each pustule will pop up the QAC information. I gave the KML output a little styling, which is literally as simple as dropping a couple of files like this in your layer folder (here’s description.ftl):
[sourcecode language=”text”]
${partner_na.value}
${street.value}
${phone.value}
Hours: ${hours.value}
Langauges served: ${language_s.value}
1 |
|
Next I made a standard HTML radio button list, with the value being the language.
[sourcecode language=”html”]
English
Arabic
Chinese
French
1 |
|
Let’s walk through this. First, we set all the radio buttons to be unchecked (Firefox likes to remember that stuff from session to session). Next we detect whenever a change occurs (i.e. a radio button is checked) and run a function. We set the layer to visible, grab the language value of the checked radio button, and create the CQL filter. It’ll end up looking something like this, where language_s is the field name we’re querying:
[sourcecode language=”sql”]
language_s like ‘%Spanish%’
1 |
|
Here we take the CQL_FILTER parameter we added to the layer, and we’re dropping in the CQL we created. The layer is refreshed with the new URL, and only the features that match our CQL filter will come back. A user clicks on German, only the German QAC’s show up.
The CQL Filter option is available on any layer in GeoServer (not just vector), and with the parameter option in OpenLayers it’s very easy to dynamically change the content of a layer. We were able to turn around this request in an extremely short amount of time (a couple of hours, a large portion of which was navel-gazing design) and in a way that’s easy to extract from the application when the QAC’s go away in a month.
You can view it on GeoPortal, second accordion tab on the left.