Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
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
@azatoth authored
View
1  .gitignore
@@ -2,7 +2,6 @@
alltwinkle.js
/.settings
/.project
-/twinkle.js
jsl.conf
stash*.txt
stash*.diff
View
36 Makefile
@@ -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
View
4 modules/friendlyshared.js
@@ -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);
View
4 modules/friendlytag.js
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** friendlytag.js: Tag module
@@ -1334,3 +1337,4 @@ Twinkle.tag.callback.evaluate = function friendlytagCallbackEvaluate(e) {
break;
}
};
+})(jQuery);
View
4 modules/friendlytalkback.js
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** friendlytalkback.js: Talkback module
@@ -345,3 +348,4 @@
};
}());
+})(jQuery);
View
4 modules/friendlywelcome.js
@@ -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);
View
4 modules/twinklearv.js
@@ -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);
View
4 modules/twinklebatchdelete.js
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinklebatchdelete.js: Batch delete module (sysops only)
@@ -379,3 +382,4 @@ Twinkle.batchdelete.callbacks = {
pageobj.save(params.onsuccess);
}
};
+})(jQuery);
View
4 modules/twinklebatchprotect.js
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinklebatchprotect.js: Batch protect module (sysops only)
@@ -417,3 +420,4 @@ Twinkle.batchprotect.callbacks = {
} );
}
};
+})(jQuery);
View
4 modules/twinklebatchundelete.js
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinklebatchundelete.js: Batch undelete module
@@ -123,3 +126,4 @@ Twinkle.batchundelete.callbacks = {
}
}
};
+})(jQuery);
View
4 modules/twinkleconfig.js
@@ -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);
View
4 modules/twinkledelimages.js
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinkledelimages.js: Batch deletion of images (sysops only)
@@ -221,3 +224,4 @@ Twinkle.delimages.callbacks = {
self.save();
}
};
+})(jQuery);
View
4 modules/twinkledeprod.js
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinkledeprod.js: Batch deletion of expired PRODs (sysops only)
@@ -155,3 +158,4 @@
});
};
}());
+})(jQuery);
View
4 modules/twinklediff.js
@@ -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);
View
4 modules/twinklefluff.js
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinklefluff.js: Revert/rollback module
@@ -555,3 +558,4 @@ Twinkle.fluff.init = function twinklefluffinit() {
}
}
};
+})(jQuery);
View
4 modules/twinkleimage.js
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinkleimage.js: Image CSD module
@@ -339,3 +342,4 @@ Twinkle.image.callbacks = {
}
}
};
+})(jQuery);
View
4 modules/twinkleprod.js
@@ -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);
View
4 modules/twinkleprotect.js
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinkleprotect.js: Protect/RPP module
@@ -1254,3 +1257,4 @@ Twinkle.protect.callbacks = {
rppPage.save();
}
};
+})(jQuery);
View
4 modules/twinklespeedy.js
@@ -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);
View
4 modules/twinkleunlink.js
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinkleunlink.js: Unlink module
@@ -273,3 +276,4 @@ Twinkle.unlink.callbacks = {
}
}
};
+})(jQuery);
View
4 modules/twinklewarn.js
@@ -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);
View
4 modules/twinklexfd.js
@@ -1,3 +1,6 @@
+(function($){
+
+
/*
****************************************
*** twinklexfd.js: XFD module
@@ -1695,3 +1698,4 @@ Twinkle.xfd.callback.evaluate = function(e) {
break;
}
};
+})(jQuery);
View
22 sync.pl
@@ -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
View
451 twinkle.js
@@ -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.