Thành viên:Ryder1992/skin.js

Bách khoa toàn thư mở Wikipedia

Chú ý: Sau khi lưu thay đổi trang, bạn phải xóa bộ nhớ đệm của trình duyệt để nhìn thấy các thay đổi. Google Chrome, Firefox, Internet ExplorerSafari: Giữ phím ⇧ Shift và nhấn nút Reload/Tải lại trên thanh công cụ của trình duyệt. Để biết chi tiết và hướng dẫn cho các trình duyệt khác, xem Trợ giúp:Xóa bộ nhớ đệm.

/*** Restorer ***/

// Documentation at [[User:BrandonXLF/Restorer]]
// By [[User:BrandonXLF]]
// Dịch sang tiếng Việt bởi [[User: AzusaNyan]]

$(function() {
	if (mw.config.get('wgAction') != 'history') return;

	window.restorerSummary = window.restorerSummary || 'Lùi sửa về phiên bản $ID bởi [[Special:Contributions/$USER|$USER]] sử dụng [[En:User:BrandonXLF/Restorer|Restorer]]';

	function restore(user, revid) {
		return new mw.Api().postWithEditToken({
			action: 'edit',
			pageid: mw.config.get('wgArticleId'),
			undo: mw.config.get('wgCurRevisionId'),
			undoafter: revid,
			summary: window.restorerSummary.replace(/\$ID/g, revid).replace(/\$USER/g, user)
		}).then(
			function() {
				mw.notify('Lùi sửa thành công.');
				location.reload();
			},
			function(_, data) {
				mw.notify(new mw.Api().getErrorMessage(data), {type: 'error'});
			}
		);
	}

	function addLink(item) {
		var revid = item.getAttribute('data-mw-revid'),
			user,
			links,
			el,
			parent;

		if (revid == mw.config.get('wgCurRevisionId')) return;

		user = item.getElementsByClassName('mw-userlink')[0].textContent.replace('User:', '');
		links = item.getElementsByClassName('mw-changeslist-links');
		links = links[links.length - 1];
		parent = document.createElement('span');
		el = document.createElement('a');

		el.addEventListener('click', function() {
			el.className = 'restorer-loading';

			restore(user, revid).always(function() {
				el.className = '';
			});
		});

		el.innerHTML = 'lùi tự động';
		parent.appendChild(el);
		links.appendChild(parent);
	}

	var parents = document.querySelectorAll('li[data-mw-revid]');

	for (var i = 0; i < parents.length; i++) {
		addLink(parents[i]);
	}

	mw.loader.addStyleTag(
		'@keyframes restorer-loading {' +
		'0%, 100% {content: " ⡁"} 16% {content: " ⡈"} 33% {content: " ⠔"} 50% {content: " ⠒"} 66% {content: " ⠢"} 83% {content: " ⢁"}}' +
		'.restorer-loading::after {white-space: pre; content: ""; animation: restorer-loading 0.5s infinite}'
	);
});

// SectionMover
// Originaly by User:Flooded with them hundreds
// Copied to [[User:DannyS712/SectionMover.js]] after FWTH retired, who took over as maintainer

