Skip to content

A jQuery autocomplete plugin for the discerning developer.

Notifications You must be signed in to change notification settings

stevemayhew/jquery-marcopolo

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

57 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Marco Polo

A jQuery autocomplete plugin for the discerning developer.

After spending years struggling with various autocomplete plugins, I became fed up with their bugginess, poor documentation, lack of updates, inflexibility, and antiquated coding patterns. Surely something as fundamental as autocomplete could — really, should — be done better. And now it has. Meet Marco Polo. For the discerning developer.

Developed by Justin Stayton at Monk Development for the Ekklesia 360 CMS.

Features

  • Cache and buffer. Marco Polo prevents unnecessary requests through its build-in results cache (shared by all instances) and key press buffer (only makes a request after the user has finished typing).
  • Remembers selection. Once a result is selected, if that same result appears in the results again, it's automatically highlighted. This is very similar to how select inputs mark the currently selected item.
  • Require selection. Marco Polo can be configured to require a selection be made from the results, ensuring that the text input is left empty when no selection is made.
  • Overlabel support. Overlabel is the concept of placing a label element over a text input for a more compact display. Marco Polo offers built-in support for hiding and showing the label automatically, depending on the state of interaction with the plugin.
  • Complete styling control. With straightforward markup that's explained in detail, you can easily style and modify all of the components to fit your needs and aesthetic.
  • Callbacks for all major events. Add your own twist when a search is made, result is selected, error occurs, and more.
  • Maintained. I developed this plugin for production use in the Ekklesia 360 CMS at Monk Development, so you can very much believe that it will remain bug-free and up-to-date. Any feature requests, bug reports, or feedback you submit will be responded to quickly as well.
  • Documented. I believe that code is only as useful as its documentation. This manifests itself not only in clear and thorough developer documentation (below), but also verbose documentation within the code itself.

Requirements

  • jQuery 1.4.2 or newer.
  • jQuery UI Widget 1.8.14. Included in the minified version.
  • All modern browsers are supported, as well as IE 6 and newer.

Getting Started

Let's say you want to create a user search field that redirects to the user's profile when a result is selected. To start, make sure both jQuery and Marco Polo are included in your HTML:

<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="jquery.marcopolo.min.js"></script>

Next, add a text input, if you haven't already:

<input type="text" name="userSearch" id="userSearch" />

Then attach Marco Polo to the text input in your JavaScript:

$('#userSearch').marcoPolo({
  url: '/users/search',
  formatItem: function (data, $item) {
    return data.first_name + ' ' + data.last_name;
  },
  onSelect: function (data, $item) {
    window.location = data.profile_url;
  }
});

When a search happens, a GET request is made to the url with q (the search value) added to the query string. (Additional data can be included using the data option.) Let's say a search is made for Butler. A GET request is made to /users/search?q=Butler. Your backend code must then use the q parameter to find and return the matching users in JSON format:

[
  {
    first_name: 'James',
    last_name: 'Butler',
    profile_url: '/users/78749',
    …
  },
  {
    first_name: 'Win',
    last_name: 'Butler',
    profile_url: '/users/41480',
    …
  },
  …
]

Each JSON user object is passed to the formatItem callback option for display in the results list. And when a user is selected from the results list, their JSON object is then passed to the onSelect callback option to complete the browser redirect.

You should now have enough understanding of Marco Polo to start configuring it for your specific needs. While this example demonstrates a number of fundamental concepts, the possibilities extend far beyond the straightforward search, click, redirect setup shown here. And when you're ready, consider reading through some of the more advanced guides:

Feedback

Please open an issue to request a feature or submit a bug report. Or even if you just want to provide some feedback, I'd love to hear. I'm also available on Twitter as @jstayton.

Options

