This patch adds a very basic JavaScript theming layer to Drupal:

  • There are two places for theme functions: The general theme functions (theme_* in PHP) are located in Drupal.theme.prototype whereas the overridden theme specific theme functions are in Drupal.theme. As a module developer, you add your functions therefore to Drupal.theme.prototype and as a theme developer, you can override these functions by adding them to Drupal.theme.
  • Like style.css, a default JavaScript file is added automatically for each theme. This file is called scripts.js and must be located in the theme’s directory, like style.css.

This patch adds also extensive documentation for the new functions (mostly copied from their PHP equivalents). With the JS aggregation patch, this should not be an issue.

While this patch does not provide much benefit on its own (except for the default JS file), it paves the way for several other functionalities that will hopefully move into core rather soon, such as autocomplete list theming, JS string translation and so on. It also provides a clearly structured framework for contrib modules to prevent uncoordinated growth in this domain.

CommentFileSizeAuthor
#4 theme-js_0.patch6.24 KBkkaefer
#1 theme-js.patch3.03 KBkkaefer

Comments

kkaefer’s picture

StatusFileSize
new3.03 KB

Errm, and the patch file ;)

kkaefer’s picture

While the patch may look extremely simple, it is very powerful if used in a proper way. A theme function could for example look like this:

Drupal.theme.box = function(title, content) {
  var box = {
    'title': $('<span class="title"></span>').html(title || ''),
    'close': $('<img src="/misc/close.png" />'),
    'content': $('<div class="content"></div>').html(content || ''),
    'container': $('<div class="craqbox"></div>')
  };

  box.container.append(
    $('<div class="title-bar"></div>')
      .append(box.title, box.close, box.content
  );

  box.show = function() {
    this.fadeIn('slow');
  }

  return box;
}

Ok, imagine we create an imaginary popup box and write the theme for it. In the theme function, all necessary elements the actual script needs to target are stored as an object which is returned. Due to the flexible nature of JavaScript, these can’t only be jQuery objects, but also simple strings, regular expressions or even entire callback functions.

What the actual script does is the following:

this.theme = Drupal.theme('box', 'Title text');
this.theme.container.hide();
$('body').append(this.theme.container);

if (this.theme.show) {
  this.theme.show.call(this.theme.container);
}
else {
  this.theme.container.show();
}

First, we create a new box, hide it and append it to the box. Then, we check if the theme defines a custom show function. If it does, we call it (with this as the container of the box), if it doesn’t, we use a default mechanism

In the rest of the script, we could for example attach the close handler to this.theme.close or modify the content later by injecting new HTML into this.theme.content. The actual HTML structure, even class names in most cases, are completely irrelevant to the script. A theme developer could even use a HTML table to show this box, use an input button to close the box, or wrap the whole thing in several divs for applying rounded corners to it.

If there is no theme function defined, Drupal.theme() uses the default function defined in Drupal.theme.prototype which the script developer has to define.

sime’s picture

subscribing to grok later.

kkaefer’s picture

StatusFileSize
new6.24 KB

To get an example for JavaScript theming into core, I have gone through progress.js and moved all themeable elements into theme functions. I even included an example for a “themeable” update function interface into the patch. While going through that file, I have cleaned up here and there a bit.

nedjo’s picture

This simple improvement is a major step forward. Most or all of our behaviours currently include hard-coded elements that are impossible to alter without overriding the whole functions. Specifically, I use the Drupal progress bar in my modules and have had many requests for the ability to customize it.

Obviously we could do a lot more (convert all the existing behaviours), but this is a good beginning.

The implementation is well written and straightforward. However, the last patch seems to be missing the drupal.js pieces.

kkaefer’s picture

#118026: JavaScript localization(http://drupal.org/node/118026) also includes a (more current) version of this patch because `Drupal.t()` requires a `theme_placeholder` equivalent.

Thanks for reviewing this patch. This patch is not so much about code, it's more about documentation and creating a guideline for themeable JavaScript function.

I'm currently undecided on how to proceed. Should I try to get in JS themeing as a separate patch or try to get it in together with JS translation?

moshe weitzman’s picture

subscribe ... seems like a very good idea.

kkaefer’s picture

Status: Needs review » Closed (won't fix)

(This patch will be incorporated in JavaScript localization)