Foxhound is the better* Database Monitor for SQL Anywhere.
*better: More thorough, more relevant, more effective.
...more Alerts, more All Clears, more details, more control in your hands.


[Home] [Back to Tip 73] [Forward to Tip 75] [Archives]

Breck Carter
Last modified: November 21, 1997
mail to: bcarter@bcarter.com



Tip 74: Getting Started with NetImpact Dynamo

(This Tip originally appeared on the PowerBuilder and Java Journal web site.)


Tip 74: Getting Started with NetImpact Dynamo

Summary: NetImpact Dynamo lets you code web server-based database programs in a JavaScript-like language called Dynamo Script. By combining server-side Dynamo Script, client-side JavaScript and HTML code in the same web page you can automate many of the mundane tasks required in the creation of interactive web sites. And your whole web site can be stored in a single database to make administration, publishing, backup and recovery much easier!

The easiest way to write new code is to copy and edit existing code. The only problem is you might end up with a working program and no idea how you got there. That’s where I am right now with JavaScript from Netscape and NetImpact Dynamo from the Watcom subsidiary of Sybase.

Dynamo is Watcom’s first contribution to the NetImpact family of internet-related products coming from Sybase. It started shipping in October as part of Sybase SQL Anywhere Professional 5.5.

NetImpact Dynamo lets you write database update applications that run on the web server instead of the client or browser side of the internet connection. You code the application as a combination of HTML and Dynamo Script, and you use the SQL Central database administration utility to store all the code in a SQL Anywhere 5.5 database as shown in Figure 1.

Figure 1: The Web Site In SQL Central

Undisplayed Graphic

When your program runs, the application server portion of NetImpact Dynamo executes the Dynamo scripts to create more HTML code before shipping it all off to the client. This process usually includes database I/O, and when interactive input is received back from the client yet more Dynamo Script code is executed to process the user’s request.

A major component of NetImpact Dynamo is an application server which attaches to the CGI, ISAPI or NSAPI-compatible web server of your choice. It also comes with a Personal Web Server for testing applications, and includes several major enhancements to SQL Central and the SQL Anywhere database server to support web sites. The servers and development tools only run on Windows 95 or NT but there is no such restriction on deployment: All vestiges of Dynamo Script are removed from your web pages before they leave the server so any operating system and browser can be used on the client.

The JavaScript Connection

JavaScript is an interpreted language that looks a bit like Java but is a whole lot easier to learn and use. JavaScript is important to NetImpact Dynamo because it forms the foundation for Dynamo Script, just like BASIC is the foundation for PowerBuilder’s PowerScript. In other words, PowerScript is BASIC-like while Dynamo Script is JavaScript-like, and JavaScript is in turn Java-like.

If you count 60 days as being one Internet Year then JavaScript was developed many years ago by Sun and Netscape and introduced in Netscape Navigator Version 2. The latest version is JavaScript 1.1 supported by Navigator 3. You can code JavaScript to run on the client side, or on the server side as part of Netscape’s LiveWire product line and now Sybase’s NetImpact Dynamo.

As part of Microsoft’s Let’s Catch Up Slowly strategy, JavaScript is also available as “JScript” in Internet Explorer Version 3. JScript seems to be a partial copy of the older version of JavaScript, with some annoying differences that should eventually disappear if Microsoft and Netscape follow through with their promise to define a “standard JavaScript”.

The future looks bright for JavaScript. It’s popularity is increasing, and not just for displaying sophomoric messages in scrolling status bars. It provides an easy way to partition your application between the client and the server without making the leap into Java.

What’s It Like?

If you believe the bumper sticker “Strong Typing is for Programmers with Weak Minds” then JavaScript is the language for you. Unlike Java, JavaScript and Dynamo Script variables don’t have to be declared ahead of time and they don’t have fixed data types at execution time. In other words, x = 5 and x = “Hello” both work and old dBase programmers should feel right at home.

JavaScript and Dynamo Script share some other big differences from Java: Your script is interspersed with HTML rather than held in separate applets, it is dynamically interpreted rather than compiled ahead of time, and object references are resolved at run time rather than compile time.

JavaScript is called object-based rather than object oriented because it lets you use and extend built-in objects but doesn’t let you declare or inherit from new classes. Both Java and Dynamo Script, on the other hand, let you create new classes and fully indulge in the Big Three of object orientation: encapsulation, inheritance and polymorphism.

