Jump to content

User:Alex Smotrov/logpage.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
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="' + 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)