Thursday, May 14, 2009

OpenLayers again

Leaving aside all that I still need to learn about how to download data from a WCS call, I thought that a good place to start would be to make sure I knew how to use an OpenLayers map that would allow a user to draw a bounding box rectangle and then have the javascript capture the BBOX coordinates. I could see such functionality in action on a couple of sites and thought it would be fairly straightforward.

It was almost a full day's work to find an example. I get frustrated paging through all the http://www.openlayers.org/dev/examples/. A lot of them don't work or, if they do work, it's not clear what you have to do to get them to work and what it is that you are supposed to see when you use them. The list changes rapidly and when I'm looking for something in particular I start at the top of the list and work my way down and usually run out of time or patience before I get to the bottom. This time I decided to start at the bottom of the list.

As well as looking at the examples on the OpenLayers site, I thought I would try some Google queries, too. That turned up some interesting information, but nothing that was what I was specifically looking for. In this particular instance those searches, combined with the decision to start at the bottom of the OpenLayers list, caused me to lose a lot of time. I finally found what I was looking for near the top of the list of OpenLayers examples. I shouldn't look at it as lost time, I suppose, because I learned new things along the way.

In any case, using a combination of ideas from custom-control.html and custom-control-point.html (that one doesn't even display the map when you look at it on the OpenLayers site) I created a BBOX1.html with the basic functionality that I wanted. The user can use the shift-click (and where is this documented in OpenLayers?) to draw a bounding box. When the mouse is released the BBOX coordinates display in the area below the map. Not very useful, in and of itself, but it's a big step because now I can capture those coordinates and use them when I'm to the point of building the URL to make the WCS call.

But today we have a new problem. A common approach in the OpenLayers examples, and the one being used in BBOX1.html, is to create an init() function that does the work of creating the map object with the base layers and controls and events that then gets called from onload() in the body tag. That's all well and good for a normal web page, but it doesn't work in the portlet world, which is where I'm playing.

Since portlets are fragments of HTML markup you cannot use the head, title, or body tags. Those tags are under the control of the portlet container. Whenever I use javascript in a portlet I have to make sure that the code is all within the body tag, because that is the only place you can put HTML in a portlet. When I get an OpenLayers example to work I take the code in the init() function and put it all within the body tag, instead of a separate function. I've always wondered if there'd be a situation where that would mess things up.

I made a BBOX2.html file with the init() function removed and all the code put inside the body tag. Unless I'm overlooking an obvious mistake, there are no other differences between the two HTML files. But now when I load the BBOX2.html file in Firefox I get a script error that points me to a line of code that's within the OpenLayers.js file. The code is referring to an element.style object and the error states that "element has no properties." It's next to impossible to follow any flow of code within OpenLayers.js because there's no formatting in the file. And I certainly wouldn't want to make changes to that file. So why does Firefox complain that the element has no properties just because the code is taken out of the head tag and put in the body tag? It makes no sense. Welcome to my OpenLayers world.

2 comments:

Javi Bahe said...

You don't need the tag body to call de javascript function init() with the onload event. You can create a div with id="map" and call the script inside. Just like this:
< div id="map">
< script>init();< /script>
< /div>

It works fine in a portlet.

Barbara said...

Thanks for the tip! I didn't know this.