Nevertheless, Dynamo Script looks more like JavaScript than Java. This resemblance is more than academic because the Sybase documentation concentrates on facilities unique to NetImpact Dynamo. The little Dynamo booklet barely fills 100 pages, leaving you on your own to learn about the features shared between Dynamo Script and JavaScript. This stands in stark contrast with the thousand-plus pages in the SQL Anywhere 5.5 database manuals. Fortunately, you can find all you need on the web itself. Figure 2 shows where to get more information about the Netscape and Microsoft implementations of JavaScript.

Figure 2: All About JavaScript

 JavaScript 1.0 Specifications from Netscape:
    http://home.netscape.com/eng/mozilla/Gold/handbook/javascript/index.html
 New Features in JavaScript 1.1:
    http://home.netscape.com/eng/mozilla/3.0/handbook/javascript/index.html
 JavaScript Articles in NetscapeWorld Magazine:
    http://www.netscapeworld.com/netscapeworld
 JavaScript Articles in JavaWorld Magazine:
    http://www.javaworld.com
 JScript from Microsoft:
    http://www.microsoft.com/jscript/
 JScript Documentation Download:
    http://www.microsoft.com/jscript/us/download/jsdoc.exe

JavaScript In Action

Figure 3 shows a simple JavaScript example. Lines 6 to 13 contain the script code to display today’s date. Line 8 creates a new instance of the Date object in a variable called today and initializes it by default with the current date and time. Line 9 displays today’s date using the writeln method of the built-in object called document. The writeln function sends text to the HTML output stream, making it one of the most heavily used functions in both JavaScript and Dynamo Script.

Figure 3: A Simple JavaScript Demonstration

 1  <HTML>
 2  <TITLE>A JavaScript Demonstration</TITLE>
 3  <BODY>
 4  <H2>A JavaScript Demonstration</H2>
 5
 6  <SCRIPT LANGUAGE="JavaScript">
 7  <!--
 8  today = new Date();
 9  document.writeln
 10   ( "<P>JavaScript Date: "
 11       + today.toLocaleString() );
 12 //-->
 13 </SCRIPT>
 14
 15 </BODY>
 16 </HTML>

The rest of Figure 3 consists of ordinary HTML tags to start the document definition (lines 1 through 4) and end it (lines 15 and 16). Because all the HTML and JavaScript is executed by the browser, the whole thing is sent as-is to the client. In fact, a special application server is not required for the code in Figure 3, it can be stored in a simple text file like any other static HTML page. Figure 4 shows what displayed output and the source code looks like in Netscape Navigator.

Figure 4: JavaScript At The Browser

Undisplayed Graphic

A Dynamo Demonstration

While Figure 3 shows how JavaScript can be added to an HTML document by using a special tag, Figure 5 shows how Dynamo Script uses three new tags called SCRIPT, SQL and formatting. The page starts with the usual HTML on lines 1 to 4 followed by the JavaScript from before on lines 6 through 13.

The special SCRIPT tag on line 15 begins the section of Dynamo Script code which ends on line 20. The statements in this section work exactly the same as the JavaScript code except they are executed on the server instead of at the client.

Figure 5: A Simple Dynamo Demonstration

 1  <HTML>
 2  <TITLE>A Dynamo Demonstration</TITLE>
 3  <BODY BGCOLOR="#FFFFFF">
 4  <H2>A Dynamo Demonstration</H2>
 5
 6  <SCRIPT LANGUAGE="JavaScript">
 7  <!--
 8  today = new Date();
 9  document.writeln
 10   ( "<P>JavaScript Date: "
 11       + today.toLocaleString() );
 12 //-->
 13 </SCRIPT>
 14
 15 <!--SCRIPT
 16 today = new Date();
 17 document.writeln
 18   ( "<P>Dynamo Date: "
 19       + today.toLocaleString() );
 20 -->
 21
 22 <!--SQL
 23 SELECT status_code,
 24        sort_order,
 25        DateFormat ( last_updated_at,
 26          'yyyy mm dd hh:mm' )
 27   FROM activity_status
 28  ORDER BY sort_order
 29 -->
 30
 31 <P>
 32 <TABLE BORDER>
 33 <TR>
 34 <TH>Status Code</TH>
 35 <TH>Sort Order</TH>
 36 <TH>Last Updated</TH>
 37 </TR>
 38
 39 <!--formatting-->
 40 <TR>
 41 <TD><!--data--></TD>
 42 <TD><!--data--></TD>
 43 <TD><!--data--></TD>
 44 </TR>
 45 <!--/formatting-->
 46
 47 </TABLE>
 48
 49 </BODY>
 50 </HTML>

