Misplaced Pages

User:Lupin/popups.js: Difference between revisions

Article snapshot taken from Wikipedia with creative commons attribution-sharealike license. Give it a read and then ask your questions in the chat. We can research this topic together.
< User:Lupin Browse history interactively← Previous editContent deleted Content added
Revision as of 16:09, 11 September 2005 view sourceLupin (talk | contribs)19,513 edits fix block links, hopefully← Previous edit Latest revision as of 14:34, 9 February 2021 view source Xaosflux (talk | contribs)Edit filter managers, Autopatrolled, Bureaucrats, Importers, Interface administrators, Oversighters, Administrators83,870 edits expand directions 
(61 intermediate revisions by 17 users not shown)
Line 1: Line 1:
var popScript = '//en.wikipedia.org/search/?action=raw&ctype=text/javascript&title=MediaWiki:Gadget-popups.js';
var popupVersion="Sat Sep 10 10:18:44 EDT 2005 bugfix(1)";
var popStyleSheet = '//en.wikipedia.org/search/?action=raw&ctype=text/css&title=MediaWiki:Gadget-navpop.css';
// CONTENTS
if ( window.localCSS ) { popStyleSheet = 'http://localhost:8080/js/navpop.css'; }


function popups_importScriptURI(url) {
// Utility functions
var s = document.createElement('script');

s.setAttribute('src',url);
// Popup stuff
s.setAttribute('type','text/javascript');
// global variables
document.getElementsByTagName('head').appendChild(s);
// html generation
return s;
// downloading
// link generation
// manipulation functions
// tests
// actions
// thingies

////////////////////////////////////////////////////////////////////
// Utility functions
////////////////////////////////////////////////////////////////////

function time() {
var d=new Date();
return d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds() +
'.' + (d.getTime() % 1000);
};

var gMsg='';
function log(x) { if(gMsg!='')gMsg += '\n'; gMsg+=time() + ' ' + x; };

function myalert(x) { return alert(time()+'\n'+ x); };


// eg sourceJS('http://www.bosrup.com/web/overlib/overlib.js');

function sourceJS(url) {
var str='<script type="text/javascript" src="';
str += url;
str += '"></script>';
return document.write(str);
};

// eg sourceWikipediaJS('en.wikipedia.org', 'User:Lupin/overlib.js');

function sourceWikipediaJS(wiki, name) {
var url='http://' + wiki + '/search/?title=';
url += name;
url += '&action=raw&ctype=text/javascript&dontcountme=s';
return sourceJS(url);
};

// eg sourceLupinJS('overlib');

function sourceLupinJS(name) {
return sourceWikipediaJS('en.wikipedia.org', 'User:Lupin/'+name + '.js');
};

////////////////////////////////////////////////////////////////////
// Popup stuff
////////////////////////////////////////////////////////////////////

sourceLupinJS('livepreview');
sourceLupinJS('overlib');
sourceLupinJS('md5-2.2alpha');

// livepreview uses a broken hex_md5 function, so we avoid it
function md5_hex(s) { return rstr2hex(rstr_md5(str2rstr_utf8(s))); };

//////////////////////
// GLOBAL VARIABLES //
//////////////////////

// regexes

var exceptions=RegExp('((title=|/)Special:|section=)') ;
var contributions=RegExp('(title=|/)Special:Contributions(&target=|/|/User:)(.*)') ;
var emailuser= RegExp('(title=|/)Special:Emailuser' +'(&target=|/|/User:)(.*)') ;
var talk=RegExp('Talk:', 'i') ;

// (^|\]* ]) *
// (^|\]* ])(]*(+) *px)?
// $4 = 120 as in 120px
var imageRegex= RegExp('(^|\\]* ])(]*(+) *px)?',
'img') ;
var imageRegexBracketCount = 4;

var categoryRegex= RegExp('\\]* ]) *', 'i') ;
var categoryRegexBracketCount = 1;

var stubRegex= RegExp('stub|This .*-related article is a .*stub', 'im') ;
var disambigRegex=
RegExp('(disambig|disambig|dab)' +
'|is a .*disambiguation.*page', 'im') ;

var ipUserRegex=RegExp('(User:)?' +
'((25|2|1||)\\.){3}' +
'(25|2|1||)');

var oldidRegex=RegExp('oldid=(*)');

var splitLoc=window.location.href.split('/');
var thisWiki=splitLoc;
var wikimediaWiki=RegExp('wikiedia\.org').test(thisWiki);
var protocol=splitLoc.split(':');

var titletail='/index.php?title=';
if (wikimediaWiki) titletail = '/w' + titletail;


// /REGEX

// we're not set up for interwiki stuff yet - only affect en, commons
// and wiktionary links

var reStart='*://';
var preTitles='wiki/|w/index\\.php\\?title=';
if (!wikimediaWiki) preTitles += '|index\\.php\\?title=';
var reEnd='/(' + preTitles + ')(*)';
var re = RegExp(reStart + thisWiki.split('.').join('\\.') + reEnd);

var titlebase=protocol+'://'+thisWiki+titletail;
var wikibase=protocol+'://'+thisWiki+'/';

var popupImagesToggleSize=true;
var popupImageSize=60;

var imageSources=new Array ();
imageSources.push(
{active: false, wiki: thisWiki, thumb: true, width: popupImageSize},
{active: false, wiki: thisWiki, thumb: true, width: 180}, // default
{active: false, wiki: thisWiki, thumb: true, width: 120}, // gallery
{active: false, wiki: thisWiki, thumb: true, width: 200}, // common?
{active: false, wiki: thisWiki, thumb: true, width: 210},
{active: false, wiki: thisWiki, thumb: true, width: 230},
{active: false, wiki: thisWiki, thumb: true, width: 250}, // common?
{active: false, wiki: thisWiki, thumb: true, width: 300},
{active: false, wiki: thisWiki, thumb: false, width: 0} // no comma
);
if (wikimediaWiki && thisWiki!='commons.wikimedia.org') {
imageSources.push(
{active: false, wiki: 'commons.wikimedia.org',
thumb: true, width: popupImageSize},
{active: false, wiki: 'commons.wikimedia.org',
thumb: true, width: 180},
{active: false, wiki: 'commons.wikimedia.org',
thumb: true, width: 120},
{active: false, wiki: 'commons.wikimedia.org',
thumb: false, width: 0} // no trailing comma
);
} }


function popups_importStylesheetURI(url) {
// downloading images are put here
return document.createStyleSheet ? document.createStyleSheet(url) : popups_appendCSS('@import "' + url + '";');
var imageArray=new Array();

// page caching
var gCachedPages = new Array ();
var gImageCache = new Array();
// FIXME what is this for?
var gImage=null; // global for image

// check to see if images are done with this timer
var popupImageTimer=null;

// misc debug messages
var popupDebug=null;

// These are for checkImages()
var counter=0;
var checkImagesTimer=null;
var loopcounter=0;

// ids change with each popup: popupImage0, popupImage1 etc
var popupImageId=0;

var kateBase='http://kohl.wikimedia.org/~kate/cgi-bin/count_edits'
+ '?dbname='

switch(thisWiki) {
case 'commons.wikimedia.org': kateBase += 'commonswiki';
break;
case 'en.wiktionary.org': kateBase += 'enwiktionary';
break;
default: kateBase += 'enwiki';
} }


function popups_appendCSS(text) {
kateBase += '&user=';
var s = document.createElement('style');

s.type = 'text/css';
// for myDecodeURI
s.rel = 'stylesheet';
var decodeExtras = new Array ();
if (s.styleSheet) s.styleSheet.cssText = text //IE
decodeExtras.push (
else s.appendChild(document.createTextNode(text + '')) //Safari sometimes borks on null
{from: '%2C', to: ',' },
document.getElementsByTagName('head').appendChild(s);
{from: '_', to: ' ' },
return s;
{from: '%26', to: '&' } // no ,
);

// for setPopupHTML - needed for timers and stuff
var popupHTMLTimers=new Array();
var popupHTMLLoopFunctions = new Array();

// FIXME - eliminate this
var redirCount=0;


// options

// this should expand to something like
// if (window.foo===null) window.foo=window.dfoo;
function defaultize(x) {
var a='window.'+x;
var b='window.d'+x;
eval('if ('+a+'===null) '+a+'=' + b + ';');
};

// this should expand to something like
// if (typeof window.foo=='undefined') { window.foo=null; }; window.dfoo = 0.5;
function newOption(x, def) {
var a='window.' + x;
var b='window.d' + x;
eval('if (typeof '+ a + '==\'undefined\') {' + a + '=null; }; ' +
b + '=' + def + ';');
};

// user-settable parameters and defaults
newOption('popupDelay', 0.5);
newOption('popupFgColor', "'#CCCCFF'");
newOption('popupBgColor', "'#333399'");
newOption('removeTitles', true);
newOption('imagePopupsForImages', true);
newOption('popupSummaryData', true);
newOption('simplePopups', false);
newOption('popupAdminLinks', false);
newOption('popupImages', true);
newOption('popupPreviews', true);
newOption('maxPreviewSentences', 4);
newOption('maxPreviewCharacters', 600);
newOption('popupNavLinks', true);
newOption('popupNavLinkSeparator', "' &sdot; '");
newOption('popupOnlyArticleLinks', true);
newOption('popupNeverGetThumbs', false);
newOption('popupImagesFromThisWikiOnly', false);
newOption('popupAppendRedirNavLinks', true);
newOption('popupMaxWidth', 300);
newOption('popupSimplifyMainLink', true);
newOption('popupMinImageWidth', 50);


// browser-specific hacks

// if (typeof window.opera != 'undefined') {}

if ((self.navigator.appName)=='Konqueror') {
dpopupNavLinkSeparator=' &bull; ';
} else if ((self.navigator.appName).indexOf("Microsoft")!=-1) {
dpopupNavLinkSeparator=' &#183; ';
} }


popups_importStylesheetURI(popStyleSheet);
// String.prototype.parenSplit should do what ECMAscript says
popups_importScriptURI(popScript);
// String.prototype.split does, interspersing paren matches between
// the split elements


