Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ranelpadon/cd8d7d0d734d24b53c5f to your computer and use it in GitHub Desktop.
Save ranelpadon/cd8d7d0d734d24b53c5f to your computer and use it in GitHub Desktop.
Sample integration of Twitter TypeAhead Library with a remote data server (TripAdvisor API).
MAPWIDGET = MAPWIDGET || {};
// Constructor function for TripAdvisor's TypeAhead behavior.
MAPWIDGET.Autocomplete = function(domElement) {
// TypeAhead Source URL per documentation of TripAdvisor.
// See http://api.tripadvisor.com/api/partner/2.0/doc?key=TA_KEY.
// %QUERY is a wildcard needed by the suggestion engine.
var typeAheadUrl = TripAdvisor_API_BASE_URL + '/typeahead/%QUERY?key=' + tripAdvisorKey;
// Create a new suggestion engine dedicated for the specified category.
function suggestionEngine(category) {
// Create a new BloodHound suggestion engine.
// See https://github.com/twitter/typeahead.js for API.
var places = new Bloodhound({
// Data Source for the suggestion engine.
// Other options: "local" and "prefetch".
remote: {
url: typeAheadUrl,
// Fetch the TripAdvisor's JSON object.
// Filter the information that will be displayed.
filter: function (places) {
// Get the current text of the search field.
var currentText = jQuery('input.tt-input').val();
// Check if the currently searched Place name has no returned results.
// And it should not consider already selected Place name.
// The selected Place name contains left and right parentheses.
if (jQuery.isEmptyObject(places) && currentText.indexOf("(") == -1) {
// Modify the search bar to indicate a no result behavior.
// This is a light orange color to slighty blend with the generally
// white and gray elements of the Dialog window.
MAPWIDGET.Autocomplete.display_error();
}
// If there's a result, revert to the default color.
// This is necessary especially to switch back from orange color
// to transparent color.
else {
MAPWIDGET.Autocomplete.display_default();
}
// Get the index of "-" char if any.
var dashIndex = jQuery('input.tt-input').val().indexOf("-");
// If the current Place is not found in the TripAdvisor servers,
// check if it has a dash on it. Truncating the dash works
// for some specific Place names.
if (jQuery.isEmptyObject(places) && dashIndex != -1) {
// Remove the dash.
cleaned = jQuery('input.tt-input').val().replace(/-/g, "");
// Modify the currently searched Place name.
jQuery('input.tt-input').typeahead("val", cleaned);
}
// Check if there's at least one search result in the
// current category. Categories are 'Attractions', 'Hotels',
// and 'Restaurants'. Not using this check will throw a bunch
// of annoying console error notices, and will make the autocomplete
// to behave erratically after some time.
if (places.hasOwnProperty(category)) {
// Fetch the target category only.
return $.map(places[category], function (place) {
// Container for City name, since we want to include
// this information to minimize ambiguity
// between Places of the same name.
var city = "";
// Check if the current Place has a defined City name.
if (place.address_obj.city != "" && place.address_obj.city != null) {
city = place.address_obj.city;
}
var address = "";
// Check if the current Place has a defined City name.
if (place.address_obj.address_string != "" && place.address_obj.address_string != null) {
address = place.address_obj.address_string;
}
// Build the suggestion item for the current Place.
// Include the City name to avoid ambiguity.
var suggestion = (city != "") ? place.name + " (" + city + ")": place.name;
return {
// Set the property of each Place object
// that will be displayed in the autosuggestion.
// This will display the names of Places.
// City and Location ID will be not displayed in
// the suggestions list but will be used behind the scenes.
// Luckily, Twitter TypeAhead API has this clever mechanism
// yet not clearly documented on its site.
// This set of information could be retieved later in real-time
// via the suggestion obejct when the "typeahead:selected" and
// "typeahead:autocompleted" events have been fired.
// At a minimum, this object must have a "value" parameter/key.
"value": suggestion,
"city": city,
"address": address,
"locationId": place.location_id
};
});
}
// This part is very important. This is the handler for cases
// with no search results.
else {
return {
// Return an empty object. That's it.
// These combinations will not work:
// return { value: "" }, or retun { value: null }.
};
}
}
},
// Transform the data source into an array of string tokens.
// This is a required parameter.
datumTokenizer: function (datum) {
return Bloodhound.tokenizers.whitespace(datum.value);
},
// Transform the search query into an array of string tokens.
// This is a required parameter.
queryTokenizer: Bloodhound.tokenizers.whitespace,
});
return places;
}
var categories = ["attractions", "hotels", "restaurants"];
var len = categories.length;
var places_datasets = [];
// Do some TypeAhead pre-processing needed.
for (var i = 0; i < len; i++) {
// Create a new suggestion object.
var places = suggestionEngine(categories[i]);
// Load/initialize the suggestion engine for this Place.
places.initialize();
// Create a new object for storing TypeAhead dataset and its options.
var dataset = {};
// Format the sub-group name/header to be displayed.
var firstWordCapitalized = categories[i].charAt(0).toUpperCase() + categories[i].slice(1);
// Add template for displaying the autosuggestion's sub-groups.
dataset.templates = {header: '<h4 class="place_group">' + firstWordCapitalized + '</h4>'}
//dataset.templates = {footer: '<p class="search-more">Search More Results</p>'}
// Set the TypeAhead's data source.
dataset.source = places.ttAdapter();
// Add to the existing TypeAhead datasets.
places_datasets.push(dataset);
}
// Convert the text field as a typeahead object.
// Set the hint and highlighting behavior in the suggestions list,
// as well as the minimum number of characters typed by a user before
// the typeahead engine will kick-in.
domElement.typeahead({
hint: true,
highlight: true,
minLength: 3
},
places_datasets
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment