JIRA Enhanced Navigator

Makes the columns in tables resizable and remembers column width, additionally it allows the hiding of the filter box on the left.

// ==UserScript==
// @name           JIRA Enhanced Navigator
// @version        1.5
// @description    Makes the columns in tables resizable and remembers column width, additionally it allows the hiding of the filter box on the left.
// @namespace      http://home.comcast.net/~mailerdaemon
// @include        */ManageFilters.jspa*
// @include        */IssueNavigator.jspa*
// @include        */QuickSearch.jspa*
// @include        */BulkEditDetailsValidation.jspa*
// @include        */BulkEdit1!default.jspa*
// @include        */UserVotes!default.jspa*
// @include        */UserWatches!default.jspa*
// @include        */ViewUserIssueColumns!default.jspa*
// @include        */ViewSearchRequestIssueColumns!default.jspa*
// ==/UserScript==

//enable resizing on the Column Order page
const resize_on_ordering = false;

//size of the resize handle
const div_width = 3;

if(!String.prototype.trim) String.prototype.trim = function() {return this.replace(/^\s+|\s+$/g,"");}
function process(array, before, after, between){	return (before?before:"")+no_wrap.join((after?after:"") +(between?between:"")+ (before?before:""))+(after?after:""); }

var domain = document.location.host;
var regex = /[\W\s \n\r]+/g;

var ColumnOrderPage = document.location.pathname.search(/\/View(User|SearchRequest)IssueColumns!default\.jspa/) > -1;
if(ColumnOrderPage)
{
	$Z("//table[@id='issuetable']//tr[following-sibling::tr[@class='rowAlternate']]/td/b", function(r,i,p){
		c = document.createElement("input")
		c.type = "checkbox";
		c.title = "Do not wrap long lines."
		
		var temp = r.textContent.replace(regex, "");
		c.id = temp?temp:i + "?";
		
		c.checked = GM_getValue(domain+".column."+c.id+".nowrap", false);
		insertBefore(c, r);
		addEvent(c, "click", function(event){GM_setValue(domain+".column."+this.id+".nowrap", this.checked)});
	});
}
if(resize_on_ordering || !ColumnOrderPage)
{
	function stop(event){event.stopPropagation();}

	function auto(event){
	//	eb.style.marginLeft=eb.style.marginRight="";
		var link = GetParentNodeByTag(event.target, "td");
		var name = domain+".column."+link.id+".width";
		link.removeAttribute("width");
		base.className="resizing";
		var w = link.clientWidth-(pad+pad);
		link.width=(w<min_width)?min_width:w;
		GM_setValue(name, link.width);
		base.removeAttribute("class");
	//	eb.style.marginLeft=eb.style.marginRight="auto";
	}

	function down(event){
		addEvent(document, "mouseup", up);
		addEvent(document, "mousemove", movemouse);
		dobj = this;
		isdrag = true;
		x = event.pageX;
		w = parseInt(GetParentNodeByTag(dobj, "td").width+".0");
	//	GM_log(new Array(x,w));
		return false;
	}

	function up(event){
		if(isdrag)
		{
			isdrag=false;
			removeEvent(document, "mousemove", movemouse);
			removeEvent(document, "mouseup", up);
			var link = GetParentNodeByTag(dobj, "td");
			var name = domain+".column."+link.id+".width";
	//		GM_log(name);
			GM_setValue( name, link.width);
		}
	}

	function movemouse(event){
	  if (isdrag)
	  {
		var p = event.pageX;
		var k = w + p - x;
		GetParentNodeByTag(dobj, "td").width = k<min_width?min_width:k;
	//	GM_log(new Array(w, p, x, k))
		return false;
	  }
	}

	function toggle(set){
		if(header.style.display == "none" && set != false)
		{
			header.style.display = "";
			GM_setValue(domain+".filter."+header.className+".visible", true)
		}
		else if(set != true)
		{
			header.style.display = "none";
			GM_setValue(domain+".filter."+header.className+".visible", false)
		}
	}
	
	var no_wrap = [];

	var res = $Y("//table[@id='issuetable']/tbody/tr[position()=1 and not(@class)]/td");

	var len = res.snapshotLength;
	if(len <= 0) return;
	var first = res.snapshotItem(0);
	var row = GetParentNodeByTag(first, "tr")
	var base = GetParentNodeByTag(row, "table");
	var space=parseInt(base.cellSpacing+".0");
	var pad = parseInt(base.cellPadding+".0");
	var height = (first.height = (base.rows[0].clientHeight - space)) - (pad + pad);// + space + space + pad + pad;
	var eb = GetParentNodeByTag(base, "table", base);
	//eb.style.backgroundColor="transparent";
	eb.removeAttribute("width");
	eb.style.marginLeft="20px;"//eb.style.marginRight="auto";

	var div_center_offset = (pad /*+ Math.floor(div_width / 2)*/ + space);
	var min_width = (ColumnOrderPage?56:div_width - space + 1);
	const etype = "div";

	for (i = 0; link = res.snapshotItem(i); ++i)
	{
		link.style.whiteSpace="nowrap";
		link.style.minWidth=min_width+"px";

		var text = link;
		var u = link.getElementsByTagName("span");
		if(u && u[0])
		{
			text = link.removeChild(u[0]);
			link.title = text.title;
		}
		else
		{//for BulkEdit1
			if(u = getFirstNonTextChild(link))
			{
				text = document.createElement("span");
				text.appendChild(link.removeChild(u));
			}
		}
		
		var temp = text.textContent.replace(regex, "");
		link.id = temp?temp:i + "?";
		
		if(GM_getValue(domain+".column."+link.id+".nowrap", false))
			no_wrap.push($X("//table[@id='issuetable']/tbody/tr[preceding-sibling::tr[position()=1 and not(@class)]]/td["+(i+1)+"]").className.replace("nav ",""));
		
		var width = parseInt(GM_getValue(domain+".column."+link.id+".width", "0"));
	//	GM_log(width);
		if(width == 0 || isNaN(width))
			width = link.clientWidth - (pad + pad);
		if(width < min_width && width >= 0)
			width = min_width;
		
		var burn = document.createElement(etype);
		var divider = document.createElement(etype);
		burn.className="GM_burn";
		
		var t = link.childNodes.length;
		while(t > 0)
		{
			var m = link.removeChild(link.childNodes[--t]);
			if(m.nodeName != "#text")
				burn.appendChild(m);
		}
		if(burn.childNodes.length > 0)
		{
			link.appendChild(divider);
			link.appendChild(burn);
		}
		else
			link.appendChild(divider = burn);
		if(link != text)
			link.appendChild(text);
		divider.title="Click and drag to resize this column";
		divider.className="GM_divider";
	//	addEvent(floater, "mouseup", up);
		addEvent(divider, "mousedown", down);
		addEvent(divider, "click", stop);
		addEvent(divider, "dblclick", auto);
		link.width=Math.abs(width) + (width>=0?"":"%");
	}

	GM_addStyle(process(no_wrap, "#issuetable .", " {white-space:nowrap;} "));
	//GM_log(no_wrap.join(","));
	
	var tx;
	var ty;
	var x;
	var w;
	var dobj;

	GM_addStyle(".GM_divider {background-color:black; cursor:col-resize; height:"+height+"px; opacity:0.125; width:"+div_width+"px;} .GM_burn, .GM_divider {float:right; left:"+div_center_offset+"px; position:relative;}")
	GM_addStyle("table.resizing {table-layout:auto!important; overflow:auto!important;} table.resizing tbody tr td.colHeaderLink *, table.resizing tbody tr td.colHeaderOver * {display:none;}" );
	GM_addStyle("table#issuetable tbody tr td {overflow:hidden!important;} table#issuetable {table-layout:fixed; overflow:hidden; width:0px;}");
	GM_addStyle("table#issuetable tbody tr td:hover {overflow:visible!important;} table#issuetable tbody tr td:hover + td {opacity:0.2;} .faded {opacity:0.1!important;}");
	GM_addStyle("td.colHeaderOver {color:black;} td.colHeaderOver:hover + td + td {opacity:0.4;}");

	var header = $X("//tr[not(boolean(@class))]/td[@class='filterSummaryCell' or @class='filterFormCell' or (not(@class) and div[@class='vcard'])]");

	if(header)
	{
		var div = document.createElement("td");
		div.style.background = "#9DBBDA";
		div.style.verticalAlign = "middle";
		div.style.cursor="pointer";
		text = document.createElement("div");
		text.style.width = "5px";
		div.appendChild(text);
		insertAfter(div, header);
		addEvent( div, "click", toggle );
		if(!header.className)
			if(new_name = document.URL.replace(/.*\/([^!]+)\!default\.jspa.*/, "$1"))
				header.className = "URL-" + new_name;
		toggle(GM_getValue(domain+".filter."+header.className+".visible", true));
		div.title="Click to toggle the visiblity of the filters";
	}

	$Z("//td[contains(@class, 'assignee') and contains(text(), 'Unassigned')]", function(r, i, p){r.className += " faded"}, base);
}

