Adding Twitter Tweets to Your Web Page

June 1st, 2009 by Gage Pacifera

Note: This post is one of a series of posts that breaks out the individual topics of my presentation “Pimp My Web Page” given at WebVisions 2009. You can see the fully pimped page that includes the code detailed below at http://pimpedblog.harmonicnw.com. Code tested for XHTML 1.0 Strict pages on IE 6 and 7 for PC, Firefox 3 for PC/Mac, Safari 4 public beta for mac.

Adding Twitter tweets your web page is pretty easy. Basically it involves a JavaScript call to Twitter’s public API and then using a JavaScript function to parse out a JSON object and write HTML to your page. You can copy the code below and paste it into your page just above the </body>:

<!-- twitter -->
<script type="text/javascript">
// <![CDATA[
	function showTweets(data) {
		/** USER SETTINGS ***********/
		var targetId = "tweets";								// Id of element where twitters will be inserted
		var showUsername = true;							// Set to true to show username
		var showTime = true;									// Set to true to show time
		var showFollowMe = true;								// Set to true to show "follow me on Twitter" link
		/*****************************/

		var tweets = data;
		var targetObj = document.getElementById(targetId);

		// check to see if Twitter is down [not yet successfully tested]
		if (tweets['error']) {
			var errTxtNd = tweets['error'];
			var newP = document.createElement('p');
			newP.appendChild(errTxtNd);
			newP.className = "twitterError";
			targetObj.appendChild(newP);
			return;
		}

		var newUl = document.createElement('ul');
		newUl.className = "tweetList";

		for (var i=0; i<tweets.length; i++) {
			var username = tweets[i]['user']['screen_name'];
			var tweetId = tweets[i]['id'];
			var userUrl = "http://www.twitter.com/" + username + "/";
			var tweetUrl = "http://www.twitter.com/" + username + "/status/" + tweetId;

			var text = tweets[i]['text'];

			// parse text - add links to URLs and @usernames
			var arr = [];

			// find URLs, put in array to replace later
			var urlRgx = /\b(http|ftp|www)\S+\b/gi;
			while ((urlArray = urlRgx.exec(text)) != null) {
				var url = urlArray[0];
				var urlLink = url;

				var wwwRgx = /^www/gi;
				if (wwwRgx.test(urlLink)) {
					urlLink = "http://" + url;
				}
				var replacement = '<a href="'+urlLink+'">'+url+'</a>';

				var obj = new Object();
				obj.find = urlArray[0];
				obj.repl = replacement;
				arr.push(obj);
			}

			// find @ usernames, put in array to replace later
			var unRgx = /(^|\s)(@\S+)\b/gi;
			while ((unArray = unRgx.exec(text)) != null) {
				var atUsr = unArray[2];
				var usr = unArray[2].slice(1);
				var urlLink = "http://www.twitter.com/" + usr + "/";
				var replacement =  '<a href="'+urlLink+'" title="'+usr+' on Twitter">'+atUsr+'</a>';
				var obj = new Object();
				obj.find = atUsr;
				obj.repl = replacement;
				arr.push(obj);
			}

			// do the replacing
			for (var j=0; j<arr.length; j++) {
				var text = text.replace(arr[j].find, arr[j].repl);
			}

			// parse time - based on code from http://twitter.com/javascripts/blogger.js
			var time = "";
			var createdAt = tweets[i]['created_at'];
			var B=createdAt.split(" ");
			var C=B[1]+" "+B[2]+", "+B[5]+" "+B[3];
			var A=Date.parse(C);
			var D=(arguments.length>1)?arguments[1]:new Date();
			var E=parseInt((D.getTime()-A)/1000);
			E=E+(D.getTimezoneOffset()*60);
			if (E<60) {
				time = "less than a minute ago";
			} else if (E<120) {
				time = "about a minute ago";
			} else if (E<(60*60)) {
				time = (parseInt(E/60)).toString() + " minutes ago";
			} else if (E<(120*60)) {
				time = "about an hour ago";
			} else if (E<(24*60*60)) {
				time = "about " + (parseInt(E/3600)).toString() + " hours ago";
			} else if (E<(48*60*60)) {
				time = "1 day ago";
			} else {
				time = (parseInt(E/86400)).toString() +" days ago";
			}

			var newLi = document.createElement('li');

			if (showUsername) {
				var newStrong = document.createElement('strong');
				var newTxtNd = document.createTextNode(username + " ");
				newStrong.appendChild(newTxtNd);
				newLi.appendChild(newStrong);
			}

			var newSpan = document.createElement('span');
			//var newTxtNd2 = document.createTextNode(text + " ");
			//newSpan.appendChild(newTxtNd2);
			newLi.appendChild(newSpan);
			newSpan.innerHTML = text + " ";

			if (showTime) {
				var newSmall = document.createElement('small');
				var newA = document.createElement('a');
				newA.href = tweetUrl;
				newA.title = username + " Twitter status " + tweetId;
				var newTxtNd3 = document.createTextNode(time);
				newA.appendChild(newTxtNd3);
				newSmall.appendChild(newA);
				newLi.appendChild(newSmall);
			}

			newUl.appendChild(newLi);
		}

		targetObj.appendChild(newUl);

		if (showFollowMe) {
			var newA2 = document.createElement('a');
			newA2.className = "twitterLink";
			newA2.title = "follow " + username + " on Twitter";
			newA2.href = userUrl;

			var newTxtNd4 = document.createTextNode("follow me on Twitter");
			newA2.appendChild(newTxtNd4);

			targetObj.appendChild(newA2);
		}
	}
