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: