The physical layout and cosmetic design of a web site requires skill and effort that is often beyond or not in line with the responsibilities of a typical software developer. Approaches have been taken to separate coding logic from the web page view. The tiles (link) framework and JSP templates are examples of approaches that address easing maintenance and reusability of web page layouts. But I believe these approaches are a bit backwards. They are built around the concept of template pages that determine the layout of content and directly pull in the relevant "sub-pages". So these templates take on the responsibilities of how the types of content should be laid out and what content should be included in each page. This document proposes another approach where the template determines the layout but the "child pages" determine the specific content and insert it into the master template.
As I see it, the trouble with the typical approach applies to all types of web pages (jsp, asp, html, etc.). I will use *.jsp pages in this example. Consider this simple template:
<html>
<head>
<title><!-- title here --></title>
</head>
<body>
<div id="header">
<!-- header content here -->
</div>
<div id="body">
<!-- body content here -->
</div>
<div id="footer">
<!-- body content here -->
</div>
</body>
</html>
Let's say we want to use this template to create a web page of recipes. We could make a copy of this template for each recipe and include the relevant content sub-pages in each:
<html>
<head>
<title>English Muffin</title>
</head>
<body>
<div id="header">
<%@ include file="./eng-muff-header.jsp" %>
</div>
<div id="body">
<%@ include file="./eng-muff-recipe.jsp" %>
</div>
<div id="footer">
<%@ include file="./eng-muff-footer.jsp" %>
</div>
</body>
</html>
<html>
<head>
<title>Lasagna</title>
</head>
<body>
<div id="header">
<%@ include file="./lasagna-header.jsp" %>
</div>
<div id="body">
<%@ include file="./lasagna-recipe.jsp" %>
</div>
<div id="footer">
<%@ include file="./lasagna-footer.jsp" %>
</div>
</body>
</html>
You can imagine how the content of the different included files will result in different composite JSP files (recipes for English muffins, lasagna, etc.). If you can't imagine it, maybe this helps:
Now let's say create a new web page template that has all sorts of new div's and images and looks just great. You want to use this new template and place all your existing content in it. With the approach above, there is a file for every recipe. Since the html layouts are different, a lot of work has to be done to re-wrap each recipe with the new layout. The basis of the problem is this: the “template" was more than a boilerplate as to how content should be arranged - - it determined what specific content should be included in each of files that were based on it.
This document proposes an approach that would address this problem. Let's re-look at the example above starting with the template:
<html>
<head>
<title>{{=$title}}</title>
</head>
<body>
<div id="header">
{{=#header}}
</div>
<div id="body">
{{=#body}}
</div>
<div id="footer">
{{=#footer}}
</div>
</body>
</html>
The obvious change is that this template no longer has “inlclude" directives in it. These notations, which I've made up arbitrarily:
{{=#header}}
{{=#body}}
{{=#footer}}
represent placeholders for content that should be inserted into the JSP template. Much like the mail merge paradigm, this file is meaningless from a content point of view by itself. It needs a source of data to drive its content.
Here's how the recipe files would look:
<@merge into="./template.cwpt" dest="./eng-muffin.jsp>
#{{
$title = “English Muffin Recipe"
}}
#header {{
<%@ include file="./eng-muff-header.jsp" %>
}}
#body {{
<%@ include file="./eng-muff-recipe.jsp" %>
}}
#footer {{
<%@ include file="./eng-muff-footer.jsp" %>
}}
<@merge into="./template.cwpt" dest="./lasagna.jsp>
#{{
$title = “Lasagna Recipe"
}}
#header {{
<%@ include file="./lasagna-header.jsp" %>
}}
#body {{
<%@ include file="./lasagna-recipe.jsp" %>
}}
#footer {{
<%@ include file="./lasagna-footer.jsp" %>
}}
Since the content files don't have any concept of the web page layout, a completely different layout for all the recipes could be achieved by creating a new template.cwpt file.
Most the mechanics of this approach involve constructs that don't exist yet. Let me explain how this is intended to work.
The merge directive would tell a pre-processor to merge its contents into the template file indicate by the “into" attribute and create a resulting file named by the “dest" attribute.
These source files define content constructs and give them names. These names will match the placeholder names in the “merge into" template.
These constructs are used to define string variables that can be merged into a template, similarly to how html content blocks are merged.
So the contents of the eng-muff.cwpt file would be merged by a pre-processor into the template.cwpt file. The placeholders in that file would be replaced as follows:
| Template file: template.cwpt | Content file: eng-muff.cwpt | Resulting file: eng-muffin.jsp |
|---|---|---|
<html>
<head>
|
<@merge into="./template.cwpt" dest="./eng-muffin.jsp> |
<html>
<head>
|
<title>{{=$title}}>/title>
|
#{{
$title = “English Muffin Recipe"
}}
|
<title>{{=$title}}</title>
|
</head>
<body>
<div id="header">
|
|
</head>
<body>
<div id="header">
|
{{=#header}}
|
#header {{
<%@ include file="./eng-muff-header.jsp" %>
}}
|
<%@ include file="./eng-muff-header.jsp" %>
|
</div>
<div id="body">
|
|
</div>
<div id="body">
|
{{=#body}}
|
#body {{
<%@ include file="./eng-muff-recipe.jsp" %>
}}
|
<%@ include file="./eng-muff-recipe.jsp" %>
|
</div>
<div id="footer">
|
|
</div>
<div id="footer">
|
{{=#footer}}
|
#footer {{
<%@ include file="./eng-muff-footer.jsp" %>
}}
|
<%@ include file="./eng-muff-footer.jsp" %>
|
</div>
</body>
</html>
|
|
</div>
</body>
</html>
|
In order to realize this idea without any changes to the JSP specification, the following tools would be practical.
The ANT task should merge all .cwpt files into their JSP (or whatever) targets and move these files to the appropriate destination folder in the web application project.
An Eclipse plug-in that brought the files together on a virtual page would assist with page creation. The editor in the plug-in should arrange and identify the different file components in the merge sequence.