UnFuck Facebook

By sizzlemctwizzle Last update Oct 23, 2009 — Installed 62,980 times. Daily Installs: 209, 200, 178, 216, 213, 199, 195, 215, 214, 186, 172, 159, 185, 139, 178, 160, 604, 969, 923, 755, 713, 573, 552, 436, 391, 434, 383, 297, 341, 270, 335, 292

There are 61 previous versions of this script.

Add Syntax Highlighting (this will take a few seconds, probably freezing your browser while it works)

// ==UserScript==
// @name          UnFuck Facebook
// @namespace     sizzlemctwizzle
// @description	  A quick fix that doesn't freezer your browser! Will release a complete fix soon.
// @version       2.4.7
// @require       http://gmconfig.googlecode.com/svn/trunk/gm_config.js
// @require       http://sizzlemctwizzle.com/gm_config_updater.php?id=11992
// @include       http://*.facebook.com/*
// @include       https://*.facebook.com/*
// ==/UserScript==

// Greasemonkey users can graphically configure the script from the User Scripts Commands submenu

// Safari Settings
// If you use GreaseKit you need to change settings manually
var blockAppReqs = true, // Block Application Requests
    blockFanReqs = true, // Block Fan Requests
    blockGroupReqs = false, // Block Group Requests
    blockEventReqs = false, // Block Event Requests
    hideAppStories = true, // Hide Application Stories
    blockAppStories = true, // Prevent apps from showing up in your stream in the futur
    hideWallStories = true, // Hide the one-sided wall conversations
    hideAppHighlights = true, // Hide Application Highlights
    hideFanHighlights = true, // Hide Fan Highlights
    directShareLinks = true, // Avoid Facebook's "seamless browsing"
    showStatusOnHome = true, // Show your status on the home page
    twoColumnHome = true, // Make the home page two columns
    expandNewsFeed = true, // Auto Expand the News Feed to show more stories
    showNavNameLink = false, // Show your name in the Navigation bar
    showNavHomeLink = false; // Show the Home link in the Navigation bar
// == Don't Modify Below This ==