function $X(_xpath, node){return document.evaluate(_xpath, node?node:document, null,	XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotItem(0);}
function $Y(_xpath, node){return document.evaluate(_xpath, node?node:document, null,	XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);}
function $Z(_xpath, func, node, payload){
	var res = document.evaluate(_xpath, node?node:document, null,	XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
	var i, j;
	for (i = j = 0; link = res.snapshotItem(i); ++i)
		j += func(link, i, payload);
	return j;
}
function GetParentNodeByTag(child, tag, bad) {
	tag = tag.toUpperCase();
	while((child = child.parentNode) && child.tagName != tag);
	return child?child:bad;
}
function insertAfter(insert, after){return after.parentNode.insertBefore(insert, after.nextSibling);}
function insertBefore(insert, before){return before.parentNode.insertBefore(insert, before);}

function addEvent( obj, type, fn, capture ) {
 	if ( obj.attachEvent ) {
 		obj["e"+type+fn] = fn;
 		obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
 		obj.attachEvent( "on"+type, obj[type+fn] );
 	} else
 		obj.addEventListener( type, fn, capture?capture:false );
}
function removeEvent( obj, type, fn, capture ) {
 	if ( obj.detachEvent ) {
 		obj.detachEvent( "on"+type, obj[type+fn] );
 		obj[type+fn] = obj["e"+type+fn] = null;
 	} else
 		obj.removeEventListener( type, fn, capture?capture:false );
}
function getFirstNonTextChild(obj){
	if(obj.firstChild.nodeName != "#text") return obj.firstChild;
	return getNextNonTextSibling(obj.firstChild);
}
function getNextNonTextSibling(obj){
	while((obj=obj.nextSibling) && (obj.nodeName == "#text"));
	return obj;
}

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址