mbrio / backbone.suggestions

An autocompletion view for Backbone.js
MIT License
10 stars 1 forks source link

backbone.suggestions.js

An autocompletion view for Backbone.js

Requirements

To run the demo

cake demo

To build

cake build

To uglify

cake uglify

To build spec tests

cake spec

To build documentation

cake docs

To clean

cake clean

Introduction

backbone.suggestions.js is a Backbone.js view written in CoffeeScript that enables AJAX autocompletion backed by a localStorage cache for text input fields.

There is no need to add HTML to your document to display the suggestion menu. A <div> element will be generated and placed within the document.body element.

<div class="suggestions-menu">
  <ol>
    <li class="selected">Alabama</li>
    <li>Alaska</li>
  </ol>
</div>

Demo

I have supplied a demo application which sits in /demo, along with the necessary libraries and HTML code. I've added an Express server that will manage serving HTML and JSON data.

There is a custom compiler middleware configured within the demo that will compile the CoffeeScript files automatically whenever a JS file is requested, the compiled JS will be cached for five seconds.

The demo will run on port 3000, http://localhost:3000.

Usage

Suggestions.View(options)

Options

Example

view = new Suggestions.View({
  el: $('input[type="text"].suggestions'),
  ajax: {
    url: '/suggestions.json?p=:page&t=:take&q=:query'
  }
});

Templates

You can pass templates in as options, the following example displays all of the available template options and what their default values are. The values for each of the templates must result in a function.

view = new Suggestions.View({
  el: $('input[type="text"].suggestions'),
  ajax: {
    url: '/suggestions.json?p=:page&t=:take&q=:query'
  },
  templates: {
    container: _.template('<div class="<%= cssClass %>"></div>')
    default: _.template('<span class="message default">Begin typing for suggestions</span>')
    loading: _.template('<span class="message loading">Begin typing for suggestions (Loading...)</span>')
    loadedList: _.template('<ol class="<%= cssClass %>"></ol><ol class="<%= pagingPanelCssClass %>"><li><a href="https://github.com/mbrio/backbone.suggestions/blob/master/javascript:void(0)" class="<%= prevActionCssClass %>">Prev</a></li><li><a href="https://github.com/mbrio/backbone.suggestions/blob/master/javascript:void(0)" class="<%= nextActionCssClass %>">Next</a></li></ol>')
    loadedItem: _.template('<li class="<%= cssClass %>"><a href="#" class="<%= actionCssClass %>"><%= value %></a></li>')
    empty: _.template('<span class="message empty">No suggestions were found</span>')
    error: _.template('<span class="message error">An error has occurred while retrieving data</span>')
  }
});

JSON Results

JSON formatted responses must contain 1 object with a property called suggestions that represents an array of suggestion values. It may also contain a second object called hasMore that represents if there are more values that can be loaded in.

With No More Pages

{
  "suggestions": [
    { "value": "Alabama" },
    { "value": "Alaska" },
    { "value": "American Samoa" },
    { "value": "Arizona" },
    { "value": "Arkansas" }
  ],
  "hasMore": false
}

With More Pages

{
  "suggestions": [
    { "value": "Alabama" },
    { "value": "Alaska" },
  ],
  "hasMore": true
}

Your suggestions do not have to contain the same data as above (i.e. a property called value); though if they contain fields different than above you must pass in a custom templates.loadedItem template, as well as the valueField option.

Testing

All of the tests are built using Jasmine and Mary. You can run the tests by launching /specs/SpecRunner.html in your browser after running the following commands:

cake spec

Upgrading To Version 0.7.0

The major change is in the way that options are passed. The url option needs to be passed through the ajax property and all of the callback options need to be passed through the callbacks property.

Before

view = new Suggestions.View({
  el: $('input[type="text"].suggestions'),
  url: '/suggestions.json?q=:query',
  selected: function() { console.log('selected'); }
});

After

view = new Suggestions.View({
  el: $('input[type="text"].suggestions'),
  ajax: {
    url: '/suggestions.json?q=:query'
  },
  callbacks: {
    selected: function() { console.log('selected'); }
  }
});

Upgrading To Version 0.7.2

The name property is no longer the default value property of the returned JSON data, the new default value property name is value.

Before

{
  "suggestions": [
    { "name": "Alabama" },
    { "name": "Alaska" },
    { "name": "American Samoa" },
    { "name": "Arizona" },
    { "name": "Arkansas" }
  ]
}