if (String('abc'.split(/(b)/))!='a,b,c') { if ( typeof mw !== 'undefined' ) {
mw.loader.using( , function() {
// broken String.split, e.g. konq, IE
var k = 'User:Lupin/popups.js',
String.prototype.parenSplit=function (re) {
t = 'Information: You are importing User:Lupin/popups.js' +
var m=re.exec(this);
' into your User:USERNAME/common.js or User:USERNAME/<skin>.js!\n' +
if (!m) return ;
'This script is unmaintained. Please remove this inclusion and enable the Navigation popups Gadget in the preferences of your account instead.',
// without this, we have
x = mw.storage.get( k );
// 'ab'.parenSplit(/a|(b)/) != 'ab'.split(/a|(b)/)
for(var i=0; i<m.length; ++i) {
if (typeof m=='undefined') m='';
}
return
.concat(m.slice(1))
.concat(this.substring(m.index+m.length).parenSplit(re));
};
} else {
String.prototype.parenSplit=function (re) {return this.split(re);};
}


if ( !x ) {
/////////////////////
mw.storage.set( k, 1 );
// HTML GENERATION //
alert( t );
/////////////////////
} else {

x++;
// generate html for popup image
mw.storage.set( k, x );
// <a id="popupImageLinkn"><img id="popupImagen">
if ( x % 25 === 0 ) {
// where n=popupImageId
mw.notify( t );
function imageHTML(article) {
}
var ret='';
}
popupImageId++;
});
ret += '<a id="popupImageLink' + popupImageId + '">';
ret += '<img align="right" valign="top" id="popupImage' + popupImageId + '" '
+ 'style="display: none;"></img>';
ret += '</a>';
return ret;
};

function isInToc(a) {
return isSubElementOf(a,'toc');
};

function isInArticle(a) {
// content is for monobook.. damn. was hoping to avoid skin references
if (document.getElementById('article')) return isSubElementOf(a, 'article');
else return isSubElementOf(a, 'content');
};

function isSubElementOf(a, tag) {
var obj = a;
var i=0;
// this may well slow things down when this function is iterated
// would perhaps be more efficient to cache this result before the
// function is called. or maybe the browser does that magically anyway
var tagged=document.getElementById(tag);
if (!tagged) return false;

do {obj = obj.parentNode; ++i; }
while (obj != tagged && obj.nodeName != 'HTML');

if (obj.nodeName == 'HTML') return false;
return true;
};

function articleFromAnchor(a) {
// log('articleFromAnchor');
var h=a.href;
var article=null;
// log('h='+h);

var contribs=contributions.exec(h);
if (contribs != null) {
article='User:'+contribs;
return article;
}
var email=emailuser.exec(h);
if (email != null) {
article='User:'+email;
return article;
}

// no more special cases to check --
// hopefully it's not a disguised user-related page

var m=re.exec(h);
if(m===null) return null;
article=m;
return article;
};

function oldidFromAnchor(a) {
// log('oldidFromAnchor');
var h=a.href;
var m=oldidRegex.exec(h);
if (m) return m;
return null;
};

// Generate html for whole popup
function popupHTML (a) {

var c=a.className;
// if (c=='new') alert('new!');

var article = articleFromAnchor(a);

var html='';
html +=imageHTML(article);

var hint=a.originalTitle;
if (hint == '' || hint == null)
hint = safeDecodeURI(article);

var oldid=oldidFromAnchor(a);
defaultize('popupNavLinks');
if (popupNavLinks)
html += navLinksHTML(article, hint, oldid);

html += emptySpanHTML('popupWarnRedir', popupImageId);
html += emptySpanHTML('popupGubbins' , popupImageId);
html += emptySpanHTML('popupPreview' , popupImageId);
return html;
};


function isIpUser(user) {
return ipUserRegex.test(user);
};

function mainLinkHTML(article, hint, oldid) {
var html='';
var visibleMainLinkText=safeDecodeURI(article);

defaultize('popupSimplifyMainLink');
if ( popupSimplifyMainLink ) {
var s= visibleMainLinkText.split('/');
visibleMainLinkText = s;
if (visibleMainLinkText == '' && s.length > 1) {
// shouldn't happen...
visibleMainLinkText=s;
}
}
if (typeof hint =='undefined') hint=safeDecodeURI(article);
if (oldid) hint += ' oldid='+oldid;
html+='<b>';
html+=titledWikiLink(article, 'view', visibleMainLinkText, hint, oldid);
html+='</b>';
return html;
};


function emptySpanHTML(name, id) {
return '<span id="' + name + id + '"></span>';
};

function userNavLinksHTML(article) {
// contribs - count - email - block
// count only if applicable; block only if popupAdminLinks
var html = '';
html += contribsLink(article, 'contribs');
var k = kateLink(article, 'count');
if (k) html += popupNavLinkSeparator + kateLink(article, 'count');
html += popupNavLinkSeparator + emailLink(article, 'email');
if (popupAdminLinks) html += popupNavLinkSeparator + blockLink(article, 'block');
return html;
};

function reportErrorHTML(err) {
return 'Error: '+err+ ' Please <a href="' +
'http://en.wikipedia.org/User_talk:Lupin?action=edit&section=new' +
'">report this</a>!';
};

// this function, rather ugly
function editingNavLinksHTML(article, oldid) {
// edit - history - un|watch - talk|edit|new, OR (if a talk page)

// edit|new - history - un|watch - article|edit
var html = '';

var t=talkPage(article);
if (t) {
// it's not a talk page
html += wikiLink(article, 'edit', 'edit', oldid);
html += popupNavLinkSeparator + wikiLink(article, 'history', 'history');
html += popupNavLinkSeparator + wikiLink(article, 'unwatch', 'un')
+ '|' + wikiLink(article, 'watch', 'watch');
html += popupNavLinkSeparator +
'<b>' + wikiLink(t, 'view', 'talk') + '</b>' +
'|' + wikiLink(t, 'edit', 'edit') +
'|' + wikiLink(t, 'edit&section=new', 'new');
} else {
var ta=articleFromTalkPage(article);
if (!ta) return reportErrorHTML('Not a talk page and not an article.');
// it's a talk page
html += wikiLink(article, 'edit', 'edit', oldid)
+'|' + wikiLink(article, 'edit&section=new', 'new');
html += popupNavLinkSeparator + wikiLink(article, 'history', 'history');
html += popupNavLinkSeparator + wikiLink(article, 'unwatch', 'un')
+ '|' + wikiLink(article, 'watch', 'watch');
html += popupNavLinkSeparator +
'<b>' + wikiLink(ta, 'view', 'article') + '</b>' +
'|' + wikiLink(ta, 'edit', 'edit');
}
return html;
};

function miscNavLinksHTML(article) {
// whatLinksHere - relatedChanges - move
var html='';
html += specialLink(article, 'Whatlinkshere', 'whatLinksHere');
html += popupNavLinkSeparator + specialLink(article, 'Recentchangeslinked',
'relatedChanges');
html += popupNavLinkSeparator + specialLink(article, 'Movepage', 'move');
return html;
};

function adminNavLinksHTML(article) {
var html = '';
html += wikiLink(article, 'unprotect', 'un') + '|';
html += wikiLink(article, 'protect', 'protect');
html += popupNavLinkSeparator + undeleteLink(article, 'un') + '|';
html += wikiLink(article, 'delete', 'delete');
return html;
};

function navLinksHTML (article, hint, oldid) {
var html='';

html += mainLinkHTML(article, hint, oldid);

// Get rid of anchor (or whatever the bit after the # is called) now
article=removeAnchor(article);

// span for blinkenlights
html+=emptySpanHTML('popupImageStatus', popupImageId);

defaultize('popupNavLinkSeparator');
defaultize('popupAdminLinks');

if (userName(article) != null)
html += '<br>' + userNavLinksHTML(article);

html += '<br>' + editingNavLinksHTML(article, oldid);

html += '<br>' + miscNavLinksHTML(article);

if (popupAdminLinks)
html += '<br>' + adminNavLinksHTML(article);
return html;
};

/////////////////
// DOWNLOADING //
/////////////////

//////////////
//
// downloader
//
//

function downloader(url) {
// Source: http://jibbering.com/2002/4/httprequest.html
this.http= false;

/*@cc_on @*/
/*@if (@_jscript_version >= 5)
// JScript gives us Conditional compilation,
// we can cope with old IE versions.
// and security blocked creation of the objects.
try {
this.http = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
this.http = new ActiveXObject("Microsoft.XMLHTTP");
} catch (E) {
// this.http = false;
}
}
@end @*/

if (! this.http && typeof XMLHttpRequest!='undefined') {
this.http = new XMLHttpRequest();
}

this.url = url;
this.id=null;
this.callbackFunction = null;
};

new downloader();

downloader.prototype.send = function (x) {
if (!this.http) return;
return this.http.send(x);
};

downloader.prototype.abort = function () {
if (!this.http) return;
return this.http.abort();
};

downloader.prototype.setCallback = function (f) {
if(!this.http) return;
this.http.onreadystatechange = f;
this.callbackFunction = f;
};

downloader.prototype.runCallback = function () {
this.callbackFunction(this);
};

downloader.prototype.getData = function () {
if(!this.http) return;
return this.http.responseText;
};

downloader.prototype.setTarget = function () {
if(!this.http) return;
this.http.open("GET", this.url, true);
};

downloader.prototype.start=function () {
// alert('downloader instance got told to start()');
if(!this.http) return;
return this.http.send(null);
};

downloader.prototype.getReadyState=function () {
if(!this.http) return;
return this.http.readyState;
};

function newDownload(url, id, callback) {
var d=new downloader(url);
d.id=id;
d.setTarget();
var f = function () {
if (d.getReadyState() == 4)
{ d.data=d.getData(); callback(d);}
};
d.setCallback(f);
return d;//d.start();
};

function fakeDownload(url,id,callback,data) {
var d=newDownload(url,callback);
d.id=id;
d.data=data;
return callback(d);
};

function startDownload(url, id, callback) {
var d=newDownload(url, id, callback);
d.start();
};

//
//
// downloader
//
//////////////


// Schematic for a getWiki call
//
// getWiki->-getPageWithCaching
// |
// false | true
// getPage<-->-onComplete(a fake download)
// \.
// (async)->addPageToCache(download)->-onComplete(download)

function getWiki(wikipage, onComplete, oldid) {
// log('getWiki, wikipage='+wikipage);
// set ctype=text/css to get around opera bug
var url = titlebase + removeAnchor(wikipage) + '&action=raw&ctype=text/css';
if (oldid!=null && oldid!='')
url += '&oldid='+oldid;

return getPageWithCaching(url, onComplete);
};

// check cache to see if page exists

function getPageWithCaching(url, onComplete) {
log ('getPageWithCaching, url='+url);
var i=findInPageCache(url);
if (i > -1) {
return fakeDownload(url, popupImageId, onComplete, gCachedPages.data);
}
return getPage(url, onComplete);
};

function getPage(url, onComplete) {
log ('getPage, url='+url);

var callback= function (d) {
// log('callback from getPage activated');
addPageToCache(d); onComplete(d) } ;
return startDownload(url, popupImageId, callback);
};

function findInPageCache(url) {
for (var i=0; i<gCachedPages.length; ++i) {
if (url==gCachedPages.url) return i;
}
return -1;
};

function cachedPage (url,data) {
this.url=url;
this.data=data;
};

function addPageToCache(download) {
log ('addPageToCache, page.url='+download.url);
var page = new cachedPage(download.url, download.data);
return gCachedPages.push(page);
};

/*
var gCurrentDownload = null;

function abortCurrentDownload(download) {
if (gCurrentDownload) {
try { gCurrentDownload.abort(); }
catch (anerror) {return 'could not abort download object';}
}
return true;
}
*/


/////////////////////
// LINK GENERATION //
/////////////////////

function wikiLink(article, action, text, oldid) {
var prehint=null;

switch (action) {
case 'edit': prehint = 'Edit '; break;
case 'history': prehint = 'Show history for '; break;
case 'unwatch': prehint = 'Stop watching '; break;
case 'watch': prehint = 'Watch '; break;
case 'view': prehint = 'Go to '; break;
case 'unprotect': prehint = 'Unprotect '; break;
case 'protect': prehint = 'Protect '; break;
case 'delete': prehint = 'Delete '; break;
case 'edit&section=new': prehint = 'Start a new topic on '; break;
default: true;
}

if (action!='edit' && action!='view') oldid=null;
var hint;
if (prehint != null) {
hint=prehint + safeDecodeURI(article);
hint += (oldid) ? ' oldid='+oldid : '';
}
else hint = safeDecodeURI(article + '&action=' + action)
+ (oldid) ? '&oldid='+oldid : '';
return titledWikiLink(article, action, text, hint, oldid);
};

function titledWikiLink(article, action, text, title, oldid) {
var base = titlebase + article;
var url=base;
// no need to add action&view, and this confuses anchors
if (action != 'view') url = base + '&action=' + action;

var hint='';
if (title != null && title != '')
hint = 'title="' + title + '"';

if (oldid != null && oldid != '')
url+='&oldid='+oldid;

return '<a href="' + url + '" ' + hint + '>' + text + '</a>';
};

function specialLink(article, specialpage, text, sep) {
var base = titlebase + 'Special:'+specialpage;
if (typeof sep == 'undefined' || sep===null) sep='&target=';
var url = base + sep + article;
var prehint=null;
switch (specialpage) {
case 'Whatlinkshere': prehint='Show articles which link to '; break;
case 'Recentchangeslinked': prehint='Show changes in articles related to '; break;
case 'Contributions': prehint='Show contributions made by '; break;
case 'Emailuser': prehint='Email '; break;
case 'Blockip': prehint='Block '; break;
case 'Movepage': prehint='Move '; break;
case 'Undelete': prehint='Show deletion history for '; break;
}
var hint;
if (prehint != null) hint = prehint + safeDecodeURI(article);
else hint = safeDecodeURI(specialpage+':'+article) ;
return '<a href="' + url + '" title="' + hint + '">' + text + '</a>';
};

function redirLink(redirMatch) {
/* NB redirMatch is in wikiText */

defaultize('popupAppendRedirNavLinks');
defaultize('popupNavLinks');

if (popupAppendRedirNavLinks && popupNavLinks)
return '<hr>' + 'Redirects to ' +
navLinksHTML(wikiMarkupToAddressFragment(redirMatch));
else return '<br> Redirects to ' +
titledWikiLink(myEncodeURI(redirMatch), 'view',
safeDecodeURI(redirMatch), 'Bypass redirect');
};

function doNotRedirLink(redirPage, linkText, hintText) {
/* NB redirPage is in wikiText */
return titledWikiLink(myEncodeURI(redirPage), 'edit', linkText, hintText);
};

function contribsLink(article, text) {
return specialLink(userName(article), 'Contributions', text);
};

function emailLink(article, text) {
return specialLink(userName(article), 'Emailuser', text);
};

function blockLink(article, text) {
return specialLink(userName(article), 'Blockip', text, '&ip=');
};

function kateLink(article, text) {
if (isIpUser(userName(article)) || ! wikimediaWiki) return null;

var uN=safeDecodeURI(userName(article));
return '<a href="' + kateBase + uN + '" title="'
+ 'Count the contributions made by ' + uN + '">' + text + '</a>';
};

function undeleteLink(article, text) {
return specialLink(article, 'Undelete', text, '/');
};

////////////////////////////
// MANIPULATION FUNCTIONS //
////////////////////////////

function upcaseFirst(str) {
return str.charAt(0).toUpperCase() + str.substring(1);
};

function formatBytes(num) {
return (num > 949) ? (Math.round(num/100)/10+'kB') : (num +'&nbsp;bytes') ;
};

function popupFilterStubDetect(data) {
return (isStub(data)) ? 'stub' : '';
};

function popupFilterDisambigDetect(data) {
return (isDisambig(data)) ? 'disambig' : '';
};

function popupFilterPageSize(data) {
return formatBytes(data.length);
};

function popupFilterCountLinks(data) {
var num=countLinks(data);
return String(num) + '&nbsp;wikiLink' + ((num!=1)?'s':'');
};

function popupFilterCountImages(data) {
var num=countImages(data);
return String(num) + '&nbsp;image' + ((num!=1)?'s':'');
};

function popupFilterCountCategories(data) {
var num=countCategories(data);
return String(num) + '&nbsp;categor' + ((num!=1)?'ies':'y');
} }

var popupFilters=new Array();

popupFilters.push(popupFilterStubDetect);
popupFilters.push(popupFilterDisambigDetect);
popupFilters.push(popupFilterPageSize);
popupFilters.push(popupFilterCountLinks);
popupFilters.push(popupFilterCountImages);
popupFilters.push(popupFilterCountCategories);

if (typeof extraPopupFilters=='undefined') { var extraPopupFilters=new Array(); }

function getPageInfo(data) {
if (!data || data.length == 0) return 'Empty page';

var pageInfoArray=new Array();
for (var i=0; i<popupFilters.length; ++i) {
var s=popupFilters(data);
if (s!='') pageInfoArray.push(s);
}

for (var i=0; i<extraPopupFilters.length; ++i) {
var s=extraPopupFilters(data);
if (s!='') pageInfoArray.push(s);
}

var pageInfo=pageInfoArray.join(', ');
if (pageInfo != '' )
pageInfo = upcaseFirst(pageInfo);
return pageInfo;
};

function getValidImageFromWikiText(wikiText) {
var imagePage=null;
// nb in imageRegex we're interested in the second bracketed expression
// this may change if the regex changes :-(
//var match=imageRegex.exec(wikiText);
var matched=null;
var match;
defaultize('popupMinImageWidth');
while ( match = imageRegex.exec(wikiText)) {
/* now find a sane image name - exclude templates by seeking { */
var m = match;
var pxWidth=match;
if ( isValidImageName(m) &&
(!pxWidth || parseInt(pxWidth) >= popupMinImageWidth) ) {
matched=m;
break;
}
}
imageRegex.lastIndex=0;
if (!matched) return null;
if (matched.charAt(0) >= 'a' && matched.charAt(0) <= 'z') {
// upcase first character if ascii
matched = upcaseFirst(matched);
}
imagePage='Image:'+matched;
return imagePage;
};

function countLinks(wikiText) {
// this could be improved!
return wikiText.split('[[').length - 1;
};

// if N = # matches, n = # brackets, then
// String.parenSplit(regex) intersperses the N+1 split elements
// with Nn other elements. So total length is
// L= N+1 + Nn = N(n+1)+1. So N=(L-1)/(n+1).

function countImages(wikiText) {
return (wikiText.parenSplit(imageRegex).length - 1) /
(imageRegexBracketCount + 1);
};

function countCategories(wikiText) {
return (wikiText.parenSplit(categoryRegex).length - 1) /
(categoryRegexBracketCount + 1);
};

function talkPage(article) {
if (article.indexOf('Talk:') > -1 || article.indexOf('talk:') > -1 )
return null;

var i=article.indexOf(':');
if (i == -1) return 'Talk:'+article;
else return article.substring(0,i)+'_talk:' + article.substring(i+1);
};

function articleFromTalkPage(talkpage) {
var i=talkpage.indexOf('Talk:');
var j=talkpage.indexOf('_talk:');
if ( i == -1 && j == -1 ) return null;
if ( i > -1 ) return talkpage.substring(i+5);
return talkpage.split('_talk:').join(':');
};

function userName(article) {
var i=article.indexOf('User');
var j=article.indexOf(':');
if (i != 0 || j < -1) return null;
var k=article.indexOf('/');
if (k==-1) return article.substring(j+1);
else return article.substring(j+1,k);
};

function stripNamespace(article) {
// this isn't very sophisticated
// it just removes everything up to the final :
var list = article.split(':');
return list;
};

function imagePathComponent(article) {
var stripped=stripNamespace(article);
var forhash=safeDecodeURI(stripped).split(' ').join('_');
var hash=md5_hex(forhash);
var pathcpt=hash.substring(0,1) + '/' + hash.substring(0,2) + '/';
return pathcpt;
};

function getImageUrlStart(wiki) { // this returns a trailing slash
switch (wiki) {
case 'en.wikipedia.org':
return 'http://upload.wikimedia.org/wikipedia/en/';
case 'commons.wikimedia.org':
return 'http://upload.wikimedia.org/wikipedia/commons/';
case 'en.wiktionary.org':
return 'http://en.wiktionary.org/upload/en/';
default: // unsupported - take a guess
if (wikimediaWiki) {
var lang=wiki.split('.');
return 'http://' + wiki + '/upload/' + lang +'/';
}
else /* this should work for wikicities */
return 'http://' + wiki + '/images/';
}
};

function imageURL(img, wiki) {
defaultize('popupImagesFromThisWikiOnly');
if (popupImagesFromThisWikiOnly && wiki != thisWiki) return null;
var imgurl=null;
if (isImage(img)) {
var pathcpt = imagePathComponent(img);
var stripped=stripNamespace(img);
imgurl=getImageUrlStart(wiki) + pathcpt + stripped;
}
return imgurl;
};

function imageThumbURL(img, wiki, width) {
//
// eg http://upload.wikimedia.org/wikipedia/en/thumb/6/61/
// Rubiks_cube_solved.jpg/120px-Rubiks_cube_solved.jpg
// ^^^^^^^^^^^^^^^^^^^^^^^
// wikicities omits this bit
// AND wikicities needs a new pathcpt for each filename including thumbs

defaultize('popupImagesFromThisWikiOnly');
if (popupImagesFromThisWikiOnly && wiki != thisWiki) return null;

defaultize('popupNeverGetThumbs');
if (popupNeverGetThumbs) return null;

var imgurl=null;
if (isImage(img)) {
var stripped=stripNamespace(img);
var pathcpt;
if (wikimediaWiki) pathcpt = imagePathComponent(stripped);
else pathcpt = imagePathComponent(width+'px-'+stripped);
imgurl=getImageUrlStart(wiki) + "thumb/" + pathcpt;
if (wikimediaWiki) imgurl += stripped + '/';
imgurl += width +"px-" + stripped;
}
return imgurl;
};


// (a) myDecodeURI (first standard decodeURI, then exceptions)
// (b) change spaces to underscores
// (c) encodeURI (just the straight one, no exceptions)

function wikiMarkupToAddressFragment (str) { // for images
var ret = safeDecodeURI(str);
ret = ret.split(' ').join('_');
ret = encodeURI(ret);
return ret;
};

function addressFragmentToWikiMarkup (str) {
// seemingly, not :( the inverse of wikiMarkupToAddressFragment
return safeDecodeURI(str);
};

function myDecodeURI (str) {
log('myDecodeURI, str=' + str);
var ret;
try { ret=decodeURI(str); }
catch (summat) { return null; }
for (var i=0; i<decodeExtras.length; ++i) {
var from=decodeExtras.from;
var to=decodeExtras.to;
ret=ret.split(from).join(to);
}
return ret;
};

function safeDecodeURI(str) {
var ret=myDecodeURI(str);
return ret || str;
}

function myEncodeURI (str) {
log ('myEncodeURI: str='+str);
var ret=str;
ret=encodeURI(ret);
for (var i=0; i<decodeExtras.length; ++i) {
var from=decodeExtras.from;
var to=decodeExtras.to;
ret=ret.split(to).join(from);
}
return ret;
};

function removeAnchor(article) {
// is there a #? if not, we're done
var i=article.indexOf('#');
if (i == -1) return article;

return article.substring(0,i);
};

///////////
// TESTS //
///////////

function isStub(data) { return stubRegex.test(data); };
function isDisambig(data) { return disambigRegex.test(data); };

function isValidImageName(str){ // extend as needed...
return ( str.split('{').length == 1 );
};

function isInNamespace(article, namespace) {
var i=article.indexOf(namespace+':');
var j=article.indexOf(namespace+'_talk:');
if (i == -1 && j == -1) return false;
return true;
};

function isImage(thing) {
return isInNamespace(thing, 'Image');
};

function isImageOk(img)
{
// IE test
if (!img.complete)
return false;

// gecko test
if (typeof img.naturalWidth != "undefined" && img.naturalWidth == 0)
return false;

// test for konqueror and opera

// note that img.width must not be defined in the html with a width="..."
// for this to work.

// konq seems to give "broken images" width 16, presumably an icon width
// this test would probably work in gecko too, *except for very small images*
if (typeof img.width == 'undefined' || img.width <= 16) return false;

// No other way of checking: assume it's ok.
return true;
};

function anchorContainsImage(a) {
// iterate over children of anchor a
// see if any are images
if (a===null) return false;
kids=a.childNodes;
for (var i=0; i<kids.length; ++i) {
if (kids.nodeName=='IMG') return true;
}
return false;
};

/////////////
// ACTIONS //
/////////////

var imageCache = new Array ();

function loadThisImage (image) {
if (!popupImages) return;
if (!isValidImageName(image)) return false;

if(popupDebug != null)
alert(msg);
msg='List of urls:\n';
var imageUrls=new Array();
for (var i=0; i<imageSources.length; ++i) {

var url;

if (imageSources.thumb)
url=imageThumbURL(image, imageSources.wiki, imageSources.width);
else
url=imageURL(image, imageSources.wiki);

for (var j=0; j<gImageCache.length; ++j) {
if (url == gImageCache) return loadThisImageAtThisUrl(image, url);
}
if (url!=null) imageUrls.push(url);
}
msg='imageUrls:\n';
for (var i=0; i<imageUrls.length; ++i) {
var url = imageUrls;
imageSources.active=false;
msg += '\n'+url;

imageArray=new Image();
imageArray.src=url;
}
//myalert(msg);
if (popupDebug) alert (msg);

if (popupImageTimer != null) {
clearInterval(popupImageTimer);
counter=0;
}
gImage=image;
popupImageTimer=setInterval("checkImages()", 250);
return;
};

function loadThisImageAtThisUrl(image, url) {
//myalert('loading "best" image:\n'+url);
gImage=image;
imageArray = new Array();
imageArray = new Image();
imageArray.src=url;
if (popupImageTimer != null) {
clearInterval(popupImageTimer);
counter=0;
}
popupImageTimer=setInterval("checkImages()", 250);
return;
};

function loadImages(article) {
if(! isImage(article) ) return;
if (popupDebug) alert('loadImages, article='+article);
return loadThisImage(article);
};

function setPopupHTML (str, elementId, popupId) {
if (typeof popupId === 'undefined') popupId = popupImageId;
var popupElement=
document.getElementById(elementId+popupId);
var timer;

if (typeof popupHTMLTimers == 'undefined') {
timer=null;
}
else {
timer=popupHTMLTimers;
}

if (popupElement != null) {
if(timer) clearInterval(timer);
popupHTMLTimers=null;
popupElement.innerHTML=str;
return true;
} else {
var loopFunction=function() { setPopupHTML(str,elementId,popupId);}
popupHTMLLoopFunctions = loopFunction;
if (!timer) {
var doThis = 'popupHTMLLoopFunctions()';
popupHTMLTimers = setInterval(doThis, 600);
}
}
};

function setImageStatus(str, id) {
return setPopupHTML(str, 'popupImageStatus', id);
};

function setPopupTrailer(str,id) {
return setPopupHTML(str, 'popupGubbins', id);
};

function checkImages() {

if (checkImagesTimer!=null) {
clearInterval(checkImagesTimer);
checkImagesTimer=null;
if (loopcounter > 10); {loopcounter=0; return;}
loopcounter++;
} else counter++;

var status = ( counter % 2 ) ? ':' : '.' ;
setImageStatus(status);

if (counter > 100) {counter = 0; clearInterval(popupImageTimer);}

var popupImage=null;
popupImage=document.getElementById("popupImage"+popupImageId);
if (popupImage == null) {
// this doesn't seem to happen any more in practise for some reason
// still, I'll leave it in
checkImagesTimer=setInterval("checkImages()",333);
return;
}
// get the first image to successfully load
// and put it in the popupImage
for(var i = 0; i < imageArray.length; ++i) {
if(isImageOk(imageArray)) {
// stop all the gubbins, assign the image and return

clearInterval(popupImageTimer);

if(isImage(gImage)) {
popupImage.src=imageArray.src;
popupImage.width=popupImageSize;
popupImage.style.display='inline';
imageSources.active=true;
// should we check to see if it's already there? maybe...
gImageCache.push(imageArray.src);

setPopupImageLink(gImage, imageSources.wiki);
stopImagesDownloading();
}

setImageStatus('');

// reset evil nonconstant globals
delete imageArray; imageArray=new Array();
popupImageTimer=null;

counter=0;
loopcounter=0;

return popupImage.src;
}
}
};

function stopImagesDownloading() {
gImage=null;
if (imageArray == null) return null;
var i;
for (i=0; i<imageArray.length; ++i) {
//imageArray.src=''; // this is a REALLY BAD IDEA
delete imageArray;
//imageArray = new Image();
}
imageArray = new Array ();
return i;
};

function toggleSize() {
var imgContainer=this;
if (!imgContainer) { alert('imgContainer is null :/'); return;}
img=imgContainer.firstChild;
if (!img) { alert('img is null :/'); return;}
var msg='';
for (var i=0; i<imgContainer.childNodes.length; ++i)
msg += '\nimgContainer.childNodes.width=' +
imgContainer.childNodes.width;
if (!img.style.width || img.style.width=='')
img.style.width='100%';
else img.style.width=''; // popupImageSize+'px';
};

function setPopupImageLink (img, wiki) {
if( wiki === null || img === null ) return null;
var a=document.getElementById("popupImageLink"+popupImageId);
if (a === null) return null;

var linkURL = imageURL(img, wiki);
if (linkURL != null) {
if (popupImagesToggleSize) {
a.onclick=toggleSize;
a.title='Toggle image size';
} else {
a.href=linkURL;
a.title='Open full-size image';
}
}
return linkURL;
};

var ranSetupTooltipsAlready=false;

function setupTooltips() {
if (ranSetupTooltipsAlready) return;
ranSetupTooltipsAlready=true;

var anchors;
defaultize('popupOnlyArticleLinks');

if (popupOnlyArticleLinks)
anchors=( document.getElementById('article') ||
document.getElementById('content') ).getElementsByTagName('A');
else
anchors=document.getElementsByTagName('A');
// alert(anchors.length + 'anchors');
var s='';
defaultize('removeTitles');

for (var i=0; i<anchors.length; ++i) {
var a=anchors;
var h=a.href;
// var contribs=contributions.test(h);
// var email=emailuser.test(h);
// var exc=exceptions.test(h);
// var m=re.test(h);
if (
( (re.test(h) && !exceptions.test(h))
||
(contributions.test(h) && h.indexOf('&limit=') == -1 )
)
&& (! isInToc(a))
) {
a.onmouseover=mouseOverWikiLink;
a.onmouseout= mouseOutWikiLink;
a.onclick= killPopup;
if (removeTitles && typeof a.originalTitle=='undefined') {
a.originalTitle=a.title;
a.title='';
}
}
}
};


//////////////
// THINGIES //
//////////////

// How the URLs for images in the popup come about

// loadPreviewImage
// |
// getWiki
// |<----------------see other schematic for details
// insertPreviewImage (insertPreviewImage = onComplete)
// |
// | insertPreviewImage gets a wikiText fragment from
// | the wikiText downloaded by getWiki
// |
//
// |
// | mouseOverWikiLink (gets an "address fragment",
// | | no processing needed)
// \->-loadThisImage---<----loadImages
// |
// -->--hopefully valid image urls


var currentLink=null;

function mouseOverWikiLink() {
// FIXME: should not generate the HTML until the delay has elapsed,
// and then popup immediately. Can be a CPU hog otherwise.
/* // good idea? dunno
if ( typeof o3_showingsticky != "undefined" && o3_showingsticky != 0 ) {
return;
}
*/

var a=this;

if (a==currentLink) return;
else currentLink=a;

var html = popupHTML(a);
var article=articleFromAnchor(a);
var oldid=oldidFromAnchor(a);

if (popupImageTimer != null) {
clearInterval(popupImageTimer);
counter=0;
}

defaultize('popupDelay');
defaultize('popupFgColor');
defaultize('popupBgColor');
defaultize('popupImages');
defaultize('popupMaxWidth');

log('running overlib now');
if (typeof popupMaxWidth == 'number') {
window.setmaxwidth = function () {
over.style.maxWidth = popupMaxWidth+'px';
// hack for IE
// see http://www.svendtofte.com/code/max_width_in_ie/
// who knows if this will work? not me.
// use setExpression as documented here on msdn: http://tinyurl.com/dqljn
if (over.style.setExpression) {
over.style.setExpression('width',
'document.body.clientWidth > '
+ popupMaxWidth + ' ? "'
+ popupMaxWidth + 'px": "auto" );');
}
};
registerHook("createPopup", window.setmaxwidth, FAFTER);
}

overlib(html, STICKY, WRAP, CELLPAD, 5, OFFSETX, 2, OFFSETY, 2,
DELAY, popupDelay*1000, FGCOLOR, popupFgColor, BGCOLOR, popupBgColor);
defaultize('simplePopups');
if(simplePopups) return;

defaultize('imagePopupsForImages');

var previewImage=true;

gImage=null;

if (isImage(article) && ( imagePopupsForImages || ! anchorContainsImage(a) )) {
loadImages(article);
}
else if (!isImage(article) && previewImage) {
redirCount=0;
loadPreviewImage(article, oldid);
}
};

function loadPreviewImage(article, oldid) {
return getWiki(article, insertPreviewImage, oldid);
};

function loadPreviewImageFromRedir(redirPage, redirMatch) {
/* redirMatch is a regex match */
var target = redirMatch;
var trailingRubbish=redirMatch;
++redirCount;
var warnRedir = redirLink(target);
/*if (trailingRubbish.length > 0) {
warnRedir += ', '+formatBytes(trailingRubbish.length);
warnRedir += '&nbsp;' +
doNotRedirLink(redirPage, 'hidden', 'Show text hidden after #redirect]');
}
*/
setPopupHTML(warnRedir, 'popupWarnRedir');
return loadPreviewImage(myEncodeURI(target));
};

function extractChunk(str, header, breakChar) {
if (str.indexOf(header) != 0) return null;
if (!breakChar) return str.substring(header.length);
var findChar=str.indexOf(breakChar);
if (findChar==-1) return str.substring(header.length);
return str.substring(header.length, findChar);
};

function urlToWikiPage (url) {
log ('urlToWikiPage\nurl='+url);
var urlFragment=null;

if (!urlFragment) urlFragment=extractChunk(url, titlebase, '&');
if (!urlFragment) urlFragment=extractChunk(url, wikibase, '?');

if (!urlFragment) return null;
return addressFragmentToWikiMarkup(urlFragment);
};

function insertPreviewImage(download) {
if (download.id != popupImageId) return;

var wikiText=download.data;

var redirectRegex= RegExp('^*redirect*\\]*)\\]\\]\\s*(.*)',
'i') ;
var redirMatch = redirectRegex.exec(wikiText);

if (redirMatch && redirCount==0) {
return loadPreviewImageFromRedir(urlToWikiPage(download.url), redirMatch);
} else redirCount=0;

defaultize('popupSummaryData');

if (popupSummaryData) {
var pgInfo=getPageInfo(wikiText);
setPopupTrailer('<br>' + pgInfo);
}

var imagePage=getValidImageFromWikiText(wikiText);
if(imagePage) {
// loadThisImage expects an "address fragment"
imagePage = wikiMarkupToAddressFragment(imagePage);
loadThisImage(imagePage);
}
defaultize('popupPreviews');
if (popupPreviews) {popupPreview(download);}

};

var localTest=false;

function popupPreview(download) {
// FIXME: horizonal rules should be skipped
// FIXME: get rid of html tagsx
if (!download || typeof download.data=='undefined'
|| typeof download.data.length=='undefined') return;
if (localTest)
var data = download.substring(0,8000); // FOR TESTING
else
var data=download.data.substring(0,10000); // huge pages be gone
var datum=new Array();
datum.push(data.substring(0,1000));
// we strip in order:
//
// * html comments <!-- ... -->
// * contents of <div...> ... </div> and <gallery> ... </gallery>
// * HACK: {{taxobox_start ... taxobox_end}}
// * templates {{ .... }} (replace with spaces so that '''{{template}}''' works)
// * wikitext tables
// * wikitext images and category tags
// * wikitext rules ----
// * lines starting with a :
// * html tables
// * a mop-up: delete all lines starting with <
// * all html tags
// * "chunks" of italic text (heuristics alert)
// * __TOC__, __NOTOC__


// hasta la vista, comments
// NB *? is non-greedy (minimal) version of * - see
// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:RegExp
data=data.replace(RegExp('<!--(\\n|.)*?-->', 'g'), '');

// say goodbye, divs
data=data.replace(RegExp('< *div* *>(.|\\n)*< */ *div *>',
'gi'), '');
// and galleries

data=data.replace(RegExp('< *gallery* *>(.|\\n)*< */ *gallery *>',
'gi'),
'');

// taxobox hack... in fact, there's a saudiprincebox_begin, so let's be more general
data=data.replace(RegExp('*box_begin(.|\\n)**box_end *',
'gi'), '');
// try to remove templates
data=data.replace(RegExp('(*|)*', 'g'), ' ');
//datum.push(data);
// tables are bad, too
data=data.replace
(RegExp('\\|((|\\|)*||\\|)*\\|', 'g')
, '');
datum.push(data.substring(0,1000));

// images are a nono
// who says regexes aren't fun?
// this ain't so good, try it on ]
// i think we should match:
// ] where ....... is consists of repetitions of any of:
// 1. not
// 2. )* ]]
// 3. )* ]
var imagedetector
='\\s*(image|category)\\s*:(]|\\]*\\]\\]|\\]*\\])*\\]\\]';
var crudeImageRegex = RegExp(imagedetector, 'gi');
// alert(data.match(crudeImageRegex).join('\n-\n'));

data=data.replace(crudeImageRegex, '');
// we simply *can't* be doing with horizontal rules right now
data=data.replace(RegExp('^-{4,}','mg'),'');

// no indented lines
data=data.replace(RegExp('(^|\\n) *:*','g'), '\n');

// or html tables // this doesn't cope with embedded tables
//data=data.replace(RegExp('<table*>(||<|</|'+
// may this is good enough?
data=data.replace(RegExp('<table*>(.|\\n.)*\\n?</ *table *>\\n+', 'gi'),
'');
// let's delete lines starting with <. it's worth a try.
data=data.replace(RegExp('(^|\\n) *<*', 'g'), '\n');

// and those pesky html tags
data=data.replace(RegExp('<*>','g'),'');

// chunks of italic text? you crazy, man?
var italicChunkRegex=new RegExp
("((^|\\n)\\s*:*\\s*''(|'''|'){20}(.|\\n)*''*\\n)*"
, 'g');
data=data.replace(italicChunkRegex, '');
// return data; //TESTING

// replace __TOC__, __NOTOC__ and whatever else there is
// this'll probably do
data=data.replace(RegExp('^__*__ *$', 'gmi'),'');

// dont't be givin' me no subsequent paragraphs, either, you hear me?
/// first we "normalize" section headings, removing whitespace after, adding before
data=data.replace(RegExp('\\s*(==+*==+)\\s*', 'g'), '\n\n$1 ');

/// then we want to get rid of paragraph breaks whose text ends badly
data=data.replace(RegExp('() *\\n{2,}', 'g'), '$1\n');

stuff=(RegExp('^\\s*(|\\n)*')).exec(data);
if (stuff)
data = stuff;
/// now put \n\n after sections so that bullets and numbered lists work
data=data.replace(RegExp('(==+*==+)\\s*', 'g'), '$1\n\n');

// superfluous sentences are RIGHT OUT.
// note: 1 set of parens here needed to make the slice work
data = data.parenSplit(RegExp('(+*\\s)','g'));
// leading space is bad, mmkay?
data=data.replace(RegExp('^\\s*'), '');

var notSentenceEnds=RegExp('(|etc|sic|Dr|Mr|Mrs|Ms)$'
+ '|' +
'\\]*$'
, 'i');
data = fixSentenceEnds(data, notSentenceEnds);

defaultize('maxPreviewSentences');
defaultize('maxPreviewCharacters');
var n=maxPreviewSentences;
var d;
do {d=firstSentences(data,n); --n; }
while ( d.length > maxPreviewCharacters && n > 0 );
data = d;
datum.push('\n\nfinal one:');
datum.push(data.substring(0,1000));

if (localTest) return data; // FOR TESTING

var newhtml=wiki2html(data); // needs livepreview
if (!RegExp('^\\s*$').test(newhtml) &&
(popupNavLinks || popupSummaryData))
{
newhtml = '<hr>' + newhtml;
setPopupHTML(newhtml, 'popupPreview');
}
};

