Bugzilla See Earlier Comments

By Justin Mason 1 Last update Aug 10, 2006 — Installed 239 times.
// ==UserScript==
// @name          Bugzilla See Earlier Comments
// @namespace     http://jmason.org/software
// @description   Display previous comments on a bug, when viewing the Bugzilla 'create new attachment' page.  Thanks to Jesse Ruderman - http://www.squarefree.com/ - for the nifty iframe-transclusion trick.
// @author        Justin Mason - http://jmason.org/
// @include       http://bugzilla.*/attachment.cgi*
// @include       http://bugs.*/attachment.cgi*
// @include       http://issues.*/attachment.cgi*
// ==/UserScript==

var commentsUrl = null; // the URL, or null for pending/none
var entryForm = null;

// the new HTML that will be added after the textbox 'entryform', to hold
// transcluded comments.  Note that the first DOM child of div
// id='transcluded_comments' will be removed and replaced by the comments,
// once they're loaded.
var newHtmlChunk = 
        "<div style='border: 1px; border-style: dashed; "+
             "padding: 1px 10px 10px 10px;'> "+
        "<h4>Description And Earlier Comments:</h4> "+
        "<div id='transcluded_comments' style='border: 10px; '>"+
        "<span class='transcluded_comments_loading'>"+
             "<em>Loading...</em></span>"+
        "</div></div>";

// do all the hard work after the page is loaded, and from a timer
window.addEventListener("load", init, false);
setInterval(loadComments, 500);


function init() 
{
  // find the 'entryform' textbox; we'll be adding our new nodes after
  // that one.

  var nodes;
  nodes = document.evaluate(
        "//form[contains(@name,'entryform')]",
        document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);

  if (nodes) {
    entryForm = nodes.snapshotItem(0);
  } else {
    //GM_log("failed to find entryform");
    return;
  }

  // extract the good bits from the page's URL
  var url = document.URL;
  var bugidRe = new RegExp("^(.*)attachment.cgi\\?.*?bugid=(\\d+)");
  var m = bugidRe.exec(url);
  if (m != null) {
    var urlBase = m[1];
    var bugId = parseInt(m[2]);
    commentsUrl = urlBase+"show_bug.cgi?id="+bugId;
  }

  // and now, all that stuff is saved for when loadComments() runs
}

function loadComments() 
{
  // have we got the data we need yet?
  if (commentsUrl == null) { return; }
  if (entryForm == null) { return; }

  // add in the HTML framework, complete with "loading..." indicator
  var newspan = document.createElement("span");
  newspan.innerHTML = newHtmlChunk;
  document.body.insertBefore(newspan, entryForm.nextSibling);

  // this (very nifty) trick is largely nicked from Jesse Ruderman's "endless
  // forum pages" script.  cheers ;)
  var iframe = document.createElement("iframe");
  iframe.addEventListener("load", whee, false);
  iframe.width = 1;
  iframe.height = 1;
  iframe.style.display = "none";
  iframe.src = commentsUrl;
  document.body.appendChild(iframe);

  // Don't load this more than once.
  commentsUrl = null;

  function whee() {
    var iframeDoc = iframe.contentDocument;

    var nodes = document.evaluate(
          "//div[contains(@id,'transcluded_comments')]",
          document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
    var appendCursor = nodes.snapshotItem(0);

    // remove the "waiting" indicator
    appendCursor.removeChild(appendCursor.firstChild);

    // we want both the pre id='comment_text_N' *and* the
    // <span class='bz_comment'> nodes.
    nodes = iframeDoc.evaluate(
          "//div/pre[contains(@id,'comment_text_')]|"+
          "//div/span[contains(@class,'bz_comment')]",
          iframeDoc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);

    for(div = null, i = 0; (div = nodes.snapshotItem(i)); i++) {
      appendCursor.appendChild(div);
    }

    // Get rid of the iframe to free memory once it's GCed and so on.
    // Use a setTimeout to work around bug 305471 and to spread out
    // the CPU usage to keep Firefox responsive.
    setTimeout( function() { iframe.parentNode.removeChild(iframe); }, 1500);
  }
}