Lift 2.2-M1 introduces designer-friendly HTML templates.All Lift templates can be fully valid XHTML or HTML5 with no extra namespaces, yet retain all of Lift’s features.The enhancements to Lift include:
<!DOCTYPE...>
elementsBefore 2.2-M1, a typical Lift template looked like:
<lift:surround with="default" at="content">
<h2>Welcome to your project!</h2>
<p>
<lift:HelloWorld.howdy>
<span class="my_class">Welcome to app at<b:time/></span>
</lift:HelloWorld.howdy>
</p>
</lift:surround>
The <lift:surround>
tag invoked the “surround” snippet which surrounds the content of the template with the template page chrome.The <lift:surround>
and <lift:HelloWorld.howdy>
tags invoke snippets, but these tags are not valid XHTML or HTML5 without declaring the separate “lift” namespace.
Instead, we can invoke snippets via the class attribute on nodes.For example:
<div class="lift:surround?with=default;at=content">
<h2>Welcome to your project!</h2>
<p>
<span class="my_class lift:HelloWorld.howdy">
<span>Welcome to app at<b:time/></span>
</span>
</p>
</div>
We’re almost to the point where we’ve removed new namespaces from the template . Here’s the Scala code for HelloWorld:
class HelloWorld {
def howdy(in: NodeSeq): NodeSeq =
Helpers.bind("b", in, "time" ->Helpers.formattedTimeNow)
}
Using CSS Selector Transforms, HelloWorld becomes:
class HelloWorld {
def howdy = ".time" #>Helpers.formattedTimeNow
}
And the template becomes:
<div class="lift:surround?with=default;at=content">
<h2>Welcome to your project!</h2>
<p>
<span class="my_class lift:HelloWorld.howdy">
<span>Welcome to app at<span class="time">no time like the present</span></span>
</span>
</p>
</div>
Thus, we’ve eliminated the extra namespaces.We’re well on our way to having a single file in the source repository that can be opened in a browser, opened and edited by designers and coders alike.
We still can’t load the page into our browser because it doesn’t have an <html>
or <body>
tag… so, we have to find a way to put this chrome around the page, but have Lift dynamically replace the chrome using the surround mechanism.
So, we want our template file to look like:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type" />
<title>Home</title>
</head>
<body>
<div class="lift:surround?with=default;at=content">
<h2>Welcome to your project!</h2>
<p>
<span class="lift:helloWorld.howdy">
Welcome to your Lift app at<span id="time">Time goes here</span>
</span>
</p>
</div>
</body>
</html>
But how do we get the surround functionality and do away with the boilerplate chrome… mark the actual root element with an id, for example “real_content” and put the following class in the body tag:lift:content_id=real_content , so the template looks like:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type" />
<title>Home</title>
</head>
<body class="lift:content_id=real_content">
<div class="lift:surround?with=default;at=content" id="real_content">
<h2>Welcome to your project!</h2>
<p>
<span class="lift:helloWorld.howdy">
Welcome to your Lift app at<span id="time">Time goes here</span>
</span>
</p>
</div>
</body>
</html>
And now we’ve got a template that’s completely valid and contains all the Lift logic, but is designer friendly.