Auto Complete Tutorial for Dummies

arjun.r - May 26, 2007 - 13:55

K. I've been reading up and trying to work on Drupal for the past couple of weeks. And things have been easy so far. However I tried figuring out how to use autocomplete and make a module of my own. And I felt the documentation provided was insufficient and the forum answered questions on a somewhat higher level than what I understood (or maybe I'm just dumb, either ways...).
So I decided to create an account and here's my first post!

WARNING: I have to tell you, this is a very low level explanation (reason being, I dont know half the things I'm talking about :-P). If you have some experience with Drupal, you probably are on the wrong page.

Wont go into the technical details. Plenty of that around. I've always liked getting my hands dirty on the code and so here it is.
This a very bare-bones example. But, like me, if you have a test Drupal site created on your local machine, all you need to do is a copy-paste and make sure u get the filenames right.

Create a folder "autocomp" in your module folder. path chould be something like this: \sites\all\modules\autocomp
and put the following in it.

"autocomp.info"
; $Id$
name = Autocomp example
description = Shows how to build a Drupal form.
version = "$Name$"

"autocomp.module"

<?php
// $Id$

/**
* Implementation of hook_menu().
*/
function autocomp_menu($may_cache) {
 
$items = array();
  if (
$may_cache) {
   
$items[] = array(
     
'path' => 'autocomp/myautocomp',
     
'title' => t('AutoComp Menu'),
     
'callback' => 'myautocomp',
     
'access' => TRUE
   
);
  }
  return
$items;
}


/**
* Retrieve a pipe delimited string of autocomplete suggestions for existing users
*/
function myautocomp($string) {
 
$matches = array();
 
$result = db_query_range("SELECT name FROM {users} WHERE LOWER(name) LIKE LOWER('%s%%')", $string, 0, 10);
  while (
$user = db_fetch_object($result)) {
   
$matches[$user->name] = check_plain($user->name);
  }
  print
drupal_to_js($matches);
  exit();
}
?>

Right. The first file is the info file. For more info, check out http://drupal.org/node/101009 to know more.
The second one is the autocomp module file, with the autocomplete function copied straight off from user.module.

The things to note here are:
'path' : specifies the path that will be passed to the module in the url field. eg: http://localhost/mysite/?q=autocomp/myautocomp
'title' : shows the txt inside t() in the Admin Menu page. Really not needed.
'callback' : you specify the function to call for the corresponding 'path'.
Read up on menu callbacks for more info: http://drupal.org/node/10901

After this you define the function you specified in the 'callback' param. In our case myautocomp. I've just copy-pasted this from user.module. But you can modify the query to pick data from and table.
eg: instead of ...LIKE LOWER('%s%%'), we may use LIKE LOWER('%%%s%%'). This query will retrieve not only the user names starting with the entered characters, but also if the characters occur in between the name.

The entire parsing/display part is handled by Drupal. So you neednt bother about it. The print drupal_to_js($matches); function does this for you. However, if you are interested in formatted results, watch this space, cos I'll be working on it next and try to come up with a simple explanation for it as well.

Next, create a form. For convinience here's a basic form:
Again, create a formexample folder and put these files in. Dont forget to create the .info file which would be almost the same as autocomp.info, except for the file name and name and description params.

"formexample.module"

<?php
// $Id$
/**
* Implementation of hook_menu().
*/
function formexample_menu($may_cache) {
 
$items = array();
  if (
$may_cache) {
   
$items[] = array(
     
'path' => 'formexample',
     
'title' => t('View the form'),
     
'callback' => 'formexample_page',
     
'access' => TRUE
   
);
  }
  return
$items;
}
/**
* Called when user goes to example.com/?q=formexample
*/
function formexample_page() {
 
$output = t('This page contains our example form.');
 
// Return the HTML generated from the $form data structure.
 
$output .= drupal_get_form('formexample_nameform');
  return
$output;
}
/**
* Defines a form.
*/
function formexample_nameform() {
 
$form['user_name'] = array(
   
'#title' => t('Your Name'),
   
'#type' => 'textfield',
   
'#description' => t('Please enter your name.'),
   
'#autocomplete_path' => 'autocomp/myautocomp',
  );
 
$form['submit'] = array(
   
'#type' => 'submit',
   
'#value' => t('Submit')
  );
  return
$form;
}
/**
* Validate the form.
*/
function formexample_nameform_validate($form_id, $form_values) {
  if (
$form_values['user_name'] == 'King Kong') {
   
// We notify the form API that this field has failed validation.
   
form_set_error('user_name',
     
t('King Kong is not allowed to use this form.'));
  }
}
/**
* Handle post-validation form submission.
*/
function formexample_nameform_submit($form_id, $form_values) {
 
$name = $form_values['user_name'];
 
drupal_set_message(t('Thanks for filling out the form, %name',
    array(
'%name' => $name)));
}
?>

(I wont explain forms... cos I havent really figured them out yet, but I dont think they are too difficult to understand)

To access this form, just type ...?q=formexample
The thing to note here is:
function formexample_nameform() {
$form['user_name'] = array(
'#title' => t('Your Name'),
'#type' => 'textfield',
'#description' => t('Please enter your name.'),
'#autocomplete_path' => 'autocomp/myautocomp',
);

You specify your module and path (the menu callback basically) in the #autocomplete_path param. This essentially calls http://localhost/mysite/?q=autocomp/myautocomp. Since you have already mapped this path in your autocomp.module, the myautocomp will be called. The rest is blah blah blah.

If you wanna figure out more, check out:
http://drupal.org/node/42552 - "Tutorial 2: Using existing Javascript widgets: autocomplete"
http://drupal.org/node/125231 - "Enhance autocomplete feature"
http://groups.drupal.org/node/3471 - "Practical lesson: An autocomplete nodereference field that is dependent upon a choice made in another"

Not very clear

Michelle - May 26, 2007 - 16:42

It looks like you put a lot of work into this, but I'm not entirely sure what it is you're doing. Where does the auto completion come into play? Maybe make an introduction along with a link to an example if you have one? This has the potential to be a handbook page if it's clarified a bit.

Michelle

--------------------------------------
My site: http://shellmultimedia.com

 
 

Drupal is a registered trademark of Dries Buytaert.