The SQL tag on line 22 begins the special embedded Dynamo SQL section which ends on line 29. This works very much like an embedded SELECT inside PowerScript. It is possible to write Dynamo Script to build a SQL command inside a string variable and then call a function to execute it, but for simple situations the SQL tag is much easier.

Unlike embedded SELECTs in PowerScript the Dynamo SELECT on line 23 returns a result set. The formatting tag on line 39 tells the server what to do with each row: The three data tags are placeholders for the three columns, and the code between lines 40 and 44 causes a new HTML table row with three columns to be created for each row in the result set.

The rest of Figure 5 consists of ordinary HTML tags that start the table definition (lines 31 through 37), end the table (line 47) and close the whole document (lines 49 and 50). Figure 6 shows the result in Netscape Navigator.

Figure 6: JavaScript and Dynamo Script On Parade

Undisplayed Graphic

Figure 7 shows that all the Dynamo Script code was turned into HTML before it reached the browser. This explains why the two times displayed in Figure 6 are one second apart: The Dynamo date was calculated on the server while the JavaScript date wasn’t calculated until the HTML was displayed by the client. To see a window like Figure 7 on your computer, use View - Document Source in Navigator or View - Source in Internet Explorer.

Figure 7: Dynamo Script As HTML

Undisplayed Graphic

The whole script in Figure 5 was initially created by the SQL Central wizard shown in Figure 8. The script was modified slightly for publication but almost all the ugly <tags> were filled in by the wizard.

Figure 8: A Dynamo Wizard in SQL Central

Undisplayed Graphic

Dynamic Dynamo

Old dBase programmers have another reason to feel at home writing JavaScript and Dynamo programs. That’s because dBase programs often contain macros that produce more dBase code as output. In other words, programs that write programs. And that’s what you have to do for World Wide Web applications: Write programs that produce HTML, and sometimes even JavaScript, as output.

But wait, there’s more! Unlike C++ or even PowerBuilder programs, JavaScript and Dynamo applications are interpreted in the truest sense of the word. Both languages contain the eval() function which can evaluate the expression or execute the statements contained in a string argument. This facility is not to be taken lightly: It can be used to create elegant and sophisticated solutions to solve some very difficult problems, and it can also be used to create code that is incredibly difficult to understand and maintain.

Even if you don’t use eval() there is still opportunity for confusion. The simplest Dynamo application always involves at least two languages, Dynamo Script and HTML. If you add some client-side JavaScript then you’re working with a third language, and maybe your code in one language (Dynamo, JavaScript) is generating code in another (JavaScript, HTML). Even though Dynamo Script and JavaScript look very similar, they have many different features and they’re executed at different times on different platforms. This all means you sometimes find yourself asking these questions:

• Is this HTML? Is it Dynamo Script? Or is it JavaScript?

• Is this statement just doing something simple or is it generating code in another language?

• Is this Dynamo Script statement generating HTML? Or JavaScript?

• Is this JavaScript statement generating HTML?

• Or is this a Dynamo Script statement generating JavaScript to generate HTML?

• Or (gasp) is this Dynamo Script generating Dynamo Script to generate...

And that’s when you run screaming from the room. Or if you persist, Figure 9 shows nine different kinds of HTML, Dynamo and JavaScript code, each in its own section labeled A through I. These sections progress in complexity and strangeness from simple HTML in Section A, through Dynamo Script generating JavaScript in Section E, all the way to self-generating JavaScript in Section I.

Each section is shown again in its final form in Figure 10. Where Figure 9 shows the original source code, Figure 10 shows the code as the browser sees it. The next few paragraphs describe each section and what happens to it along the way from Figure 9 to Figure 10 and how it produces the final output in Figures 11 and 12.

