Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Code and html separation - always or mostly doable?

by kiat (Vicar)
on Jun 16, 2004 at 10:16 UTC ( #367163=perlquestion: print w/ replies, xml ) Need Help??
kiat has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks,

I've been using HTML::Template for quite a while now. It has helped greatly in moving a lot of html (and sometimes logic, as when using tmpl_if) out of my code. The result is a more readable code as well as separation of code and html.

When the layout is simple, such as pulling rows of data from a db and displaying them on an html page, it's trivial to achieve a clean separation of code and html.

However, when the page's layout involves quite a bit of logic, I find it sometimes difficult to filter out the html from the code. What I tend to do in such cases is to build up an html string, and then feed that string, together with other tmpl outputs, to the template file.

Do you have that sort of problems? Or are you able to always cleanly compartmentize code and html? I would love to hear from you :)

Thanks in anticipation.

Update: Many thanks to all for sharing :)

It appears the majority find it always possible to separate the program code from the html. There's however some support for the inclusion of html in the code in cases where their separation proves difficult or impossible (in the eyes of the beholder).

Update2: Reading some of the comments, it seems that it's quite common to move the logic from the Perl code to the template (nodes 367304, 367252). amw1 says it's display logic vs processing logic. So it appears to me that some mixing of code and html is inavoidable. It's where that mixing takes place. If part of the logic is moved to the template, then you inevitably have a more complicated template. If the (display) logic resides in the Perl code, then you inevitably have a more complicated Perl code. So perhaps it's a matter of which type of complication you are more comfortable with?