// Build GM_config replacement
if (typeof GM_config === 'undefined') {
    var GM_config = {
        values: {
            appReq: blockAppReqs,
            fanReq: blockFanReqs,
            groupReq: blockGroupReqs,
            eventReq: blockEventReqs,
            appHide: hideAppStories,
            appBlock: blockAppStories,
            wallStory: hideWallStories,
            appHigh: hideAppHighlights,
            fanHigh: hideFanHighlights,
            dLinks: directShareLinks,
            showStat: showStatusOnHome,
            twoColumn: twoColumnHome,
            expand: expandNewsFeed,
	    nameLink:showNavNameLink,
	    homeLink:showNavHomeLink
        },
        get: function(name) { return this.values[name]; }
    };
} else {
    GM_config.init('UnFuck Facebook', {
        appReq:{
            section:[
                'Invite Blocking',
                'Check the types of invites you want to block automatically'
            ],
            label:'Application',
            type:'checkbox',
            'default':true
        },
        fanReq:{
            label:'Fan Page',
            type:'checkbox',
            'default':true
        },
        groupReq:{
            label:'Group',
            type:'checkbox',
            'default':false
        },
        eventReq:{
            label:'Event',
            type:'checkbox',
            'default':false
        },
        appHide:{
            section:[
                'Stream Options',
                'Control what appears in your stream'
            ],
            label:'Hide App Stories',
            type:'checkbox',
            'default':true
        },
        appBlock:{
            label:'Block App Stories',
            title:'Prevent apps from showing up in your stream in the future',
            type:'checkbox',
            'default':true
        },
        wallStory:{
            label:'Hide Wall Stories',
            title:'Hide the one-sided wall conversations',
            type:'checkbox',
            'default':true
        },
        appHigh:{
            section:[
                'Highlights Section',
                'Control what appears in the highlights section on the homepage'
            ],
            label:'Hide App Highlights',
            type:'checkbox',
            'default':true
        },
        fanHigh:{
            label:'Hide Fan Highlights',
            type:'checkbox',
            'default':true
        },
        dLinks:{
            section:[
                'Extras'
            ],
            label: 'Direct Share Links',
            title: 'Avoid Facebook\'s "seamless browsing"',
            type:'checkbox',
            'default':true
        },
        showStat:{
            label: 'Show status on home page',
            type:'checkbox',
            'default':true
        },
        twoColumn:{
            label: 'Two Column Layout',
            title: 'Make the home page two columns',
            type:'checkbox',
            'default':true
        },
        expand:{
            label: 'Auto Expand News Feed',
            title: 'Show more stories by default',
            type:'checkbox',
            'default':true
	},
	nameLink:{
	    label:'Show your name in the Nav Bar',
	    title: "It's the link that leads to your profile",
	    type:'checkbox',
	    'default':false
	},
	homeLink:{
	    label:'Show Home link in Nav Bar',
	    type:'checkbox',
	    'default':false
	},
        autoCheck:{
            section:[
                'Update Checking',
                AutoUpdater_11992.name+' v'+AutoUpdater_11992.version
            ],
            label:'Auto Checking',
            type:'checkbox',
            'default':true
        },
        checkInt:{
            label:'Days Between Checks',
            type:'float',
            'default':2
        },
        checkNow:{
            label:'Check Now',
            type:'button',
	    title: 'Last Checked ' + new Date(+GM_getValue('updated_11992', 0) - new Date().getTimezoneOffset()*60000).toUTCString(),
	    script:function() { AutoUpdater_11992.call(true) }
        }
    },
    '.config_header { color: #3B5998 !important; } .section_header { background-color: #3B5998 !important; } .section_desc { color: #999999 !important; } .field_label { color: #3E5A88 !important; }',
    {
        save: function() { window.location.reload(); }
    });
  
    GM_registerMenuCommand("UnFuck FB Options", function() {GM_config.open()});
}

// I've mananged to do a lot of my script in CSS
var unfuckStyle='#right_column { width: 77% !important; } div[id^="box_app_"]:not(#box_app_2297529396):not(#box_app_2305272732):not(#box_app_2309869772):not(#box_app_2327158227):not(#box_app_2341989679):not(#box_app_2347471856):not(#box_app_2356318349):not(#box_app_2361831622):not(#box_app_2407511955):not(#box_app_2503140832):not(#box_app_2719290516):not(#box_app_2392950137):not(#box_app_2550392059), .gifts_received, .wall_contextual_extra, .nextstep, .app_icon_row, .invitefriends, #ssponsor, div[class$="_ad"], .divider_bar, .more_section, .fbpage_fan, .ad_capsule, .see_more_arrow, #more_apps_divider_narrow, .platform, .profile_empty_divider, .newstuff, .app_install_story, .emu_sponsor, div[id^="emu_"], .adcolumn, .social_ad, .sponsor, #attachment_buttons_list span[style*="app_"], li[id^="bookmarked_app_"] a[href^="http://apps."], li[id^="bookmarked_app_"] a[href*="gift"], '+(GM_config.get('homeLink') ? '' : '#fb_menu_home, ')+'#profile_tab_add, .footer_ad, .UIComposer_More_Container, .UIComposer_Attachment a[style*="gift.gif"], li[view="box_3"], li[view^="app_"], .approve_friend, .app_story, .UIComposer_Attachment a[style*="/app_"], '+(GM_config.get('nameLink') ? '' : '#fb_menu_account, ')+'.UIRoundedImage_CornersSprite, #home_sponsor, .hp_connect_box, .UIUpcoming_Info small, .house_sponsor, #home_sponsor_nile, div[style*="white"], #pymk_hp_box, #unfucked, .PYMK_Reqs_Sidebar { display: none !important; }\n' + 'li[view="app_2347471856"], li[view="app_2392950137"] { display: block !important; }\n' +
'.request_link { padding: 5px !important; }\n' +
'#wallpage { width: 700px !important; }\n' +
'#wall_text { height: 80px !important; }\n' +
'.request_link { padding-left: 20px !important; }'+(GM_config.get('twoColumn') ? '\n#home_filter_list { display: block !important; float: none !important; width: 100% !important; padding-bottom: 20px !important; }\n#home_stream { width: 650px !important; }' : '');

