Version 6, last updated by guy.bolton.king at December 01, 2010 03:17 UTC

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:

Before 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 (binding as part of Lift’s NodeSeq => NodeSeq snippet transformation used to require a snippet-specific namespace to do binding). 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 (the one with the surround snippet) 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.