Today's Episode:
Fun with Regular Expressions
Today, we look at the latest problem which the Application That Must Be Web Enabled™ threw me. In this portion of the application, the luser was supposed to be able to edit a table of entries corresponding to various computer systems managed by the customer. Each row consisted of two entries: a 4-5 character alphanumeric string whose formulation may have had some logic and meaning associated with it back in 1966, and an associated English-language title for said computer that was much more useful to modern audiences.
When editing in the client-server version, the luser had to type in the first value, whereupon the application would check the backend database for the correct title. I looked at this behavior and immediately thought, this is stupid. It should be the other way around. Users should be selecting the title from a popup menu and then have the application look up the alphanumeric code. The way it should be was intuitively obvious, which of course made it (wait for it...) difficult to code. To add insult to injury, the luser also needed to be able to jump over to the associated computer system record, which meant some sort of hyperlink also needed to be modified at the same time. Me and my big ideas...
THE SOLUTION
One of the many features built into Javascript over the years is a regular expression engine whose syntax is stolen borrowed from Perl. This is a win for me since I've made most of an information technology career out of slinging Perl. The relevance in mentioning this is that while I was moping about the situation I had coded myself into I realized that I could use the values generated from a popup menu in a match-and-replace regular expression. Several, actually, since I had a lot of information I needed to rewrite on the fly. Stick the call into an onchange handler associated with each popup, and I had exactly what I wanted in a form the luser could easily handle.
WALKTHROUGH
Let's go to the code:
1 function my_test(popup, id) {
2
3 // -- get the value and label from the selected option
4 var i = popup.selectedIndex;
5 var dsd = popup.options[i].value;
6 var name = popup.options[i].text;
7
The function takes two arguments: a reference to the <SELECT> tag that called it (popup), and the id of the cell containing the link to be modified (id). Lines 4-6 cache the menu choice just made by the luser for later use in the next block.
8 // -- rewrite the link
9 var cell = document.getElementById(id);
10 var stuph = cell.innerHTML.replace(/\b\w+\</, dsd+'<');
11 stuph = stuph.replace(/\b\w+&/, dsd+'&');
12 cell.innerHTML = stuph.replace(/\b\w+\"\>/, name+'">');
13 }
This is the money block. Line 9 gets an object reference to the target cell. Lines 10 and 11 change the value in both places of the URL string and puts the result both times into a temporary variable. Line 12 applies the second regular expression to the temporary variable and stores the result back into the innerHTML property of our target cell. Note the complicated syntax to the regexp in line 10, because we need to match the same chunk of text twice in our target -- once in the search portion of the link's URL, and again in the body of the link.
USAGE
The function is called as an onchange handler within each <SELECT> tag of the data table. We use the keyword this as the first argument, which serves to pass the <SELECT> tag in as an object reference. The second argument is a reference to the table cell containing the link to be rewritten, and can easily be generated on the fly in any number of templating systems.
BUGS FEATURES
The variables dsd and name are legacies of when I was originally testing and debugging this code. Strictly speaking, they aren't really necessary in production-quality code.
I wish I didn't need the intermediate variable stuph while applying both regexp's, but every HTML rendering engine I tested this code against insisted that I needed it.
You have to know something about regular expression syntax to understand exactly how the regexps in lines 10 and 11 are built and what they're doing. It's not Rocket Science (and I should know...), but it's as close as anyone in the Information Technology field is going to get without actually working at NASA or JPL.
The original version of this code, which worked under any browser using the Gecko rendering engine used zero-width positive lookahead assertions in both regexp replacements to minimize the amount of text we were going to have to replace. Microsoft's rendering engine for IE/Mac 5.1, though, is so brain-damaged that it flagged them as errors. Hence, we had to do the regexp transforms the big, slow, and stupid way. View Source on this page to see the code as it should have been.