By Junk Blocker
—
Last update
Jul 8, 2007
—
Installed
62,772 times.
// ==UserScript==
// @name RSS+Atom Feed Subscribe Button Generator
// @description Finds RSS and/or Atom links on a page and inserts feed subscription links for use by aggregators
// @namespace http://loonyone.livejournal.com
// @include *
// @creator Manpreet Singh [junkblocker@yahoo.com]
// @source http://userscripts.org/scripts/show/688
// @identifier http://userscripts.org/scripts/source/688.user.js
// @version 1.6
// @date 2007-07-08
// ==/UserScript==
/*
* Copyright (c) 2006-2007, Manpreet Singh [junkblocker@yahoo.com]
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
// ******
// Opera and IE7Pro compatible except
//
// 1) the auto update feature works only on firefox
// 2) link tags injection does not work in IE7Pro
//
// due to non-firefox platform limitations/differences.
//
// IE7Pro bundles an older version of this script by default.
// ******
// Version 1.6 - Insert discovered link tags in header for the browser's detection to list them too
// Version 1.5 - Added license info
// Added checks for feeds like &feed=rss or &feed=atom and some case insensitivity
// Version 1.4 - Made the feed check slightly more stringent by excludeing javascript: mailto: etc. urls
// Version 1.3 - Reduce the number of button shown initially to a sane minimum
// Version 1.2 - Fixed partially broken auto update.
// Don't increase the install count on userscripts.org while checking for updates
// Version 1.1 - Misc code cleanup
// Version 1.0 - Added auto update without requiring an external script
// Version 0.9 - Added a close button
// Version 0.8 - Checks some wiki feeds with ?action=rss_rc and feeds with /rss/$ or /atom/$
// Version 0.7 - Check for feedburner feeds
// Version 0.6 - Fixed a major issue with using snapshotLength when it was not available
// Version 0.5 - Updated contact info
// Version 0.4 - Added optional auto-update facility
// Version 0.3 - Added some speed optimizations
// Version 0.2 - Merged Iain Brodfoot's floating div behaviour and removed purl.org links
// - Allow revert to old behaviour by hand editing this script
// Version 0.1 - First release
/*
* Options contribution by Iain Broadfoot (ibroadfo@geeksoc.org)
* - remove link to purl
* (Manually edit this script to restore old behaviour. See TWEAK NOTE 1 below)
* - Float the buttons to enable better behaviour on blogger/blogspot.com
* (Manually edit this script to restore old behaviour. See TWEAK NOTE 2 below)
*
* Initially lifted mostly from
* Generate RSS and ATOM tags: http://highbyte.bounceme.net/greasemonkey/genrsslinkrel.user.js
* Amazon Atom Injector: http://docs.g-blog.net/code/greasemonkey/amazon_xml_feeds.user.js
* Add RSS Index: http://www.xs4all.nl/~jlpoutre/BoT/Javascript/RSSpanel/rsspanel.user.js
*
* Original buttons from the excellent: http://kalsey.com/tools/buttonmaker/
*/
(function() {
function autoUpdateFromUserscriptsDotOrg(SCRIPT) {
// Note: Version numbers must be in x.y float format
try {
if (!GM_getValue) return;
// avoid a flood of dialogs e.g. when opening a browser with multiple tabs set to homepage and a script with * includes
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;
var lastChecked = GM_getValue('LAST_CHECKED', null);
var ONE_DAY = 24 * 60 * 60 * 1000;
if (lastChecked && (now - lastChecked) < ONE_DAY) return;
GM_xmlhttpRequest({
method: 'GET',
url: SCRIPT.url + '?source', // don't increase the 'installed' count just for checking
onload: function(result) {
if (!result.responseText.match(/@version\s+([\d.]+)/)) return;
var theOtherVersion = parseFloat(RegExp.$1);
if (theOtherVersion <= parseFloat(SCRIPT.version)) return;
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);
}
}
});
GM_setValue('LAST_CHECKED', now.toString());
} catch (ex) {
}
}
autoUpdateFromUserscriptsDotOrg({
name: 'RSS+Atom Feed Subscribe Button Generator',
url: 'http://userscripts.org/scripts/source/688.user.js',
version: '1.6'
});
var head = document.getElementsByTagName('head');
if (head && head[0]) head = head[0];
var INITIAL_COUNT = 5;
var ATOM_ICON = '<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAAAPCAMAAAEzEIgrAAAAwFBMVEUiIiKZmZlmZmaIiIi7u7vMzMwzMzP5+fkRERHu7u6Wlpb9/f3KyspVVVXGxsb7+/t3d3fPz8/S0tLDw8P8/Py9vb2xsbG+vr6rq6u/v79ERETl5eXKq6vFxcXb29txcXGpqamysrLOzs6zu+J+fn4eHh56enoDHH7W1tb01NS3t7dSUlKrtN7ExMSzs7OapdXHx8e6urrLy8vAwMDHpaXMlZWstd/Jycm1veSurq6YmJibptXIyMgAAACIjXj///+BJyE6AAABVklEQVQ4y52T6VLbMBRGryRvIWSBhL0t0FL2rWXt8um8/1vxQ44xwemEfuOxRpqjoyvZMjUxBT1LMRKtNYqdI4gxmhACrKiIdUwA03WA1mBHjGDV4BdZ4RsSQ3LAMThiJEYiBgBf207SQoCA9TXO6m6zaBt0qBgr+wHfOFKmIMdMXz8JlKxCAthyQiRw3rhklgfr2oMHNkruu/cSZYDJZxJsAt+DcoVuMB8H9bTLNpegQrrQHEgCd4WQ/wk3DOXNVhaAmUwU+gLk/U5wVmPKDqOtptMBLn+OzGW1bkerG5O/nx74WOaFTvIAXG+XSb/3dkL8d2bCIFUmjV39TQ836/m/W5vpNcLUvn+/CnuDKqmc5BkdlPB48gf6+5LHZKyk+7JQmP7tRmhS8JKRSxqclnV9+cR1CxdoX4WQ9WaSbG8IwPTqc//9oS95hm+ztvN0ezcs+Z/oBckmBmW7bigcAAAAAElFTkSuQmCC" style="border:none;" />';
var RSS_ICON = '<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAAAPCAIAAAD8q9/YAAAA5ElEQVR4nOVWMQ7DIAw8V/krc5YMfUCGLp15LR1IHAvb0EopDNwEhzE+bAuAyUAAUkqjw+gEIlqOYaAb/MX0ej9v8PMfbOsO4DE6jN6YTvBSEvHsZ1nkmjTNBHL9AMhFvq27HkgDcxczxbRgPIfmEUowa4ipHEj91Z7nIOrw7kL7kUuesbmkbSzBOXssKVCbUQcXmTHBGWju0lVgei4cmsZWD2sZgS6RHqNCZAF1m292SaZyiZ5DyVgZxplDLmkmM35sYDjZa/anl/PMa+XNI3B9POZ4h4loumdpOsHT/aVHh9AdH916sSoQOJxpAAAAAElFTkSuQmCC" style="border:none;" />';
var RDF_ICON = '<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAAAPCAIAAAD8q9/YAAAA40lEQVR4nOVWoRbDIAy87PVf0TUVfEAFBs3XMsFGGUkA0RXBqfYIIUcSAFgMBCDGODuMh0BE2+fT0A3+QnTe3uDnPzj2E8BrdhhPYznBW02Ebz/nIh9hGFL9AEhFfuwn/ygNxFmZqX4rRnMoLsEEZxkhXno0Rlc70szaXnA/5ZBmLA5xG0lwSmD7GGvaOG+rzIjIGejO4lUgeq4cisZSD4+c2IbaZs7bLKBtMzKrZBqbqDksGSnDAAz9FPBIzqX4ytLim93tTy3niefKu0vgeniscQ8T0XLX0nKCl3tLzw7hcbwB232nKlQYcjEAAAAASUVORK5CYII=" style="border:none;" />';
var XML_ICON = '<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAAAPCAIAAAD8q9/YAAAA3klEQVR4nOVWuxKEIAzc3Piv1jYWfoCFjbVfyxU4EfMAbsaTgq1wCSGbBAHoDAQghNA6jJdARMM5HOkBf0fY9uUBP//BPK0APq3DeBvdCR4kcYSrvXlcJBVi/wCITT5Pqx6kBuYqZsSnYDyH5hZK8EinEqGHyQpwEHl4udB+0inP2JzSNkowYKjFPREVSkRlTHAFiqt0F5iehUPT2DrDnrBf/uTbvrCAvE3NqpTJJNFzmDL+GTbrrI1hJEIfHrN6xfPp1TzyWnlxC1wPjz7uYSLq7lrqTnB3b+nWIbyOLwOWtSLcWFU8AAAAAElFTkSuQmCC" style="border:none;" />';
var CLOSE_ICON = '<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAScwAAEnMBjCK5BwAAABh0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjA1G8PgXAAAAFRJREFUOE9jZGBg+A/EZIP/5ACYpRC9aQzEY6ByGmjG5Qpkcbw2oxuAhY/f2TAN2FxClJ/xeIFGNpPtZ4pDm1CCISrAcBmCoZnEBA4PbSgDll6JpgF1Tx8yB8tBWgAAAABJRU5ErkJggg==" style="border:none;" />';
var MORE_ICON = '<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAPCAIAAAAZNRq0AAAA20lEQVR42sWVsRKCMAyG/3B14j2pq4uD7g46MPdBO+FdHCgKTVIr3EmmNJfm6x9oSl3XYQ9zAEIIf6Z6711yjwSewoSPX2/Trnho2yEi8KO/slbofLoBaNJqnsCb1LRDnMqUCjVbu0biuKToqwAHNn25DDNVMlJka4pHQIbxBE+LoBXRTLI18FjOKJGLnqdlXSmyjW/8larm2IoB3PvL7z/X2APZhqzVtuKMmgaIqePtExSk5YgxIKlLxYXu8qp7ZVOXYF51fcX2Z+NqZ3V+ebZP/+LoSCff63V6AapbYVL3XNKNAAAAAElFTkSuQmCC" style="border:none;" />';
// array to keep track of 'seen' feed links.
var seen = [];
var fsbdiv = document.createElement("div");
fsbdiv.setAttribute("id", "XmlButtons");
with (fsbdiv.style) {
textAlign = "left";
margin = "0px";
// top right bottom left
padding = "0px 3px 0px 3px";
// TWEAK NOTE 1 START: Comment out the next three lines to disable the buttons from floating
position = "fixed";
top = "0px";
zIndex = "99999";
// TWEAK NOTE 1 END
}
// Get links already declared properly in <link> elements in <head>
function getKnownTags() {
var linkRelElems = document.getElementsByTagName("link");
var tlink;
var i = 0;
while (tlink = linkRelElems[i++]) {
var thref = tlink.href;
var type = tlink.type;
if (type && type.match(/.*\/rs[sd](\+xml)?$/i)) {
addRssLinkTag(thref, RSS_ICON);
} else if (type && type.match(/.*\/atom\+xml$/i)) {
addRssLinkTag(thref, ATOM_ICON);
} else if (type && type.match(/^text\/xml$/i)) {
addRssLinkTag(thref, RSS_ICON);
}
}
}
function discoverUnknownFeeds() {
if( !document.links ) {
document.links = document.getElementsByTagName("a");
}
var links = document.links;
for (var a = 0, len = links.length; a < len ; a++) {
var link = links[a];
linkhref = link.href;
if (linkhref.match(/^rss:/)
|| linkhref.match(/^(http|ftp|feed).*([\.\/]rss([\.\/]xml|\.aspx|\.jsp|\/)?$|\/node\/feed$|\/rss\/[a-z0-9]+$|[?&;](rss|xml|rdf)=|[?&;]feed=rss[0-9.]*$|[?&;]action=rss_rc$|feeds\.feedburner\.com\/[a-z0-9]+$)/i)) {
addRssLinkTag(linkhref, RSS_ICON, "rss");
} else if (linkhref.match(/^(http|ftp|feed).*\/atom(\.xml|\.aspx|\.jsp|\/)?$|[?&;]feed=atom[0-9.]*$/i)) {
addRssLinkTag(linkhref, ATOM_ICON, "atom");
} else if (linkhref.match(/^(http|ftp|feed).*(\/feeds?\/[^.\/]*\.xml$|.*\/index\.xml$|feed\/msgs\.xml(\?num=\d+)?$)/i)) {
addRssLinkTag(linkhref, XML_ICON, "rss");
} else if (linkhref.match(/^(http|ftp|feed).*\.rdf$/i)) {
addRssLinkTag(linkhref, RDF_ICON, "rss");
} else if (linkhref.match(/^feed:\/\//i)) {
addRssLinkTag(linkhref, RSS_ICON, "rss");
}
}
}
function beenThere(linkhref) {
if (seen.length <= 0) return false;
var href = linkhref.toLowerCase();
for (var i = seen.length-1; i >=0; --i) {
if (seen[i].toLowerCase() == href) return true;
}
return false;
}
function addRssLinkTag(linkhref, icon, addheadtype) {
if (beenThere(linkhref)) {
return;
} else {
seen.push(linkhref);
}
if (seen.length == (INITIAL_COUNT + 1)) {
var moreButton = document.createElement('a');
moreButton.innerHTML = MORE_ICON;
moreButton.href = 'javascript: moreFSB();';
moreButton.style.display = 'inline';
moreButton.style.cursor = 'pointer';
moreButton.id = 'MoreFSBButton';
fsbdiv.appendChild(moreButton);
fsbdiv.appendChild(document.createTextNode(" "));
}
var flink = document.createElement("a");
with (flink) {
innerHTML = icon;
href = linkhref;
// TWEAK NOTE 2 START : Uncomment the href line below to retore linking
// to purl.org pages for easy subscription in feed readers. This service
// creates link for all known aggregators which support RSS subscription
// service via a URL.
// href = "http://purl.org/net/syndication/subscribe/?rss=" + linkhref;
// TWEAK NOTE 2 END
alt = linkhref;
title = linkhref;
id = 'XmlButton' + seen.length;
}
if (seen.length >= (INITIAL_COUNT + 1)) {
flink.style.display = 'none';
}
fsbdiv.appendChild(flink);
fsbdiv.appendChild(document.createTextNode(" "));
// <link href="url" rel="alternate" title="desc" type="application/rss+xml" />
if (addheadtype && head) {
var link = document.createElement("link");
link.href=linkhref;
link.rel="alternate";
link.title=linkhref + " (discovered by RSS+Atom Feed Subscribe Button Generator)";
link.type="application/" + addheadtype + "+xml";
head.appendChild(link)
}
}
getKnownTags();
discoverUnknownFeeds();
var body = document.getElementsByTagName("body")[0];
// insert the div only if something was found
if (seen.length > 0) {
if (head) {
var closeButton = document.createElement('a');
closeButton.innerHTML = CLOSE_ICON;
closeButton.href = 'javascript: closeFSB();';
closeButton.style.display = 'inline';
closeButton.style.cursor = 'pointer';
var s = document.createElement('script');
s.language='javascript';
s.type = 'text/javascript';
s.text = 'function closeFSB(){try{document.getElementById("XmlButtons").style.display="none"}catch(e){}}';
head.appendChild(s);
var sm = document.createElement('script');
sm.language='javascript';
sm.type = 'text/javascript';
sm.text = 'function moreFSB(){for (var i=' + (INITIAL_COUNT + 1) + ';i<=' + seen.length + ';i++){try {document.getElementById("XmlButton" + i).style.display="inline"}catch(e){}}document.getElementById("MoreFSBButton").style.display="none";}';
head.appendChild(sm);
}
fsbdiv.insertBefore(closeButton, fsbdiv.firstChild);
setTimeout(function() {
body.insertBefore(fsbdiv, body.firstChild);
}, 333); // hack to workaround the duplicated content problem
}
})();