Facebook User List Maker

Save and Load Friend Lists for Facebook Lists

// ==UserScript==
// @name         Facebook User List Maker
// @namespace    facebookuserlistmaker
// @version      1.5.0
// @author       Tophness
// @match        http://www.facebook.com/*
// @match        https://www.facebook.com/*
// @description  Save and Load Friend Lists for Facebook Lists
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js
// @grant   GM_getValue
// @grant   GM_setValue
// @grant   GM_deleteValue
// @grant   GM_listValues
// @run-at       document-idle
// ==/UserScript==

var friendsSelector = 'div[id$="_friends"]';
var friendsSelector2 = 'div[role="dialog"]';
var friendsSelector3 = 'div[id="pagelet_group_members"]';
var storySelector = 'a[data-hovercard]';
var scrollResultSelector = 'div[class^="fbProfileBrowserResult"]';
var scrollMoreSelector = 'a[class$="uiMorePagerPrimary"]';
var scrollNoMoreSelector = 'div[class$="NoMoreItems"]';
var scrollul = 'ul[class^="uiList"]';
var users = [];
var friendsel;
var saveDiv = '<form name="save"><input name="savebut" type=button onclick="document.forms.save.dosave.value=true;" value="Save List"><input type=text name=listname><input type=hidden name=dosave value="false"></form>';
var loadDiv = '<form name="load"><input name="loadbut" type=button onclick="document.forms.load.doload.value=true;" value="Load List"><input type=hidden name=doload value="false"><input type=hidden name=dodelete value="false"><input type=button onclick="document.forms.load.dodelete.value=true;" value="Delete List"></form>';

function includes(k) {
	for(var i=0; i < this.length; i++){
		if( this[i].name === k ){
			return true;
		}
	}
	return false;
}

function block(link){
	if(link.outerHTML.indexOf('data-hovercard') != -1){
		var uname = link.innerText;
		var uid = link.getAttribute('uid');
		if(uname != "" && !users.includes(uname)){
			var newuser = {};
			newuser.name = uname;
			if(uid){
				newuser.id = uid;
			}
			else{
				uid = link.getAttribute('data-hovercard');
				uid = uid.substring(uid.indexOf('id=') + 3);
				if(uid.indexOf('&') == -1){
					uid = uid.substring(0, uid.indexOf('"'));
				}
				else{
					uid = uid.substring(0, uid.indexOf('&'));
				}
				newuser.id = uid;
			}
			users.push(newuser);
		}
	}
}

function processFilter(stories){
	if (!stories) {
		return;
	}
	var story = stories.querySelectorAll(storySelector);
	if (!story.length) {
		return;
	}
	for (var i = 0; i < story.length; i++) {
		block(story[i]);
	}
}

function process() {
	if(document.forms.save){
		if(document.forms.save.listname.value != ""){
			if(location.href.indexOf('/members') != -1){
				processFilter(document.querySelector(friendsSelector3));
			}
			else if(location.href.indexOf('/friends') != -1){
				processFilter(document.querySelector(friendsSelector));
			}
			else{
				processFilter(friendssel);
			}
			GM_setValue(document.forms.save.listname.value, JSON.stringify(users));
		}
	}
	else{
		start();
	}
}

function waitForEl(selector, callback, timer=100){
	var poller1 = setInterval(function(){
		$jObject = jQuery(selector);
		if($jObject.length < 1){
			return;
		}
		clearInterval(poller1);
		callback($jObject);
	},timer);
}

function uToken(username, id){
	var newdiv = document.createElement('span');
	newdiv.className = "removable uiToken";
	var newdiv2 = document.createElement('span');
	newdiv2.className = "uiTokenText";
	newdiv2.innerHTML = username;
	var newdiv3 = document.createElement('input');
	newdiv3.name="members[]";
	newdiv3.autocomplete="off";
	newdiv3.type="hidden";
	newdiv3.value = id;
	var newdiv4 = document.createElement('input');
	newdiv4.value=username;
	newdiv4.name="text_members[]";
	newdiv4.autocomplete="off";
	newdiv4.type="hidden";
	var newdiv5 = document.createElement('a');
	newdiv5.href="#";
	newdiv5.aria_label="Remove " + username;
	newdiv5.className="remove uiCloseButton uiCloseButtonSmall";
	newdiv.appendChild(newdiv2);
	newdiv.appendChild(newdiv3);
	newdiv.appendChild(newdiv4);
	newdiv.appendChild(newdiv5);
	document.getElementById('fbFriendListTokenizer').getElementsByClassName('tokenarea')[0].appendChild(newdiv);
}

