HTMLTemplate tutorials

Copyright (C) 2004 HAS


----------------------------------------------------------------------
CONTENTS

- Generating a basic links page

- Grouping and repeating nodes as a single block

- TO DO: more examples


----------------------------------------------------------------------
TUTORIALS

======= Generating a basic links page =======

1. The following HTML template contains three elements (<title>, <li>, <a>) containing compiler directives (node="con:title", node="rep:item", node="con:link"):

	html = """
	<html>
		<head>
			<title node="con:title">TITLE</title>
		</head>
		<body>
			<ul>
				<li node="rep:item">
					<a href="" node="con:link">LINK</a>
				</li>
			</ul>
		</body>
	</html>
	"""


HTMLTemplate will compile this template to the following object model:

	Template
	    |
	    |----title
	    |
	    |----item
	    |      |
	    |      |----link


2. Both the Template and Repeater ('rep:item') nodes require callback functions to control their rendering.

The main 'renderTemplate' callback function inserts text into the <title> element and generates a list of <li> items:

	def renderTemplate(tem, pagetitle, linksinfo):
		tem.title.content = pagetitle
		tem.item.repeat(renderItem, linksinfo)

This function takes a copy of the Template object as its first argument, followed by two user-supplied arguments containing the data to be inserted into the template:

	pagetitle : string -- the page title
	linksinfo : list of tuple -- a list of form [(URI, name),...]


The repeat() method call in the 'renderTemplate' function takes a second callback function, 'renderItem' to control the rendering of each <li> list item and its <a> element:

	def renderItem(item, linkinfo):
		URI, name = linkinfo
		item.link.atts['href'] = URI
		item.link.content = name


3. Compiling the template is simple. Just create a new Template instance, passing it the 'renderTemplate' function and the HTML template as a string:

	template = HTMLTemplate.Template(renderTemplate, html)


4. To render a page, call the Template object's render() method, passing it any data to be forwarded to the renderTemplate function:

	title = "Site Map"
	links = [('index.html', 'Home'), ('products/index.html', 'Products'), ('about.html', 'About')]
	print template.render(title, links)

Here's the result:

	<html>
		<head>
			<title>Site Map</title>
		</head>
		<body>
			<ul>
				<li>
					<a href="index.html">Home</a>
				</li>
	<li>
					<a href="products/index.html">Products</a>
				</li>
	<li>
					<a href="about.html">About</a>
				</li>
			</ul>
		</body>
	</html>



======= Grouping and repeating nodes as a single block =======

 When designing an HTML template, you'll sometimes need to insert additional HTML elements (typically <div> and <span>) to allow you to define template nodes in the proper locations. For example, to generate a page like:

	<h2>title 1</h2>
	<p>description 1</p>

	<h2>title 2</h2>
	<p>description 2</p>

	<h2>title 3</h2>
	<p>description 3</p>

you need to repeat the <h2> and <p> elements as a single block. A common mistake for beginners is to write:

	<h2 node="rep:title">section title</h2>
	<p node="rep:desc">section description</p>

but this template generates the following output, which is not what you want:

	<h2>title 1</h2>
	<h2>title 2</h2>
	<h2>title 3</h2>
	<p>description 1</p>
	<p>description 2</p>
	<p>description 3</p>

The solution is to group the <h2> and <p> elements within a single Repeater node and repeat that. To do this, first wrap them in a <div> element:

	<div>
		<h2>section title</h2>
		<p>section description</p>
	</div>

Now mark this <div> as a Repeater object:

	<div node="rep:section">
		<h2>section title</h2>
		<p>section description</p>
	</div>

then mark the <h2> and <p> elements as Containers:

	<div node="rep:section">
		<h2 node="con:title">section title</h2>
		<p node="con:desc">section description</p>
	</div>

When rendered, this template will generate the following:

	<div>
		<h2>title 1</h2>
		<p>description 1</p>
	</div>
	<div>
		<h2>title 2</h2>
		<p>description 2</p>
	</div>
	<div>
		<h2>title 3</h2>
		<p>description 3</p>
	<div>

Finally, if the <div> tags serve no useful purpose in the finished page then you can omit them using the 'minus tags' modifer:

	<div node="-rep:section">
		<h2 node="con:title">section title</h2>
		<p node="con:desc">section description</p>
	</div>

Here's how the finished page will typically look:

	
		<h2>title 1</h2>
		<p>description 1</p>
	

		<h2>title 2</h2>
		<p>description 2</p>
	

		<h2>title 3</h2>
		<p>description 3</p>
	

