Facebook User List Maker

Save and Load Friend Lists for Facebook Lists

  1. // ==UserScript==
  2. // @name Facebook User List Maker
  3. // @namespace facebookuserlistmaker
  4. // @version 1.5.0
  5. // @author Tophness
  6. // @match http://www.facebook.com/*
  7. // @match https://www.facebook.com/*
  8. // @description Save and Load Friend Lists for Facebook Lists
  9. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js
  10. // @grant GM_getValue
  11. // @grant GM_setValue
  12. // @grant GM_deleteValue
  13. // @grant GM_listValues
  14. // @run-at document-idle
  15. // ==/UserScript==
  16.  
  17. var friendsSelector = 'div[id$="_friends"]';
  18. var friendsSelector2 = 'div[role="dialog"]';
  19. var friendsSelector3 = 'div[id="pagelet_group_members"]';
  20. var storySelector = 'a[data-hovercard]';
  21. var scrollResultSelector = 'div[class^="fbProfileBrowserResult"]';
  22. var scrollMoreSelector = 'a[class$="uiMorePagerPrimary"]';
  23. var scrollNoMoreSelector = 'div[class$="NoMoreItems"]';
  24. var scrollul = 'ul[class^="uiList"]';
  25. var users = [];
  26. var friendsel;
  27. 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>';
  28. 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>';
  29.  
  30. function includes(k) {
  31. for(var i=0; i < this.length; i++){
  32. if( this[i].name === k ){
  33. return true;
  34. }
  35. }
  36. return false;
  37. }
  38.  
  39. function block(link){
  40. if(link.outerHTML.indexOf('data-hovercard') != -1){
  41. var uname = link.innerText;
  42. var uid = link.getAttribute('uid');
  43. if(uname != "" && !users.includes(uname)){
  44. var newuser = {};
  45. newuser.name = uname;
  46. if(uid){
  47. newuser.id = uid;
  48. }
  49. else{
  50. uid = link.getAttribute('data-hovercard');
  51. uid = uid.substring(uid.indexOf('id=') + 3);
  52. if(uid.indexOf('&') == -1){
  53. uid = uid.substring(0, uid.indexOf('"'));
  54. }
  55. else{
  56. uid = uid.substring(0, uid.indexOf('&'));
  57. }
  58. newuser.id = uid;
  59. }
  60. users.push(newuser);
  61. }
  62. }
  63. }
  64.  
  65. function processFilter(stories){
  66. if (!stories) {
  67. return;
  68. }
  69. var story = stories.querySelectorAll(storySelector);
  70. if (!story.length) {
  71. return;
  72. }
  73. for (var i = 0; i < story.length; i++) {
  74. block(story[i]);
  75. }
  76. }
  77.  
  78. function process() {
  79. if(document.forms.save){
  80. if(document.forms.save.listname.value != ""){
  81. if(location.href.indexOf('/members') != -1){
  82. processFilter(document.querySelector(friendsSelector3));
  83. }
  84. else if(location.href.indexOf('/friends') != -1){
  85. processFilter(document.querySelector(friendsSelector));
  86. }
  87. else{
  88. processFilter(friendssel);
  89. }
  90. GM_setValue(document.forms.save.listname.value, JSON.stringify(users));
  91. }
  92. }
  93. else{
  94. start();
  95. }
  96. }
  97.  
  98. function waitForEl(selector, callback, timer=100){
  99. var poller1 = setInterval(function(){
  100. $jObject = jQuery(selector);
  101. if($jObject.length < 1){
  102. return;
  103. }
  104. clearInterval(poller1);
  105. callback($jObject);
  106. },timer);
  107. }
  108.  
  109. function uToken(username, id){
  110. var newdiv = document.createElement('span');
  111. newdiv.className = "removable uiToken";
  112. var newdiv2 = document.createElement('span');
  113. newdiv2.className = "uiTokenText";
  114. newdiv2.innerHTML = username;
  115. var newdiv3 = document.createElement('input');
  116. newdiv3.name="members[]";
  117. newdiv3.autocomplete="off";
  118. newdiv3.type="hidden";
  119. newdiv3.value = id;
  120. var newdiv4 = document.createElement('input');
  121. newdiv4.value=username;
  122. newdiv4.name="text_members[]";
  123. newdiv4.autocomplete="off";
  124. newdiv4.type="hidden";
  125. var newdiv5 = document.createElement('a');
  126. newdiv5.href="#";
  127. newdiv5.aria_label="Remove " + username;
  128. newdiv5.className="remove uiCloseButton uiCloseButtonSmall";
  129. newdiv.appendChild(newdiv2);
  130. newdiv.appendChild(newdiv3);
  131. newdiv.appendChild(newdiv4);
  132. newdiv.appendChild(newdiv5);
  133. document.getElementById('fbFriendListTokenizer').getElementsByClassName('tokenarea')[0].appendChild(newdiv);
  134. }
  135.  
  136. function listpaste(){
  137. if(document.getElementById('createListMembers')){
  138. if(document.getElementById('createListname') && document.forms.load.listnames.value){
  139. document.getElementById('createListname').value = document.forms.load.listnames.value;
  140. }
  141. if(document.getElementById('fbFriendListTokenizer').getElementsByClassName('tokenarea')[0]){
  142. document.getElementById('fbFriendListTokenizer').getElementsByClassName('tokenarea')[0].className = "tokenarea";
  143. }
  144. for (var i = 0; i < users.length; i++) {
  145. uToken(users[i].name, users[i].id);
  146. }
  147. }
  148. else{
  149. setTimeout(listpaste, 1000);
  150. }
  151. }
  152.  
  153. function startObserver(){
  154. if(document.forms.save){
  155. if(document.forms.save.dosave.value == "true"){
  156. var listname = document.forms.save.listname.value.toLowerCase().replace(/[^a-zA-Z0-9]+/g, "");
  157. users = JSON.parse(GM_getValue(listname, "[]"));
  158. if(!users){
  159. console.warn("error");
  160. }
  161. users.includes = includes;
  162. process();
  163. }
  164. }
  165. }
  166.  
  167. function doscroll(el){
  168. var scrollbut = el.querySelector(scrollMoreSelector);
  169. waitForEl(scrollbut, function() {
  170. scrollbut.click();
  171. if(!el.querySelector(scrollNoMoreSelector)){
  172. doscroll(el);
  173. }
  174. else{
  175. startObserver();
  176. }
  177. },1000);
  178. }
  179.  
  180. function loadbegin(contentarea){
  181. if(document.forms.load.doload.value == "true"){
  182. users = JSON.parse(GM_getValue(document.forms.load.listnames.value, "[]"));
  183. if(!users){
  184. console.warn("error");
  185. }
  186. contentarea = document.getElementById('contentArea');
  187. if(contentarea.getElementsByClassName('uiHeaderActions')[0].childNodes[0]){
  188. contentarea.getElementsByClassName('uiHeaderActions')[0].childNodes[0].addEventListener('click', listpaste, false);
  189. contentarea.getElementsByClassName('uiHeaderActions')[0].childNodes[0].click();
  190. }
  191. }
  192. else if(document.forms.load.dodelete.value == "true"){
  193. var select = document.forms.load.listnames;
  194. GM_deleteValue(select.value);
  195. dvalue = select.selectedIndex;
  196. select.removeChild(select[dvalue]);
  197. }
  198. else{
  199. setTimeout(loadbegin, 1000);
  200. }
  201. }
  202.  
  203. function loadfindpage(el){
  204. if(el.firstChild.id != 'saveDiv'){
  205. var savebutton = document.createElement('div');
  206. savebutton.id = 'saveDiv';
  207. savebutton.innerHTML = saveDiv;
  208. el.insertAdjacentElement('afterbegin', savebutton);
  209. document.forms.save.savebut.addEventListener('click', function(){startObserver();}, true);
  210. }
  211. }
  212.  
  213. function findpage(){
  214. var divs = document.querySelectorAll(friendsSelector2);
  215. var found = false;
  216. for (var i = 0; i < divs.length; ++i) {
  217. if(divs[i].querySelectorAll(storySelector).length){
  218. friendssel = divs[i];
  219. found = true;
  220. }
  221. }
  222. if(found){
  223. loadfindpage(friendssel);
  224. startObserver();
  225. }
  226. else{
  227. setTimeout(findpage, 1000);
  228. }
  229. }
  230.  
  231. function scrollmembers(el){
  232. var scrollresult = el.querySelectorAll(scrollResultSelector);
  233. if(scrollresult){
  234. for (var i = 0; i < scrollresult.length; ++i) {
  235. doscroll(scrollresult[i]);
  236. }
  237. }
  238. }
  239.  
  240. function scrollfriends(el, oldlength=0, timeout=10){
  241. var uilist = el.querySelectorAll(scrollul);
  242. if(uilist.length > 0){
  243. uilist[uilist.length-1].scrollIntoView();
  244. if(uilist.length > oldlength){
  245. scrollfriends(el, uilist.length);
  246. }
  247. else{
  248. if(uilist.length <= oldlength){
  249. timeout --;
  250. if(timeout > 0){
  251. console.log('timeout: ' + timeout);
  252. setTimeout(function() {
  253. scrollfriends(el, oldlength, timeout);
  254. }, 1000);
  255. }
  256. else{
  257. startObserver();
  258. }
  259. }
  260. }
  261. }
  262. }
  263.  
  264. function start(){
  265. if(location.href.indexOf('bookmarks/lists') != -1){
  266. var contentarea = document.getElementById('contentArea');
  267. waitForEl(contentarea, function() {
  268. var loadbut = document.createElement('div');
  269. loadbut.innerHTML = loadDiv;
  270. var x = document.createElement("select");
  271. x.name="listnames";
  272. var alllists = GM_listValues();
  273. for (var i = 0; i < alllists.length; i++) {
  274. var option = document.createElement("option");
  275. option.text = alllists[i];
  276. x.add(option);
  277. }
  278. contentarea.insertAdjacentElement('afterbegin', loadbut);
  279. document.forms.load.appendChild(x);
  280. loadbegin();
  281. });
  282. }
  283. else if(location.href.indexOf('/friends') != -1){
  284. var fs = document.querySelector(friendsSelector);
  285. scrollfriends(fs);
  286. waitForEl(fs, function() {
  287. loadfindpage(fs);
  288. },500);
  289. }
  290. else if(location.href.indexOf('/members') != -1){
  291. var fs3 = document.querySelector(friendsSelector3);
  292. scrollmembers(fs3);
  293. waitForEl(fs3, function() {
  294. loadfindpage(fs3);
  295. },500);
  296. }
  297. else{
  298. findpage();
  299. }
  300. }
  301. start();