// GM_addStyle if not available
if (typeof GM_addStyle === 'undefined') GM_addStyle = function(css) {
    var head = document.getElementsByTagName('head')[0], style = document.createElement('style');
    if (!head) {return}
    style.type = 'text/css';
    try {style.innerHTML = css}
    catch(x) {style.innerText = css}
    head.appendChild(style);
};

// Inject a script into the page
function addScript(js) {
    var body = document.body, script = document.createElement('script');
    if (!body) {return}
    script.type = 'text/javascript';
    try {script.innerHTML = js}
    catch(x) {script.innerText = js}
    body.appendChild(script);
}

// Smart XPath Function
function $x(x, t, r) {
    if (t && t.nodeType) 
        var h = r, r = t, t = h;    
    var d = r ? r.ownerDocument || r : r = document, p;
    switch (t) {
    case 1:
        p = 'numberValue';
        break;
    case 2:
        p = 'stringValue';
        break;
    case 3:
        p = 'booleanValue';
        break;
    case 8: case 9:
        p = 'singleNodeValue';
        break;
    default:
        return d.evaluate(x, r, null, t || 6, null);
    }
    return d.evaluate(x, r, null, t, null)[p];
}

// Optional shortcut functions I like
var $x1 = function(x, r) { return $x(x, 9, r) }, 
    $xb = function(x, r) { return $x(x, 3, r) };
    
// A robust and universal forEach
function forEach(lst, cb) {
    if (lst.snapshotItem) {
        var i = 0, len = lst.snapshotLength;
        while (i < len) 
            cb(lst.snapshotItem(i), i++, lst);
    }
    else if (lst.iterateNext) {
        var item;
        while (item = lst.iterateNext()) 
            cb(item, lst);
    }
    else if (lst.forEach) 
        lst.forEach(cb);
    else if (lst.length && typeof lst === 'object') 
        Array.forEach(lst, cb);
    else if (typeof lst === 'object')
        for (var i in lst) cb(lst[i], i, lst);
    else 
        return false;
}

// Insert an element after another
function insertAfter(node, after) { after.parentNode.insertBefore(node, after.nextSibling);}

// A really cool element creation funtion by avg and given to JoeSimmons who then gave to me
function create(a,b) {
  var ret=document.createElement(a);
  if(b) for(var prop in b) {
      if(/^on/.test(prop)) ret.addEventListener(prop.substring(2),b[prop],false);
      else if(prop=="kids") {
	append(ret, b[prop]);	
      }
      else if(prop=="style") ret.setAttribute("style", b[prop]);
      else ret[prop]=b[prop];
    }
  return ret;
}

// I tore out the append part of create() so I could use it elsewhere
function append(a,b) { for(var i=0,len=b.length;i<len;i++) a.appendChild(b[i]); }

// Remove an element
function destroy(element) { element.parentNode.removeChild(element); }
// Get element by id
function $(element) { return document.getElementById(element); }
// Get elements by class. I know... long xpath for something so simple
function $c(element, root) {
if (!root) root = document;
if (root.getElementsByClassName) 
  return root.getElementsByClassName(element)[0];
 else
   return $x1(".//*[contains(concat(' ', @class, ' '), ' " + element + " ')]", root);
}

// Destroy elements that are retrieved with xpath
function seekAndDestroy(xpath, root) {
  forEach($x(xpath, root), destroy);
}

