Displaying the last Twitter Tweet in your webpage
I was just looking for an easy way to integrate the last tweet/current status of a Twitter user in a web page without any heavy plugins, widgets, or embedded tweets.
I was rather surprised how difficult it proved finding a simple example online.
It could, of course, be my laziness in navigating Twitter’s developer API, but Twitter clearly has updated their API over the years, and there’s a lot of deprecated examples out there.From the looks of it, Twitter API now utilizes ids with each tweet, which makes sense. If you’re wondering where you can find the id of a tweet, it can easily be found in the source code of a feed page.

The tweet id is stored as an HTML5 -data attribute in any twitter.com feed page
To add the last tweet, let’s start with some simple HTML:
<p>@mandalatv's last tweet: <a id="status" href="#"></a></p> <ul> <li><a id="favorite" href="#">Favorite</a></li> <li><a id="reply" href="#">Reply</a></li> <li><a id="retweet" href="#">Retweet</a></li> </ul>
You can call Twitter’s API from your own page by including the following script call (replacing out my Twitter username, of course):
<script src="http://twitter.com/statuses/user_timeline/mandalatv.json?callback=getLastTweet&count=1"></script>
You’ll notice I’ve tacked on a callback argument in the query. This defines the JavaScript function I want to handle Twitter’s API response. Here’s the callback’s definition:
function getLastTweet(tweets) {
lastTweet = tweets[0];
var status = document.getElementById('status');
status.innerHTML = lastTweet.text;
status.href = 'http://twitter.com/mandalatv/status/' + lastTweet.id;
var retweet = document.getElementById('retweet');
retweet.href = 'http://twitter.com/intent/retweet?tweet_id=' + lastTweet.id;
var reply = document.getElementById('reply');
reply.href = 'http://twitter.com/intent/tweet?in_reply_to=' + lastTweet.id;
var favorite = document.getElementById('favorite');
favorite.href= 'https://twitter.com/intent/favorite?tweet_id=' + lastTweet.id;
}
Basically, this callback gets the last tweet object in the array (tweets[0]) and inserts its text property into <a id=”status” href=”#”></a>. The object also has an id, which we use to create and assign links to the retweet, reply, and favorite links.
Note that I include these scripts after the HTML code. If they’re included beforehand, the JavaScript won’t know what HTML you’re referring to since it’ll load before the HTML (this, of course, could be handled with an event listener that listens for the page to complete loading).
Lastly, here’s a separate page with a simple last tweet example.
I hope this helps someone save some time!
The Rockville Bridge
I’ve probably seen hundreds of pictures of the Rockville Bridge thanks to Beyond Second, but I’d never actually shot it myself until last week.
I took some of my photography students down to Fort Hunter last Saturday as a field trip, and finally fired off a few shots. What was particularly cool was we ran into this rather unkempt, yet extremely friendly young man carrying a tripod and a video camera. I soon discovered he was a train enthusiast who’d come to shoot the train going over the bridge (apparently, he thought we were enthusiasts as well). I still haven’t found his work on YouTube, but I’m sure it’s up there amidst the sea of other videos.
Firefox Bug with context.scale() in HTML5 Canvas
While testing my last blog post, I discovered that my canvas exercise didn’t work in Firefox 10.0.2 Mac. There were no console errors, and the script worked fine in Safari and Chrome.
What I discovered was a really remote bug in Firefox regarding canvas and scaling. After a bunch of troubleshooting, I determined that scaling the context to 0 prevented the animation from drawing.
My workaround is simply to catch the size and reset it to a really low number, like 0.01.
ctx.save();
ctx.translate(this.x, this.y);
var size = (Math.round(_count*100)/100);
// Workaround for Firefox bug
if(size <= 0){
size = 0.01;
}
I immediately did a search after making the correction and came across this bug documentation on Mozilla’s site. I hope they fix it.
Flying X: Experimenting with OOP JavaScript
Several years ago I completed a Flash-based screensaver for an X-Games website (here’s the SWF example). I wanted to see how difficult it would be to recreate such an animation using HTML5 Canvas.
I started by creating a shape in Adobe Illustrator and using the excellent Ai->Canvas plugin. I then restructured the code as an object (Lee Brimlow has a great intro tutorial on OOP Javascript).
Now, one of the limitations with OOP Javascript versus ActionScript 3.0 is that JavaScript objects don’t inherit an addEventListener() method like Flash Objects do. I was tempted to write this from scratch, but fortunately came across this MIT-licensed JavaScript class that can manage custom events.
By basing my shape’s prototype off of this EventTarget class, I can dispatch and listen to events similar to how I would in Flash. Each X shape initializes with a maximum size, then, once it reaches that size, it dispatches an event, which in-turn triggers a reset() method that assigns a new max, along with a new random x and y position.
The last step I wanted to take was to use window.requestAnimationFrame() instead of setInterval() since it’s supposed to yield better performance. I ended up abandoning this, though, since it’s still in the experimental phase and doesn’t offer as much browser support.
UPDATE: I discovered a Firefox-specific bug related to scaling a canvas’s context to 0. I updated the code, and here’s my documentation.
Perlin Noise in HTML5 Canvas
I was experimenting with Perlin Noise for an underwater effect on a website. I posted the results here, since there doesn’t seem to be an example online of what I wanted.
Not surprisingly, I canned the idea, as it’s simply too processor-intensive for aesthetics. It made for an interesting exercise in canvas, though.
Coming from an ActionScript background, I really wish I better knew how the “offset” array was implemented in the ActionScript call, as it’s not a part of Perlin’s original class:
perlinNoise(baseX:Number, baseY:Number, numOctaves:uint, randomSeed:int, stitch:Boolean, fractalNoise:Boolean, channelOptions:uint = 7, grayScale:Boolean = false, offsets:Array = null):void Generates a Perlin noise image.
Fortunately, I didn’t have to port the original code to JavaScript, as I found it on GitHub. In the ActionScript world, I’d increment the offset over time to create an organic-looking water effect. For HTML5 canvas, I found this could be replicated by incrementing the z argument (zOff) in “classical” noise:
var result = perlin.noise(xVal, yVal, zOff);
Brownian Motion in HTML5 Canvas
Ya know, cause I couldn’t find it anywhere (Lovingly stolen from Processing documentation). View the example.
I’m hoping to convert Craig Reynolds’ Boids to JavaScript/Canvas at some point in the future, too.
window.addEventListener('load', init, false);
function init(){
var canvas = document.getElementById("canvas");
if (canvas.getContext('2d')){
main(canvas);
} else {
console.log("Canvas tag is not supported");
}
}
function main(canvas){
var canvas = canvas;
var ctx = canvas.getContext("2d");
const CANVAS_WIDTH = canvas.width;
const CANVAS_HEIGHT = canvas.height;
var num = 10;
var range = 200;
var ax = [];
var ay = [];
for(var i = 0; i < num; i++) {
ax[i] = CANVAS_WIDTH/2;
ay[i] = CANVAS_HEIGHT/2;
}
setInterval(draw, 30);
function draw(){
// Shift all elements 1 place to the left
for(var i = 1; i < num; i++) {
ax[i-1] = ax[i];
ay[i-1] = ay[i];
}
// Put a new value at the end of the array
var r2x = range*2;
ax[num-1] += (Math.random()*r2x)-range;
ay[num-1] += (Math.random()*r2x)-range;
// Constrain all povars to the screen
ax[num-1] = constrain(ax[num-1], 0, CANVAS_WIDTH);
ay[num-1] = constrain(ay[num-1], 0, CANVAS_HEIGHT);
// Draw a line connecting the povars
for(var i = 1; i < num; i++) {
var alpha = i/num;
ctx.globalAlpha = i/num;
ctx.moveTo(ax[i-1], ay[i-1]);
ctx.lineTo(ax[i], ay[i]);
ctx.stroke();
}
}
function constrain(val, min, max){
if(val > max){
val = max;
}else if(val < min){
val = min;
}
return val;
}
}
Working with HTML5 Range Input
I felt compelled to post this HTML5 range input example because I couldn’t find code online that didn’t rely on JQuery to output a value (not that I have anything against it, just that it can be overkill for simple things like this).
The code below outputs the value of the range to a nearby <span>. I created a “showOutput” function to make it easier to use with multiple inputs.
window.addEventListener('load', initSlider, false);
/**
* Initializes sliders
*/
function initSlider(){
// get range input
var myRange = document.getElementById("myRange");
myRange.addEventListener('change', function(){showOutput(myRange, "rangeOuput")}, false);
document.getElementById("rangeOuput").innerHTML = rangeOuput.value;
// call range input on window init to display initial value
showOutput(myRange, "rangeOuput");
/**
* Displays output to text fields.
* @param slider id of range input
* @param field id of span to write value.
*/
function showOutput(slider, field){
document.getElementById(field).innerHTML = slider.value;
}
}
Revisiting Interactive Media
I recently read a CNN op-ed piece by my former instructor, Doug Rushkoff, on how coding should be taught in every school as a way to be more competitive in the global industry. I couldn’t agree more.
For the past two years I’ve taught an Interactive Media course at Harrisburg Area Community College that has traditionally been taught in Adobe Flash. This semester, I decided to revisit the medium in which to teach interactive media, especially now that web-based Flash is being replaced with web standards technology like HTML, CSS, and JavaScript.
I haven’t completely replaced Flash in the course, as it remains a valuable tool for complex animation, video, and games. I have, however, decided to begin with the fundamentals of programming, and feel that the Flash IDE has too many distractions to serve as the starting medium.
I gave a lot of thought towards Processing, provided it’s easy-to-approach IDE, its large community, and its excellent documentation. In the end, though, I decided on HTML5 Canvas, as my students will likely end up using javascript instead of Java.
To a more selfish end, it’s forced me to better grasp canvas and JavaScript. I purposely chose a medium I wanted to learn, as I’m already comfortable with Flash and doubt I will be revisiting Java.
I’m going to try and start posting more code, such as this for the Fibonacci example:
window.addEventListener('load', init, false);
var canvas;
/**
* Detects for context 2d
*/
function init(){
canvas = document.getElementById("myCanvas");
if (canvas.getContext('2d')){
main(canvas);
initSliders();
} else {
console.log("Canvas not supported");
}
}
/**
* Initializes sliders
*/
function initSliders(){
var radRange = document.getElementById("radRange");
radRange.addEventListener('change', function(){showOutput(radRange, "rangeOuput")}, false);
document.getElementById("rangeOuput").innerHTML = radRange.value;
var distRange = document.getElementById("distRange");
distRange.addEventListener('change', function(){showOutput(distRange, "distOuput")}, false);
document.getElementById("distOuput").innerHTML = distRange.value;
/**
* Displays output to text fields.
* @param slider id of range input
* @param field id of span to write value.
*/
function showOutput(slider, field){
document.getElementById(field).innerHTML = slider.value;
}
}
/**
* Main
* @param canvas target canvas
*/
function main(canvas){
var ctx = canvas.getContext("2d");
var max = 200; // number of items on screen
var i = 0; // initialize for counter
const fib = 1/1.618033989; // Fibonacci Sequence
var radius = 0; // initial radius
var lastInputRadius; // remembers previous state to determine if positioning needs changed
var lastInputDistance; // remembers previous state to determine if positioning needs changed
var circles = []; // Create Array to hold items
const CANVAS_RIGHT = canvas.width;
const CANVAS_BOTTOM = canvas.height;
var interval = setInterval(draw, 30);
/**
* Draws pattern to screen
*/
function draw() {
var inputRadius = document.getElementById("rangeOuput").innerHTML;
var inputDistance = document.getElementById("distOuput").innerHTML;
if(i < max){
// create shape
radius += inputRadius*fib;
lastInputRadius = inputRadius;
lastInputDistance = inputDistance;
var dist = i*inputDistance; //represents distance from object
var x = Math.cos(radius*Math.PI/180)*dist + CANVAS_RIGHT/2;
var y = Math.sin(radius*Math.PI/180)*dist + CANVAS_BOTTOM/2;
var hex = rgbToHex(255-i,0,i);
circles[i] = new Circle(ctx, x, y, (i/max)*100, hex);
i++;
}else{
// if input has changed, reposition shape
if(lastInputRadius != inputRadius || lastInputDistance != inputDistance){
radius += inputRadius*fib;
clear();
for(var j = 0; j < max; j++){
radius += inputRadius*fib;
var dist = j*inputDistance; //represents distance from object
var x = Math.cos(radius*Math.PI/180)*dist + CANVAS_RIGHT/2;
var y = Math.sin(radius*Math.PI/180)*dist + CANVAS_BOTTOM/2;
var hex = rgbToHex(255-j,0,j);
circles[j].render(x, y, (j/max)*100, hex);
}
}
}
lastInputRadius = inputRadius;
lastInputDistance = inputDistance;
}
/**
* Draws circle.
*/
function Circle(ctx, x, y, r, hex){
this.ctx = ctx;
this.centerX = x;
this.centerY = y;
this.radius = r;
this.render = function render(x, y, r, hex){
this.centerX = x;
this.centerY = y;
this.radius = r;
this.ctx.beginPath();
this.ctx.arc(this.centerX, this.centerY, this.radius, 0, 2*Math.PI, false);
this.ctx.fillStyle = hex;
this.ctx.fill();
this.ctx.lineWidth = 2;
this.ctx.strokeStyle = "black";
this.ctx.stroke();
}
this.render(this.centerX, this.centerY, this.radius, hex);
}
/**
* Converts RGB values to hexidecimal
* @param r 0-255 red value
* @param g 0-255 green value
* @param b 0-255 blue value
*/
function rgbToHex(r, g, b) {
/**
* Converts numeric value to base-16
* @param c target value
*/
function componentToHex(c) {
var hex = c.toString(16);
return hex.length == 1 ? "0" + hex : hex;
}
return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}
/**
* Clears the canvas
*/
function clear(){
ctx.clearRect(0, 0, CANVAS_RIGHT, CANVAS_BOTTOM);
}
}
It’s been difficult not having a definitive API documentation like ActionScript and Processing have. The best I’ve found so far has been HTML5 Canvas Tutorials accompanied by a lot of O’Reilly JavaScript books. Coming from an ActionScript background, I’m still wrapping my head on how every function is an object, and how privatization, and event listening isn’t quite so baked in. I’m know the code above could be optimized more–eliminating globals, calculating x and y-positions once in draw(), etc., but it’s just a sketch.
I haven’t quite figured out how to structure my experiments on this blog, but my goal this year is posting more content, and spending less time examining distractions and vices.
About Me
I'm a designer, developer, and teacher based in Harrisburg, Pa. I run Hauck Interactive, Inc.
Categories
Archives
- May 2012
- April 2012
- March 2012
- January 2012
- December 2011
- October 2011
- August 2011
- July 2011
- June 2011
- May 2011
- March 2011
- February 2011
- December 2010
- November 2010
- October 2010
- September 2010
- August 2010
- July 2010
- June 2010
- May 2010
- April 2010
- March 2010
- February 2010
- January 2010
- December 2009
- November 2009
- October 2009
- September 2009
- August 2009
- July 2009
- June 2009
- May 2009
- April 2009
- March 2009
- February 2009
- January 2009
- December 2008
- November 2008
- October 2008
- September 2008
- August 2008
- July 2008
- June 2008
- May 2008
- April 2008
- March 2008
- February 2008
- January 2008
- December 2007
- November 2007
- October 2007
- September 2007
- August 2007
- July 2007
- June 2007
- May 2007
- April 2007
- March 2007
- February 2007
- January 2007
- December 2006
- November 2006
- October 2006
- September 2006
- August 2006
- July 2006
- June 2006
- May 2006
- April 2006
- March 2006
- February 2006
- January 2006
- December 2005
- November 2005
- October 2005
- September 2005






