By engtech
Has 38 other scripts.
/*
--------------------------------------------------------------------
How to Install a Greasemonkey Script
--------------------------------------------------------------------
- You need the Firefox web browser - Download and install
http://www.mozilla.com/en-US/firefox/
- You need to install Greasemonkey - How-To
http://internetducttape.com/2007/08/23/howto-install-firefox-extensions-screenshots/
- Install this script - How-To
http://internetducttape.com/2007/08/24/howto-use-firefox-greasemonkey-userscripts-screenshots/
*/
// ==UserScript==
// @name Friend Feed By Service
// @namespace http://InternetDuctTape.com
// @description Search through FriendFeed by specific services
// @include http://friendfeed.com/*
// @exclude http://friendfeed.com/settings*
// @exclude http://friendfeed.com/account*
// @version 0.64
// ==/UserScript==
/*
- BUGFIX: Works with Even More Expander
- BUGFIX: the By Service fixed position menu wasn't clickable after scrolling
- BUGFIX: the 'click to share this script' link should be hidden unless you're hovering
- Change the promote link to go to the new documentation
*/
var friendfeedbyservice_version = "0.64";
(function() {
// Script updates itself every two weeks.
autoUpdateFromUserscriptsDotOrg({
name: 'Friend Feed By Service',
url: 'http://userscripts.org/scripts/source/24161.user.js',
version: friendfeedbyservice_version,
});
window.IDT_BYSERVICE_HIDE_LIST = [];
// Function for going through the list and hiding related services.
window.IDT_BYSERVICE_HIDE_SERVICE = function(node) {
window.IDT_BYSERVICE_HIDE_LIST.forEach( function(service) {
$(node).find('.icon a[@href="?service='+service+'"]').parents('.cluster').hide();
});
}
window.IDT_BYSERVICE_SETPOPUPMENU = function (B, E, STYLE) {
// This is a copy of FriendFeed's setPopupMenu routine because it
// has to handle fixed positioning.
var A = $(".popupmenu");
if (A.length && A[0].menulink == E) {
unsafeWindow.closePopupMenu();
return;
}
unsafeWindow.closePopupMenu();
var F = $("<div class=\"popupmenu\" "+STYLE+">");
var H = $("<div class=\"shadow\">");
var C = $("<div class=\"foreground\">");
F.append(H);
F.append(C);
F[0].menulink = E;
$.each(B, function (K, L) {
var J = $.extend({href:"#"}, L.attrs || {});
var I = $(unsafeWindow.tag("a", J, L.l));
if (L.onclick) {
I.click(function (M) {
L.onclick(M);
unsafeWindow.closePopupMenu();
return false;
});
}
C.append(I);
});
if (!B.length) {
C.append("No options :(");
}
$("body").append(F);
var G = $(E).offset();
G.top += $(E).height() + 2;
F.css(G);
var D = 2;
H.width(C.width() + D);
H.height(C.height() + D);
}
// Create a callback after FF's addExtraLinks task to run the HIDE_SERVICE method.
if ('function' != typeof(unsafeWindow.origAddExtraLinks)) {
unsafeWindow.origAddExtraLinks = unsafeWindow.addExtraLinks;
unsafeWindow.addExtraLinks = function(B, C) {
// console.log("addExtraLinks: ",B, C);
unsafeWindow.origAddExtraLinks(B, C);
window.IDT_BYSERVICE_HIDE_SERVICE(B);
};
}
GM_addStyle('.idt-services .idt-promote { visibility:hidden; } .idt-services:hover .idt-promote { visibility:visible; } .popupmenu a { white-space:nowrap; } .popupmenu { margin-left: -70px; }');
function friendFeedByService() {
loadServicesFromGM();
var IDT_FF_SERVICES = [];
var IDT_FF_SERVICES_LOADING = 0;
var ff_by_service_promote = '<div class="idt-promote" style="padding-bottom: 0.5em;"><a title="Click to share Friend Feed By Service script with your friends" target="_blank" href="http://friendfeed.com/share?url=http://internetducttape.com/2008/04/10/friendfeed-scripts-unsubscribe-who-service/%23byservice&title=Add%20links%20to%20Friend%20Feed%20to%20filter%20by%20service">Click to share this script</a></div>';
function loadServicesFromGM() {
var now = new Date().getTime();
var ONE_DAY = 24 * 60 * 60 * 1000;
var lastChecked = GM_getValue('IDT_SERVICES_LAST_CHECKED', null);
if (lastChecked && (now - lastChecked) < ONE_DAY) {
// Less than a day, don't check
return;
}
else {
// More than a day, check for new services
GM_setValue('IDT_FF_SERVICES', ''); // Reset the services
GM_setValue('IDT_SERVICES_LAST_CHECKED', now.toString());
}
}
function loadServiceLinks() {
GM_xmlhttpRequest({url:'http://friendfeed.com/search/advanced',
method:"GET",
headers:{
"Content-Type": "application/x-www-form-urlencoded"},
data:'',
onload:function(xhr){
var services = [];
xhr.responseText.match(/option value="[^\"]+"/g).forEach(function(i) {
var service = i.split('"')[1];
if ('friendfeed' == service) {
service = 'internal';
}
services.push(service);
});
GM_setValue('IDT_FF_SERVICES', services.join(',') );
// console.log("got services ", services);
},
onerror:function(xhr){
alert("Unable to download service list from Friend Feed.");
}
});
}
function checkServices() {
IDT_FF_SERVICES = GM_getValue('IDT_FF_SERVICES', '').split(',');
// console.log("checkServices ", "loading: ", IDT_FF_SERVICES_LOADING, "length: ", IDT_FF_SERVICES.length);
if ((0 == IDT_FF_SERVICES_LOADING) && (1 == IDT_FF_SERVICES.length)) {
// console.log("loading services");
IDT_FF_SERVICES_LOADING = 1;
loadServiceLinks();
}
if ((1 == IDT_FF_SERVICES_LOADING) && (1 == IDT_FF_SERVICES.length)) {
// console.log("waiting for services ", IDT_FF_SERVICES_LOADING);
setTimeout(checkServices, 100);
}
else {
// console.log("have services ", IDT_FF_SERVICES);
window.IDT_FF_SERVICES = IDT_FF_SERVICES;
if ((document.location.pathname != '/') &&
(document.location.pathname != '/public')
) {
buildServiceFilterSidebar();
buildServiceClickHandler("")
}
else {
buildServiceLinks();
buildServiceClickHandler('style="position:fixed;"')
}
}
}
function buildServiceClickHandler(style) {
// Because I can never remember how setPopupMenu works.
// unsafeWindow.clickHandlers.options = function(B) { console.log("clickHandlers.options: ", B); }
// unsafeWindow.setPopupMenu = function(B, E) { console.log("setPopupMenu: ", B, E); };
// unsafeWindow.clickHandlers.idt_byservice = function(B) { console.log("clickHandlers.idt_byservice: ", B); }
unsafeWindow.clickHandlers.idt_byservice = function(B) {
var service = B.attr('service');
var D = [];
D.push({
l:"Filter by "+service,
attrs:{
'class':"noframe",
href:'?q=&service='+service+'&num='+unsafeWindow.gFeedArgs.num+'&who='
}
});
var pos = $.inArray(service, window.IDT_BYSERVICE_HIDE_LIST);
// Hide/Show is a toggle. One or the other shows depending on the current setting.
if (pos == -1) {
D.push({
l:"Hide "+service,
onclick:function() {
var pos = $.inArray(service, window.IDT_BYSERVICE_HIDE_LIST);
if (pos >= 0) { window.IDT_BYSERVICE_HIDE_LIST.splice(pos, 1); }
window.IDT_BYSERVICE_HIDE_LIST.push(service);
$('.cluster > .icon a[@href="?service='+service+'"]').parents('.cluster').hide();
window.idtUpdateHideBox();
}});
}
else {
D.push({
l:"Show "+service,
onclick:function() {
var pos = $.inArray(service, window.IDT_BYSERVICE_HIDE_LIST);
if (pos >= 0) { window.IDT_BYSERVICE_HIDE_LIST.splice(pos, 1); }
$('.cluster > .icon a[@href="?service='+service+'"]').parents('.cluster').show();
window.idtUpdateHideBox();
}});
}
// Hide everything always shows.
D.push({
l:"Hide everything<br /> but "+service,
onclick:function() {
// Copy all services
window.IDT_BYSERVICE_HIDE_LIST = window.IDT_FF_SERVICES.slice();
var pos = $.inArray(service, window.IDT_BYSERVICE_HIDE_LIST);
if (pos >= 0) { window.IDT_BYSERVICE_HIDE_LIST.splice(pos, 1); }
window.IDT_BYSERVICE_HIDE_LIST.forEach( function(s) {
$('.cluster > .icon a[@href="?service='+s+'"]').parents('.cluster').hide();
});
window.idtUpdateHideBox();
}});
window.IDT_BYSERVICE_SETPOPUPMENU(D, B, style);
};
}
function buildServiceLinks() {
var services = IDT_FF_SERVICES;
// &public=1
var extra_opts = '';
if ('/public' == document.location.pathname) {
extra_opts += '&public=1';
}
var text = '<div id="infobox" class="idt-services" style="position:fixed; right:0pt; top:250px; width:190px; z-index:1; }"><div class="rounded"><div class="t"><div class="l"><div class="r"><div class="b"><div class="bl"><div class="br"><div class="tl"><div class="tr"><div class="body"><div class="section"><h3>Filter By Service</h3>';
var num = '';
if (unsafeWindow.gFeedArgs) {
num = '&num='+unsafeWindow.gFeedArgs.num;
}
// #?q=&service='+s+extra_opts+num+'&who=
services.forEach(function(s) {
text += ' <a service="'+s+'" class="l_idt_byservice" title="'+s+'" href="#"><img height="16" width="16" src="http://friendfeed.com/static/images/icons/'+s+'.png" alt="'+s+'"/></a>';
}
);
// text += '</div>';
text += '<div id="idt-byservice-hidden"></div>';
text += ff_by_service_promote;
text += '</div></div></div></div></div></div></div></div></div></div></div></div>';
$('#body').prepend( text );
text = null;
window.idtUpdateHideBox();
};
function buildServiceFilterSidebar() {
var insert = '<div class="section idt-services"><h3>Filter By Service</h3>';
insert += '<a service="internal" class="l_idt_byservice" title="Filter by FriendFeed" href="#"><img width="16" height="16" alt="internal" src="http://friendfeed.com/static/images/icons/internal.png"/></a>';
var last = '';
$('.section img.icon[alt]').each( function(i) {
var alt = $(this).attr('alt');
if (last != alt) {
last = alt;
// ?q=&service='+alt.replace(/\./g,'').toLowerCase()+'&num='+unsafeWindow.gFeedArgs.num+'&who=
var s = alt.replace(/\./g,'').toLowerCase();
insert += '<a service="'+s+'" class="l_idt_byservice" title="Filter by '+alt+'" href="#">'+$(this).parent().html()+'</a>';
}
});
insert += '<div id="idt-byservice-hidden"></div>';
insert += ff_by_service_promote;
insert += '</div>';
$('.section:first').after(insert);
insert = null;
window.idtUpdateHideBox();
}
function addFilter(func, i) {
i = i || 4;
if (window.AutoPagerize && window.AutoPagerize.addFilter) {
window.AutoPagerize.addFilter(function (nodes) {
// Have to rebuild the click handler for every page for some reason.
// buildServiceClickHandler();
nodes.forEach(func);
});
}
else if (i > 1) {
setTimeout(arguments.callee, 1000, func, i - 1);
}
else {
(function () {
func(document);
setTimeout(arguments.callee, 200);
})();
}
}
function idtUpdateHideBox() {
function idtByServiceMakeUrl(s) {
return '<a service="'+s+'" class="l_idt_byservice" href="#">'+s+'</a>';
}
if (window.IDT_BYSERVICE_HIDE_LIST.length > 0) {
var permalink = document.location.href;
if (document.location.search == "") {
permalink += '?hide_service='+window.IDT_BYSERVICE_HIDE_LIST.join('-');
}
else {
permalink += '&hide_service='+window.IDT_BYSERVICE_HIDE_LIST.join('-');
}
$('#idt-byservice-hidden').html('<ul style="list-style: none; padding-left: 10px;"><li>Hiding: '+
window.IDT_BYSERVICE_HIDE_LIST.map(idtByServiceMakeUrl).join(', ')+
'</li><li>Save: <a title="Permalink to this page" href="'+
permalink+
'">Permalink</a></li></ul>'
);
}
else {
$('#idt-byservice-hidden').html(' ');
}
}
function hideByUrlParams() {
// Let users turn off services by command line urls.
document.location.search.split(/[\?&]/).forEach( function(param) {
var pair = param.split('=');
if (pair[0] == "hide_service") {
window.IDT_BYSERVICE_HIDE_LIST = pair[1].split('-');
}
});
window.IDT_BYSERVICE_HIDE_LIST.forEach(function(service) {
$('.cluster > .icon a[@href="?service='+service+'"]').parents('.cluster').hide();
});
window.idtUpdateHideBox();
}
// main
window.IDT_BYSERVICE_HIDE_LIST = window.IDT_BYSERVICE_HIDE_LIST || [];
window.idtUpdateHideBox = idtUpdateHideBox;
hideByUrlParams();
checkServices();
addFilter(window.IDT_BYSERVICE_HIDE_SERVICE);
};
function jquery_wait() {
if(typeof unsafeWindow.jQuery == 'undefined') { window.setTimeout(jquery_wait,100); }
else { $ = unsafeWindow.jQuery; friendFeedByService(); }
}
jquery_wait();
})();
function autoUpdateFromUserscriptsDotOrg(SCRIPT) {
// Update code from Junk Blocker: http://loonyone.livejournal.com/
// usage example
// autoUpdateFromUserscriptsDotOrg({
// name: 'RSS+Atom Feed Subscribe Button Generator',
// url: 'http://userscripts.org/scripts/source/688.user.js',
// version: "1.2",
// });
try {
if (!GM_getValue) return; // Older version of Greasemonkey. Can't run.
// avoid a flood of dialogs e.g. when opening a browser with multiple tabs set to homepage
// and a script with * includes or opening a tabgrop
var DoS_PREVENTION_TIME = 2 * 60 * 1000;
var isSomeoneChecking = GM_getValue('CHECKING', null);
var now = new Date().getTime();
GM_setValue('CHECKING', now.toString());
if (isSomeoneChecking && (now - isSomeoneChecking) < DoS_PREVENTION_TIME) return;
// check daily
var ONE_DAY = 24 * 60 * 60 * 1000;
var ONE_WEEK = 7 * ONE_DAY;
var TWO_WEEKS = 2 * ONE_WEEK;
var lastChecked = GM_getValue('LAST_CHECKED', null);
if (lastChecked && (now - lastChecked) < TWO_WEEKS) return;
GM_xmlhttpRequest({
method: 'GET',
url: SCRIPT.url + '?source', // don't increase the 'installed' count just for update checks
onload: function(result) {
if (!result.responseText.match(/@version\s+([\d.]+)/)) return; // did not find a suitable version header
var theOtherVersion = parseFloat(RegExp.$1);
if (theOtherVersion <= parseFloat(SCRIPT.version)) return; // no updates or older version on userscripts.orge site
if (window.confirm('A new version ' + theOtherVersion + ' of greasemonkey script "' + SCRIPT.name + '" is available.\nYour installed version is ' + SCRIPT.version + ' .\n\nUpdate now?\n')) {
GM_openInTab(SCRIPT.url); // better than location.replace as doing so might lose unsaved data
}
}
});
GM_setValue('LAST_CHECKED', now.toString());
} catch (ex) {
}
}