function listpaste(){
	if(document.getElementById('createListMembers')){
		if(document.getElementById('createListname') && document.forms.load.listnames.value){
			document.getElementById('createListname').value = document.forms.load.listnames.value;
		}
		if(document.getElementById('fbFriendListTokenizer').getElementsByClassName('tokenarea')[0]){
			document.getElementById('fbFriendListTokenizer').getElementsByClassName('tokenarea')[0].className = "tokenarea";
		}
		for (var i = 0; i < users.length; i++) {
			uToken(users[i].name, users[i].id);
		}
	}
	else{
		setTimeout(listpaste, 1000);
	}
}

function startObserver(){
	if(document.forms.save){
		if(document.forms.save.dosave.value == "true"){
			var listname = document.forms.save.listname.value.toLowerCase().replace(/[^a-zA-Z0-9]+/g, "");
			users = JSON.parse(GM_getValue(listname, "[]"));
			if(!users){
				console.warn("error");
			}
			users.includes = includes;
			process();
		}
	}
}

function doscroll(el){
	var scrollbut = el.querySelector(scrollMoreSelector);
	waitForEl(scrollbut, function() {
		scrollbut.click();
		if(!el.querySelector(scrollNoMoreSelector)){
			doscroll(el);
		}
		else{
			startObserver();
		}
	},1000);
}

function loadbegin(contentarea){
	if(document.forms.load.doload.value == "true"){
		users = JSON.parse(GM_getValue(document.forms.load.listnames.value, "[]"));
		if(!users){
			console.warn("error");
		}
		contentarea = document.getElementById('contentArea');
		if(contentarea.getElementsByClassName('uiHeaderActions')[0].childNodes[0]){
			contentarea.getElementsByClassName('uiHeaderActions')[0].childNodes[0].addEventListener('click', listpaste, false);
			contentarea.getElementsByClassName('uiHeaderActions')[0].childNodes[0].click();
		}
	}
	else if(document.forms.load.dodelete.value == "true"){
		var select = document.forms.load.listnames;
		GM_deleteValue(select.value);
		dvalue = select.selectedIndex;
		select.removeChild(select[dvalue]);
	}
	else{
		setTimeout(loadbegin, 1000);
	}
}

function loadfindpage(el){
	if(el.firstChild.id != 'saveDiv'){
		var savebutton = document.createElement('div');
		savebutton.id = 'saveDiv';
		savebutton.innerHTML = saveDiv;
		el.insertAdjacentElement('afterbegin', savebutton);
		document.forms.save.savebut.addEventListener('click', function(){startObserver();}, true);
	}
}

function findpage(){
	var divs = document.querySelectorAll(friendsSelector2);
	var found = false;
	for (var i = 0; i < divs.length; ++i) {
		if(divs[i].querySelectorAll(storySelector).length){
			friendssel = divs[i];
			found = true;
		}
	}
	if(found){
		loadfindpage(friendssel);
		startObserver();
	}
	else{
		setTimeout(findpage, 1000);
	}
}

function scrollmembers(el){
		var scrollresult = el.querySelectorAll(scrollResultSelector);
		if(scrollresult){
			for (var i = 0; i < scrollresult.length; ++i) {
				doscroll(scrollresult[i]);
			}
		}
}

function scrollfriends(el, oldlength=0, timeout=10){
	var uilist = el.querySelectorAll(scrollul);
	if(uilist.length > 0){
		uilist[uilist.length-1].scrollIntoView();
		if(uilist.length > oldlength){
			scrollfriends(el, uilist.length);
		}
		else{
			if(uilist.length <= oldlength){
				timeout --;
				if(timeout > 0){
					console.log('timeout: ' + timeout);
					setTimeout(function() {
						scrollfriends(el, oldlength, timeout);
					}, 1000);
				}
				else{
					startObserver();
				}
			}
		}
	}
}

function start(){
if(location.href.indexOf('bookmarks/lists') != -1){
	var contentarea = document.getElementById('contentArea');
	waitForEl(contentarea, function() {
		var loadbut = document.createElement('div');
		loadbut.innerHTML = loadDiv;
		var x = document.createElement("select");
		x.name="listnames";
		var alllists = GM_listValues();
		for (var i = 0; i < alllists.length; i++) {
			var option = document.createElement("option");
			option.text = alllists[i];
			x.add(option);
		}
		contentarea.insertAdjacentElement('afterbegin', loadbut);
		document.forms.load.appendChild(x);
		loadbegin();
	});
}
else if(location.href.indexOf('/friends') != -1){
	var fs = document.querySelector(friendsSelector);
	scrollfriends(fs);
	waitForEl(fs, function() {
		loadfindpage(fs);
	},500);
}
else if(location.href.indexOf('/members') != -1){
	var fs3 = document.querySelector(friendsSelector3);
	scrollmembers(fs3);
	waitForEl(fs3, function() {
		loadfindpage(fs3);
	},500);
}
else{
	findpage();
}
}
start();