function fixSentenceEnds(strs, reg) {
// take an array of strings, strs
// join strs to strs & strs if strs matches regex reg
for (var i=0; i<strs.length-2; ++i) {
if (reg.test(strs)) {
a=new Array ();
for (var j=0; j<strs.length; ++j) {
if (j<i) a=strs;
if (j==i) a=strs+strs+strs;
if (j>i+2) a=strs;
}
return fixSentenceEnds(a,reg);
}
}
//alert('returning '+strs.join('\n\n'));
return strs;
};

function firstSentences(strs, howmany) {
var t=strs.slice(0, 2*howmany);
return t.join('');
};

var stopPopupTimer=null;

function fuzzyCursorOff(fuzz) {
if (!over) return null;
var left = parseInt(over.style.left);
var top = parseInt(over.style.top);
var right = left + (over.offsetWidth >= parseInt(o3_width) ? over.offsetWidth : parseInt(o3_width));
var bottom = top + (over.offsetHeight >= o3_aboveheight ? over.offsetHeight : o3_aboveheight);
if (o3_x < left-fuzz || o3_x > right+fuzz || o3_y < top-fuzz || o3_y > bottom + fuzz) return true;
return false;
}

// seems that fuzzyCursorOff should precede mouseOutWikiLink in the source
// or sometimes during page loads, errors are generated

function mouseOutWikiLink () {
if (fuzzyCursorOff(5)) {
if (stopPopupTimer) {
clearInterval(stopPopupTimer);
stopPopupTimer=null;
}
killPopup();
return;
}
if (!stopPopupTimer)
stopPopupTimer=setInterval("mouseOutWikiLink()", 500);
};

function killPopup() {
// o3_showingsticky should be defined in overlib.js
//if ( typeof o3_showingsticky != "undefined" && o3_showingsticky == 0 ) {
cClick();
currentLink=null;
// abortCurrentDownload();
stopImagesDownloading();
if (checkImagesTimer != null) {
clearInterval(checkImagesTimer); checkImagesTimer=null;
}
if (popupImageTimer != null) {
clearInterval(popupImageTimer); popupImageTimer=null;
}
//}
return true; // preserve default action (eg from onclick)
};

////////////////////////////////////////////////////////////////////
// Run things
////////////////////////////////////////////////////////////////////

if (window.addEventListener) {
window.addEventListener("load",setupTooltips,false);
}
else if (window.attachEvent) {
window.attachEvent("onload",setupTooltips);
}
else {
window._old_ABCD_onload = window.onload;
window.onload = function() {
window._old_ABCD_onload();
setupTooltips();
}
}

/// Local Variables: ///
/// mode:c ///
/// End: ///

Latest revision as of 14:34, 9 February 2021

var popScript     = '//en.wikipedia.org/search/?action=raw&ctype=text/javascript&title=MediaWiki:Gadget-popups.js';
var popStyleSheet = '//en.wikipedia.org/search/?action=raw&ctype=text/css&title=MediaWiki:Gadget-navpop.css';
if ( window.localCSS ) { popStyleSheet = 'http://localhost:8080/js/navpop.css'; }

function popups_importScriptURI(url) {
	var s = document.createElement('script');
	s.setAttribute('src',url);
	s.setAttribute('type','text/javascript');
	document.getElementsByTagName('head').appendChild(s);
	return s;
}

function popups_importStylesheetURI(url) {
	return document.createStyleSheet ? document.createStyleSheet(url) : popups_appendCSS('@import "' + url + '";');
}

function popups_appendCSS(text) {
	var s = document.createElement('style');
	s.type = 'text/css';
	s.rel = 'stylesheet';
	if (s.styleSheet) s.styleSheet.cssText = text //IE
	else s.appendChild(document.createTextNode(text + '')) //Safari sometimes borks on null
	document.getElementsByTagName('head').appendChild(s);
	return s;
}

popups_importStylesheetURI(popStyleSheet);
popups_importScriptURI(popScript);

if ( typeof mw !== 'undefined' ) {
mw.loader.using( , function() {
	var k = 'User:Lupin/popups.js',
		t = 'Information: You are importing User:Lupin/popups.js' +
			' into your User:USERNAME/common.js or User:USERNAME/<skin>.js!\n' +
			'This script is unmaintained. Please remove this inclusion and enable the Navigation popups Gadget in the preferences of your account instead.',
		x = mw.storage.get( k );

	if ( !x ) {
		mw.storage.set( k, 1 );
		alert( t );
	} else {
		x++;
		mw.storage.set( k, x );
		if ( x % 25 === 0 ) {
			mw.notify( t );
		}
	}
});
}