-
Notifications
You must be signed in to change notification settings - Fork 210
Reuters tutorial: step 7
- Reuters tutorial
- Step 1: Talk to Solr
- Step 2: Add a results widget
- Step 3: Add a pager widget
- Step 4: Add a tagcloud widget
- Step 5: Display the current filters
- Step 6: Add a free-text widget
- Step 7: Add an autocomplete widget
- Step 8: Add a map widget
- Step 9: Add a calendar widget
- Step 10: Extra credit
We’ll now replace the free-text widget we created in the last step with a widget that can do auto-completion on the facet values of the topics, organizations, and exchanges facet fields. For this, we’ll use the jQuery Autocomplete plugin.
Create a new widget, AutocompleteWidget.js, inheriting from AbstractFacetWidget:
(function ($) { AjaxSolr.AutocompleteWidget = AjaxSolr.AbstractFacetWidget.extend({ }); })(jQuery);
In index.html, replace:
<script type="text/javascript" src="widgets/TextWidget.js"></script>
With:
<link rel="stylesheet" type="text/css" href="ext/jquery.autocomplete.css" media="screen" /> <script type="text/javascript" src="ext/jquery.autocomplete.js"></script> <script type="text/javascript" src="widgets/AutocompleteWidget.js"></script>
And, in reuters.js, replace:
Manager.addWidget(new AjaxSolr.TextWidget({ id: 'text', target: '#search', field: 'allText' }));
With:
Manager.addWidget(new AjaxSolr.AutocompleteWidget({ id: 'text', target: '#search', field: 'allText', fields: [ 'topics', 'organisations', 'exchanges' ] }));
The autocompletion widget will take a custom fields parameter, listing the facet fields on which to perform auto-completion. By not hard-coding these facet fields, we make the widget re-usable.
Implement the abstract method afterRequest, like so:
afterRequest: function () { $(this.target).find('input').val(''); var self = this; var list = []; for (var i = 0; i < this.fields.length; i++) { var field = this.fields[i]; for (var facet in this.manager.response.facet_counts.facet_fields[field]) { list.push({ field: field, value: facet, text: facet + ' (' + this.manager.response.facet_counts.facet_fields[field][facet] + ') - ' + field }); } } this.requestSent = false; $(this.target).find('input').autocomplete(list, { formatItem: function(facet) { return facet.text; } }).result(function(e, facet) { self.requestSent = true; if (self.manager.store.addByValue('fq', facet.field + ':' + facet.value)) { self.manager.doRequest(0); } }).bind('keydown', function(e) { if (self.requestSent === false && e.which == 13) { if (self.add($(this).val())) { self.manager.doRequest(0); } } }); }
There is, actually, very little going on here specific to your understanding of AJAX Solr. We are again using the ParameterStore addByValue and add API methods, as we did in the results widget and free-text widget, respectively. The rest is jQuery Autocomplete plugin implementation.
A limitation is that it will only do auto-completion for the facet values that fall within the facet.limit for the given facet fields. For example, it will only do auto-completion for twenty of the facet values in the exchanges facet field, because we set facet.limit to 20 in reuters.js. If we want to do auto-completion for all facet values, we will need to retrieve them in a separate Solr request.
First, wrap the code after var self = this;
in a callback function, replacing all occurrences of this with self, because this will not refer to the widget instance inside the callback function. Then, replace all occurrences of this.manager.response with response. The callback function will take response as an argument, which will contain the Solr response we will request in a moment.
afterRequest: function () { $(this.target).find('input').val(''); var self = this; var callback = function (response) { var list = []; for (var i = 0; i < self.fields.length; i++) { var field = self.fields[i]; for (var facet in response.facet_counts.facet_fields[field]) { list.push({ field: field, value: facet, text: facet + ' (' + response.facet_counts.facet_fields[field][facet] + ') - ' + field }); } } self.requestSent = false; $(self.target).find('input').autocomplete(list, { formatItem: function(facet) { return facet.text; } }).result(function(e, facet) { self.requestSent = true; if (self.manager.store.addByValue('fq', facet.field + ':' + facet.value)) { self.manager.doRequest(0); } }).bind('keydown', function(e) { if (self.requestSent === false && e.which == 13) { if (self.add($(self).val())) { self.manager.doRequest(0); } } }); } // end callback }
The only important change we’ve made so far is to change the code to inspect a different Solr response than the one stored in this.manager.response. Before we send a new request to Solr, we must first build the list of parameters to send to Solr. Add the following code after the callback function:
var params = [ 'q=*:*&facet=true&facet.limit=-1&facet.mincount=1&json.nl=map' ]; for (var i = 0; i < this.fields.length; i++) { params.push('facet.field=' + this.fields[i]); }
These parameters should be familiar; they are a subset of the parameters we set in reuters.js, with an important difference – we’ve set facet.limit to a negative value, so that Solr returns all facet values.
We now borrow some code from managers/Manager.jquery.js to send the request to Solr:
$.getJSON(this.manager.solrUrl + '?' + params.join('&') + '&wt=json&json.wrf=?', {}, callback);
We can now do auto-completion for all facet values!
To support sending the request through a proxy, we would have borrowed more code from Manager.jquery.js.
OK, now let’s get fancy and add a map widget.