Source for "StumbleUpon Best Friends"

By Thlayli
Has 20 other scripts.


// ==UserScript==
// @name           StumbleUpon Best Friends
// @namespace      thlayli.detrave.net
// @description    Adds a section for Best Friends on SU
// @include        http://*.stumbleupon.com/friends/*
// @include        http://*.stumbleupon.com/fans/*
// @version        2.3
// ==/UserScript==

// auto-update variables
var script_title = 'StumbleUpon Best Friends';
var source_location = 'http://thlayli.detrave.net/su-bestfriends.user.js';
var version_holder = 'http://thlayli.detrave.net/su-bestfriends.version.txt';
var current_version = '2.3';
var latest_version = '';
var manual_check = true;
var lastupdatecheck = GM_getValue('Updated', 'never');

GM_registerMenuCommand('Update - '+script_title, CheckVersion);
CheckForUpdate();

var editFlag = 0;
var aboutFlag = 0;
var fullFriends = 1;
var fullFans = 1;
var mutualBfs = 0;
var fanBfs = 0;
var whatsNew = xpath(document, "//a[contains(@href, 'stumbleupon.com/prefs/' )]");
var isYourPage = (whatsNew.snapshotLength > 0) ? 1 : 0;
var allFriends = xpath(document,'//dl');

if(isYourPage == 1){
	// get logged in name
	var thisStumbler = document.getElementById('search').firstChild.nextSibling.firstChild.nextSibling.textContent.replace('Hello ','');
	var friendsPref = GM_getValue(thisStumbler,'');
	var friendsList = (friendsPref.indexOf(';')) ? friendsPref.split(';') : new Array();
	friendsList = friendsList.sort(sortFriends);
	var friendsCount = friendsList.length;
	if(friendsList[0] == '')
		var friendsCount=0;
	//create bf section
	if(document.location.pathname.indexOf('/fans/') == -1){
		var mfBar = xpath(document, "//h2[contains(., ' mutual friends')]").snapshotItem(0);
		if(document.location.pathname.indexOf('/all/') == -1){
			var fanContent = xpath(document,"//h2[contains(., 'You are a fan of ')]").snapshotItem(0);
			if(fanContent){
				fanContent = fanContent.nextSibling.nextSibling.nextSibling.nextSibling;
				//check for "Who are they?" link
				if(fanContent.textContent.indexOf('see their favorites') != -1)
					fanContent = fanContent.nextSibling.nextSibling;
			}
		}
	}else{
		var mfBar = xpath(document, "//h2[contains(., ' fans')]").snapshotItem(0);
	}
	var mfLinks = mfBar.nextSibling.nextSibling;
	var mfContent = mfBar.nextSibling.nextSibling.nextSibling.nextSibling;
	//check for "Who are they?" link
	if(mfContent.textContent.indexOf('sharing your discoveries') != -1)
		mfContent = mfContent.nextSibling.nextSibling;
	var bfBar = mfBar.cloneNode(true);
	var bfLinks = mfLinks.cloneNode(true);
	var bfContent = mfContent.cloneNode(true);
	var bfSpacer = document.createElement('div');
	bfSpacer.className = 'clear pdgTopLg';
	bfContent.innerHTML = '\n';
	mfBar.parentNode.insertBefore(bfSpacer,mfBar.previousSibling);
	mfBar.parentNode.insertBefore(bfBar,bfSpacer);
	mfBar.parentNode.insertBefore(bfLinks,bfSpacer);
	mfBar.parentNode.insertBefore(bfContent,bfSpacer);
	bfText = (friendsCount!=1) ? 'friends' : 'friend';
	bfBar.innerHTML = 'Your ' + friendsCount + ' best ' + bfText;
	bfLinks.innerHTML = '<ul class="cmds"><li class="textlink"><a href="javascript:void(0);" class="textlink" id="edit_bf">Edit best friends</a></li><li class="textlink"><span class="bullet" id="cancel_bullet" style="display: none;"> &bull;</span><a href="javascript:void(0);" class="textlink" id="cancel_edit" style="display: none;">Cancel edit</a></li></ul><div class="clear"><!-- --></div>';
	//create full content sections
	var fullFriendsContent = mfContent.cloneNode(true);
	fullFriendsContent.style.display = 'none';
	fullFriendsContent.id = 'full_friends';
	mfContent.parentNode.insertBefore(fullFriendsContent,mfContent);
	if(fanContent){
		var fullFansContent = fanContent.cloneNode(true);
		fullFansContent.style.display = 'none';
		fullFansContent.id = 'full_fans';
		fanContent.parentNode.insertBefore(fullFansContent,fanContent);
	}
	var moreFans = xpath(document, "//a[contains(@href, 'friends/all/#nm')]").snapshotItem(0);
	if(moreFans){
		moreFans.href = 'javascript: void(0);';
		moreFans.wrappedJSObject.addEventListener('click', toggleFanLists, true);
	}
	var moreFriends = xpath(document, "//a[contains(., 'Show more friends')]").snapshotItem(0);
	if(moreFriends){
		moreFriends.href = 'javascript: void(0);';
		moreFriends.wrappedJSObject.addEventListener('click', toggleFriendLists, true);
	}
	//check for About Link modification
	if(mfContent.firstChild.nextSibling.firstChild.nextSibling.firstChild.href.indexOf('/about/') != -1)
		var aboutFlag = 1;
	//edit & cancel event listeners
	document.getElementById('edit_bf').wrappedJSObject.addEventListener('click', editFriends, true);
	document.getElementById('cancel_edit').wrappedJSObject.addEventListener('click', cancelEdit, true);
	//retrieve full list
	if(document.location.pathname.indexOf('/friends/all/') == -1 && document.location.pathname.indexOf('/fans/') == -1){
		var allLocation = document.location.href.replace(/\/fans\//ig,'')+'all/';
		GM_xmlhttpRequest({
			method: 'GET',
			url: allLocation,
			headers: {
				'User-agent': 'Mozilla/4.0 (compatible) Greasemonkey',
				'Accept': 'text/html',
			},
			onload: function(responseDetails) {
					//split content from all friends page and fill full content section
					var tempContent = responseDetails.responseText.split('class="listPeople">');
					tempFriendContent = tempContent[1].split('</div>');
					fullFriendsContent.innerHTML = tempFriendContent[0];
					removeDupes(fullFriendsContent);
					if(tempContent[2] && fullFansContent){
						tempFansContent = tempContent[2].split('</div>');
						fullFansContent.innerHTML = tempFansContent[0];
						removeDupes(fullFansContent);
					}
					if(moreFriends)
						toggleFriendLists();
					if(moreFans)
						toggleFanLists();
					fixAboutLinks();
					insertFullLists();
					updateNumbers();
			}
		});
	}else{
		writeBfs();
	}
}

function removeDupes(section){
	allFriends = xpath(section,'dl');
	var offset = 0;
	var toRemove = new Array();
	for(n=friendsList.length-1;n>=0;n--){
		for(i=0;i<allFriends.snapshotLength;i++){
			var linkName = allFriends.snapshotItem(i).firstChild.nextSibling.nextSibling.nextSibling.firstChild.textContent.replace(/^\s+|\s+$/g,'');
			if(friendsList[n].split(',')[0] == linkName){
				//count bfs
				if(section.id=='full_friends')
					mutualBfs++;
				if(section.id=='full_fans')
					fanBfs++;
				// check online status
				if(allFriends.snapshotItem(i).firstChild.nextSibling.nextSibling.nextSibling.firstChild.lastChild.nodeName == 'IMG'){
					var tempFriend = friendsList[n];
					friendsList.splice(n,1);
					friendsList.splice(friendsList.length - offset, 0, tempFriend+',online');
					offset++;
				}
				toRemove.push(i);
				break;
			}
		}
	}
	//remove nodes
	for(r=0;r<toRemove.length;r++)
		allFriends.snapshotItem(toRemove[r]).parentNode.removeChild(allFriends.snapshotItem(toRemove[r]));
}

function fixAboutLinks(){
	if(aboutFlag==1){
		var docLinks = xpath(document,'//a');
		for(i=0;i<docLinks.snapshotLength;i++){
			if(docLinks.snapshotItem(i).href.match(/^http:\/\/www|^http:\/\/buzz.stumbleupon|^javascript|.group.stumbleupon.com|about\/$/i) == null && docLinks.snapshotItem(i).href.indexOf('stumbleupon.com/') != -1 && docLinks.snapshotItem(i).href.indexOf('http://'+thisStumbler.toLowerCase()) == -1 && docLinks.snapshotItem(i).href.split('/').length < 5)
				docLinks.snapshotItem(i).href = docLinks.snapshotItem(i).href + 'about/';
		}
	}
}

function insertFullLists(){
	if(document.location.pathname.indexOf('/friends/all/') == -1){
		if(moreFriends){
			mfContent.parentNode.removeChild(mfContent);
			document.getElementById('full_friends').style.display = 'block';
		}
		if(fanContent){
			fanContent.parentNode.removeChild(fanContent);
			document.getElementById('full_fans').style.display = 'block';
		}
	}
	writeBfs();
}

function writeBfs(){
	allFriends = xpath(document,'//dl');
	for(i=friendsList.length-1;i>=0;i--){
		var bf = friendsList[i].split(',');
		var bfOnline = '';
		var bfAbout = '';
		if(bf.length >= 3){
			var bfName = bf[0];
			var bfTitle = bf[1];
			var bfImg = bf[2];
			if(bf[3])
				bfOnline = ' <img style="vertical-align: middle; width: 6px; height: 6px;" title="Online now" alt="Online now" src="http://cdn.stumble-upon.com/images/icon_online.gif"/>';
			if(aboutFlag == 1)
				bfAbout = 'about/';
			var newBf = document.createElement('dl');
			newBf.className = 'bf';
			newBf.innerHTML = '\n<dd class="thumbnail"><a title="'+bfTitle+'" href="http://'+bfName+'.stumbleupon.com/'+bfAbout+'"><img alt="'+bfTitle+'" src="http://cdn.stumble-upon.com/'+bfImg+'.jpg"/></a></dd>\n<dt><a href="http://'+bfName+'.stumbleupon.com/'+bfAbout+'">'+bfName+bfOnline+'</a></dt>';
			bfContent.appendChild(newBf);
		}
	}
}

function updateNumbers(){
	if(mutualBfs > 0){
		var plural = (mutualBfs == 1) ? 'friend' : 'friends';
		var mutualLabel = xpath(document, "//h2[contains(., ' mutual friends')]").snapshotItem(0);
		var mutualNumber = mutualLabel.innerHTML.split(' ')[1];
		mutualLabel.innerHTML = 'Your ' + (mutualNumber - mutualBfs) + ' mutual friends <span style="font-size: 12px;">(not including ' + mutualBfs + ' best ' + plural + ')</span>';
	}
	if(fanBfs > 0){
		var plural = (fanBfs == 1) ? 'friend' : 'friends';
		var yourFansLabel = xpath(document, "//h2[contains(., 'You are a fan of ')]").snapshotItem(0);
		var yourFansNumber = yourFansLabel.innerHTML.split(' ')[5];
		yourFansLabel.innerHTML = 'You are a fan of ' + (yourFansNumber - fanBfs) + ' people <span style="font-size: 12px;">(not including ' + fanBfs + ' best ' + plural + ')</span>';
	}
	if((friendsList.length - mutualBfs - fanBfs) > 0 && fanContent){
		var plural = ((friendsList.length - mutualBfs - fanBfs) == 1) ? 'friend' : 'friends';
		var fansLabel = xpath(document, "//h2[contains(., ' fans')]").snapshotItem(0);
		fansLabel.innerHTML += ' <span style="font-size: 12px;">(including ' + (friendsList.length - mutualBfs - fanBfs) + ' best ' + plural + ')</span>';
	}
}

function toggleFriendLists(){
	var fullFriendsList = xpath(document.getElementById('full_friends'),'dl');
	if(fullFriends == 1){
		moreFriends.innerHTML = 'Show more friends';
		fullFriends = 0;
		for(i=15;i<fullFriendsList.snapshotLength;i++)
			fullFriendsList.snapshotItem(i).style.display = 'none';
	}else{
		moreFriends.innerHTML = 'Show less friends';
		fullFriends = 1;
		for(i=15;i<fullFriendsList.snapshotLength;i++)
			fullFriendsList.snapshotItem(i).style.display = 'block';
	}
}

function toggleFanLists(){
	var fullFansList = xpath(document.getElementById('full_fans'),'dl');
	if(fullFans == 1){
		moreFans.innerHTML = 'Show more fans';
		fullFans = 0;
		for(i=15;i<fullFansList.snapshotLength;i++)
			fullFansList.snapshotItem(i).style.display = 'none';
	}else{
		moreFans.innerHTML = 'Show less fans';
		fullFans = 1;
		for(i=15;i<fullFansList.snapshotLength;i++)
			fullFansList.snapshotItem(i).style.display = 'block';
	}
}

function markFriend(evt){
    if(evt){
		var elem = (evt.target) ? evt.target : evt.srcElement;
		if(elem.nodeName == 'IMG'){
			if(!elem.style.border)
				elem.style.border='3px solid';
			else
				elem.style.border='';
		}else{
			if(!elem.parentNode.previousSibling.previousSibling.firstChild.firstChild.style.border)
				elem.parentNode.previousSibling.previousSibling.firstChild.firstChild.style.border="3px solid";
			else
				elem.parentNode.previousSibling.previousSibling.firstChild.firstChild.style.border="";
		}
	}
    return false;
}

function cancelEdit(){
	window.location.reload();
}

function editFriends(){
	allFriends = xpath(document,'//dl');
	if(editFlag == 0){
		//edit
		if(fanContent){
			if(moreFriends){
				fullFriends = 0;
				toggleFriendLists();
			}
			if(moreFans){
				fullFans = 0;
				toggleFanLists();
			}
		}
		document.getElementById('edit_bf').innerHTML = 'Save best friends';
		document.getElementById('cancel_edit').style.display = 'inline';
		document.getElementById('cancel_bullet').style.display = 'inline';
		for(i=1;i<allFriends.snapshotLength;i++){
			if(allFriends.snapshotItem(i).childNodes.length < 6){
				allFriends.snapshotItem(i).wrappedJSObject.addEventListener('click', markFriend, false);
				allFriends.snapshotItem(i).innerHTML = (aboutFlag == 0) ? allFriends.snapshotItem(i).innerHTML.replace(/href=\"http:\/\/([^\.]+).stumbleupon.com\/\"/g,'href="javascript:void(0);" alt="$1"') : allFriends.snapshotItem(i).innerHTML.replace(/href=\"http:\/\/([^\.]+).stumbleupon.com\/about\/\"/g,'href="javascript:void(0);" alt="$1"')

				allFriends.snapshotItem(i).firstChild.nextSibling.setAttribute('style', 'padding-bottom: 6px;');
			}
		}
		editFlag=1;
	}else{
		//save
		document.getElementById('edit_bf').innerHTML = 'Edit best friends';
		document.getElementById('cancel_edit').style.display = 'none';
		document.getElementById('cancel_bullet').style.display = 'none';
		for(i=1;i<allFriends.snapshotLength;i++){
			var firstLink = allFriends.snapshotItem(i).firstChild.nextSibling.firstChild;
			if(allFriends.snapshotItem(i).childNodes.length < 6)
				allFriends.snapshotItem(i).wrappedJSObject.removeEventListener('click', markFriend, false);
			if(allFriends.snapshotItem(i).className == 'bf'){
				//remove best friend
				if(allFriends.snapshotItem(i).firstChild.nextSibling.firstChild.firstChild.style && allFriends.snapshotItem(i).firstChild.nextSibling.firstChild.firstChild.style.border){
					var linkName = allFriends.snapshotItem(i).firstChild.nextSibling.nextSibling.nextSibling.firstChild.textContent.replace(/^\s+|\s+$/g,"");
					for(n=0;n<friendsList.length;n++){
						if(friendsList[n].split(',')[0]==linkName)
							friendsList.splice(n,1);
					}
				}
			}else{
				//add best friend
				if(allFriends.snapshotItem(i).firstChild.nextSibling.firstChild.firstChild.style.border){
					var friendImg = firstLink.firstChild.src.replace(/http:\/\/cdn\.stumble-upon\.com\/|\.jpg/ig,''); //add code to deal with no avatar
					friendsList.push(firstLink.getAttribute('alt')+','+firstLink.title+','+friendImg);
				}
			}
		}
		editFlag=0;
		if(friendsList[0] == '')
			friendsList.shift();
		friendsPref = (friendsList.length > 0) ? friendsList.join(';').replace(/,online/ig,'') : '';
		GM_setValue(thisStumbler,friendsPref);
		window.location.reload();
	}
}

function sortFriends(a,b){
	a = a.toLowerCase();
	b = b.toLowerCase();
	if (a<b) return 1;
	if (a>b) return -1;
	return 0;
}

function xpath(obj,query) {
    return document.evaluate(query, obj, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
}

// Userscript Auto-Update - http://userscripts.org/scripts/show/22372 - edited July 18 2008 by Nathan Blume

function GetNewVersion() {
        var today = new Date();
        GM_setValue('Updated', String(today));
        window.location = source_location;
}

function CheckForUpdate(){   
    var today = new Date();
    var one_day = 24 * 60 * 60 * 1000; //One day in milliseconds
    if(lastupdatecheck != 'never'){
        today = today.getTime(); //Get today's date
        lastupdatecheck = new Date(lastupdatecheck).getTime();
        var interval = (today - lastupdatecheck) / one_day; //Find out how many days have passed       
        if(interval >= 7){
			manual_check = false;
            CheckVersion();
		}
    }else{
        lastupdatecheck = new Date(lastupdatecheck).getTime();
		manual_check = false;
        CheckVersion();
	}
}

function CheckVersion(){
    GM_xmlhttpRequest({
            method: 'GET',
            url: version_holder,
            headers: {'Content-type':'application/x-www-form-urlencoded'},           
            onload: function(responseDetails){
                var latest_version = responseDetails.responseText.match(/version=([0-9\.]+)/);
                if(latest_version[1] != null && latest_version[1] != 'undefined'){
                    if(current_version != latest_version[1]){
                        if(confirm('A more recent version of ' + script_title + ' (' + latest_version[1] + ') has been found.\nWould you like to get it now?'))
                            GetNewVersion();
                        else
                            AskForReminder();
                    }else{
						SkipWeeklyUpdateCheck();
						if(manual_check == true)
							alert('You have the latest version of ' + script_title + '.');
					}
                }else{
                    alert('Sorry, there was problem checking for the update.\nPlease try again later.');
                }
            }
        });
}

function AskForReminder(){
    if(confirm('Would you like to be reminded in 24 hours ?\n(Cancel to be reminded in one week.)')){
        var today = new Date();
        today = today.getTime();       
        var sixdays_ms = 6 * 24 * 60 * 60 * 1000;
        var sda_ms = today - sixdays_ms;       
        var sixdaysago = new Date(sda_ms)
        GM_setValue('Updated', String(sixdaysago));
    }else{
        SkipWeeklyUpdateCheck();
	}
}

function SkipWeeklyUpdateCheck(){
    var today = new Date();
    GM_setValue('Updated', String(today));
}