// ]]>
</script>
<script type="text/javascript" src="http://twitter.com/statuses/user_timeline/THE_REAL_SHAQ.json?callback=showTweets&amp;count=3"></script>
<!-- end twitter -->

In that second JavaScript block, replace THE_REAL_SHAQ with the Twitter user of your choice and adjust the number of Tweets to display where you see count=3. Then add this <div> to your page where you want your tweets to appear:

<div id="tweets"></div>

Background

This script makes use of the Twitter statuses/user_timeline API method. This method is easy and doesn’t require authentication (thus you can access anybody’s timeline, not just yours!) This script uses JSON format, but the API also accommodates XML, RSS and Atom.

How it Works

That second block of JavaScript makes a request to the Twitter API and passes a few key parameters: Twitter user id and number of statuses. In return, the Twitter API passes back a JSON object (basically just a JavaScript object) that contains a bunch of information that we’ll use. The function in the first block of Javascript code, showTweets(), sifts through the object to find the bits of information we need and then writes them to the tweets div. Note that the showTweets() function was designated in the API request in the second block of JavaScript. Also note that the designated function must be declared before the API call.

I might also mention that I hand coded the showTweets() function.. you can find other parsers out there or write your own if this one isn’t quite what you’re looking for.

showTweets() Variables

There are some variables you can set in the first few lines of the showTweets() function:

  • targetId (string) – Id of the DOM object where Twitter content will be added
  • showUsername (boolean) – Shows (true) or hides (false) Twitter username in front of each status
  • showTime (boolean) – Shows (true) or hides (false) how long ago status was posted with link to status
  • showFollowMe (boolean) – Shows (true) or hides (false) anchor below the tweets linking to user’s Twitter home

The HTML Output

The HTML written to your page is structured like the example below. Again, this particular structure is a product of my hand-coded showTweets() function.. if you want it to be formatted differently, hack away at that function until you get the structure you like.

<ul class="tweetList">
	<li>
		<strong>THE_REAL_SHAQ</strong>
		<span>Hey brett favre, dnt retire bro, retire when I retire in 4 yrs, and o yea I will sack u , keep playin You are legend</span>
		<small><a href="http://twitter.com/THE_REAL_SHAQ/status/1727888345">8:16 AM May 7th</a></small>
	</li>
</ul>
<a class="twitterLink" title="follow THE_REAL_SHAQ on Twitter" href="http://www.twitter.com/THE_REAL_SHAQ/">follow me on Twitter</a>

This code is fully customizable via CSS. For example, if you wanted to do away with the typical list-style formatting, you might add a rule to your stylesheet like .tweetList li { list-style: none } or if you wanted to change the color of the username you might add something like .tweetList li strong { color: #d00 }.

Side Notes

In the first version of my showTweets() function, I only used totally W3C-compliant DOM insertion methods (creating text nodes and elements, appending children, etc.) Then when I updated the function to make URL and @username links appear as links in the statuses, I ended up using a bit of innerHTML insertion. I prefer to use the former method but it proved to be a bigger challenge than I wanted to take on to properly add the status text with links. I figured it would actually make more sense to write or find a function that executes the proper DOM insertions based on that HTML string.. so instead of having something like

document.getElementById('tweets').innerHTML = '<ul><li>Go to <a href="https://www.harmonicnw.com">Harmonic Northwest</a></li></ul>';

you would have something more like

insertIntoPage(document.getElementById('tweets'),'<ul><li>Go to <a href="https://www.harmonicnw.com">Harmonic Northwest</a></li></ul>');

A function like that, in addition to simplifying my showTweets() function, could be really useful in a whole bunch of situations. Maybe I’ll find a good reason to write that sometime down the road. If you happen to find that somebody else has already written a innerHTML-to-DOM-insertion function, post a comment about it here for some extra bonus karma points.

Further Reading

Posted in HTML, JavaScript, Web Development, WebVisions

Back to blog home