// Find out where a share link really leads
function discoverShare(e) {
  var link = e.target, 
    cachedLinks = eval(GM_getValue('cachedLinks', '({})')),
    sid;
  if (!link.href) return;
  if (sid=link.href.match(/sid=(.*?)&/i)) 
    sid = sid[1];
  else
    return;
  if (cachedLinks[sid]) {
    link.href = cachedLinks[sid];
    link.setAttribute('unmasked', '');
  } else
    GM_xmlhttpRequest({
          method: 'GET',
	  url: link.href,
	  headers: {
	    'User-agent':window.navigator.userAgent,
	    'Accept': 'application/atom+xml,application/xml,text/xml',
	  },
	  onload: function(res) {
	     var url;
	     if (res.status == 200 && (url = res.finalUrl)) {
	       link.href = url;
	       cachedLinks[sid] = url;
	       GM_setValue('cachedLinks', cachedLinks.toSource());
	       link.setAttribute('unmasked', '');
	     }
          }
    });
}

function displayStatus(status, time) {
    $c('UIComposer_Content').insertBefore(create('div', {id:'UIComposer_Status', style: 'padding-bottom: 5px;', kids:[
                        create('a',{href:$('fb_menu_account').firstChild.href,textContent:$('fb_menu_account').firstChild.textContent, style: 'font-weight: bold; font-size: 12px;'}),
                        create('span',{innerHTML:'&nbsp;'}),
                        create('span',{style:'font-weight: normal; font-size: 12px;',innerHTML:status}),
                        create('span',{innerHTML:'&nbsp;'}),
                        create('span',{style:'color: #BBBBBB; font-size: 8px;',textContent:time}),
                        create('span',{innerHTML:'&nbsp;'}),
                        create('a',{href:'#',style:'font-size: 8px;',textContent:'clear',onclick:function (e) { fbAjax('http://www.facebook.com/ajax/updatestatus.php', 'clear=1&profile_id='+$('user').value, true);GM_addStyle('#UIComposer_Status { display: none !important; }');e.preventDefault()}})
                        ]}), $c('UIComposer_Content').firstChild);
    GM_addStyle('#UIComposer_Status { display: block !important; }');
}

function getStatus() {
  if (typeof GM_xmlhttpRequest !== 'undefined')
        GM_xmlhttpRequest({ // Faster fetching using mobile facebook, but requires cross-domain
            method: 'GET',
            overrideMimeType: 'text/html; charset=x-user-defined',
            url: 'http://m.facebook.com/home.php',
            onload: function(res) {  
                if (res.status == 200 && (stat=res.responseText.match(new RegExp('<input[^>]+><div id="anchor_fbid_.+?" class="nopad">'+$('fb_menu_account').firstChild.textContent.split(' ')[0]+' (.+?)&nbsp;<small>\(([^\)]+)\)','i')))) {
                    displayStatus(stat[1], stat[2].replace(/^\(/,''));
                }
            }
        });
    else {
        var xmlhttp =  new XMLHttpRequest(); // Fetching from profile if cross-domain unavailable
        xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState==4 && xmlhttp.status==200) {
                if ((stat=xmlhttp.responseText.match(/<span id="status_text">(.+?)<\/span>/i))&&(time=xmlhttp.responseText.match(/<span id="status_time_inner">(.+?)<\/span>/i))&&(stat[1]!=' ')) {
                    displayStatus(stat[1], time[1]);
                }
            }
        }
        xmlhttp.open("GET", $('fb_menu_account').firstChild.href, true);
        xmlhttp.overrideMimeType("text/html; charset=x-user-defined"); // this fixes the content type glitch...
        xmlhttp.send(null);
    }
}

// Simulate Facebook's Ajax calls
function fbAjax(url, params) {
    var xmlhttp =  new XMLHttpRequest();
    xmlhttp.open("POST", url, true);
    params += "&post_form_id="+unsafeWindow.Env["post_form_id"]+"&__a=1&post_form_id_source=AsyncRequest&nctr[nid]="+unsafeWindow.Env["nctrlid"]+'&nctr[id]='+unsafeWindow.env_get("nctrlid")+'&fb_dtsg='+unsafeWindow.Env["fb_dtsg"]+'&nctr[ct]='+unsafeWindow.presence.pageLoadTime;
    xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xmlhttp.setRequestHeader("Content-length", params.length);
    xmlhttp.setRequestHeader("Connection", "close");
    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState==4 && xmlhttp.status==200) {
        }
    }
    xmlhttp.send(params);
}

