Hi all!
I am currently learning a bit more about the current crop of different "templating mechanisms" primarily used for web page generation that are in use in the industry today. My list sofar is more or less like this:
- A simple "variable substitution" engine. You can easily hack one of these yourself and I have seen it used the webenging of 4D for example. Typically everyone implements "their own" and there are tons of these out there on the net. Typically quite primitive and can't deal with stuff like "loops" etc.
- Proprietary template mecanisms in web application servers. Seemingly there are many of these too which are probably more advanced than the above "hacks" but still not "standard" in any way.
- Embedding "custom tags". ColdFusion did this early on and it is a "simple" idea that makes all the HTML tools behave quite ok. At least earlier they just ignored tags they couldn't understand (and hopefully didn't remove them) and nowadays they probably deal with them nicely (since XHTML has taken the scene). What the tags are capable of is still up to the proprietary product of course.
- JSP/ASP-pages. From the beginning these approaches were based on embedding imperative serverside code in HTML pages but according to a collegue "JSP best practices" is currently to use "custom tags with parameters" instead making this apporach more declarative and in fact "just another template engine" I guess.
- XML+XSL. XSL is a XML-based language that can describe very complex transforms of XML-documents into other XML-documents. As "standard" as it gets. Which mean tons of tools and tutorials and websites etc but at the sime time quite complex IMHO. Sure, you don't need to use all that complexity but I have heard that one before... ;-)
- Seaside/HttpView. In Seaside and HttpView we have taken a Smalltalk-centric approach (well, Seaside has multiple approaches I think) where we "build" HTML using smalltalk. Almost like DOM but more "streamish", at least in HttpView.
Well, surely there are other approaches out there too.
When I did HttpView I was sick of everything called JSP/ASP and wanted something much simpler and direct. I also wanted something that could work with Forms in a very easy way. The end result turned into a HtmlBuilder object that produces XHTML. Since CSS has come quite a long way and you typically only have one or very few CSS-files this meant that there was essentially only one source for a page - the Smalltalk code. Nice and simple.
I had an intention to implement new HtmlBuilder classes that could also "merge" the HTML into some form of template coming from the "outside". Exactly how that could work is still a bit clouded. One way could be to not change anything and just slap an XSL engine "on top" that can add "looks" as a last step before hitting the client browser. Another way could be to create some "custom" highlevel XML document and feed that into an XSL engine to turn it into XHTML with looks.
Or perhaps use some other templating mechanism that can let the "HTML gurus" do their job. For example - here is one interesting approach that may be impossible:
1. Build the webapp as simply as possible but actually working. 2. Turn on some form of "ids in tags" generation which means that the HtmlBuilder adds ids in the generated tags to keep track of them. 3. Let the designer run the app and simply do "Save as..." on the HTML pages/HTML components. (Given that any given component easily can be addressed separately or at least "cut out" from an HTML page, for example if contained within a div-tag). Of course you could let the serverside app save out the HTML pages instead of returning them through HTTP, etc. whatever. 4. Let the designer edit them into glorious looking HTML that no mortal can ever read. 5. Feed the new HTML pages (and CSS+any scripts of course) back into the HtmlBuilder that somehow can take the original page and the "glorified" page and from that (and the embedded "track" tag ids) construct an internal template of some kind. 6. Turn of the tag ids, they aren't useful anymore - they were only used for tracking the generated tags.
Anyway, perhaps the above is impossible to accomplish - but it would be cool if it did. I can focus on coding Smalltalk and a simple subset of XHTML, the designer can focus on webpage "good looks" and doesn't need to handcode XSL or anything.
Ok, now Avi and Julian - what do you think? What is the ultimate templating mechanism? :-)
regards, Göran
On Wed, 11 Dec 2002 goran.hultgren@bluefish.se wrote:
<lots about templating systems>
Ok, Avi, Julian, what do you think?
Since you ask...
I find any system that treats the template purely as text to be too low level - forcing me to textually insert a value or variable for every attribute of every form field is equivalent to writing a GUI app by making write() calls to a X-windows client socket; you might feel it gives you more control, but mostly what it does is make busywork and reduce abstraction. This rules out the large majority of the templating systems out there: variable subsitution systems like WebMacro or FreeMarker, typical use of embedded code systems like PHP and JSP, tag-languages like ColdFusion - in each case, every character of the final HTML output is the direct result of some piece of code the developer wrote. I won't even get into the evils of mingling logic and presentation that are inherent in most such systems, because they already fail on that basic principle: HTML and HTTP have very well defined structure and semantics, and a good templating system should know these intimately and largely protect me from them.
I know of three general approaches to avoiding this problem: parse the template and modify it programmatically, produce the HTML through (declarative) transformation of the data, or generate the HTML directly in code.
The first of these is the only one that's really "templating". It's the approach taken by WebObjects, Seaside 0.9x, and Enhydra/XMLC (used, I think, by Barracuda, which was mentioned elsewhere in this thread). Usually this involves producing some kind of a DOM from the template, finding and transforming some special elements (which were given unique ids in the template) while leaving the bulk of the elements alone, and the regenerating HTML from the modified DOM. Some systems provide better abstractions for this than others (Seaside and WebObjects provide sophisticated models of elements such as forms, links, and inputs, that you interact with in a fairly high level way, whereas I believe XMLC users tend still to directly manipulate HTML attributes), but once you have the DOM in memory you can obviously interact with it as abstractly as you like.
The only example of the second, transformative approach that I know of is XSLT. I've never used Coocoon or any other XSL-based system, so I don't feel terribly qualified to speak about them, but I don't know any designers *or* developers who don't shudder in horror at the thought of writing XSL. If somebody has good experiences with this approach, or knows what the current best practices are, I'd love to hear about it.
Finally, there's the approach HttpView and Seaside2 take, which is not to have templates at all, but rather to generate all of the HTML programmatically. As someone who's spent a lot of time implementing and using template systems, this seemed at first horribly backwards. What I've discovered is that ditching templates entirely provides much more opportunity for refactoring and abstraction. The problem with templates is that they force you to always think at the level of individual HTML tags. Once a tag is a method, it's much easier and more natural to start combining them into larger and larger methods and classes, and the wins from this are huge.
The other thing I've discovered simultaneously is that CSS is making templates less and less necessary - if your code produces bare bones HTML that's fully annotated with divs, spans, classes and ids, the designer has a lot of huge amount of control over the look through the CSS file. Going forward, this is where I think the division of responsibility should lie: the programmer produces the (X)HTML, and the designer controls the CSS.
As a still fairly low level example, I added a method to Seaside recently named #rowWithLabelledTextInputOn:of: which is used like
html rowWithLabelledTextInputOn: #firstName of: customer.
and produces something somewhat like
<tr id="firstName"><td class="label">First Name:</td><td><input type="text" value="Avi"></td></tr>
Note a few things about this: - it's one method call instead of 5 or so tags - this pattern likely gets used hundreds of places in your app; now you can change it from one place - it automatically inserts classes and ids so that CSS can modify any part of the look - you can use this as a building block for higher level abstractions
Now, in theory in JSP-like systems with custom tags you could build a <labelledRow> tag, that would be used something like
<table> <labelledRow name="firstName" target="customer"> ... </table>
or some such. But what's the point? You've lost the benefits of templates (Dreamweaver has no clue what to do with that, an HTML designer can't do much with it either), and also lost the benefits of having it be in code (is senders of #firstName gonna find your template? How about inst var references to 'customer'?). In practice, people don't do this - they just copy and paste the same HTML boilerplate all over the place.
Or perhaps use some other templating mechanism that can let the "HTML gurus" do their job. For example - here is one interesting approach that may be impossible:
- Build the webapp as simply as possible but actually working.
- Turn on some form of "ids in tags" generation which means that the
HtmlBuilder adds ids in the generated tags to keep track of them. 3. Let the designer run the app and simply do "Save as..." on the HTML pages/HTML components. (Given that any given component easily can be addressed separately or at least "cut out" from an HTML page, for example if contained within a div-tag). Of course you could let the serverside app save out the HTML pages instead of returning them through HTTP, etc. whatever. 4. Let the designer edit them into glorious looking HTML that no mortal can ever read. 5. Feed the new HTML pages (and CSS+any scripts of course) back into the HtmlBuilder that somehow can take the original page and the "glorified" page and from that (and the embedded "track" tag ids) construct an internal template of some kind. 6. Turn of the tag ids, they aren't useful anymore - they were only used for tracking the generated tags.
I'll respond to this later, this email's more than long enough already. Basically I think it's a good idea if you can manage to pull it off.
Avi Bryant wrote:
On Wed, 11 Dec 2002 goran.hultgren@bluefish.se wrote:
<lots about templating systems>
Ok, Avi, Julian, what do you think?
Since you ask...
I find any system that treats the template purely as text to be too low level - forcing me to textually insert a value or variable for every attribute of every form field is equivalent to writing a GUI app by making write() calls to a X-windows client socket; you might feel it gives you more control, but mostly what it does is make busywork and reduce abstraction. This rules out the large majority of the templating systems out there: variable subsitution systems like WebMacro or FreeMarker, typical use of embedded code systems like PHP and JSP, tag-languages like ColdFusion - in each case, every character of the final HTML output is the direct result of some piece of code the developer wrote. I won't even get into the evils of mingling logic and presentation that are inherent in most such systems, because they already fail on that basic principle: HTML and HTTP have very well defined structure and semantics, and a good templating system should know these intimately and largely protect me from them.
Avi and I work together a lot on this stuff so it's not surprising that we have generally the same beliefs. Whether this is the reason we work together or a cause of the fact that we work together, I'm not sure. But certainly the things we dislike about existing systems are pretty similar.
I know of three general approaches to avoiding this problem: parse the template and modify it programmatically, produce the HTML through (declarative) transformation of the data, or generate the HTML directly in code.
The first of these is the only one that's really "templating". It's the approach taken by WebObjects, Seaside 0.9x, and Enhydra/XMLC (used, I think, by Barracuda, which was mentioned elsewhere in this thread). Usually this involves producing some kind of a DOM from the template, finding and transforming some special elements (which were given unique ids in the template) while leaving the bulk of the elements alone, and the regenerating HTML from the modified DOM. Some systems provide better abstractions for this than others (Seaside and WebObjects provide sophisticated models of elements such as forms, links, and inputs, that you interact with in a fairly high level way, whereas I believe XMLC users tend still to directly manipulate HTML attributes), but once you have the DOM in memory you can obviously interact with it as abstractly as you like.
The only example of the second, transformative approach that I know of is XSLT. I've never used Coocoon or any other XSL-based system, so I don't feel terribly qualified to speak about them, but I don't know any designers *or* developers who don't shudder in horror at the thought of writing XSL. If somebody has good experiences with this approach, or knows what the current best practices are, I'd love to hear about it.
Finally, there's the approach HttpView and Seaside2 take, which is not to have templates at all, but rather to generate all of the HTML programmatically. As someone who's spent a lot of time implementing and using template systems, this seemed at first horribly backwards. What I've discovered is that ditching templates entirely provides much more opportunity for refactoring and abstraction. The problem with templates is that they force you to always think at the level of individual HTML tags. Once a tag is a method, it's much easier and more natural to start combining them into larger and larger methods and classes, and the wins from this are huge.
Avi moved towards ditching templates much earlier than I. The way he and I work when developing has, so far, not involved a designer and has resulted in us generating simple HTML with fairly minimal formatting. I have held on for quite some time arguing that this is likely not the way that many people will end up working.
I will say that for the type of stuff we seem to end up doing, templates do feel largely unnecessary and reuse is definitely improved. In Seaside 0.9x (and Iowa) I complained frequently about the lack of inheritance of behaviour and this was actually due in large part to the use of templates. So working with the code generation approach in the base levels of Seaside2 is somewhat liberating.
I also believe in following standards and best practices as much as possible, so I have also been pushing for quite some time to make it easier to use CSS with Seaside, to try to make sure we are generating HTML that is strictly valid, and to use divs and CSS for layout rather than nested tables. I think I have finally won Avi over in this regard (at least in terms of CSS... see below :) so we'll see what comes of this.
The other thing I've discovered simultaneously is that CSS is making templates less and less necessary - if your code produces bare bones HTML that's fully annotated with divs, spans, classes and ids, the designer has a lot of huge amount of control over the look through the CSS file. Going forward, this is where I think the division of responsibility should lie: the programmer produces the (X)HTML, and the designer controls the CSS.
I believe we need to enable a web designer to do as much as possible of the design, because I certainly don't want to have to do it. I am truly hopeful that CSS will provide enough control (along with a general cooperation between the developer and the designer) to do what is needed. I do, however have a sneaking suspicion that it isn't quite going to be enough in all cases. I think, though, that this is due mostly to the variations in implementation of HTML and CSS in various browsers. I think most of the ugly, crazy code that designers generate is to workaround bugs in various browsers. I am pretty confident that as we go forward and browsers begin to properly parse HTML (and soon, hopefully, XHMTL) and properly interpret the full range of CSS that such hacks will be unnecessary and we will finally be able to consider CSS sufficient.
[...further discussion snipped...]
Julian
Julian Fitzell julian@beta4.com wrote:
Avi Bryant wrote:
On Wed, 11 Dec 2002 goran.hultgren@bluefish.se wrote:
<lots about templating systems>
Ok, Avi, Julian, what do you think?
Since you ask...
I find any system that treats the template purely as text to be too low level - forcing me to textually insert a value or variable for every attribute of every form field is equivalent to writing a GUI app by making write() calls to a X-windows client socket; you might feel it gives you more control, but mostly what it does is make busywork and reduce abstraction. This rules out the large majority of the templating systems out there: variable subsitution systems like WebMacro or FreeMarker, typical use of embedded code systems like PHP and JSP, tag-languages like ColdFusion - in each case, every character of the final HTML output is the direct result of some piece of code the developer wrote. I won't even get into the evils of mingling logic and presentation that are inherent in most such systems, because they already fail on that basic principle: HTML and HTTP have very well defined structure and semantics, and a good templating system should know these intimately and largely protect me from them.
Avi and I work together a lot on this stuff so it's not surprising that we have generally the same beliefs. Whether this is the reason we work together or a cause of the fact that we work together, I'm not sure. But certainly the things we dislike about existing systems are pretty similar.
I know of three general approaches to avoiding this problem: parse the template and modify it programmatically, produce the HTML through (declarative) transformation of the data, or generate the HTML directly in code.
The first of these is the only one that's really "templating". It's the approach taken by WebObjects, Seaside 0.9x, and Enhydra/XMLC (used, I think, by Barracuda, which was mentioned elsewhere in this thread).
Yes, I looked at XMLC - there are some nice webpages to read there. Interesting approach. Someone complained about the performance of this solution but the XMLC people claim to use a technique they call "lazy DOM".
Interesting enough the page describing XMLC argued that the webdesigner first build a mockup with ids embedded and then feed that into XMLC which parses and produces the "DOM templates".
My idea that I outlined starts a bit earlier with a working system running in Seaside/HttpView generating very simple XHTML (more or less like today) but with id tags turned on for traceability. Given those pages the webdesigner can start whipping it into shape and then feed it back.
One thing needed to make this work is to differentiate between the truly *needed* XHTML and what is just "fluff" to make it look at least readable. Today my HttpView apps do have a little bit of "visual fluff" in them (even though I try to use CSS as much as possible) and it would be nice if I later - when the webdesigner has fed his "good looking pages" back into the system - could simply "turn off" that fluff.
Usually this involves producing some kind of a DOM from the template, finding and transforming some special elements (which were given unique ids in the template) while leaving the bulk of the elements alone, and the regenerating HTML from the modified DOM. Some systems provide better abstractions for this than others (Seaside and WebObjects provide sophisticated models of elements such as forms, links, and inputs, that you interact with in a fairly high level way, whereas I believe XMLC users tend still to directly manipulate HTML attributes), but once you have the DOM in memory you can obviously interact with it as abstractly as you like.
The only example of the second, transformative approach that I know of is XSLT. I've never used Coocoon or any other XSL-based system, so I don't feel terribly qualified to speak about them, but I don't know any designers *or* developers who don't shudder in horror at the thought of writing XSL. If somebody has good experiences with this approach, or knows what the current best practices are, I'd love to hear about it.
Me too. I have a collegue that likes XSL but I am trying to argue that webdesigners don't use it and don't know how to. Not their tools either, that's my guess of course.
I have also heard that performance is tricky.
Finally, there's the approach HttpView and Seaside2 take, which is not to have templates at all, but rather to generate all of the HTML programmatically. As someone who's spent a lot of time implementing and using template systems, this seemed at first horribly backwards. What I've discovered is that ditching templates entirely provides much more opportunity for refactoring and abstraction. The problem with templates is that they force you to always think at the level of individual HTML tags. Once a tag is a method, it's much easier and more natural to start combining them into larger and larger methods and classes, and the wins from this are huge.
Avi moved towards ditching templates much earlier than I. The way he and I work when developing has, so far, not involved a designer and has resulted in us generating simple HTML with fairly minimal formatting. I have held on for quite some time arguing that this is likely not the way that many people will end up working.
I have had this "nagging feeling" to about it but has postponed the issue since the apps I have been building so far hasn't been "glorified" by anyone but me.
I will say that for the type of stuff we seem to end up doing, templates do feel largely unnecessary and reuse is definitely improved. In Seaside 0.9x (and Iowa) I complained frequently about the lack of inheritance of behaviour and this was actually due in large part to the use of templates. So working with the code generation approach in the base levels of Seaside2 is somewhat liberating.
I also believe in following standards and best practices as much as possible, so I have also been pushing for quite some time to make it easier to use CSS with Seaside, to try to make sure we are generating HTML that is strictly valid, and to use divs and CSS for layout rather than nested tables. I think I have finally won Avi over in this regard (at least in terms of CSS... see below :) so we'll see what comes of this.
I also like this approach - I really tried to learn and read up on CSS when I designed www.bluefish.se. One thing I learned is that CSS works very fine for some things and totally fails in other areas. The most important area where it seems to have utterly failed is positioning. I *really* tried to make the first page work properly using CSS positioning but I couldn't make heads or tails of it - I was really close but never managed to get it working the same in both IE and Mozilla. And if I can't even do that then forget about the rest of the browsers...
I also read on www.evolt.org that they also had to fall back on tables for positioning. They apparently did a huge effort when redesigning their site and making it look good in a pletora of browsers using CSS. But they just caved in regarding positioning.
The other thing I've discovered simultaneously is that CSS is making templates less and less necessary - if your code produces bare bones HTML that's fully annotated with divs, spans, classes and ids, the designer has a lot of huge amount of control over the look through the CSS file. Going forward, this is where I think the division of responsibility should lie: the programmer produces the (X)HTML, and the designer controls the CSS.
I believe we need to enable a web designer to do as much as possible of the design, because I certainly don't want to have to do it. I am truly hopeful that CSS will provide enough control (along with a general cooperation between the developer and the designer) to do what is needed. I do, however have a sneaking suspicion that it isn't quite going to be enough in all cases. I think, though, that this is due
Totally agree.
mostly to the variations in implementation of HTML and CSS in various browsers. I think most of the ugly, crazy code that designers generate is to workaround bugs in various browsers. I am pretty confident that as we go forward and browsers begin to properly parse HTML (and soon, hopefully, XHMTL) and properly interpret the full range of CSS that such hacks will be unnecessary and we will finally be able to consider CSS sufficient.
I have my doubts. But the idea of going with the "programmatic" approach being able to add "tracking device ids and divs", then feeding the pages to the designer and back and producing some kind of internal template DOM-kindof thing and finally simply "turn off" the minimal visual fluff that was needed from the start feels like a real cool way of doing it. Sortof XMLC inspired but a bit more "round-trippy". :-)
The only thing I can't really see is how to handle the "component" aspect. The webdesigner wants to work with pages (I guess) but a page may be composed of Seaside/HttpView components of some sort. What do we do with the glorified page when it comes back? How would the mapping be done?
regards, Göran
On Thu, 12 Dec 2002 goran.hultgren@bluefish.se wrote:
I have my doubts. But the idea of going with the "programmatic" approach being able to add "tracking device ids and divs", then feeding the pages to the designer and back and producing some kind of internal template DOM-kindof thing and finally simply "turn off" the minimal visual fluff that was needed from the start feels like a real cool way of doing it. Sortof XMLC inspired but a bit more "round-trippy". :-)
I think generated tracking ids are going to be more trouble than they're worth - if they're generated, all they can really reflect is sequence, and that's not terribly stable. So I think we should be going on developer-provided ids, which means we might as well use the CSS id attribute (and ensure that everything thus has a CSS id while we're at it).
So what we're building is an HTML merge tool - you have to merge the HTML generation code with the HTML template from the designer. I've been thinking about how you would manage this with HtmlRenderer (or HV's HtmlBuilder), but actually, I think it would be much, much easier to do at the HTML level, when you have two complete pieces of output. That also means it could stand on its own, apart from either Seaside or HV.
So we narrow to this: you have two HTML documents, both with matching CSS ids, one with content, and one with presentation fluff. You want to merge the content from one into the fluff of the other.
As a first pass, how about this: take the fluffed document. Any element that is found that matches an element (same id) in the content document, has its attributes replaced with the equivalents from the content document. Elements whose only child is a piece of text, should have that text treated as an attribute as well. The tag names are always taken from the fluff document.
Once an element has been matched, its children should be matched against the children of the corresponding content element.
If a content element repeats, the corresponding template element should also be repeated.
So, if your content output is this:
<h1>Edit Names</h1>
<form id="names" action="1245"> <div id="nameRow"> <span class="label">1</td> <input type="text" name="1" id="name" value="Avi"> </div>
<div id="nameRow"> <span class="label">2</span> <input type="text" name="2" id="name" value="Goran"> </div>
<input type="submit"> </form>
and your template is this:
<form id="names"> <table> <tr> <td colspan="2">Edit Names</td> </tr> <tr id="nameRow"> <td class="label" align="right">42</td> <td><input type="text" id="name" size="40"></td> </tr> <tr> <td colspan="2"><input type="submit" value="Save"></td> </tr> </table>
then the final output should be this:
<form id="names" action="12345"> <table> <tr> <td colspan="2">Edit Names</td> </tr> <tr id="nameRow"> <td class="label" align="right">1</td> <td><input type="text" id="name" size="40" name="1" value="Avi"></td> </tr> <tr id="nameRow"> <td class="label" align="right">2</td> <td><input type="text" id="name" size="40" name="2" value="Goran"></td> </tr> <tr> <td colspan="2"><input type="submit" value="Save"></td> </tr> </table>
Now obviously those rules are somewhat open to interpretation, and we need to write some solid test cases, but I don't think they're impossible to implement, and they may be flexible enough to do what you want.
But then, it's late, so this may be gibberish.
The hardest part, incidentally, will be handling non-regular repeats. What if every nth row has an image in it that the others don't? How can the template represent that?
The only thing I can't really see is how to handle the "component" aspect. The webdesigner wants to work with pages (I guess) but a page may be composed of Seaside/HttpView components of some sort. What do we do with the glorified page when it comes back? How would the mapping be done?
Yes, it's awkward. Put some comments marking the beginning and end of each component, and split the template into those segments when you read it in. The comments will have info about which component class those segments should be attached to. The difficult part is that the same components will show up in multiple templates, and how do you pick which version to use?
Avi
Avi Bryant avi@beta4.com wrote:
On Thu, 12 Dec 2002 goran.hultgren@bluefish.se wrote:
I have my doubts. But the idea of going with the "programmatic" approach being able to add "tracking device ids and divs", then feeding the pages to the designer and back and producing some kind of internal template DOM-kindof thing and finally simply "turn off" the minimal visual fluff that was needed from the start feels like a real cool way of doing it. Sortof XMLC inspired but a bit more "round-trippy". :-)
I think generated tracking ids are going to be more trouble than they're worth - if they're generated, all they can really reflect is sequence, and that's not terribly stable. So I think we should be going on developer-provided ids, which means we might as well use the CSS id attribute (and ensure that everything thus has a CSS id while we're at it).
I actually was thinking of the CSS id. That's how XMLC does it I think and it wouldn't trip up any HTML tool. But what do you gain from having them "developer provided"?
So what we're building is an HTML merge tool - you have to merge the HTML generation code with the HTML template from the designer. I've been thinking about how you would manage this with HtmlRenderer (or HV's HtmlBuilder), but actually, I think it would be much, much easier to do at the HTML level, when you have two complete pieces of output. That also means it could stand on its own, apart from either Seaside or HV.
Hmmm, possibly. (this starts to sound like XSL... Hrmph.)
So we narrow to this: you have two HTML documents, both with matching CSS ids, one with content, and one with presentation fluff. You want to merge the content from one into the fluff of the other.
As a first pass, how about this: take the fluffed document. Any element that is found that matches an element (same id) in the content document, has its attributes replaced with the equivalents from the content document. Elements whose only child is a piece of text, should have that text treated as an attribute as well. The tag names are always taken from the fluff document.
Once an element has been matched, its children should be matched against the children of the corresponding content element.
If a content element repeats, the corresponding template element should also be repeated.
So, if your content output is this:
<h1>Edit Names</h1>
<form id="names" action="1245"> <div id="nameRow"> <span class="label">1</td> <input type="text" name="1" id="name" value="Avi"> </div>
<div id="nameRow"> <span class="label">2</span> <input type="text" name="2" id="name" value="Goran"> </div>
<input type="submit"> </form>
and your template is this:
<form id="names"> <table> <tr> <td colspan="2">Edit Names</td> </tr> <tr id="nameRow"> <td class="label" align="right">42</td> <td><input type="text" id="name" size="40"></td> </tr> <tr> <td colspan="2"><input type="submit" value="Save"></td> </tr> </table>
then the final output should be this:
<form id="names" action="12345"> <table> <tr> <td colspan="2">Edit Names</td> </tr> <tr id="nameRow"> <td class="label" align="right">1</td> <td><input type="text" id="name" size="40" name="1" value="Avi"></td> </tr> <tr id="nameRow"> <td class="label" align="right">2</td> <td><input type="text" id="name" size="40" name="2" value="Goran"></td> </tr> <tr> <td colspan="2"><input type="submit" value="Save"></td> </tr> </table>
Now obviously those rules are somewhat open to interpretation, and we need to write some solid test cases, but I don't think they're impossible to implement, and they may be flexible enough to do what you want.
But then, it's late, so this may be gibberish.
The hardest part, incidentally, will be handling non-regular repeats. What if every nth row has an image in it that the others don't? How can the template represent that?
Right, it gets complicated. When stuff gets dynamic it falls somewhat apart. But I like the general approach - more or less like I envision it - even though I can't see why you need "developer assigned" ids.
The only thing I can't really see is how to handle the "component" aspect. The webdesigner wants to work with pages (I guess) but a page may be composed of Seaside/HttpView components of some sort. What do we do with the glorified page when it comes back? How would the mapping be done?
Yes, it's awkward. Put some comments marking the beginning and end of each component, and split the template into those segments when you read it in. The comments will have info about which component class those segments should be attached to. The difficult part is that the same components will show up in multiple templates, and how do you pick which version to use?
Exactly. You need to somehow map "skins" onto the components depending on some form of context. "When this component is used in this page it should have this skin but not otherwise" or "This component should have this skin in all cases except when otherwise noted" etc.
The end result I am "after" is to provide an "active" application that the webdesigner can edit and run at the same time. More or less he/she saves the HTML into Dreamweaver, edits it, saves it in a special folder. Seaside/HttpView picks it up, finds a "page id" inside the file and "applies" the fluff somehow to the system. The designer does a reload and voíla it looks better (almost Swikilike in behaviour). Repeat. :-)
Avi
regards, Göran
I think this idea would be a really good approach. It's quite simple and will work in 90% of the (my) cases. So far I was used to develop web-apps as following: The designer created a simple prototype. Then I started coding the web-app - producing ugly, simple html (e.g. just forms without layout). The prototype was then used by the designer to create some nicer design. During the development process we had many iterations of "coding - designing". Most produced html code by the designer is a) tables (some very complex) and b) formatting (done with CSS). I think, an approach which enables an iterative workflow between programmer and designer would be what many people need.
If Avi's idea could be implemented, it would really be nice. The reminding 10 or 20% of special cases ("every 9th row has an image") would not be a too big disadvantage or problem, I think.
Adrian
----- Original Message ----- From: "Avi Bryant" avi@beta4.com Sent: Thursday, December 12, 2002 11:40 AM
So we narrow to this: you have two HTML documents, both with matching CSS ids, one with content, and one with presentation fluff. You want to merge the content from one into the fluff of the other.
As a first pass, how about this: take the fluffed document. Any element that is found that matches an element (same id) in the content document, has its attributes replaced with the equivalents from the content document. Elements whose only child is a piece of text, should have that text treated as an attribute as well. The tag names are always taken from the fluff document.
Once an element has been matched, its children should be matched against the children of the corresponding content element.
If a content element repeats, the corresponding template element should also be repeated.
So, if your content output is this:
<h1>Edit Names</h1>
<form id="names" action="1245"> <div id="nameRow"> <span class="label">1</td> <input type="text" name="1" id="name" value="Avi"> </div>
<div id="nameRow"> <span class="label">2</span> <input type="text" name="2" id="name" value="Goran"> </div>
<input type="submit"> </form>
and your template is this:
<form id="names"> <table> <tr> <td colspan="2">Edit Names</td> </tr> <tr id="nameRow"> <td class="label" align="right">42</td> <td><input type="text" id="name" size="40"></td> </tr> <tr> <td colspan="2"><input type="submit" value="Save"></td> </tr> </table>
then the final output should be this:
<form id="names" action="12345"> <table> <tr> <td colspan="2">Edit Names</td> </tr> <tr id="nameRow"> <td class="label" align="right">1</td> <td><input type="text" id="name" size="40" name="1" value="Avi"></td> </tr> <tr id="nameRow"> <td class="label" align="right">2</td> <td><input type="text" id="name" size="40" name="2" value="Goran"></td> </tr> <tr> <td colspan="2"><input type="submit" value="Save"></td> </tr> </table>
Now obviously those rules are somewhat open to interpretation, and we need to write some solid test cases, but I don't think they're impossible to implement, and they may be flexible enough to do what you want.
But then, it's late, so this may be gibberish.
The hardest part, incidentally, will be handling non-regular repeats. What if every nth row has an image in it that the others don't? How can the template represent that?
The only thing I can't really see is how to handle the "component" aspect. The webdesigner wants to work with pages (I guess) but a page may be composed of Seaside/HttpView components of some sort. What do we do with the glorified page when it comes back? How would the mapping be done?
Yes, it's awkward. Put some comments marking the beginning and end of each component, and split the template into those segments when you read it in. The comments will have info about which component class those segments should be attached to. The difficult part is that the same components will show up in multiple templates, and how do you pick which version to use?
Avi
On Thu, 12 Dec 2002, Adrian Lienhard wrote:
I think this idea would be a really good approach. It's quite simple and will work in 90% of the (my) cases.
<snip>
If Avi's idea could be implemented, it would really be nice. The reminding 10 or 20% of special cases ("every 9th row has an image") would not be a too big disadvantage or problem, I think.
Well, I'll make you a deal - if you write the test cases (of the form "self assertContentHtml: '...' mergedWithDesignHtml: '...' yieldsHtml: '...'"), I'll try to make them pass. :)
Avi
On Thursday 12 December 2002 03:53 pm, Adrian Lienhard wrote:
I think this idea would be a really good approach. It's quite simple and will work in 90% of the (my) cases. So far I was used to develop web-apps as following: The designer created a simple prototype. Then I started coding the web-app - producing ugly, simple html (e.g. just forms without layout). The prototype was then used by the designer to create some nicer design. During the development process we had many iterations of "coding - designing". Most produced html code by the designer is a) tables (some very complex) and b) formatting (done with CSS). I think, an approach which enables an iterative workflow between programmer and designer would be what many people need.
If Avi's idea could be implemented, it would really be nice. The reminding 10 or 20% of special cases ("every 9th row has an image") would not be a too big disadvantage or problem, I think.
Adrian
Why not just use 'morphs' that represent controls, tables, etc, that have tags that developers can define that 'hook' into post-get messages, but can be decorated with CSS/HTML/etc attributes....
Then, just as you can ask a page to spit itself out as a postscript image, ask the morphs to spit themselves out as HTML and CSS files?
Since the nesting heirarchy of the HTML design morphs would match the nesting heirarchy of the CSS tags, then one can handle the nesting rules for CSS too ( context sensitive CSS, "When <a> is inside a <td> then decorate it like so ).
So the designer can design the layout, and the programmer can say "Okay, this is a drop down box that contains this, and sends this back to the server.... "
IE, a UI layout widget that handles both....
The layout guy could shift them around, and the programmer could make sure the program hooks are all there for the form submits, etc....
-Daniel
I also like this approach - I really tried to learn and read up on CSS when I designed www.bluefish.se. One thing I learned is that CSS works very fine for some things and totally fails in other areas. The most important area where it seems to have utterly failed is positioning. I *really* tried to make the first page work properly using CSS positioning but I couldn't make heads or tails of it - I was really close but never managed to get it working the same in both IE and Mozilla. And if I can't even do that then forget about the rest of the browsers...
I also read on www.evolt.org that they also had to fall back on tables for positioning. They apparently did a huge effort when redesigning their site and making it look good in a pletora of browsers using CSS. But they just caved in regarding positioning.
Plain and simple, IE is broke... It does NOT have a complete implementation of CSS level 1 or 2. Konqueror, Galeon, and Mozilla are much farther along in that regard.
CSS is a fine spec, and works fine on compliant webbrowsers. Cute hover-over menus and directories can be made in it. But IE is just plain broke as usual...
CSS positioning is simple, just realize that IE will not render it properly
-Daniel
Julian,
I am pretty confident that as we go forward and browsers begin to properly parse HTML (and soon, hopefully, XHMTL) and properly interpret the full range of CSS that such hacks will be unnecessary and we will finally be able to consider CSS sufficient.
What? Properly parse HTML? Why would you want to do that?
Anyway...I've occassionaly thought this about the designer problem: Just give them some fully rendered examples of the pages in your app...let them go nuts re-designing it, then have the developers fold the changes back into the system. That way you can use whatever web application framework that makes sense and maintain control over how it all hangs together with the application.
- Stephen
"Stephen Pair" spair@acm.org wrote:
Julian,
I am pretty confident that as we go forward and browsers begin to properly parse HTML (and soon, hopefully, XHMTL) and properly interpret the full range of CSS that such hacks will be unnecessary and we will finally be able to consider CSS sufficient.
What? Properly parse HTML? Why would you want to do that?
:-)
Anyway...I've occassionaly thought this about the designer problem: Just give them some fully rendered examples of the pages in your app...let them go nuts re-designing it, then have the developers fold the changes back into the system. That way you can use whatever web application framework that makes sense and maintain control over how it all hangs together with the application.
In some ways I agree. But if we could come up with a simple enough scheme that covers 80% then it could still be useful.
I like the idea of having a designer being able to edit the pages "in place" somehow and just press reload to see how it looks. I also like the idea for the developer to code the application logic once and then not need to change that just because the pages need "fluff".
- Stephen
regards, Göran
On Thursday, December 12, 2002, at 06:06 AM, Stephen Pair wrote:
Julian,
I am pretty confident that as we go forward and browsers begin to properly parse HTML (and soon, hopefully, XHMTL) and properly interpret the full range of CSS that such hacks will be unnecessary and we will finally be able to consider CSS sufficient.
What? Properly parse HTML? Why would you want to do that?
Anyway...I've occassionaly thought this about the designer problem: Just give them some fully rendered examples of the pages in your app...let them go nuts re-designing it, then have the developers fold the changes back into the system. That way you can use whatever web application framework that makes sense and maintain control over how it all hangs together with the application.
That's fine if you only have one iteration. But if the designer is tweaking the look every week, he drives the programmer nuts with change requests for trivialities as far as the programmer is concerned.
Colin Putney Whistler.com
Hmm... this doesn't seem to have shown up on the list... I'm sending it again. Apologies if it appears twice.
---------------------------------------
Avi Bryant wrote:
On Wed, 11 Dec 2002 goran.hultgren@bluefish.se wrote:
<lots about templating systems>
Ok, Avi, Julian, what do you think?
Since you ask...
I find any system that treats the template purely as text to be too low level - forcing me to textually insert a value or variable for every attribute of every form field is equivalent to writing a GUI app by making write() calls to a X-windows client socket; you might feel it gives you more control, but mostly what it does is make busywork and reduce abstraction. This rules out the large majority of the templating systems out there: variable subsitution systems like WebMacro or FreeMarker, typical use of embedded code systems like PHP and JSP, tag-languages like ColdFusion - in each case, every character of the final HTML output is the direct result of some piece of code the developer wrote. I won't even get into the evils of mingling logic and presentation that are inherent in most such systems, because they already fail on that basic principle: HTML and HTTP have very well defined structure and semantics, and a good templating system should know these intimately and largely protect me from them.
Avi and I work together a lot on this stuff so it's not surprising that we have generally the same beliefs. Whether this is the reason we work together or a cause of the fact that we work together, I'm not sure. But certainly the things we dislike about existing systems are pretty similar.
I know of three general approaches to avoiding this problem: parse the template and modify it programmatically, produce the HTML through (declarative) transformation of the data, or generate the HTML directly in code.
The first of these is the only one that's really "templating". It's the approach taken by WebObjects, Seaside 0.9x, and Enhydra/XMLC (used, I think, by Barracuda, which was mentioned elsewhere in this thread). Usually this involves producing some kind of a DOM from the template, finding and transforming some special elements (which were given unique ids in the template) while leaving the bulk of the elements alone, and the regenerating HTML from the modified DOM. Some systems provide better abstractions for this than others (Seaside and WebObjects provide sophisticated models of elements such as forms, links, and inputs, that you interact with in a fairly high level way, whereas I believe XMLC users tend still to directly manipulate HTML attributes), but once you have the DOM in memory you can obviously interact with it as abstractly as you like.
The only example of the second, transformative approach that I know of is XSLT. I've never used Coocoon or any other XSL-based system, so I don't feel terribly qualified to speak about them, but I don't know any designers *or* developers who don't shudder in horror at the thought of writing XSL. If somebody has good experiences with this approach, or knows what the current best practices are, I'd love to hear about it.
Finally, there's the approach HttpView and Seaside2 take, which is not to have templates at all, but rather to generate all of the HTML programmatically. As someone who's spent a lot of time implementing and using template systems, this seemed at first horribly backwards. What I've discovered is that ditching templates entirely provides much more opportunity for refactoring and abstraction. The problem with templates is that they force you to always think at the level of individual HTML tags. Once a tag is a method, it's much easier and more natural to start combining them into larger and larger methods and classes, and the wins from this are huge.
Avi moved towards ditching templates much earlier than I. The way he and I work when developing has, so far, not involved a designer and has resulted in us generating simple HTML with fairly minimal formatting. I have held on for quite some time arguing that this is likely not the way that many people will end up working.
I will say that for the type of stuff we seem to end up doing, templates do feel largely unnecessary and reuse is definitely improved. In Seaside 0.9x (and Iowa) I complained frequently about the lack of inheritance of behaviour and this was actually due in large part to the use of templates. So working with the code generation approach in the base levels of Seaside2 is somewhat liberating.
I also believe in following standards and best practices as much as possible, so I have also been pushing for quite some time to make it easier to use CSS with Seaside, to try to make sure we are generating HTML that is strictly valid, and to use divs and CSS for layout rather than nested tables. I think I have finally won Avi over in this regard (at least in terms of CSS... see below :) so we'll see what comes of this.
The other thing I've discovered simultaneously is that CSS is making templates less and less necessary - if your code produces bare bones HTML that's fully annotated with divs, spans, classes and ids, the designer has a lot of huge amount of control over the look through the CSS file. Going forward, this is where I think the division of responsibility should lie: the programmer produces the (X)HTML, and the designer controls the CSS.
I believe we need to enable a web designer to do as much as possible of the design, because I certainly don't want to have to do it. I am truly hopeful that CSS will provide enough control (along with a general cooperation between the developer and the designer) to do what is needed. I do, however have a sneaking suspicion that it isn't quite going to be enough in all cases. I think, though, that this is due mostly to the variations in implementation of HTML and CSS in various browsers. I think most of the ugly, crazy code that designers generate is to workaround bugs in various browsers. I am pretty confident that as we go forward and browsers begin to properly parse HTML (and soon, hopefully, XHMTL) and properly interpret the full range of CSS that such hacks will be unnecessary and we will finally be able to consider CSS sufficient.
[...further discussion snipped...]
Julian
Somewhat related to this I am working on a hierarchy of Widgets that know how to emit themselves as HTML or PDF (and perhaps as XML, etc. sometime in the future), which leaves you coding only in Smalltalk. These widgets are added to a Document (currently only HTML, PDF soon to come) and the document can then be rendered. For the actual UI design, I still depend on a UI team to give me mock ups of the design, and I simply build Screen classes which reflect that design by creating Widgets to be added to Documents.
=jason
On Wed, 2002-12-11 at 08:29, goran.hultgren@bluefish.se wrote:
Hi all!
I am currently learning a bit more about the current crop of different "templating mechanisms" primarily used for web page generation that are in use in the industry today. My list sofar is more or less like this:
- A simple "variable substitution" engine. You can easily hack one of
these yourself and I have seen it used the webenging of 4D for example. Typically everyone implements "their own" and there are tons of these out there on the net. Typically quite primitive and can't deal with stuff like "loops" etc.
- Proprietary template mecanisms in web application servers. Seemingly
there are many of these too which are probably more advanced than the above "hacks" but still not "standard" in any way.
- Embedding "custom tags". ColdFusion did this early on and it is a
"simple" idea that makes all the HTML tools behave quite ok. At least earlier they just ignored tags they couldn't understand (and hopefully didn't remove them) and nowadays they probably deal with them nicely (since XHTML has taken the scene). What the tags are capable of is still up to the proprietary product of course.
- JSP/ASP-pages. From the beginning these approaches were based on
embedding imperative serverside code in HTML pages but according to a collegue "JSP best practices" is currently to use "custom tags with parameters" instead making this apporach more declarative and in fact "just another template engine" I guess.
- XML+XSL. XSL is a XML-based language that can describe very complex
transforms of XML-documents into other XML-documents. As "standard" as it gets. Which mean tons of tools and tutorials and websites etc but at the sime time quite complex IMHO. Sure, you don't need to use all that complexity but I have heard that one before... ;-)
- Seaside/HttpView. In Seaside and HttpView we have taken a
Smalltalk-centric approach (well, Seaside has multiple approaches I think) where we "build" HTML using smalltalk. Almost like DOM but more "streamish", at least in HttpView.
Well, surely there are other approaches out there too.
When I did HttpView I was sick of everything called JSP/ASP and wanted something much simpler and direct. I also wanted something that could work with Forms in a very easy way. The end result turned into a HtmlBuilder object that produces XHTML. Since CSS has come quite a long way and you typically only have one or very few CSS-files this meant that there was essentially only one source for a page - the Smalltalk code. Nice and simple.
I had an intention to implement new HtmlBuilder classes that could also "merge" the HTML into some form of template coming from the "outside". Exactly how that could work is still a bit clouded. One way could be to not change anything and just slap an XSL engine "on top" that can add "looks" as a last step before hitting the client browser. Another way could be to create some "custom" highlevel XML document and feed that into an XSL engine to turn it into XHTML with looks.
Or perhaps use some other templating mechanism that can let the "HTML gurus" do their job. For example - here is one interesting approach that may be impossible:
- Build the webapp as simply as possible but actually working.
- Turn on some form of "ids in tags" generation which means that the
HtmlBuilder adds ids in the generated tags to keep track of them. 3. Let the designer run the app and simply do "Save as..." on the HTML pages/HTML components. (Given that any given component easily can be addressed separately or at least "cut out" from an HTML page, for example if contained within a div-tag). Of course you could let the serverside app save out the HTML pages instead of returning them through HTTP, etc. whatever. 4. Let the designer edit them into glorious looking HTML that no mortal can ever read. 5. Feed the new HTML pages (and CSS+any scripts of course) back into the HtmlBuilder that somehow can take the original page and the "glorified" page and from that (and the embedded "track" tag ids) construct an internal template of some kind. 6. Turn of the tag ids, they aren't useful anymore - they were only used for tracking the generated tags.
Anyway, perhaps the above is impossible to accomplish - but it would be cool if it did. I can focus on coding Smalltalk and a simple subset of XHTML, the designer can focus on webpage "good looks" and doesn't need to handcode XSL or anything.
Ok, now Avi and Julian - what do you think? What is the ultimate templating mechanism? :-)
regards, Göran
Sorry for jumping in so late. I don't get to read this list on a daily (or rather minute by minute) basis, so I didn't read the rest of the thread before replying. As I read through, it seemed there came a consensus to using Widgets. However, I can now offer some real world experience where we use this approach in a Java webapp for an Organ Transplantation tracking and information system. We use the Widget/Screen/Document approach for generating all of our HTML and PDF. We have a Human Interaction Team (affectionately known as the HIT Squad) that gives us mock-ups of the UI. We have been using this system and adapting it for nearly two years. It has really helped us a lot in the presentation layer and I would have only traded it out for the same thing written in Smalltalk.
The hierarchy of classes I am writing now are based on that experience (pluses, minuses, everything)...
=jason
On Thu, 2002-12-12 at 12:13, Jason Rogers wrote:
Somewhat related to this I am working on a hierarchy of Widgets that know how to emit themselves as HTML or PDF (and perhaps as XML, etc. sometime in the future), which leaves you coding only in Smalltalk. These widgets are added to a Document (currently only HTML, PDF soon to come) and the document can then be rendered. For the actual UI design, I still depend on a UI team to give me mock ups of the design, and I simply build Screen classes which reflect that design by creating Widgets to be added to Documents.
=jason
On Wed, 2002-12-11 at 08:29, goran.hultgren@bluefish.se wrote:
Hi all!
I am currently learning a bit more about the current crop of different "templating mechanisms" primarily used for web page generation that are in use in the industry today. My list sofar is more or less like this:
- A simple "variable substitution" engine. You can easily hack one of
these yourself and I have seen it used the webenging of 4D for example. Typically everyone implements "their own" and there are tons of these out there on the net. Typically quite primitive and can't deal with stuff like "loops" etc.
- Proprietary template mecanisms in web application servers. Seemingly
there are many of these too which are probably more advanced than the above "hacks" but still not "standard" in any way.
- Embedding "custom tags". ColdFusion did this early on and it is a
"simple" idea that makes all the HTML tools behave quite ok. At least earlier they just ignored tags they couldn't understand (and hopefully didn't remove them) and nowadays they probably deal with them nicely (since XHTML has taken the scene). What the tags are capable of is still up to the proprietary product of course.
- JSP/ASP-pages. From the beginning these approaches were based on
embedding imperative serverside code in HTML pages but according to a collegue "JSP best practices" is currently to use "custom tags with parameters" instead making this apporach more declarative and in fact "just another template engine" I guess.
- XML+XSL. XSL is a XML-based language that can describe very complex
transforms of XML-documents into other XML-documents. As "standard" as it gets. Which mean tons of tools and tutorials and websites etc but at the sime time quite complex IMHO. Sure, you don't need to use all that complexity but I have heard that one before... ;-)
- Seaside/HttpView. In Seaside and HttpView we have taken a
Smalltalk-centric approach (well, Seaside has multiple approaches I think) where we "build" HTML using smalltalk. Almost like DOM but more "streamish", at least in HttpView.
Well, surely there are other approaches out there too.
When I did HttpView I was sick of everything called JSP/ASP and wanted something much simpler and direct. I also wanted something that could work with Forms in a very easy way. The end result turned into a HtmlBuilder object that produces XHTML. Since CSS has come quite a long way and you typically only have one or very few CSS-files this meant that there was essentially only one source for a page - the Smalltalk code. Nice and simple.
I had an intention to implement new HtmlBuilder classes that could also "merge" the HTML into some form of template coming from the "outside". Exactly how that could work is still a bit clouded. One way could be to not change anything and just slap an XSL engine "on top" that can add "looks" as a last step before hitting the client browser. Another way could be to create some "custom" highlevel XML document and feed that into an XSL engine to turn it into XHTML with looks.
Or perhaps use some other templating mechanism that can let the "HTML gurus" do their job. For example - here is one interesting approach that may be impossible:
- Build the webapp as simply as possible but actually working.
- Turn on some form of "ids in tags" generation which means that the
HtmlBuilder adds ids in the generated tags to keep track of them. 3. Let the designer run the app and simply do "Save as..." on the HTML pages/HTML components. (Given that any given component easily can be addressed separately or at least "cut out" from an HTML page, for example if contained within a div-tag). Of course you could let the serverside app save out the HTML pages instead of returning them through HTTP, etc. whatever. 4. Let the designer edit them into glorious looking HTML that no mortal can ever read. 5. Feed the new HTML pages (and CSS+any scripts of course) back into the HtmlBuilder that somehow can take the original page and the "glorified" page and from that (and the embedded "track" tag ids) construct an internal template of some kind. 6. Turn of the tag ids, they aren't useful anymore - they were only used for tracking the generated tags.
Anyway, perhaps the above is impossible to accomplish - but it would be cool if it did. I can focus on coding Smalltalk and a simple subset of XHTML, the designer can focus on webpage "good looks" and doesn't need to handcode XSL or anything.
Ok, now Avi and Julian - what do you think? What is the ultimate templating mechanism? :-)
regards, Göran
squeak-dev@lists.squeakfoundation.org