User:Splarka/scapmap.js

From mediawiki.org

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);
}