// Now we can actually block the application from the Feed
function blockApp(appId) {
    var extraParams = "value="+appId+"&action=unfollow&filter_key=app_"+appId;
    fbAjax("http://www.facebook.com/ajax/feed/filter_action.php", extraParams, true);
}

// Block and Ignore requests
// By default we only block app and fanpage requests
// To block group and event invites un-comment the required portions
function blockReqs(doc) {

  var codes, a_icon, p_icon, g_icon, e_icon;

  // Block all app invites from a friend since most app invites are from repeat offenders
   if (GM_config.get('appReq')) {
        forEach($x('//a[contains(@onclick, "block_user_requests_dialog")]', doc), 
                function(friend) {
                    if (codes=/block_user_requests_dialog\("(.*?)",\s*"(.*?)"/.exec(friend.getAttribute('onclick'))) 
                        fbAjax('http://www.facebook.com/ajax/block_user_requests.php?app_id='+codes[1]+'&blockee_uid='+codes[2], 'confirm=1');
	    });
  
        // Block invites from apps
        apps = $x('//a[contains(@onclick, "block_app_dialog")]', doc);
        forEach(apps, 
                function(app) {
                    if (codes=/block_app_dialog\("(.*?)"/.exec(app.getAttribute('onclick'))) 
                        fbAjax('http://www.facebook.com/ajax/block_app.php?app_id='+codes[1]+'&source=requests', 'confirm=1');
	    });

        // Strikeout blocked requests
        if ((a_icon = $x1('.//a[@class="request_link"]/span[contains(@id, "app_")]', $c('UIRequestBox'))) && (apps.snapshotLength > 0)) {
        req_link = a_icon.parentNode.parentNode.getElementsByTagName('a')[0];
        insertAfter(create('del', {textContent:req_link.textContent, style:'padding-left:20px;'}), req_link);
        destroy(req_link);
        }
    }

  // Ignore requests from fanpages
  if (GM_config.get('fanReq')) {
        pages = $x('//input[contains(@onclick, "fbpage_fan") and contains(@onclick, "reject")]', doc);
        forEach(pages, 
                function(page) {
                    if (codes=/handle_request_click\("fbpage_fan",\s*"(.*?)";/.exec(page.getAttribute('onclick'))) 
                        fbAjax('http://www.facebook.com/ajax/reqs.php', 
                                'type=fbpage_fan&id='+codes[1]+'&action=reject');
	    });

        // Strikeout blocked requests
        if ((p_icon = $x1('.//img[contains(@class,"sx_icons_fbpage")]', $c('UIRequestBox'))) && (pages.snapshotLength > 0)) {
            req_link=p_icon.parentNode.getElementsByTagName('a')[0];
            insertAfter(create('del', {textContent:req_link.textContent, style:'padding-left:20px;'}), req_link);
            destroy(req_link);
        }
    }

  // Ignore group invites
  if (GM_config.get('groupReq')) {
        groups = $x('//input[contains(@onclick, "group_invite") and contains(@onclick, "reject")]', doc);
        forEach(groups, 
                function(group) {
                    if (codes=/handle_request_click\("group_invite",\s*"(.*?)"/.exec(group.getAttribute('onclick'))) 
                        fbAjax('http://www.facebook.com/ajax/reqs.php', 
                                'type=group_invite&id='+codes[1]+'&action=reject');
	    });

        // Strikeout blocked requests
        if ((g_icon = $x1('.//img[contains(@class,"sx_icons_group")]', $c('UIRequestBox'))) && groups.snapshotLength > 0) {
            req_link=g_icon.parentNode.getElementsByTagName('a')[0];
            insertAfter(create('del', {textContent:req_link.textContent, style:'padding-left:20px;'}), req_link);
            destroy(req_link);
        }
    }

  // Ignore event invites
    if (GM_config.get('eventReq')) {
        events = $x('//a[contains(@onclick, "show_remove_event_dialog")]', doc);
        forEach(events, 
                function(event) {
                    if (codes=/show_remove_event_dialog\("(.*?)"/.exec(event.getAttribute('onclick'))) 
                    fbAjax('http://www.facebook.com/ajax/reqs.php', 
                            'type=event_invite&id='+codes[1]+'&action=remove&params[event_rsvp_msg]=');
	     });
    
        // Strikeout blocked requests
        if ((e_icon = $x1('.//img[contains(@class,"sx_icons_event")]', $c('UIRequestBox')))&&events.snapshotLength > 0) {
            req_link=e_icon.parentNode.getElementsByTagName('a')[0];
            insertAfter(create('del', {textContent:req_link.textContent, style:'padding-left:20px;'}), req_link);
            destroy(req_link);
        }
    }
}

// Gets the page with the requests on it
function getReqs() {
var xmlhttp =  new XMLHttpRequest();
  xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState==4 && xmlhttp.status==200) {
      var doc = document.implementation.createDocument('','',null);
      var html = document.createElement('html');
      html.innerHTML = xmlhttp.responseText;
      doc.appendChild(html);
      blockReqs(doc);
    }
  }
  xmlhttp.open("GET", "http://www.facebook.com/reqs.php", true);
  xmlhttp.send(null);
}

function unfuckFeed(stream) {
  // Now may I introduce some really complicated god-like XPath that locates app and fan stories so that we can remove them
  // Wall stories = eavesdropping. Why would I care what people say to eachother?
  seekAndDestroy((GM_config.get('appHide') ? '//a[contains(@href, "http://apps.facebook.com/") or contains(@href, "http://apps.new.facebook.com/") or contains(@href, "http://www.facebook.com/pages/") or contains(@href, "http://quiz.applatform.com/")]/ancestor::div[starts-with(@id, "div_story_")] | //img[contains(@class, "sx_icons_fbpage_add") or contains(@src, "/app_")]/ancestor::div[starts-with(@id, "div_story_")]' : '') + (GM_config.get('appHide') && GM_config.get('wallStory') ? ' | ' : '') + (GM_config.get('wallStory') ? '//img[contains(@class, "UIIntentionalStory_Arrow")]/following-sibling::a[@href]/child::text()[not(.="' + $('fb_menu_account').firstChild.textContent + '")]/ancestor::div[starts-with(@id, "div_story_")]' : ''), stream);

  // Mark the stream so we don't sanitize it again
  stream.setAttribute('unfucked', 'true');
}

function unfuckFB() {

    // Unfuck the feeds
    forEach($x('//div[contains(@class, "UIStream") and not(@unfucked)]', $('content')), 
            function(stream) { 
            if (GM_config.get('appHide') || GM_config.get('wallStory')) unfuckFeed(stream);
            });

    if (window.firstStreamId && (st = $c('UIIntentionalStream_ShowNewStories')) && (s=st.getAttribute('style')) && s.match('display: block;')) 
    addScript('javascript:(function() { void($(__UIControllerRegistry["' + window.firstStreamId + '"]).doShowNewStories()); })();');

  if (!$('unfucked')) {
  
    var right, left, pokes, events, requests;
    if(right=$('home_sidebar')) {
        // Move requests, filters, events, and pokes to the top of left column so we can ignore the Highlights section easier
        if (pymk=$('pymk_hp_box')) destroy(pymk);
        if(pokes=$c('pokes')) right.insertBefore(pokes, right.firstChild);
        if(events=$c('UIUpcoming')) right.insertBefore(events.parentNode.parentNode, right.firstChild);

        // Now that everything is clean we have room to make the home page two columns
        // Inspired by http://userscripts.org/scripts/show/44687
        if (GM_config.get('twoColumn')) {
            right.insertBefore($('home_filter_list'), right.firstChild);
            
            // Remove the thumbnail and expand the composer
            //$c('UIComposer').style.marginLeft = "-59px";
            //$c('UIComposer').style.width = "650px";
            //destroy($c('UIComposer_Pic'));
        }
        
        if (GM_config.get('showStat')) getStatus();

        // Move requests back to the top
        if (requests=$c('UIRequestBox')) {
        right.insertBefore(requests.parentNode.parentNode, right.firstChild);
        getReqs(); // Start ignore requests process
        }
        
        // Remove App and Fan Highlights
        /*if (GM_config.get('appHigh') || GM_config.get('fanHigh'))
          seekAndDestroy((GM_config.get('appHigh') ? '//a[contains(@href, "http://www.facebook.com/apps/")]/ancestor::div[contains(@class, "UIHotStory")]' : '') + (GM_config.get('appHigh') && GM_config.get('fanHigh') ? ' | ' : '') + (GM_config.get('fanHigh') ? '//img[contains(@class, "sx_icons_fbpage")]/ancestor::div[contains(@class, "UIHotStory")]' : ''), $c('UIHotStream').parentNode.parentNode);*/
    }  
    
    // Remove and permanently block any application in the filters
    if (GM_config.get('appBlock'))
        forEach($x('//div[contains(@class, "UIFilterList_Item")]/a[contains(@href, "?filter=app_") or contains(@href, "?filter=pp")]'), 
                function(app) {
                    if(!/(2361831622|2344061033|2347471856|2392950137|2309869772|2305272732|2915120374)/.test(app.href)) {
                        if (app.href.indexOf('app_') != -1) 
                            blockApp(appId=app.href.split('app_')[1]);
                    destroy(app.parentNode);
                }
                });
    
    /*if (GM_config.get('expand')) {
        // Show older posts on home page
        if (more=$c('PagerMoreLink')) {
            var checker=setInterval(function(){
                if(unsafeWindow.__UIControllerRegistry) {
                    clearInterval(checker);
                    code = $c('PagerMoreLink').getAttribute('onclick');
                    if (trySplit=/\$\(__UIControllerRegistry\["(.*?)"\]\)/.exec(code)) {
		      code = trySplit[1];
		      addScript('javascript:(function() { void($(__UIControllerRegistry["' + code + '"]).loadOlder()); })();');
		      window.firstStreamId = code;
		    }
                }
            },200);
        }

        // Show more posts on profiles
        //if (unsafeWindow.ProfileStream) addScript('javascript:(function() { void(ProfileStream.getInstance().showMore()); })();');
        }*/
    
    $('content').appendChild(create('div', {id:'unfucked',style:'display:none;'}));
  }

  // Direct links http://userscripts.org/scripts/show/40691
  /*if (typeof GM_xmlhttpRequest != 'undefined' && GM_config.get('dLinks'))
    forEach($x('//a[contains(@href, "http://www.facebook.com/ext/share.php") and not(@unmasked)]'), 
            function(link) {
	      if ((click=link.getAttribute('onclick')) && (click.indexOf('ft(') != -1)) {
		link.removeAttribute('onclick');
		link.addEventListener('mouseover', discoverShare, false);
	      }
              });*/
}

// Re-run my code when the page changes, wouldn't have to do this if I could use CSS
function process() {
  $('content').removeEventListener('DOMNodeInserted', process, false);
  setTimeout(unfuckFB, 0);
  $('content').addEventListener("DOMNodeInserted", process, false);
}

// Wait for Facebook's content element to exist
if (self.location == top.location) var checker=setInterval(function(){
    if($('content')) {
      clearInterval(checker);
      GM_addStyle(unfuckStyle);
      if(typeof unsafeWindow==='undefined') unsafeWindow = window;
      process(); // Start the listener
    }
  }, 200);