Skip to content

Instantly share code, notes, and snippets.

@ryanmcgrath
Created November 3, 2010 03:04
Show Gist options
  • Save ryanmcgrath/660757 to your computer and use it in GitHub Desktop.
Save ryanmcgrath/660757 to your computer and use it in GitHub Desktop.
An example Twitter widget thing to answer a Quora thread.
/* TweetScraper - example Twitter feed JS parser written for
http://www.quora.com/Whats-the-best-twitter-plugin-to-create-a-simple-tweet-feed-in-Wordpress
by Ryan McGrath (ryan@venodesigns.net) out of boredom. Enjoy. ;P
*/
/* TweetScraper options:
slot: node reference or string (#id) of node, optional, injection point (default: document.body)
username: string, required, username of feed to pull down (must be public)
count: string, optional, amount of initial tweets to pull down (default: 8)
Usage:
var b = new TweetScraper({
slot: "",
username: "",
count: ""
}).install();
Note: .install() can be delayed until after document.ready-esque scenarios.
*/
var TweetScraper = function(opts) {
/* Used for calling Twitter, durh. */
this.apiURL = "http://twitter.com/statuses/user_timeline/" +
opts.username + ".json?count=" + (opts.count ? opts.count : "8") + "&page=1";
/* Store this for now, but don't care at the moment - if it's a string reference,
we'll grab it later and give the DOM/etc more time to stabilize.
*/
this.slot = opts.slot ? opts.slot : document.body;
};
/* Util functions are kind of different than the other things - consider them private,
in a way. Keep it namespaced but don't have this junk wind up on every new TweetScraper object.
*/
TweetScraper.util = {
bindFn: function(bindReference, fn) {
return function() {
console.log(bindReference);
return fn.apply(bindReference, arguments);
};
}
};
TweetScraper.prototype = {
/* Regex to catch links */
linkCatch: /((((ht|f){1}(tp:[/][/]){1})|((www.){1}))[-a-zA-Z0-9@:%_\+.~#?&//=]+)/gm,
/* Regex to catch usernames... (hint: hashtags?) */
usernameCatch: /@(\w+)/gm,
/* Make URLs and username references into... well, URLs. Set them to
open in a new window while we're at it.
Exercise for the reader: modify this to also handle hash-tags. ;)
*/
convertUrls: function(text) {
text = text.replace(this.linkCatch, function(t) {
return '<a href="' + t + '" title="' + t + '" target="_blank">' + t + '</a>';
});
return text.replace(this.usernameCatch, '<a href="http://twitter.com/$1" title="External Link" target="_blank">@$1</a>');
},
/* Handles checking Twitter for a stream to parse and display.
Note that this relies on the options for TweetScraper to be
all properly passed in.
Note that we need a globally-reachable function for our Twitter callback,
so we set some global properties here, then clean them up as soon as we're
done parsing through things (keep it clean and all).
*/
install: function() {
/* We'll need to call this when the request is done...
Note that we want it bound to execute in the scope of our TweetScraper object,
not the window which it's set on.
*/
window.TweetScraperJSONPCallback = TweetScraper.util.bindFn(this, this.parseResults);
/* JSON-P, smack cross domain restrictions in the FACE */
this.newScript = document.createElement("script");
this.newScript.type = "text/javascript";
/* This entire method relies on there being a document.ready()-esque
scenario in place, because you're appending to the DOM. Because of this,
async being set to true isn't the worst thing in the world. YMMV.
*/
this.newScript.setAttribute("async", "true");
this.newScript.setAttribute("src", this.apiURL + "&callback=TweetScraperJSONPCallback");
/* Ordinarily, we'd wanna implement some kind of timer for the onload/etc event here
to handle cleanup, but instead of going through all that, we'll just handle the cleanup
at the end of the updateUI phase.
*/
document.documentElement.firstChild.appendChild(this.newScript);
},
/* Pretty self explanatory.
Keep in mind that if you wanted to update this all to do some kind
of long-polling/live-updating, you'd wanna annotate each element with
the id of its respective Tweet, so you can check against your returned
results in the future and know what's new.
*/
parseResults: function(tweets) {
/* If we got a string ID, trade it for the real node (no taksies-backsies) */
if(typeof this.slot === "string") this.slot = document.getElementById(this.slot);
/* We'll inject a list, customize this as you wish. */
var structure = "<ul>";
/* Build that junks up... */
for(var i = 0; i < tweets.length; i++) {
structure += '<li>' + this.convertUrls(tweets[i].text) + '</li>';
}
/* ...close it. */
structure += "</ul>";
/* Append it and clean up. */
this.slot.innerHTML += structure;
this.cleanUp();
},
cleanUp: function() {
try {
/* Eh why the hizell not. */
delete window.TweetScraperJSONPCallback;
} catch(e) {
/* Let it get (hopefully) collected in the future. */
window.TweetScraperJSONPCallback = null;
}
/* Walks a bit more than we may want to, but this is an example for a Quora post. Hush. ;) */
this.newScript && document.documentElement.firstChild.removeChild(this.newScript);
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment