Jump to content

Building Dynamic Web Sites:Part V: Difference between revisions

From EDM2
Created page with "By Chris Wenham '''Summary:''' Learn how to create a web catalog by importing your information from a database or spreadsheet program. Last month I showed you how to create..."
 
Ak120 (talk | contribs)
mNo edit summary
 
(6 intermediate revisions by 2 users not shown)
Line 1: Line 1:
By [[Chris Wenham]]
{{Building Dynamic Web Sites}}
''By [[Chris Wenham]]''


'''Summary:''' Learn how to create a web catalog by importing your information from a database or spreadsheet program.
==Widgets and Macros==
In the latest releases of [[PPWizard]] - arguably now the most powerful pre-processor for HTML, Rexx, INF or otherwise - there have been a lot of improvements that make it extremely easy to add what web developers drool over: widgets.


Last month I showed you how to create a simple "poor man's database" that was used to generate a catalog web site, one that could be used in an e-commerce site or "Web storefront." The database wasn't really a very practical one, as its "format" was very ad-hoc and consisted mostly of embedding commands for the HTML preprocessor into the data itself. Not very elegant, and not very editable. If you had a catalog with hundreds of items, the database file could get extremely unwieldy in an ordinary text editor. What we really need is the ability to import from a real database.
You've probably seen a few crop up here in the pages of OS/2 e-Zine! as I play with this program myself. The most recent are the improved screenshot links that include a button for optionally viewing the screenshot in a pop-up JavaScript window, but omit that button from the Printer-Friendly version to help save ink and make life easier for Lynx users. These links are created by a macro that PPWizard interprets, and while all I do is give the name of the screenshot's file and the text to link it with, the macro figures out 1) the file's size, rounded to the nearest K; 2) the file type; 3) the image's dimensions; and 4) the Javascript code to open the pop-up window. These are what I call labour saving devices for webmasters, and here I'm not only going to teach you how to make your own, I'm also going to give away a few e-Zine! trade secrets.


Luckily this is easier than it may seem. Most database programs for OS/2 can export to a comma or tab delimited format and those are a piece of cake to work with. In fact, PPWizard has an #import function that does just this.
==What is a Macro?==
A macro, in PPWizard terms, is a lot like the functions you might write in C, Java or some other programming language. It's an encapsulated portion of code that works almost autonomously and accepts parameters to alter its behaviour. Here's an example of a simple one that creates an e-mail link:<pre><nowiki>
#define Email <a href="mailto:{$address}">{$address}</a>
</nowiki></pre>
In your web pages you could then call the macro like this:<pre><nowiki>
<$Email address="feedback@os2ezine.com">
</nowiki></pre>
And after "compiling" the page with PPWizard, it would produce a functioning link like this:
feedback@os2ezine.com
If you've been reading the Dynamic Web Sites series so far, you'll notice the standard convention for calling #defined variables (embed the variable's name in a tag, preceded by a dollar sign, like this "<$variable_name>"). You'll also notice a new one, where curly brackets were used instead of pointed ones. In our example, this was "{$address}". The curly brackets tell PPWizard to look for a parameter with that same name. Of course, you can name parameters anything you like, and you can have as many as you like.


==#import==
You can also make a parameter optional by telling the macro to give it a default value. For example, let's say we use the "feedback@os2ezine.com" address all the time, but also occasionally use other addresses in our web pages. For convenience, we'd like every <$Email> tag to point to the feedback address by default, but we'd also like to override that. Here's how you'd do it:<pre><nowiki>
#define Email <a href="mailto:{$address='feedback@os2ezine.com'}>{$address}</a>
</nowiki></pre>
In between the curly brackets, after naming the parameter, we added an equals sign and gave it a default value: our feedback address. As long as you give a parameter a default value at least once at the beginning of the macro, PPWizard will use that default everywhere else in the same macro. That's why we only had to type the feedback address in once, even though we used the {$address} tag a second time.


This function is one of the most complex and powerful in PPWizard's set. By default, the command will read a comma delimited, tab delimited and fixed-column-width file and format the contents it finds into a table - the most obvious structure for what is essentially data in tabular form. For example, say you had a comma delimited file called staff.csv that looked a bit like this:
Now, all we have to do to insert our feedback address anywhere in a web page is type:
<$Email>
And PPWizard, once run, will resolve it to a complete and functioning link that looks like this in a browser:
feedback@os2ezine.com
But if we wanted to override the default with a different address, it's easy. We type this in our web page's source:
<$Email address="editor@os2ezine.com">
And PPWizard resolves it to this:
editor@os2ezine.com
Correctly linked, simple and easy.


