プロジェクト:ウィキ技術部/スクリプト開発/trunk/MassRollback.js
表示
/*********************************************************************************************\
MassRollback (一括巻き戻しスクリプト)
利用者の投稿記録上でツールボックスに一括巻き戻し用リンクを追加します。
可能な設定:
* ボット巻き戻し (管理者のみ)
* 利用者名を隠した巻き戻し
* 巻き戻し対象ページをウォッチリストに追加
作者: [[User:Dragoniez]]
\*********************************************************************************************/
//<nowiki>
(function(mw, $) {
// [[特別:投稿記録]]のみでスクリプトを使用
if (mw.config.get('wgCanonicalSpecialPageName') !== 'Contributions') return;
// 依存モジュールとDOMの読み込みが完了したら
$.when(
mw.loader.using(['mediawiki.util', 'jquery.ui']),
$.ready
).then(function() {
// ページ内に巻き戻しリンクがあれば
if ($('.mw-rollback-link:visible').length !== 0) {
// 一括巻き戻し用のポートレットリンクを生成
$(mw.util.addPortletLink('p-tb', '#', '一括巻き戻し' , 't-mr', '投稿記録の一括巻き戻し')).click(openDialog);
}
});
/**
* ダイアログを生成・開く
* @param {jQuery.event} e
*/
function openDialog(e) {
// リンク先への遷移をキャンセル
e.preventDefault();
// ダイアログが生成されていなければ
if ($('#mr-dialog').length === 0) {
// <style>タグを生成
$('head').append(
'<style>' +
'.mr-checkbox {' +
'margin-right: 0.3em;' +
'}' +
'</style>'
);
// ダイアログのHTMLを生成
$('body').append(
'<div id="mr-dialog" title="Mass Rollback">' +
'<h2>一括巻き戻し</h2>' +
'<div>' +
'<div id="mr-bot" style="display: none;">' +
'<input id="mr-bot-checkbox" class="mr-checkbox" type="checkbox"></input>' +
'<label for="mr-bot-checkbox">ボット巻き戻し</label>' +
'</div>' +
'<div id="mr-hideusername">' +
'<input id="mr-hideusername-checkbox" class="mr-checkbox" type="checkbox"></input>' +
'<label for="mr-hideusername-checkbox">利用者名を隠す</label>' +
'</div>' +
'<div id="mr-watchlist">' +
'<input id="mr-watchlist-checkbox" class="mr-checkbox" type="checkbox"></input>' +
'<label for="mr-watchlist-checkbox">巻き戻し対象ページをウォッチリストに追加</label>' +
'</div>' +
'</div>' +
'</div>'
);
// 使用者が特定の利用者権限を持つ場合、「ボット巻き戻し」のチェックボックスを表示しチェック
var allowedMarkBot = [].concat(mw.config.get('wgUserGroups'), mw.config.get('wgGlobalGroups')).some(function(group) {
return $.inArray(group, ['sysop', 'global-sysop', 'global-rollbacker', 'steward']) !== -1;
});
if (allowedMarkBot) {
$('#mr-bot').css('display', 'block');
$('#mr-bot-checkbox').prop('checked', true);
}
}
// 生成したHTMLをダイアログ化
$('#mr-dialog').dialog({
resizable: false,
height: 'auto',
width: 'auto',
minWidth: 515,
minHeight: 175,
modal: true,
buttons: [{
text: '実行',
click: massRollback
}, {
text: '閉じる',
click: function() {
$(this).dialog('close');
}
}]
});
}
var spinner = '<img src="https://upload.wikimedia.org/wikipedia/commons/4/42/Loading.gif" style="vertical-align: middle; height: 1em; border: 0;" />';
var dWidth, rblinkCnt;
/**
* 一括巻き戻し
*/
function massRollback() {
// 巻き戻しの設定を取得
var markBot = $('#mr-bot-checkbox').is(':checked'),
hideUsername = $('#mr-hideusername-checkbox').is(':checked'),
watchPage = $('#mr-watchlist-checkbox').is(':checked'),
summary = hideUsername ? '$1 による ID: $3 ($4) の版へ[[H:RV|巻き戻し]]' : null;
// パラメータを取得
var params = (markBot ? '&bot=1' : '') + (watchPage ? '&watchlist=watch' : '&watchlist=nochange') + (summary ? '&summary=' + summary : '');
// ダイアログコンテンツを変更
dWidth = $('#mr-dialog').width();
rblinkCnt = $('.mw-rollback-link:visible').length;
$('#mr-dialog')
.dialog({buttons: []}) // ボタンを隠す
.css('width', dWidth) /// 処理開始時にダイアログが小さくならないように、横幅を絶対値に変更
.children('div').empty() // ダイアログの内容を除去
.append( // 進捗状態を新たに表示
'<p>' +
'リンク数: ' + rblinkCnt +
' 成功: <span id="mr-progress-resolved">0</span>' +
' 失敗: <span id="mr-progress-rejected">0</span>' +
'</p>' +
'<p id="mr-progress-msg">一括巻き戻しを実行中' + spinner + '</p>'
);
// 全ての巻き戻しリンクをループ処理
$('.mw-rollback-link:visible').each(function() {
var href = $(this).children('a').attr('href') + params;
rollback($(this), href);
});
}
var rollbackCnt = 0,
resolveCnt = 0,
rejectCnt = 0;
/**
* 一括巻き戻しの内部処理 (単一の巻き戻し)
* @param {jQuery} $rblink
* @param {string} href
*/
function rollback($rblink, href) {
// 巻き戻しリンクをスピナーに置換
$rblink.removeClass('mw-rollback-link').prop('innerHTML', spinner);
// ボット巻き戻しのリンクがある場合は除去 ([[MediaWiki:Gadget-rollbackBot.js]])
$rblink.siblings('.mw-rollback-link-bot').remove();
// 巻き戻しを実行
$.ajax({
url: href
}).then(function() { // 成功
rollbackCnt++;
resolveCnt++;
$('#mr-progress-resolved').text(resolveCnt);
$rblink.prop('innerHTML', '[巻き戻し完了]');
}).catch(function() { // 失敗
rollbackCnt++;
rejectCnt++;
$('#mr-progress-rejected').text(rejectCnt);
$rblink.prop('innerHTML', '[巻き戻し失敗]');
}).then(function() { // 成功・失敗の処理後
// 最後の一括巻き戻し処理の場合、ブラウザがrepaintしたらダイアログの表示項目を変更
window.requestAnimationFrame(function() {
setTimeout(function() {
if (rollbackCnt === rblinkCnt) {
$('#mr-progress-msg').text('一括巻き戻し処理が完了しました').css('color', 'MediumSeaGreen');
$('#mr-dialog').dialog({
buttons: [{
text: '閉じる',
click: function() {
$(this).dialog('close');
}
}]
}).css('width', dWidth);
}
});
});
});
}
// ダイアログを閉じる際、ページ内に巻き戻しリンクがなければダイアログとポートレットリンクを除去
$(document).off('dialogclose', '#mr-dialog').on('dialogclose', '#mr-dialog', function() {
if ($('.mw-rollback-link:visible').length === 0) {
$('#mr-dialog, #t-mr').remove();
}
});
})(mediaWiki, jQuery);
//</nowiki>