Created
November 3, 2010 03:04
-
-
Save ryanmcgrath/660757 to your computer and use it in GitHub Desktop.
An example Twitter widget thing to answer a Quora thread.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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