deprecated has asked for the wisdom of the Perl Monks concerning the following question:

I am writing a small suite of standalone applications for the back end of a client I am working with right now. The front end of the site is very extensive, and totally non-portable because it has grown organic over a period of years. Sort of like a big ecosystem. Pull a script out and it dies unless you take its liver (filesystem), kidneys (associated shell scripts), heart (symlinks), and so on with it. So these applications are being built to withstand the test of (more) time, and should be highly portable, as well as modular so that re-use is possible, and programmer time is spent more effectively.

So I actually have written highly portable code that works on any of our servers, through any of the clients looking at it, and does what I need it to do.

The problem is I have written code that does not have a pretty interface, and no provisions therein.

Here's an overview of how stuff is currently done:

======== ============== = = perl = javascript = = HTML = <------- cgi <-------============== = = = html = ======== ============== ^ | | ============== = oracle = ==============

When the url is requested, the perl program answers. The output in html is essentially a composite of three things. First, you have the oracle data. So, say we have "name" and "address". You also have an HTML template so that the web design people can just create a page look-and-feel. However, if you want to be able to provide names and addresses for people in hawaii, alaska, new york, it might be nice to be able to have palm trees, sky scrapers (or rude people, ymmv), and snow as a theme, depending upon which user you are sending data to. The javascript allows us to create interface-specific stuff that might be difficult to do in perl/html (that was not my call, and isnt up for discussion).

The challenge thus, is to be able to have perl programs that run independantly of the database, and still provide them with a uniform style. Javascript is not necessary. Images and tables may well be. You have perl content that needs to be displayed in a fashion that is configurable to some extent by the users (after all, it is their interface), and also configurable by the site/application owner.

Take this for example:

