Theming a block

When we looked at the jQuery ready handler in the previous section, we saw how the menu was themed first, and then the resulting string was used as one of the components for building a block.

We are going to look at the theming functions in reverse. The reason for this is simplicity. Block theming in both PHP and JavaScript is simple. Theming a menu is considerably more complex. So we will build up from easy to harder.

In the Bluemarine theme, which is the base for our Frobnitz theme, blocks are themed using a template. You can find this template under Drupal's installation directory at /themes/bluemarine/block.tpl.php. Here's what the PHP Template looks like:

// $Id: block.tpl.php,v 1.3 2007/08/07 08:39:36 goba Exp $ ?>

<div class="block block-<?php print $block->module; ?>" id="block-<?php print $block->module; ?>-<?php print $block->delta; ?>"> <h2 class="title"><?php print $block->subject; ?></h2> <div class="content"><?php print $block->content; ?></div> </div>

That's the entire thing. It is a short snippet of HTML with a few embedded PHP statements (<?php ... ?>).

We looked at another template, page.tpl.php, in Chapter 2. This one is I even simpler than the one we saw there.

When this template is rendered, it will generate a piece of HTML that looks something like this:

<div class="block block-mymodule" id="block-mymodule-1"> <h2 class="title">The Title</h2> <div class="content">The Content</div> </div>

How does it get from the earlier template to this output? Each of the PHP statements is executed, and the results are added into the HTML. <?php print $block->module; ?> prints the name of the module that created the block ($block->module). A print statement tells PHP that the text should be added into the document.

Each piece of PHP code is simply printing parts of the block into the HTML. So if the block's content ($block->content) is The Content, then you might wonder what happens with code like this:

<div class="content"><?php print $block->content; ?></div>

The value of $block->content is inserted between the <div class="content"> and </div> tags. So the output becomes:

<div class="content">The Content</div>

Of course, as you have no doubt noticed already, the <?php and ?> as well as everything between them is left out of the rendered document. Only the HTML remains in the document that is sent to the client.

In order to re-implement this template as a JavaScript function, we need to find out what data gets placed into the template. Here's the information that gets pulled from the $block object into the template:

• $block->module: This is the name of the module that generated the block. We have the luxury of getting to hardcode this in our function.

• $block->delta: This is a numeric value that augments the module name, giving us a delta number for this module's block. If a module includes only one block on the page, that block's delta will be 0. The next block generated by that module will be 1, and so on. The key is to make the module name and delta number combination unique.

• $block->subject: This is the title of the block.

• $block->content: This is the content of the block.

These four pieces of information are all that is used to populate the template.

Now that we can interpret the PHP Template, the next step is to transform that into JavaScript.

As we saw before, JavaScript has no template system, and the Drupal theming system does not add one. Therefore, we will be turning the template into a JavaScript function that builds a string of HTML.

While this might not be the prettiest solution, it is the de facto way of doing things using the Drupal JavaScript theme system.

Here's our function for theming a block:

* Theme a block object.

* This matches the bluemarine block.tpl.php.

* @param block

* A block object. Like the PHP version, it is expected to

* have a title and content. It may also have an id.

* Returns a string formated as a block. */

Drupal.theme.prototype.block = function (block) { if (iblock.id) {

block.id = "frobnitz-" + Math.floor(Math.random() * 9999);

var text = '<div class="block block-frobnitz" id="block-' +

'<h2 class="title">' + block.title +

'</h2><div class="content">' + block.content + '</div></div>';

return text;

The function Drupal.theme.prototype.block() will be get called when we call

Drupal.theme('block', blockObject).

Earlier, when we looked at the jQuery ready handler, we saw that there are two properties to the block object that gets passed into this function: title and content. These correspond to two of the values we saw before.

The first thing the previous function does is check to see if the block object also has an id property. We want to set an ID attribute on our block. It is a requirement of HTML that ID attributes have to be unique within a document.

If the block doesn't have an ID attribute, we generate one based on a random number.

That is the only additional piece of information we need. Instead of using a module name (the code isn't generated from a module, and hence does not have a module name), we are just hardcoding in the name frobnitz. So there is no need to get the fourth piece of information that the PHP Template used.

From here, all that is left is to build up a string containing the HTML and return that string. This is done in one big string concatenation operation:

var text = '<div class="block block-frobnitz" id="block-' +

'<h2 class="title">' + block.title +

'</h2><div class="content">' + block.content + '</div></div>'; return text;

The string that this returns should be in the same form as the PHP Template's output that we just saw. It might look something like this:

<div id="block-frobnitz-3 931" class="block block-frobnitz"> <h2 class="title">Title Goes Here</h2> <div class="content">

As you can see, with a simple PHP Template, not much work is involved in translating it to JavaScript.

Since the HTML is generated by JavaScript, the newly added HTML will not show up when you view the source. However, you can use the HTML I inspector in Firebug. This works because Firebug shows the HTML as it currently is, not as it was when the page was loaded.

The next one we will look at is going to be a little different.

Was this article helpful?

0 0

Post a comment