An autocomplete middleware for Sinatra & jQuery
An autocomplete script is based on a dom element that uses javascript to generate asynchronous requests to a remote service and parse the response to offer matching choices to the user, if any is found.
Let's use a trivial Player model with a username method and build an autocomplete field for it.
View
we need to specify three things for the input field: it must have `autocomplete` as class attribute so that jQuery will be able to attach events to it, and specify the ruby class and method (klass, method) we want to invoke. It's also a good idea to disable the browser autocomplete feature that would interfere with our autocomplete. Specifying klass and method may seem redundant as they could appear in the ID, but it's not: player_picture_count is an example of ambiguous ID.
Javascript
the autocomplete javascript attaches and handles keyboard and mouse events for all the input fields of `autocomplete` class and the associated autocomplete list div. In our example, the player_username field will generate requests to /autocomplete/player/username/query when the length of the input is at least 2 and the ASCII code for the pressed key is between 45 and 106 (letters, numbers and some symbols), or a backspace. Arrows, clicks and tabs are used to interact with the autocomplete list.
Middleware
the middleware responds to autocomplete requests with some magic*. It's important to whitelist every single class and method that are allowed to avoid issues: the ensure_autocompletable will halt the execution otherwise. There are two possibliy configurable elements in the query: the search by wildcard - that is usually a use case expected by the user - and a limit of 10 items to return. Also, generating HTML here... TODO: refactor.
Partial
the js partial rendered by the autocomplete simply populates the autocomplete div with the result from the query and attaches some event handling for highlighting the currently selected item in the autocomplete list.
Main App
That's about it!
published on 18 Jul

