diaspora/app/assets/javascripts/app/views/search_base_view.js

112 lines
3.3 KiB
JavaScript

app.views.SearchBase = app.views.Base.extend({
initialize: function(options) {
this.ignoreDiasporaIds = [];
this.typeaheadInput = options.typeaheadInput;
this.suggestionLink = options.suggestionLink || false;
this.setupBloodhound(options);
if(options.customSearch) { this.setupCustomSearch(); }
this.setupTypeahead();
if(options.autoselect) { this.setupAutoselect(); }
},
bloodhoundTokenizer: function(str) {
if(typeof str !== "string") { return []; }
return str.split(/[\s\.:,;\?\!#@\-_\[\]\{\}\(\)]+/).filter(function(s) { return s !== ""; });
},
setupBloodhound: function(options) {
var bloodhoundOptions = {
datumTokenizer: function(datum) {
// hashtags
if(typeof datum.handle === "undefined") { return [datum.name]; }
// people
if(datum.name === datum.handle) { return [datum.handle]; }
return this.bloodhoundTokenizer(datum.name).concat(datum.handle);
}.bind(this),
queryTokenizer: Bloodhound.tokenizers.whitespace,
sufficient: 5
};
// Allow bloodhound to look for remote results if there is a route given in the options
if(options.remoteRoute) {
bloodhoundOptions.remote = {
url: options.remoteRoute + ".json?q=%QUERY",
wildcard: "%QUERY",
transform: this.transformBloodhoundResponse.bind(this)
};
}
this.bloodhound = new Bloodhound(bloodhoundOptions);
},
setupCustomSearch: function() {
var self = this;
this.bloodhound.customSearch = function(query, sync, async) {
var _async = function(datums) {
var results = datums.filter(function(datum) {
return datum.handle !== undefined && self.ignoreDiasporaIds.indexOf(datum.handle) === -1;
});
async(results);
};
self.bloodhound.search(query, sync, _async);
};
},
setupTypeahead: function() {
this.typeaheadInput.typeahead({
hint: false,
highlight: true,
minLength: 2
}, {
async: true,
display: "name",
limit: 5,
source: this.bloodhound.customSearch !== undefined ? this.bloodhound.customSearch : this.bloodhound,
templates: {
/* jshint camelcase: false */
suggestion: HandlebarsTemplates.search_suggestion_tpl
/* jshint camelcase: true */
}
});
},
transformBloodhoundResponse: function(response) {
return response.map(function(data) {
// person
if(data.handle) {
data.person = true;
data.link = this.suggestionLink;
return data;
}
// hashtag
return {
hashtag: true,
name: data.name,
url: Routes.tag(data.name.substring(1))
};
}.bind(this));
},
_deselectAllSuggestions: function() {
this.$(".tt-suggestion").removeClass("tt-cursor");
},
_selectSuggestion: function(suggestion) {
this._deselectAllSuggestions();
suggestion.addClass("tt-cursor");
},
// Selects the first result when the result dropdown opens
setupAutoselect: function() {
var self = this;
this.typeaheadInput.on("typeahead:render", function() {
self._selectSuggestion(self.$(".tt-menu .tt-suggestion").first());
});
},
ignorePersonForSuggestions: function(person) {
if(person.handle) { this.ignoreDiasporaIds.push(person.handle); }
}
});