Chris Wenham,Editor-In-Chief,chris@os2ezine.com
But what makes Macros really show their power is when you start treating them as fully programmable objects. Imagine what my problem was: I had to add links to a lot of screenshots in every issue of OS/2 e-Zine! The traditional way called for me to look up the screenshot's filename, go back to the HTML document, paste it in, go back and find it's file size, go back to the HTML document and paste that in, type the file's extension in the little parenthesis, and type the "<A HREF>" business to make it link properly. Boring stuff. So I wrote a macro to do it for me, one which only asks for two parameters: The screenshot's file name and the text to link to it with. The call, in the body of the "uncompiled" article, looks a bit like this:
  Chris Wright,Senior Editor,wright@dtcweb.com
  <$Screenshot shot="screen1.gif" text="This is a sample screenshot">
And when "compiled" with PPWizard it looks like this:


And imported it into a web page with this line:
This is a sample screenshot


#import staff.csv CMA '' "Name" "Position" "Email"
[[Image:BuildDyn-5-screen1.gif]]


Then it would generate the code for a table that looks like this:
When it came to writing the macro itself I started with the simplest functionality:
#define Screenshot <a href="{$shot}">{$text}</a>
All that would do is link the image to the text and is barely worth getting excited about. But I still had all those trips I had to make back and forth between a directory listing and the file I was editing. So I started building and expanded the macro to this:
<code>
#define Screenshot \
        #evaluate+ rc "SysFileTree('{$Shot}', 'hh_Tree', 'F')"  -\
        #evaluate '' "Parse var hh_tree.1 hh_date hh_time hh_size remains"  -\
        #evaluate+ hh_size "Left( hh_size + 500, length( hh_size) - 3)"  -\
        ;--- Supply the standard link -------------------------------  -\
        <a href="{$shot}">{$text}</a>  -\
        ;--- Label it with the file size ----------------------------  -\
        (<$hh_size>K)
</code>
I've got some explaining to do. First of all, the "dash-slashes" ( -\ ) at the end of each line tell PPWizard that the macro is continued on the next line. Otherwise it'd assume the macro ended before we got to the first #evaluate line. PPWizard doesn't yet have any "Begin/End" pairs that you find in other languages for marking the boundries of functions and macros.


Name         Position       Email
Secondly, the #evaluate statements tell PPWizard to execute a line of Rexx code. They take the following syntax:
  Chris Wenham Editor-In-Chief        chris@os2ezine.com
  #evaluate name_of_variable_to_store_results_in "Rexx code to run"
Chris Wright Senior Editor       wright@dtcweb.com
The variable that you store the results in will be a PPWizard variable, not a Rexx variable. There is a difference!


It's quite simple to see how PPWizard mapped the names of the fields with the records in the staff.csv by taking them in the order in which they were named on the #import line. As it turns out, you have the power to rearrange the order of these columns as you please, but we won't be covering that this week.
What we were doing in those three #evaluate lines was this:
# Use the SysFileTree function to get the directory listing of the screenshot in question.
# Use the PARSE function to separate the date, time and size that are included in that directory listing
# Concerning ourselves with the size only, we add 500 to it, then throw away the last three digits. What does that do? It rounds the file-size up or down to the nearest K. If it was 16,600 bytes, for example, adding 500 to the value would bump it up to "17,100". Dropping the last three digits then leaves us with just "17". If it was 16,499 bytes or lower, adding 500 would have brought the total to 16,999 and the macro would be left with "16" after dropping the last three digits. It's a simple way of rounding up or down to the nearest K. You can do away with all this mathematical gymnastics if you like and just drop the last three digits - always rounding down every time. Simply delete the "+ 500" bit.  


