User:GregU/randomlink.js

// Travel to a random page linked in the article or listed on a special page. // See talk page for documentation. Greg Ubben

//randomlink_start  = [ "Wikipedia:Featured articles", "Wikipedia:Featured pictures" ]; //randomlink_hops   = 2; //randomlink_exclude = /^List of/; //randomlink_paged  = true;        // cats > 200 entries or multi-paged lists //randomlink_open   = true;        // if you want to open in new windows //randomlink_debug  = true;        // set this, to debug randomlink_maxfrom  = 22000000;    // 10-20% less than max page id randomlink_maxoffset = 950;         // en.wikipedia is limited to 1000

function scrapeLinks( descend ) {   var topnode = document.getElementById('bodyContent') || document; var node   = document.getElementById('mw-subcategories'); var atags  = []; var links  = []; var nspat  = /^(Talk|User|Wik\w+|File|MediaWiki|Template|Help|Category|Portal|Book)( talk)?:/i;

var spec = getElementsByClassName(topnode, 'div', 'mw-spcontent'); if (spec.length == 1) topnode = spec[0];      // skip help links at top of specials

if (node && descend) topnode = node;          // pick a sub-category else for (var id in {'mw-pages':0, 'mw-category-media':0 }) { node = document.getElementById( id ); if (node) { var nodelist = node.getElementsByTagName('a'); for (var i=0; i < nodelist.length; i++) atags.push( nodelist[i] ); }       }

if (atags.length == 0) atags = topnode.getElementsByTagName('a');

nextlink: for (var i=0; i < atags.length; i++) { var link = atags[i]; var href = link.href; var title = link.title;

if (!href)                                // needed? continue; if (link.className.search(/\b(external|internal|extiw|image)\b/) >= 0) continue; if (href.search(/\/Special:|\?(?!.*redirect=|.*from=.*to=)/) >= 0) continue; if (mw.config.get('wgIsArticle') && mw.config.get('wgNamespaceNumber') != 14 && title.search(/^(Category|File):|^$|^#/) >= 0) continue; if (mw.config.get('wgIsArticle') && mw.config.get('wgNamespaceNumber') == 0 && title.search(nspat) >= 0) continue; if ((mw.config.get('wgAction') == "history") != hasClass(link, "mw-userlink")) continue; if (link.hostname != location.hostname)   // commons.wikimedia.org on images continue; if (link.parentNode.id == "coordinates") continue;                             // coords too common, or help link if (typeof randomlink_exclude != "undefined" && title.search(randomlink_exclude) >= 0) continue;

// Exclude message boxes and the Metadata section on Image pages. // And also mw-usertool links and comments in page listings. // And also top links on Recent changes and watchlists. //       for (var n = link.parentNode; n != topnode; n = n.parentNode) { if (n.id.search(/^mw-watchlist-options|^recentchangestext/) >= 0) continue nextlink; if (n.className.search(/\b(usertool|summary|metadata|.mbox|comment|warn)/) >= 0) continue nextlink; }       links.push( link ); }

while (links.length && links[0].parentNode.id.search( /contentSub|jump-to|target/i ) >= 0) links.shift;                                 // breadcrumb links

if (links.length && links[0].title == "Wikipedia:FAQ/Categories") links.shift;                                 // "learn more" link in cats

return links; }

function randomLink( links, hops ) {   var continuing = (typeof links == "object" && links == null);

if (typeof links == "undefined" && typeof randomlink_start != "undefined") links = randomlink_start;

if (typeof hops == "undefined" && typeof randomlink_hops != "undefined") hops = randomlink_hops;

if (typeof hops == "undefined") hops = 1;

if (hops > 4)      // sanity check; 4 needed for Special:AllPages hops = 4;

if (typeof links == "string" &&       links.search(/^Special:(WhatLinksHere|RecentChangesLinked)$/i) >= 0) {       links += "/" + mw.config.get('wgPageName') + "?limit=250"; if (mw.config.get('wgNamespaceNumber') == 0) links += "&namespace=0";   // stay in article space if in it now }

// Random contrib: Toggles between user, page, user, page, ... //   if (typeof links == "string" && links == "Special:Contributions") if (mw.config.get('wgPageName').search(/^User:[^\/]+$/) >= 0) links += "/" + mw.config.get('wgPageName').slice(5) + "?namespace=0"; else links = mw.config.get('wgPageName') + "?action=history";

if (typeof links == "string") links = links.split("|");

if (typeof links == "object" && links != null) { for (var i=0; i < links.length; i++) links[i] = mw.config.get('wgArticlePath').replace("$1", links[i]).replace(/ /g, "_"); hops++; }   else { links = scrapeLinks( hops > 1 ); }

if (typeof randomlink_debug != "undefined" && randomlink_debug) { var msg = links.slice(0); if (msg.length > 36) msg.splice( 20, msg.length-35, "..." ); alert( links.length + " links:\n  " + msg.join("\n   ")); }

if (links.length == 0) return alert("I am unable to comply.");

var newpage = links[ Math.floor(links.length * Math.random) ].toString;

if (typeof randomlink_paged != "undefined" && randomlink_paged) newpage = pagedUrl( newpage );

if (mw.config.get('wgCanonicalNamespace') == "Category" && newpage.indexOf("/Category:") == -1) hops = 1;

if (--hops > 0) { newpage += (newpage.indexOf("?") >= 0) ? "&" : "?";       newpage += "random_hops=" + hops; }

// WikiProjects organize by talk pages, but let's end on the subject page. //   if ((mw.config.get('wgCanonicalNamespace') == "Category" || mw.config.get('wgCanonicalSpecialPageName') == "Whatlinkshere")             && continuing && hops <= 0) newpage = newpage.replace("/Talk:", "/").replace("_talk:", ":");

if (typeof randomlink_open != "undefined" && randomlink_open && !continuing) window.open( newpage ); else window.location = newpage; }

function pagedUrl( url ) {   var param = ""; var value; var alphabet = "!abcdefghijklmnoprstuvwy~";

if (url.indexOf("/Category:") >= 0) { value = alphabet.charAt(alphabet.length * Math.random).toUpperCase + alphabet.charAt(alphabet.length * Math.random); param = (value < "M" ? "from" : "until"); }   if (url.indexOf("Special:WhatLinksHere") >= 0) { param = "from"; value = Math.floor( randomlink_maxfrom * Math.random ); // Clustering will hurt randomness, but better than nothing }   if (url.search(/Special:\w+s\b/) >= 0) { param = "offset"; value = Math.floor( randomlink_maxoffset * Math.random ); }   if (param) { url += (url.indexOf("?") >= 0) ? "&" : "?";       url += param + "=" + encodeURIComponent(value); }   return url; }

addOnloadHook( function {   var hops = document.URL.match( /[?&]random_hops=(\d+)/ );    if (hops)  randomLink( null, hops[1] );

var where = 'this page'; if (typeof randomlink_start != 'undefined') where = randomlink_start.toString.slice(0,500);

mw.util.addPortletLink('p-navigation', 'javascript:randomLink', 'Random link',                  'n-randomlink', 'Follow a randomly chosen link on ' + where, '@'); });