Building a Twitter Widget using Distal

Dmitri Lau

I’ll show you how to build a Twitter widget for your website that downloads the latest tweets from your twitter account using Twitter’s search API, and displays them in a table.

To download the tweets, we will be using Twitter’s search API. We will be using HTML to build the user interface, and then Distal to dynamically add the data into the interface.

Firstly, let’s familiarize ourselves with the Twitter API. Twitter uses a REST API which means we need to load a URL containing the search query and Twitter will return formatted text containing the search results. We need to load this URL in our widget:

http://search.twitter.com/search.json?q={keywords}&callback={function}

And Twitter will return something like this:

callback({
  "page": 1,
  "query": "{keywords}",
  "results": [{
    "created_at": "Mon, 13 Feb 2012 01:23:45 +0000",
    "from_user": "ladiesman217"
    "from_user_id": 123456789,
    "profile_image_url": "http://www..jpg",
    "text": "I'm eating food!"
  }]
})

The request URL is pretty straight forward, so let’s dissect the response. The response is in the format of a regular JavaScript object. The object has a property called “results”, which is an array of objects and each object represents a tweet. Each tweet has a property that exposes the sender’s name, tweet message, and the date it was made.

To make the call we can’t use the browser’s native XMLHttpRequest, because it is a cross-domain call, which is not allowed by the browser for security reasons.

Instead, we will be using the JSON-P technique, which means we will dynamically add a script tag to our document that points to the Twitter page. The Twitter server will return a JSON object surrounded by a function call, known as a callback, that will be executed by the browser. We will need to define that callback function in order to be able to grab the JSON object.

Here is our code to make the JSON-P call:

function searchTwitter() {
  var node = document.getElementsByTagName("script")[0];
  var script = document.createElement("script");
  node.parentNode.insertBefore(script, node);
  script.src = "http://search.twitter.com/search.json?q=from:dalmaer&callback=searchTwitterCallback";
}

When the Twitter server responds, it will pass a JSON object to our callback, which we can use to pluck data out of:

function searchTwitterCallback(response) {
  //do something
}

Meanwhile, let’s design the Twitter widget interface. We’ll want to display all the crucial information such as the sender’s name, their avatar, as well as the tweet message, and the date.

There will be several tweets so it will need to be in a list view. We could display it in a table with a column for each field, but that is too old-fashioned. We’ll display the avatar and username on the left, and the message on the right with the date underneath, in a smaller size.

We’ll start with a two column table. Let’s go ahead and add this to our web page where we want the Twitter box to be located:

<table id="twitter_box">
  <tr>
    <td>
      <img border="0" /><div class="name"></div>
    </td>
    <td>
      <div class="txt"></div>
      <div class="date"></div>
    </td>
  </tr>
<table>

This is a template for one tweet. We will need to repeat this template for each tweet from Twitter.

Now let’s fill in that table with data from Twitter, which is stored in the JSON object mentioned earlier. To use Distal, we need to map the properties in the JSON object with the individual nodes in the HTML.

Let’s go back to the HTML and mark what data goes where. First, we’ll mark the table row, which needs to be repeated for how many tweets we have. We’ll use the data-qrepeat attribute to tell Distal which row needs to be repeated:

<table id="twitter_box">
  <tr data-qrepeat="twt results">
    (truncated)
  </tr>
</table>

Here we’re telling Distal to repeat the row element based on the array called “results” found in the JSON object. And for each item in that array, it will be represented by the variable “twt” (for tweet).

Next, we tell Distal where to put the tweet message, date, and username. We’ll use the data-qtext attribute and the name of the properties (“from_user”, “text”, and “created_at”) on the JSON object inside the “results” array:

<table id="twitter_box">
  <tr data-qrepeat="twt results">
    <td>
      <img border="0" /><div class="name" data-qtext="twt.from_user"></div>
    </td>
    <td>
      <div class="txt" data-qtext="twt.text"></div>
      <div class="date" data-qtext="twt.created_at"></div>
    </td>
  </tr>
</table>

When Distal runs, it will place the values of those properties inside the HTML node.

Next, we tell Distal to set the image source attribute to the avatar URL represented by the JSON object’s property name “profile_image_url”. We use the data-qattr attribute to do this:

<td>
  <img border="0" data-qattr="src twt.profile_image_url" />
</td>

Notice we need to supply two arguments. The first is the attribute name to be modified, the second is where the data can be found.

Now we need to hook up our Twitter callback function to Distal. We do this by defining our callback function that Twitter calls and, inside the callback function, we pass the JSON data to Distal.

To call Distal, we need to supply two arguments. The first is the node where our data is to be placed, the second is the twitter data:

function searchTwitterCallback(response) {
  var node = document.getElementById("twitter_box");
  distal(node, response);
}

We now have a function to call Twitter, a callback function for Twitter to call, and we are pushing the data to the HTML template. We now need a way to call the Twitter function when the web page loads. Near the bottom of your web page, but before the ending body tag, add this code:

<script>searchTwitter();</script>

Now load up the web page in the browser and see what it looks like.

It works fine, but the appearance is a little bland as we have not spruced it up with CSS yet. We can leave that as an exercise for later, but meanwhile I’ll throw in a little CSS style to save my eyes.

<style type="text/css">
  #twitter_box {font: normal 10pt Arial; text-align: center}
  #twitter_box td {vertical-align: top; padding: 0.4em 0.4em 0.2em 0.4em;   background: #eee}
  #twitter_box .name {font-size: 8pt}
  #twitter_box .txt {text-align: left; font-style: italic}
  #twitter_box .date {text-align: left; font-size: 8pt; color: #999}
</style>

The date field also looks rather long and wordy. Let’s shorten it by keeping the date and removing the time. We’ll change the callback function and loop through the JSON object, and change the date property to be shorter.

function searchTwitterCallback(response) {
  var list = response.results;
  for(var i = 0; i < list.length; i++) {
    list[i].created_at = new Date(list[i].created_at).toLocaleDateString();
  }
  var node = document.getElementById("twitter_box");
  distal(node, response);
}

Now, load up the web page in the browser again and see what it looks like.

We now have a nifty Twitter widget that we made in only a few lines of code.

More information on DISTAL and Template Attribute Language:

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://www.joezimjs.com Joe Zim, The JavaScript Blogger

    Personally, I thought the pre-CSS-styled table looked better. Just shrink the text a little and add some padding/margins and it’s a nice minimal style. The gray background and the hugely extra space in the content cells make it look amateurish. Anyway, I thought the rest of the article was interesting though. It’s essentially just an alternative to JavaScript Templating.

  • http://www.thomasvanhoutte.be Thomas Vanhoutte

    Nice tutorial, step by step well explained.

    But you mention “from_user_id”: 123456789
    Where could one find that user id; is it the twitter user account’s id?

  • http://www.spilledink.com jackson

    I would love to know how to do this with PHP :D

    • Alex

      The Twitter API is very easy to use. If you want to access it via PHP, just use CURL and process the JSON or XML results on the server side for display.