MediaWiki:Gadget-ondemand-arbcomVoting.js

Материал из Википедии — свободной энциклопедии
Это старая версия этой страницы, сохранённая Stjn (обсуждение | вклад) в 20:51, 1 марта 2024 (2 правки возвращены к версии 136285287 Stjn: не уверен, что в допотопном коде всё будет верно работать, поэтому отменю). Она может серьёзно отличаться от текущей версии.
Перейти к навигации Перейти к поиску
JS-код ниже относится к скрытому гаджету ondemand-arbcomVoting. Связанный CSS-файл: MediaWiki:Gadget-ondemand-arbcomVoting.css. Связанный JSON-файл: MediaWiki:Gadget-ondemand-arbcomVoting.json. Он вызывается по умолчанию на страницах в категории Википедия:Страницы с гаджетом по требованию arbcomVoting.

После сохранения или недавних изменений очистите кэш браузера.

/* 
 * Скрипт для выборов в Арбитражный комитет (ВП:АК)
 * 
 * Авторы: Kalan, Serhio Magpie (эта версия).
 * История правок старого скрипта:
 * https://ru.wikipedia.org/wiki/MediaWiki:Script/Voting-backup.js
 */

(function () {

	/******* COMMON ******* */

	function en(e) { return encodeURIComponent(e) }
	function el(e) { return document.createElement(e) }
	function tstamp(t) { return !t.getUTCFullYear() ? null : // Safari + Chrome
								(t.getUTCFullYear()+":0"+(t.getUTCMonth()+1)+":0"+t.getUTCDate()+":0"+
								t.getUTCHours()   +":0"+ t.getUTCMinutes() +":0"+t.getUTCSeconds())
								.replace(/:0?(\d\d)/g, '$1') }
	function ch(o) { for (var i in o) { return o[i] } }

	/******* VARIABLES *******/

	var data = {};	// MediaWiki:Script/Voting.json
	var wgServer = mw.config.get('wgServer');
	var wgScript = mw.config.get('wgScript');
	var wgAPIPath = wgServer + mw.config.get('wgScriptPath') + '/api.php?format=json&';
	var wgUserName = mw.config.get('wgUserName');
	var wgNamespaceNumber = mw.config.get('wgNamespaceNumber');
	var votes = {};
	var saving = null;
	var api = new mw.Api();
	var containerEl, statusEl, btnEl;

	/******* MAIN *******/
	function votingLength( date, days ) {
		var result = new Date( date );
		result.setDate( result.getDate() + days );
		return result;
	}

	function votingStart() {
		containerEl.className = 'active';
		statusEl.innerHTML = data.strings.statuscriteria;
		btnEl.setDisabled(true);
		btnEl.$element.css( 'display', 'none' );

		api.get({
			'action': 'query',
			'list': 'users',
			'usprop': ['registration', 'editcount'],
			'prop': 'revisions',
			'rvprop': 'content',
			'ususers': wgUserName,
			'titles': data.config.voteexceptionspath
		}).done(votingStartContinue);
	}

	function votingStartContinue(d) {
		query = d.query;
		pages = query.pages;
		userinfo = query.users[0];
		if ((// a valid voter must be a non-anonymous user
			typeof userinfo === 'undefined' || typeof userinfo.missing !== 'undefined' ||
			// who is not blocked
			userinfo.blockedby ||
			// whose editcount is at least data.config.criteria.count
			userinfo.editcount < data.config.criteria.count ||
			// and who is registered no later than data.config.criteria.registration
			// "null" means "before 2005-12-29", user creation was not logged before then
			(userinfo.registration !== null && userinfo.registration > data.config.criteria.registration)) &&
			// exemptions
			('\n' + ch(pages).revisions[0]['*'] + '\n').indexOf('\n* %\n'.replace('%', wgUserName)) == -1
		) {
			votingCriteriaFail();
		} else {
			votingContinue();
		}
	}

	function votingCriteriaFail() {
		statusEl.innerHTML = data.strings.criteriafail;
	}

	function votingContinue() {
		statusEl.innerHTML = data.strings.loadingvotes;
		// latest contributions in ns:4
		api.get({
			'action': 'query',
			'list': 'usercontribs',
			'ucnamespace': wgNamespaceNumber,
			'uclimit': 500,
			'ucuser': wgUserName,
			'ucend': tstamp(data.config.start),
			'ucdir': 'older',
			'prop': 'revisions',
			'rvprop': 'content'
		}).done(votingDraw);
	}

	function votingDraw(d) {
		statusEl.innerHTML = '';
		btnEl.setLabel(data.strings.savebutton);
		btnEl.setDisabled(false);
		btnEl.off('click').on('click', votingSave);
		btnEl.$element.css( 'display', '' );

		var query = d.query;
		var co = query.usercontribs;

		// retrieving votes, according to contributions, only latest ones are valid
		for (i=0; i<data.candidates.length; i++) {
			votes[data.candidates[i]] = {'orig':0, 'value':0};
		}
		for (var i=co.length-1; i>=0; i--) {
			var m = co[i].title.indexOf(data.config.votepath) === 0;
			if (m) {
				m = co[i].title.match(/\/([+-])\/(.*?)$/);
			}
			if (m) {
				votes[m[2]] = { 'orig' : m[1]=='+' ? +1 : -1, 'value': 0 };
			}
		}

		// drawing
		var div1 = el('div');
		div1.id = 'voting-standard';
		div1.innerHTML = data.strings.votinghelp;
		var tab = el('table');

		var tr, img, td1, td2, td3, lin;
		for (i in votes) {
			if (!i.match(/^_[srl]$/)) {
				tr = el('tr');
				td1 = el('td');
				img = el('img');
				img.alt = '+';
				img.width = img.height = 39;
				img.src = data.icons.up + (votes[i].orig == 1 ? data.icons.suppinact : data.icons.supp);
				lin = el('a');
				lin.href = '#';
				lin.title = '+';
				lin.appendChild(img);
				td1.appendChild(lin);

				td2 = el('td');
				img = el('img');
				img.alt = '−';
				img.width = img.height = 39;
				img.src = data.icons.up + (votes[i].orig == -1 ? data.icons.oppinact : data.icons.opp);
				lin = el('a');
				lin.href = '#';
				lin.title = '-';
				lin.appendChild(img);
				td2.appendChild(lin);

				td3 = el('td');
				td3.className = 'talklink';
				lin = el('a');
				lin.href = wgServer + wgScript + '?title=' + encodeURI(data.config.talkpath + i);
				lin.target = '_blank';
				lin.innerHTML = i;

				td3.appendChild(lin);

				tr.appendChild(td1);
				tr.appendChild(td2);
				tr.appendChild(td3);
				tab.appendChild(tr);
			}
		}
		div1.appendChild(tab);
		// IE has problems inserting the table
		div1.innerHTML += '';
		var imgs = div1.getElementsByTagName('img');
		for (i=0; i<imgs.length; i++) {
			imgs[i].parentNode.onclick = oncl;
		}

		statusEl.innerHTML = data.strings.justbeforesave;
		statusEl.parentNode.insertBefore(div1, statusEl);
	}
	function votingSave() {
		if (!saving) {
			var div = el('div');
			div.id = 'voting-saving';
			div.innerHTML = '<div id="voting-progress"><div id="voting-progress-progress" style="width:0%">&nbsp;</div></div>' + data.strings.saveprog;
			statusEl.parentNode.appendChild(div);
			btnEl.setDisabled(true);
			document.getElementById('voting-standard').style.visibility = 'hidden';

			saving = {'cursor': 0, 'pages': []};

			for (var i in votes) {
				if (votes[i].value != 0 && votes[i].orig != votes[i].value) {
					saving.pages[saving.cursor++] = {
						'text': '\n# [[user:' + wgUserName + '|' + wgUserName + ']] ~' + '~~' + '~~\n',
						'page': data.config.votepath + (votes[i].value==1?'+':'-') + '/' + i
					};
				}
			}

			saving.cursor = -5;
			if (saving.pages.length) {
				votingSave();
			} else {
				document.getElementById('voting-container').innerHTML = data.strings.thankyou;
			}
		} else {
			if (saving.cursor === -5) {
				saving.cursor = 0;
			}
			if (saving.cursor === -1) {
				return;
			}

			document.getElementById('voting-progress-progress').style.width = 100*(saving.cursor+1)/saving.pages.length + '%';

			api.postWithToken('edit', {
				'action': 'edit',
				'notminor': 1,
				'unwatch': 1,
				'summary': data.strings.summary,
				'title': saving.pages[saving.cursor].page,
				'appendtext': saving.pages[saving.cursor].text
			}).done(votingSave);
			saving.cursor++;
			if (!saving.pages[saving.cursor]) {
				saving.cursor = -1;
				document.getElementById('voting-container').innerHTML = data.strings.thankyou;
			}
		}
	}

	// onclick() for round buttons
	function oncl() {
		var imgs = this.parentNode.parentNode.getElementsByTagName('img');
		var link = this.parentNode.parentNode.getElementsByTagName('a')[2];
		var ca = link.innerHTML;
		var ti = this.title;
		var vo = ti=='+'?1:-1;
		votes[ca].value = (votes[ca].value==vo) ? 0 : vo;

		imgs[0].src = data.icons.up + (votes[ca].value== 1 ?data.icons.suppact:(votes[ca].orig== 1 ?data.icons.suppinact:data.icons.supp));
		imgs[1].src = data.icons.up + (votes[ca].value==-1 ?data.icons.oppact :(votes[ca].orig==-1 ?data.icons.oppinact :data.icons.opp));

		link.className = ['opp', '', 'supp'][votes[ca].value + 1];

		return false;
	}

	mw.loader.using(['mediawiki.util', 'oojs', 'oojs-ui']).done(function () {
		// Add styles
		mw.loader.load('//ru.wikipedia.org/ruwiki/w/index.php?title=MediaWiki:Voting.css&action=raw&ctype=text/css', 'text/css');
		// Load configuration
		$.getJSON( mw.util.wikiScript(), {
			title: 'MediaWiki:Script/Voting.json',
			action: 'raw'
		} ).done( function (ans) {
			data = ans;
			// Prepare dates
			data.config.start = new Date(data.config.start);
			if ( typeof data.config.votelength !== 'undefined' ) {
				data.config.end = votingLength( data.config.start, data.config.votelength );
			} else {
				data.config.end = new Date( data.config.end );
			}
			// Prepare pages paths
			data.config.pagepath = data.config.pagepath.replace('%config.path%', data.config.path);
			data.config.talkpagepath = data.config.talkpagepath.replace('%config.path%', data.config.path);
			data.config.talkpath = data.config.talkpath.replace('%config.path%', data.config.path);
			data.config.votepath = data.config.votepath.replace('%config.path%', data.config.path);
			data.config.voteexceptionspath = data.config.voteexceptionspath.replace('%config.path%', data.config.path);
			// Prepare strings
			data.strings.justbeforesave = data.strings.justbeforesave.replace('%config.talkpagepath%', data.config.talkpagepath);
			// Init
			containerEl = document.getElementById('voting-container');
			if ( containerEl ) {
				containerEl.innerHTML = '';

				statusEl = el('div');
				statusEl.id = 'voting-status';
				containerEl.appendChild(statusEl);

				btnEl = new OO.ui.ButtonWidget( {
					label: data.strings.votebutton,
					flags: ['primary', 'progressive'],
					id: 'voting-button'
				} );
				btnEl.on('click', votingStart);
				containerEl.appendChild(btnEl.$element.get(0));
			}
		} );
	} );
})();