I created jQuery Multicomplete while I was working at Nudge Digital because I saw a need for multiple result groups in one autocomplete action. Think the last.fm search box. Allow your users to find what they want, over multiple fields, instantly.
Tested in IE6+, FF3+, Safari, Opera 10+ and Chrome. Try it yourself below!
Installation couldn't be simpler! Simply include jQuery, the Multicomplete plugin (including it's CSS if you want it to look pretty!) and add this to your initialisation code for the page:
$(document).ready(function() {
$('#my-input').multicomplete({
'source': 'search.php'
});
});
This will create an instance of Multicomplete which will query search.php to get its results by sending what was written in the input as a query header. If the plugin was set to use the GET method then the request would be search.php?query=what+i+asked+for. The next step is to get search.php to return what we need for the plugin to work!
The plugin expects data back in a certain format, otherwise it will not work as expected. Consider this following excerpt from the demo:
{
"Takeaway": [
{
name: "Bobby's Takeaway",
address: "162a Stopes Croft, Bristol, TE5 3TT",
cuisine: "Moroccan, Wraps"
}
],
"Pubs": [
{
name: "The Pipe and Slippers",
address: "11 Chelston Road, Bristol, TE5 3TT",
cuisine: "Pies, roasts, etc."
},
{
name: "The Hatchet",
address: "27 Frog Street, Bristol, TE5 3TT",
cuisine: "English pub grub"
}
]
}
You have the following structure:
{
[name of group]: [
{
[result 1]
},
{
[result 2]
}
],
[name of group]: [
{
[result 1]
},
{
[result 2]
},
{
[result 3]
},
[...]
],
}
Which can easily be generated in PHP or another language of your choice.
Important: jQuery Multicomplete has been designed to work with JSON only at this stage.
Here's a really simple example script to generate some results using a fake dataset. This code is not efficient and really is just meant as a jump off point to get you thinking about how you'd grab your data.This example is using CodeIgniter and the Active Record Class:
application/models/search_model.php
class Search_Model extends CI_Model {
public function search_users($query) {
$this->db->like('users.first_name', $query);
$this->db->like('users.last_name', $query);
$this->db->like('users.address_line_1', $query);
$this->db->like('users.town', $query);
$users_object = $this->db->get('users');
if($users_object->num_rows() > 0) {
return $users_object->result();
}
else {
return array();
}
}
public function search_books($query) {
$this->db->join('authors', 'authors.id = books.author_id');
$this->db->like('authors.name', $query);
$this->db->like('books.name', $query);
$this->db->like('books.publish_date', $query);
$this->db->like('books.genre', $query);
$books_object = $this->db->get('books');
if($books_object->num_rows() > 0) {
return $books_object->result();
}
else {
return array();
}
}
}
application/controllers/search.php
class Search extends CI_Controller {
public function search() {
// Import variable from POST
$query = $this->input->post('query');
if(!empty($query)) {
$this->load->model('search_model');
// Perform the searches
$users = $this->search_model->search_users($query);
$books = $this->search_model->search_books($query);
// Format the result
$result = array(
'Users' => $users,
'Books' => $books
);
// Send the result back to the browser
header('Content-Type: application/json');
echo json_encode($result);
exit;
}
}
}
For these examples to work, source needs to be set to /search/search in the initialization settings. See below for more information.
| Option | Default | Effect |
|---|---|---|
| debug | true | Provides error messages and logs variables to the console |
| source | [ ] |
When set to a string Example: search.phpWill perform an AJAX request to this URL in an attempt to get a JSON response with your results. When set to an array Example: see example Will search the local array based on the query. Much quicker than a AJAX request. Ignores min_length and delay.
|
| method | POST | Can be one of GET or POST. This dictates how the AJAX request is performed if source is set to a string. |
| minimum_length | 3 | How many characters the query needs to be before a search is triggered |
| search_delay | 500 | How many milliseconds after the last key is pressed before a search is triggered. |
| case_sensitive | false | When set to true, the search will only return results that match the exact case of the query. |
| highlight_results | true | Highlights the terms found within the result. Will only apply if the actual term is included in the template. Creates a span with a class of highlight to the found node. |
| offset_left | 0 | The results pane will be created at the bottom of the input element with a left offset of offset_left pixels. You do not need to include "px" on the end of this value. |
| offset_top | 0 | The results pane will be created at the bottom of the input element with a top offset of offset_top pixels. You do not need to include "px" on the end of this value. |
| result_template | N/A | See the results section for more information on how to create result templates. |
| result_click | N/A | Specify a function to be executed when a result is clicked. This function is passed the result as the first parameter, which contains the row object itself. The second parameter is group which is a string with the name of the group. |
| form_submit | N/A | Specify a function to be executed when the form that encapsulates this element is submitted. See the discussion on form submissions for more information on what happens by default. |
jQuery Multicomplete searches all of the available fields provided in a given row to return results. This means the user will most likely receive a piece of information that they were searching for. It's up to you whether you actually display that field (but a good user experience would definitely include it to show why that result has been shown to them!). You can fully control the output of a given result by changing the result template.
A crucial element of the plugin is the ability to define how the results are displayed. Fortunately jQuery Multicomplete allows for complete flexibility over the markup output for various types of results. Below is the example template we use on the demo at the top of this page:
function(result, group, field) is simply being passed the row of the resultset that was matched as the first parameter and the group the row was in as the second. The third and final parameter contains the name of the field which the result was matched in, which is very useful if you only want to display fields that contained results. This can be used to generate any form of markup you need for the resultset.
Built with lots of love by @tomhallam. Initially developed for Nudge Digital (they're a wicked agency in Bristol that do web applications!).