Figure 9: A Simple Macro Demonstration

 <HTML>

 <!-- (A) Simple HTML Code -->
 <HEAD>
 <TITLE>A Macro Programming Demonstration</TITLE>

 <!-- (B) Simple Dynamo Script Code -->
 <!--SCRIPT
 dynamoToday = new Date();
 -->

 <!-- (C) Simple JavaScript Code -->
 <SCRIPT LANGUAGE="JavaScript">
 <!--
 javaScriptToday = new Date();
 //-->
 </SCRIPT>

 <!-- ... more Simple HTML Code -->
 </HEAD>
 <BODY BGCOLOR="#FFFFFF">
 <H2>A Macro Programming Demonstration</H2>

 <!-- (D) Dynamo Script to Generate HTML -->
 <!--SCRIPT
 document.writeln
   ( "<P>dynamoToday = "
       + dynamoToday.toLocaleString() );
 -->

 <!-- (E) Dynamo Script to Generate JavaScript -->
 <!--SCRIPT
 javaScriptCode
   = "\<\!\-\- Code Generated by Example (E) \-\-\>\n"
   + "<SCRIPT LANGUAGE=\"JavaScript\">\n"
   + "\<\!\-\-\n"
   + "alert ( \"The Dynamo Document Name is '"
   + document.name
   + "'\" );\n"
   + "\/\/\-\->\n"
   + "</SCRIPT>\n";
 document.writeln ( javaScriptCode );
 -->

 <!-- (F) JavaScript to Generate HTML -->
 <SCRIPT LANGUAGE="JavaScript">
 <!--
 document.writeln
   ( "<P>javaScriptToday = "
       + javaScriptToday.toLocaleString() );
 //-->
 </SCRIPT>

 <!-- (G) Dynamo to JavaScript to HTML -->
 <!--SCRIPT
 javaScriptCode
   = "\<\!\-\- Code Generated by (G) \-\-\>\n"
   + "<SCRIPT LANGUAGE=\"JavaScript\">\n"
   + "\<\!\-\-\n"
   + "document.writeln\n"
   + "  ( \"<P>document.name = '"
   + document.name
   + "'<BR>\" );\n"
   + "document.writeln\n"
   + "  ( \"<BR>document.referrer = '\""
   + " + document.referrer + \"'\" );\n"
   + "\/\/\-\->\n"
   + "</SCRIPT>\n";
 document.writeln ( javaScriptCode );
 -->

 <!-- (H) Dynamo to Dynamo -->
 <!--SCRIPT
 expression = "Math.PI * 2";
 document.writeln
   ( "<P>eval expression = "
   + eval ( expression ) );
 -->

 <!-- (I) JavaScript to JavaScript -->
 <SCRIPT LANGUAGE="JavaScript">
 <!--
 eval
   ( "document.writeln "
   + "  ( \"<P>eval document.referrer = '\""
   + "    + document.referrer + \"'\" );" );
 //-->
 </SCRIPT>

 <!-- ... more Simple HTML Code -->
 </BODY>
 </HTML>

Section A in Figure 9 contains straightforward HTML code. Neither the Dynamo Script nor the JavaScript interpretation stages have any effect on it, and it looks the same in Figure 10. In other words, Section A is a piece of “static HTML” that is passed unchanged to the browser.

Section B contains some straightforward Dynamo Script, and by “straightforward” I mean it “doesn’t generate any display text, HTML tags or JavaScript”. In fact Section B doesn’t appear in Figure 10 at all because it runs on the server and assigns a value to a variable that exists only on that server. In other words, NetImpact Dynamo removes Section B completely.

Section C in Figure 9 contains straightforward JavaScript code. It is passed unchanged to the browser as shown in Figure 10. This code is executed by the browser to assign a value to a client-side variable. Since it does not produce any display text or HTML it has no visible effect on Figures 11 or 12.

Section D contains Dynamo Script that runs on the server to create an HTML tag and one line of text. Figure 10 shows what Section D looks like after the server is finished with it, and the final display is shown in Figure 12.

Section E contains more Dynamo Script but this time it is generating code that can only be written in JavaScript: a call to alert(). This call displays the document.name property and since that’s only available in Dynamo Script then a combination of both languages is required. Figure 10 shows that the value for document.name has been filled in, and the final result is shown in Figure 11.

At first glance the embedded JavaScript in Section E looks monstrously ugly because of all the backslash \ characters but the idea’s quite simple. To prevent Dynamo from getting confused by special characters embedded within string literals, every one of them is preceded by the special escape character \. Some of these backslash characters might be unnecessary but it’s too hard to remember the rules. It’s easier just to fill a huge saltshaker with backslash characters and sprinkle them throughout your strings. It’s also easy to debug problems because your browser can show you the result from Figure 10.

Section F is like Section D but this time it’s JavaScript that’s generating the HTML tag and display text. This code looks the same in Figures 9 and 10 because it’s up to the browser to process it.

