Scott Boms

Implementing Livesearch (Updated)

It’s been a while since I’ve done a tutorial on anything so as a last-minute holiday treat I’ve got one cooked up on a feature that I’ve wanted to explore implementing here for some time.

Resources

Let’s get the resources out of the way so you know where to get the relevant pieces of open-source code and can see a nice implementation of what we’re going to build.

Laying The Groundwork

Follow along and you should have a basic framework for implementing livesearch functionality on your own site. Start by downloading the required BitFlux JavaScript file and take note of the installation details. We’ll go over them here, but read through the content on the topic there first.

Take the ‘livesearch.js’ file and copy it to your site wherever you keep your Javascript files. For the purposes of this tutorial, I’ll assume this file will be located in the root directory of your site.

In the livesearch.js file locate the first line that contains /livesearch.php?q= near the end of the file. To specify the search variable as something other than “q”, change this here and in the lines that follow. There are a total of three instances that will need to be changed.

As an example, to rename the variable to “s”, the replacement text would be /livesearch.php?s=. Also note that you can rename the livesearch.php file to something else if desired. This script will do the work of performing the search and returning the results back to the browser. Just be sure to make the same changes in the Javascript if you rename the file.

Determine the necessary SQL query to search your Movable Type entries. Exactly how you decide to do this is really up to you. The SQL here is more of a quick example and you may want something more robust.


SELECT entry_id, entry_title, entry_excerpt, 
DATE_FORM(entry_created_on, '%Y_%m') AS date 
FROM mt_entry WHERE entry_text LIKE '%$s%' 
ORDER BY entry_created_on DESC

The $search variable included in the SQL should also match the name passed from the search form. Exactly what is returned is entirely up to you. In this case, the query returns the entry ID, title, and excerpt with the results sorted by date in descending order.

To restrict the results to a single blog if you have more than one, you would also want to filter by the entry_blog_id in the WHERE clause. For example, WHERE entry_blog_id = '1' AND entry_text LIKE '%$s%', etc.

It would be useful to split the results into multiple pages if a large result set is sent back (eg. 10 results at a time) but that’s outside the scope of this tutorial.

The next piece of the puzzle is to return the results in a standard XML format to be parsed by the XMLHTTPRequest JavaScript object. The Wiki page describes the format required but you can see it more clearly here in context of the PHP you will need to return a correctly formatted result set.


echo "<?xml version='1.0' encoding='utf-8' ?>"
echo "<ul class='LSRes'>\n"
while ($row = @mysql_fetch_array($query_results)) {
  echo "<li class='LSRow'>Link text</li>"
}
echo "</ul>\n"

You may not want to copy this verbatim, but it should be enough to give you a good start on how to return the results. Include links and such where appropriate and watch out for whitespace parsing and validation issues with the XML returned. Note that you don’t have to use an unordered list here, this is just a suggestion to keep thing clean and arguably semantically correct. It’s also easy to style with CSS.

Once your PHP script is completed, test it manually to see if it’s returning results as expected. Upload the file to your server and call it along with the appropriate search query appended. For example,

yoursite.com/livesearch.php?s=querystring

If all goes well and matches are returned you should see a nicely formatted list of results. If not, you’ve got some SQL or PHP debugging to do.

Implementation

Implementing livesearch into Movable Type, replacing the default search functionality is straightforward, but presents a few challenges. The first thing to take into account is where search is located throughout the site. For now, I’m assuming that search functionality is only available within the Main Index template.

In that Main Index template, locate the search form code. The default search form in Movable Type does not include an ID/name attribute and uses a button we technically will no longer need. Change the form code to:


<form name="searchform" id="searchform" action="archives/" method="get">
  <input type="text" name="s" id="livesearch" onkeypress="liveSearchStart();">
  <div id="LSResult" style="display: none;"><div id="LSShadow"></div></div>
</form>

Formatting is important here. Make sure the third line with the DIVs has any whitespace removed. Whitespace appeared to cause problems returning results during my testing.

Next, in the HEAD section of the template, include the livesearch.js file and initialize the livesearch script by attaching an onload event to the BODY tag.

<body onload="liveSearchInit();">

There are better ways to handle this, especially if you need to be able to execute multiple functions on the DOM when the page loads, but this is suitable for this simple example. Save the template changes and style as desired with CSS. Repeat as required wherever the search form appears.

Caveats

This isn’t foolproof of course. It doesn’t work in some browsers, or in some cases, not completely. It doesn’t work at all in IE 5 for the Mac or Opera 7.x (and one can assume earlier versions as well). It mostly works in OmniWeb 5.1 beta 5 based on very minimal testing. And there’s also the issue of graceful degradation. Users with Javascript turned off are out of luck with search since livesearch relies entirely on Javascript. Providing a fallback for those users would be a worthwhile addition.

Last Updated: December 22, 2004

So say you…

Thank you very much! I’ve seen a couple of sites that use livesearch and I’m thinking of implementing myself on my upcoming site, but I’ve never found an article on the subject before you posted.

Regards Johan.

Johan Johan December 20, 2004

I will likely update the article a bit sometime this week. There’s some small details I’d like to flesh out a little more because I’m not sure if things are really clear on how to get it all to work.

I couldn’t find one either so once I got things working I decided it was worth the time.

Scott Scott December 20, 2004

That’s pretty darn cool. Well done. Unfortunately for me, Typepad doesn’t support PHP. Too bad, I have ten days off starting on Friday and this would have been a fun project! I really like it.

dave dave December 20, 2004

I’ve been thinking about this more today and am going to now look at seeing if I can have the best of both worlds — keep the original MT search working as well as have livesearch for users with newer, more standards-compliant browsers.

With any luck this will be easy and should be up and running by end of day tomorrow.

Scott Scott December 20, 2004