Theming with templates

The last part of our template system is a theme function that can make use of the template.

Based on the jQuery ready handler we just wrote, we now have a template stored in TplHtml.template.node. Here, we need to provide a function that will take that template and then populate it with data.

To do this, we will once again use jQuery since it provides powerful tools for navigating HTML and modifying the document's structure. Here's our new function:

Drupal.theme.node = function (node) { var out = '';

if (TplHtml.template.node) {

var tpl = $(TplHtml.template.node);

// Do title and title's link at the same time, if (!node.nodeUrl) node.nodeUrl = '#'; tpl.find('.title a').text(node.title) .attr('href', node.nodeUrl);

// These are the things we are going to place in // the template.

// Fortunately for us, class names match 1-to-1 with // the names of the node properties.

var values = ['content,,,submitted,,,taxonomy,,,links']; for (var i = 0; i < values.length; ++i) { var value = values[i]; if (node[value]) {

// Now we dump the template to a string, out = tpl.parent().html();

return out;

Though this function is large, it doesn't use any new functions or techniques. In fact, all it is doing is taking the node data and the TplHtml.template.node template, and merging the data into the template.

To get through this large function, let's look at it in smaller chunks:

Drupal.theme.node = function (node) {

The theme function takes one parameter: node. This parameter is expected to be an object and may have any of the following properties:

• node.title: The title of the node. This is the only required item.

• node.nodeUrl: The relative URL of the node.

• node.sticky: A flag indicating whether this node should be treated as sticky at the top of the page. (The default is false.)

• node.content: The content of the node.

• node.submitted: Information about the date and submitter of the node.

• node.taxonomy: A string containing hyperlinks to taxonomy terms.

• node.links: A string containing additional links (like to comments).

As we build up the layout, we will put each bit of node information into its appropriate place in the template.

Let's take a look at the next section of the function:

Drupal.theme.node = function (node) { var out = '';

if (TplHtml.template.node) {

var tpl = $(TplHtml.template.node);

// Do title and title's link at the same time. if (!node.nodeUrl) node.nodeUrl = '#'; tpl.find('.title a').text(node.title) .attr('href', node.nodeUrl)

return out;

The out variable is going to hold the string that we return.

The first thing we do after declaring our out variable is check to see whether the template exists. If it does, we continue with the formatting. If not, we return an empty string.

Returning an empty string like this is fine for demonstration purposes, but it isn't a great way of doing things on a production system. Since the template is being fetched from a remote server, it is possible that the template couldn't be loaded. It might be a better solution to add some default theming in cases where the template cannot be loaded.

Inside the conditional, we create a new jQuery object to wrap the node template. The tpl variable will refer to our template jQuery object. We can now conveniently manipulate the HTML DOM for our template.

Next, we begin modifying the template. We check to see if node.sticky is set and true. If it is, we then want to add a sticky CSS class to any element with the node class. This is done with a simple jQuery string: tpl.parent().find (,.node').addClass(,sticky'). This starts from the top of the template DOM (tpl.parent()), and then finds all elements with the node class. Each of those nodes gets the sticky class added.

From here, we move on to the node title and URL. The HTML template we created had a title section that looked like this:

<h2 class="title"><a href="#"></a></h2>

We want to find that section and add both a title and a URL. We can do this with one long jQuery chain:

tpl.find('.title a').text(node.title) .attr('href', node.nodeUrl)

This finds the link element inside the title section, sets its text to node.title, and then re-targets the link to node.nodeUrl.

The following chunk of code makes it easy enough for us to accomplish several content-filling tasks in a compact loop:

Drupal.theme.node = function (node) { var out = '';

if (TplHtml.template.node) {

var tpl = $(TplHtml.template.node);

// Do title and title's link at the same time, if (Inode.nodeUrl) node.nodeUrl = '#'; tpl.find('.title a').text(node.title) .attr(,href', node.nodeUrl)

// These are the things we are going to place in // the template.

// Fortunately for us, class names match 1-to-1 with // the names of the node properties.

var values = ['content'j'submitted'j'taxonomy'j'links']; for (var i = 0; i < values.length; ++i) { var value = values[i]; if (node[value]) {

// Now we dump the template to a string, out = tpl.parent().html();

return out;

The first thing we do in this highlighted section is define a new array:

var values = ['content,,,submitted,,,taxonomy,,,links'];

We have four CSS classes defined in the document that we need to fill in: content, submitted, taxonomy, and links. We potentially have four attributes on our node object that need to be slotted in these spots: node.content, node.submitted, node, taxonomy, and node.links.

Fortunately for us, the names match up! We can loop through the values array and drop the contents of our node properties into the correct location in the template:

for (var i = 0; i < values.length; ++i) { var value = values[i]; if (node[value]) {

We can make use of the fact that JavaScript allows array-like access to object properties to check whether or not each of the items in the values array exists. For example, if the node.submitted exists, then node['submitted'] will be evaluated as true. So we look through the values array and check for each property in the node object. If it exists (if (node[value])), then we insert the value. If it doesn't exist, we hide the relevant part of the template so an empty container is not displayed.

The highlighted line in the previous code is responsible for adding the content into the template:

This jQuery chain begins with the template and finds all elements whose class is the current value. During first iteration, it will look for is content, then submitted, and so on until all of the items in the values array have been inserted. With any match, it will simply add the appropriate node property's content.

We will see an example of this in a moment.

Finally, there's one more thing this function does before returning the themed content:

Drupal.theme.node = function (node) { var out = '';

if (TplHtml.template.node) {

var tpl = $(TplHtml.template.node);

// Do title and title's link at the same time, if (!node.nodeUrl) node.nodeUrl = '#'; tpl.find('.title a').text(node.title) .attr(,href', node.nodeUrl)

// These are the things we are going to place in

// Fortunately for us, class names match 1-to-1 with

// the names of the node properties.

var values = [,content,/,submitted,/,taxonomy,/,links']; for (var i = 0; i < values.length; ++i) { var value = values[i]; if (node[value]) {

// Now we dump the template to a string, out = tpl.parent().html();

return out;

The template has now been populated. However, like all theme functions, this must return the results neither as a jQuery object, nor as HTML elements, but as a string. To do this, we call tpl.parent().html(). This goes to the very root of the template and retrieves the HTML as a string. At the end of this function, the string is returned.

0 0

Post a comment