If you think Section E is ugly then Section G’s gonna make you hurl. Here is Dynamo Script code that generates JavaScript, and when that code runs it generates HTML. On the other hand, if you’ve ever coded the tildes in a call to the PowerBuilder Modify() function then you’re tough enough to handle Section G. Once again, some Dynamo-only code (document.name) is combined with JavaScript-only code (document.referrer) and the result is displayed via HTML instead of calling alert().

Section H shows that NetImpact Dynamo can indeed evaluate Dynamo Script created on the fly. Figure 9 shows a string literal containing “Math.PI * 2” while Figure 10 shows that eval() has turned it into 6.2831.

Section I looks a lot like Section H except this time it’s JavaScript code that’s calling eval(), and rather than a simple arithmetic expression it is a complete JavaScript statement embedded in a string. Figure 10 shows that unlike Section H, Section I is passed unchanged to the browser because this call to eval() is processed on the client side instead of on the server.

Figure 10: The Final Macro Demonstration Code

 <HTML>

 <!-- (A) Simple HTML Code -->
 <HEAD>
 <TITLE>A Macro Programming Demonstration</TITLE>

 <!-- (B) Simple Dynamo Script Code -->

 <!-- (C) Simple JavaScript Code -->
 <SCRIPT LANGUAGE="JavaScript">
 <!--
 javaScriptToday = new Date();
 //-->
 </SCRIPT>

 <!-- ... more Simple HTML Code -->
 </HEAD>
 <BODY BGCOLOR="#FFFFFF">
 <H2>A Macro Programming Demonstration</H2>

 <!-- (D) Dynamo Script to Generate HTML -->
 <P>dynamoToday = 12/04/96 15:27:23

 <!-- (E) Dynamo Script to Generate JavaScript -->
 <!-- Code Generated by Example (E) -->
 <SCRIPT LANGUAGE="JavaScript">
 <!--
 alert ( "The Dynamo Document Name is 'simpleMacroDemo.stm'" );
 //-->
 </SCRIPT>

 <!-- (F) JavaScript to Generate HTML -->
 <SCRIPT LANGUAGE="JavaScript">
 <!--
 document.writeln
   ( "<P>javaScriptToday = "
       + javaScriptToday.toLocaleString() );
 //-->
 </SCRIPT>

 <!-- (G) Dynamo to JavaScript to HTML -->
 <!-- Code Generated by (G) -->
 <SCRIPT LANGUAGE="JavaScript">
 <!--
 document.writeln
   ( "<P>document.name = 'simpleMacroDemo.stm'<BR>" );
 document.writeln
   ( "<BR>document.referrer = '" + document.referrer + "'" );
 //-->
 </SCRIPT>

 <!-- (H) Dynamo to Dynamo -->
 <P>eval expression = 6.28318530717959

 <!-- (I) JavaScript to JavaScript -->
 <SCRIPT LANGUAGE="JavaScript">
 <!--
 eval
   ( "document.writeln "
   + "  ( \"<P>eval document.referrer = '\""
   + "    + document.referrer + \"'\" );" );
 //-->
 </SCRIPT>

 <!-- ... more Simple HTML Code -->
 </BODY>
 </HTML>

Figure 11: The Alert Box From Section (E)

Undisplayed Graphic

Figure 12: The Final Macro Demonstration Display

Undisplayed Graphic

What Is This Guy Doing?

All this talk of macro programming might seem out of place in an article entitled “Getting Started”, especially since the examples seem to be doing a lot of work for little benefit. After all, most applications don’t need to calculate pi-times-two at all let alone do it dynamically via eval().

The examples in Figures 9 and 10 were kept trivial for a reason: To show the syntax of macro programming without the added complexity of real-world application logic. But now it’s time for a dose of real-world and a good place to start is the monotony of form-based HTML and JavaScript coding.

Figure 13 shows a very simple HTML form in action. There are seven text fields with titles, two buttons, and judging from the alert() box showing there’s also JavaScript code that checks each input field to make sure it’s filled in. If you’ve ever worked with HTML forms then you know that even the simple ones are laborious to code and the addition of client-side validation logic makes it even more time-consuming.

Figure 13: A Simple Input Form

Undisplayed Graphic

The corresponding Dynamo Script is shown in Figure 14. Yes, there’s more Dynamo Script behind the scenes but it was written once and reused. The code in Figure 14 is the only new code required, and it only takes 9 function calls to do it all.

