User:StrawberryMaster/global.js

/** * This file loads for myself. * For skin specific variants see User:StrawberryMaster/monobook.js and User:StrawberryMaster/wikia.js * for monobook and oasis respectively * * Please test any changes made to this file. * Jshint  can catch syntax errors to help testing. * Alternatively, Wikia's code editor has jshint embedded to make life extra simple. * * The majority of the scripts here are for personal use as they modify parts of the Oasis/Monobook skin violating Wikia's Terms of Use. * * Some of the scripts here were taken from: Iynque, Dorumin, Slyst and Cqm, alongside GitHub and the Dev Wiki. * * Note: Update global.js version at the end of the page. As of May 24, 2016, it is version 43.2. */ /* global mw, wgServer, wgScriptPath, wgPageName, wgArticleId, wgAction, importArticles, importScript, importScriptPage, BannerNotification, wgCanonicalSpecialPageName, config /* jshint bitwise:true, browser:true, camelcase:true, curly:true, devel:true, eqeqeq:true, es3:true, forin:true, immed:true, jquery:true, latedef:true, newcap:true, noarg:true, noempty:true, nonew:true, onevar:false, plusplus:true, quotmark:single, undef:true, unused:true, strict:true, trailing:true /* -- */ /* Settings  */ /* Header slightly modified from Iynque.  - */ /* -- */

// these have to be defined here for reasons I don't understand // Monch tells me IFFE's can mess with the run order of js but neither of us know why or how. // #confused

function importScriptPage( p, w ) { var s = document.createElement( 'script' ); s.type = 'text/javascript'; s.src = 'http://' + w + '.wikia.com/index.php?title=' + p.replace( / /g, '_' ) + '&action=raw&ctype=text/javascript&maxage=0&smaxage=0'; document.getElementsByTagName( 'body' )[0].appendChild( s ); } function importScript( p ) { var s = document.createElement( 'script' ); s.type = 'text/javascript'; s.src = '/index.php?title=' + p.replace( / /g, '_' ) + '&action=raw&ctype=text/javascript&maxage=0&smaxage=0'; document.getElementsByTagName( 'body' )[0].appendChild( s ); }