Comment on Code and html separation - always or mostly doable?
Re: Code and html separation - always or mostly doable?
by Aragorn (Curate) on Jun 16, 2004 at 10:36 UTC
    I have no experience with HTML::Template, but I use Template Toolkit for my templating needs. Skimming through the documentation of HTML::Template, it seems to me that the Template Toolkit has a bit more features which support code/logic separation better, like default values of variables, and more sophisticated control structures.

    There is in my opinion practically always a certain gray area where complete separation of code and presentation is impossible. I try to let the program logic be as generic and modular as possible, and let the template present return values from functions or objects in HTML.

    What I tend to do in such cases is to build up an html string, and then feed that string, together with other tmpl outputs, to the template file.
    I just give TT a bunch of scalars, arrays and/or hashes which I want to present in HTML, and let the templating engine deal with that.

    Arjen

      like default values of variables
      <TMPL_VAR NAME="monkey" DEFAULT="fred">

      davis
      It wasn't easy to juggle a pregnant wife and a troubled child, but somehow I managed to fit in eight hours of TV a day.
      Template::Toolkit is a great system.

      One of the problems I find when making pages with lots of interactivity is that you want to make "subroutines" that create parts of the HTML.

      Example: in a CMS that I'm making - yes, another one - I have a page that lists the document tree, with "nieuw" links that open the editor for a new page. These links can be put on several parts of the page. To simplify this, i made a BLOCK, like so:

      [% BLOCK new_page %] <td width=10><a href="[% editbase %]?action=open&type=page&parent=[% p +age.id %]"><img src="[% imgurl %]/filenew.gif" alt="N"></a></td><td c +olspan="[% span %]" align="left"><a href="[% editbase %]?action=open& +type=page&parent=[% page.id %]" class="new">Nieuw</a></td> [% END %]
      Here, the page items are Class::DBI objects. Now, whenever I want to to show these links, I do:
      [% IF form.action == 'new' %] [% INCLUDE new_page page=some_page span=2 %] [% END %]

      TT uses the same syntax to include other templates, so if needed, I can move the BLOCK to a seperate file without having to change the calling code.

      By the way, I use a seperate hash-ref "form" to store the values I want to set in the form on the editor.

      This $form hashref is initially filled with the values from the CGI request, but it allows me to change the values in "form" (for instance, with data from the $page object from the database) but still have the original request object lying around if I need it. This is a nice seperation of concerns that is very much used in the Struts java MVC framework, and works pretty well for more complicated interactions.

        Another feature of TT that works well with blocks is the macro stuff. It allows you to write "functions" to do various things. i.e.

        this takes a scalar and a list or scalar. If the scalar matches the other scalar or matches a value in the list the macro resolves to "selected" otherwise it does nothing. (used to find selected values in a <select> list.

        [% # sets selected if both values match # tries to see if either side is an array to try and find a match # out of an array of possibly selected values. This will work for m +ultiple # select lists. %] [%- MACRO is_selected(val1, val2) BLOCK -%] [% IF val1 == val2 %] selected [%- selected = 1 %] [% END %] [% IF !selected %] [%- FOREACH value = val1 -%] [%- IF value == val2 -%] selected [%- selected = 1 -%] [%- LAST -%] [%- END -%] [%- END -%] [% END %] [%- IF !selected -%] [%- FOREACH value = val2 -%] [%- IF value == val1 -%] selected [%- LAST -%] [%- END -%] [%- END -%] [%- END -%] [%- END -%]
        This lets you do things like. . . .
        [% # selected items is a list of what should be selected # from this list %] <select name=foo> [% FOREACH select_item = option_list.keys %] <option value="[% option_list.$select_item.value %]" [% is_select +ed(option_list.$select_item.value, selected_items %]> [% option_list.$select_item.display_name %] </option> [% END %] </select>
        I have not seen anything in HTML::Template that will let me come close to being able to do this. Most of the work that the template is doing would have to be shifted into the perl code. with html::Template (afaik, I stopped using after I got approval to use TT). In the above example option_list is a hash (that for sake of argument I got from a library call that I don't control). In H::T I'd have to re-write that structure into an array, I'd also have to resolve the selected attribute inside the perl code. The only place where those things are needed are for the display, so why should they be in the perl code.

        Granted, there is logic in the templates now, but it is solely DISPLAY logic. It is not processing logic. The split I try to get is to not have ANY display logic in the perl code and to not have ANY processing logic in the template. Stuff like properly formatting a date gets put into the template. Stuff like cooking data before it is put into the database lives in the perl code. There seems to be a fairly large camp that does not want to put any logic inside the templates. They are right too. :)

        Sorry if this is a bit long winded but I really enjoy working with this stuff.

        I've started working in this mode as well since switching to CGI::Application, using templates for layout and CGI for form generation. Can you share some MVC style perl here?
Re: Code and html separation - always or mostly doable?
by yosefm (Friar) on Jun 16, 2004 at 10:44 UTC

    Once you understand wht is the data structure, HTML::Template is really in your favour - you can create nested loops, ifs and includes. The problem is when you want to do something like taking a simple loop and print it in two columns, and then the design of the page will reflect in your code (I did this by creating a loop of rows inside a loop of collumns). I don't know if that's considered clean enough for you, but it's batter, IMO, than printing raw HTML, since the visual design is still left to the template

    A related question is printing CGI fields: put them in the template or create them with CGI.pm? I mean:

    <input type="text" value="<TMPL_VAR BlaBlaBla>" />
    vs just
    <TMPL_VAR BlaBlaBla>

    The answer depends on the complexity of the field (a hidden field is easy to put in the template, a dynamic n-level menu isn't) and the overall level of seperation you decided on - I usually separate as much as I can. Just look at it from the design / logic point of view: "Do I have to know what widget gave me this value?" usually not. Mostly you just have to know if the value is single, multiple choice, etc. but not how it got there.

    Hope this helps


    perl -e'$b=unpack"b*",pack"H*","59dfce2d6b1664d3b26cd9969503";\ for(;$a<length$b;$a+=9){print+pack"b8",substr$b,$a,8;}'
    My public key
Re: Code and html separation - always or mostly doable?
by Michalis (Pilgrim) on Jun 16, 2004 at 11:14 UTC
    I don't use HTML::Template or Template Toolkit, but I'm using a custom Template engine based on the (discontinued) HTMLTP, plus some custom modules for error checking etc. I beleive that the one I use is quite restrictive, but I find it impossible to NOT be able to completely seperate code from presentation.
    I haven't written a single line of HTML on my code,since 2002 at least...

    So, I beleive that with the correct analysis, and pre-design, you can always seperate the two.

    -- Michalis
Re: Code and html separation - always or mostly doable?
by bradcathey (Prior) on Jun 16, 2004 at 12:05 UTC
    kiat, I've been using HTML::Template for about 6 months now. Before that, it was all Here documents, which made it impossible for my designers to do any editing (can't expect graphic designers to learn Perl). And now, through experience and a little creativity (loops nested 3 deep which has forced me to master AoHoA....'s) I've been able to move all Perl-built HTML strings out of my Perl and into my HTML.

    Do I truly have HTML separated from code (code equaling logic)? Not if you consider H::T 'code', which you often because of conventions like conditionals and loops. So, I haven't really completely separated code from HTML. My designers still have to deal with some level of 'code' when editing the HTML. Thought the use of comment tags and carriage returns between H::T and HTML, it's a little easier to read.

    Because I have moved to all CSS-tableless XHTML 1.0 strict for my HTML, I can't validate my code in BBEDIT because it stumbles over all the H::T stuff. A bit frustrating (of course, it can all go in comment tags, but the doc warns of bandwidth problems, so eventually it gets stripped out.)

    One thing I have improved on is using nomenclature that helps tie my MySQL tables to the loops in my HTML, so column names equal loop names.

    In summary, I'm pleased with H::T and now that I'm building CMS apps, I find it indispensible. And in combo with Perl, it sure beats the ASP alternatives.

    kiat, it's been interesting to read your nodes over the past 9 months. It sounds like you and I are on parallel tracks (though you are a couple of lengths ahead of me) and doing very similar work. Thanks for all your great questions—I have learned a lot in following them.

    Good luck.

    —Brad
    "Don't ever take a fence down until you know the reason it was put up. " G. K. Chesterton
      Hey, bradcathey,

      This community thrives because there are enough people with questions (good, bad or ugly) and even more people who not only have the knowledge but are willing to spend a little of their precious time to help and to share the knowledge.

      Thanks for your feedback! It's very encouraging :)

        This community thrives because there are enough people with questions (good, bad or ugly)

        yep, question means quest of knowledge.!

      I can't validate my code in BBEDIT because it stumbles over all the H::T stuff. A bit frustrating

      HTML::Template allows you to put your TMPL_VAR, TMPL_LOOP, and other directives inside HTML comments, e.g. <!-- TMPL_VAR NAME=foo --> is the same as <TMPL_VAR NAME=foo>. Unless your HTML editing tool mangles comments, this should allow you to have your cake and eat it too.

      HTH

        True facts, revdiablo, but as I pointed out in my orig. reply, the H::T manpages state that the commented directives have a negative effect on bandwidth (but I might be misunderstanding their comment). I prolly should run some of my own tests. Thanks.

        Update: Per revdiablo's reply, below, the comment issue is one I need to look into, both for validation and readibility issues, aforementioned.

        —Brad
        "Don't ever take a fence down until you know the reason it was put up. " G. K. Chesterton
Re: Code and html separation - always or mostly doable?
by exussum0 (Vicar) on Jun 16, 2004 at 15:26 UTC
    Why not create libraries for "rendering" data. And what little logic you need for it, put in there.

    One thing I used to do, for putting results in pages, was to provide my data to a display object, and have the display object do all the heavy work of either just doing a straight template->render() call (we used a custom template solution like HTML::Template), or populate certain parts based on the data.

    The other solution, is to use a "stronger" template engine. HTML::Template is great if you do the above. But things like TT or using XML::XSLT (i like this one) leaves you better off. With XML::XSLT, at least your template language is more universal. Some XSLT implementations aren't as complete as others, but the basics usually are.

    Bart: God, Schmod. I want my monkey-man.

Re: Code and html separation - always or mostly doable?
by thraxil (Prior) on Jun 16, 2004 at 15:50 UTC

    with a bit of thought, i've found that it's always possible to seperate the business logic and display logic using HTML::Template. (at least it has been for everything i've written for the last 3 or 4 years).

    you may need to spend a bit of time coming up with a decent solution, but it almost always pays off. eg, i used to resort to using CGI.pm's popup_menu() to produce <select>s and then just passing them in as html strings. eventually i sat down and thought up a better solution and the result has been cleaner code with more control in the hands of the designer.

    also, don't be afraid to subclass HTML::Template and override parts of it. that road has many interesting possibilities.

Re: Code and html separation - always or mostly doable?
by injunjoel (Priest) on Jun 16, 2004 at 16:08 UTC
    Greetings all,
    Some good comments up to now. I do CGI based scripting almost exclusively and this is indeed a common issue for me and my team. However what we try to keep in mind is that a total seperation of logic from display is not always possible, especially with web-based applications. Our strategy is to utilize other technologies to help bridge the gap such as CSS or JavaScript. Standardizing styles can go a long way in terms of helping the programmers conform to the designers sense of style.
    We usually define styles for HTML tags first, stuff like body, td, p, dir, blockquote, ...etc Then define custom styles (but standardized names!) for things like navigation links and any other funky stuff we need. This way if you forget the name of the custom style to use at least you will have a default style for most of your HTML tags and missings a style wont result in a non-conforming element.
    It still boils down to you creating some HTML strings as you mentioned earlier, however you will now have a standard set of styles to work with. This way if your code ever needs a face lift you wont have to touch your code as much, just update the HTML templates and tweek the style sheet, so long as your style names stay the same you will be fine.
    I know this is not the best of solutions but its better than hard-coding style related things in your scripts.

    -injunjoel
Re: Code and html separation - always or mostly doable?
by nothingmuch (Priest) on Jun 16, 2004 at 16:29 UTC
    What you should look into is the Model View Controller pattern.

    The basic idea is that you design a model, which is a set of object that represents your data in data-centered way - disregard the need for display code.

    Then you have a controller, which performs user actions on the model, like adding items, performing calculations, and so forth. It should be pretty thin, and if you find yourself doing too much logic in the controller, that has to do with the contents of the data instead of the contents of the user request, you should probably refactor your model so that it's objects know how to apply this logic to themselves.

    Lastly, you have the view, which accept a data model with is view oriented. It cares about display logic only. The controller is responsible for creating objects that are intuitive for the view, from objects that are intuitive to the data model.

    I like using the Petal templating system for views, which is similar to HTML::Template, because it's very limited in terms of logic - you have to insert a real object model into it (as objects, or nested data structures), you don't get much more than if-else. It also looks kind of like H::T, because the templates are valid XHTML themselves.

    In contrast to H::T it i a bit easier to use simple logic to create more fine grained HTML output, so I've yet to need to create HTML strings in the perl code.

    If you are hard enough on yourself, refactoring your objects often, as annoying as that is, and keeping all the view logic simple, but not letting it in the perl code at all, you usually have much more maintainable code. Rereading stuff like Apache::ASP code is something I really don't enjoy, because Perl and HTML are mixed freely.

    Another thing you should look at is Maypole - it's purpose is to bring MVC to web programming, and let you build web UIs very easily and quickly. It's new, so it's still under heavy development, but if you don't like it most the discussions about it notes the nice set of alternatives that are available.

    -nuffin
    zz zZ Z Z #!perl
Re: Code and html separation - always or mostly doable?
by dragonchild (Archbishop) on Jun 16, 2004 at 16:41 UTC
    Remember this - HTML::Template was designed as a slimmed down option to the first Template Toolkit. samtregar deliberately removed a lot of the meta-templating that TT2 has.

    Given that, if your templating system doesn't have all the features you need, then maybe it's time to use a different templating system. We're actually going to be doing that in the next six months.

    With proper tools and adequate design time, it is always possible to accomplish a clean MVC separation.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

    I shouldn't have to say this, but any code, unless otherwise stated, is untested

Re: Code and html separation - always or mostly doable?
by MrCromeDome (Deacon) on Jun 16, 2004 at 16:58 UTC
    Frankly, the first two or three projects I did with HTML::Template were not done the right way ;) There were a lot of places where I was generating HTML inside of my Perl scripts because in my head I could make more sense of it there. Another project came along later. . . was writing a fully-featured demo to try and land a big contract for my company, and I knew my meager design skills wouldn't cut it, so I needed a real web page designer. The one I liked wouldn't know Perl if it bit her in the ass ;) Sooooo, my poor practices had to stop. I gave her simple text files with the variables I needed in them. . .

    . . .And I've never looked back since. It takes some work sometimes, but my content and program logic are entirely separate now. I can hand my designer blank template files, write my programs, and know they will work perfectly and look great when the templates come back.

    How do I do it??? Liberal use of some of the more advanced features of H::T, lots of TMPL_IFs, TMPL_VARs, and TMPL_LOOPs, and the good ole' conditional operator ;) I'm not saying this is the best way, but it works well for me.

    Here's a brief example of what I do. First, the template:

    <table border="0" cellpadding="0" cellspacing="3"> <tr valign="top"> <td> <b><a href="<!-- TMPL_VAR NAME=SCRIPT -->?<!-- TMPL_IF NAM +E=SESSION -->CGISESSID=<!-- TMPL_VAR NAME=SESSION -->&<!-- /TMPL_IF - +->mode=results&sort=parcel&dir=<!-- TMPL_VAR NAME=PARCEL_DIR -->&chan +ge=true">Parcel Number</a></b> <!-- TMPL_IF NAME=PARCEL_ASC --> <img src="/images/arrow_up.gif"> <!-- /TMPL_IF --> <!-- TMPL_IF NAME=PARCEL_DESC --> <img src="/images/arrow_down.gif"> <!-- /TMPL_IF --> &nbsp; </td> <td> <b><a href="<!-- TMPL_VAR NAME=SCRIPT -->?<!-- TMPL_IF NAM +E=SESSION -->CGISESSID=<!-- TMPL_VAR NAME=SESSION -->&<!-- /TMPL_IF - +->mode=results&sort=name&dir=<!-- TMPL_VAR NAME=NAME_DIR -->&change=t +rue">Name</a></b> <!-- TMPL_IF NAME=NAME_ASC --> <img src="/images/arrow_up.gif"> <!-- /TMPL_IF --> <!-- TMPL_IF NAME=NAME_DESC --> <img src="/images/arrow_down.gif"> <!-- /TMPL_IF --> &nbsp; </td> <td><b>Address</b></td> </tr> <!-- TMPL_LOOP NAME=RESULTS --> <tr valign="top"> <td><font color="<!-- TMPL_VAR NAME=COLOR -->"><a href="<!-- T +MPL_VAR NAME=SCRIPT -->?mode=view&parcel=<!-- TMPL_VAR NAME=UPARCEL - +->&year=<!-- TMPL_VAR NAME=YEAR -->"><!-- TMPL_VAR NAME=PARCEL --></a +></font></td> <td><font color="<!-- TMPL_VAR NAME=COLOR -->"><!-- TMPL_VAR N +AME=NAME --></font></td> <td><font color="<!-- TMPL_VAR NAME=COLOR -->"><!-- TMPL_VAR N +AME=ADDRESS --></font></td> </tr> <!-- /TMPL_LOOP --> </table>
    And now the Perl:
    $tmpl_results->param ( RESULTS => \@results, SESSION => $config{USE_SESSION_HACK} eq "Y" ? $self->param("se +ssion")->id : "", SCRIPT => $request->url, SORT => $sort, PARCEL_DIR => (($sort eq "parcel" and $dir eq "ASC" ) ? "DESC" : +"ASC"), PARCEL_ASC => (($sort eq "parcel" and $dir eq "ASC" ) ? "Y" : "") +, PARCEL_DESC => (($sort eq "parcel" and $dir eq "DESC") ? "Y" : "") +, NAME_DIR => (($sort eq "name" and $dir eq "ASC") ? "DESC" : +"ASC"), NAME_ASC => (($sort eq "name" and $dir eq "ASC" ) ? "Y" : " +"), NAME_DESC => (($sort eq "name" and $dir eq "DESC" ) ? "Y" : " +"), DIR => $dir, TIME => sprintf("%$config{FORMAT_TIME}", $time), NUM_RESULTS => $rows, START => $first, END => $last, FIRST => ($first == 1 ? "" : "first=1&last=$config{INCREMENT +}"), PREV => ($first == 1 ? "" : "first=" . ($first - $config{IN +CREMENT}) . "&last=" . ($last - $config{INCREMENT})), NEXT => ($last >= $rows ? "" : "first=" . ($first + $config +{INCREMENT}) . "&last=" . ($last + $config{INCREMENT})), LAST => ($last >= $rows ? "" : "first=" . ($rows - $config{ +INCREMENT}) . "&last=$rows"), );
    One thing that has drastically helped my development is HTML::Template. It promotes cleaner application structure, and plays nicely with H::T. Give it a check.

    Feel free to contact me with questions about what I did.

    Cheers!
    MrCromeDome

Re: Code and html separation - always or mostly doable?
by DaWolf (Curate) on Jun 16, 2004 at 18:22 UTC
    I'd like to add my humble 2 cents here:

    I've came from a HTML background so this node really drew my attention.

    I think that although is possible to do a clean separation of presentation and logic, sometimes it's not the best way to do it, because you end up messing with the readability of the page. Let me clarify this with a (silly) example:

    Let's say that a user of your web system should see a red background if he/she has a "0" level or a blue background if he/she has a "1" level.

    So, you could do this in two different ways (i'm coding this in a freely, lazy way so dont evaluate my code, this is just an example):

    First way (separating logic and presentation):
    if ($u_level == 0) { $bgcolor = "#FF0000"; } else if ($u_level == 1) { $bgcolor = "#0000FF"; } # tons of code... print<<<HTML <HTML> <HEAD> <TITLE> DaWolf's silly example </TITLE> </HEAD> <BODY BGCOLOR="$bgcolor"> <!-- tons of content... --> </BODY> </HTML> HTML;
    Second way (mixing logic and presentation):
    # tons of code... print<<<HTML1 <HTML> <HEAD> <TITLE> DaWolf's silly example </TITLE> </HEAD> HTML1; if ($u_level == 0) { print "<BODY BGCOLOR=\"#FF0000\">"; } else if ($u_level == 1) { print "<BODY BGCOLOR=\"#0000FF\">"; } print<<<HTML2 <!-- tons of content... --> </BODY> </HTML> HTML2;
    The advantage of the second way in my point of view is that you don't need to go all the way up to understand what $bgcolor means and why it have this or that value, so the code is more easily understandable and more practical to debug.

    That's why I think separation should be avoided unless you are not used to deal with HTML.

    As I've stated before, this is just my humble opinion.

    UPDATE:

    Quick explanation: I've never used a Templating system with Perl, so I can't really give my opinion on that, but I've just tried to show the best way ***for me*** to code my pages =:c)

    Best regards,

    my ($author_nickname, $author_email) = ("DaWolf","erabbott\@terra.com.br") if ($author_name eq "Er Galvão Abbott");

      I can see $bgcolor and know exactly what it means. Same with any other well-named variable. That aside there are tons of problems with your approach

      1. What happens when you need to make a really large page? You can't see $bgcolor if its buried under 1000 lines of lines of HTML. You also will find it much harder to see anything else in your program.
      2. Designers don't know and don't want to learn Perl. They want to make HTML in Dreamweaver and then have you make it work. Templating makes this much easier and I can write the program while they're making pretty pictures.
      3. Much less typing! No need for the extra print statements! Design with an HTML editor if you want to. Or as I stated above another designer can work on it.
      4. This code isn't modular, you can't reuse the HTML design easily without copying it to another script. Templates make reuse simple

      No offense intended and I understand its your opinion, however your suggestion is the exact opposite of what the parent poster is trying to accomplish. So its not exactly helpful. Also try some templating, trust me, its not hard (I personally like H::T!) and once you get it you'll never ever go back!

      Update: Fixed some typos and my terrible spelling :)

      Thanks, DaWolf!

      I used to do it that way. There's a lot of html in the code. In the long run, it might be better to move the bulk of the html to a template.

      You might want to seriously consider something like HTML::Template. I started using it at the beginning of this year and there's no turning back.

      I've moved out lots of html from the code into the templates, and it makes for a cleaner code and probably an easier maintanence task.

      What I find difficult and sometimes impossible to achieve is a 100% separation of code and html. But as others have pointed out, it's doable with a clear idea of the program logic. With time and more practice, I might be able to do that.

      On a different note, I've seen rather huge programs (ikonboard and yabb) with code and html glued together.

      cheers

Re: Code and html separation - always or mostly doable?
by saberworks (Curate) on Jun 16, 2004 at 18:50 UTC
    I've always wondered how you separate things like alternating table row background colors. Currently, I assign it in code, but that sucks. HTML::Template doesn't appear to have enough logic features to allow you to do modulus division on each iteration and pick a bgcolor from an array. So I have color definitions in my code - which sucks if the designer wants to change the colors. Of course, then I could use something like a config file or store the colors in a db, but that way, it's separated into 3 different areas instead of just two.
    my @colors = ('#FFFFFF', '#F0F0F0'); my $cnt = 1; foreach my $row (@$list) { $row->{bgcolor} = $colors[$cnt % 2]; # Assign $row to your template engine or AoH or whatever... $cnt++; }
      for Template Toolkit this macro will do it This does it using CSS classes for coloring but setting it in a different way works as well.
      create a block macro [% MACRO alt_color(loop_count) BLOCK %] [% IF loop_count % 2 == 0 %] color1 [% ELSE %] color2 [% END %] [% END %] in your template you do loop.count is a special property of the iterator [% FOREACH thing = things %] <td class=[% alt_color(loop.count) %]>[% thing %]</td> [% END %]
      for H::T you can do
      <tmpl_loop name='things'> <td class=<TMPL_IF __ODD__>color<TMPL_ELSE>color2</TMPL_IF>> thing</ +td> </tmpl_loop> you need to make sure you have loop_context_vars set to 1 in H::T to h +ave access to __ODD__/__EVEN__
      Hi,

      If you only speak of two colors, it's quite easy in the template system I use (and I guess, even easier on standard Template systems).
      I create an array (call it @array) on my perl program, containing hashes. One of the hash elements is named "bgcolor" and is actually a boolean value. Let's say for example that it also has a "content" value which is string and a "cnt" value which is integer (a counter).

      The code notation provided works for HTMLTP, but it should work anywhere as the logical part.

      <table> <!--: ascending array :--> <tr class="<!--: if bgcolor :-->colored<!--: else :-->noncolored<!--: +end :-->"><td>[:cnt:]</td><td>The content of the [:cnt:]th element is + : [:content:]</td></tr> <!--: end :--> </table>

      The only remaining part is to define the "colored" and "noncolored" classes on your CSS.

      --
      Michalis
        Both of the above are fine for two colors, but in my code, you can easily add an arbitrary number of colors and it will still work. I think template systems should provide functionality to handle very common cases such as this. Maybe something like (haven't used html::template in forever so I don't remember the syntax for loops, but I'll guess):
        <TMPL_LOOP NAME=rows ALTERNATE=FFFFFF,F0F0F0,CCCCCC> <td bgcolor=rows.alternate> .... </td> </TMPL_LOOP>
        I guess I could add it ;)
Re: Code and html separation - always or mostly doable?
by mvc (Scribe) on Jun 16, 2004 at 20:57 UTC

    It is not so easy to avoid what is known as scattering and tangling. Here is a good paper on separation of concerns in web apps, suggesting an AOP approach.

    Speaking of AOP, there is a new developer release of the Aspect module.

Re: Code and html separation - always or mostly doable?
by Anonymous Monk on Jun 16, 2004 at 21:37 UTC
    It is doable if you force yourself to adhere to a specific model of doing things.

    I wrote a (yet unpublished to CPAN) module called "QWizard" that lets you write "wizard" screens that do complex sets of interrelated web pages easily. You define your questions to ask of the user (or things to just display, whatever) and code that acts on those questions (perl). When you write it using the generic widget building set (HASH descriptions), it will display it for you. We have used no HTML in the GUI part of net-policy, which is where these modules live currently, and the result is that the interface works under both HTML and Perl/tk without modification. new backends can be done at will as well (I have a half-working curses version). but, you have to conform to "how the screens are intended to look" (though its really flexible).

    The advantage of Qwizard in particular is that you can write a CGI script that works asa HTML display when run from apache, and the same script when executed from the command line runs as a TK window without any modification...

Re: Code and html separation - always or mostly doable?
by dws (Chancellor) on Jun 17, 2004 at 04:19 UTC

    I come down firmly in favor of keeping code out of templates.

    The project I'm on now assembles HTML hierarchically, using HTML::Template-based fragements to assemble larger pages. This lets us build reusable components while still keeping our HTML separated from our code. Consider something like:

    <h1>Here somes a table</h1> <TMPL_VAR NAME=table ESCAPE=0> <hr>

    On first glance, you might assume that table is a chunk of HTML table tags generated from code, but nothing says that it can't be the result of expanding a different template and stored the resulting HTML in a hash that gets used when constructing arguments for the outer template.

      I used to come down firmly on keeping all logic outside of the templates. However I ran into a number of cases where it was either put code in the template or put display only logic inside of the program.

      An example of this was date formatting. All of our routines that get data structures from the database/files/aether etc. return times as seconds since epoch. Much of our backend code makes use of this number without ever converting it. In fact, the only time we ever need to cook that number is when we display it. After cooking the date in the cgi and passing it to the template I started to think that it made no sense to do this work inside the CGI as it had nothing to do with the actual work of the CGI. i.e. the cgi was no longer agnostic wrt how the data was displayed.

      After spending some time thinking about this I started to draw the following lines:

    • Anything that does work other than calling a template or processing form submissions lives in a module.
    • Anything that does work that is display only (formatting things (like dates above), colors, layout etc) only lives in the template. Yes, this often leads to having some programming inside the template, I just felt since it was only for display it made more sense here.
    • Everything else lives in the CGI.

      The only time I end up breaking this is for things that make a ton more sense to do in a langauge other than the template. (i.e. heavy data manipulation etc) but I try like the devil to code my way around that.

      It may have been my lack of experience with H::T but I found myself having to re-form many of the data structures we were using into AoH's for use by H::T. With TT I was able to use whatever datastructure I wanted to pass to the system. Again, this lead to a bit more logic in the template, but it was for display only. Using the cgi to reformat data for the template seemed like a huge waste of effort. Granted, we could have re-formed the datastructures from the backend but there were more places where it made sense for us to use straight hashes than AoH's. Since H::T (to my knowledge) won't process a hash I had to spend more time writing code in the CGI that ultimately did nothing but format data for display.

      my .02

Re: Code and html separation - always or mostly doable?
by gwhite (Friar) on Jun 18, 2004 at 13:19 UTC

    I am suprised no one has really recommended Text::Template written by Mark-Jason Dominus. The best thing about this module is the templating logic is Perl, not some made up something else to learn.

    I like to break out my display logic into a separate file, so I have code, display logic, and template. The template only contains output variables (so webdesigners don't have to mess with logic elements) and it gives me the power to change the template based on display logic. So I can deliver HTML, plain text, XML or whatever, I can also internationalize output easily with this method.

    g_White
      Just for completness, there's also Text::ScriptTemplate which is a simple templating system with asp/jsp-like tags and also uses perl for the template logic. I wonder if somebody tried both Text::ScriptTemplate and Text::Template and can tell which one is to prefer.
Re: Code and html separation - always or mostly doable?
by metaperl (Curate) on Dec 23, 2004 at 21:11 UTC
    If you want maximal separation of Perl and HTML, then you want HTML::Seamstress or XML::LibXML... I wrote the former and Matts wrote the latter.

    Not far off in degree of separation is Petal.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://367163]
Approved by Tomte
Front-paged by davido
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (7)
As of 2014-12-28 16:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (182 votes), past polls