$.when( mw.loader.using(['mediawiki.util','mediawiki.api']), $.ready).done( function () {
	var validSections = {},
		fromTos = {},
		wikiText = '',
		revStamp, startMoveButton, overlay;

	if ( mw.config.get( 'wgNamespaceNumber' ) == -1 ) {
		// is a special page
		return;
	}
	$( 'head' ).append(
		'<style>a.arxylink { font-weight:bold } .arxyhighlight { background-color:#aef9fc }</style>'
	);

	startMoveButton = mw.util.addPortletLink(
		'p-cactions',
		'#',
		'Move section',
		'pt-oeca',
		'Enter/exit the process',
		null,
		null
	);
	overlay = $( document.createElement( 'button' ) );
	$( startMoveButton ).click( function ( e ) {
		$( '.arxylink' ).click();
		$( '.arxy' ).toggle();
		$( '#Movebutton' ).toggle();
	} );
	overlay.html( 'move' )
		.attr( 'id', 'Movebutton' )
		.css( 'position', 'fixed' )
		.css( 'bottom', '20px' )
		.css( 'height', '50px' )
		.css( 'width', '100%' )
		.css( 'font-size', '200%' );
	$( document.body ).append( overlay );
	overlay.toggle();
	overlay.click( function ( e ) {
		var numOfThreads, archiveTarget, sections, archiveThis, cutOffset,
			revisedPage;
		function cut( s, start, end ) {
			return s.substr( 0, start ) + s.substring( end );
		}
		cutOffset = numOfThreads = 0;
		revisedPage = wikiText;
		sections = $( 'a.arxylink' ).map( function () {
			return $( this ).attr( 'data-section' );
		} );
		if ( !( numOfThreads = sections.length ) ) {
			return alert( 'No sections selected, aborting' );
		}
		archiveTarget = prompt(
			'Moving' + numOfThreads + ' sections: where should we move them to?',
			mw.config.get( 'wgPageName' )
		);
		if ( !archiveTarget || archiveTarget == mw.config.get( 'wgPageName' ) ) {
			return alert( 'No target selected, aborting' );
		}
		sections.each( function ( i, n ) {
			revisedPage = cut(
				revisedPage,
				fromTos[ n ][ 0 ] - cutOffset,
				fromTos[ n ][ 1 ] - cutOffset
			);
			cutOffset += fromTos[ n ][ 1 ] - fromTos[ n ][ 0 ];
		} );
		archiveThis = sections.map( function () {
			return wikiText.substring( fromTos[ this ][ 0 ], fromTos[ this ][ 1 ] );
		} ).toArray().join( '' );
		console.log( 'archive this:' + archiveThis );
		console.log( 'revised page:' + revisedPage );
		if ( 1 ) {
			new mw.Api().postWithToken(
				'csrf',
				{
					action: 'edit',
					title: mw.config.get( 'wgPageName' ),
					text: revisedPage,
					summary: 'Chuyển phần mục đến [[' + archiveTarget + ']] sử dụng SectionMover',
					basetimestamp: revStamp,
					starttimestamp: revStamp
				}
			).done( function ( res1 ) {
				alert( 'Successfully moved sections from page' );
				console.log( res1 );
				new mw.Api().postWithToken(
					'csrf',
					{
						action: 'edit',
						title: archiveTarget,
						appendtext: '\n' + archiveThis,
						summary: 'Chuyển phần mục từ [[' + mw.config.get( 'wgPageName' ) + ']] sử dụng SectionMover'
					}
				).done( function ( res2 ) {
					alert( 'Successfully added sections to page' );
				} ).fail( function ( res2 ) {
					alert( 'failed to add sections to page. manual inspection needed.' );
				} ).always( function ( res2 ) {
					console.log( res2 );
					window.location.reload();
				} );
			} ).fail( function ( res1 ) {
					alert( 'failed to move sections from page. aborting process.' );
					console.log( res1 );
					window.location.reload();
				} );
		}
	} );
	new mw.Api().get( {
		action: 'parse',
		page: mw.config.get( 'wgPageName' )
	} ).done( function ( dataShit ) {
			var i;
			new mw.Api().get( {
				action: 'query',
				pageids: mw.config.get( 'wgArticleId' ),
				prop: [ 'revisions' ],
				rvprop: [ 'content', 'timestamp' ]
			} ).done( function ( shit ) {
				var rv;
				rv = shit.query.pages[ mw.config.get( 'wgArticleId' ) ].revisions[ 0 ];
				wikiText = rv[ '*' ];
				revStamp = rv.timestamp;
			} );
			$( dataShit.parse.sections )
				.filter( function ( i, s ) { return s.index == parseInt( s.index ) } )
				.each( function ( i, s ) { validSections[ s.index ] = s } );
			for ( i in validSections ) {
				i = parseInt( i );
				fromTos[ i ] = [
					validSections[ i ].byteoffset,
					validSections.hasOwnProperty( i + 1 ) ? validSections[ i + 1 ].byteoffset : Infinity
				];
			}
			$( '#mw-content-text' )
				.find( ':header' )
				.find( 'span.mw-headline' )
				.each( function ( i, title ) {
					var header, editSection, sectionNumber;
					header = $( this ).parent();
					editSection = header.find( '.mw-editsection' ); // 1st child
					sectionNumber = header.find( '.mw-editsection a:first' );
					if ( sectionNumber[ 0 ] ) {
						sectionNumber = sectionNumber.attr( 'href' ).match( /&section=(\d+)/ );
						if ( sectionNumber ) {
							sectionNumber = sectionNumber[ 1 ];
						} else {
							// eg <h2>not a real section</h2>
							sectionNumber = undefined;
						}
					}
					if ( validSections.hasOwnProperty( sectionNumber ) ) {
						editSection[ 0 ].innerHTML += '&nbsp;'
							+ '<span class=arxy style=display:none>'
							+ '<span class=mw-editsection-bracket>[</span>'
							+ '<a data-section=' + sectionNumber + ' '
							+ 'onclick=$(this).closest(\':header\').toggleClass(\'arxyhighlight\');$(this).toggleClass(\'arxylink\');>'
							+ 'move section</a>'
							+ '<span class=mw-editsection-bracket>]</span>'
							+ '</span>';
					}
				} );
		} );
} );



