| Decaffeinating Forms
and Browses by S.H. Parker (c) 1999 Last month, we examined the core of the "caffeine-free" Internet Connect technology demanded by an increasing number of IC developers. Whether invoked through the templates (hence, automatically, the way most of us consume our coffee) or hand-coded, the Target.Writeln method lies at its foundation. Tony Goldstein of Information Packaging Unlimited has modified the IC templates and classes to ensure Java-free HTML automatically (see his article at http://www.cwsuperpage.com/articles/cwicfaq/caffeinefreecwic.htm, the decaffeination reference). What remains to examine are data entry forms and lists. I gave a detailed description of how to do a report substitute and I also showed a display-only form. How do we do live entry forms and browse boxes?-The later being the heaviest user of the Topspeed Java classes and, therefore, the most difficult to decaffeinate. Or, more accurately, browses embody the greatest functionality and, therefore, use the most (and most of the) applets. Forms Some years ago, I visited my Rabbi and found him watching a boxing match on TV. Normally a thoroughly kind and gentle fellow, I found him hunched over, intent on the bout. "No rachmonos, no rachmonos," no mercy, he kept saying. Because mercy is one of the two key Prophetic attributes of God (justice being the other) ... some discussion ensued. And, from this I learned that, while extraordinarily rare, there were, in principle, exceptions to the mandate for mercy (though we never did come to agreement on whether boxing matches were legitimately one of them). Decaffeinating forms is actually quite easy. It requires only a certain ruthlessness, that is, a complete absence of rachmonos in eliminating all Java controls. For, the first control that invokes an Applet will cause the entire class structure to be downloaded. (Finally, I found a solid exception.) You have two ways of doing this: globally or locally. Globally, press Global ... Extensions ... Internet Application Extension. Go to the Classes tab.
You will see a list of all the possible controls and their default classes. You need to find each and every Java control. These are easily identified by the fact that the class name contains "Java." Typically, the class names begin "WebJava" and then names the control type. Highlighting each in turn, press Properties and check the "Override default class" box.
Change each to its HTML equivalent (usually) by overwriting "Java" with "HTML." For example, in the list above, I have highlighted the List control. In the override entry field, I would change "WebJavaListClass" to "WebHTMLListClass." Of course this is a tremendous amount of work. So, may just a little bit of rachmonos, if not for the classes, for the sake of your wrist and fingers is called for (an exception to the exception?). It probably is wiser to do this only for control types that you actually do use. Locally, you will have to override the class for each control. You cannot skip any that have Java equivalents, as one might generate as a Java control without your knowledge (yes, this can happen; stay tuned). From the Procedure Properties screen (remarkable that we still call this a "screen" even though we're in Windows, isn't it?), press "Internet Options." Go to the Controls tabs and highlight the control you are interested in. Press "Properties" and go to the Classes tab. You will get the same "Override default classes" screen as if you had accessed it from the Global properties with one very important exception. This screen gives you a drop down list of all eligible classes from which to select. Simply select the appropriate HTML class.
You must show absolutely no rachmonos, no mercy whatsoever. Every single control must generate to HTML and not call a Java applet. List Boxes
Funny things happen when you change your browse box to an HTML list.
You lose a number of things, two that many, myself included, consider important. First, the HTML list box supports only one column. So, you lose all the columns in your browse except the first. Second, you lose page navigation keys. Page Up, Page Down, Home and End no longer work, not in Windows, but on the Web. Both are effects of the same cause: an HTML list is created, much as you might expect, as an HTML <SELECT> structure. The values are taken from the browse queue and generated as <Option>s. Once you click on the Select/Option structure, i.e. the List box, the up and down arrow keys will work. But, to get another page of records, you must get a new subset of records and create a new Select structure (the HTML Select is a static structure, that's why, and only supports a single string field -- HTML, not Clarion). What this means is that you will need to provide your own buttons for page navigation. Since buttons, by default, do a Submit and, therefore, a full page refresh, you will get the next or previous set of records. For the same reason, it is probably not a good idea to provide an up or down (single record) button as I do: each button click will give you a page re-draw. (No, you cannot request a Partial Refresh. The Partial Refresh option only refreshes Java controls.) The navigation buttons can rely on standard Clarion code like: Post(Event:PageDown,?List) or BRW1.TakeScroll(Event:PageDown) Because the application does not allow for on-line file maintenance, you will not find Insert, Change or Delete buttons. The Read button just calls the report substitute described last month. But, if your browse has file update buttons, they will work in decaf mode. You will notice that I use buttons of my own in place of Tabs. The code behind these buttons calls a routine using standard Clarion/ABC stuff: BRW1:SetFilter() in a Case structure: Case FilterString !Set when button is pressed
Of 'CW2.x'
BRW1.SetFilter('(Clip(Upper(FAQ:Product)) = ''CW2.X'')')
StatusString = 'CW2 FAQs'
Of 'IC'
BRW1.SetFilter('(Clip(Upper(FAQ:Product)) = ''IC'')')
StatusString = 'IC FAQs'
Of 'C4/ABC'
BRW1.SetFilter('(Clip(Upper(FAQ:Product)) = ''C4/ABC'')')
StatusString = 'C4/ABC FAQs'
Of 'DCT'
BRW1.SetFilter('(Clip(Upper(FAQ:Product)) = ''DCT'')')
StatusString = 'DCT FAQs'
Of 'SQL'
BRW1.SetFilter('(Clip(Upper(FAQ:Product)) = ''SQL/ODBC'')')
StatusString = 'SQL/ODBC FAQs'
End
ThisWindow.Reset(1) Using the Clarion templates, the setting of FilterString on the button press might be all you need if you filter the browse with something like: ~FilterString or ( Clip(Upper(FAQ:Product) = Clip(FilterString) ) But why not just use HTML classes for Tabs? Indeed, if you try to override the Sheet and Tab classes, you will discover that there is no "Java" implementation available on the drop down list. It turns out that, despite the class name, Sheets and Tabs are Java controls. In a separate test, I created an app with Tabs, an HTML list and no other controls. I deleted Clarion.CAB and .ZIP from the /public directory (not very sophisticated, but quite effective). Running the app produced a script error and then it ran. But, it ran sans the Tabs; they never appeared. Examination of the HTML source revealed that two applets were being called: ClarionTabControl.Class and ClarionLoader.Class. So don't use these controls when you want to go decaf. What Else Do You Lose? There is more that you lose when you decaffeinate. But these are things one expects based on the IC documentation. You lose any indication of what "Tab" you are on. That is, you cannot see which sort order button was pressed. I hand coded an indicator to provide this functionality. Of course, this is an issue only if you need to use Sheets and Tabs. You lose the ability to control button size. This is the nature of HTML; they size to their contents. You lose the ability to put images on buttons. The IC templates force such buttons to use an applet to display the image. (A standard HTML equivalent would require a script or CGI program to get an action to occur. So, again, this is HTML, not Clarion.) When the page refreshes, the list area will resize itself, changing width to accommodate the widest record in the current set. HTML. If there are no qualifying records for a filtered browse, you can get a very odd looking display.
No show stoppers here; only items to be aware of when you design for caffeine-free. But, I Really Need ... multi-column lists. Tony Goldstein has created some alternate classes to handle non-Java lists (as well as HTML buttons with images). I am hoping that Information Packaging Unlimited will release these as a commercial product, if not by the time you read this, very shortly. Go to http://www.cwsuperpage.com/devcon/eurodevcon98/cwicclass.htm and follow the "sample app" link (you can also download a Powerpoint slide show of Tony's presentation at Euro Devcon from the same place) to see the alternatives available. In the meantime ... back to classic Clarion. Populate your List control with a local variable. In the SetQueueRecord (ABC Templates) or Format Element of the Browse Queue (Clarion Templates), assign a concatenated string to the local variable. There, that didn't hurt too much, did it? I suppose you could get a less Clarion and more HTML look and feel (if that is important to you) by controlling this assignment: LOC:ListItem = '<<a href=" ' & ... & '>' & Clip(pre:variable) & ... if you have some way of calculating the link from the file data. You could even create HTML tables, in place of the List box to give a grid effect: DisplayString = '<<table border="1" cellpadding="0" cellspacing="0" ' &|
'width="50%"> <<tr><<td>' &|
Clip(first field) &|
'<</td><<td>' &|
Clip(second field) &|
'<</td><<td> &|
Clip(third field) &|
'<</td><</tr><</table>
Target.Writeln(DisplayString)
The possibilities are endless. The Problem is that even after you have applied all of the above techniques, even after you have shown so little rachmonos that you redline your guiltometer, you will still find Clarion.CAB or .ZIP loading when executing your apps. Huh? Quoting Tony's article: even if you don't use any Java controls, the classes "still get downloaded when the application starts up. That's because the form input is handled by the Submit applet." To put some perspective on Tony's remark, in HTML, buttons are Form objects. Therefore, all submits (i.e., button presses) are handled by an applet. This includes the HTML buttons on your HTML List boxes where you have (so mercilessly) eliminated all calls to Java classes. To confirm this, just use your browser's ability to view source. No matter how little rachmonos you showed, you will still see references to applets. Of course, if your buttons are at the end of the control order, the non-Java controls will load before the classes (this is the way my app is constructed). You will gain virtually all of the speed of decaffeination, once the classes are loaded, since they are used only for buttons. But you will still restrict your users to Java-enabled browsers (actually, non-Java browsers will work, they will just give applet errors every time something is selected -- test this by turning off Java in your browser and going back to the app). If your users have Java-enabled browsers, perhaps this is acceptable for your purposes. Or, you could apply the template modifications Tony has documented and simply not bother with any of these issues or with all the class overrides (you may still have to do one or two overrides, and I don't think Tabs are supported, but that is certainly preferable to having to override every control or every control type). When IPU releases its classes, purchase them, and let them handle the browses for you too. Summary To entirely decaffeinate your IC apps, you must apply Tony Goldstein's template modifications. There is no other way. Then you have a choice of HTML List boxes, roll-your-own-with-Target.Writeln or, when available, IPU's List classes. There you have it, three levels of caffeine. And two flavors of decaf (and another coming?). Who could ask for more? |