View text source at Wikipedia
var logPage = new function(){
var imcomm = 'http://upload.wikimedia.org/wikipedia/commons/'
var imuser = '/skins-1.5/monobook/user.gif'
var m = {
//Mediawiki messages: considered default for IP blocks
mwAnonOnly: 'anon. only', //considered default for IP blocks
mwNoReg: 'account creation blocked', //considered default
//Mediawiki messages: considered unusual for user blocks
mwNoAuto: 'autoblock disabled',
mwNoEmail: 'e-mail blocked',
//output messages
NotAnonOnly: ' <span title="Registered users also blocked">'
+ '<img src='+imcomm+'thumb/c/cc/Nuvola_apps_kdmconfig.png/15px-Nuvola_apps_kdmconfig.png>'
+ '</span>',
YesReg: '<span title="Registration is ok"><img src='+imuser+'></span>',
NoAuto: '<s>autoblock</s>',
NoEmail: '<img src='+imcomm+'thumb/3/3e/Email_delete.png/12px-Email_delete.png>',
NewUserLog: 'account creation log',
ShowTable: '[show table]',
ShowList: '[show list]'
}
var type, user, ul, lis, logTable, logLink, tbody, isTable = false
var thisYear = (new Date()).getFullYear()
this.onLoad = function(){
//get page structure
var content = document.getElementById('content') || document.body
ul = content.getElementsByTagName('ul')[0]
if (!ul) return //log is empty
//create and attach switching link
logLink = document.createElement('a')
logLink.href = 'javascript:logPage.switchTable()'
logLink.style.marginLeft = '10px'; logLink.style.fontSize = '85%'
ul.parentNode.insertBefore(logLink, ul)
//create table
lis = ul.getElementsByTagName('li')
if (window.logMaxRows && lis.length > logMaxRows) isTable = true //surpress creation if too many rows
logPage.switchTable()
addEvent (logTable, 'mouseup', click)
}
this.switchTable = function(){
if (isTable){
ul.style.display = 'block'
if (logTable) logTable.style.display = 'none'
logLink.innerHTML = m.ShowTable
}else{
if (!logTable) createTable()
ul.style.display = 'none'
logTable.style.display = 'block'
logLink.innerHTML = m.ShowList
}
isTable = !isTable
}
function createTable(){
if (!window.logDateIn) logDateIn = /(\d\d:\d\d), (\d\d?) (\S\S\S)\S* (\d\d\d\d)/
if (!window.logDateOut) logDateOut = '$1 $2 $3 $4'
if (!window.logBlDivider) logBlDivider = '<br>'
logPageCSS = '.logcomment div {overflow:auto} .logtime {width:15px}' + (window.logPageCSS?logPageCSS:'')
addCSS(logPageCSS)
if (type = document.URL.match(/&type=([^&]+)/)) type = type[1] //"move", "block", etc. or just empty
if (user = document.URL.match(/&user=([^&]+)/)) user = document.getElementById('user').value
var columns = 5
tbody = '<tr>'
+'<th><img src=' + imcomm + 'thumb/a/af/Relogio07_15.svg/15px-Relogio07_15.svg.png></th>'
+'<th width=10px class=unsortable> </th>'
+'<th><img src=' + imcomm + '/3/3c/A_help_text.gif></th>'
if (user){ //no need for user column
columns--
tbody = '<caption style="text-align:left; padding-left:20%"><img src='+imuser+'>: '
+user.replace(/\+/,' ')+'</caption>'+tbody
}else{
tbody += '<th><img src=' + imuser + '></th>'
}
tbody += '<th><img src=' + imcomm + '8/80/Icons-mini-comment_blue.gif></th></tr>'
//parse entries
for (var i=0; i<lis.length; i++){
try {
parseRow(lis[i].innerHTML)
} catch(e) { //put without parsing
tbody += '<td colspan='+columns+'>' + lis[i].innerHTML + '</td>'
jsMsg('<b>logPage:</b> ' + e.lineNumber + ': ' + e.name + ': ' + e.message + ' ; please <a href="http://en.wikipedia.org/wiki/user_talk:Alex_Smotrov">report</a>')
}
}
//insert table
logTable = document.createElement('div')
logTable.innerHTML = '<table class=wikitable width=100% id=logTable>' + tbody + '</table>'
ul.parentNode.insertBefore(logTable, ul)
ts_makeSortable(document.getElementById('logTable'))
}
function parseRow(row){ //modifies tbody var
var icon='', when, what, who, comment='', ma, word, lastLink=''
var r1, r2, opt = '', extra='', until='', trstyle=''
//extract date, user and userlinks (talk | cotrib | block)
ma = row.match(/([^<]+)(<a.+?>) (\(<a.+?<\/a>\)) /i) //date, user and user links
when = ma[1]
who = ma[2]
row = row.substring(ma[0].length) //get the rest
if (!window.logNoUserLinks) //add talk/contib links
who += ' ' + ma[3].replace(/>(.)(.*?)</g, '>$1<').replace(/> </,'> <') //shorten into (t | c | b)
//possibly get a link at the end
if (ma = row.match(/\((<a[^<]+<\/a>)\) ?$/i)){
lastLink = ma[1]
row = row.substring(0, row.length - ma[0].length)
}
//possibly get a comment at the end
if (ma = row.match(/<span class="?comment"?>\((.*)\)<\/span> ?$/i)){
comment = ma[1]
row = row.substring(0, row.length - ma[0].length)
}
var tooltip = row.replace(/<[^>]+>/g, '').replace(/"/g, '`')
tooltip = tooltip.substring(0, tooltip.length-2) //get rid of last char, visible in IE
// or .replace(/<a[^>]+>/g, '«').replace(/<\/a>/g, '»')
//get the «action» word
//ma = row.match(/^[a-zA-Z]+/) //everything before link or quotes
ma = row.match(/^[^"<«#]+/) //" everything before link or quotes
if (ma) word = ma[0].replace(/\s+$/, '') //trim spaces at the end
what = row //just in case and for default in switch
//workaround: some weird characters at the end of this string
if (row.length < 20) word = 'New user account'
switch (word){
case 'marked':
what = row.match(/<a.+<\/a>/i)[0]
putIcon('thumb/7/73/U2713.svg/10px-U2713.svg.png')
break
case 'deleted':
what = row.match(/<a[^<]+<\/a>/i)[0]
putIcon('thumb/0/0b/Cancel.png/10px-Cancel.png')
break
case 'restored':
what = row.match(/<a[^<]+<\/a>/i)[0]
putIcon('thumb/a/a7/Add.png/10px-Add.png')
if (type == 'delete') trstyle = ' style="background-color:#EEFFEE"'
break
case 'uploaded a new version of':
extra = ' <small>(version)</small>'
case 'uploaded':
what = getShortLink() + extra
putIcon('thumb/c/cc/Icons-mini-image.gif/15px-Icons-mini-image.gif')
break
case 'New user account':
putIcon(imuser)
what = who
who = ''
break
case 'created new account':
case 'created account for':
putIcon(imuser)
ma = row.match(/(<a.+?>) (.+)/i)
what = ma[1] + ma[2].replace(/>(.)(.*?)</g, '>$1<')
if (type == 'newusers') trstyle = ' style="background-color:#FFEEEE"'
break
case 'changed protection level for':
extra = ' <i>('+word.split(' ')[0] + ')</i>'
case 'protected':
what = getLink()
if (ma = comment.match(/\(\S+ (.+? \(UTC\))\)$/)){ //expiration date
until = '<small> / ' + ma[1] + '</small>'
//period = getPeriod(when, until)
comment = comment.replace(ma[0],'')
}
if (ma=comment.match(/\[(edit=[a-z]+)?:?(move=[a-z]+)?\]/)){ //edit/move protection
if (ma[0].indexOf('sysop') != -1) //is sysop protection at all
putIcon('thumb/5/59/Padlock.svg/20px-Padlock.svg.png') //yellow
else
putIcon('thumb/f/fa/Padlock-silver-medium.svg/20px-Padlock-silver-medium.svg.png') //gray
if (ma[1]) opt += (ma[1].indexOf('sysop')!=-1) ? 'sysop' : 'user'
opt += ' :: '
if (ma[2]) opt += (ma[2].indexOf('sysop')!=-1) ? 'sysop' : 'user'
}else if (ma=comment.match(/\[(create=[a-z]+)?\]/)){ //create protection
if (ma[0].indexOf('sysop') != -1){
putIcon('thumb/4/4f/Padlock-purple.svg/20px-Padlock-purple.svg.png')
opt = 'sysop'
}else{
putIcon('thumb/7/70/Padlock-pink.svg/20px-Padlock-pink.svg.png')
opt = 'user'
}
}
comment = opt + extra + ' ' + until + '<br>' + comment.replace(ma[0],'')
break
case 'unprotected':
what = getLink()
putIcon('thumb/5/5e/Padlock-lightolive.svg/15px-Padlock-lightolive.svg.png')
if (type == 'protect') trstyle = ' style="background-color:#EEFFEE"'
break
case 'blocked':
putIcon('thumb/4/4f/Blocked_user.svg/18px-Blocked_user.svg.png')
var length
//get user and user links
ma = row.match(/.*(<a.+?>) \((<a.+?>)\)(.+)$/i)
if (!ma) { what = row.substring(word.length + 1); break }
var blockedLink = ma[1]
var talkContribLinks = ma[2]
var blockedUser = blockedLink.match(/>(.+?)<\/a>/i)[1]
row = ma[3]
//get options
var options = row.match(/\(.*\)/)
options = options ? options[0] : ''
//get period
ma = row.match(/<span .*>(.+)<\/span>/i)
if (ma) length = ma[1]
else length = row.match (/\d+ \S+/)[0] //custom length without span, then it always starts with a number
what = blockedLink+' <small>('+talkContribLinks.replace(/>(.)(.*?)</g, '>$1<')+')</small>'
if (options.indexOf(m.mwNoReg) == -1) opt += m.YesReg //registration is allowed
if (blockedUser.match(/^\d\d?\d?\.\d\d?\d?\.\d\d?\d?\.\d\d?\d?/)) {//IP block
//what += ' style="background-color:white"'
if (blockedUser.match(/\/\d\d?$/)) what = '<b>'+what+'</b>' //range block
if (options.indexOf(m.mwAnonOnly) == -1) opt += m.NotAnonOnly //registered users blocked too
}else{ //user block
// what += ' <small>(<a title="' + m.NewUserLog + '" href="/w/index.php?title=Special:Log&type=newusers&user=' +encodeURIComponent(blockedUser) + '">?</a>)</small>'
if (options.indexOf(m.mwNoAuto) != -1)
opt += ' <span title="' + m.mwNoAuto + '">'+ m.NoAuto + '</span>'
if (options.indexOf(m.mwNoEmail) != -1)
opt += ' <span title="' + m.mwNoEmail + '">' + m.NoEmail + '</span>'
}
opt = '<small title="'+options+'">'+opt+'</small>'
what += logBlDivider + length + ' ' + opt
//' <span style="white-space:nowrap" title="' + options + '">' + '</span>'
//reason = reason.replace(/<span class="comment">\(/,'').replace(/\)<\/span>/,'') //remove ()
break
case 'unblocked':
putIcon('thumb/2/23/Nuvola_apps_edu_languages.svg/20px-Nuvola_apps_edu_languages.svg.png')
if (type == 'block') trstyle = ' style="background-color:#EEFFEE"'
if (ma = row.match(/(<a.+?>) (\(<a.+?<\/a>\))/i)) //date, user and user links; otherwise it's "unlocked #7773"
what = ma[1] + ' <small>' + ma[2].replace(/>(.)(.*?)</g, '>$1<') + '</small>' //shorten into (t | c | b)
break
case 'moved':
ma = row.match(/<a[^<]+<\/a>/ig)
what = ma[0] + '<br>' + ma[1]
icon = '→'
break
// !!! over redirect
//bot status
case 'granted bot status to':
putIcon('thumb/a/a9/Wikiactividade_bot_bronze.png/16px-Wikiactividade_bot_bronze.png')
what = 'bot: ' + getShortLink()
break
case 'removed bot status from':
putIcon('thumb/1/16/Wikiactividade_bot_prata.png/16px-Wikiactividade_bot_prata.png')
what = '<s>bot: ' + getShortLink() + '</s>'
break
//user rights
case 'Для участника':
case 'changed rights for':
what = row.match(/<\/a> (.*) \u200E/i)[1] //devs, why use \u200E ?
what = what.replace(/\([^\)]+\)/g,'()')
ma = what.match(/from (.*) to (.*)/)
if (!ma) {
what = getShortLink() + ': ' + what
putIcon('thumb/b/b3/Kgpg_key3.png/15px-Kgpg_key3.png')
break
}
r1 = ma[1]; r2 = ma[2]
if (r1 == r2)
putIcon('thumb/8/80/Keyring.png/12px-Keyring.png')
else if (r1.length < r2.length){ //added flags
if ((r1 == '()' && r2 == 'rollbacker') || (r1 + ', rollbacker' == r2))
putIcon('thumb/4/40/Wrench.svg/10px-Wrench.svg.png')
else
putIcon('thumb/5/53/Kgpg_key1.png/15px-Kgpg_key1.png') //visible vertical key
}else{ //removed flags
if ((r1 == 'rollbacker' && r2 == '()') || (r1 == 'rollbacker, '+r2) || (r1 == r2+', rollbacker'))
putIcon('thumb/4/40/Wrench.svg/6px-Wrench.svg.png')
else
putIcon('thumb/8/82/Kgpg_key2.png/15px-Kgpg_key2.png') //grey and yellow keys
}
// putIcon('thumb/4/43/Crystal_Clear_app_password.png/17px-Crystal_Clear_app_password.png') //clear keys
what = '<br />' + r1 + ' → ' + r2
what = getShortLink() + ': ' + what
break
case 'renamed':
putIcon('thumb/e/ee/Crystal_Clear_app_kdmconfig.png/15px-Crystal_Clear_app_kdmconfig.png')
what = row
break
default:
icon = '?'
}
if (lastLink) icon = lastLink.replace(/>[^<]+</,'>'+icon+'<') //use icon as undo/protect/etc. link
tbody += '<tr' + trstyle + ' title="' + tooltip + '">'
+ '<td class=logtime title="'+when+'">'
+ when.replace(logDateIn, logDateOut).replace(thisYear,'') + '</td>'
+'<td class=logicon>'+icon+'</td>'
+'<td class=logcontent><div>'+what+'</div></td>'
+(user ? '' : '<td class=loguser>'+who+'</td>')
+'<td class=logcomment><div>'+comment + '</div></td></tr>'
function putIcon(src){
if (src.substring(0,1) != '/') src = imcomm + src
icon = '<img src=' + src + '>'
}
function getProtect(txt){
if (!txt) return ' '
else if (txt.indexOf('sysop') != -1) return 'sysop'
else return 'anon'
}
function getLink(){ //get first link from the row
return row.match(/<a[^<]+<\/a>/i)[0]
}
function shortLink(htm){ //returns a link without namespace in the text
return htm.replace(/>.+?:(.+?)</, '>$1<')
}
function getShortLink(){ //combination of above
return row.match(/<a[^<]+<\/a>/i)[0].replace(/>.+?:(.+?)</, '>$1<')
}
} //parseRow
function shortDate(when){
var ma = when.match(/(\d\d:\d\d), (\d\d?) (\S ...)/)
var when2 = when
if (ma) when2 = ma[1]+'<br/>'+ma[2].replace(/ /,' ')
return '<td class=logtime title="'+when+'"><small>'+when2+'</small></td>'
}
function addCSS(text){ //could use createStyleSheet for IE as well
var s = document.createElement('style')
s.setAttribute('type', 'text/css')
if (s.styleSheet) s.styleSheet.cssText = text //IE
else s.appendChild(document.createTextNode(text))
document.getElementsByTagName('head')[0].appendChild(s)
return s
}
function click(e){ //table onclick event: show additional links
e = e || window.event
var targ = e.srcElement || e.target
if (targ.nodeName == 'DIV') targ = targ.parentNode
if (targ.nodeName != 'TD' || !targ.className.match(/^(loguser|logcontent)/)) return
var link = targ.getElementsByTagName('a')[0]
if (!link) return
if (/&redirect=no$/.test(link.href)) link = targ.getElementsByTagName('a')[1] //when move
if (targ.className.indexOf('info')!=-1){ //remove info
targ.className = targ.className.replace(' info', '')
link.parentNode.removeChild(link.parentNode.lastChild)
return
}
var page = link.title, user, htm = ' ('
if (user=page.match(/:Contributions\/([\d\.]+)/)){ //IP address
user = user[1]
page = 'user:'+user
}else if (user=page.match(/^(User|Участник):(.*)/))
user = user[2]
if (user)
htm += showLink('Special:Logs?user=' + user, 'user', 'Logs by this user') + ' '
htm += showLink('Special:Logs?page=' + page, 'logs', 'Page logs')
if (link.className != 'new' && !user)
htm += ' ' + showLink(page + '?action=history', 'hist', 'Page history')
targ.className += ' info'
link.parentNode.innerHTML += '<span style="white-space:nowrap">' + htm + ')</span>'
}
function showLink(page, name, tip){
return '<a href="' + mw.config.get('wgArticlePath').replace('$1',page) + '" title="' + tip + '">'+name+'</a>'
}
}//obj
if (mw.config.get('wgCanonicalNamespace') == 'Special' && mw.config.get('wgCanonicalSpecialPageName') == 'Log')
addOnloadHook (logPage.onLoad)