Looking at the #import line itself, you see that after the filename of the file to import there's a keyword "CMA." This tells PPWizard that it's importing a CoMmA separated file. Other keywords are "TAB" for tab delimited files (good if some of your records have commas in their data) and "FIX" for fixed width files. Check the PPWizard manual, because additional format support may have been added by the time you read this. There's also the option to specify the delimiter yourself, so if you used semicolons instead of commas, PPWizard will know what to look for.
I should point out that this rounding mechanism is only as simple as it is because Rexx can interchangeably treat variables as strings of characters, or as numbers; even in the same line. At the beginning we treat it as a number by adding 500 to it. But then we're suddenly treating it as a string of characters again; measuring its length in digits and dropping the last three with the LEFT function. This is not always something you can get away with in other programming languages.


If you put a minus sign after the file type keyword, such as "CMA-" or "TAB-" then PPWizard will ignore the first line it finds in the file - assuming it's probably where the database had inserted the names of the fields rather than the first actuall record.
There's a comment just after the #evaluate lines. PPWizard ignores any line that begins with a semi-colon, so we use it to stick in a reminder. The line just after it inserts a simple link to the screenshot.


It's easy to change the way the table looks, because PPWizard stores its defaults in variables you can override with the #define command. For example, say we put these two lines before the #import statement:
The next line inserts our rounded file size in the parenthesis, appending it with the letter "K" so the reader knows what kind of measurement it is. As it's the last line of the macro, we don't put a "dash-slash" ( -\ ) at the end of it.


<PRE>
The code to put the file type (".GIF") in the parenthesis too was even easier, just grab the last 4 characters of the file name. In addition, I also used one of PPWizard's built-in functions called GetImageWidthHeight which, after passing it the filename of a GIF or JPG image, will return the "WIDTH=xxx HEIGHT=xxx" parameters that you can put in an <IMG> tag. But in this case, I used it to size the JavaScript pop-up window instead. It's a handy alternative to jumping back and forth between your HTML editor and PMView just to get an inline image's tag right.
#define IMPORT_TABLE_ATTRIBS BORDER=1 CELLSPACING=2
#define IMPORT_RECORD <TR><TD ALIGN=CENTER>{$Column1} \
  <TD ALIGN=CENTER>{$Column2} \
  <TD ALIGN=CENTER><a href="mailto:{$Column3}">{$Column3}</a></TR>
</PRE>


