Automatically Expand Facebook “Older Posts” Links

EDIT: Sadly, although not entirely surprisingly, this doesn’t appear to work any more. Facebook is constantly changing the layout and content of their various pages, and I have no real intention to keep up with them. However the code may be useful for someone else to modify at any point in time to work on the current version. Sorry!


This evening I had that not-uncommon need to track down some dusty old Facebook comments from a couple of years ago. Naturally, Facebook makes it difficult to see anything more than a week old, but if you keep clicking “Older Posts” at the bottom of your (or a friend’s) Wall for long enough, you can see all posts back to the beginning of time.

This is kind of nice, but very tedious. Surely there’s a way to automate this process? I’ve seen numerous attempts, but many are either too complex for such a simple task (such as the sprawling Social Fixer browser extension), or too simple for the ever-changing complexities of Facebook. I decided to take a couple of pointers and put my new-found jQuery skills to a quick test. The result: FBExpand, a simple tool for a simple purpose.

The code is up on Bitbucket for inspection, but to put it to work right away it’s much easier to use this bookmarklet: FBExpand. Drag that link to your bookmarks bar, and simply click it when you want to expand some Facebook history (e.g. when viewing your Wall). Too easy!

The code

(function(){
// The text in the link you wish to automatically expand.
var expandText = "Older Posts";
// Timer delay (ms) between 'clicks'. Set to roughly the time it takes to load
// the next link text. May need to increase value for slower connections.
// Too short may freeze the script, however too long will waste time.
var delay = 1500;

These couple of lines allow for some minimal customisability. The script locates the link button based on the text within it, chosen by the expandText variable. This strikes me as more future-proof against Facebook’s endless interface changes than an otherwise more precise approach of drilling down the DOM or picking out element IDs and classes. The delay variable is more or less explained by its comments.

/*
Reduced from Karl Swedberg's jQuerify bookmarklet script at:

http://www.learningjquery.com/2009/04/better-stronger-safer-jquerify-bookmarklet/

*/
// Ensure jQuery is available as $jq

(function(){
if(typeof jQuery!='undefined'){$jq=jQuery; return;}
var head=document.getElementsByTagName('head')[0],done=false;
var script=document.createElement('script');
script.src='http://code.jquery.com/jquery-latest.min.js';
script.onload=script.onreadystatechange=function(){
if(!done&&(!this.readyState||this.readyState in ['loaded','complete'])) {
$jq=jQuery.noConflict();
script.onload=script.onreadystatechange=null;
head.removeChild(script);done=true;
}
};
head.appendChild(script);
})();

This block is simply Karl Swedberg’s jQuerify script reduced to its bare bones (i.e. removing the visual feedback). It ensures that the jQuery library is loaded and bound to the variable $jq before proceeding. Read his post for an explanation; it’s about the third version, and it’s quite neat.

// Keep clicking the links until there's none left
var loop = setInterval(function() {
var a = $jq('a:contains("'+expandText+'")');
if(a.length) eval(a.attr('onclick').split('return')[0]);
else {clearInterval(loop); console.log("All posts expanded.");}
}, delay);
})();

Here’s my stuff – it looks awfully straightforward after all that. Essentially, it follows a few simple steps, outlined below. Since the code is wrapped in a setInterval() function call, it is called again every delay milliseconds. This allows Facebook a little time to load the next batch of posts before performing another click.

  1. Find the expand link based on the text contained within it using a jQuery DOM selection.
  2. If the link exists, grab its onclick code and execute it, effectively emulating a user’s mouse click. For some reason simply calling .click() on the jQuery object wasn’t working, so this was my workaround.
  3. If the link doesn’t exist, there’s nothing to expand, so the script ends, putting a stop to the repetitive interval execution and printing a simple debug message to the browser’s console.

Thoughts

This little exploration has done little to change my perception of JavaScript as a rather hacky approach to software development. Of course, any language can only be as elegant as the task (and developer) allows, and if you’re trying to do hacky things like this, then JS/jQ are fantastic. As far as modern web UI design goes however, I’m still looking forward to spending some quality time learning Dojo in the future. Coupled with Backbone.js, it looks like a very powerful tool for any serious web development.

Naturally, such a tiny script should be very possible without any jQuery-like library. In retrospect, the only thing I use it for is to select the expand link node. Perhaps I’ll rewrite it tomorrow to do that in standard JS and cut the script in half. It’s all good practice, in any case.

Finally, my efforts went somewhat unrewarded, since I didn’t find the exact post I was looking for. I realised too late that it was a comment on an activity (Liking a Facebook page) rather than on a post. Since activities aren’t really shown on one’s Wall the same way any more, neither that Like or its comments could be found. If anyone knows how I might be able to locate something so specific, please let me know! I’ll own you one.

Migrating Windows Mobile to Android

Windows to Android SMS conversionToday was the day I finally broke free from the shackles of Windows Mobile 6.5 on my HTC HD2 (brilliant device, merely decent OS), loading a ROM for Android 2.3 (Gingerbread). I’ll go into details another time, but the only major obstacle for me was transferring SMSes. After much Googling, it was still not obvious how to do it, but I can now confirm it is possible. Here’s how I did it (short version):

  • Back up messages using PIM Backup (freeware)
  • Convert backup file format from CSV to XML (?)
  • Restore XML using SMS Backup & Restore (freeware)

It’s the middle step, the conversion, that is unintuitive. Surely there should be a PIM Backup app for Android? Or an app that imports PIM Backup files? As far as I can tell, there’s not, but this post by the SMS Backup & Restore creator Ritesh Sahu set me on the right track. He created a WinMo app called SMS Exporter, but there were mixed reports of success, so I followed his advice and read through this post by Mario instead.

Mario had written a Perl script to convert the PIM Backup format (semicolon-separated values) to a format compatible with SMS Backup & Restore (XML) such that the converted file could be ‘restored’ on the new Android OS.

Unfortunately I (and other users) couldn’t get his script to work properly, and I don’t know Perl, and he wasn’t replying in the comments, but looking at the code I figured it couldn’t be too hard to recreate in Python. Neither format is terribly complicated after all; each is effectively just a row of attributes for each message.

You can check out and download my Windows Mobile to Android SMS Converter tool from this site. To use it, you just need to have Python 2.x installed (you may have already – type “python” without quotes in your command prompt or terminal), and to perform the conversion, set the working directory to that of the Python script and use the command python pim2smsbr.py backup_file [output_file], where:

  • backup_file refers to the name of your PIM Backup file, something like PIMBackup_20110701.pib (if you created it on the date of this post), and
  • [output_file] is an optional argument that allows you to specify a filename for the output (or you can omit it, and it will output alongside the input file).

The final step is simply copying the output file onto your Android device, opening SMS Backup & Restore, choosing Restore, and selecting the output file (and choosing not to check for duplicates). And then you’re done, congratulations! It should import all the messages rather quickly and they are automatically associated with existing contacts and built into conversation threads.

So that’s it! It’s a ugly, hacky three-step process, but it’s very possible. Enjoy your superior operating system with your data intact :). Let me know of any trouble you have in the comments and I’ll get back to you ASAP.