Reputation: 5386
I'm writing a program that should be able to find a university course based on a few of the courses parameters. I have a huge json object containing 1360 objects, and each object has around 20-30 parameters. I am only interested in about 3-5 of them however.
What I want to do is to be able to find a course based on it's number, the name, the name of the teacher or a set of keywords that each course has in it's description.
Anyway. I have tried messing around with twitters typeahead.js and as far as I can understand you need to parse it an array of strings, and it only takes 1 array as far as it seems. Isn't there an easy way (or another javascript module) that I can do this?
My current object is:
var courses = [
{ "number": "<5 digits>",
"name": "<course name>",
"teacher": "<teacher name>",
"keywords": "<string of keywords>" }
{ ... }
{ ... }
{ ... }
and so forth..
];
And it is as mentioned 1360 objects of size.
I want to get an output similar to this:
However I want to be able to search on the parameters mentioned (number, name, teacher name, keywords) and get the best possible match for whatever was input into the text field.
Does anyone have an idea of how to achieve this?
Upvotes: 1
Views: 1778
Reputation: 85528
This is very easy, but not with typeahead.js
. It has 231 open issues (at the time typing, some very serious) and has not been updated in a year.
Use bootstrap3-typeahead instead. It is maintained and uptodate. Take a look at the docs before reading further. You are not providing a JSON so I am using another JSON in the example below.
All you have to do is to define a matcher
method, here a very simple not case sensitive that compares with all attributes in a JSON item :
matcher: function(item) {
for (var attr in item) {
if (~item[attr].toString().toLowerCase().indexOf(this.query.toLowerCase())) return true
}
return false
}
You can override which attrs / text that should be shown in the dropdown using displayText
(pure example) :
displayText: function(item) {
return item.id + ' ' + item.label + ' ' + item.value
}
If you want to override the rendering of the items completely, as complex HTML, use a combination of displayText
and highlighter
where each display string contain the stringified JSON :
displayText: function(item) {
return JSON.stringify(item)
},
highlighter: function(item) {
item = JSON.parse(item)
return '<span><h4>'+item.value + '</h4>' + item.id + ' ' + item.label +'</span>'
}
When the display string is stringified, the <input>
must be updated with the value attribute(s) that should be the selected value :
afterSelect: function(item) {
this.$element[0].value = item.value
}
Complete example :
$('#example').typeahead( {
source: json,
matcher: function(item) {
for (var attr in item) {
if (~item[attr].toString().toLowerCase().indexOf(this.query.toLowerCase())) return true
}
return false
},
displayText: function(item) {
return JSON.stringify(item)
},
highlighter: function(item) {
item = JSON.parse(item)
return '<span><h4>'+item.value + '</h4>' + item.id + ' ' + item.label +'</span>'
},
afterSelect: function(item) {
this.$element[0].value = item.value
}
})
demo -> http://jsfiddle.net/vhme3td1/
Upvotes: 2