How to build a news aggregator with Dojo

Nowadays many websites display twitter widgets with good or bad moods of their authors. I told myself that it was not bad at all, but I think better things could be done.

Emmett Brown And this morning, I was standing on the edge of my toilet hanging a clock, the porcelain was wet, I slipped, hit my head on the sink, and when I came to I had a revelation! A vision! A picture in my head! A picture of this! This is what makes time travel possible: the flux capacitor! This is what displays news on subjects I am interested in: a Dojo widget!

This is what I needed to realize it:
Dojo Toolkit, a modular JavaScript library for building cross-platform desktop and mobile web applications.
And NewsinApp.io, a free service making possible to get aggregated news on subjects. It’s perfect to feed my widget.

Just before I start, here is what we will build:
news aggregator widget news aggregator widget

Two widgets displaying respectively the latest news about Johnny Depp and Tim Burton.
Live demo
The source code of the article

Newsinapp.io, huh ?

Newsinapp.io is a REST API allowing us to get news from topics. Each topic is associated with a context (arts, games, health …), so news provided are more relevant.
For example, when I define the Tim Burton topic, I associate it to the arts/movies context (or entity as they call it). Same if I define a Dojo topic, I can use the computers entity.

To use this API, I have subscribed to their website, then I have received an access key. So I could define all topics I’m interested in. In my case: Tim Burton and Johnny Depp.

Karate lesson with Dojo

It’s time to get some news.
To communicate with newsinapp.io, I use the Dojo XHR module which allows AJAX request.

require(["dojo/_base/xhr"], function(xhr){
  var def = xhr.get({
    headers: {'X-Requested-With': null},
    url: "http://api.newsinapp.io/topics/news/v1/",
    handleAs: "json",
    content : { page: "1",   
                auth_api_key: "your_newsinapp_api_key"}
  });
  def.then(function(response){
    callback(response);
  });
});

xhr.get makes a HTTP GET request. It takes some parameters:

  • url: resource to get.
  • content: parameters to pass to resource url

Example of response displayed in the Chrome console:
ajax request response in chrome

Great Scott!! 20 news about Tim Burton and Johnny Depp!

But according to Dojo, XHR.get should not be able to do a cross-domain request. And yet it works! It’s because newsinapp.io is compatible CORS (Cross-Origin Resource Sharing). This is a web browser technology specification, which defines ways for a web server to allow its resources to be accessed by a web page from a different domain.
However to be compatible with CORS, XHR request must have the following parameter: headers: {'X-Requested-With': null} (More details on CORS, Dojo and X-Requested-With)

And now … the widget!

I put in a Dojo module all files that compose the widget:
dojo module organization

  • Index.html: html page sample
  • Client.js: class which enables access to newsinApp.io
  • NewsListWidget.js: class of the widget
  • NewsListWidget.html: html template

I begin with the class that defines the widget:

define([ "dijit/_WidgetBase",
         "dojox/dtl/_Templated",
         "dojo/_base/declare",
         "dojo/text!./NewsListWidget.html",
         "dojox/dtl/tag/logic"
          ],
  function(_WidgetBase, _Templated, declare, template){
    return declare([_WidgetBase, _Templated], {
      newsList: null,
...
      templateString: template,
...
    });
  });

Not so much code here, but some explanation is required.

The class inherits from:

  • dijit/_WidgetBase, to have the taste of a widget
  • dojox/dtl/_Templated, to have HTML rendering using a template

The widget read the HTML template from templateString variable. And dojo/text! loads the content of the file NewsListWidget.html in templateString. It allows to avoid having the template directly into the JavaScript code.

newslist variable is important here because it contains the list of news coming from newsinapp.io.

The template… or how to dress our widget

What I like with templates is the ability to separate code and presentation. On one side, I have my widget with data and logic, on the other I have my template for the design.
To define HTML template, Dojo has it’s own implementation of the django template language (DTL).

The HTML template in NewsListWidget.html:

<div class="feed-box">
  <div class="header">
    <h3>{{ title }}<h3>
  </div>

{% for news in newsList %}

  {% if news.image %}
  <div class="media">
    <div class="img-container">
      <img src="{{ news.image }}" />
    </div>
  {% else %}
  <div class="media no-image">
  {% endif %}
    {% if news.title %}
    <a href="{{ news.url }}" target="_blank">{{ news.title }}</a>
    {% endif %}
    {% if news.source %}
    <p class="source">{{ news.source }}</p>
    {% endif %}
    <div class="footer"></div>
  </div>

{% endfor %}

</div>

The template can use variables defined in the widget class. So {{ title }} displays the member title of the widget. And the loop {% for news in newsList %} allows to display each news using member newsList.

To use template tag if and for, I have to include a dependency to the module dojox/dtl/tag/logic. For tag such as now or extends, other modules must be added.

We approach 88 mph

Last step, creating the widget:

require(["newsinapp.io/Client", "newsinapp.io/NewsListWidget", 
         "dojo/dom", "dojo/_base/array", "dojo/domReady!"],
  function(NewsinappioClient, NewsListWidget, dom, arrayUtil){

    var newsinapp = new NewsinappioClient('your_newsinapp_api_key');

    newsinapp.getLastNews(function(response) { 
      var container;
      container = dom.byId("newsListWidgetContainer");

      new NewsListWidget({title: "Johnny Depp - Latest news",
                          newsinappResponse: response,
                          topicFilter: "Johnny Depp"}).placeAt(container);;
    });
  });

Some explanations to understand this code:

First, NewsInAppioClient class retrieves the list of news to pass them to the Widget. Then, the Widget filters only news referring to Johnny Deep (topicFilter). And finally, the method placeAt renders the Widget where the HTML tag with ID newsListWidgetContainer is located.

Back to the future!

And voila! It’s already finished for this article. Finally, it was not too hard: we have a widget that can be placed on any HTML page, with news on personalized topics!

Next entry

blog comments powered by Disqus