with Ges Seger

STRAAANGE COOODE

Today's Episode:

Finding Default

In addition to web design, I do considerable work developing mod_perl-enabled Apache web servers. For the uninformed und andere schweinhund, this is a way of building a full-featured Perl interpreter into an Apache executable, thereby avoiding the huge performance and memory hit incurred by calling Perl each time you run a CGI script written in Perl. I mention this because today's excursion into the world of Strange Code concerns a common design problem encountered in building web-based forms. Namely: How do you populate a form with default values retrieved from a database?

As with any solution involving Perl at some point, There's More Than One Way To Do It. The easiest is to just build the entire page in Perl, using a combination of its DBI and CGI packages. Stylistically, I don't like that approach -- I prefer using a templating package (Mark-Jason Dominus' Text::Template, if you're curious) in conjunction with my Perl handler(s) so I can separate my programming and display logic into different chunks. This is all well and good, until the moment comes when you have to display a popup menu of values and set its default value to whatever the database stored for that record. At first glance, there's no way you can do this with a templating system.

When I bumped into this problem recently, I solved it by the simple expedient of making my perl handler generate the menu and having the template include the whole thing bodily. The only advantages it had were that it could be programmed quickly and it worked. The price of this was to force the Perl handler to maintain large amounts of list and hash data statically to support menu generation, increasing the server's memory requirements because each server instance has to maintain its own copy of that static data. I was convinced there had to be a better way.

My first attempt at solving this mess involved defining a shared memory area for the static data that each server instance could then access. Unfortunately, the most common Perl packages supporting a shared global memory area wouldn't pass make test on my server platform. The data didn't exist in our backend database (which would be global to each server instance), so I couldn't write a PL/SQL procedure to build the menu there. Even if I didn't loathe Java on general principles, I didn't have the time or inclination to figure out how to do it that way. The whole situation sucked, but there was no way I could see of getting around it any better.

Inspiration hits me at the oddest times. It was in the middle of doing what I always do on Wednesday nights (be at church choir rehearsal and my daughter's Irish dance school at the same time) when the solution to the above dilemma occurred to me. Go ahead and write the popup menu in HTML -- but don't try to set the default option there. Instead, write a javascript handler that sets the default option in that menu for you at page load and have the templating system include the proper option value into the handler call. It took an hour of tinkering the next day to smooth out the wrinkles, but it worked like a charm when I was done.

As usual, I encourage you to use the View Source command on your browser to follow along with what I did. On page load, the init_popups() function is called from the <BODY> tag. This javascript snippet consists of nothing but calls to the function set_defaults, one for each popup that requires a default value be set. set_defaultsthen loops over all the options in the menu, stopping only on three conditions:

In the event of a match, the control's SELECTED attribute is set at that point and the function exits. In the event of no match being found, it just exits.

BUGS FEATURES

Each menu must be assigned an unique ID via the ID attribute. I typically use the same value as the menu NAME attribute.

The call to init_popups() on this page has the default option value hard-coded into the second parameter passed. This is what you want to replace with whatever your templating system uses for tags.

EXAMPLE

Service Designator