Figure 14: Define a Form in Dynamo Script

 <HTML>
 <TITLE>Test Field Macros</TITLE>
 <BODY BGCOLOR="#FFFFFF">
 <H3>Test Field Macros</H3>

 <!--SCRIPT
 import defineForm.ssc;
 defineForm ( "testFields", "testFieldsConfirm.ssc" );
 defineField ( "First Name", "firstName" );
 defineField ( "Last Name", "lastName" );
 defineField ( "Address Line 1", "address1" );
 defineField ( "Address Line 2", "address2" );
 defineField ( "Address Line 3", "address3" );
 defineField ( "Zip/Postal Code", "postalCode" );
 defineField ( "Phone", "phoneNumber" );
 generateForm();
 -->

 </BODY>
 </HTML>

When the Dynamo server interprets the code in Figure 14 it uses macro logic in defineForm() and the other functions to generate the JavaScript code and HTML tags shown in Figure 15. The generated HTML defines the <FORM> with its seven <INPUT> fields and two buttons. The generated JavaScript functions do the work of checking each field, displaying an error message and putting the cursor on the field in error.

Figure 15: The Generated JavaScript and HTML

 <HTML>
 <TITLE>Test Field Macros</TITLE>
 <BODY BGCOLOR="#FFFFFF">
 <H3>Test Field Macros</H3>

 <SCRIPT LANGUAGE="JavaScript">
 <!--
 function testFieldsIsOK ( aForm ) {
   if ( aForm.firstName.value.length == 0 ) {
     alert ( "\nPlease fill in the First Name field." );
     aForm.firstName.focus();
     return ( false );
   }
   if ( aForm.lastName.value.length == 0 ) {
     alert ( "\nPlease fill in the Last Name field." );
     aForm.lastName.focus();
     return ( false );
   }
   if ( aForm.address1.value.length == 0 ) {
     alert ( "\nPlease fill in the Address Line 1 field." );
     aForm.address1.focus();
     return ( false );
   }
   if ( aForm.address2.value.length == 0 ) {
     alert ( "\nPlease fill in the Address Line 2 field." );
     aForm.address2.focus();
     return ( false );
   }
   if ( aForm.address3.value.length == 0 ) {
     alert ( "\nPlease fill in the Address Line 3 field." );
     aForm.address3.focus();
     return ( false );
   }
   if ( aForm.postalCode.value.length == 0 ) {
     alert ( "\nPlease fill in the Zip/Postal Code field." );
     aForm.postalCode.focus();
     return ( false );
   }
   if ( aForm.phoneNumber.value.length == 0 ) {
     alert ( "\nPlease fill in the Phone field." );
     aForm.phoneNumber.focus();
     return ( false );
   }
   return ( true );
 }
 function submittestFields ( aForm ) {
     if ( ! testFieldsIsOK ( aForm ) ) return;
     document.testFields.submit();
     return;
 }
 //-->
 </SCRIPT>
 <FORM NAME="testFields" ACTION="testFieldsConfirm.ssc" METHOD="GET">
 First Name: <INPUT NAME="firstName" TYPE="text"><BR>
 Last Name: <INPUT NAME="lastName" TYPE="text"><BR>
 Address Line 1: <INPUT NAME="address1" TYPE="text"><BR>
 Address Line 2: <INPUT NAME="address2" TYPE="text"><BR>
 Address Line 3: <INPUT NAME="address3" TYPE="text"><BR>
 Zip/Postal Code: <INPUT NAME="postalCode" TYPE="text"><BR>
 Phone: <INPUT NAME="phoneNumber" TYPE="text"><BR>
 <INPUT TYPE="button" NAME="Submit" VALUE="Submit" onClick="submittestFields ( this.form )">
 <INPUT TYPE="reset" VALUE="Clear Fields">
 </FORM>

 <SCRIPT LANGUAGE="JavaScript">
 <!--
 document.testFields.firstName.focus();
 //-->
 </SCRIPT>

 </BODY>
 </HTML>

If you didn't believe that coding HTML forms was boring then Figure 15 should convince you. And remember, this is a simple form, many are much harder. So how was it generated? Figure 16 tells the story: It contains the code called from Figure 14 to produce Figure 15.