After

{
  "suggestions": [
    { "value": "Alabama" },
    { "value": "Alaska" },
    { "value": "American Samoa" },
    { "value": "Arizona" },
    { "value": "Arkansas" }
  ]
}

You can make the new code work with the old data by passing the following options to the view:

view = new Suggestions.View({
  el: $('input[type="text"].suggestions'),
  ajax: {
    url: '/suggestions.json?q=:query'
  },
  valueField: 'name',
  callbacks: {
    selected: function() { console.log('selected'); }
  },
  templates: {
    loadedItem: _.template('<li class="<%= cssClass %>"><a href="#" class="<%= actionCssClass %>"><%= name %></a></li>'),
  }
});

Upgrading to Version 0.7.11

The templates now rely on CSS classes for selecting the elements of the template. This should make the templates much more flexible. Any custom templates made for previous versions of the backbone.suggestions.js view must be converted to the new template structure.

Before

container: _.template('<div></div>')
default: _.template('<span class="message default">Begin typing for suggestions</span>')
loading: _.template('<span class="message loading">Begin typing for suggestions (Loading...)</span>')
loadedList: _.template('<ol></ol>')
loadedItem: _.template('<li><a href="#"><%= value %></a></li>')
empty: _.template('<span class="message empty">No suggestions were found</span>')
error: _.template('<span class="message error">An error has occurred while retrieving data</span>')

After

container: _.template('<div class="<%= cssClass %>"></div>')
default: _.template('<span class="message default">Begin typing for suggestions</span>')
loading: _.template('<span class="message loading">Begin typing for suggestions (Loading...)</span>')
loadedList: _.template('<ol class="<%= cssClass %>"></ol>')
loadedItem: _.template('<li class="<%= cssClass %>"><a href="#" class="<%= actionCssClass %>"><%= value %></a></li>')
empty: _.template('<span class="message empty">No suggestions were found</span>')
error: _.template('<span class="message error">An error has occurred while retrieving data</span>')

Upgrading to Version 0.8.0

The service now supports loading in of more suggestions. The JSON data returned can now have a value called hasMore which enables the loading of more values. This value should be set to true if there are more results that can be loaded in, otherwise if all values have been requested it should return false.

Before

{
  "suggestions": [
    { "name": "Alabama" },
    { "name": "Alaska" },
    { "name": "American Samoa" },
    { "name": "Arizona" },
    { "name": "Arkansas" }
  ]
}

After

{
  "suggestions": [
    { "value": "Alabama" },
    { "value": "Alaska" },
    { "value": "American Samoa" },
    { "value": "Arizona" },
    { "value": "Arkansas" }
  ],
  "hasMore": false
}

There is an update to the templates as well, the loadedList template now contains the element that represents the more button.

Before

loadedList: _.template('<ol class="<%= cssClass %>"></ol>')

After

loadedList: _.template('<ol class="<%= cssClass %>"></ol><span class="<%= morePanelCssClass %>"><a href="https://github.com/mbrio/backbone.suggestions/blob/master/javascript:void(0)" class="<%= moreActionCssClass %>">More</a></span>')

Upgrading to Version 0.8.1

The moreActionCssClass parameter has been renamed to nextActionCssClass and the morePanelCssClass has been renamed to pagingPanelCssClass.

Along with this the template for loadedList has changed to support a previous button.

loadedList: _.template('<ol class="<%= cssClass %>"></ol><ol class="<%= pagingPanelCssClass %>"><li><a href="https://github.com/mbrio/backbone.suggestions/blob/master/javascript:void(0)" class="<%= prevActionCssClass %>">Prev</a></li><li><a href="https://github.com/mbrio/backbone.suggestions/blob/master/javascript:void(0)" class="<%= nextActionCssClass %>">Next</a></li></ol>')

Another service update has been made in this version, you can now pass in both the page number and how many items to take from the result set.

Before

view = new Suggestions.View({
  el: $('input[type="text"].suggestions'),
  ajax: {
    url: '/suggestions.json?q=:query'
  }
});

After

view = new Suggestions.View({
  el: $('input[type="text"].suggestions'),
  ajax: {
    url: '/suggestions.json?p=:page&t=:take&q=:query'
  }
});

License

Copyright (c) 2011-2012 Michael Diolosa [michael.diolosa@gmail.com](michael.diolosa@gmail.com)

The backbone.suggestions.js library is licensed under the MIT license. For more information see the Wiki.