There are 3 previous versions of this script.
// ==UserScript==
// @name Mefi deleted posts
// @namespace http://plutor.org/
// @description Shows deleted posts on the Metafilter front page
// @include http://*.metafilter.com/
// @include http://*.metafilter.com/daily.mefi/*
// @include http://*.metafilter.com/index.cfm?*
// @include http://*.metafilter.com/home/recentposts
// @exclude http://music.metafilter.com/
// @exclude http://music.metafilter.com/*
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js
// ==/UserScript==
//
// DONE 2008-10-??
// * jQuery
// * AJAX to inline FPP text
var debug = 0;
var deletedbar = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAgCAYAAADaDrJgAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A%2FwD%2FoL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9gKEBI1LdBckgEAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAO0lEQVQoz2NkYGBg%2BH%2FmzH8GKGA0MWFEEYApYGLAAhjRVeIGMJXINLXMJKx9YN2JzY5BGJ6MdEsMRAMAp8dakMN66%2FQAAAAASUVORK5CYII%3D';
/*
* mdp_init
*
* Finds the deleted threads on the page.
*/
function mdp_init() {
var i = 0;
var threadlist = new Array();
var threadinfo = new Object();
// First pass, collect all the thread objects and ids
$("div[class=copy] span[class=smallcopy]:has(a[href*=/user/]) a:contains(comment)," +
"div[class=copy] span[class=smallcopy]:has(a[href*=/user/]) a:contains(answer)")
.each( function() {
var url = $(this).attr('href');
mdp_log("Checking " + url);
var matches = url.match(/(http:\/\/([^\.]*\.)?metafilter\.com)?\/(\d+)\//i);
if (matches && matches.length > 1) {
var threadid = parseInt(matches[3]);
mdp_log("Adding " + threadid + " to list of seen threads");
var anon = $(this).parent().html().indexOf("/user/17564");
threadlist.push(threadid);
threadinfo[threadid] = { obj: $(this),
anon: (anon != -1) };
}
} );
// Second pass, find the deleted threads and do the needful
var lastthread = 0;
for (var i=0; i<threadlist.length; ++i) {
var threadid = threadlist[i];
if (!threadinfo[threadid] || threadinfo[threadid].anon) continue;
var thread = threadinfo[threadid].obj;
if ((lastthread > 0) && (threadid < lastthread - 1)) {
var post = thread.parents("div[class=copy]");
for (var j = lastthread - 1; j > threadid; --j) {
if (threadinfo[j]) continue;
mdp_handle_deleted( j, post );
}
}
lastthread = threadid;
}
}
/*
* mdp_handle_deleted
*
* Given a thread id and the sibling to insert before, does the right thing for
* a deleted thread
*/
function mdp_handle_deleted( threadid, nextSibling ) {
mdp_log("Thread " + threadid + " was deleted");
var content = GM_getValue('content_' + document.domain + '_' + threadid);
try {
content = eval(content);
} catch(e) {
mdp_log("Couldn't evaluate: " + e);
content = null;
}
if (content != null) {
mdp_log("Got content from cache: " + content.content.length + " bytes");
nextSibling.before(
'<div class="deletedpost copy" id="deletedpost_' + threadid + '">' +
'</div><br>'
);
mdp_replace(threadid, content);
} else {
mdp_log("Requesting content for: " + threadid);
nextSibling.before(
'<div class="deletedpost copy" id="deletedpost_' + threadid + '">' +
'<span class="smallcopy">' +
'Getting deleted thread: <a href="/' + threadid + '/">' + threadid + '</a>' +
'</span></div><br>'
);
$("#deletedpost_" + threadid + " span[class=smallcopy]").css('color', '#f99');
mdp_getcontent(threadid);
}
}
/*
* mdp_getcontent
*
* Given a thread id, fires request for the thread, gets the post content,
* deletion reason, and the reason's background color from the response.
* Caches the data and calls mdp_replace.
*/
function mdp_getcontent(threadid) {
$.get('/' + threadid + '/', {}, function(data, textStatus) {
mdp_log("Got data for " + threadid + ": " + data.length + " bytes");
// XXX - I want to use jQuery for this, but it doesn't seem to be
// totally comfortable parsing whole AJAX-ed HTML
var matches;
// Get the reason
var reason = "";
matches = data.match(/<p class="reason"[^>]*>(.*?)<\/p>/);
if (matches && matches.length == 2) reason = matches[1];
mdp_log("Got reason text: '" + reason + "'");
// Get the post content
var post = "";
matches = data.match(/<div class="copy"[^>]*>([\s\S]*?)<\/?(div|span)/);
if (matches && matches.length == 3) {
post = matches[1];
if (matches[2] == 'div') // There was more inside
post += '<span class="smallcopy">'
+ '[<a href="/' + threadid + '/">more inside</a>]'
+ '</span><br>';
}
mdp_log("Got post text: '" + post + "'");
// Get the footer
var foot = ""
matches = data.match(/<div class="copy"[^>]*>([\s\S]*?)<span class="smallcopy"[^>]*>([\s\S]*?)<\/span>/);
if (matches && matches.length == 3) foot = matches[2];
mdp_log("Got foot text: '" + foot + "'");
// Get the stamp
var stamp = ""
matches = data.match(/<span class="smallcopy"[^>]*>\S* \d*, \d* (\d*:\d* [AP]M)/);
if (matches && matches.length == 2) stamp = matches[1];
mdp_log("Got stamp: '" + stamp + "'");
// Cache it
var content = {
'content': post,
'foot': foot,
'url': '/' + threadid + '/',
'stamp': stamp,
'reason': reason,
};
GM_setValue('content_' + document.domain + '_' + threadid, content.toSource());
// Show it
mdp_replace(threadid, content);
}, "html");
}
/*
* mdp_replace
*
* Given a thread id and a content hash, replaces the content of the deleted
* post empty div with the "right" stuff.
*/
function mdp_replace(threadid, content) {
// Make the footer look a little more like the normal page
if (content.foot.match(/ \((\d* comments?) total\)/)) {
content.foot = content.foot.replace(
/ \(\d* comments? total\)[\s\S]*/,
' at ' + content.stamp + ' - ' +
'<a href="' + content.url + '">' +
RegExp.$1 + '</a>'
);
}
// Build the post and insert it into the dom
var postcontent = '<div class="deletedpost_show">' + content.content
+ '<span class="smallcopy">' + content.foot + '</span>'
+ '<br><br>'
+ '<span class="smallcopy">' + content.reason + '</span></div>'
+ '<div class="deletedpost_hide">Deleted thread: <a href="' + content.url + '">' + threadid + '</a></div>';
$("#deletedpost_" + threadid)
.empty().append(postcontent)
.css( {
background: 'transparent url(' + deletedbar + ') repeat-y left',
color: '#f99',
padding: '0.5em 0.5em 0.5em 1em'
} )
.find("span[class=smallcopy]").css('color', '#f99');
// Add the hide button
$("#deletedpost_" + threadid)
.append('<div class="smallcopy hidebutton">Hide</div>')
.hover(
function() {
var t = $(this);
var b = $(this).children('.hidebutton');
var hidey = t.offset().top - 5;
var hidex = t.offset().left - b.width() - 9;
b.show().css({
'left': hidex + 'px',
'top': hidey + 'px',
'height': (t.height() - 10) + 'px'
});
},
function() {
$(this).children('.hidebutton').hide();
}
)
.children('.hidebutton')
.css({
'color': '#ccc',
'position': 'absolute',
'font-size': '80%',
'padding': '5px',
'cursor': 'pointer'
})
.hide()
.click( function() {
$(".deletedpost").each( function() {
$(this).children('.deletedpost_show').toggle();
$(this).children('.deletedpost_hide').toggle();
if ($(this).children('.hidebutton').html() == "Hide") {
$(this).children('.hidebutton').hide().html("Show");
GM_setValue("hideall", 1);
} else {
$(this).children('.hidebutton').hide().html("Hide");
GM_setValue("hideall", 0);
}
} );
});
// Show or hide?
var hide = GM_getValue("hideall");
if (hide) {
$("#deletedpost_" + threadid + ' .deletedpost_show').hide();
$("#deletedpost_" + threadid + ' .hidebutton').html("Show");
} else {
$("#deletedpost_" + threadid + ' .deletedpost_hide').hide();
}
}
function mdp_log(t) {
if (debug)
GM_log(t);
}
mdp_init();