Figure 16: A Form Generator in Dynamo Script

 <!--SCRIPT defineForm.ssc

 var formName;
 var formAction;
 var fieldUpperBound;
 var fieldTitle;
 var fieldName;
 var i;

 function defineForm ( aFormName, aFormAction ) {

   // Start saving data about a new form.
   formName        = aFormName;
   formAction      = aFormAction;
   fieldUpperBound = -1;
 }

 function defineField ( aFieldTitle, aFieldName ) {

   // Save data about another field in the current form.
   fieldUpperBound++;
   fieldTitle [ fieldUpperBound ] = aFieldTitle;
   fieldName  [ fieldUpperBound ] = aFieldName;
 }

 function generateForm() {

   // Write a JavaScript header.
   document.writeln
     ( "<SCRIPT LANGUAGE=\"JavaScript\">\n"
     + "\<\!\-\-" );

   // Write the <formName>IsOK function header.
   document.writeln
     ( "function "
     + formName
     + "IsOK ( aForm ) {" );

   // Write the individual field check logic.
   for ( i = 0; i <= fieldUpperBound; i++ ) {
     document.writeln
       ( " if ( aForm."
       + fieldName [ i ]
       + ".value.length == 0 ) {\n"
       + " alert ( \"\\nPlease fill in the "
       + fieldTitle [ i ]
       + " field.\" );\n"
       + " aForm."
       + fieldName [ i ]
       + ".focus();\n"
       + " return ( false );\n"
       + " }" );
   }

   // Write the <formName>IsOK function trailer.
   document.writeln
     ( " return ( true );\n"
     + "}\n" );

   // Write the submit<formName> function.
   document.writeln
     ( "function submit"
     + formName
     + " ( aForm ) {\n"
     + " if ( ! "
     + formName
     + "IsOK ( aForm ) ) return;\n"
     + " document."
     + formName
     + ".submit();\n"
     + " return;\n"
     + "}\n" );

   // Write a JavaScript trailer.
   document.writeln
     ( "\/\/\-\->\n"
     + "</SCRIPT>\n" );

   // Write the HTML form header tag.
   document.writeln
     ( "\<FORM NAME=\""
     + formName
     + "\" ACTION=\""
     + formAction
     + "\" METHOD=\"GET\"\>" );

   // Write the individual HTML field tags.
   for ( i = 0; i <= fieldUpperBound; i++ ) {
     document.writeln
       ( fieldTitle [ i ]
       + ": \<INPUT NAME=\""
       + fieldName [ i ]
       + "\" TYPE=\"text\"\>\<BR\>" );
   }

   // Write the HTML submit button tag.
   document.writeln
     ( "<INPUT TYPE=\"button\" NAME=\"Submit\""
     + " VALUE=\"Submit\""
     + " onClick=\"submit"
     + formName
     + " ( this.form )\"\>" );

   // Write the HTML reset button tag.
   document.writeln
     ( "\<INPUT TYPE=\"reset\""
     + " VALUE=\"Clear Fields\"\>" );

   // Write the HTML form trailer tag.
   document.writeln
     ( "\<\/FORM\>\n" );

   // Write a JavaScript header.
   document.writeln
     ( "<SCRIPT LANGUAGE=\"JavaScript\">\n"
     + "\<\!\-\-" );

   // Write the JavaScript code to position the cursor.
   document.writeln
     ( "document."
     + formName
     + "."
     + fieldName [ 0 ]
     + ".focus();" );

   // Write a JavaScript trailer.
   document.writeln
     ( "\/\/\-\->\n"
     + "</SCRIPT>\n" );
 }
 -->

The two functions defineForm() and defineField() store information about the form and its fields in Dynamo variables and arrays. This is necessary because two separate sections of code have to be generated in one pass, JavaScript and HTML. That's what generateForm() does: It takes the information gathered in the arrays and spits out first the JavaScript functions and then the HTML <FORM>-related tags. And as a final friendly act it generates a bit of JavaScript to put the cursor on the first input field so the user can start typing as soon as the form appears.

Except for all the strange strings and escape characters the code in Figure 16 is fairly straightforward. That's good, because a real form generator should give the programmer more control over design and layout. It should allow for check boxes, radio buttons and other kinds of fields as well as text input, and it should permit different fields to have different kinds of validation checks. And, of course, the world is crying out for the HTML equivalent of PowerBuilder's DropDownDataWindow.


[Home] [Back to Tip 73] [Forward to Tip 75] [Archives]
     
[mail to: bcarter@bcarter.com]