All options are optional, although url is usually specified unless the input field is in a form by itself (in which case the form's action attribute can be used).

  • cache boolean

    Whether to cache query results. The cache is shared by all instances, which is a big advantage when many of the same field type appear on the same page. For example, a tags field that's repeated for every record on a page.

    Default: true


  • compare boolean, string

    Whether to compare the selected item against items displayed in the results list. The selected item is highlighted if a match is found, instead of the first item in the list (by default). Set this option to true if the data is a string; otherwise, specify the data object attribute name to compare on.

    Default: false


  • data object, string

    Additional data to be sent in the request query string. (Note: The query string parameter that is set with the input value (param option) will overwrite the value in the data object if an attribute with the same name exists.)

    Default: {}


  • delay integer

    The number of milliseconds to delay before firing a request after a change is made to the input value. This helps prevent an ajax request on every keystroke from overwhelming the server and slowing down the page.

    Default: 250


  • hideOnSelect boolean

    Whether to hide the results list when an item is selected. Interesting things can be done when this is set to false, such as hiding and showing certain items when other items are selected. The results list is still hidden when the input is blurred for any other reason.

    Default: true


  • label selector, jQuery object, DOM element, null

    Positioning a label over an input is a common design pattern (sometimes referred to as overlabel) that unfortunately doesn't work so well with all of the input focus/blur events that occur with autocomplete. With this option, however, the hiding/showing of the label is handled internally to provide a built-in solution to the problem. The label receives the class mp_label.

    Default: null


  • minChars integer

    The minimum number of characters required before a request is fired. See the formatMinChars callback to format the (optional) message displayed when this value is not reached.

    Default: 1


  • param string

    The name of the query string parameter that is set with the input value.

    Default: q


  • required boolean

    Whether to clear the input value when no selection is made from the results list. This happens when the input is blurred, usually by clicking or tabbing out of the field.

    Default: false


  • selectable selector

    The list items to make selectable. For example, say you add the class header to a number of list items (in the formatItem callback) that you want to act as non-selectable headers. They can be excluded with the selector :not(.header). Selectable items receive the class mp_selectable.

    Default: *


  • selected object, null

    Prime the input with a selected item. onSelect is called just as if the item were selected from the results list.

    Default: null


  • url string, null

    The URL to GET request for the results, which must be an array of strings or JSON. If no URL is set, the parent form's action attribute value is used if one exists. q is added to the query string with the input value, along with any additional data.

    Default: null

Callbacks

Formatting

  • formatData (data) function, null

    Format the raw data that's returned from the ajax request. Useful for further filtering the data or returning the array of results that's embedded deeper in the object.

    Default: null

    Parameters:

    • data object Data returned from the request.

    this: jQuery object Text input (no need to wrap like $(this)).

    Return: array of objects to use as the data.


  • formatError ($item, jqXHR, textStatus, errorThrown) function, null

    Format the text that's displayed when the ajax request fails. The message is displayed in a list item with the class mp_error:

    <li class="mp_error">
      <em>Your search could not be completed at this time.</em>
    </li>
    

    Setting this option to null or returning false suppresses the message from being displayed.

    Default:

    return '<em>Your search could not be completed at this time.</em>';
    

    Parameters:

    • $item jQuery object List item to display the message.
    • jqXHR object or XMLHTTPRequest in jQuery 1.4.x.
    • textStatus string Error status of the request.
    • errorThrown string HTTP error status.

    this: jQuery object Text input (no need to wrap like $(this)).

    Return: string, DOM element, or jQuery object to use as the message.


  • formatItem (data, $item) function

    Format the display of each item in the results list. By default, the title or name value of the data object is displayed. The returned value is added to a list item with the class mp_item:

    <li class="mp_item">The Title of Something</li>
    

    Default:

    return data.title || data.name;
    

    Parameters:

    • data object Data returned from the request.
    • $item jQuery object List item to display the result.

    this: jQuery object Text input (no need to wrap like $(this)).

    Return: string, DOM element, or jQuery object to use as the display.


  • formatMinChars (minChars, $item) function, null

    Format the text that's displayed when the minimum number of characters (specified with the minChars option) hasn't been reached. The message is displayed in a list item with the class mp_min_chars:

    <li class="mp_min_chars">
      <em>Your search must be at least <strong>3</strong> characters.</em>
    </li>
    

    Setting this option to null or returning false suppresses the message from being displayed. It is also not displayed when there is no input value.

    Default:

    return '<em>Your search must be at least <strong>' + minChars + '</strong>characters.</em>';
    

    Parameters:

    • minChars integer Minimum number of characters required.
    • $item jQuery object List item to display the message.

    this: jQuery object Text input (no need to wrap like $(this)).

    Return: string, DOM element, or jQuery object to use as the message.


  • formatNoResults (q, $item) function, null

    Format the text that's displayed when there are no results returned for the requested input value. The message is displayed in a list item with the class mp_no_results:

    <li class="mp_no_results">
      <em>No results for <strong>something</strong>.</em>
    </li>
    

    Setting this option to null or returning false suppresses the message from being displayed.

    Default:

    return '<em>No results for <strong>' + q + '</strong>.</em>';
    

    Parameters:

    • q string Requested input value.
    • $item jQuery object List item to display the message.

    this: jQuery object Text input (no need to wrap like $(this)).

    Return: string, DOM element, or jQuery object to use as the message.

Events

  • onChange (q) function, null

    Called when the input value changes.

    Default: null

    Parameters:

    • q string Changed input value.

    this: jQuery object Text input (no need to wrap like $(this)).

    Bind: You can also bind to the marcopolochange event:

    $(selector).bind('marcopolochange', function (event, q) { … });
    

  • onError ($item, jqXHR, textStatus, errorThrown) function, null

    Called when the ajax request fails.

    Default: null

    Parameters:

    • $item jQuery object List item to display the message.
    • jqXHR object or XMLHTTPRequest in jQuery 1.4.x.
    • textStatus string Error status of the request.
    • errorThrown string HTTP error status.

    this: jQuery object Text input (no need to wrap like $(this)).

    Bind: You can also bind to the marcopoloerror event:

    $(selector).bind('marcopoloerror', function (event, $item, jqXHR, textStatus, errorThrown) { … });
    

  • onFocus () function, null

    Called when the text input receives focus.

    Default: null

    Parameters: none

    this: jQuery object Text input (no need to wrap like $(this)).

    Bind: You can also bind to the marcopolofocus event:

    $(selector).bind('marcopolofocus', function (event) { … });
    

  • onMinChars (minChars, $item) function, null

    Called when the minimum number of characters (specified with the minChars option) hasn't been reached by the end of the delay.

    Default: null

    Parameters:

    • minChars integer Minimum number of characters required.
    • $item jQuery object List item to display the message.

    this: jQuery object Text input (no need to wrap like $(this)).

    Bind: You can also bind to the marcopolominchars event:

    $(selector).bind('marcopolominchars', function (event, minChars, $item) { … });
    

  • onNoResults (q, $item) function, null

    Called when there are no results returned for the request.

    Default: null

    Parameters:

    • q string Requested input value.
    • $item jQuery object List item to display the message.

    this: jQuery object Text input (no need to wrap like $(this)).

    Bind: You can also bind to the marcopolonoresults event:

    $(selector).bind('marcopolonoresults', function (event, q, $item) { … });
    

  • onRequestBefore () function, null

    Called before the ajax request is made. Useful for showing a loading spinner if the request is going to take some time.

    Default: null

    Parameters: none

    this: jQuery object Text input (no need to wrap like $(this)).

    Bind: You can also bind to the marcopolorequestbefore event:

    $(selector).bind('marcopolorequestbefore', function (event) { … });
    

  • onRequestAfter (jqXHR, textStatus) function, null

    Called after the ajax request completes (success or error). Useful for hiding a loading spinner that's shown in onRequestBefore.

    Default: null

    Parameters:

    • jqXHR object or XMLHTTPRequest in jQuery 1.4.x.
    • textStatus string Status of the request.

    this: jQuery object Text input (no need to wrap like $(this)).

    Bind: You can also bind to the marcopolorequestafter event:

    $(selector).bind('marcopolorequestafter', function (event, jqXHR, textStatus) { … });
    

  • onResults (data) function, null

    Called when there are results to be displayed.

    Default: null

    Parameters:

    • data object Data returned from the request.

    this: jQuery object Text input (no need to wrap like $(this)).

    Bind: You can also bind to the marcopoloresults event:

    $(selector).bind('marcopoloresults', function (event, data) { … });
    

  • onSelect (data, $item) function, null

    Called when an item is selected from the results list or passed in through the selected option. By default, the title or name value of the data object is used to populate the input value.

    Default:

    this.val(data.title || data.name);
    

    Parameters:

    • data object Data returned from the request.
    • $item jQuery object, null Selected results list item. null if selected option used.

    this: jQuery object Text input (no need to wrap like $(this)).

    Bind: You can also bind to the marcopoloselect event:

    $(selector).bind('marcopoloselect', function (event, data, $item) { … });
    

Methods

  • change

    Programmatically change the input value without triggering a search request (use the search method for that). If the value is different than the current input value, the onChange callback is fired.

    Example:

    $('#userSearch').marcoPolo('change', 'Wilson');
    

    Parameters:

    • q string New input value.
  • destroy

    Remove the autocomplete functionality and return the selected input fields to their original state.

    Example:

    $('#userSearch').marcoPolo('destroy');
    
  • list

    Get the results list element.

    Example:

    $('#userSearch').marcoPolo('list');
    
  • option

    Get or set one or more options.

    Example:

    Get a specific option:

    $('#userSearch').marcoPolo('option', 'url');
    

    Get the entire options object:

    $('#userSearch').marcoPolo('option');
    

    Set a specific option:

    $('#userSearch').marcoPolo('option', 'url', '/new/url');
    

    Set multiple options:

    $('#userSearch').marcoPolo('option', {
      url: '/new/url',
      onSelect: function (data, $item) { … }
    });
    

    Parameters:

    • nameOrValues string, object Optional options to get or set.
    • value mixed Optional option value to set.
  • search

    Programmatically trigger a search request using the existing input value or a new one. The input receives focus to allow for keyboard navigation.

    Example:

    Trigger a search on the existing input value:

    $('#userSearch').marcoPolo('search');
    

    Trigger a search on a new value:

    $('#userSearch').marcoPolo('search', 'Wilson');
    

    Parameters:

    • q string Optional new input value to search on.

About

A jQuery autocomplete plugin for the discerning developer.

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 100.0%