MediaWiki:Gadget-ondemand-arbcomVoting.js: различия между версиями
Перейти к навигации
Перейти к поиску
Содержимое удалено Содержимое добавлено
Kalan (обсуждение | вклад) ещё актуализация |
Kalan (обсуждение | вклад) arb17 |
||
Строка 13: | Строка 13: | ||
'criteria': { |
'criteria': { |
||
'count': 500, |
'count': 500, |
||
'registration': '2013- |
'registration': '2013-08-12T23:59:60Z' |
||
}, |
}, |
||
'pagepath': 'Википедия:Выборы арбитров/ |
'pagepath': 'Википедия:Выборы арбитров/Осень 2013/Голосование', |
||
'talkpath': 'Википедия:Выборы арбитров/ |
'talkpath': 'Википедия:Выборы арбитров/Осень 2013/Обсуждение/', |
||
'votepath': 'Википедия:Выборы арбитров/ |
'votepath': 'Википедия:Выборы арбитров/Осень 2013/Голосование/', |
||
'start': new Date(' |
'start': new Date('Nov 22 2013 00:00 +0000'), |
||
'end': new Date(' |
'end': new Date('Nov 29 2013 00:00 +0000') |
||
} |
} |
||
var ico = { |
var ico = { |
||
Строка 66: | Строка 66: | ||
'thankyou': '<h3>Спасибо за участие в выборах!</h3><p>Вы сможете изменить ваши голоса до конца голосования.</p><p>Только что отданные голоса можно посмотреть на <a href="/ruwiki/wiki/Special:Mycontributions">странице вклада</a>.</p>' |
'thankyou': '<h3>Спасибо за участие в выборах!</h3><p>Вы сможете изменить ваши голоса до конца голосования.</p><p>Только что отданные голоса можно посмотреть на <a href="/ruwiki/wiki/Special:Mycontributions">странице вклада</a>.</p>' |
||
} |
} |
||
var cand = ' |
var cand = 'Dima io!El-chupanebrej!Krassotkin!Messir!Neolexx!Vajrapani!Vladimir Solovjev!W2!Wanderer777!Zemliakov!Иван Богданов!Роман Курносенко!Фил Вечеровский!Цезарь Валентиниан'.split('!') |
||
var wgAPIPath = wgServer + wgScriptPath + '/api.php?format=json&' |
var wgAPIPath = wgServer + wgScriptPath + '/api.php?format=json&' |
||
Версия от 23:14, 21 ноября 2013
(function(){
appendCSS('.cand-list { width: 25em } #voting-container ul { margin: 1.5em 0 } #voting-container ul li { width: 19em !important } #voting-help-final { margin: 3em 0 0; border-top: 1px solid #888} .cand-selected { background: #97B6E2 !important } #voting-limited-count { float: right; font-size: 300%; text-align: right; width: 1.5em; line-height: 100%; color: #ff5555 } #voting-limited-count.ok { color: #71C837; font-weight: bold }')
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 conf = {
'criteria': {
'count': 500,
'registration': '2013-08-12T23:59:60Z'
},
'pagepath': 'Википедия:Выборы арбитров/Осень 2013/Голосование',
'talkpath': 'Википедия:Выборы арбитров/Осень 2013/Обсуждение/',
'votepath': 'Википедия:Выборы арбитров/Осень 2013/Голосование/',
'start': new Date('Nov 22 2013 00:00 +0000'),
'end': new Date('Nov 29 2013 00:00 +0000')
}
var ico = {
'up': '/upwiki/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': 'Посмотреть',
'loadingvotes': 'Проверка имеющихся голосов…',
'draghere': 'Перетащите первого кандидата сюда',
'votinghelp': '<div class="voting-help"><h4>Основная часть</h4>\
<p>Расставьте голоса «за» и «против» рядом с именами тех кандидатов, относительно которых у вас сформировано мнение. Вы сможете дополнить или изменить выбор позже.</p>\
</div>',
'etchelp1': '<div class="voting-help"><h4>Дополнительная часть</h4>\
<p>Дополнительная часть состоит из нескольких опросников. Вы можете принять участие не во всех или вовсе проигнорировать этот блок, но лучше всего заполните все три. Это поможет улучшить процедуру выборов.</p></div>\
<div class="voting-help"><h5>Метод Шульце</h5>\
<ol>\
<li>Перетащите какого-нибудь подходящего, на ваш взгляд, кандидата на первый уровень.</li>\
<li>Перетаскивайте остальных кандидатов в этом же направлении. Кандидатов можно оставлять на существующих уровнях (отмечены цифрами) или на новых (места для их создания обозначены пунктиром). Во время перетаскивания пунктир показывает относительное расположение кандидата в списке.</li>\
<li>Перед сохранением убедитесь в соответствии расстановки вашему мнению: более хорошие кандидаты выше, менее хорошие ниже, равные на одном уровне, совсем неподходящие в разделе «нет предпочтения». Если вы являетесь одним из кандидатов, <em>не оставляйте</em> себя в нижней секции.</li>\
</ol>\
</div>',
'etchelp2': '<div id="voting-etc-schulze"></div>\
<div class="voting-help"><h5>Целевой набор резервных арбитров</h5>\
<p>Оцените, насколько каждый кандидат пригоден на роль <strong>именно резервного арбитра</strong>. Если, по вашему мнению, кандидат будет хорош только как основной арбитр, <strong>не голосуйте за</strong>.</p>\
</div>',
'etchelp3': '<div class="voting-help"><h5>Идеальный состав</h5>\
<p>Выберите <strong>ровно пять</strong> арбитров из списка. Голос за большее или меньшее количество арбитров будет сохранён, но проигнорирован при подсчёте.</p>\
</div>',
'etchelp4': '<div class="voting-help" id="voting-help-final"><p>До конца выборов вы сможете изменить своё мнение.</p>\
<p>Если что-то осталось непонятным, можно <a target="_blank" href="/wiki/Обсуждение_Википедии:Выборы_арбитров/Весна_2013/Голосование">задать вопрос</a>.</p></div>',
'nopreference': 'нет предпочтения',
'newlevel': 'новый уровень',
'justbeforesave': 'Смело направляйте любые отзывы, предложения и сообщения об ошибках на <a href="/wiki/MediaWiki_talk:Script/Voting.js">страницу обсуждения</a>.',
'savebutton': 'Сохранить',
'saveprog': '<b>Не закрывайте страницу</b> до завершения сохранения.',
'summary': '\u200Bг\u200Bол\u200Bос\u200B',
'thankyou': '<h3>Спасибо за участие в выборах!</h3><p>Вы сможете изменить ваши голоса до конца голосования.</p><p>Только что отданные голоса можно посмотреть на <a href="/wiki/Special:Mycontributions">странице вклада</a>.</p>'
}
var cand = 'Dima io!El-chupanebrej!Krassotkin!Messir!Neolexx!Vajrapani!Vladimir Solovjev!W2!Wanderer777!Zemliakov!Иван Богданов!Роман Курносенко!Фил Вечеровский!Цезарь Валентиниан'.split('!')
var wgAPIPath = wgServer + wgScriptPath + '/api.php?format=json&'
var votes = {}
var criteriaMatch
var saving = null
var aj = sajax_init_object()
var aj2 = sajax_init_object()
var token
// drag-n-drop
var coo
var cooD
var drag, dragGhost, dragItem, dragOriginal
var dragHere
function votingStart() {
importStylesheetURI('//ru.wikipedia.org/ruwiki/w/index.php?title=MediaWiki:Voting7.css&action=raw&ctype=text/css')
btn.disabled = true
btn.style.display = 'none'
status.innerHTML = loc.statuscriteria
aj2.onreadystatechange = votingStartContinue
aj2.open('GET', wgAPIPath + 'action=query&list=users&usprop=registration|editcount&prop=revisions&rvprop=content&ususers=' +
en(wgUserName) + '&titles=' + en(conf.votepath + '^'), true)
aj2.send('')
}
function votingStartContinue() {
if (aj2.readyState != 4) return
if (aj2.status != 200) { // temporary problems?
votingStart()
return
}
query = eval('(' + aj2.responseText + ')').query
userinfo = 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)) &&
// exemptions
('\n' + ch(query.pages).revisions[0]['*'] + '\n').indexOf('\n* %\n'.replace('%', wgUserName)) == -1)
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 = votingToken
btn.value = loc.savebutton
btn.disabled = true
// latest contributions in ns:4 + Schulze method page
aj.open('GET', wgAPIPath + 'action=query' +
'&list=usercontribs&ucnamespace=4&uclimit=500' +
'&ucuser=' + en(wgUserName) +
(tstamp(conf.start) ? '&ucend=' + tstamp(conf.start) : '') +
'&ucdir=older' +
'&fake=1&prop=revisions&rvprop=content' +
'&titles=' + en(conf.votepath+'$|')
+ en(conf.votepath+'%|')
+ en(conf.votepath+'=') ,
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 = ''
var query = eval('(' + aj.responseText + ')')
query = query.query
var co = query.usercontribs
for (var k in query.pages) {
spl = query.pages[k].revisions[0]['*'].split('\n')
switch (query.pages[k].title.match(/(.)$/)[1]) {
case '$':
var sc = spl
break
case '%':
var reserve = spl
break
case '=':
var limited = spl
break
}
}
// retrieving "traditional" votes, according to contributions, only latest ones are valid
for (i=0; i<cand.length; i++) votes[cand[i]] = {'orig':0, 'value':0}
for (var i=co.length-1; i>=0; i--) {
var m = co[i].title.indexOf(conf.votepath) == 0
if (m) m = co[i].title.match(/\/([+-])\/(.*?)$/)
if (m) votes[m[2]] = { 'orig' : m[1]=='+' ? +1 : -1,
'value': 0 }
}
// retrieving Schulze method page
// we assume that the bot will immediately revert not-well-formed edits
for (i=0; i<sc.length; i++) {
if (sc[i].indexOf('* ' + wgUserName + ' | ') == 0) {
votes._s = {'reading': true}
var j = 0
continue
}
if (!votes._s) continue
if (sc[i].indexOf('* ') == 0) votes._s.reading = undefined
if (votes._s.reading) {
j++
var m = sc[i].match(/^\*(.) (.*)/)
m[2] = m[2].split(' | ')
votes._s[m[1]=='#'?j:0] = m[2]
}
}
if (!votes._s) {
votes._s = {0: cand}
}
if (!votes._s[1]) votes._s[1] = []
if (!votes._s[0]) votes._s[0] = []
if (votes._s.reading) votes._s.reading = undefined
// retrieving "reserve" voting
votes._r = {}
for (i = 0; i < cand.length; ++i)
votes._r[cand[i]] = { 'orig' : 0, 'value': 0 }
reading = false
for (i=0; i<reserve.length; i++) {
if (reserve[i].indexOf('* ' + wgUserName + ' | ') == 0) {
reading = true
continue
}
if (!votes._r) continue
if (reserve[i].indexOf('* ') == 0) reading = false
if (reading) {
m = reserve[i].match(/^\*: (.) (.*)$/)
votes._r[m[2]].orig = votes._r[m[2]].value = ((m[1] == '.') ? 0 : (m[1] == '+' ? 1 : -1))
}
}
// retrieving "limited" voting
votes._l = {}
for (i = 0; i < cand.length; ++i)
votes._l[cand[i]] = { 'orig' : 0, 'value': 0 }
reading = false
for (i=0; i<limited.length; i++) {
if (limited[i].indexOf('* ' + wgUserName + ' | ') == 0) {
reading = true
continue
}
if (!votes._l) continue
if (limited[i].indexOf('* ') == 0) reading = false
if (reading) {
m = limited[i].match(/^\*: (.) (.*)$/)
votes._l[m[2]].orig = votes._l[m[2]].value = ((m[1] == '.') ? 0 : 1)
}
}
// 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.match(/^_[srl]$/)) {
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 = wgServer + 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
dragHere = el('span')
dragHere.id = 'voting-draghere'
dragHere.innerHTML = loc.draghere
var divetc = el('div')
divetc.id = 'voting-schulze'
var div2 = el('div')
div2.id = 'voting-etc-schulze'
div2.innerHTML = loc.etchelp1
var ul = el('ul')
ul.id = 'schulze-list'
var gw, theid, can, first, level, spc
var c
for (i=1; i!=null; i==0 ? i=null : i++) {
gw = el('li')
gw.className = 'groundwork'
theid = el('div')
theid.className = 'li-id'
theid.innerHTML = !votes._s[i] ? i : (i==1 ? '' : i-1) + '…' + i
gw.appendChild(theid)
if (!votes._s[i]) i=0
level = el('li')
level.className = 'level'
if (i==0) level.id = 'voting-no-preference'
if (i==1 && votes._s[i].join('!') == '') {
level.appendChild(dragHere)
}
theid = el('div')
theid.className = 'li-id'
theid.innerHTML = i==0 ? loc.nopreference : i
level.appendChild(theid)
for (c=0; c<votes._s[i].length; c++) {
can = el('a')
can.onclick = function() { return false }
can.onmousedown = boxMouseDown
can.innerHTML = votes._s[i][c]
can.className = 'cand'
level.appendChild(can)
}
level.appendChild(spacer())
ul.appendChild(gw)
ul.appendChild(level)
}
div2.appendChild(ul)
divetc.appendChild(div2)
var div2 = el('div')
div2.id = 'voting-etc-reserve'
div2.innerHTML = loc.etchelp2
var tab = el('table')
var tr, img, td1, td2, td3, lin
for (i in votes._r) {
tr = el('tr')
td1 = el('td')
img = el('img')
img.alt = '+'
img.width = img.height = 19
img.src = ico.up + (votes._r[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 = 19
img.src = ico.up + (votes._r[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 = wgServer + 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)
}
div2.appendChild(tab)
var imgs = div2.getElementsByTagName('img')
for (i=0; i<imgs.length; i++) {
imgs[i].src = imgs[i].src.replace(/39px/, '19px')
imgs[i].parentNode.onclick = onclr
}
divetc.appendChild(div2)
var div2 = el('div')
div2.id = 'voting-etc-limited'
div2.innerHTML = loc.etchelp3
var count = 0
var hol = el('div')
hol.className = 'cand-list'
for (i in votes._l) {
one = el('a')
one.innerHTML = i
one.className = votes._l[i].orig ? 'cand cand-selected' : 'cand'
count += votes._l[i].orig
one.href = '#'
one.onclick = oncll
hol.appendChild(one)
}
var cnt = el('div')
cnt.id = 'voting-limited-count'
cnt.innerHTML = count
if (count == 5) cnt.className = 'ok'
div2.appendChild(cnt)
div2.appendChild(hol)
divetc.appendChild(div2)
var div2 = el('div')
div2.innerHTML = loc.etchelp4
divetc.appendChild(div2)
if (navigator.appName=='Microsoft Internet Explorer') {
// troubles with scopes
document.onmousemove = mouseMove
document.onmouseup = mouseUp
} else {
hookEvent('mousemove', mouseMove)
hookEvent('mouseup', mouseUp)
}
status.innerHTML = loc.justbeforesave
status.parentNode.insertBefore(div1, status)
status.parentNode.insertBefore(divetc, status)
}
function votingToken() {
aj = sajax_init_object()
aj.onreadystatechange = votingTokenContinue
aj.open('GET', wgAPIPath + 'action=query&prop=info&intoken=edit&titles=42', true)
aj.send('')
}
function votingTokenContinue() {
if (aj.readyState != 4) return
if (aj.readyState == 4 && aj.status != 200) {
votingToken()
return
}
token = eval('(' + aj.responseText + ')')
token = ch(token.query.pages).edittoken
votingSave()
}
function votingSave() {
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-schulze' ).style.visibility = 'hidden'
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': conf.votepath + (votes[i].value==1?'+':'-') + '/' + i}
}
}
var text, text2, changed
var ms, mi
var li = document.getElementById('schulze-list').getElementsByTagName('li')
text = text2 = '\n* ' + wgUserName + ' | ~' + '~~' + '~~\n'
for (i=0; i<li.length; i++) {
ms = li[i].getElementsByTagName('a')
if (ms.length) {
mi = []
for (var j=0; j<ms.length; j++) mi[mi.length] = ms[j].innerHTML
text += (li[i].id == 'voting-no-preference' ? '*: ' : '*# ') + mi.join(' | ') + '\n'
}
}
for (i=1; i!=null; i==0 ? i=null : i++) {
if (!votes._s[i]) i=0
if (votes._s[i].join('.')) text2 += (i==0 ? '*: ' : '*# ') + votes._s[i].join(' | ') + '\n'
}
if (text != text2) {
saving.pages[saving.cursor++] = {'page': conf.votepath + '$',
'text': text}
}
text = '\n* ' + wgUserName + ' | ~' + '~~' + '~~\n'
changed = false
for (var i in votes._l) {
text += '*: ' + (votes._l[i].value ? '+' : '.') + ' ' + i + '\n'
if (votes._l[i].orig != votes._l[i].value)
changed = true
}
if (changed) {
saving.pages[saving.cursor++] = {'page': conf.votepath + '=',
'text': text}
}
text = '\n* ' + wgUserName + ' | ~' + '~~' + '~~\n'
changed = false
var vd = {99: '-', 100: '.', 101: '+'}
for (var i in votes._r) {
text += '*: ' + vd[votes._r[i].value + 100] + ' ' + i + '\n'
if (votes._l[i].orig != votes._l[i].value)
changed = true
}
if (changed) {
saving.pages[saving.cursor++] = {'page': conf.votepath + '%',
'text': text}
}
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 = sajax_init_object()
aj.open('POST', wgAPIPath + 'action=edit¬minor=1&unwatch=1&token=' + en(token) + '&summary=' + en(loc.summary) +
'&title=' + en(saving.pages[saving.cursor].page) +
'&appendtext=' + en(saving.pages[saving.cursor].text), true)
aj.onreadystatechange = votingSave
aj.send('')
saving.cursor++
if (!saving.pages[saving.cursor]) {
saving.cursor = -1
document.getElementById('voting-container').innerHTML = loc.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 = 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
}
function onclr() {
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._r[ca].value = (votes._r[ca].value==vo) ? 0 : vo
imgs[0].src = ico.up + (votes._r[ca].value== 1 ?ico.suppact:(votes._r[ca].orig== 1 ?ico.suppinact:ico.supp)).replace(/39px/, '19px')
imgs[1].src = ico.up + (votes._r[ca].value==-1 ?ico.oppact :(votes._r[ca].orig==-1 ?ico.oppinact :ico.opp)).replace(/39px/, '19px')
link.className = ['opp', '', 'supp'][votes._r[ca].value + 1]
return false
}
function oncll() {
if (this.className == 'cand')
this.className = 'cand cand-selected'
else
this.className = 'cand'
var ca = this.innerHTML
votes._l[ca].value = (this.className == 'cand')?0:1
var count = 0
for (var i in votes._l)
count += votes._l[i].value
document.getElementById('voting-limited-count').innerHTML = count
document.getElementById('voting-limited-count').className = (count==5)?'ok':''
return false
}
// used by drag-n-drop
function disableSelection(el, g){
// doesn't work for Opera, thus onmousemove drops selection ranges
el.onselectstart = g ? function(){ return false } : null
el.unselectable = g ? "on" : "off"
el.style.MozUserSelect = g ? "none" : ""
}
function absolutePosition(el) {
q = el
co = {'x': 0, 'y': 0}
while (q.offsetParent){
co.x += q.offsetLeft
co.y += q.offsetTop
q = q.offsetParent
}
return co
}
function coords(e) {
if (e.pageX !== undefined)
return {'x': e.pageX, 'y': e.pageY}
else // IE (buggy for v7 while zoomed, but who cares?)
return {
'x': e.clientX + document.documentElement.scrollLeft,
'y': e.clientY + document.documentElement.scrollTop
}
}
function boxMouseDown() {
if (dragHere && dragHere.parentNode) dragHere.parentNode.removeChild(dragHere)
dragGhost = this
dragGhost.id = 'voting-ghost'
dragOriginal = dragItem = this.parentNode
dragItem.className += ' dragitem'
drag = document.createElement('a')
drag.innerHTML = this.innerHTML
drag.id = 'voting-drag'
drag.className = 'cand'
cooD = absolutePosition(dragGhost)
cooD.x -= coo.x
cooD.y -= coo.y
mouseMove({'pageX': coo.x, 'pageY': coo.y})
document.body.appendChild(drag)
disableSelection(document.body, true)
disableSelection(drag, true)
}
function mouseMove(e) {
coo = coords(e || window.event)
if (!drag) return
if (document.defaultView) // Opera: removing selection
document.defaultView.getSelection().removeAllRanges()
drag.style.left = (coo.x + cooD.x) + "px"
drag.style.top = (coo.y + cooD.y) + "px"
var lis = document.getElementById('schulze-list').getElementsByTagName('li')
var dragCurrent
for (i=0; i<lis.length; i++) {
pos = absolutePosition(lis[i])
if (pos.x <= coo.x &&
pos.y <= coo.y &&
pos.x + lis[i].offsetWidth > coo.x &&
pos.y + lis[i].offsetHeight > coo.y) {
dragCurrent = lis[i]
}
}
if (!dragCurrent) { // pointer outside the whole list, returning ghost to its original location
dragCurrent = dragOriginal
}
if (dragCurrent != dragItem) { // changing target level
dragItem.className = dragItem.className.replace(' dragitem', '')
d = dragItem.getElementsByTagName('div')[0]
d.innerHTML = d.innerHTML.replace(/^([^:]+).*/, '$1')
dragItem.removeChild(dragGhost)
dragItem = dragCurrent
dragItem.className += ' dragitem'
if (dragItem.className.match(/groundwork/)) {
dragItem.getElementsByTagName('div')[0].innerHTML += ': ' + loc.newlevel
dragItem.appendChild(dragGhost)
}
else { // not an empty level, so inserting dragGhost in an appropriate place
var bef
var ch = dragItem.getElementsByTagName('a')
var spacer = dragItem.getElementsByTagName('span')[0]
if (ch.length == 0) {
bef = spacer
} else {
bef = ch[0]
for (i=0; i<ch.length; i++)
if (ch[i].innerHTML < dragGhost.innerHTML)
bef = ch[i+1] || spacer
}
dragItem.insertBefore(dragGhost, bef)
}
}
}
function spacer() {
var el = document.createElement('span')
el.className = 'spacer'
el.innerHTML = ' '
return el
}
function mouseUp() {
if (!dragGhost || !drag || !dragItem) return
dragItem.className = dragItem.className.replace(' dragitem', '')
dragItem = null
dragGhost.id = ''
dragGhost = null
disableSelection(document.body, false)
disableSelection(drag, false)
document.body.removeChild(drag)
drag = null
// arranging structures
function groundwork() {
var el = document.createElement('li')
el.className = 'groundwork'
el.innerHTML = '<div class="li-id">!</div>'
return el
}
// creating groundworks around any newly created level
var lis = document.getElementById('schulze-list').getElementsByTagName('li')
for (i=0; i<lis.length-1; i++)
if (lis[i].className == 'groundwork' && lis[i].getElementsByTagName('a').length > 0) {
lis[i].className = 'level'
lis[i].appendChild(spacer())
lis[i].parentNode.insertBefore(groundwork(), lis[i].nextSibling)
lis[i].parentNode.insertBefore(groundwork(), lis[i])
}
// destroying empty levels, except when there's only one
var lis = document.getElementById('schulze-list').getElementsByTagName('li')
if (lis.length > 4)
for (i=0; i<lis.length-1; i++)
if (lis[i].className == 'level' && lis[i].getElementsByTagName('a').length == 0)
lis[i].parentNode.removeChild(lis[i])
// blowing up inevitable duplicate groundworks
var lis = document.getElementById('schulze-list').getElementsByTagName('li')
for (i=1; i<lis.length; i++) {
if (lis[i].className == 'groundwork' && lis[i-1].className == 'groundwork')
lis[i].parentNode.removeChild(lis[i])
}
var lis = document.getElementById('schulze-list').getElementsByTagName('li')
// "drag first candidate here" label
if (lis[1].getElementsByTagName('a').length == 0)
lis[1].insertBefore(dragHere, lis[1].getElementsByTagName('span')[0])
// renumbering
var j = 0
for (i=0; i<lis.length-1; i++) {
lis[i].getElementsByTagName('div')[0].innerHTML =
lis[i].className == 'groundwork'
? (j==0 ? '…'+(++j) : (i==lis.length-2 ? ++j : j+'…'+(++j))) : j
}
}
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)
})()