/* Indicates closed and highlighted threads. * Something I found on the threads.  */ $(function {   if (mw.config.get('wgNamespaceNumber') !== 2000) {        return;    }    // Loop to add padlock/exclamation.    function update {        $('.ThreadList .thread').each(function { var $this = $(this); // Formatting fix $this.find('a').css('display','inline'); // With many thanks to w:User:Cqm! $.get(mw.util.wikiScript('wikia'), {               controller: 'Forum',                method: 'brickHeader',                id: $this.data('id'),                format: 'json'            }, function(data) {                if (data.isClosed) {                    $this.find('h4 > a').before(' ');                }                if (data.isNotifyeveryone) {                    $this.find('h4 > a').before(' ');                }            }); });   }    // Run it!    update;    // Make sure it works on all pages, not just page 1.    var observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) {           if (mutation.addedNodes.length || mutations.removedNodes.length) {                update;            }        }); });   observer.observe($('.ThreadList')[0], { childList: true }); });

/* * AjaxBlock (w:c:dev:AjaxBlock) * * @author: Dorumin * @scope: Personal use * @description: Allows user blocking without leaving the current page. * @update 04/05/16: Now detects block and unblock links that were added after window onload. * @update 22/05/16: Now supports unblocking IDs + a few minor changes. */ $(function {   var ug = mw.config.get('wgUserGroups');    if (ug.indexOf('sysop') + ug.indexOf('vstf') + ug.indexOf('staff') + ug.indexOf('helper') > -4) {        // Creates the objects that will hold the variables used in this script        var obj = window.AjaxBlock || {};        obj.check = obj.check || {};        // Quick Block Expiry times (customizable)        obj.expiryTimes = obj.expiryTimes || {            '2 hours': '2 hours',            '5 hours': '5 hours',            '12 hours': '12 hours',            '1 day': '1 day',            '3 days': '3 days',            '5 days': '5 days',            '1 week': '1 week',            '2 weeks': '2 weeks',            '1 month': '1 month',            '3 months': '3 months',            '6 months': '6 months',            '1 year': '1 year',            '2 years': '2 years',            '3 years': '3 years',            'infinite': 'Infinite' };       // Quick Block reasons (customizable) obj.blockReasons = obj.blockReasons || { 'Vandalism': 'Vandalism', 'Spam': 'Spam', 'Repeated policy violations': 'Repeated violations', 'Sockpuppetry/Ban Evasion': 'Sockpuppetry', 'Removing content/blanking pages': 'Page blanking', 'Inserting false information or nonsense': 'Gibberish', 'Intimidating behaviour/harassment/trolling': 'Troll/Harassment', 'Unacceptable username, avatar, or global masthead': 'Name/avatar', 'Under the legal age': 'COPPA' };       obj.check.creation = obj.check.creation || true; obj.check.talk = obj.check.talk || false; obj.check.autoBlock = obj.check.autoBlock || true; obj.check.override = obj.check.override || false; $(document).click(function(e) {           // Ajax Block            if ($(e.target).is('a[href*="/wiki/Special:Block/')) {                if (e.ctrlKey || e.shiftKey) return;                e.preventDefault;                var usr = decodeURIComponent($(e.target).attr('href').split('Special:Block/')[1]).replace(/_/g, ' '),                    token = mw.user.tokens.get('editToken'),                    Api = new mw.Api;                // Show the block modal                $.showCustomModal('Ajax Block: ' + usr, 'Expiry:\                 Other  \                 \                Reason: Other  \                 \                 Prevent account creation \                Prevent from posting on message wall \                Block all IPs from this user (AutoBlock) \                <label for="overrideBlock">Override any blocks already in effect ', { id: 'ajaxBlockModal', callback: function { // Auto checks checkboxes (customizable) if (obj.check.creation) { $('#accountCreation').attr('checked', true) } if (obj.check.talk) { $('#disableWall').attr('checked', true) } if (obj.check.autoBlock) { $('#autoBlock').attr('checked', true) } if (obj.check.override) { $('#overrideBlock').attr('checked', true) } var $expirySelect = $('#AjaxBlockExpirySelect'); var $reasonSelect = $('#AjaxBlockReasonSelect'); // Adds the common times and reasons (customizable) $.each(obj.expiryTimes, function(key, value) {                           $expirySelect                                .append($('  ') .attr('value', key) .text(value));                       }); $.each(obj.blockReasons, function(key, value) {                           $reasonSelect                                .append($('  ') .attr('value', key) .text(value));                       }); },                   buttons: [{ // Block button id: 'ajaxBlockButton', defaultButton: true, message: 'Block this user', handler: function { var blockDuration = $('#AjaxBlockExpirySelect').val === 'other' ? $('#AjaxBlockCustomExpiry').val.toLowerCase : $('#AjaxBlockExpirySelect').val.toLowerCase; var blockReason = $('#AjaxBlockReasonSelect').val === 'other' ? $('#AjaxBlockCustomReason').val : $('#AjaxBlockReasonSelect').val + ($('#AjaxBlockCustomReason').val.trim !==  ? ': ' + $('#AjaxBlockCustomReason').val : ); // Creates the base block object var config = { action: 'block', user: usr, expiry: blockDuration, reason: blockReason, bot: true, token: token };                           // Set object values if certain checkboxes are checked if ($('#accountCreation').is(':checked')) { config.nocreate = 1 } if ($('#autoBlock').is(':checked')) { config.autoblock = 1 } if (!$('#disableWall').is(':checked')) { config.allowusertalk = 1 } if ($('#overrideBlock').is(':checked')) { config.reblock = 1 } Api.post(config).done(function(d) { // Does the actual blocking                               if (!d.error) {                                    new BannerNotification(usr + ' has been blocked successfully!', 'confirm').show;                                } else {                                    new BannerNotification('Block for ' + usr + ' failed: ' + d.error.code, 'error').show;                                }                            }).fail(function {                                new BannerNotification('Block for ' + usr + ' has failed.', 'error').show;                            }); $('#ajaxBlockModal').closeModal; // Close the modal setTimeout(function {                               if (wgCanonicalSpecialPageName === 'Contributions') {                                    window.location.reload; // Refresh (to check if its correct, or if something went wrong)                                }                            }, 2000); }                   }, { // Cancel button id: 'ajaxBlockCancel', defaultButton: true, message: 'Cancel', handler: function { $('#ajaxBlockModal').closeModal; }                   }]                });                // Ajax Unblock            } else if ($(e.target).is('a[href*="/wiki/Special:Unblock/') || $(e.target).is('a[href*="/wiki/Special:Unblock?wpTarget=')) {                if (e.ctrlKey || e.shiftKey) return;                e.preventDefault;                var isId = $(e.target).is('a[href*="/wiki/Special:Unblock?wpTarget='),                    usr = isId ? $(e.target).attr('href').split('?wpTarget=%23')[1] : decodeURIComponent($(e.target).attr('href').split('Special:Unblock/')[1]).replace(/_/g, ' '),                    token = mw.user.tokens.get('editToken'),                    Api = new mw.Api;                // Show the unblock modal                $.showCustomModal('Ajax Unblock: ' + isId ? '#' : '' + usr, 'Reason:<input id="AjaxUnblockReason" type="text" size="50"> ', {                    id: 'ajaxUnblockModal', buttons: [{ // Unblock button id: 'ajaxUnblockButton', defaultButton: true, message: 'Unblock this user', handler: function { var unblockReason = $('#AjaxUnblockReason').val; config = { action: 'unblock', reason: unblockReason, token: token };                           (isId) ? config.id = usr : config.user = usr; Api.post(config).done(function(d) { // Does the actual unblocking                               if (!d.error) {                                    new BannerNotification(usr + ' has been unblocked successfully!', 'confirm').show;                                } else {                                    new BannerNotification('Unblock for ' + usr + ' failed: ' + d.error.code, 'error').show;                                }                            }) .fail(function {                               new BannerNotification('Unblock for ' + usr + ' has failed.', 'error').show;                            }); $('#ajaxUnblockModal').closeModal; // Close the modal setTimeout(function {                               if (wgCanonicalSpecialPageName === 'Contributions') {                                    window.location.reload;                                }                            }, 2000); }                   }, { // Cancel button id: 'ajaxUnblockCancel', defaultButton: true, message: 'Cancel', handler: function { $('#ajaxUnblockModal').closeModal; }                   }]                });            }        });    } });

/* Adds an 'AJAX UNDO' link next into the undo link on page histories/diff pages. * Something I found on Dorumin's global.js. <c:User:Dorumin/global.js> * See w:c:dev:AjaxUndo (stable?) for info & attribution. */ jQuery(document).ready(function($) {   'use strict';

function createUndoLink(diffUndoUrl) { var $ajaxUndoLink = $('<a />').text('AJAX Undo').attr('href', '#').click(function {           var $ajaxUndoLinkob = $(this),                undoIdRegex = /&undo=([^&]*)/,                undoId = undoIdRegex.exec(diffUndoUrl)[1],                editToken,                etUrl = wgServer + wgScriptPath + '/api.php?action=query&prop=info|revisions&intoken=edit&titles=' + encodeURIComponent(wgPageName) + '&format=json',                usrUnd = $('#mw-diff-ntitle2 .mw-userlink').html,                smry = prompt('Undo summary', 'Undo revision ' + undoId + ' by ' + usrUnd + ' (talk)');                if (smry === null) return;                else if (!smry) smry = 'Undo revision ' + undoId + ' by ' + usrUnd + ' (talk)';            $ajaxUndoLinkob.html(' <img src="http://images2.wikia.nocookie.net/dev/images/8/82/Facebook_throbber.gif" style="vertical-align: baseline;" border="0" alt="Undoing..." />');           $.getJSON(etUrl, function(data) { editToken = data.query.pages[wgArticleId].edittoken; $.ajax({                   url: wgScriptPath + '/api.php?',                    data: 'action=edit&format=json&title=' + encodeURIComponent(wgPageName) + '&undo=' + encodeURIComponent(undoId) + '&bot=1&summary=' + encodeURIComponent(smry) + '&token=' + encodeURIComponent(editToken),                    dataType: 'json',                    type: 'POST',                    success: function(data) {                        if (data.edit && data.edit.result === 'Success') {                            $ajaxUndoLinkob.text('(undone)');                        } else if (data.error && data.error.code === 'undofailure') {                            $ajaxUndoLinkob.text('(error)');                            alert(data.error.info);                        } else {                            $ajaxUndoLinkob.text('(error)');                            alert('Error: Unknown result from API.'); }                   },                    error: function { $ajaxUndoLinkob.text('(error)'); }               });            });        });        return $ajaxUndoLink;    }

if ($('.mw-history-undo > a').length && wgAction === 'history') { $('.mw-history-undo > a').each(function {           var diffUndoUrl = $(this).attr('href'),                $ajaxUndoLink = createUndoLink(diffUndoUrl);            $(this).replaceWith($ajaxUndoLink);        }); } else if ($('table.diff').length && typeof $.getUrlVar('diff') !== 'undefined') { var $diffUndoLink = $('table.diff').find('.diff-ntitle > #mw-diff-ntitle1 a:last'), diffUndoUrl = $diffUndoLink.attr('href'), $ajaxDiffUndoLink = createUndoLink(diffUndoUrl); $diffUndoLink.replaceWith($ajaxDiffUndoLink); } });

// Ajax Block settings window.AjaxBlock = { blockReasons: { 'Vandalism': 'Vandalism', 'Spam': 'Spam', 'Repeated policy violations': 'Repeated violations', 'Sockpuppetry/ban evasion': 'Sockpuppetry', 'Removing content/blanking pages': 'Page blanking', 'Inserting false information or nonsense': 'Gibberish', 'Intimidating behaviour/harassment/trolling': 'Troll/harassment', 'Unacceptable username, avatar, or global masthead': 'Name/avatar', 'Under the legal age': 'COPPA', 'Failing to comply with the file policy.': 'File Policy' },   check: { creation: true, talk: true, autoBlock: true, override: true } };

/* Auto updating recent changes opt-in. * Something I found on Dorumin's global.js. <c:User:Dorumin/global.js> * See w:c:dev:AjaxRC for info & attribution. */ window.ajaxPages = ['Blog:Recent_posts', 'Special:RecentChanges', 'Special:WikiActivity', 'Special:Chat', 'Special:Watchlist', 'Special:Log', 'Special:Log/upload', 'Special:Contributions']; window.ajaxIndicator = 'http://vignette2.wikia.nocookie.net/dev/images/8/82/Facebook_throbber.gif'; window.ajaxRefresh = 30000; window.AjaxRCRefreshText = 'Auto-refresh'; window.AjaxRCRefreshHoverText = 'Automatically refresh the page';

/* Create userpage script. * See w:c:dev:QuickCreateUserPage for info & attribution. */

window.qtUserPageTemplate = ''; window.qtEnableUserPageOverwrite = true;

/* Vector skin configuration. * See w:c:dev:Pseudo-Vector JS for info & attribution. */ window.pseudoVector = { loadCss: true, addReadTab: true, addContributionsTab: true, disableWatchIcon: false, newDiffStyle: true };

/* Removes backlinks from pages. * See w:c:dev:Linksweeper for info & attirbution. */ window.linkSweepConfirmation = true; window.LinkSweeperDelay = 1000;

/* Places "QuickToolsv2" button on the "My Tools" section. * Something I found on Zmario's global.js. <c:User:Zmario/global.js> * See w:c:dev:QuickToolsv2 for info & attribution. */ window.QuickToolsAdvancedtop = false;

/** * Import JavaScript and Stylesheet articles from any wiki. * @author Kyle Florence <kflorence@wikia-inc.com> * * >> Examples: * * // Importing a single Stylesheet from the local wiki * importArticle({ *    type: "style", *     article: "Mediawiki:MyCustomStyles.css" * }); * * // Importing multiple JavaScript files from an external wiki * importArticles({ *    type: "script", *     articles: [ *         "Mediawiki:MyCustomJavaScript.js", *         "w:starwars:Mediawiki:External.js" *     ] * }); * * @param {...Object} Any number of modules to load. * @returns {Array} An array of DOM nodes used for injection. */

importArticles({	type: 'script',	articles: [           // ...            'u:dev:MediaWiki:AjaxRC/code.js', // Special:RecentChanges live update            'u:dev:MediaWiki:AjaxBatchDelete/code.2.js',            'u:dev:MediaWiki:AjaxBatchUndelete.js',            // 'u:dev:MediaWiki:AjaxBlock/code.js', // Blocks users quickily              // ↳ temporarily disabled while modified code is here (above)            'u:dev:MediaWiki:AjaxPatrol/code.js',            'u:dev:MediaWiki:ArchiveTool/code.js',            'u:dev:MediaWiki:DisplayClock/code.js', // Show UTC clock            // 'u:dev:MediaWiki:FastDelete/beta.js',               // ↳ disabled while another code is here (below)            'u:dev:MediaWiki:Linksweeper/code.js',            'u:dev:MediaWiki:MassBlock/code.js',            'u:dev:MediaWiki:MassCategorization/code.js',            'u:dev:MediaWiki:MassProtect/code.js',            'u:dev:MediaWiki:MassRename/code.js', 'u:dev:MediaWiki:MassUserRights/code.js', 'u:dev:MediaWiki:Pseudo-Vector.js', 'u:dev:MediaWiki:QuickCreateUserPage/code.js', 'u:dev:Mediawiki:QuickToolsv2/code.js', // adds quick tools to pages // ↳ Not used very often; Wikimarks handles a lot of this anyway 'u:dev:MediaWiki:WHAM/code.2.js' // ...	] });

( function ( $, mw, importArticles ) {   'use strict';    var self = {        /**         * @desc Loads functions conditionally         */        init: function  {            var config = mw.config.get( [ 'wgCanonicalSpecialPageName', 'wgNamespaceNumber', 'wgTitle' ] );           self.imports;            if ( $( '#UserProfileMasthead' ).length ) {                self.mastheadEditcount;            }            if ( config.wgCanonicalSpecialPageName === 'Movepage' && ( /File/ ).test( config.wgTitle ) ) {               self.uncheckFileRedirects;            }            if ( config.wgNamespaceNumber === 6 && !$( '#file > a' ).length ) {                self.removeAutoplay;            }            if ( $( '[src*="youtube.com"]' ).length ) {                self.switchAutoplay;            }        },        /**         * @desc Defines variables for imported scripts and import said scripts         *         * @author Cqm         */        imports: function  {            var fdButtons = [],                scripts = [],                config = mw.config.get( [ 'wgAction', 'wgCityId', 'wgCanonicalSpecialPageName', 'wgNamespaceNumber' ] );            /**             * Setup globals vars here             */            // fastdelete buttons            fdButtons[ fdButtons.length ] = { summary: 'Housekeeping', label: 'HK' };            // for rswiki only if ( config.wgCityId === '304' ) { fdButtons[ fdButtons.length ] = { summary: 'Successful RfD', label: 'RfD' }; }           // add as global window.fdButtons = fdButtons; /**            * Create an array of scripts to be imported conditionally * See imported pages for documentation * @todo Find a way to turn these on/off from console or something */           // always load these scripts.push(               // CSS testing input                // 'u:dev:PortableCSSPad/code.js', // Add CSS injector to toolbar                  // ↳ Not necessary with modern browser debug/developer tools                // Customisable On The Wiki tab                // 'u:dev:Wikimarks/code.js',                // Fix search for Special pages                'u:rs:User:Cqm/specialsearchfix.js'            ); if ( config.wgAction === 'view' ) { scripts.push(                   // Icon to link to header tags                    // 'u:dev:HeaderLinks/code.js'                ); if ( $( '#ca-delete' ).length ) { // Fast Delete buttons // scripts.push( 'u:dev:FastDelete/code.js' ); scripts.push( 'u:dev:FastDelete/beta.js' ); }               if ( config.wgNamespaceNumber === 6 ) { scripts.push(                       // Changes file pages back to original styling                        // @todo fix this up at some point                        'u:rs:User:Cqm/oldfilepages.js'                    ); }               if ( [ 'Allpages', 'Prefixindex' ].indexOf( config.wgCanonicalSpecialPageName ) > 1 ) { scripts.push(                       // Adds a hide redirect button to AllPages & PrefixIndex                        'u:dev:AllPagesHideRedirect/code.js'                    ); }               if ( config.wgAction === 'history' || $( '#mw-history-searchform' ).length ) { scripts.push(                       // Add an undo link to page diffs and histories                        // 'u:dev:AjaxUndo/code.js'                    ); }           }            /**             * Import the filled arrays */           importArticles( { type: 'script', articles: scripts } ); },       /**         * @desc Adds a link to Special:Editcount on the user profile masthead *        * @author Matthew2602 <http://c.wikia.com/User:Matthew2602> * @author Cqm */       /* mastheadEditcount: function  { var config = mw.config.get( [                   'wgCanonicalNamespace',                    'wgTitle'                ] ), user = config.wgTitle, link; if ( config.wgCanonicalNamespace === 'Special' ) { user = user.split( '/' )[1]; }           link = $( '<a>' ) .attr( {                   href: '/wiki/Special:Editcount/' + user,                    title: 'Special:Editcount'                } ) .text(                   $( '#UserProfileMasthead .tally em' ).text                ); $( '#UserProfileMasthead .tally em' ).html( link ); }, */       /**         * @desc Uncheck file redirects on Special:MovePage *        * File redirects are normally bad because they will create false positives on Special:WantedFiles * In very rare cases it's reasonable to have them, but those are so rare it's better to have this as        * the default behaviour. *        * @author Cqm */       uncheckFileRedirects: function  { $( '#wpLeaveRedirect' ).removeAttr( 'checked' ); },       /**         * @desc Set the type attribute of input elements to type="text" (which it defaults to anyway) *      Used to undo styling in touchScreen.scss which indiscriminately makes every input *      element larger than I need. */       setInputType: function  { $( 'input' ).each( function {                if ( !this.type ) {                    this.type = 'text';                }            } ); },       /**         * @desc For preventing autoplay on embedded youtube videos *      which are normally embedded through templates and MediaWiki pages *        * @example <http://lego.wikia.com/wiki/Template:YTMusicPlayer> * @example <http://bigtimerush.wikia.com/wiki/MediaWiki:Song> *        * @author Bobogoobo <http://c.wikia.com/User:Bobogoobo> * @author Cqm */       switchAutoplay: function  { $( '[src*="youtube.com"]' ).each( function {                var $this = $( this ),                    source = $this.attr( 'src' );                if ( source.indexOf( 'autoplay=' ) > -1 ) {                    $this.attr( 'src', source.replace( 'autoplay=1',  ).replace( 'autoplay=0',  ) );                }                // for embedded flash files                // which are so annoying they get their own console message                if ( $this.prop( 'tagName' ) === 'EMBED' ) {                    console.log( 'kill embed with fiyah' );                    $this.remove;                }            } ); },       /**         * @desc For preventing autoplay for embedded youtube videos on file pages *        * @author Cqm */       removeAutoplay: function  { var loading; // used in setInterval function iframeLoad { if ( $( '#file iframe[src*="youtube.com"]' ).length ) { self.switchAutoplay; window.clearInterval( loading ); }           }            // @todo use mutation observers for this instead loading = window.setInterval( iframeLoad, 500 ); }   };    $( self.init ); }( this.jQuery, this.mediaWiki, this.importArticles ) );

/* -- END of User:StrawberryMaster/global.js -- */ /* - Header slightly modified from Iynque. <w:c:User:Iynque> -- */ console.info('Loaded User:StrawberryMaster/global.js version 43.2');