MediaWiki:Gadget-Twinkle.js: Difference between revisions

Jump to navigation Jump to search
Content added Content deleted
imported>AzaToth
m (v2.0-556-g0beacc0: use .utc() for timestamps and format them the sme way as the wiki does)
 
(create)
Line 17: Line 17:
* every Wikipedian in between. Visit [[WP:TW]] for more information.
* every Wikipedian in between. Visit [[WP:TW]] for more information.
*/
*/

//<nowiki>
//<nowiki>

( function ( window, document, $, undefined ) { // Wrap with anonymous function
( function ( window, document, $, undefined ) { // Wrap with anonymous function

var Twinkle = {};
var Twinkle = {};
window.Twinkle = Twinkle; // allow global access
window.Twinkle = Twinkle; // allow global access

// Check if account is experienced enough to use Twinkle
// Check if account is experienced enough to use Twinkle
Twinkle.userAuthorized = Morebits.userIsInGroup( "autoconfirmed" ) || Morebits.userIsInGroup( "confirmed" );
Twinkle.userAuthorized = Morebits.userIsInGroup( "autoconfirmed" ) || Morebits.userIsInGroup( "confirmed" );

// for use by custom modules (normally empty)
// for use by custom modules (normally empty)
Twinkle.initCallbacks = [];
Twinkle.initCallbacks = [];
Twinkle.addInitCallback = function twinkleAddInitCallback( func ) {
Twinkle.addInitCallback = function twinkleAddInitCallback( func ) {
Twinkle.initCallbacks.push( func );
Twinkle.initCallbacks.push( func );
};
};

Twinkle.defaultConfig = {};
Twinkle.defaultConfig = {};
/**
/**
Line 45: Line 45:
Twinkle.defaultConfig.twinkle = {
Twinkle.defaultConfig.twinkle = {
// General
// General
summaryAd: " ([[WP:TW|TW]])",
summaryAd: " ([[TW:TW|TW]])",
deletionSummaryAd: " ([[WP:TW|TW]])",
deletionSummaryAd: " ([[TW:TW|TW]])",
protectionSummaryAd: " ([[WP:TW|TW]])",
protectionSummaryAd: " ([[TW:TW|TW]])",
userTalkPageMode: "window",
userTalkPageMode: "window",
dialogLargeFont: false,
dialogLargeFont: false,
Line 111: Line 111:
proddeleteChunks: 50
proddeleteChunks: 50
};
};

// now some skin dependent config.
// now some skin dependent config.
if ( mw.config.get( "skin" ) === "vector" ) {
if ( mw.config.get( "skin" ) === "vector" ) {
Line 126: Line 126:
Twinkle.defaultConfig.twinkle.portletNext = null;
Twinkle.defaultConfig.twinkle.portletNext = null;
}
}

Twinkle.defaultConfig.friendly = {
Twinkle.defaultConfig.friendly = {
// Tag
// Tag
Line 156: Line 156:
markSharedIPAsMinor: true
markSharedIPAsMinor: true
};
};

Twinkle.getPref = function twinkleGetPref( name ) {
Twinkle.getPref = function twinkleGetPref( name ) {
var result;
var result;
Line 166: Line 166:
result = window.TwinkleConfig[name];
result = window.TwinkleConfig[name];
}
}

if ( result === undefined ) {
if ( result === undefined ) {
return Twinkle.defaultConfig.twinkle[name];
return Twinkle.defaultConfig.twinkle[name];
Line 172: Line 172:
return result;
return result;
};
};

Twinkle.getFriendlyPref = function twinkleGetFriendlyPref(name) {
Twinkle.getFriendlyPref = function twinkleGetFriendlyPref(name) {
var result;
var result;
Line 182: Line 182:
result = window.FriendlyConfig[ name ];
result = window.FriendlyConfig[ name ];
}
}

if ( result === undefined ) {
if ( result === undefined ) {
return Twinkle.defaultConfig.friendly[ name ];
return Twinkle.defaultConfig.friendly[ name ];
Line 188: Line 188:
return result;
return result;
};
};



/**
/**
* **************** Twinkle.addPortlet() ****************
* **************** Twinkle.addPortlet() ****************
Line 226: Line 226:
return null;
return null;
}
}

var item = document.getElementById( id );
var item = document.getElementById( id );
if ( item ) {
if ( item ) {
Line 234: Line 234:
return null;
return null;
}
}

var nextnode;
var nextnode;
if ( nextnodeid ) {
if ( nextnodeid ) {
nextnode = document.getElementById(nextnodeid);
nextnode = document.getElementById(nextnodeid);
}
}

//verify/normalize input
//verify/normalize input
type = ( skin === "vector" && type === "menu" && ( navigation === "left-navigation" || navigation === "right-navigation" )) ? "menu" : "";
type = ( skin === "vector" && type === "menu" && ( navigation === "left-navigation" || navigation === "right-navigation" )) ? "menu" : "";
Line 266: Line 266:
break;
break;
}
}

// Build the DOM elements.
// Build the DOM elements.
var outerDiv = document.createElement( "div" );
var outerDiv = document.createElement( "div" );
Line 281: Line 281:
root.appendChild( outerDiv );
root.appendChild( outerDiv );
}
}

var h5 = document.createElement( "h3" );
var h5 = document.createElement( "h3" );
if ( type === "menu" ) {
if ( type === "menu" ) {
Line 287: Line 287:
span.appendChild( document.createTextNode( text ) );
span.appendChild( document.createTextNode( text ) );
h5.appendChild( span );
h5.appendChild( span );

var a = document.createElement( "a" );
var a = document.createElement( "a" );
a.href = "#";
a.href = "#";

$( a ).click(function ( e ) {
$( a ).click(function ( e ) {
e.preventDefault();
e.preventDefault();

if ( !Twinkle.userAuthorized ) {
if ( !Twinkle.userAuthorized ) {
alert("Sorry, your account is too new to use Twinkle.");
alert("Sorry, your account is too new to use Twinkle.");
}
}
});
});

span = document.createElement( "span" );
span = document.createElement( "span" );
span.appendChild( document.createTextNode( text ) );
span.appendChild( document.createTextNode( text ) );
Line 307: Line 307:
}
}
outerDiv.appendChild( h5 );
outerDiv.appendChild( h5 );

var innerDiv = document.createElement( "div" ); // Not strictly necessary with type vectorTabs, or other skins.
var innerDiv = document.createElement( "div" ); // Not strictly necessary with type vectorTabs, or other skins.
innerDiv.className = innerDivClass;
innerDiv.className = innerDivClass;
outerDiv.appendChild(innerDiv);
outerDiv.appendChild(innerDiv);

var ul = document.createElement( "ul" );
var ul = document.createElement( "ul" );
innerDiv.appendChild( ul );
innerDiv.appendChild( ul );

return outerDiv;
return outerDiv;
};
}


/**
/**
* **************** Twinkle.addPortletLink() ****************
* **************** Twinkle.addPortletLink() ****************
Line 337: Line 337:
}
}
return link;
return link;
};
}


/**
/**
* **************** General initialization code ****************
* General initialization code
*/
*/

var scriptpathbefore = mw.util.wikiScript( "index" ) + "?title=",
var scriptpathbefore = mw.util.wikiScript( "index" ) + "?title=",
scriptpathafter = "&action=raw&ctype=text/javascript&happy=yes";
scriptpathafter = "&action=raw&ctype=text/javascript&happy=yes";

// Retrieve the user's Twinkle preferences
// Retrieve the user's Twinkle preferences
$.ajax({
$.ajax({
url: scriptpathbefore + "User:" + encodeURIComponent( mw.config.get("wgUserName")) + "/twinkleoptions.js" + scriptpathafter,
url: scriptpathbefore + "User:" + encodeURIComponent( mw.config.get("wgUserName")) + "/twinkleoptions.js" + scriptpathafter,
dataType: "text"
dataType: "text",
error: function () { mw.util.jsMessage( "Could not load twinkleoptions.js" ); },
})
success: function ( optionsText ) {
.fail(function () { mw.util.jsMessage( "Could not load twinkleoptions.js" ); })
.done(function ( optionsText ) {

// Quick pass if user has no options
// Quick pass if user has no options
if ( optionsText === "" ) {
if ( optionsText === "" ) {
return;
return;
}
}

// Twinkle options are basically a JSON object with some comments. Strip those:
// Twinkle options are basically a JSON object with some comments. Strip those:
optionsText = optionsText.replace( /(?:^(?:\/\/[^\n]*\n)*\n*|(?:\/\/[^\n]*(?:\n|$))*$)/g, "" );
optionsText = optionsText.replace( /(?:^(?:\/\/[^\n]*\n)*\n*|(?:\/\/[^\n]*(?:\n|$))*$)/g, "" );

// First version of options had some boilerplate code to make it eval-able -- strip that too. This part may become obsolete down the line.
// First version of options had some boilerplate code to make it eval-able -- strip that too. This part may become obsolete down the line.
if ( optionsText.lastIndexOf( "window.Twinkle.prefs = ", 0 ) === 0 ) {
if ( optionsText.lastIndexOf( "window.Twinkle.prefs = ", 0 ) === 0 ) {
optionsText = optionsText.replace( /(?:^window.Twinkle.prefs = |;\n*$)/g, "" );
optionsText = optionsText.replace( /(?:^window.Twinkle.prefs = |;\n*$)/g, "" );
}
}

try {
try {
var options = $.parseJSON( optionsText );
var options = $.parseJSON( optionsText );

// Assuming that our options evolve, we will want to transform older versions:
// Assuming that our options evolve, we will want to transform older versions:
//if ( options.optionsVersion === undefined ) {
//if ( options.optionsVersion === undefined ) {
Line 381: Line 378:
//}
//}
// At the same time, twinkleconfig.js needs to be adapted to write a higher version number into the options.
// At the same time, twinkleconfig.js needs to be adapted to write a higher version number into the options.

if ( options ) {
if ( options ) {
Twinkle.prefs = options;
Twinkle.prefs = options;
Line 389: Line 386:
mw.util.jsMessage("Could not parse twinkleoptions.js");
mw.util.jsMessage("Could not parse twinkleoptions.js");
}
}
})
},
.always(function () {
complete: function () {
$( Twinkle.load );
$( Twinkle.load );
});
}
});

// Developers: you can import custom Twinkle modules here
// Developers: you can import custom Twinkle modules here
// For example, mw.loader.load(scriptpathbefore + "User:UncleDouggie/morebits-test.js" + scriptpathafter);
// For example, mw.loader.load(scriptpathbefore + "User:UncleDouggie/morebits-test.js" + scriptpathafter);

Twinkle.load = function () {
Twinkle.load = function () {
// Don't activate on special pages other than "Contributions" so that they load faster, especially the watchlist.
// Don't activate on special pages other than "Contributions" so that they load faster, especially the watchlist.
Line 402: Line 400:
&& mw.config.get('wgCanonicalSpecialPageName') !== "Contributions"
&& mw.config.get('wgCanonicalSpecialPageName') !== "Contributions"
&& mw.config.get('wgCanonicalSpecialPageName') !== "Prefixindex" ),
&& mw.config.get('wgCanonicalSpecialPageName') !== "Prefixindex" ),

// Also, Twinkle is incompatible with Internet Explorer versions 8 or lower, so don't load there either.
// Also, Twinkle is incompatible with Internet Explorer versions 8 or lower, so don't load there either.
isOldIE = ( $.client.profile().name === 'msie' && $.client.profile().versionNumber < 9 );
isOldIE = ( $.client.profile().name === 'msie' && $.client.profile().versionNumber < 9 );

// Prevent users that are not autoconfirmed from loading Twinkle as well.
// Prevent users that are not autoconfirmed from loading Twinkle as well.
if ( isSpecialPage || isOldIE || !Twinkle.userAuthorized ) {
if ( isSpecialPage || isOldIE || !Twinkle.userAuthorized ) {
return;
return;
}
}

// Load the modules in the order that the tabs should appears
// Load the modules in the order that the tabs should appears
// User/user talk-related
// User/user talk-related
Line 416: Line 414:
Twinkle.warn();
Twinkle.warn();
Twinkle.welcome();
Twinkle.welcome();
Twinkle.shared();
Twinkle.talkback();
Twinkle.talkback();
// Deletion
// Deletion
Twinkle.speedy();
Twinkle.speedy();
Twinkle.prod();
Twinkle.xfd();
Twinkle.image();
Twinkle.image();
// Maintenance
// Maintenance
Twinkle.protect();
Twinkle.protect();
Twinkle.tag();
// Misc. ones last
// Misc. ones last
Twinkle.diff();
Twinkle.diff();
Line 441: Line 435:
$( Twinkle.initCallbacks ).each(function ( k, v ) { v(); });
$( Twinkle.initCallbacks ).each(function ( k, v ) { v(); });
Twinkle.addInitCallback = function ( func ) { func(); };
Twinkle.addInitCallback = function ( func ) { func(); };

// Increases text size in Twinkle dialogs, if so configured
// Increases text size in Twinkle dialogs, if so configured
if ( Twinkle.getPref( "dialogLargeFont" ) ) {
if ( Twinkle.getPref( "dialogLargeFont" ) ) {
Line 448: Line 442:
}
}
};
};

} ( window, document, jQuery )); // End wrap with anonymous function
} ( window, document, jQuery )); // End wrap with anonymous function

// </nowiki>
// </nowiki>