Skip to content

Reuters tutorial: step 8

James McKinney edited this page Apr 13, 2013 · 22 revisions

Table of Contents

We want to allow the user to explore the Reuters business news by place of origin. In a first stage, we will allow the user to use the facet data for filtering. In a second stage, we will allow the user to see the facet data displayed via a map using the Google Chart API.

First, update the Solr parameters for faceting in reuters.js:

var params = {
  ...
  'facet.field': [ 'topics', 'organisations', 'exchanges', 'countryCodes' ],
  ...
  'f.countryCodes.facet.limit': -1,
  ...
};

The facet.limit parameter for countryCodes is set to a negative value so that Solr returns all facet values.

Create a new widget, CountryCodeWidget.js, inheriting from AbstractFacetWidget, as for the tagcloud:

(function ($) {
AjaxSolr.CountryCodeWidget = AjaxSolr.AbstractFacetWidget.extend({
});
})(jQuery);

Add the JavaScript file:

<script src="widgets/CountryCodeWidget.js"></script>

And add an instance of the widget to the Manager in reuters.js:

Manager.addWidget(new AjaxSolr.CountryCodeWidget({
  id: 'countries',
  target: '#countries',
  field: 'countryCodes'
}));

We will need the following utility function to implement the widget, so add it to reuters.js:

$.fn.showIf = function (condition) {
  if (condition) {
    return this.show();
  }
  else {
    return this.hide();
  }
}

Now, we’re ready to implement afterRequest. Below, we keep track of the largest facet count, because we will need it in the second stage outlined above:

afterRequest: function () {
  var self = this;

  $(this.target).empty();

  var maxCount = 0;
  var options = { '': '--select--' };
  for (var facet in this.manager.response.facet_counts.facet_fields[this.field]) {
    if (facet.length == 2) { // only display country codes
      var count = this.manager.response.facet_counts.facet_fields[this.field][facet];
      if (count > maxCount) {
        maxCount = count;
      }
      options[facet] = facet + ' (' + count + ')';
    }
  }
  $(this.target).append(this.template('country', options));

  $(this.target).find('#country').change(function () {
    var value = $(this).val();
    if (value && self.add(value)) {
      self.doRequest();
    }
  });
},

template: function (name, container) {
  var options = [];
  for (var value in container) {
    options.push('<option value="' + value +'">' + container[value] + '</option>');
  }
  return '<select id="' + name + '" name="' + name + '">' + options.join('\n') + '</select>';
}

Within the afterRequest method, in the first block of code after emptying the target, we compile a list of options for a select tag, and append to the target a select tag with an id of #country with those options. The rest of this first block should be familiar.

In the second block of code, as in the free-text widget, we use the AbstractFacetWidget add API method directly.

[What we have so far]

Now, let’s display the facet data with a map visualization. First, create a drop-down list with which the user may select which part of the world to focus on. Add the following code right after emptying the target:

var maps = {
  world: 'view the World',
  africa: 'view Africa',
  asia: 'view Asia',
  europe: 'view Europe',
  middle_east: 'view the Middle East',
  south_america: 'view South America',
  usa: 'view North America'
};
$(this.target).append(this.template('region', maps));

$(this.target).find('#region').change(function () {
  $(self.target).find('img').hide();
  $('#' + self.id + $(this).val()).show();
});

The change function will control which part of the world we display to the user. Now, we can create those maps by adding the following code before the end of the afterRequest method:

var chd = [];
var chld = '';
for (var facet in this.manager.response.facet_counts.facet_fields[this.field]) {
  if (facet.length == 2) { // only display country codes
    chd.push(parseInt(this.manager.response.facet_counts.facet_fields[this.field][facet] / maxCount * 100) + '.0');
    chld += facet;
  }
}
for (var value in maps) {
  var src = 'http://chart.apis.google.com/chart?chco=f5f5f5,edf0d4,6c9642,365e24,13390a&chd=t:' + chd.join(',') + '&chf=bg,s,eaf7fe&chtm=' + value + '&chld=' + chld + '&chs=350x180&cht=t';
  $('<img>').attr('id', this.id + value).showIf(value == 'world').attr('src', src).appendTo(this.target);
}

The above code has almost nothing to do with AJAX Solr. I include it only to show that it is very easy to create fancy visualizations with AJAX Solr. Congrats, you now have a map widget!

[What we have so far]

Show me something else fancy.