User:Splarka/scapmap.js
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (â-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (â-Shift-R on a Mac)
- Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
- Opera: Press Ctrl-F5.
/* Scap roadmap viewer, version [0.0.7]
Originally from: http://www.mediawiki.org/wiki/User:Splarka/scapmap.js
Notes:
* Loads on, for example: http://www.mediawiki.org/wiki/Special:Code/MediaWiki
** Click [overview] to generate map.
* Text in the "path" input box is stripped from the path line in the summary.
* Clicking a colored box takes you to that relevant line, and a backlink is created in the id column on focus.
* Hovering over a colored box pops up a little info packet box.
*/
var overviewTimeoutObj;
var overviewPopupData = [];
function reviewOverview() {
// check if we're on a page with a useful list of revisions
var path = document.getElementById('path');
var table = getElementsByClassName(document,'table','TablePager');
if(!path || table.length == 0) return;
addPortletLink('p-cactions','javascript:reviewOverviewDisplay();','Overview','ca-defrag','Show a graphical overview of this list.','1');
}
function reviewOverviewDisplay() {
//doublecheck that they're there and we can use them
var table = getElementsByClassName(document,'table','TablePager');
var above = document.forms[0]; //stick above the first form, no IDs on the forms currently!
table = table[0];
var tr = table.getElementsByTagName('tr');
if(tr.length < 2 || document.getElementById('overviewmap')) return
appendCSS(
'#overviewmap {border:1px solid black;margin:.5em;padding:2px;position:relative;margin-right:16em;} '
+ '#overviewmap #overviewpop {padding:3px;border:1px solid black;position:absolute;height:6.5em;width:16em;display:none;'
+ ' background-color:#ffffdd;font-size:80%;line-height:100%;overflow:hidden;white-space:pre;} '
+ '#overviewmap .box-overview {display:block;border:1px solid black;float:left;width:1.5em;height:1.5em;margin:1px;overflow:hidden;} '
+ '#overviewmap .box-overview:target {border-style:dashed !important} #overviewmap .summary {clear:both;} '
+ '.box-status-new {background: #ffffc0 !important;} .box-status-new:hover {background: #dfdfa0 !important;} '
+ '.box-status-fixme {background: #ff9999 !important;} .box-status-fixme:hover {background: #df0000 !important;} '
+ '.box-status-resolved {background: #b0eeb0 !important;} .box-status-resolved:hover {background: #80ff80 !important;} '
+ '.box-status-reverted {background: #bbddee !important;} .box-status-reverted:hover {background: #66bbff !important;} '
+ '.box-status-deferred {background: #dddddd !important;} .box-status-deferred:hover {background: #aaaaaa !important;} '
+ '.box-live-live {border:1px solid #00ff00 !important;} '
+ 'tr:target {font-weight:bold;} .overview-backlink {margin-left:1em;display:none;} tr:target .overview-backlink {margin:1em;display:inline;}'
);
var output = document.createElement('div');
output.setAttribute('id','overviewmap');
addHandler(document,'mousemove',mouseMoveBox);
var vpath = document.getElementById('path').value;
var totals = {};
for(var i=0;i<tr.length;i++) {
var live = false, status = false;
var trc = tr[i].getAttribute('class');
if(!trc) continue
trc = trc.split(' ');
for(var j=0;j<trc.length;j++) {
if(/mw\-codereview\-(not|)live/.test(trc[j])) live = trc[j].substring(14)
if(trc[j].substring(0,21) == 'mw-codereview-status-') status = trc[j].substring(21)
}
var td = tr[i].getElementsByTagName('td');
if(!td) continue
overviewPopupData[i] = {};
var statusname = tdGetByClass(tr[i],'TablePager_col_cr_status',true);
if(!statusname || !status || !live) continue
overviewPopupData[i]['status'] = status;
overviewPopupData[i]['statusname'] = statusname;
var rev = tdGetByClass(tr[i],'TablePager_col_cr_id',true);
if(!rev) rev = tdGetByClass(tr[i],'TablePager_col_cp_rev_id',true)
overviewPopupData[i]['rev'] = rev;
overviewPopupData[i]['notes'] = tdGetByClass(tr[i],'TablePager_col_comments',true);
var path = tdGetByClass(tr[i],'TablePager_col_cr_path',true);
if(path && path.indexOf(vpath) == 0 && path != vpath && vpath != '') path = '\u2026' + path.substring(vpath.length)
overviewPopupData[i]['path'] = path;
overviewPopupData[i]['author'] = tdGetByClass(tr[i],'TablePager_col_cr_author',true);
overviewPopupData[i]['live'] = live;
if(!totals[statusname]) totals[statusname] = 0
if(!totals[live]) totals[live] = 0
totals[statusname]++;
totals[live]++;
tr[i].setAttribute('id','TablePager-row-' + rev);
var revtd = tdGetByClass(tr[i],'TablePager_col_cr_id');
if(!revtd) revtd = tdGetByClass(tr[i],'TablePager_col_cp_rev_id')
if(revtd) {
var top = document.createElement('a');
top.appendChild(document.createTextNode('^'));
top.setAttribute('class','overview-backlink');
top.setAttribute('href','#box-' + i);
revtd.appendChild(top);
}
var box = document.createElement('a');
box.setAttribute('href','#TablePager-row-' + rev);
box.setAttribute('class','box-overview box-status-' + status + ' box-live-' + live);
box.setAttribute('id','box-' + i );
//box.appendChild(document.createTextNode(live));
output.appendChild(box);
}
var summary = document.createElement('div');
summary.setAttribute('class','summary');
var sumtext = [];
for(var i in totals) {
if(typeof i != 'string' || typeof totals[i] != 'number') continue
sumtext.push(i + ': ' + totals[i]);
}
sumtext.sort();
summary.appendChild(document.createTextNode('Total revisions: ' + (tr.length-1) + '. [' + sumtext.join(', ') + ']'));
output.appendChild(summary);
var opop = document.createElement('div');
opop.setAttribute('id','overviewpop');
output.appendChild(opop);
above.style.clear = 'both';
above.parentNode.insertBefore(output,above);
}
if(wgNamespaceNumber == -1 && wgCanonicalSpecialPageName == 'Code') addOnloadHook(reviewOverview)
function tdGetByClass(obj,classy,textonly) {
var td = obj.getElementsByTagName('td');
if(!td) return
for(var i=0;i<td.length;i++) {
if(td[i].getAttribute('class') == classy) {
if(textonly) {
return getInnerText(td[i]);
} else {
return td[i];
}
}
}
return false;
}
function mouseMoveBox(e) {
//document.onmousemove sure is spooky! Lets be super extra paranoid and error check everything.
try {
if(overviewTimeoutObj != null) {
clearTimeout(overviewTimeoutObj);
overviewTimeoutObj = null;
}
var e = window.event || e;
if(!e) return
var target = e.target || e.srcElement;
if(!target) return
if(target.id == 'overviewpop') return
var opop = document.getElementById('overviewpop');
if(!opop) return
if(target.tagName == 'A' && target.className.indexOf('box-overview') == 0) {
if(opop.getAttribute('for') == target.getAttribute('id')) return
overviewTimeoutObj = setTimeout(function() { showOverviewPopupBox(target,opop); }, 400);
} else {
opop.style.display = ''
}
} catch (e) {
return;
}
}
function showOverviewPopupBox(target,opop) {
if(!opop || !target) return
var left = target.offsetLeft + target.offsetWidth -10;
var top = target.offsetTop + target.offsetHeight -10;
while(opop.firstChild) opop.removeChild(opop.firstChild)
var id = parseInt(target.id.replace(/box\-/i,''));
var txt = 'Rev: r' + overviewPopupData[id]['rev'] + '\nStatus: ' + overviewPopupData[id]['statusname'] + ' (' + overviewPopupData[id]['status'] + ')\nNumber of notes: ' + overviewPopupData[id]['notes'] + '\nPath: ' + overviewPopupData[id]['path'] + '\nAuthor: ' + overviewPopupData[id]['author'] + '\nLive: ' + overviewPopupData[id]['live'];
opop.appendChild(document.createTextNode(txt));
opop.style.left = left + 'px';
opop.style.top = top + 'px';
opop.style.display = 'block';
opop.setAttribute('for','box-' + id);
}