Search Form Zen, Using jQuery, with WordPress and Drupal Examples

…after all, everything is instantly cooler with the word ‘Zen’ tacked onto it, especially if you add a picture of some cheesy stones nearby…

In one of my earliest blog posts, I described an approach to customizing a search form that I employ on many of my sites. Instead of having a search form that consists of three elements: a label, text input field, and submit button, I like to reduce everything to just the text field with the label inside it, as you can see on the right hand column of this very blog. This frees up room, and requires less mouse work on the part of the user.

The Fundamental Approach from Mambo

To make this work properly, you need to use Javascript to allow the following behavior:

  • By default, the text box either contains some ‘label’ text like ‘searching…’ or alternately, a search that has just been executed.
  • When the user clicks on the search box, the default label text disappears.
  • When the user clicks off of the search box, it will retain what was entered, or if nothing was entered, return to the default label text.

I originally saw this basic functionality on the Mambo CMS site, and because I don’t like to needlessly duplicate work (otherwise known as laziness), I decided to completely and shamelessly rip off their source:

<input class=”search” type=”text” name=”searchword” value=”search…” onblur=”if(this.value==”) this.value=’search…’;” onfocus=”if(this.value==’search…’) this.value=”;” />

More recently, however, I have been using jQuery and have been moving toward implementing Javascript unobtrusively, and so, I decided to explore re-implementing this approach accordingly.

Re-implementing in jQuery

The first step was to move this functionality out into a function, at which point, it became immediately obvious how I could make this approach more flexible and reusable:

function prepare_search_form(selector, default_string, search_term) { // what should the default label text be? var default_term = ‘search…’ if (default_string && default_string != ”) { default_term = default_string; } // lets make sure we are starting fresh $(selector).unbind(); // set the label text to either the default, or the search string if (search_term != ”) { $(selector).val(search_term); } else { $(selector).val(default_term); } // add the click on, click off behavior $(selector).focus( function() { if ($(selector).val() == default_term) { $(selector).val(”); } }); $(selector).blur( function() { if ($(selector).val() == ”) { $(selector).val(default_term); } });}

This function will allow me to pass in the CSS-like jQuery selector for the text box I want to affect, it will allow me to specify the default label text (or default to ‘search…’ if I don’t specify it), and will further give me the option to include a search string that has just been executed for display in the text box, if appropriate. Even if you aren’t familiar with jQuery, its fairly evident how this code is working. The use of ‘sensible defaults’ is the influence of Ruby on Rails showing, as this makes the function API as simple and convenient as possible.

So, for the following basic search form:

<form id=”searchform” action=”search.php”> <input type=”text” name=”searchword” /></form>

I could enable this basic functionality by adding this Javascript code:

$(document).ready(function () { prepare_search_form(‘#searchform :text’);});

Now I have a reusable function I can add to any software I’m using. But just to make things more interesting, let’s look at some more specific examples using WordPress and Drupal.

WordPress Search Form Zen

To begin on some common ground, I am going to customize the default WordPress theme, located at /wp-content/themes/default . Although I think we can assume that the theme may be customized pretty thoroughly in a typical situation, I am going to try to impact the existing files as little as possible, just for the sake of cleaner code.

Obviously you will need to download jQuery and place it in this theme directory.

The search form looks like this (from the searchform.php file):

<form method=”get” id=”searchform” action=”http://localhost”> <div><input type=”text” value=”” name=”s” id=”s” /> <input type=”submit” id=”searchsubmit” value=”Search” /> </div></form>

I don’t see any existing external Javascript files, so I will put my reusable function and its invocation code in a file in the default theme directory called common.js:

function prepare_search_form(selector, default_string, search_term) { // what should the default label text be? var default_term = ‘search…’ if (default_string && default_string != ”) { default_term = default_string; } // lets make sure we are starting fresh $(selector).unbind(); // set the label text to either the default, or the search string if (search_term != ”) { $(selector).val(search_term); } else { $(selector).val(default_term); } // add the click on, click off behavior $(selector).focus( function() { if ($(selector).val() == default_term) { $(selector).val(”); } }); $(selector).blur( function() { if ($(selector).val() == ”) { $(selector).val(default_term); } });}$(document).ready(function () { prepare_search_form(‘#s’);});

Include this in the theme by adding the appropriate script tag within the <head> tag in header.php, along with a script tag with the path to your jQuery download:

<script type=”text/javascript” src=”/wp-content/themes/default/jquery-1.2.6.min.js”></script><script type=”text/javascript” src=”/wp-content/themes/default/common.js”></script>

Then, we can hide the superfluous submit button by adding the following CSS to style.css:

#searchsubmit { display: none;}

Now, its probably a little more usable to make it so that when a search is executed, the search terms are shown in the search box. In that case, instead of putting the call to the prepare_search_form function into the commons.js file, I would move it into the footer.php file, right above the closing </body> tag:

<script>$(document).ready(function () { prepare_search_form(‘#s’, ‘search…’, ‘<?php echo htmlentities(html_entity_decode($_GET[‘s’])); ?>’);});</script>

The reason for moving this into a PHP script is so we can easily get access to the search string through PHP’s $_GET super global variable and do some basic anti-XSS (cross site scripting) manipulation on the string before displaying it. I’m not sure this is purely unobtrusive Javascript anymore, but it is at least pragmatic. For a more comprehensive XSS filtering function in PHP, check out this site.

Drupal Search Form Zen

The Drupal implementation is a little easier in some ways.

Assuming that you have turned on the search form ‘block’, you can simply configure the block through the appropriate Drupal admin screens to not show the the block label. Otherwise, the following CSS will hide both the block label and search form submit button:

#search-block-form label, #search-block-form input.form-submit { display: none;}

If you’ve read my blog in the past, it will come as no surprise that I use the Blueprint theme for Drupal which integrates the Blueprint CSS framework. For that theme, this custom CSS will go into the css/style.css file.

Drupal comes pre-installed with jQuery, so you don’t need to download it and include it separately–it’s already available to us. The Blueprint theme also has a scripts/general.js file that makes for a logical place to include the above prepare_search_form() function. Again, the goal here is to try to add this functionality in a way that makes the most sense in the environment we are in.

Now, because by default the search results page displays its own search box with the appropriate search terms added, I tend not to duplicate this functionality in the block search form, preferring the bare bones implementation of prepare_search_form(), which can also be tacked onto the scripts/general.js file:

$(document).ready(function () { prepare_search_form(‘#search-block-form :text’);});

But if you want to go that extra mile in your block search form, you will need to know a few Drupal API functions. To get the search terms entered by the user, call the search_get_keys() function. And for XSS filtering, Drupal provides a robust function for that with filter_xss(). So the complete implemenation in the Blueprint theme can be achieved by adding the following to the page.php file, just before the closing </body> tag:

<script>$(document).ready(function () { prepare_search_form(‘#search-block-form :text’, ‘search…’, ‘<?php echo filter_xss(search_get_keys()); ?>’);});</script>

Wrapping Up…

Once you start down this road, its easy to think of other ways to further enhance the search form using jQuery, perhaps the most obvious being an autocomplete feature. Please share your ideas for improving what I’ve done here.

Related Post