Sometimes in the web development process, the need arises to create an autocomplete field in order to enhance usability. As worked examples of such fields, widgets for cck-fields Node reference and User reference can be mentioned.
Let's look at some attempts of program creation of such fields. According to Drupal Forms API reference #autocomplete_path function can be added only for text field element. This feature will identify the path through which Drupal JavaScript-code that is automatically turned on will send HTTP-requests, using JQuery.
First of all, we'll announce text field in the form:
php
$form['example'] = array(
'#type' => 'textfield',
'#title' => t('Example Textfield'),
'#autocomplete_path' => 'products/autocomplete',
);
Now we'll identify callback for autocomplete in hook_menu():
php
/**
* Implementation of hook_menu
*/
function module_menu() {
$items['products/autocomplete'] = array(
'page callback' => 'module_products_autocomplete',
'type' => MENU_CALLBACK,
'access arguments' => array('administer nodes'),
);
return $items;
}
Finally, we must describe callback function itself that will transfer some array of drupal_json() function:
php
function module_products_autocomplete($string) {
$matches = array();
$res = db_query("SELECT title, nid FROM {node} WHERE LOWER(title) LIKE LOWER('%s%%')", $string);
while ($row = db_fetch_array($res)) {
$matches[$row['nid']] = $row['title'];
}
drupal_json($matches);
}
Now we have a full-blown autocomplete field.
Quite often, though, there is a need to pass some parameters of the autocomplete function. In my case, there was a need to pass an array of node identifications and to limit the scope of nodes to only this array in autocomplete. For this reason, we'll identify page arguments in hook_menu() for that:
php
/**
* Implementation of hook_menu
*/
function module_menu() {
$items['products/autocomplete/%'] = array(
'page callback' => 'module_products_autocomplete',
'page arguments' => array(2),
'type' => MENU_CALLBACK,
'access arguments' => array('administer nodes'),
);
return $items;
}
Let's make some amendments in the autocomplete_path settings for text field definition:
php
//we get $nids array with identificators of nodes
$string_nids = implode('|', $nids);
$form['example'] = array(
'#type' => 'textfield',
'#title' => t('Example Textfield'),
'#autocomplete_path' => "products/autocomplete/{$string_nids}",
);
$string parameter is being automatically passed to autocomplete function with the help of API. If you want to pass additional parameters, place them before $string:
php
function module_products_autocomplete($arg2, $string) {
$matches = array();
$nids = explode('|', $arg2);
$res = db_query("SELECT title, nid FROM {node} WHERE LOWER(title) LIKE LOWER('%s%%') AND nid IN (" . db_placeholders($nids, 'int') . ")", array_merge(array($string), $nids));
while ($row = db_fetch_array($res)) {
$matches[$row['nid']] = $row['title'];
}
drupal_json($matches);
}
Drupal will visualize all above-mentioned the following way: