/* Based on the original markblocked script [[:ru:MediaWiki:Gadget-markblocked.js]]
by Alex Smotrov et al., original idea by Kalan
Additional inspiration from [[User:Equazcion/sysopdetector.js]]
*/
var MarkBlockedPlus = {
defaultPref: function ( cfig, dflt ) {
return ( typeof cfig === typeof dflt ? cfig : dflt );
},
// replacement for jQuery's deprecated isArray; name is a historical artifact
hackIsArray: function ( maybeArray ) {
return Array.isArray( maybeArray );
},
// expanded later
}
// TODO: Store the defaulted prefs in MarkBlockedPlus instead of writing them back to window
window.mbShowUnregistered = MarkBlockedPlus.defaultPref( window.mbShowUnregistered, true );
window.mbShowGroups = MarkBlockedPlus.defaultPref( window.mbShowGroups, true );
window.mbShowEditCount = MarkBlockedPlus.defaultPref( window.mbShowEditCount, true );
window.mbShowRegDateAbs = MarkBlockedPlus.defaultPref( window.mbShowRegDateAbs, true );
window.mbRemoveWaitingCSSOnError = MarkBlockedPlus.defaultPref( window.mbRemoveWaitingCSSOnError, true );
window.mbLinkClassifierRedirWarn = MarkBlockedPlus.defaultPref( window.mbLinkClassifierRedirWarn, true );
window.mbLinkClassifierTimeoutHack = MarkBlockedPlus.defaultPref( window.mbLinkClassifierTimeoutHack, true );
MarkBlockedPlus.showRedirectWarning = window.mbLinkClassifierRedirWarn;
// Exposed globally for compatibility with original markblocked
function markBlocked( container ) {
var contribPageNames = [ 'Contributions' ];
function scrapeContribLink( ) {
//something went wrong, so get local alias for "Contributions" from "my contribs" link on top
var mwCont = /:([^\/]+)\//.exec( $( '#pt-mycontris a' ).attr( 'href' ) );
if( mwCont ) { mwCont = mwCont[1]; contribPageNames[0] = mwCont; }
MarkBlockedPlus.reallyMarkBlocked( container, contribPageNames );
}
function getContribNameCallback( r, sts, xhr ) {
if ( !r || !r.query ) { scrapeContribLink( ); return; }
if ( !r.query.specialpagealiases ) { scrapeContribLink( ); return; }
for ( pag in r.query.specialpagealiases ) {
if ( pag.realname == 'Contributions' ) {
if ( pag.aliases ) { contribPageNames = pag.aliases; break; }
}
}
MarkBlockedPlus.reallyMarkBlocked( container, contribPageNames );
}
function getContribNamePanic( xhr, textStatus, errorThrown ) {
//TODO: error reporting
scrapeContribLink( );
}
if ( typeof window.mbLocalContribsName == 'string' ) {
contribPageNames[0] = window.mbLocalContribsName;
MarkBlockedPlus.reallyMarkBlocked( container, contribPageNames );
}
else if ( MarkBlockedPlus.hackIsArray( window.mbLocalContribsName ) ) {
contribPageNames = window.mbLocalContribsName;
MarkBlockedPlus.reallyMarkBlocked( container, contribPageNames );
}
else {
var q = {
format:'json',
action:'query',
meta:'siteinfo',
siprop:'specialpagealiases'
}
$.ajax( {
url:mw.util.wikiScript('api'),
dataType:'json',
type:'POST',
data:q,
rawdata:q,
success:getContribNameCallback,
error:getContribNamePanic
} );
}
}
MarkBlockedPlus.reallyMarkBlocked = function ( container, contribPageNames ) {
//----- start of reallyMarkBlocked
var contentLinks = container ? $( container ).find( 'a' ) : $( '#content a' ).add( '#ca-nstab-user a' );
if ( typeof window.mbTempStyle == 'string' && typeof window.mbTemp2Style != 'string' ) window.mbTemp2Style = window.mbTempStyle;
mw.util.addCSS('\
.user-blocked-temp{' + MarkBlockedPlus.defaultPref(window.mbTempStyle, 'opacity: 0.7; text-decoration: line-through') + '}\
.user-blocked-temp2{' + MarkBlockedPlus.defaultPref(window.mbTemp2Style, 'opacity: 0.7; text-decoration: line-through') + '}\
.user-blocked-indef{' + MarkBlockedPlus.defaultPref(window.mbIndefStyle, 'opacity: 0.4; font-style: italic; text-decoration: line-through') + '}\
.user-blocked-tipbox{' + MarkBlockedPlus.defaultPref(window.mbTipBoxStyle, 'font-size:smaller; background:#FFFFF0; border:1px solid #FEA; padding:0 0.3em; color:#AAA') + '}\
.user-info-tipbox{' + MarkBlockedPlus.defaultPref(window.mbTipBoxInfoStyle, 'font-size:smaller; background:#FFFFF0; border:1px solid #FEA; padding:0 0.3em; color:#AAA') + '}\
')
MarkBlockedPlus.tooltip = MarkBlockedPlus.defaultPref( window.mbTooltip, '; blocked ($1) by $2: $3 ($4 ago)' );
MarkBlockedPlus.tipBoxCharsToTrim = MarkBlockedPlus.defaultPref( window.mbTipBoxCharsToTrim, 2 );
//TODO: Figure out a sane way to let users customize the rest of the tooltip.
//get all aliases for user:, user_talk: and special:
MarkBlockedPlus.userNS = [ ];
var userNonTalkNS = [ ], specialNS = [ ];
var firstSpecialNS = '';
var nIDs = mw.config.get( 'wgNamespaceIds' );
for (var ns in nIDs) {
var colonifiedNS = ns + ':';
var cleanNS = colonifiedNS.replace(/_/g, ' ');
if ( nIDs[ns] == 2 ) {
MarkBlockedPlus.userNS.push( cleanNS );
userNonTalkNS.push( cleanNS );
}
else if ( nIDs[ns] == 3 ) {
MarkBlockedPlus.userNS.push( cleanNS );
}
else if ( nIDs[ns] == -1 ) {
if ( firstSpecialNS === '' ) { firstSpecialNS = colonifiedNS.charAt(0).toUpperCase( ) + colonifiedNS.substr(1); }
specialNS.push( cleanNS );
}
}
var contribNames = contribPageNames;
//RegExp for all titles that are User:| User_talk: | Special:Contributions/ (for userscripts)
var userTitleRX = new RegExp('^'
+ '(' + MarkBlockedPlus.userNS.join('|')
+ '|(?:' + specialNS.join('|') + ')(?:' + contribNames.join('|') + ')\\/'
+ ')'
+ '([^\\/#]+)$', 'i');
//RegExp for links. XXX: Is it safe for us to assume that $1 is always at the end of wgArticlePath?
var wAP = mw.config.get( 'wgArticlePath' ), wS = mw.config.get( 'wgScript' );
var cleanArticlePath = wAP.replace('$1', '');
var articleRX = new RegExp( '^' + cleanArticlePath + '([^#]+)' );
var scriptRX = new RegExp( '^' + wS + '\\?title=([^#&]+)' );
MarkBlockedPlus.userLinks = { };
var url, ma, pgTitle;
//find all "user" links and save them in userLinks : { 'users': [<link1>, <link2>, ...], 'user2': [<link3>, <link3>, ...], ... }
contentLinks.each(function(i/* unused */, lnk) {
//exclude links added to user(talk) pages by [[User:Bility/copySectionLink]] or built-in MW feature
var $lnk = $( lnk );
var myId = $lnk.attr( 'id' );
if ( myId && /^sectiontitlecopy\d+$/.test( myId ) ) return;
if ( $lnk.hasClass( 'mw-headline-anchor' ) ) return;
url = $lnk.attr( 'href' );
if ( !url ) return;
//XXX personal hack XXX
if (
window.mbShibbocuridleet === true &&
url.indexOf( 'title=' ) != -1 &&
url.indexOf( 'curid=' ) != -1 &&
!( $lnk.hasClass( 'external' ) ) &&
!( $lnk.hasClass( 'extiw' ) )
) {
var fixURL = url.replace( /&curid=\d+/, '' );
if ( fixURL !== url ) {
$lnk.addClass( 'curid-stripped' );
$lnk.attr( 'href', fixURL );
url = fixURL;
}
}
//for compatibility with other scripts which may add redirect=no to links
var redirNoRegex = ( wAP.indexOf( '?' ) == -1 ? /\?redirect=no$/ : /&redirect=no$/ );
url = url.replace( redirNoRegex, '' );
//The case beginning with ? is necessary to avoid these parameters polluting the username.
//The & case is just for consistency (is this needed/useful? hmm)
url = url.replace( /[\?&]vanarticle=[^&]+&noautowarn=(tru|fals)e&vanarticlerevid=\d+$/, '' );
//TODO: There should be an option to add a CSS class
if ( url.charAt(0) != '/' || url.indexOf( 'friendlywelcome=' ) != -1 ) { return; }
else if ( ma = articleRX.exec( url ) ) { pgTitle = ma[1]; }
else if ( ma = scriptRX.exec( url ) ) { pgTitle = ma[1]; }
else { return; }
pgTitle = decodeURIComponent( pgTitle ).replace( /_/g, ' ' );
user = userTitleRX.exec( pgTitle );
if ( !user ) return;
user = user[2];
user = user.replace( /^\s+|\s+$/g, '' );
if ( user == '0' || user == 'newbies' || user.length > 64 ) { $lnk.addClass( 'baduserlink' ); return; }
if ( /[\u0080-\u009F\u00A0\u2000-\u200F\u2028-\u202F\u3000\uE000-\uF8FF\uFFFD]/.test( user ) ) { $lnk.addClass( 'baduserlink' ); return; }
user = user.charAt(0).toUpperCase( ) + user.substr(1);
var doubledPrefix = userTitleRX.exec( user );
if( doubledPrefix ) { $lnk.addClass( 'baduserlink' ); return; }
$lnk.addClass( 'userlink' );
if( !( MarkBlockedPlus.hackIsArray( MarkBlockedPlus.userLinks[user] ) ) ) MarkBlockedPlus.userLinks[user] = [ ];
MarkBlockedPlus.userLinks[user].push( lnk );
//optionally replace userpage redlinks with contributions links
if ( window.mbReplaceUserRedLinksWithContribs === true && $lnk.hasClass( 'new' ) ) {
var userNonTalkNSJoined = userNonTalkNS.join('|');
var userNonTalkTitleRX = new RegExp('^'
+ '(' + userNonTalkNSJoined
+ ')'
+ '([^\\/#]+)$', 'i');
if ( !( userNonTalkTitleRX.test( pgTitle ) ) ) { return; }
// "Special:" "Contributions" "/"
var contribTitlePfx = firstSpecialNS + contribNames[0] + '/';
// "Special:" "Contributions" "/" "user_name"
var contribFullTitle = contribTitlePfx + user.replace( / /g, '_' );
//if we're viewing a contributions page, don't create self links
if ( mw.config.get( 'wgPageName' ) === contribFullTitle ) { return; }
//in all: wgArticlePath-without-$1 Special: Contributions / user_name
var newURL = cleanArticlePath + contribFullTitle;
$lnk.attr( 'href', newURL );
var newTitle = $lnk.attr( 'title' );
if ( newTitle ) {
var userNonTalkPrefixRX = new RegExp('^'
+ '(' + userNonTalkNSJoined
+ ')', 'i');
newTitle = newTitle.replace( userNonTalkPrefixRX, contribTitlePfx );
//XXX: make compatible with non-English wikis
newTitle = newTitle.replace( ' (page does not exist)', ' (no user page)' );
$lnk.attr( 'title', newTitle );
}
$lnk.removeClass( 'new' );
$lnk.addClass( 'userlink-redreplaced' );
}
})
//convert users into array
var users = [ ];
for ( var u in MarkBlockedPlus.userLinks ) { users.push( u ); }
if ( users.length === 0 ) { return; }
//API request
MarkBlockedPlus.apiRequests = 0;
MarkBlockedPlus.waitingCSS = mw.util.addCSS( 'a.userlink {opacity:' + MarkBlockedPlus.defaultPref(window.mbLoadingOpacity, 0.85) + '}' );
while ( users.length > 0 ) {
MarkBlockedPlus.apiRequests++;
var formattedUsers = users.splice(0,50).join('|');
$.post(
mw.util.wikiScript('api') + '?format=json&action=query',
{ list: 'blocks|users',
bklimit: 150, bkusers: formattedUsers, //XXX: I increased this limit from 100...could that cause problems?
bkprop: 'user|by|timestamp|expiry|reason',
uslimit: 51, ususers: formattedUsers, //+1 just to be safe (XXX: why? could this actually cause problems?)
usprop: 'groups|editcount|registration' },
MarkBlockedPlus.markLinks
)
}
return; //done sending API requests
}//-- end of reallyMarkBlocked
//callback: receive data and mark links
MarkBlockedPlus.markLinks = function ( resp, status, xhr ) {
function countRequestAsDone( bSuccess ) {
if( --MarkBlockedPlus.apiRequests == 0 ){ //last response
MarkBlockedPlus.waitingCSS.disabled = ( bSuccess || window.mbRemoveWaitingCSSOnError );
$( '#ca-showblocks' ).remove( ); //remove added portlet link (TODO: only if success?)
}
}
MarkBlockedPlus.wgServerTime = new Date( xhr.getResponseHeader( 'Date' ) );
var list, list2, blk, usr, tip, tip2, links, kmax, lnk, curLinkRW, curLinkOldTitle;
if( !resp ){
if ( window.mbReportApiErrors === true ){
MarkBlockedPlus.waitingCSS.disabled = window.mbRemoveWaitingCSSOnError;
throw new Error('markBlockedPlus: No response from API');
}
else{
countRequestAsDone(false); return;
}
}
if( !(list=resp.query) ){
if ( window.mbReportApiErrors === true ){
MarkBlockedPlus.waitingCSS.disabled = window.mbRemoveWaitingCSSOnError;
var errStr = 'markBlockedPlus: API error';
if ( resp.error ){
errStr += ': code: ' + resp.error.code + ', info: ' + resp.error.info;
}
throw new Error(errStr);
}
else{
countRequestAsDone(false); return;
}
}
else {
list2=list.users;
list=list.blocks;
}
var mbShowRegDate = window.mbShowRegDateAbs || window.mbShowRegDateRel;
var mbUsingNewFeatures = window.mbShowUnregistered || window.mbShowGroups || window.mbShowEditCount || mbShowRegDate;
var mbNewFeaturesValid = mbUsingNewFeatures && list2;
var userNSRX = new RegExp( '^' + '(' + MarkBlockedPlus.userNS.join('|') + ')', 'i' );
if ( list ){
for( var i=0; i<list.length; i++){
blk = list[i]
if( /^in/.test(blk.expiry) ){
clss = 'user-blocked-indef';
blTime = blk.expiry;
}else{
var rawBlTime = MarkBlockedPlus.parseTS(blk.expiry) - MarkBlockedPlus.parseTS(blk.timestamp);
var blTimeRem = MarkBlockedPlus.parseTS(blk.expiry) - MarkBlockedPlus.wgServerTime;
var timeToCheck = ( window.mbLongThreshIsRemainingTime === true ? blTimeRem : rawBlTime );
if ( typeof window.mbPseudoIndefThreshold == 'number' && timeToCheck >= window.mbPseudoIndefThreshold ) {
clss = 'user-blocked-indef';
}
else {
clss = 'user-blocked-temp';
if ( typeof window.mbLongThreshold == 'number' && timeToCheck >= window.mbLongThreshold ) clss += '2';
}
blTime = MarkBlockedPlus.inHours( rawBlTime );
}
if( blk.reason ) {
var preventive = /(pr(otec|even)t|in case|[ei]nsure)/i.test(blk.reason);
//TODO: uw-compblock blocks should not be considered preventive
if ( /(compr[io]mise|(been|got|was) ?hack|pass[- ]?word|hijack|uw-compblock|taken over)/i.test(blk.reason) ) {
clss += ( preventive ? ' user-blocked-preventcompromise' : ' user-blocked-compromised' );
}
if ( /(wiki[- ]?break|(self|user)[- ]?request|retir(ed|ement|ing))/i.test(blk.reason) && !( /\b(abus|ban|sock)/i.test(blk.reason) ) ) {
clss += ' user-blocked-wikibreakenforce';
}
if ( /decease|ha(d|s|ve) died|pass(ed|ing)? (away|on)|mortem/i.test(blk.reason) ) {
clss += ' user-blocked-deceased';
}
else if ( /is dead/i.test(blk.reason) && preventive ) {
clss += ' user-blocked-deceased';
}
}
if ( blk.user == blk.by ) clss += ' user-blocked-self';
tip = MarkBlockedPlus.tooltip.replace('$1', blTime).replace('$2', blk.by).replace('$3', blk.reason)
.replace('$4', MarkBlockedPlus.inHours( MarkBlockedPlus.wgServerTime - MarkBlockedPlus.parseTS(blk.timestamp) ) );
links = MarkBlockedPlus.userLinks[blk.user];
kmax = ( links === undefined ? 0 : links.length ); //TODO: add error reporting
for (var k=0; k<kmax; k++){
lnk = $(links[k]).addClass(clss);
curLinkRW = '';
curLinkOldTitle = lnk.attr('title') + '';
if( MarkBlockedPlus.showRedirectWarning && !mbNewFeaturesValid && ( lnk.hasClass( 'redirect' ) || lnk.hasClass( 'mw-redirect' ) ) ){
if ( userNSRX.test( MarkBlockedPlus.skipLCAppend( curLinkOldTitle ) ) === false ) {
curLinkRW = '\nBlock log for ' + blk.user + '; redirects outside this wiki\'s user namespaces';
lnk.addClass( 'userlink-redirnonuser' );
}
else if ( MarkBlockedPlus.tipNameDiffers( curLinkOldTitle, blk.user ) ) {
curLinkRW = '\nBlock log for ' + blk.user + '; redirects to other username or IP';
lnk.addClass( 'userlink-redirothername' );
}
}
if( window.mbTipBox === true ){
$('<span class="user-blocked-tipbox">'+MarkBlockedPlus.defaultPref( window.mbTipBoxText, 'B' )+'</span>').attr('title', tip.substr(MarkBlockedPlus.tipBoxCharsToTrim) + curLinkRW).insertBefore(lnk);
}else{
if ( lnk.children( ) ) lnk.children( ).removeAttr( 'title' );
lnk.attr( 'title', curLinkOldTitle + tip + curLinkRW );
}
}
}
}
if ( mbNewFeaturesValid ){
for( var i=0; i<list2.length; i++){
usr = list2[i];
tip2 = '';
if( usr.missing === '' ){
if( window.mbShowUnregistered === true ) tip2 = MarkBlockedPlus.defaultPref( window.mbUnregisteredText, '\nnot registered' )
}
else if( usr.invalid !== '' ){
if ( (window.mbShowGroups === true) && usr.groups ){
tip2 += '\n' + MarkBlockedPlus.remStar( usr.groups );
}
if ( (window.mbShowEditCount === true) && usr.editcount ){
tip2 += '\n' + usr.editcount + ' edit';
if ( usr.editcount != '1' ) tip2 += 's';
if ( mbShowRegDate && usr.registration ){
tip2 += ' since ';
if ( (window.mbShowRegDateAbs === true) && (window.mbShowRegDateRel === true) ){
tip2 += usr.registration + ' (' + MarkBlockedPlus.inHours( MarkBlockedPlus.wgServerTime - MarkBlockedPlus.parseTS(usr.registration) ) + ' ago)';
}
else if ( window.mbShowRegDateAbs === true ){
tip2 += usr.registration;
}
else /* relative only */{
tip2 += MarkBlockedPlus.inHours( MarkBlockedPlus.wgServerTime - MarkBlockedPlus.parseTS(usr.registration) ) + ' ago';
}
}
}
else{
if ( mbShowRegDate && usr.registration ){
tip2 += '\ncreated ';
if ( (window.mbShowRegDateAbs === true) && (window.mbShowRegDateRel === true) ){
tip2 += usr.registration + ' (' + MarkBlockedPlus.inHours( MarkBlockedPlus.wgServerTime - MarkBlockedPlus.parseTS(usr.registration) ) + ' ago)';
}
else if ( window.mbShowRegDateAbs === true ){
tip2 += usr.registration;
}
else /* relative only */{
tip2 += MarkBlockedPlus.inHours( MarkBlockedPlus.wgServerTime - MarkBlockedPlus.parseTS(usr.registration) ) + ' ago';
}
}
}
}
links = MarkBlockedPlus.userLinks[usr.name];
kmax = ( links === undefined ? 0 : links.length ); //TODO: add error reporting
for (var k=0; k<kmax; k++){
lnk = $(links[k]);
curLinkRW = '';
curLinkOldTitle = lnk.attr('title') + '';
if ( MarkBlockedPlus.showRedirectWarning && ( lnk.hasClass( 'redirect' ) || lnk.hasClass( 'mw-redirect' ) ) ){
if ( userNSRX.test( MarkBlockedPlus.skipLCAppend( curLinkOldTitle ) ) === false ) {
curLinkRW = '\nInfo shown for ' + usr.name + '; redirects outside this wiki\'s user namespaces';
lnk.addClass( 'userlink-redirnonuser' );
}
else if ( MarkBlockedPlus.tipNameDiffers( curLinkOldTitle, usr.name ) ) {
curLinkRW = '\nInfo shown for ' + usr.name + '; redirects to other username or IP';
lnk.addClass( 'userlink-redirothername' );
}
}
if( (window.mbTipBoxInfo === true) && tip2 != '' ){
$('<span class="user-info-tipbox">'+MarkBlockedPlus.defaultPref( window.mbTipBoxInfoText, 'i' )+'</span>').attr('title', tip2.substr(1) + curLinkRW).insertBefore(lnk)
}else{
if ( lnk.children( ) ) lnk.children( ).removeAttr( 'title' );
lnk.attr( 'title', curLinkOldTitle + tip2 + curLinkRW );
}
if ( usr.missing === '' ) { lnk.addClass( 'userlink-missing' ); }
}
}
}
countRequestAsDone(true);
} //-- end of markLinks
//--------AUX functions
//20081226220605 or 2008-01-26T06:34:19Z -> date
MarkBlockedPlus.parseTS = function ( ts ) {
var m = ts.replace(/\D/g,'').match(/(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/);
return new Date ( Date.UTC(m[1], m[2]-1, m[3], m[4], m[5], m[6]) );
}
//milliseconds -> "2:30" or 5d 6h or 21d
MarkBlockedPlus.inHours = function ( ms ) {
var mm = Math.round(ms/60000);
if( !mm ) return Math.round(ms/1000)+'s';
var hh = Math.floor(mm/60); mm %= 60;
var dd = Math.floor(hh/24); hh %= 24;
var yy = Math.floor(dd/365);
if ( yy && ( window.mbShowYears === true ) ){
dd %= 365;
return yy + (dd ? 'yr ' + dd + 'd' : 'yr');
}
else if (dd) return dd + 'd' + ((dd<10 && hh>0)?' '+hh+'h':'');
else return hh + ':' + MarkBlockedPlus.leadZero(mm);
}
//add leading zero to single digits: 6 -> '06'
//was named "zz" in original markblocked
MarkBlockedPlus.leadZero = function ( v ) {
if( v <= 9 ) v = '0' + v;
return v;
}
MarkBlockedPlus.remStar = function ( oldGrps ) {
var cleanGrps = [ ];
for ( var i = 0; i < oldGrps.length; i++ ) {
if ( oldGrps[i] != '*' ) cleanGrps.push( oldGrps[i] );
}
return cleanGrps;
}
MarkBlockedPlus.skipLCAppend = function ( ttip ) {
var myTtip = ttip;
if ( window.LinkClassifierRedirTitleAppend === true ) {
var lcAppendStrToCheck = '\n⤷';
var lcAppendedMsgPos = myTtip.indexOf( lcAppendStrToCheck );
myTtip = myTtip.substr( lcAppendedMsgPos + lcAppendStrToCheck.length );
}
return myTtip;
}
MarkBlockedPlus.tipNameDiffers = function ( ttip, usrnm ) {
var myTtip = MarkBlockedPlus.skipLCAppend( ttip );
var startPos = myTtip.indexOf( ':' );
if ( startPos <= 0 ) return false; //no valid username found - don't show warning
var fragEnd = MarkBlockedPlus.tooltip.indexOf( '$' );
var fragment;
if ( fragEnd == -1 ) {
fragment = MarkBlockedPlus.tooltip;
}
else if ( fragEnd == 0 ) {
//TODO: To handle this case properly, we should pass the actual values of the
//$-parameters into this function. Until then, document that window.mbTooltip
//should not begin with $
fragment = 'This wont' + Math.random( ) + 'match anything';
}
else {
fragment = MarkBlockedPlus.tooltip.substr( 0, fragEnd );
}
var slashPos = myTtip.indexOf( '/' ); if ( slashPos == -1 ) slashPos = myTtip.length;
var anchorPos = myTtip.indexOf( '#' ); if ( anchorPos == -1 ) anchorPos = myTtip.length;
var lineBrkPos = myTtip.indexOf( '\n' ); if ( lineBrkPos == -1 ) lineBrkPos = myTtip.length;
var blkMsgPos = myTtip.indexOf( fragment ); if ( blkMsgPos == -1 ) blkMsgPos = myTtip.length;
var endPos = Math.min( slashPos, anchorPos, lineBrkPos, blkMsgPos );
startPos++;
if ( endPos <= startPos ) return false; //no valid username found - don't show warning
return ( usrnm != myTtip.substr( startPos, endPos - startPos ) );
}
//start on some pages, making sure [[User:SoledadKabocha/linkclassifier2.js]] has finished
//NB: As documented, LinkClassifierChainedFunc should be a wrapper function
// that calls importScript on this script, or else we might finish loading before linkclassifier
// does, causing us not to detect the linkclassifier installation
MarkBlockedPlus.setup = function ( ) {
// If the wiki supports ResourceLoader, make sure mw.util has loaded
if ( mw.loader && typeof mw.loader.using === 'function' ) {
mw.loader.using( [ 'mediawiki.util' ], function ( ) {
/* dummy
XXX: this might not be useful as written...
*/
});
}
var linkclassifierDetected = typeof LinkClassifier === 'object';
MarkBlockedPlus.showRedirectWarning =
MarkBlockedPlus.showRedirectWarning && linkclassifierDetected;
//don't really need strict comparisons here
var shouldWaitForLinkClassifier = linkclassifierDetected &&
window.LinkClassifierSupportsFuncChain &&
!window.LinkClassifierOnDemand &&
!window.mbNoAutoStart;
if ( shouldWaitForLinkClassifier ) {
if ( window.mbLinkClassifierTimeoutHack ) {
var wBRT = mw.config.get( 'wgBackendResponseTime' );
if ( typeof wBRT !== 'number' || !isFinite( wBRT ) ) { wBRT = 100; }
else { wBRT = Math.min( Math.max( wBRT, 50 ), 1000 ); }
var rndTOMin = Math.round( Math.sqrt( wBRT ) * Math.log1p( wBRT ) );
var rndTOMax = Math.round( wBRT * Math.E );
var rndTO = rndTOMin + Math.floor( Math.random( ) * ( rndTOMax - rndTOMin + 1 ) );
if ( typeof window.LinkClassifierChainedFunc === 'function' ) {
//Don't overwrite the function if it exists, because it may already have been called.
//It might have been used to import us, after all.
setTimeout( markBlocked, rndTO );
}
else {
window.LinkClassifierChainedFunc = function ( ) {
setTimeout( markBlocked, rndTO );
}
}
}
else {
if ( typeof window.LinkClassifierChainedFunc === 'function' ) {
markBlocked( );
}
else {
window.LinkClassifierChainedFunc = markBlocked;
}
}
}
else
$(function(){
if( window.mbNoAutoStart === true ) {
var plnk = mw.util.addPortletLink( MarkBlockedPlus.defaultPref( window.mbOnDemandLinkLoc, 'p-cactions' ),
'#mb-' + Math.random( ),
MarkBlockedPlus.defaultPref( window.mbOnDemandLinkText, 'XX' ),
'ca-showblocks'
);
$( plnk ).click( function ( e ) {
e.preventDefault( );
markBlocked( );
});
}
else { markBlocked( ); }
})
}
switch ( mw.config.get( 'wgAction' ) ) {
case 'edit':
case 'submit':
if ( window.mbEnableWhenEditing ) { MarkBlockedPlus.setup( ); }
break;
case 'purge':
//shouldn't happen on recent MW; action=purge should redirect (or prompt for confirmation?) rather than showing page content
//just give up
break;
case 'view':
if ( mw.config.get( 'wgNamespaceNumber' ) === 0 && !( window.mbEnableOnMainspaceDiff === true && document.URL.indexOf( 'diff=' ) != -1 ) ) { break; }
//otherwise continue with default
default: //'history', etc.
MarkBlockedPlus.setup( );
}