Tuesday, May 15, 2012

jQuery Aligned With TimThumb

I recently had to figure out a way to crop images quickly, so I decided to use timthumb, which worked quickly and easily.  However, there were occasions where an portrait-oriented image was loaded into a landscape-oriented frame, and the center cropping ended up showing a person's midsection instead of an appropriate headshot.  With this in mind, I decided that I had to make a simple overlay that will allow the use to realign the timthumb crop as desired.  While I was at it, it seemed to make sense to also handle jQuery image scrolling/panning as well using the same arrow icons, so I added a conditional to the self-contained HTML.

You can download the code here.  By default, it will utilize jQuery scrolling.  In order to utilize timthumb, you must install the timthumb.php in the same directory and set the proper permissions (or point the html to the appropriate URI) and them pass the querystring ?tt=1 to the http call.  Not sure if anybody will find this useful, just thought I'd drop a quick post about it since I whipped it up.

Thursday, April 26, 2012

Twitter Widget Modifications: Wadget Wudget

It has been a long time since my last post. I had been working on a personal project but a sudden change in circumstance sidetracked me and I have not touch that in about a year now. Hopefully, I can re-familiarize myself with it and, at least, get it to the point where I can post it here for others to fool around with it. I had wanted to post a python XML-to-JSON convertor, but after building my iterative loop, I discovered that Google already had one available here. That one probably works better than what I whipped up.

Now, back to the topic at hand. Unless you've been living under a rock, you're already aware that Twitter has a widget that allows you to post tweets on your own website. The problem that is that it is subject to an hourly rate limit, which most people behind corporate firewalls will easily exceed. Though I've found a few posts that explain how to utilize a RESTful approach to resolve this problem, they have generally approached it by utilizing some custom HTML with jQuery injections.

Originally, I had broken down the DOM elements and were about to follow the HTML approach and recreate the tiny little widget, when I realized that I should just simply alter the widget itself to allow for an alternative location to retrieve its JSONP results. Then have the alternative location be able to call the Twitter API at some minimum interval and cache the output to avoid exceeding the hourly rate limit. After getting that to work, break it down into the steps required to update any future widgets and blog about it after failing to find anybody else who had resolved the problem using this approach.

First, I needed to establish all the Twitter API calls that were being made. Rather than wade through the segmented variables in the reduced javascript, I run through all the scenarios while running ngrep to packet sniff the api.twitter.com calls. This is what I saw:

http://api.twitter.com/1/favorites.json?screen_name=$PROFILE&callback=*
http://api.twitter.com/1/$PROFILE/lists/$LIST_ID/statuses.json?callback=*
http://api.twitter.com/1/statuses/user_timeline.json?screen_name=$PROFILE&callback=*
http://search.twitter.com/search.json?q=$SEARCH&callback=*

Next, I needed to create a script to make those API calls, cache them to disk, and decide whether to attack the Twitter API again or load from file, based on the time interval since the last request. Normally, I write CLI scripts in python, but for a quick-and-dirty web solution, I simply whipped up a PHP script that I stuck on an EC2 instance. You can find a sanitized version of that PHP script here. The comments at the top tell you what variables you need to change to customize it for your needs. Basically, all I did was add a few parameters that I needed to distinguish the different Twitter requests, but let all the original widget querystring parameters simply pass-through.

Now, to break down the modifications to the widget. For the sake of versioning, the current widget that is available and used in this blog is

http://widgets.twimg.com/j/2/widget.js

My first attempt was to replace all the api.twitter.com and search.twitter.com with the PHP script above. Twitter isolated the domain using: var t="twitter.com"; So we will also have to remove all the "api." and "search." calls as well as any paths indicated in the packet sniff above. Instead I replaced the profile/faves with a "wtype" parameter and split the list path into "profile" and "list_id" parameters. I called the result wadget.js. This should work for all four types of twitter web widget types, though you may want to add or remove the restriction for search. To utilize the "wadget", just simply use it as you would normally use the widget.js except that you would replace the first script reference:

<script src="http://widgets.twimg.com/j/2/widget.js"></script>
<script>
new TWTR.Widget({
...
}).render()...start();
</script>
with:

<script src="path-to/wadget.js"></script>

and call the TWTR.Widget exactly the same way after you edit the wadget.js with your own custom:

var t="alternate.domain.com/twtr/widget.php"

Since the search widget is of no interest to me, I decided to make a different widget altercation that would allow me to pass the full script-pathname to the TWTR.Widget and not have to alter the javascript. Instead of replacing the var t="twitter.com"; portion, I left that as is to handle the search call, but I removed all the variable definitions for p, o, and s afterwards (it is mere coincidence that they were arranged in POS order). Then I added the third variable to the setList and setUser functions so that they would invoke the same parameters as the wadget.js script, but now it can be passed into the TWTR.Widget like so:

new TWTR.Widget({
...
}).render().setList('$PROFILE', '$LIST_ID', 'your.domain.com/twtr/widget.php').start();

-OR-

}).render().setUser('$PROFILE', '', 'your.domain.com/twtr/widget.php').start();

Either script should work without a lot of changes to the original Twitter widget-generated code snippet. I named this alternate javascript wudget.js

Hopefully, I did not forget anything of importance. But if I did, feel free to comment and I will either respond or correct the blog entry.