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 $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="' + wgArticlePath.replace('$1',page) + '" title="' + tip + '">'+name+'</a>' } }//obj if (wgCanonicalNamespace == 'Special' && wgCanonicalSpecialPageName == 'Log') addOnloadHook (logPage.onLoad)