(function ($, mw, OO) {
    function loadCSS(resources) {
        resources.forEach(function (resource) {
            mw.loader.load('/w/index.php?title=MediaWiki:Gadget-' + resource + '&action=raw&ctype=text/css', 'text/css');
        });
    }

    function createBasketItems(resources) {
        var basketItems = [];
        resources.forEach(function (resource) {
            basketItems.push({
                url: '/w/index.php?title=MediaWiki:Gadget-' + resource + '&action=raw&ctype=text/javascript',
                key: resource,
                expire: 168 // Cache for 7 days
            });
        });
        return basketItems;
    }

    function utils() {
        // Don't zoom-in when focusing input
        $('head').append('<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>');
        // CSS for better Twinkle dialog on mobile
        mw.loader.load('//vi.wikipedia.org/w/index.php?title=User:P.T.Đ/TwinkleMobile.css&action=raw&ctype=text/css', 'text/css');
    }

    function main() {
        var twinkleDependencies = ['morebits.js', 'select2.min.js', 'Twinkle.js'],
            twinkleModules = [
                'twinkleconfig.js',
                'twinkleprod.js',
                'twinkleimage.js',
                'twinklewarn.js',
                'twinkleblock.js',
                'twinklespeedy.js',
                'friendlyshared.js',
                'twinklediff.js',
                'twinkleunlink.js',
                'friendlytag.js',
                'twinkledeprod.js',
                'friendlywelcome.js',
                'twinklexfd.js',
                'twinklebatchdelete.js',
                'twinklebatchundelete.js',
                'twinklebatchprotect.js',
                'twinkleprotect.js',
                'twinklearv.js',
                'friendlytalkback.js'
            ],
            twinkleModulePortletLinks = [];

        utils();
        loadCSS(['morebits.css', 'select2.min.css']);

        basket.require.apply(basket, createBasketItems(twinkleDependencies)).then(function () {
            // Override Twinkle.addPortletLink function
            Twinkle.addPortletLink = function (task, text, id, tooltip) {
                twinkleModulePortletLinks.push({
                    task: task,
                    text: text,
                    id: id,
                    tooltip: tooltip
                });
            };

            // Fix bug on Minerva (it doesn't have this)
            mw.config.set('wgCategories', []);

            // Fix bug on Special:MobileDiff pages
            if (mw.config.get('wgCanonicalSpecialPageName') === 'MobileDiff') {
                mw.config.set('wgNamespaceNumber', mw.Title.newFromText(mw.config.get('wgRelevantPageName')).getNamespaceId());
                mw.config.set('wgArticleId', mw.config.get('wgRelevantArticleId'));
                mw.config.set('wgPageName', mw.config.get('wgRelevantPageName'));
                mw.config.set('wgCurRevisionId', mw.config.get('wgDiffNewId'));
                Morebits.pageNameNorm = mw.config.get('wgRelevantPageName').replace(/_/g, ' ');
                window.history.replaceState(null, null, '?diff=' + mw.config.get('wgDiffNewId'));
            }

            return basket.require.apply(basket, createBasketItems(twinkleModules));
        }).then(function () {
            setTimeout(function () {
                // Create TwinkleMobile portlet link and dialog
                function TwinkleMobileDialog(config) {
                    TwinkleMobileDialog.super.call(this, config);
                }
                OO.inheritClass(TwinkleMobileDialog, OO.ui.ProcessDialog);

                TwinkleMobileDialog.static.name = 'TwinkleMobileDialog';
                TwinkleMobileDialog.static.title = 'TwinkleMobile';
                TwinkleMobileDialog.static.actions = [
                    {
                        action: 'save',
                        label: mw.message('ooui-popup-widget-close-button-aria-label').text(),
                        flags: ['primary', 'progressive']
                    }
                ];

                TwinkleMobileDialog.prototype.initialize = function () {
                    var dialog = this;

                    TwinkleMobileDialog.super.prototype.initialize.apply(this, arguments);
                    this.panel = new OO.ui.PanelLayout({
                        padded: true,
                        expanded: false
                    });
                    this.content = new OO.ui.FieldsetLayout();

                    var fields = [];
                    twinkleModulePortletLinks.forEach(function (link) {
                        var button;

                        if (typeof link.task === 'string') {
                            button = new OO.ui.ButtonWidget({
                                href: link.task,
                                label: link.text,
                                id: link.id,
                                title: link.tooltip
                            });
                        }

                        if (typeof link.task === 'function') {
                            button = new OO.ui.ButtonWidget({
                                label: link.text,
                                id: link.id,
                                title: link.tooltip
                            });
                            button.on('click', function (e) {
                                link.task();
                                // Only close TwinkleMobile dialog when Twinkle dialog is opened
                                if ($('.morebits-dialog').length !== 0) {
                                    dialog.close();
                                }
                            });
                        }

                        fields.push(new OO.ui.FieldLayout(button));
                    });

                    if (fields.length === 0) {
                        fields.push(new OO.ui.LabelWidget({
                            label: 'Nothing'
                        }));
                    }

                    this.content.addItems(fields);
                    this.panel.$element.append(this.content.$element);
                    this.$body.append(this.panel.$element);
                };

                TwinkleMobileDialog.prototype.getActionProcess = function (action) {
                    var dialog = this;
                    if (action) {
                        return new OO.ui.Process(function () {
                            dialog.close({
                                action: action
                            });
                        });
                    }
                    return TwinkleMobileDialog.super.prototype.getActionProcess.call(this, action);
                };

                TwinkleMobileDialog.prototype.getBodyHeight = function () {
                    return this.panel.$element.outerHeight(true);
                };

                var windowManager = new OO.ui.WindowManager();
                $(document.body).append(windowManager.$element);

                windowManager.addWindows([new TwinkleMobileDialog({
                    size: 'small'
                })]);

                var twmbLink = mw.util.addPortletLink('p-personal', '#', 'TwinkleMobile', 'twmb', 'TwinkleMobile');
                $(twmbLink).click(function (e) {
                    windowManager.openWindow('TwinkleMobileDialog');
                    e.preventDefault();
                });
            }, 1000); // Execute this after all Twinkle modules is executed
        }).catch(function (e) {
            mw.log.error(e.message);
        });
    }

    mw.loader.using([
        'mediawiki.user', 'mediawiki.util', 'mediawiki.Title',
        'mediawiki.api', 'mediawiki.language', 'jquery.ui',
        'oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui-windows'
    ]).then(function () {
        if (mw.config.get('wgUserGroups').includes('autoconfirmed')
            && mw.config.get('skin') === 'minerva') {
            return new mw.Api().loadMessagesIfMissing([
                'ooui-popup-widget-close-button-aria-label'
            ]);
        } else {
            throw new Error('TwinkleMobile only works with Minerva skin and autoconfirmed users');
        }
    }).then(function () {
        return mw.loader.getScript('https://tools-static.wmflabs.org/cdnjs/ajax/libs/basket.js/0.5.2/basket.full.min.js');
    }).then(main).catch(function (e) {
        mw.log.error(e.message);
    });
})(jQuery, mediaWiki, OO);