sub enter_data { print start_form, textarea( -name => 'name', -default => 'Smith, John' ), end_form; return 1; }
Do we then extrapolate from the above that we can do:
sub be_pretty { print img( -src => '/img/purdy.png' ), br(), img( -src => '/img/splashlogo.png' ); } be_pretty(); enter_data();
But what about more complicated schemes, like having a top logo bar and a left navigation bar, and a footer, and having your form in the middle? Because HTML is highly linear, i.e., it renders top-to-bottom, left-to-right, its not possible to paint the page and then add a form smack in the middle (well, at least not without frames, and nuh-uh, no frames on this 'ere site).

So, what, then, is the best way to allow for stylistic changes and a "graphical" side of your average perl cgi? Or, perhaps that is an open-ended question I should tie down a little. What ways have you used and which ones were successful? Not successful? Any other insights?

brother dep.

--
Laziness, Impatience, Hubris, and Generosity.

Replies are listed 'Best First'.
Re: Creating Stylized Perl Applications With Uniformity (code)
by Masem (Monsignor) on May 30, 2001 at 18:40 UTC
    HTML::Template, Template Toolkit, HTML::Mason are the solutions that you need.

    If you use these templating solutions correctly, then most of your CGI scripts will consist of 4 parts:

    1. State checking/de-tainting of input variables from the CGI via perl
    2. Data collection via perl, using DBI or whatever other sources are needed
    3. Data processing via perl, translating from any internal storage forms to something that is nearly readable.
    4. HTML output via a template solution, passing data from perl into the template.
    This provides the sufficient distinction to avoid mixing HTML and logic that can sometimes bog you down. Once you know your logic for steps 1-3 are in place, you can then tackle the template problem.

    Most of the template solutions allow you to include other template pieces to provide consistent elements such as button bars, banner ads, and the like. They also allow you to maintain some style across pages (though you should use CSS for this).

    Most of my scripts that I have right now, save for start/end_form, and submit buttons, have no CGI.pm's HTML functions in them, instead relying on TT2 for all output. The only reason I keep the form and submit buttons in the script is that I can keep the persistent state CGI variable and the appropriate values for the submit buttons in the same place; what happens in the HTML output otherwise doesn't affect the CGI logic.


    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
Re: Creating Stylized Perl Applications With Uniformity (code)
by merlyn (Sage) on May 30, 2001 at 18:36 UTC
Re: Creating Stylized Perl Applications With Uniformity (code)
by cacharbe (Curate) on May 30, 2001 at 19:38 UTC
    Another choice would be to transfer data in xml and establish XSL based on (insert your list of variables here) to be implmented on the server or the browser (YMMV). This would allow the data to be in some generic form, and display functionality determined by content.

    Just a quick thought.

    C-.

      <shameless_plug>
      I posted a tutorial on this very thing:
      DBIx::XML_RDB Tutorial
      </shameless_plug>

      Jeff

      R-R-R--R-R-R--R-R-R--R-R-R--R-R-R--
      L-L--L-L--L-L--L-L--L-L--L-L--L-L--
      
Re: Creating Stylized Perl Applications With Uniformity (code)
by DBX (Pilgrim) on May 30, 2001 at 22:40 UTC
    I am working on a very similar type of system now and I have settled on HTML::Template (thanks to the advice of some fellow monks). Besides being relatively fast and simple, it allows you to filter a template before variables are replaced in case you need to do some extra style changes. Although, depending on your system, you could leave a placeholder for javascript and either "include" the file or build up your javascript as a string and replace the "var" with it. Another thing I am doing that might help is build your system as an object-oriented system with an abstract base class. Then you can override functions for specific uses. For example, you can override a default "OutputStyle" routine with a package that inherits from the base module if you need to show palm trees, snow, etc. If your derived class doesn't have its own specific "OutputStyle" routine, the user still gets the default output. Hope that helps.
Re: Creating Stylized Perl Applications With Uniformity (code)
by larryk (Friar) on May 31, 2001 at 00:27 UTC
    My work uses CGI::FastTemplate and I found it easy to pick up. You can create multiple templates and nest them indefinitely - eg. a table template which contains 5 different row templates which in turn contain many different cell templates - and all of these can be pulled in on the fly so the Perl will control the logic and the designers can control the look and feel without having to touch your code (I mean "without you _letting_ them touch your code", obviously :-).

    If you want to know any more, feel free to give me a shout. I'll be happy to fill in any gaps I have made in this description.

    "Argument is futile - you will be ignorralated!"

Re: Creating Stylized Perl Applications With Uniformity (code)
by novitiate (Scribe) on May 31, 2001 at 01:20 UTC
    dear brother,

    style sheets may be what you are in need of -- as long as you can ensure some relatively new browsers.
    portable html should really have styles and visual effects separated from the structural
    hence, xml.

    humbly,
    novitiate
      First, a quick response to the simple case. You have a relatively complex page into which you want to drop a small amount of data. A quick and dirty way is to create the full html page and insert pipe marks or other keywords where you want the data to go. Your Perl program then slurps up this html template, replaces the text, and prints it out. Perhaps you want to split the template into parts, separated by those pipe marks. Then you can print out the different parts in the order you like, possibly after modification. This would let you be able to see in Netscape the entire page and have a non-engineer modify it easily.

      #!/usr/bin/perl -w use strict; $|=1; my $formbuf=<<'OKAY'; This is a | test template ||| you like? OKAY my @parts = &GetMultipartTemplate($formbuf); print "$_. ",length($parts[$_])," $parts[$_]\n" for (0..$#parts); # test output sub GetMultipartTemplate { # Returns pipe-separated parts of a form # Usage: @parts = GetMultipartTemplate($formbuf); my @t = split(/\|/, shift); return @t; # yes returning a reference is better.. }
      For the nontrivial case, I cannot give you a full answer but rather some points from experience. It is likely that many people end up inventing the same things over and over, but when using preprepared modules you usually give up flexibility in some way so there is always a tradeoff.

      In my experience the most important thing is to try and get as complete as possible an idea of what you are trying to do and what you may be asked to do in the future, so you don't for example build a weak authentication architecture, and have to revamp everything.

      If you are thinking portability realize this could mean moving to servers running different OS's, with different installation permissions, and maybe in different languages.

      If you are thinking of localizing into other languages (particularly two-byte languages like Japanese) you may want to test whatever solution you use first. Some encoding systems might not work well in embedded perl code, for example Japanese Shift Jis (SJIS) is like binary and will once in a while break a Perl script. If you can change encoding on the fly in that case (e.g. convert 7-bit EUC to 8-bit SJIS) you will be okay. Incidentally the above example will not always work with SJIS, since some two-byte characters include the same value as a pipe mark. So splitting by a multibyte value is better. Recently a Japanese programmer didn't believe it when I told him so until he tried to figure out some code didn't work.

      Also, consider how dynamic your site's basic templates will be, for example do you have a menu which highlights differently depending on which section you go to. I've tried both programmatic ways and the "let the designer handle it" ways, and maybe the above templating solutions will help. You will need to train your team and produce a document so that people who come along in the future don't break something or continually bug you to train them too. Also think about what schedule and volume of updates will be needed, and whether they will be primarily design or functionality related.

      One interesting strategy I found once was with a site that had no database engine, and I built a system called Magic Hands to generate programmatically a thousand static pages of layouts including little idiosyncracies. The system also uses Gimp from Perl to do a good deal of automatic resizing, thumbnail creation, and composition with frames and shadows, i.e. alpha masking. For example with this I was able to write a small subroutine to create thumbnail-based navigation with highlighting so that you could move through a series of pages (this was a hotel guide) by clicking successive thumbnails in a circle. Just two template html pages and a block of code were needed for this.

      I don't know if you can do that with Mason or Toolkit. But if you are able to install any modules on the server you like, then perhaps those template modules are good. The above system I built to solve a specific problem: very short time frame, repetitive layout, and the knowledge that we would have changes made at the last minute despite the deadline. As it happened this worked since I got a whole CD worth of new images and after normalizing file names and so on, was able to rebuild the entire site in five minutes, with non-engineers able to take over all editing in the future. So you need to think about how this may be passed on to people in the future and how much would be touched by non-engineers.

      Another thing to consider is how involved your interface (for example form validation, redisplay and editting, error messages, etc) will be. Consider that Javascript is great for some things but you may have to edit a number of copies of the same script, or you may run into incompatibilities based on browser version. Perhaps Javascript needs to be modified on the fly too. So long as you can discover the balance of processing needed early in the game you will be able to test the above solutions to see which is best for you.

      One thing I do remember, is that it was quite easy to slurp a template file into a buffer, replace a few keywords with the necessary text, and send it to the user's browser. But I found that when I had to build a complex form to display a user record from a database, it was quicker to take the html template I had and turn it into a perl program which I eval'd after setting a couple of variables in the main program which loaded it. Perhaps CGI.pm based form output commands are elegant, but you could actually load this perl program into netscape and it would look like html.

      It may be that things are quite simple and you can get away with a few simple template HTML files which you rip apart and modify on the fly. But a more complex system may very well benefit from tools that can handle nested, object oriented systems. So I'd recommend thinking carefully about what your needs are, then taking a look at the solutions other people recommended. It seems these tools have matured quite a bit so I know I'll take another look myself. If anyone has good experiences with the above tools or thinks I'm wrong somewhere would like to hear comments.