The forms Drupal automatically generates have always suffered from the 'silo' effect, where one form field is stacked on top of the other. This often presents a usability challenge for people operating the system, and generally requires some additional level of theming for developers in a really mature site.
Trellon recently released the interface module for Drupal, which is a stab at making it easier to change the look and feel of forms. Interface is a tool for authoring the interface for forms in Drupal by dragging and dropping form fields into predefined regions. This is one of those things you might need to see to see to understand - we have videos demonstrating the module at work.
These regions, the places on the page where you drop form fields, are put into something called a template. This article seeks to explain what a template file is and how to author your own. Our team has put a lot of effort into making it easy to use this module, and this includes authoring new templates. Interface ships with a number of templates we have already set up, and we understand it will be important for certain users to know how to author their own. Writing a template should be one of the simplest tasks you will ever have to do as a developer, right down there with Hello World and executing a print command.
What You Get Out of the Box
So, in interface, a template is a set of files that contain some markup developers can use to create layouts for placing form elements. Interface ships with two main templates that get you started right away with the drag and drop authoring. They are designed to be useful for the greatest number of sites, and we will include more as people give us feedback on what works and what does not. These templates include the following:
- One Column: For those who have the itch to restack the silo, this template allows people to drag form fields around in a single column. You could do the same in the content module, but you get the advantage of being able to add behaviors to form fields (which we will talk about later in this post).
- Two Column Stacked: This should be familiar for anyone who has seen the videos. You get two columns to place form elements, and there are stacked columns in each.
You will also find experimental templates for use in your own projects. We have put together a template that has some of the basic page characteristics of a Joomla template in the current release, and we are not going to say interface is out of beta until this template is a pixel-perfect knock off.
Writing Your Own Template
There will be times developers need more columns / rows / regions than the default templates include, which is when someone might want to write a new template. Again, we have tried to make this simple. Here is the code from the Two Column Stacked template.
// $Id: box.tpl.php,v 1.3 2007/08/07 08:39:36 goba Exp $
<div rid="region_zero" class="region_zero">
<!-- region -->
<div rid="region_four" class="region_four">
<!-- region -->
<div rid="region_one" class="region_one">
<!-- region -->
<div rid="region_two" class="region_two">
<!-- region -->
<div rid="region_three" class="region_three">
<!-- region -->
In the code, you will notice a few things. First off, this is just a few lines of simple HTML markup and nothing else. As long as you know how to create basic HTML layouts, or how to use Dreamweaver to do it, this should be pretty easy. For anyone who wants to get more complex, there is nothing preventing you from including some PHP as well. It is important to remember, however, that this code executes at the time forms are being built, and there may be some functions in Drupal that are not available when this code is being processed. 99% of the time, it should be unnecessary to use any PHP.
Secondly, we are using this markup to define regions to place content, and there are a couple of things going on in the code to support this. There is an RID attribute attached to some of the DIV tags, this stands for REGION ID. Interface uses this attribute to remember where to put form controls, so put an RID on any tag where you want to be able to drop elements. It is a good idea to name region ids sequentially, as this affects how interface stores information in the database. Next, there is a 'region' comment appearing within each region. Make sure to include this within each region you are going to use, interface uses it to identify where each region starts and ends.
Putting It On The Server
That's really all the coding that is involved in creating a new template for dragging and dropping form elements in interface, except for some CSS we are going to add later. Your next step is to store your new template on the server and make it accesible to interface. You do this by creating a new directory for the template in the interface/templates folder. Choose a unique, descriptive name that you are going to use for creating the files to store the template.
Each interface template has at least 2 files:
- The Template File: that contains all the markup you just created. Put it in the subdirectory for the template, and name it [name of template].tpl.php just like you would name a template file for a theme.
- The Info File: that contains information about the template that tells interface how to handle it.
Each template file contains the markup for the regions. Info files are another matter entirely, and are the only part of the process someone might consider complex. Info files store a lot of information about how a template works, which are expressed as simple attributes. Here's an example (from Two Column Stacked):
name = Two Column Stacked
description = Two column stacked template for the Interface module
template = two_column_stacked.tpl.php
directory = interface
; all css files needed for the display will be loaded through an array
css = two_column_stacked.css
; all regions will be defined here, with a key corresponding to an rid in the code
regions[region_zero] = Region Zero
regions[region_four] = Region Four
regions[region_one] = Region One
regions[region_two] = Region Two
regions[region_three] = Region Three
; create a default region where all form elements will be placed. if there is not a region defined,
; the first element will be used.
default_region = region_one
; all behaviors can be loaded through this interface
behaviors[common_groupers][name] = Common Groupers
behaviors[common_groupers][id] = common_groupers
behaviors[common_groupers][path] = /behaviors/common_groupers/common_groupers
behaviors[tabbable][name] = Tabbable
behaviors[tabbable][id] = tabbable
behaviors[tabbable][path] = /behaviors/tabbable/tabbable
behaviors[tabbable][js] = /behaviors/tabbable/tabbable_actions.js
behaviors[tabbable][css] = /behaviors/tabbable/tabbable.css
; a template for preprocessing can be defined here
I know this looks complex, but here's a breakdown of what all these attributes mean.
- name: a descriptive name for the template, to be used in menus throughout interface.
- description: a description of what makes this template special.
- template: the name of the template file used for the template. We kept it redundant so we could keep it redundant.
- directory: unsupported right now, this will someday allow developers to include templates in other directories on the server. For right now, use interface and keep your templates in the template directory.
- css: an array of css files to include when the template is loaded. There is some support for different css files based on whether you are authoring or viewing a form, this will be elaborated on later.
- regions: an array of of regions that are present in the template. These names are used by interface in the authoring tool to provide descriptive information about where form fields are being placed. Make sure there is an entry for each region in your template.
- behaviors: interface allows you to do cool things like make tabsets, change buttons into images, pop in sliders over select boxes, and other things. These are called behaviors, and each template can implement it's own set of behaviors. Every template should include common_groupers, as this is what lets you drag around things like fieldsets and file upload fields without breaking the forms. Any other behavior is optional.
- page_template: Allows users to override the page template in the theme Drupal uses to display a form. Useful if you need a different layout for a form when someone is entering content.
Once you have your info file all set, store it on the server in the directory for this template with the file name [name of template].info. Choosy coders will find that copying the settings from two_column_stacked with minor modifications will probably suffice for most of the situations where you will create a new template.
Once you have created your info file, the last thing to do is put in some CSS for your template. Unless you are using tables, it is very likely you will need to float a couple elements around to get good columns in the template layout. Create a CSS file with the same name as your template, store it in the same directory, be sure the info file points to it and interface will automatically include it.
So, that's about 15 lines of code, some power copying, and you have a new way to lay out your forms in Drupal. This should cut down on theming tasks and improve the way people are able to enter content in their sites. This also just scratches the surface of what you can do with interface, and I strongly suggest people read the readme to understand some of the other things it does.
In my next post, I will explain a little bit about how the API works, for anyone who is thinking about writing some behaviors. I made some conscious decisions about what should be a behavior and what should be a CCK field, and will elaborate on them along with a discussion about the API.