User:Alex Smotrov/logpage.js

From Wikipedia, the free encyclopedia

If a message on your talk page led you here, please be wary of who left it. Code that you insert on this page could contain malicious content capable of compromising your account. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. If this is a .js page, the code will be executed when previewing the page.
Note: After saving, you have to bypass your browser's cache to see the changes. In Internet Explorer and Firefox, hold down the Ctrl key and click the Refresh or Reload button. Opera users have to clear their caches through Tools→Preferences, see the instructions for Opera. Konqueror and Safari users can just click the Reload button.
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&nbsp;$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>&nbsp;</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(/> </,'>&nbsp;<')  //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 += '&nbsp;::&nbsp;'
    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 += '&nbsp;<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 '&nbsp;'
  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(/ /,'&nbsp;')
 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="' + wgArticlePath.replace('$1',page) + '" title="' + tip + '">'+name+'</a>'
}
 
 
 
}//obj
 
 
 
 
if (wgCanonicalNamespace == 'Special'  && wgCanonicalSpecialPageName == 'Log')
 addOnloadHook (logPage.onLoad)