Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Upload each module separate to the wiki

Due to bug https://bugzilla.wikimedia.org/show_bug.cgi?id=29784
It's recommended to split twinkle up in multiple files

Remember to add
twinkleprod.js|twinkleimage.js|twinklebatchundelete.js|twinklewarn.js|twinklespeedy.js|friendlyshared.js
|twinklediff.js|twinkleunlink.js|twinkledelimages.js|friendlytag.js|twinkledeprod.js|friendlywelcome.js
|twinklexfd.js|twinklebatchdelete.js|twinklebatchprotect.js|twinkleconfig.js|twinklefluff.js
|twinkleprotect.js|twinklearv.js|friendlytalkback.js
to gadget-definition when deploying
  • Loading branch information...
commit ea60cc0536b72ce8a8d3524003b3d0729bf93e61 1 parent dca826d
Carl Fürstenberg authored
1  .gitignore
View
@@ -2,7 +2,6 @@
alltwinkle.js
/.settings
/.project
-/twinkle.js
jsl.conf
stash*.txt
stash*.diff
36 Makefile
View
@@ -1,17 +1,27 @@
-all: twinkle.js
+all:
-twinkle.min.js: twinkle.js
- uglifyjs --output $@ $^
+modules = modules/twinkleprod.js \
+ modules/twinkleimage.js \
+ modules/twinklebatchundelete.js \
+ modules/twinklewarn.js \
+ modules/twinklespeedy.js \
+ modules/friendlyshared.js \
+ modules/twinklediff.js \
+ modules/twinkleunlink.js \
+ modules/twinkledelimages.js \
+ modules/friendlytag.js \
+ modules/twinkledeprod.js \
+ modules/friendlywelcome.js \
+ modules/twinklexfd.js \
+ modules/twinklebatchdelete.js \
+ modules/twinklebatchprotect.js \
+ modules/twinkleconfig.js \
+ modules/twinklefluff.js \
+ modules/twinkleprotect.js \
+ modules/twinklearv.js \
+ modules/friendlytalkback.js
-
-twinkle.js: twinkle.header.js $(wildcard modules/*.js) twinkle.footer.js
- awk 'FNR==1{print ""}{print}' $^ > $@
-
-
-deploy: twinkle.js morebits.js morebits.css
+deploy: twinkle.js morebits.js morebits.css $(modules)
./sync.pl --deploy $^
-clean:
- rm -f twinkle.js twinkle.min.js
-
-.PHONY: deploy clean
+.PHONY: deploy all
4 modules/friendlyshared.js
View
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** friendlyshared.js: Shared IP tagging module
@@ -186,3 +189,4 @@ Twinkle.shared.callback.evaluate = function friendlysharedCallbackEvaluate(e) {
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.shared.callbacks.main);
};
+})(jQuery);
4 modules/friendlytag.js
View
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** friendlytag.js: Tag module
@@ -1334,3 +1337,4 @@ Twinkle.tag.callback.evaluate = function friendlytagCallbackEvaluate(e) {
break;
}
};
+})(jQuery);
4 modules/friendlytalkback.js
View
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** friendlytalkback.js: Talkback module
@@ -345,3 +348,4 @@
};
}());
+})(jQuery);
4 modules/friendlywelcome.js
View
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** friendlywelcome.js: Welcome module
@@ -716,3 +719,4 @@ Twinkle.welcome.callback.evaluate = function friendlywelcomeCallbackEvaluate(e)
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.welcome.callbacks.main);
};
+})(jQuery);
4 modules/twinklearv.js
View
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinklearv.js: ARV module
@@ -773,3 +776,4 @@ Twinkle.arv.processAN3 = function( params ) {
Morebits.wiki.removeCheckpoint(); // all page updates have been started
}
+})(jQuery);
4 modules/twinklebatchdelete.js
View
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinklebatchdelete.js: Batch delete module (sysops only)
@@ -379,3 +382,4 @@ Twinkle.batchdelete.callbacks = {
pageobj.save(params.onsuccess);
}
};
+})(jQuery);
4 modules/twinklebatchprotect.js
View
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinklebatchprotect.js: Batch protect module (sysops only)
@@ -417,3 +420,4 @@ Twinkle.batchprotect.callbacks = {
} );
}
};
+})(jQuery);
4 modules/twinklebatchundelete.js
View
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinklebatchundelete.js: Batch undelete module
@@ -123,3 +126,4 @@ Twinkle.batchundelete.callbacks = {
}
}
};
+})(jQuery);
4 modules/twinkleconfig.js
View
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinkleconfig.js: Preferences module
@@ -1748,3 +1751,4 @@ Twinkle.config.saveSuccess = function twinkleconfigSaveSuccess(pageobj) {
noticeclear.style.clear = "both";
Morebits.status.root.appendChild(noticeclear);
};
+})(jQuery);
4 modules/twinkledelimages.js
View
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinkledelimages.js: Batch deletion of images (sysops only)
@@ -221,3 +224,4 @@ Twinkle.delimages.callbacks = {
self.save();
}
};
+})(jQuery);
4 modules/twinkledeprod.js
View
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinkledeprod.js: Batch deletion of expired PRODs (sysops only)
@@ -155,3 +158,4 @@
});
};
}());
+})(jQuery);
4 modules/twinklediff.js
View
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinklediff.js: Diff module
@@ -80,3 +83,4 @@ Twinkle.diff.callbacks = {
window.location = mw.util.wikiScript('index') + '?' + Morebits.queryString.create( query );
}
};
+})(jQuery);
4 modules/twinklefluff.js
View
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinklefluff.js: Revert/rollback module
@@ -555,3 +558,4 @@ Twinkle.fluff.init = function twinklefluffinit() {
}
}
};
+})(jQuery);
4 modules/twinkleimage.js
View
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinkleimage.js: Image CSD module
@@ -339,3 +342,4 @@ Twinkle.image.callbacks = {
}
}
};
+})(jQuery);
4 modules/twinkleprod.js
View
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinkleprod.js: PROD module
@@ -320,3 +323,4 @@ Twinkle.prod.callback.evaluate = function twinkleprodCallbackEvaluate(e) {
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.prod.callbacks.main);
};
+})(jQuery);
4 modules/twinkleprotect.js
View
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinkleprotect.js: Protect/RPP module
@@ -1254,3 +1257,4 @@ Twinkle.protect.callbacks = {
rppPage.save();
}
};
+})(jQuery);
4 modules/twinklespeedy.js
View
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinklespeedy.js: CSD module
@@ -1613,3 +1616,4 @@ Twinkle.speedy.callback.evaluateUser = function twinklespeedyCallbackEvaluateUse
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.speedy.callbacks.user.main);
};
+})(jQuery);
4 modules/twinkleunlink.js
View
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinkleunlink.js: Unlink module
@@ -273,3 +276,4 @@ Twinkle.unlink.callbacks = {
}
}
};
+})(jQuery);
4 modules/twinklewarn.js
View
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinklewarn.js: Warn module
@@ -1753,3 +1756,4 @@ Twinkle.warn.callback.evaluate = function twinklewarnCallbackEvaluate(e) {
wikipedia_page.setFollowRedirect( true );
wikipedia_page.load( Twinkle.warn.callbacks.main );
};
+})(jQuery);
4 modules/twinklexfd.js
View
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinklexfd.js: XFD module
@@ -1695,3 +1698,4 @@ Twinkle.xfd.callback.evaluate = function(e) {
break;
}
};
+})(jQuery);
22 sync.pl
View
@@ -41,7 +41,27 @@
my %deploys = (
'twinkle.js' => 'MediaWiki:Gadget-Twinkle.js',
'morebits.js' => 'MediaWiki:Gadget-morebits.js',
- 'morebits.css' => 'MediaWiki:Gadget-morebits.css'
+ 'morebits.css' => 'MediaWiki:Gadget-morebits.css',
+ 'modules/twinkleprod.js' => 'MediaWiki:Gadget-twinkleprod.js',
+ 'modules/twinkleimage.js' => 'MediaWiki:Gadget-twinkleimage.js',
+ 'modules/twinklebatchundelete.js' => 'MediaWiki:Gadget-twinklebatchundelete.js',
+ 'modules/twinklewarn.js' => 'MediaWiki:Gadget-twinklewarn.js',
+ 'modules/twinklespeedy.js' => 'MediaWiki:Gadget-twinklespeedy.js',
+ 'modules/friendlyshared.js' => 'MediaWiki:Gadget-friendlyshared.js',
+ 'modules/twinklediff.js' => 'MediaWiki:Gadget-twinklediff.js',
+ 'modules/twinkleunlink.js' => 'MediaWiki:Gadget-twinkleunlink.js',
+ 'modules/twinkledelimages.js' => 'MediaWiki:Gadget-twinkledelimages.js',
+ 'modules/friendlytag.js' => 'MediaWiki:Gadget-friendlytag.js',
+ 'modules/twinkledeprod.js' => 'MediaWiki:Gadget-twinkledeprod.js',
+ 'modules/friendlywelcome.js' => 'MediaWiki:Gadget-friendlywelcome.js',
+ 'modules/twinklexfd.js' => 'MediaWiki:Gadget-twinklexfd.js',
+ 'modules/twinklebatchdelete.js' => 'MediaWiki:Gadget-twinklebatchdelete.js',
+ 'modules/twinklebatchprotect.js' => 'MediaWiki:Gadget-twinklebatchprotect.js',
+ 'modules/twinkleconfig.js' => 'MediaWiki:Gadget-twinkleconfig.js',
+ 'modules/twinklefluff.js' => 'MediaWiki:Gadget-twinklefluff.js',
+ 'modules/twinkleprotect.js' => 'MediaWiki:Gadget-twinkleprotect.js',
+ 'modules/twinklearv.js' => 'MediaWiki:Gadget-twinklearv.js',
+ 'modules/friendlytalkback.js' => 'MediaWiki:Gadget-friendlytalkback.js'
);
# Config file should be an hash consisting of username and password keys
451 twinkle.js
View
@@ -0,0 +1,451 @@
+/**
+ * +-------------------------------------------------------------------------+
+ * | === WARNING: GLOBAL GADGET FILE === |
+ * | Changes to this page affect many users. |
+ * | Please discuss changes at [[WT:TW]] before editing. |
+ * +-------------------------------------------------------------------------+
+ *
+ * Imported from github [https://github.com/azatoth/twinkle].
+ * All changes should be made in the repository, otherwise they will be lost.
+ *
+ * To update this script from github, you must have a local repository set up. Then
+ * follow the instructions at [https://github.com/azatoth/twinkle/blob/master/README.md].
+ *
+ * ----------
+ *
+ * This is AzaToth's Twinkle, the popular script sidekick for newbies, admins, and
+ * every Wikipedian in between. Visit [[WP:TW]] for more information.
+ */
+
+//<nowiki>
+
+( function ( window, document, $, undefined ) { // Wrap with anonymous function
+
+var Twinkle = {};
+window.Twinkle = Twinkle; // allow global access
+
+// Check if account is experienced enough to use Twinkle
+var twinkleUserAuthorized = Morebits.userIsInGroup( "autoconfirmed" ) || Morebits.userIsInGroup( "confirmed" );
+
+// for use by custom modules (normally empty)
+Twinkle.initCallbacks = [];
+Twinkle.addInitCallback = function twinkleAddInitCallback( func ) {
+ Twinkle.initCallbacks.push( func );
+};
+
+Twinkle.defaultConfig = {};
+/**
+ * Twinkle.defaultConfig.twinkle and Twinkle.defaultConfig.friendly
+ *
+ * This holds the default set of preferences used by Twinkle. (The |friendly| object holds preferences stored in the FriendlyConfig object.)
+ * It is important that all new preferences added here, especially admin-only ones, are also added to
+ * |Twinkle.config.sections| in twinkleconfig.js, so they are configurable via the Twinkle preferences panel.
+ * For help on the actual preferences, see the comments in twinkleconfig.js.
+ */
+Twinkle.defaultConfig.twinkle = {
+ // General
+ summaryAd: " ([[WP:TW|TW]])",
+ deletionSummaryAd: " ([[WP:TW|TW]])",
+ protectionSummaryAd: " ([[WP:TW|TW]])",
+ userTalkPageMode: "window",
+ dialogLargeFont: false,
+ // Fluff (revert and rollback)
+ openTalkPage: [ "agf", "norm", "vand" ],
+ openTalkPageOnAutoRevert: false,
+ markRevertedPagesAsMinor: [ "vand" ],
+ watchRevertedPages: [ "agf", "norm", "vand", "torev" ],
+ offerReasonOnNormalRevert: true,
+ confirmOnFluff: false,
+ showRollbackLinks: [ "diff", "others" ],
+ // DI (twinkleimage)
+ notifyUserOnDeli: true,
+ deliWatchPage: "default",
+ deliWatchUser: "default",
+ // PROD
+ watchProdPages: true,
+ prodReasonDefault: "",
+ logProdPages: false,
+ prodLogPageName: "PROD log",
+ // CSD
+ speedySelectionStyle: "buttonClick",
+ speedyPromptOnG7: false,
+ watchSpeedyPages: [ "g3", "g5", "g10", "g11", "g12" ],
+ markSpeedyPagesAsPatrolled: true,
+ // these next two should probably be identical by default
+ notifyUserOnSpeedyDeletionNomination: [ "db", "g1", "g2", "g3", "g4", "g6", "g10", "g11", "g12", "g13", "a1", "a2", "a3", "a5", "a7", "a9", "a10", "f1", "f2", "f3", "f7", "f9", "f10", "u3", "t2", "t3", "p1", "p2" ],
+ welcomeUserOnSpeedyDeletionNotification: [ "db", "g1", "g2", "g3", "g4", "g6", "g10", "g11", "g12", "g13", "a1", "a2", "a3", "a5", "a7", "a9", "a10", "f1", "f2", "f3", "f7", "f9", "f10", "u3", "t2", "t3", "p1", "p2" ],
+ promptForSpeedyDeletionSummary: [ "db", "g1", "g2", "g3", "g4", "g6", "g7", "g8", "g10", "g11", "g12", "a1", "a2", "a3", "a5", "a7", "a9", "a10", "f2", "f4", "f7", "f8", "f10", "t2", "t3", "p1", "p2" ],
+ openUserTalkPageOnSpeedyDelete: [ "db", "g1", "g2", "g3", "g4", "g5", "g10", "g11", "g12", "a1", "a3", "a7", "a9", "a10", "f3", "f7", "f9", "u3", "t2", "p1" ],
+ deleteTalkPageOnDelete: false,
+ deleteRedirectsOnDelete: true,
+ deleteSysopDefaultToTag: false,
+ speedyWindowHeight: 500,
+ speedyWindowWidth: 800,
+ logSpeedyNominations: false,
+ speedyLogPageName: "CSD log",
+ noLogOnSpeedyNomination: [ "u1" ],
+ // Unlink
+ unlinkNamespaces: [ "0", "100" ],
+ // Warn
+ defaultWarningGroup: "1",
+ showSharedIPNotice: true,
+ watchWarnings: true,
+ blankTalkpageOnIndefBlock: false,
+ customWarningList: [],
+ // XfD
+ xfdWatchDiscussion: "default",
+ xfdWatchList: "no",
+ xfdWatchPage: "default",
+ xfdWatchUser: "default",
+ // Hidden preferences
+ revertMaxRevisions: 50,
+ batchdeleteChunks: 50,
+ batchDeleteMinCutOff: 5,
+ batchMax: 5000,
+ batchProtectChunks: 50,
+ batchProtectMinCutOff: 5,
+ batchundeleteChunks: 50,
+ batchUndeleteMinCutOff: 5,
+ deliChunks: 500,
+ deliMax: 5000,
+ proddeleteChunks: 50
+};
+
+// now some skin dependent config.
+if ( mw.config.get( "skin" ) === "vector" ) {
+ Twinkle.defaultConfig.twinkle.portletArea = "right-navigation";
+ Twinkle.defaultConfig.twinkle.portletId = "p-twinkle";
+ Twinkle.defaultConfig.twinkle.portletName = "TW";
+ Twinkle.defaultConfig.twinkle.portletType = "menu";
+ Twinkle.defaultConfig.twinkle.portletNext = "p-search";
+} else {
+ Twinkle.defaultConfig.twinkle.portletArea = null;
+ Twinkle.defaultConfig.twinkle.portletId = "p-cactions";
+ Twinkle.defaultConfig.twinkle.portletName = null;
+ Twinkle.defaultConfig.twinkle.portletType = null;
+ Twinkle.defaultConfig.twinkle.portletNext = null;
+}
+
+Twinkle.defaultConfig.friendly = {
+ // Tag
+ groupByDefault: true,
+ watchTaggedPages: true,
+ watchMergeDiscussions: true,
+ markTaggedPagesAsMinor: false,
+ markTaggedPagesAsPatrolled: true,
+ tagArticleSortOrder: "cat",
+ customTagList: [],
+ // Welcome
+ topWelcomes: false,
+ watchWelcomes: true,
+ welcomeHeading: "Welcome",
+ insertHeadings: true,
+ insertUsername: true,
+ insertSignature: true, // sign welcome templates, where appropriate
+ quickWelcomeMode: "norm",
+ quickWelcomeTemplate: "welcome",
+ customWelcomeList: [],
+ customWelcomeSignature: true,
+ // Talkback
+ markTalkbackAsMinor: true,
+ insertTalkbackSignature: true, // always sign talkback templates
+ talkbackHeading: "Talkback",
+ adminNoticeHeading: "Notice",
+ mailHeading: "You've got mail!",
+ // Shared
+ markSharedIPAsMinor: true
+};
+
+Twinkle.getPref = function twinkleGetPref( name ) {
+ var result;
+ if ( typeof Twinkle.prefs === "object" && typeof Twinkle.prefs.twinkle === "object" ) {
+ // look in Twinkle.prefs (twinkleoptions.js)
+ result = Twinkle.prefs.twinkle[name];
+ } else if ( typeof window.TwinkleConfig === "object" ) {
+ // look in TwinkleConfig
+ result = window.TwinkleConfig[name];
+ }
+
+ if ( result === undefined ) {
+ return Twinkle.defaultConfig.twinkle[name];
+ }
+ return result;
+};
+
+Twinkle.getFriendlyPref = function twinkleGetFriendlyPref(name) {
+ var result;
+ if ( typeof Twinkle.prefs === "object" && typeof Twinkle.prefs.friendly === "object" ) {
+ // look in Twinkle.prefs (twinkleoptions.js)
+ result = Twinkle.prefs.friendly[ name ];
+ } else if ( typeof window.FriendlyConfig === "object" ) {
+ // look in FriendlyConfig
+ result = window.FriendlyConfig[ name ];
+ }
+
+ if ( result === undefined ) {
+ return Twinkle.defaultConfig.friendly[ name ];
+ }
+ return result;
+};
+
+
+
+/**
+ * **************** twAddPortlet() ****************
+ *
+ * Adds a portlet menu to one of the navigation areas on the page.
+ * This is necessarily quite a hack since skins, navigation areas, and
+ * portlet menu types all work slightly different.
+ *
+ * Available navigation areas depend on the skin used.
+ * Monobook:
+ * "column-one", outer div class "portlet", inner div class "pBody". Existing portlets: "p-cactions", "p-personal", "p-logo", "p-navigation", "p-search", "p-interaction", "p-tb", "p-coll-print_export"
+ * Special layout of p-cactions and p-personal through specialized styles.
+ * Vector:
+ * "mw-panel", outer div class "portal", inner div class "body". Existing portlets/elements: "p-logo", "p-navigation", "p-interaction", "p-tb", "p-coll-print_export"
+ * "left-navigation", outer div class "vectorTabs" or "vectorMenu", inner div class "" or "menu". Existing portlets: "p-namespaces", "p-variants" (menu)
+ * "right-navigation", outer div class "vectorTabs" or "vectorMenu", inner div class "" or "menu". Existing portlets: "p-views", "p-cactions" (menu), "p-search"
+ * Special layout of p-personal portlet (part of "head") through specialized styles.
+ * Modern:
+ * "mw_contentwrapper" (top nav), outer div class "portlet", inner div class "pBody". Existing portlets or elements: "p-cactions", "mw_content"
+ * "mw_portlets" (sidebar), outer div class "portlet", inner div class "pBody". Existing portlets: "p-navigation", "p-search", "p-interaction", "p-tb", "p-coll-print_export"
+ *
+ * @param String navigation -- id of the target navigation area (skin dependant, on vector either of "left-navigation", "right-navigation", or "mw-panel")
+ * @param String id -- id of the portlet menu to create, preferably start with "p-".
+ * @param String text -- name of the portlet menu to create. Visibility depends on the class used.
+ * @param String type -- type of portlet. Currently only used for the vector non-sidebar portlets, pass "menu" to make this portlet a drop down menu.
+ * @param Node nextnodeid -- the id of the node before which the new item should be added, should be another item in the same list, or undefined to place it at the end.
+ *
+ * @return Node -- the DOM node of the new item (a DIV element) or null
+ */
+function twAddPortlet( navigation, id, text, type, nextnodeid )
+{
+ //sanity checks, and get required DOM nodes
+ var root = document.getElementById( navigation );
+ if ( !root ) {
+ return null;
+ }
+
+ var item = document.getElementById( id );
+ if ( item ) {
+ if ( item.parentNode && item.parentNode === root ) {
+ return item;
+ }
+ return null;
+ }
+
+ var nextnode;
+ if ( nextnodeid ) {
+ nextnode = document.getElementById(nextnodeid);
+ }
+
+ //verify/normalize input
+ type = ( skin === "vector" && type === "menu" && ( navigation === "left-navigation" || navigation === "right-navigation" )) ? "menu" : "";
+ var outerDivClass;
+ var innerDivClass;
+ switch ( skin )
+ {
+ case "vector":
+ if ( navigation !== "portal" && navigation !== "left-navigation" && navigation !== "right-navigation" ) {
+ navigation = "mw-panel";
+ }
+ outerDivClass = ( navigation === "mw-panel" ) ? "portal" : ( type === "menu" ? "vectorMenu extraMenu" : "vectorTabs extraMenu" );
+ innerDivClass = ( navigation === "mw-panel" ) ? "body" : ( type === "menu" ? "menu" : "" );
+ break;
+ case "modern":
+ if ( navigation !== "mw_portlets" && navigation !== "mw_contentwrapper" ) {
+ navigation = "mw_portlets";
+ }
+ outerDivClass = "portlet";
+ innerDivClass = "pBody";
+ break;
+ default:
+ navigation = "column-one";
+ outerDivClass = "portlet";
+ innerDivClass = "pBody";
+ break;
+ }
+
+ // Build the DOM elements.
+ var outerDiv = document.createElement( "div" );
+ outerDiv.className = outerDivClass + " emptyPortlet";
+ outerDiv.id = id;
+ if ( type === "menu" ) {
+ // Fix drop-down arrow image in Vector skin
+ outerDiv.style.backgroundImage = 'url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAQCAMAAAAlM38UAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA9QTFRFsbGxmpqa3d3deXl58/n79CzHcQAAAAV0Uk5T/////wD7tg5TAAAAMklEQVR42mJgwQoYBkqYiZEZAhiZUFRDxWGicEPA4nBRhNlAcYQokpVMDEwD6kuAAAMAyGMFQVv5ldcAAAAASUVORK5CYII=")';
+ outerDiv.style.backgroundPosition = "right 60%";
+ }
+ if ( nextnode && nextnode.parentNode === root ) {
+ root.insertBefore( outerDiv, nextnode );
+ } else {
+ root.appendChild( outerDiv );
+ }
+
+ var h5 = document.createElement( "h3" );
+ if ( type === "menu" ) {
+ var span = document.createElement( "span" );
+ span.appendChild( document.createTextNode( text ) );
+ h5.appendChild( span );
+
+ var a = document.createElement( "a" );
+ a.href = "#";
+
+ $( a ).click(function ( e ) {
+ e.preventDefault();
+
+ if ( !twinkleUserAuthorized ) {
+ alert("Sorry, your account is too new to use Twinkle.");
+ }
+ });
+
+ span = document.createElement( "span" );
+ span.appendChild( document.createTextNode( text ) );
+ a.appendChild( span );
+ h5.appendChild( a );
+ } else {
+ h5.appendChild( document.createTextNode( text ) );
+ }
+ outerDiv.appendChild( h5 );
+
+ var innerDiv = document.createElement( "div" ); // Not strictly necessary with type vectorTabs, or other skins.
+ innerDiv.className = innerDivClass;
+ outerDiv.appendChild(innerDiv);
+
+ var ul = document.createElement( "ul" );
+ innerDiv.appendChild( ul );
+
+ return outerDiv;
+}
+
+
+/**
+ * **************** twAddPortletLink() ****************
+ * Builds a portlet menu if it doesn't exist yet, and add the portlet link.
+ * @param task: Either a URL for the portlet link or a function to execute.
+ */
+function twAddPortletLink( task, text, id, tooltip )
+{
+ if ( Twinkle.getPref("portletArea") !== null ) {
+ twAddPortlet( Twinkle.getPref( "portletArea" ), Twinkle.getPref( "portletId" ), Twinkle.getPref( "portletName" ), Twinkle.getPref( "portletType" ), Twinkle.getPref( "portletNext" ));
+ }
+ var link = mw.util.addPortletLink( Twinkle.getPref( "portletId" ), typeof task === "string" ? task : "#", text, id, tooltip );
+ if ( $.isFunction( task ) ) {
+ $( link ).click(function ( ev ) {
+ task();
+ ev.preventDefault();
+ });
+ }
+ return link;
+}
+/**
+ * General initialization code
+ */
+
+var scriptpathbefore = mw.util.wikiScript( "index" ) + "?title=",
+ scriptpathafter = "&action=raw&ctype=text/javascript&happy=yes";
+
+// Retrieve the user's Twinkle preferences
+$.ajax({
+ url: scriptpathbefore + "User:" + encodeURIComponent( mw.config.get("wgUserName")) + "/twinkleoptions.js" + scriptpathafter,
+ dataType: "text",
+ error: function () { mw.util.jsMessage( "Could not load twinkleoptions.js" ); },
+ success: function ( optionsText ) {
+
+ // Quick pass if user has no options
+ if ( optionsText === "" ) {
+ return;
+ }
+
+ // Twinkle options are basically a JSON object with some comments. Strip those:
+ 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.
+ if ( optionsText.lastIndexOf( "window.Twinkle.prefs = ", 0 ) === 0 ) {
+ optionsText = optionsText.replace( /(?:^window.Twinkle.prefs = |;\n*$)/g, "" );
+ }
+
+ try {
+ var options = $.parseJSON( optionsText );
+
+ // Assuming that our options evolve, we will want to transform older versions:
+ //if ( options.optionsVersion === undefined ) {
+ // ...
+ // options.optionsVersion = 1;
+ //}
+ //if ( options.optionsVersion === 1 ) {
+ // ...
+ // options.optionsVersion = 2;
+ //}
+ // At the same time, twinkleconfig.js needs to be adapted to write a higher version number into the options.
+
+ if ( options ) {
+ Twinkle.prefs = options;
+ }
+ }
+ catch ( e ) {
+ mw.util.jsMessage("Could not parse twinkleoptions.js");
+ }
+ },
+ complete: function () {
+ $( Twinkle.load );
+ }
+});
+
+// Developers: you can import custom Twinkle modules here
+// For example, mw.loader.load(scriptpathbefore + "User:UncleDouggie/morebits-test.js" + scriptpathafter);
+
+Twinkle.load = function () {
+ // Don't activate on special pages other than "Contributions" so that they load faster, especially the watchlist.
+ var isSpecialPage = ( mw.config.get('wgNamespaceNumber') === -1
+ && mw.config.get('wgCanonicalSpecialPageName') !== "Contributions"
+ && mw.config.get('wgCanonicalSpecialPageName') !== "Prefixindex" ),
+
+ // 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 );
+
+ // Prevent users that are not autoconfirmed from loading Twinkle as well.
+ if ( isSpecialPage || isOldIE || !twinkleUserAuthorized ) {
+ return;
+ }
+
+ // Load the modules in the order that the tabs should appears
+ // User/user talk-related
+ Twinkle.arv();
+ Twinkle.warn();
+ Twinkle.welcome();
+ Twinkle.shared();
+ Twinkle.talkback();
+ // Deletion
+ Twinkle.speedy();
+ Twinkle.prod();
+ Twinkle.xfd();
+ Twinkle.image();
+ // Maintenance
+ Twinkle.protect();
+ Twinkle.tag();
+ // Misc. ones last
+ Twinkle.diff();
+ Twinkle.unlink();
+ Twinkle.config.init();
+ Twinkle.fluff.init();
+ if ( Morebits.userIsInGroup('sysop') ) {
+ Twinkle.delimages();
+ Twinkle.deprod();
+ Twinkle.batchdelete();
+ Twinkle.batchprotect();
+ Twinkle.batchundelete();
+ }
+ // Run the initialization callbacks for any custom modules
+ $( Twinkle.initCallbacks ).each(function ( k, v ) { v(); });
+ Twinkle.addInitCallback = function ( func ) { func(); };
+
+ // Increases text size in Twinkle dialogs, if so configured
+ if ( Twinkle.getPref( "dialogLargeFont" ) ) {
+ mw.util.addCSS( ".morebits-dialog-content, .morebits-dialog-footerlinks { font-size: 100% !important; } " +
+ ".morebits-dialog input, .morebits-dialog select, .morebits-dialog-content button { font-size: inherit !important; }" );
+ }
+};
+
+} ( window, document, jQuery )); // End wrap with anonymous function
+
+// </nowiki>
Please sign in to comment.
Something went wrong with that request. Please try again.