5by5 Show link grabber screenshot

I’ve done 30 episodes of Systematic now. Every week I goad my guests into sharing their “Top 3 Picks.” It’s usually software (kind of my thing), but it can be just about anything. After so many episodes I began to realize that I had no way to give guests advance warning as to what had been mentioned recently. I needed a list of every link ever mentioned on the show, all in one searchable page.

I wrote a quick script that creates a Markdown-formatted list of show links for any show page on 5by5. Click and copy. Then, I wrote one that spidered through the show starting from the first episode, just to get me caught up. Not surprisingly, I decided to test it on other people’s shows, too…

The end result is an easy-to-maintain list of every link ever posted for Systematic. After finishing the current list, I thought that at least the single-page scraper would be of interest to somebody out there, as it’s a really easy way to archive the week’s links from your favorite show. Click it and they’re ready to pop into nvALT or Evernote or whatever your bag is1.

They’re pretty simple jQuery bookmarklets. The main one for single page scraping looks like…

5by5showlinks.jsraw
// generates a Markdown list of all the show links on a 5by5 episode page, 
// autoselects the result for copying and provides next/prev navigation
// only designed for 5by5, which already has jQuery loaded and matches 
// the regex. Customize as needed for other uses.
// Brett Terpstra 2013
var output = "\n\n### [Episode "+window.location.href.replace(/.*\/(\d)/,"$1")+"]("+window.location.href+")\n\n";
$('#episode_links').find('a').each(function(){ output += "* ["+$(this).text()+"]("+$(this).attr('href')+")\n" });

// create next/prev links (no boundry checking)
var ep = parseInt(window.location.href.match(/(\d+)$/)[0],10);
var nextLink = $('<a>').attr('href',window.location.href.replace(/\d+$/,ep + 1))
				.text('Next Episode')
				.css({display:'block',padding:'10px',textAlign:'center',backgroundColor:'#ddd','float':'right'});
var prevLink = $('<a>').attr('href',window.location.href.replace(/\d+$/,ep - 1))
				.text('Previous Episode')
				.css({display:'block',padding:'10px',textAlign:'center',backgroundColor:'#ddd','float':'left'});

// generate the overlay element and add text and links
$('<div>').css({
	position:'fixed',
	top: '0',left:'0',right:'0',bottom:'0',
	overflow:'auto',
	backgroundColor:'#efefef',
	color:'#333',
	zIndex:'99999'
}).append($('<pre id="eplinkoutput">').css('padding','20px').text(output)).append($('<div>').append(prevLink).append(nextLink)).appendTo('body');

// select the text in the pre element
var doc = document,
text = doc.getElementById('eplinkoutput'),
range, selection;

if (doc.body.createTextRange) {
    range = doc.body.createTextRange();
    range.moveToElementText(text);
    range.select();
} else if (window.getSelection) {
    selection = window.getSelection();
    range = doc.createRange();
    range.selectNodeContents(text);
    selection.removeAllRanges();
    selection.addRange(range);
}

Note that this uses markup specific to 5by5 show pages and relies on jQuery already being loaded (which it is on 5by5). The script is best used as a bookmarklet, which I happen to have handy. Copy it into the address field of a bookmark in your browser (raw code here), visit a 5by5 show page and click it to run.

javascript:(function(){var%20output%3D%22%5Cn%5Cn%23%23%23%20%5BEpisode%20%22%2Bwindow.location.href.replace(%2F.*%5C%2F(%5Cd)%2F%2C%22%241%22)%2B%22%5D(%22%2Bwindow.location.href%2B%22)%5Cn%5Cn%22%3B%24(%22%23episode_links%22).find(%22a%22).each(function()%7Boutput%2B%3D%22*%20%5B%22%2B%24(this).text()%2B%22%5D(%22%2B%24(this).attr(%22href%22)%2B%22)%5Cn%22%7D)%3Bvar%20ep%3DparseInt(window.location.href.match(%2F(%5Cd%2B)%24%2F)%5B0%5D%2C10)%3Bvar%20nextLink%3D%24(%22%3Ca%3E%22).attr(%22href%22%2Cwindow.location.href.replace(%2F%5Cd%2B%24%2F%2Cep%2B1)).text(%22Next%20Episode%22).css(%7Bdisplay%3A%22block%22%2Cpadding%3A%2210px%22%2CtextAlign%3A%22center%22%2CbackgroundColor%3A%22%23ddd%22%2C%22float%22%3A%22right%22%7D)%3Bvar%20prevLink%3D%24(%22%3Ca%3E%22).attr(%22href%22%2Cwindow.location.href.replace(%2F%5Cd%2B%24%2F%2Cep-1)).text(%22Previous%20Episode%22).css(%7Bdisplay%3A%22block%22%2Cpadding%3A%2210px%22%2CtextAlign%3A%22center%22%2CbackgroundColor%3A%22%23ddd%22%2C%22float%22%3A%22left%22%7D)%3B%24(%22%3Cdiv%3E%22).css(%7Bposition%3A%22fixed%22%2Ctop%3A%220%22%2Cleft%3A%220%22%2Cright%3A%220%22%2Cbottom%3A%220%22%2Coverflow%3A%22auto%22%2CbackgroundColor%3A%22%23efefef%22%2Ccolor%3A%22%23333%22%2CzIndex%3A%2299999%22%7D).append(%24('%3Cpre%20id%3D%22eplinkoutput%22%3E').css(%22padding%22%2C%2220px%22).text(output)).append(%24(%22%3Cdiv%3E%22).append(prevLink).append(nextLink)).appendTo(%22body%22)%3Bvar%20doc%3Ddocument%2Ctext%3Ddoc.getElementById(%22eplinkoutput%22)%2Crange%2Cselection%3Bif(doc.body.createTextRange)%7Brange%3Ddoc.body.createTextRange()%3Brange.moveToElementText(text)%3Brange.select()%7Delse%7Bif(window.getSelection)%7Bselection%3Dwindow.getSelection()%3Brange%3Ddoc.createRange()%3Brange.selectNodeContents(text)%3Bselection.removeAllRanges()%3Bselection.addRange(range)%7D%7D%3B}());

If for some reason you’re interested in the one that spiders an entire show, let me know. It’s not a secret or anything, I just can’t imagine anyone else thinking that would be a good time.

  1. I actually have another one of these that lets you click any element on a page to gather all of the links within that element and send them straight to Pinboard. Another time.