(The backslashes "\" tell the preprocessor that the #define statement is continued on the next line)
This final version of the multi-purpose, widget-enhanced screenshot-linking macro with the pop-up JavaScript windows is included in the ZIP file attached to this article. It also includes the e-mail macro and an "easy peasy" image macro that not only figures out the picture's dimensions by itself, but also sets a default (and override-able) ALT and ALIGN tag. There's a sample web page in there that uses all the tags too, so you can easily see how to use them in your own pages.


PPWizard would then generate a table that looks like this:
Download the source for this week's article: [http://www.os2ezine.com/v4n3/dws.zip dws.zip (53K)]


Name         Position         Email
;PPWizard:by Dennis Bareis
Chris Wenham Editor-In-Chief chris@os2ezine.com
:download from Dennis Bareis' Homepage (263K)
Chris Wright Senior Editor         wright@dtcweb.com
:Registration: Freeware


Not only was the border and cell spacing changed, but the e-mail addresses are now properly hyperlinked. We just told PPWizard to format records differently than the default settings specify. There are several other defaults that can be overridden, ones that can switch off the formation of tables altogether. It's these that we're going to use when creating a better version of the "Catalog Maker" from last month.
[[Category:OS/2 e-Zine article]]
 
==Making #import act like a conversion utility==
 
We could settle for making our web catalog take the form of a boring table, but we're not. Remember that makeshift "poor man's database" format from last month? It's actually pretty good for making PPWizard create all the files for us, but it really only should have been an intermediate format, a temporary work file that gets thrown away. What we need to do is convert the easily manageable and exportable CSV format into our "poor man's database" format and keep the same templates from last month.
 
To do this we're going to make the preprocessor eat its own lunch, in effect. First we make it create a poor man's database, then we make it use it. Take a look at the following code, stored in a file called convert.it, and you'll see that we're tricking PPWizard into writing "#define" statements instead of finished HTML code. We'll then make it read back those #define statements that it just generated, using them to build our catalog pages.
 
 
<PRE>
;Lets create and start writing to a new file
#output database.it AsIs
 
;Clear all the defauts used to define a table's HTML code
#define IMPORT_BEFORE
#define IMPORT_AFTER
#define IMPORT_HEADER
 
;Create "#define" statements for each record
#define IMPORT_RECORD <?hash>define+ File {$Column1}<?NewLine> \
  <?hash>define+ Name {$Column2}<?NewLine> \
  <?hash>define+ Materials {$Column3}<?NewLine> \
  <?hash>define+ Description {$Column4}<?NewLine> \
  <?hash>define+ Picture {$Column5}<?NewLine> \
  <?hash>define+ Price {$Column6}<?NewLine> \
  <?hash>include item.it<?NewLine>
 
;Import the tab delimited file with the database contents
#import catalog.csv CMA '' "File" "Name" "Mat" "Desc" "Pic" "Price"
 
;Close the file
#output
</PRE>
 
It assumes there's a file called catalog.csv, looking a bit like the "staff.csv" of earlier, but which contains our catalog of goods instead. Notice the "<?hash>" and "<?NewLine>" tags. These are built-in to the preprocessor and are substituted with the hash character ("#") and a carriage return respectfully. They had to be referenced this way so that PPWizard wouldn't try to interpret the line before we're ready.
 
The IMPORT_BEFORE variable used to contain the "<TABLE BORDER=1 CELLSPACING=2>" line that started the HTML code for a table. But we cleared it so it won't try to create a table where we don't want one. We also cleared a few others, then redefined the IMPORT_RECORD variable so that instead of putting the data from the imported file into table cells, it's placed after a "#define+" line instead.
 
(By the way, after last month's column, Dennis Bareis -- author of PPWizard -- pointed out that if you use "#define+" instead of plain "#define", you won't get any warnings when the variables are redefined a moment later by the next database record. He also pointed out a couple of other good tips, which you'll see later)
 
When you run the command "PPWizard convert.it" on the command line, a file called database.it is generated. It's contents will look a bit like this:
 
<PRE>
#define+ File item1
#define+ Name Deluxe Ball Point Pen
#define+ Materials Oak, Paduk, Bubigna, Cherry
#define+ Description A fine writing implement.
#define+ Picture ballpen.gif
#define+ Price $79.95
#include item.it
 
#define+ File item2
#define+ Name Elegant Fountain Pen
#define+ Materials Oak, Chak-De-Koke, Paduk, Bloodwood
#define+ Description A magnificent compliment to your desk.
#define+ Picture fountpen.gif
#define+ Price $99.95
#include item.it
</PRE>
 
(Don't worry if there are spaces before some of the #define+ lines, this won't hurt the next step)
 
You should recognize this format from last month (with a few changes as per Dennis's suggestion; the #output and <p> lines got moved into item.it). But this time, it wasn't you who created it directly, it was created by PPWizard.
 
Taking the contents page from last month we make a slight change to the HTML code, making it look like this:
 
;Make PPWizard convert from a CSV database to a "#define" file
#include convert.it
 
 
<PRE>
 
<HTML>
<HEAD>
<TITLE>Frank's World Of Handcrafted Goods</TITLE>
</HEAD>
<BODY>
 
<H1>Frank's World Of Handcrafted Goods</H1>
 
<P>Choose from our wide range of quality handcrafted goods!
 
<ul>
;Make PPWizard now include the file that it generated earlier
#include database.it
</ul>
 
<p>Please make checks and money orders payable to:
Frank's World Of Handcrafted Goods.
<br>Mail your orders to:
Frank, 187 Hancrafted Way, Woodtown, NY, 12345
or phone (555)555-2624
<br>E-mail frank@frankcrafts.com
 
</BODY>
</HTML>
 
 
</PRE>
At the top is the #include line that starts PPWizard working on converting the CSV file you exported from your database into an intermediate, throwaway format that drives the production of all the separate catalog pages. In between the Unordered List tags (<ul>) is the line to read back the file PPWizard had just finished creating earlier. In that file is the data and the commands needed to create the remaining catalog pages. To give you an idea of what all this mumbo jumbo produces, here is an example web site created using the source code from this month's column.
 
The data for it was stored in a Lotus Approach database, then exported into a Comma Separated Value file. By typing "PPWizard contents.it" on the command line (something you can create a desktop icon for, to do the job even faster), this exported file was sucked in, mulched, and spat out as a series of finished web pages ready to go up. Since the original data was stored in Approach, it was easy to create many more records than last month's example. It was also easier to sort and edit these records.
 
This example is also not typically how databases are leveraged onto the web. Most companies with large and relational databases will make use of an SQL server (Standard Query Language). But so many principles are still shared. Once the data is read, it's usually positioned into the HTML code using a means similar to ours: a special tag is embedded into the web page code and the web server substitutes it with the real data a second before it's served to the browser. Serving data through SQL is something I may be tackling in the future, just as soon as I figure it out myself.
 
In Part V of Building Dynamic Web Sites In OS/2 I'll be showing you how to make conditional statements, how to modify text on the fly, and even how to execute Rexx code in the middle of a web page.
 
[[Category:Scripting Articles]]

Latest revision as of 01:21, 15 April 2018

Building Dynamic Web Sites
Part: I II III IV V

By Chris Wenham

Widgets and Macros

In the latest releases of PPWizard - arguably now the most powerful pre-processor for HTML, Rexx, INF or otherwise - there have been a lot of improvements that make it extremely easy to add what web developers drool over: widgets.

You've probably seen a few crop up here in the pages of OS/2 e-Zine! as I play with this program myself. The most recent are the improved screenshot links that include a button for optionally viewing the screenshot in a pop-up JavaScript window, but omit that button from the Printer-Friendly version to help save ink and make life easier for Lynx users. These links are created by a macro that PPWizard interprets, and while all I do is give the name of the screenshot's file and the text to link it with, the macro figures out 1) the file's size, rounded to the nearest K; 2) the file type; 3) the image's dimensions; and 4) the Javascript code to open the pop-up window. These are what I call labour saving devices for webmasters, and here I'm not only going to teach you how to make your own, I'm also going to give away a few e-Zine! trade secrets.

What is a Macro?

A macro, in PPWizard terms, is a lot like the functions you might write in C, Java or some other programming language. It's an encapsulated portion of code that works almost autonomously and accepts parameters to alter its behaviour. Here's an example of a simple one that creates an e-mail link:

 #define Email <a href="mailto:{$address}">{$address}</a>

In your web pages you could then call the macro like this:

 <$Email address="feedback@os2ezine.com">

And after "compiling" the page with PPWizard, it would produce a functioning link like this:

feedback@os2ezine.com

If you've been reading the Dynamic Web Sites series so far, you'll notice the standard convention for calling #defined variables (embed the variable's name in a tag, preceded by a dollar sign, like this "<$variable_name>"). You'll also notice a new one, where curly brackets were used instead of pointed ones. In our example, this was "{$address}". The curly brackets tell PPWizard to look for a parameter with that same name. Of course, you can name parameters anything you like, and you can have as many as you like.

You can also make a parameter optional by telling the macro to give it a default value. For example, let's say we use the "feedback@os2ezine.com" address all the time, but also occasionally use other addresses in our web pages. For convenience, we'd like every <$Email> tag to point to the feedback address by default, but we'd also like to override that. Here's how you'd do it:

 #define Email <a href="mailto:{$address='feedback@os2ezine.com'}>{$address}</a>

In between the curly brackets, after naming the parameter, we added an equals sign and gave it a default value: our feedback address. As long as you give a parameter a default value at least once at the beginning of the macro, PPWizard will use that default everywhere else in the same macro. That's why we only had to type the feedback address in once, even though we used the {$address} tag a second time.

Now, all we have to do to insert our feedback address anywhere in a web page is type:

<$Email>

And PPWizard, once run, will resolve it to a complete and functioning link that looks like this in a browser:

feedback@os2ezine.com

But if we wanted to override the default with a different address, it's easy. We type this in our web page's source:

<$Email address="editor@os2ezine.com">

And PPWizard resolves it to this:

editor@os2ezine.com

Correctly linked, simple and easy.

But what makes Macros really show their power is when you start treating them as fully programmable objects. Imagine what my problem was: I had to add links to a lot of screenshots in every issue of OS/2 e-Zine! The traditional way called for me to look up the screenshot's filename, go back to the HTML document, paste it in, go back and find it's file size, go back to the HTML document and paste that in, type the file's extension in the little parenthesis, and type the "<A HREF>" business to make it link properly. Boring stuff. So I wrote a macro to do it for me, one which only asks for two parameters: The screenshot's file name and the text to link to it with. The call, in the body of the "uncompiled" article, looks a bit like this:

<$Screenshot shot="screen1.gif" text="This is a sample screenshot">

And when "compiled" with PPWizard it looks like this:

This is a sample screenshot

When it came to writing the macro itself I started with the simplest functionality:

#define Screenshot <a href="{$shot}">{$text}</a>

All that would do is link the image to the text and is barely worth getting excited about. But I still had all those trips I had to make back and forth between a directory listing and the file I was editing. So I started building and expanded the macro to this:

#define Screenshot \
        #evaluate+ rc "SysFileTree('{$Shot}', 'hh_Tree', 'F')"  -\
        #evaluate  "Parse var hh_tree.1 hh_date hh_time hh_size remains"  -\
        #evaluate+ hh_size "Left( hh_size + 500, length( hh_size) - 3)"  -\
        ;--- Supply the standard link -------------------------------  -\
        <a href="{$shot}">{$text}</a>  -\
        ;--- Label it with the file size ----------------------------  -\
        (<$hh_size>K)

I've got some explaining to do. First of all, the "dash-slashes" ( -\ ) at the end of each line tell PPWizard that the macro is continued on the next line. Otherwise it'd assume the macro ended before we got to the first #evaluate line. PPWizard doesn't yet have any "Begin/End" pairs that you find in other languages for marking the boundries of functions and macros.

Secondly, the #evaluate statements tell PPWizard to execute a line of Rexx code. They take the following syntax:

#evaluate name_of_variable_to_store_results_in "Rexx code to run"

The variable that you store the results in will be a PPWizard variable, not a Rexx variable. There is a difference!

What we were doing in those three #evaluate lines was this:

  1. Use the SysFileTree function to get the directory listing of the screenshot in question.
  2. Use the PARSE function to separate the date, time and size that are included in that directory listing
  3. Concerning ourselves with the size only, we add 500 to it, then throw away the last three digits. What does that do? It rounds the file-size up or down to the nearest K. If it was 16,600 bytes, for example, adding 500 to the value would bump it up to "17,100". Dropping the last three digits then leaves us with just "17". If it was 16,499 bytes or lower, adding 500 would have brought the total to 16,999 and the macro would be left with "16" after dropping the last three digits. It's a simple way of rounding up or down to the nearest K. You can do away with all this mathematical gymnastics if you like and just drop the last three digits - always rounding down every time. Simply delete the "+ 500" bit.

I should point out that this rounding mechanism is only as simple as it is because Rexx can interchangeably treat variables as strings of characters, or as numbers; even in the same line. At the beginning we treat it as a number by adding 500 to it. But then we're suddenly treating it as a string of characters again; measuring its length in digits and dropping the last three with the LEFT function. This is not always something you can get away with in other programming languages.

There's a comment just after the #evaluate lines. PPWizard ignores any line that begins with a semi-colon, so we use it to stick in a reminder. The line just after it inserts a simple link to the screenshot.

The next line inserts our rounded file size in the parenthesis, appending it with the letter "K" so the reader knows what kind of measurement it is. As it's the last line of the macro, we don't put a "dash-slash" ( -\ ) at the end of it.

The code to put the file type (".GIF") in the parenthesis too was even easier, just grab the last 4 characters of the file name. In addition, I also used one of PPWizard's built-in functions called GetImageWidthHeight which, after passing it the filename of a GIF or JPG image, will return the "WIDTH=xxx HEIGHT=xxx" parameters that you can put in an <IMG> tag. But in this case, I used it to size the JavaScript pop-up window instead. It's a handy alternative to jumping back and forth between your HTML editor and PMView just to get an inline image's tag right.

This final version of the multi-purpose, widget-enhanced screenshot-linking macro with the pop-up JavaScript windows is included in the ZIP file attached to this article. It also includes the e-mail macro and an "easy peasy" image macro that not only figures out the picture's dimensions by itself, but also sets a default (and override-able) ALT and ALIGN tag. There's a sample web page in there that uses all the tags too, so you can easily see how to use them in your own pages.

Download the source for this week's article: dws.zip (53K)

PPWizard
by Dennis Bareis
download from Dennis Bareis' Homepage (263K)
Registration: Freeware