MediaWiki:Voting.js
Увага: Після публікування слід очистити кеш браузера, щоб побачити зміни.
- Firefox / Safari: тримайте Shift, коли натискаєте Оновити, або натисніть Ctrl-F5 чи Ctrl-Shift-R (⌘-R на Apple Mac)
- Google Chrome: натисніть Ctrl-Shift-R (⌘-Shift-R на Apple Mac)
- Internet Explorer / Edge: тримайте Ctrl, коли натискаєте Оновити, або натисніть Ctrl-F5
- Opera: натисніть Ctrl-F5
(function(){
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]; } }
var start = new Date("Sep 24 2023 21:00:00 +0000");
var conf = {
'start': start,
'actual': new Date(),
'end': new Date(start.setDate(start.getDate()+14)),
'criteria': {
'count': 300,
'registration': new Date(start.setDate(start.getDate()-90)).toISOString()
},
'pagepath': 'Вікіпедія:Вибори арбітрів/2023/Голосування',
'talkpath': 'Вікіпедія:Вибори арбітрів/2023/Обговорення/',
'votepath': 'Вікіпедія:Вибори арбітрів/2023/Голосування/'
};
var ico = {
'up': '//upload.wikimedia.org/wikipedia/commons/thumb/',
'supp' : '2/2d/Support-gray.svg/39px-Support-gray.svg.png',
'suppinact' : '8/8d/Support-colored.svg/39px-Support-colored.svg.png',
'suppact' : '5/5b/Support-filled.svg/39px-Support-filled.svg.png',
'opp' : 'e/e7/Oppose-gray.svg/39px-Oppose-gray.svg.png',
'oppinact' : '0/06/Oppose-colored.svg/39px-Oppose-colored.svg.png',
'oppact' : '7/7d/Oppose-filled.svg/39px-Oppose-filled.svg.png'
};
var loc = {
'votebutton': 'Проголосувати',
'statuscriteria': 'Перевірка критеріїв…',
'criteriafail': '<h3 class="voting-error">Ви не відповідаєте критеріям.</h3><p>Ваші голоси на цих виборах <b>не будуть враховані</b>.</p><p>Утім, якщо вам просто цікаво, як працює скрипт, ви можете подивитись на нього без збереження голосів.</p>',
'criteriafailbutton': 'Переглянути',
'votingend': '<big>Голосування завершилось</big>',
'notstartyet': '<big>Голосування ще не розпочалось</big>',
'loadingvotes': 'Перевірка наявних голосів…',
'votinghelp': '<p>Розставте голоси «за» і «проти» поряд з іменами тих кандидатів, щодо яких у вас сформована думка. Ви зможете доповнити чи змінити вибір пізніше.</p>\
</div>',
'justbeforesave': 'Сміливо пишіть будь-які відгуки, пропозиції та повідомлення про помилки на <a href="/wiki/MediaWiki_talk:Voting.js">сторінці обговорення</a>.',
'savebutton': 'Зберегти',
'saveprog': '<b>Не закривайте сторінку</b> до завершення збереження.',
'summary': '+\u200B',
'thankyou': '<h3>Дякуємо за участь у виборах!</h3><p>Ви зможете змінити ваші голоси до кінця голосування.</p><p>Щойно віддані голоси можна подивитись на <a href="/wiki/Special:Mycontributions">сторінці внеску</a>.</p>'
};
var cand = 'Ahonc : AlexKozur : AS : JTs : Repakr : Submajstro : UeArtemis : Антон Даньків : Віщун : Долинський : Юрко Градовський'.split(' : ');
var wgAPIPath = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&';
var votes = {};
var criteriaMatch;
var saving = null;
var aj = new XMLHttpRequest();
var token = mw.user.tokens.get( 'csrfToken' );
function votingStart() {
if (tstamp(conf.start)<tstamp(conf.actual)) {
if (tstamp(conf.end)>tstamp(conf.actual)) {
mw.loader.load('//uk.wikipedia.org/w/index.php?title=MediaWiki:Voting.css&action=raw&ctype=text/css', 'text/css');
btn.disabled = true;
btn.style.display = 'none';
status.innerHTML = loc.statuscriteria;
aj.onreadystatechange = votingStartContinue;
aj.open('GET', wgAPIPath + 'action=query&list=users&usprop=registration|editcount&ususers=' +
en(mw.config.get('wgUserName')) +
'&rawcontinue=', true);
aj.send('');
}
else votingEnd();
}
else votingNotStartYet();
}
function votingStartContinue() {
if (aj.readyState != 4) return;
if (aj.status != 200) { // temporary problems?
votingStart();
return;
}
userinfo = eval('(' + aj.responseText + ')').query.users[0];
if (// a valid voter must be a non-anonymous user
userinfo.missing !== undefined ||
// who is not blocked
userinfo.blockedby ||
// whose editcount is at least conf.criteria.count
userinfo.editcount < conf.criteria.count ||
// and who is registered no later than conf.criteria.registration
// "null" means "before 2005-12-29", user creation was not logged before then
(userinfo.registration !== null && userinfo.registration > conf.criteria.registration))
votingCriteriaFail();
else {
criteriaMatch = 1;
votingContinue();
}
}
function votingCriteriaFail() {
status.innerHTML = loc.criteriafail;
btn.style.display = '';
btn.disabled = false;
btn.value = loc.criteriafailbutton;
btn.onclick = function(){criteriaMatch = 0; votingContinue();};
}
function votingContinue() {
status.innerHTML = loc.loadingvotes;
btn.style.display = '';
btn.onclick = votingSave;
btn.value = loc.savebutton;
btn.disabled = true;
// latest contributions in ns:4
aj.open('GET', wgAPIPath + 'action=query' +
'&list=usercontribs&ucnamespace=4&uclimit=500' +
'&ucuser=' + en(mw.config.get('wgUserName')) +
(tstamp(conf.start) ? '&ucend=' + tstamp(conf.start) : '') +
'&ucdir=older&rawcontinue=' ,
true);
aj.onreadystatechange = votingDraw;
aj.send('');
}
function votingDraw() {
if (aj.readyState != 4) return;
if (aj.status != 200) { // temporary problems?
votingContinue();
return;
}
btn.disabled = !criteriaMatch;
status.innerHTML = '';
for (i=0; i<cand.length; i++) votes[cand[i]] = {'orig':0, 'value':0};
var query = eval('(' + aj.responseText + ')');
query = query.query;
var co = query.usercontribs;
// retrieving votes; according to contributions, only latest ones are valid
for (var i=co.length-1; i>=0; i--) {
var m = co[i].title.indexOf(conf.votepath) == 0 && co[i].comment == loc.summary;
if (m) m = co[i].title.match(/\/2023\/Голосування\/(.*?)\/([+-])$/);
if (m) votes[m[1]] = { 'orig' : m[2]=='+' ? +1 : -1,
'value': 0 };
}
// drawing
var div1 = el('div');
div1.id = 'voting-standard';
div1.innerHTML = loc.votinghelp;
var tab = el('table');
var tr, img, td1, td2, td3, lin;
for (i in votes) {
if (i != '_') {
tr = el('tr');
td1 = el('td');
img = el('img');
img.alt = '+';
img.width = img.height = 39;
img.src = ico.up + (votes[i].orig == 1 ? ico.suppinact : ico.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 = ico.up + (votes[i].orig == -1 ? ico.oppinact : ico.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 = mw.config.get('wgServer') + mw.config.get('wgScript') + '?title=' + encodeURI(conf.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;
status.innerHTML = loc.justbeforesave;
status.parentNode.insertBefore(div1, status);
}
function votingSave() {
if (tstamp(conf.end)>tstamp(new Date())) {
if (saving == null) {
var div = el('div');
div.id = 'voting-saving';
div.innerHTML = '<div id="voting-progress"><div id="voting-progress-progress" style="width:0%"> </div></div>' + loc.saveprog;
status.parentNode.appendChild(div);
btn.disabled = 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:' + mw.config.get('wgUserName') + '|' + mw.config.get('wgUserName') + ']] ~' + '~~' + '~~\n',
'page': conf.votepath + i + '/' + (votes[i].value==1?'+':'-')};
saving.cursor++;
}
}
saving.cursor = -5;
if (saving.pages.length)
votingSave();
else
document.getElementById('voting-container').innerHTML = loc.thankyou;
} else {
if (saving.cursor != -5 && aj.readyState != 4) return;
if (aj.readyState == 4 && aj.status != 200) {
votingSave();
return;
}
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 + '%';
aj = new XMLHttpRequest();
aj.open('POST', mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php', true);
aj.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
aj.onreadystatechange = votingSave;
aj.send('format=json&action=edit&summary=' + en(loc.summary) +
'&title=' + en(saving.pages[saving.cursor].page) +
'&appendtext=' + en(saving.pages[saving.cursor].text) +
'&token=' + en(token));
saving.cursor++;
if (!saving.pages[saving.cursor]) {;
saving.cursor = -1;
document.getElementById('voting-container').innerHTML = loc.thankyou;
}
}
}
else
votingEnd();
}
function votingEnd() {
status.innerHTML = loc.votingend;
btn.style.display = '';
btn.disabled = true;
btn.value = loc.criteriafailbutton;
}
function votingNotStartYet() {
status.innerHTML = loc.notstartyet;
btn.style.display = '';
btn.disabled = true;
btn.value = loc.criteriafailbutton;
}
// 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 = ico.up + (votes[ca].value== 1 ?ico.suppact:(votes[ca].orig== 1 ?ico.suppinact:ico.supp));
imgs[1].src = ico.up + (votes[ca].value==-1 ?ico.oppact :(votes[ca].orig==-1 ?ico.oppinact :ico.opp));
link.className = ['opp', '', 'supp'][votes[ca].value + 1];
return false;
}
if (mw.config.get('wgPageName').replace(/_/g,' ') == conf.pagepath) {
document.getElementById('voting-container').innerHTML = '';
var btn = el('input');
btn.type = 'button';
btn.id = 'voting-button';
btn.value = loc.votebutton;
btn.onclick = votingStart;
var status = el('div');
status.id = 'voting-status';
document.getElementById('voting-container').appendChild(status);
document.getElementById('voting-container').appendChild(btn);
}
})();