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', "' ⋅ '"); |
|
|
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=' • '; |
|
|
} else if ((self.navigator.appName).indexOf("Microsoft")!=-1) { |
|
|
dpopupNavLinkSeparator=' · '; |
|
|
} |
|
} |
|
|
|
|
|
|
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§ion=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§ion=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§ion=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§ion=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 +' 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) + ' wikiLink' + ((num!=1)?'s':''); |
|
|
}; |
|
|
|
|
|
function popupFilterCountImages(data) { |
|
|
var num=countImages(data); |
|
|
return String(num) + ' image' + ((num!=1)?'s':''); |
|
|
}; |
|
|
|
|
|
function popupFilterCountCategories(data) { |
|
|
var num=countCategories(data); |
|
|
return String(num) + ' 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 += ' ' + |
|
|
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: /// |
|