BugzillaKeyboardNavigation

By Jean-Philippe Daigle Last update Mar 9, 2009 — Installed 134 times.

There are 2 previous versions of this script.

// JPDaigle (jpdaigle@gmail.com)
// version 0.3 (2009-03-09)

// ==UserScript==
// @name          BugzillaKeyboardNavigation
// @namespace     tag:jpdaigle@gmail.com,2009-02-12:GreasemonkeyScripts
// @description   Add navigation to the comment thread in Bugzilla (J/K/N/L/P keystrokes).
// @include       http://*/show_bug.cgi?id=*
// @include       http://*/process_bug.cgi*
// ==/UserScript==

// Pretty much my first greasemonkey script so I'm a JS newbie.

document.addEventListener("keydown", handleKeyPress, true);

function handleKeyPress(event) {

	// Abort if we're handling a form keypress or something. We just want the page itself.
	if (event.originalTarget.tagName != "HTML")
		return;
		
	// Abort if a modifier key is held. (Thanks to seth@slackorama.com for bug report)
	if (event.ctrlKey || event.metaKey || event.altKey)
		return;
	
	var code = event.keyCode;
	// 74 = j
	// 75 = k
	// 76 = l
	// 78 = n
	// 80 = p
	switch(event.keyCode) {
		case 74:
		scrollNextTx();		
		break;

		case 75:
		scrollPrevTx();
		break;

		case 76:
		var lastResultsLink = getBugLink("//a[contains(text(),'last search results')]");
		if (lastResultsLink)
			window.location = lastResultsLink;
		break;
			
		case 78:
		var nextlink = getBugLink("//a[text()='Next']");
		if (nextlink)
			window.location = nextlink;
		break;

		case 80:
		var nextlink = getBugLink("//a[text()='Prev']");
		if (nextlink)
			window.location = nextlink;
		break;
	}
}

// get href of first match
function getBugLink(query) {
	var allNext = document.evaluate(query, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
	if (allNext.snapshotLength > 0) {
		return allNext.snapshotItem(0).href;
	}
}

function getCurVisibleTx() {
	var allTx, countTx, curTx, prevTx, nextTx;
	allTx = document.evaluate( "//span[@class='bz_comment'] | //a[@name='c0']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
	countTx = allTx.snapshotLength;
	var cur_ypos = get_cur_ypos();

	var i, tx_ypos;
	for (i = 0; i < countTx; i++) {
		curTx = allTx.snapshotItem(i);
		tx_ypos = find_ypos(curTx);
		if (tx_ypos >= cur_ypos)
			break;
	}
	
	if (curTx && i == 0 && tx_ypos > (get_cur_ypos() + window.innerHeight)) {
		// special case: the first comment is below the screen
		// so we scroll to that
		return [prevTx, curTx, curTx];
	}
	
	if (i < countTx-1) {
		nextTx = allTx.snapshotItem(i+1);
	}
	if (i > 0) {
		prevTx = allTx.snapshotItem(i-1);
	}
	
	return [prevTx, curTx, nextTx];
}

function scrollNextTx() {
	var selectTx = getCurVisibleTx();
	if (selectTx[2]) {
		window.scroll(0, find_ypos(selectTx[2]));
	}
}

function scrollPrevTx() {
	var selectTx = getCurVisibleTx();
	if (selectTx[0]) {
		window.scroll(0, find_ypos(selectTx[0]));
	}
}

// Find Y position of an object
function find_ypos(obj) {
	var curtop = 0;
	do {
		curtop += obj.offsetTop;
	} while (obj = obj.offsetParent);
	return curtop;
}

// Find Y position of the top of the display page
function get_cur_ypos() {
	return window.pageYOffset;
}