// ==UserScript==
// @name Jira Issue Links & Files Tablification
// @namespace http://home.comcast.net/~mailerdaemon
// @description Makes Links and Files sections of Issues into tables that can be sorted
// @include *jira*/browse/*-*
// @version 1.9
// ==/UserScript==
//Test URLS
//http://jira.atlassian.com/browse/JRA-16868
//http://jira.activemath.org/browse/IG-370
//http://jira.atlassian.com/browse/JRA-5959
//http://jira.secondlife.com/browse/WEB-856
//http://jira.atlassian.com/browse/JRA-2509
init();
GM_addStyle([
"table.jilft {}",
"table.jilft tr.row > td:nth-child(n+2) { border-left:1px dotted rgba(0, 0, 0, 0.133);}",
"table.jilft tr.header td { font-size:9px; border-bottom:1px solid rgba(0,0,0,0.25); cursor:pointer; -moz-user-select: none;}",
"table.links_table { width:100%; }",
"table.links_table td { padding-left: 1px; padding-right: 1px; }",
"table.files_table { empty-cells:show; width:auto; }",
"table.files_table td { padding: 1px 3px; }",// text-shadow: 0 0 2px white;
"#attachment_thumbnails li.latest, table.files_table tr.latest { "+CSSmulti("box-shadow", "0 0 8px rgba(0, 255, 0, 0.20)") +"}", //0.025
"#attachment_thumbnails li.latest, table.files_table tr.latest td { background-color:rgba(0, 255, 0, 0.08); text-shadow: 0 0 2px white, 0 0 2px white, 0 0 2px white, 0 0 1px white;}",
"table.files_table tr.stale td { color: rgb(153, 153, 153); }",
"table.files_table tr.stale td:hover { color: rgb(138, 138, 138); }",
"table.links_table tr.header, table.links_table td.key { white-space: nowrap; }",
"#attachment_thumbnails span.blender {display:none;}",
".t_links tbody td { width: auto; }",
"#attachment_thumbnails .attachment-content { height: 256px;}",
"#attachment_thumbnails .attachment-content > td { display:none; }",
"#attachment_thumbnails .attachment-size { top:auto; float:none;}",
"#attachment_thumbnails .attachment-title, #attachment_thumbnails dl { height:auto; }",
"#attachment_thumbnails dt, #attachment_thumbnails dd { line-height:1.1em; font-size:90%; text-align:center; float:none;}",
//copied from atlassian css
"a.user-no-hover.user-avatar, span.user-no-hover.user-avatar { background-position: left center; background-repeat: no-repeat; padding: 2px 0 2px 19px; }",
].join("\n\n"));
//update these!!!
var priorities = ["Showstopper","Critical","Major","Normal","Low","Trivial","Nice to have"];
var statuses = {
"Open":1,
"In Progress":50,
"Reopened":100,
"Fix Pending":150,
"Resolved":200,
"Closed":250,
"Ready for Translation":-1,
"Translation In Progress":-1,
"Translated":-1,
"In QA":-1,
"Passed QA":-1,
"Translation Final":-1,
"Published":-1,
"On Hold":-1,
"Editing In Progress":-1,
"Edited":-1,
"Testing":-1,
"Verified":-1,
"Verified: Fixed":-1,
"Verified: Fix Needed":-1,
"Republished":-1,
large:10000,
}
if($X("//div[contains(concat(' ', @class, ' '), ' content ') and div[contains(concat(' ', @class, ' '), ' module ')]]"))
{//V4.1.1
$Z("//div[contains(concat(' ', @class, ' '), ' content ')]/div[@id='attachmentmodule']", function(module){
$Z(".//ol[@id='file_attachments']", function(r, i){
var table = document.createElement("table");
table.cellPadding = 1;
table.cellSpacing = 0;
table.className = "files_table jilft";
table.setAttribute("order", [-1]);
tbody = document.createElement("tbody");
table.appendChild(tbody);
var tr = document.createElement("tr");
tr.align="center"
tr.style.whiteSpace="nowrap";
tr.style.boarderBottom="1px;"
tr.className="header row";
tr.appendChild(NewHeader(1, "#", "Initial Ordering"));
tr.appendChild(NewHeader(2, "T", "Type"));
tr.appendChild(NewHeader(3, "Filename"));
tr.appendChild(NewHeader(4, "Size"));
tr.appendChild(NewHeader(5, "Date"));
tr.appendChild(NewHeader(6, "Uploader"));
tr.appendChild(NewHeader(7, "Latest"));
tbody.appendChild(tr);
$Z("li[contains(concat(' ', @class, ' '), ' attachment-content ')]", function(li, i){
tbody.appendChild(File(i + 1,
$X(".//div[contains(concat(' ', @class, ' '), ' attachment-thumb ')]/a", li),
$X(".//*[contains(concat(' ', @class, ' '), ' attachment-title ')]/descendant-or-self::a", li),
$X(".//dd[contains(concat(' ', @class, ' '), ' attachment-size ')]", li)
))
}, r);
var click = generic_click(1, FileSort);//FileShifter
click.apply(tr.cells[0]);//we cheat!
replace(r, table);
//r.parentNode.appendChild(table);
for(j = 0; j < tr.cells.length; j++)
tr.cells[j].addEventListener('click', click, false);
}, module);
$Z(".//ol[@id='attachment_thumbnails']", function(ol, i){
$Z("li[contains(concat(' ', @class, ' '), ' attachment-content ')]", function(li, i){
//just provide the missing info
var dl = $X("dl", li);
var thumb = $X(".//div[contains(concat(' ', @class, ' '), ' attachment-thumb ')]/a", li);
var link = $X(".//*[contains(concat(' ', @class, ' '), ' attachment-title ')]/descendant-or-self::a", li);
var size = $X(".//dd[contains(concat(' ', @class, ' '), ' attachment-size ')]", li)
obj = FileObj(i + 1, null, link, size)
FileSetAttributes(li, obj)
if(!(date = $X("dd[contains(concat(' ', @class, ' '), ' attachment-date ')]", dl)))
dl.insertBefore(date = document.createElement("dd"), size).appendChild(obj.date[0]);
dl.insertBefore(creator = document.createElement("dd"), size).appendChild(obj.creator[0]);
// dl.appendChild(latest = document.createElement("dd")).appendChild($X("td[7]/text()", tr));
//GM_log(tr.className);
li.title = link.title;
}, ol);
var table = document.createElement("table");
table.cellPadding =1;
table.cellSpacing = 0;
table.className = "files_table jilft";
ol.setAttribute("order", [-1]);
tbody = document.createElement("tbody");
table.appendChild(tbody);
var tr = document.createElement("tr");
tr.align="center"
tr.style.whiteSpace="nowrap";
tr.style.boarderBottom="1px;"
tr.className="header row";
tr.appendChild(NewHeader(1, "Initial Ordering"));
tr.appendChild(NewHeader(2, "Filename"));
tr.appendChild(NewHeader(3, "Size"));
tr.appendChild(NewHeader(4, "Date"));
tr.appendChild(NewHeader(5, "Uploader"));
tr.appendChild(NewHeader(6, "Latest"));
tbody.appendChild(tr);
var click = generic_list_click(ol, ImageSort);
click.apply(tr.cells[0]);//we cheat!
ol.insertBefore(table, ol.firstChild);
for(j = 0; j < tr.cells.length; j++)
tr.cells[j].addEventListener('click', click, false);
}, module);
});
{//Link Tables
var click = generic_click(2, LinkSort)//, LinkShifter);
$Z("//table[@id = 'outwardLinks_table' or @id = 'inwardLinks_table']", function L1(table){
table.className = (table.className + " links_table jilft").trim();
var top = $X("thead/tr/th", table);
top.colSpan=5;
table.setAttribute("order", [1]);
$Z("tbody/tr", function(tr, i){
var summary = $X("td/div[contains(concat(' ', @class, ' '), ' flooded ')]", tr);
var wrapper = $X(".//div[contains(concat(' ', @class, ' '), ' attribute-wrap ')]", summary);
var priority = $X(".//span[contains(concat(' ', @class, ' '), ' priority ')]", wrapper);
var status = $X(".//span[contains(concat(' ', @class, ' '), ' status ')]", wrapper);
var link = $X(".//a", summary);
tr.className = tr.className.split(" ").concat("row").join(" ");
tr.setAttribute("number", i + 1);
replace(summary, document.createTextNode(i + 1));
tr.appendChild(key = document.createElement("td")).appendChild(link);
tr.appendChild(sum = document.createElement("td")).appendChild(summary);
if(priority)
{
var s = $X(".//img", priority).alt;
var e = priorities.indexOf(s);
if(e == null || e == -1) e = priorities.length;
tr.setAttribute("priority", e + 1);
tr.appendChild(document.createElement("td")).appendChild(priority);
}
else
{
tr.appendChild(document.createElement("td"));
tr.setAttribute("priority", priorities.length + 1);
}
tr.appendChild(document.createElement("td")).appendChild(status);
key.className = "key";
sum.title = link.title && link.title.trim();
var s = link.textContent.trim();
var e = s.lastIndexOf("-") + 1;
tr.setAttribute("key", s.slice(0, e).concat(Array(9 + e - s.length).join("0"), s.slice(e)));
var s = $X(".//img", status).alt;
var e = statuses[s];
if(e == null || e == -1) e = statuses.large;
tr.setAttribute("status", e);
if(!$X("*", wrapper))
remove(wrapper);
else
GM_log("unhandled attribute!")
}, table);
var tr = document.createElement("tr");
tr.align="center"
tr.className="header row";
tr.appendChild(number = NewHeader(1, "#", "Initial Ordering", {status:true}));
tr.appendChild(key = NewHeader(2, "Key", null, {status:true}));
tr.appendChild(summary = NewHeader(3, "Summary", null, {status:true}));
tr.appendChild(priority = NewHeader(4, "P", "Priority", {status:true}));
tr.appendChild(status = NewHeader(5, "S", "Status", {status:true}));
summary.width="100%";
insertAfter(tr, top.parentNode);
for(j = 0; j < tr.cells.length; j++)
tr.cells[j].addEventListener('click', click, false);
});
}
}
else
{//Old V3 to V4.1.0
if((files = $X("//td[@id='file_attachments']")) && (files.textContent.trim() != "None")) {
table = document.createElement("table");
table.cellPadding =1;
table.cellSpacing = 0;
table.className = "files_table jilft";
table.setAttribute("order", [-1]);
tbody = document.createElement("tbody");
table.appendChild(tbody);
var tr = document.createElement("tr");
tr.align="center"
tr.style.whiteSpace="nowrap";
tr.style.boarderBottom="1px;"
tr.className="header row";
tr.appendChild(NewHeader(1, "#", "Initial Ordering"));
tr.appendChild(NewHeader(2, "T", "Type"));
tr.appendChild(NewHeader(3, "Filename"));
tr.appendChild(NewHeader(4, "Size"));
tr.appendChild(NewHeader(5, "Date"));
tr.appendChild(NewHeader(6, "Uploader"));
tr.appendChild(NewHeader(7, "Latest"));
tbody.appendChild(tr);
var items = [];
var nodes = [files];
while(nodes.length > 0)
{
var node = nodes.shift();
var offset = 0;
do
{
if(offset + 7 < node.childNodes.length)
{
while(e = /^[\d]+\.$/.exec(node.childNodes[offset].nodeValue.trim()))
{
tbody.appendChild(File(e[0], node.childNodes[offset + 1], node.childNodes[offset + 3], node.childNodes[offset + 5]));
offset += 7;
}
}
if((node.childNodes.length > ++offset) && node.childNodes[offset].nodeName == "SPAN")
nodes.push(node.childNodes[offset++]);
else
break;
}while(true);
}
var click = generic_click(1, FileSort);//FileShifter
click.apply(tr.cells[0]);//we cheat!
files.innerHTML="";
files.appendChild(table);
for(j = 0; j < tr.cells.length; j++)
tr.cells[j].addEventListener('click', click, false);
}
{//Link Tables
var click = generic_click(2, LinkSort, LinkShifter);
$Z("//table[@id = 'outwardLinks_table' or @id = 'inwardLinks_table']", function L1(r, i, p){
r.className = (r.className + " links_table jilft").trim();
top = $X(".//tr[1]/td[@colspan]", r);
top.colspan=5;
r.setAttribute("order", [1]);
$Z(".//tr[position()>1 and td[@width]]", L2, r);
var tr = document.createElement("tr");
tr.align="center"
tr.className="header row";
tr.appendChild(number = NewHeader(1, "#", "Initial Ordering", {status:true}));
tr.appendChild(key = NewHeader(2, "Key", null, {status:true}));
tr.appendChild(summary = NewHeader(3, "Summary", null, {status:true}));
tr.appendChild(priority = NewHeader(4, "P", "Priority", {status:true}));
tr.appendChild(status = NewHeader(5, "S", "Status", {status:true}));
insertAfter(tr, top.parentNode);
for(j = 0; j < tr.cells.length; j++)
tr.cells[j].addEventListener('click', click, false);
});
}
}
/*
{//Sub-Tasks
//https://jira.secondlife.com/browse/SVC-5165
$Z("//form[@id='stqcform']/table[@id='issuetable']", function(r, i){
r.className = (r.className + " links_table jilft").trim();
r.setAttribute("order", [1]);
$Z("./tbody/tr", function(tr, i){
tr.setAttribute("sequence", Number(tr.cells[0]).textContent))
var sum = $X(".//a", tr.cells[1]);
tr.cells[1].colSpan="2"
var key = /\/browse\/([A-Z]{3,})-([\d]+)/.match(sum.getAttribute("href"))
tr.setAttribute("key", key[1] + key[2].leftPad(7))
tr.setAttribute("summary", sum.textContent)
tr.setAttribute("issuetype", $X(".//img", tr.cells[2])).alt)
tr.setAttribute("status", statuses[$X(".//img", tr.cells[3])).alt])
var assignee = $X("./td[contains(concat(concat(' ', @class), ' '), ' assignee ')]//img", tr);
tr.setAttribute("assignee", )
}, r);
var tr = document.createElement("tr");
tr.align="center"
tr.className="header row";
tr.appendChild(number = NewHeader(1, "#", "Initial Ordering", {status:true}));
tr.appendChild(key = NewHeader(2, "Key", null, {status:true}));
tr.appendChild(summary = NewHeader(3, "Summary", null, {status:true}));
tr.appendChild(priority = NewHeader(4, "P", "Priority", {status:true}));
tr.appendChild(status = NewHeader(5, "S", "Status", {status:true}));
insertAfter(tr, top.parentNode);
for(j = 0; j < tr.cells.length; j++)
tr.cells[j].addEventListener('click', click, false);
});
var click = generic_click(2, TaskSort);
}
//*/
function TaskSort(by, a, b){
by = Math.abs(by) - 1;
var name = ["sequence", "key", "summary", "issuetype", "status", "assignee"][by];
var left, right, ret = 0;
if(name)
{
left = a.getAttribute(name);
right = b.getAttribute(name);
}
switch(by)
{
case 2:
left = a.cells[2].title;
right = b.cells[2].title;
case 1:
ret = (left==right)?0:(left<right)?-1:1;
break;
default:
ret = left - right;
break;
}
return ret;
}
function TaskShifter(row){
return $X("./td[1]/div", row);
}
function LinkSort(by, a, b){
by = Math.abs(by) - 1;
var name = ["number", "key", null, "priority", "status"][by];
var left, right, ret = 0;
if(name)
{
left = a.getAttribute(name);
right = b.getAttribute(name);
}
switch(by)
{
case 2:
left = a.cells[2].title;
right = b.cells[2].title;
case 1:
ret = (left==right)?0:(left<right)?-1:1;
break;
default:
ret = left - right;
break;
}
//log({by:by, name:name, left:left, right:right, ret:ret});
return ret;
}
function LinkShifter(row){
return $X("./td[1]/img", row);
}
function FileShifter(row){
return row.cells[0];
}
function ImageSort(by, a, b){
by = Math.abs(by) - 1;
var name = ["number", "name", "size", "date", "creator", "latest"][by];
var left = a.getAttribute(name), right = b.getAttribute(name);
var ret = 0;
switch(by)
{
case 5:
left = (left=="false");
right = (right=="false");
case 0:
case 2:
case 3:
ret = left - right;
break;
// case 1:
// left = left.toLowerCase();
// right = right.toLowerCase();
default:
ret = (left==right)?0:(left<right)?-1:1;
break;
}
// log({by:by, name:name, left:left, right:right});
return ret;
}
function FileSort(by, a, b){
by = Math.abs(by) - 1;
var name = ["number", "type", "name", "size", "date", "creator", "latest"][by];
var left = a.getAttribute(name), right = b.getAttribute(name);
var ret = 0;
switch(by)
{
case 0:
case 3:
case 4:
ret = left - right;
break;
case 6:
left = (left=="false");
right = (right=="false");
default:
ret = (left==right)?0:(left<right)?-1:1;
break;
}
// log({by:by, name:name, left:left, right:right});
return ret;
}
function NewHeader(num, text, name, obj){
td = document.createElement("td")
td.appendChild(document.createTextNode(text));
td.title = "Sort by " + (name?name:text);
td.setAttribute("type", num);
if(obj)
for(var a in obj)
td.setAttribute(a, obj[a]);
return td;
}
function FileObj(num, icon, link, size)
{
var m = /^(?:(.+?) - |)(?:(Latest) |)(([^-]+)|([\d]{4})-([\d]{2})-([\d]{2}) ([\d]{2}):([\d]{2})) - ([^-]+)$/.exec(link.title);
var latest = m[2] != null;
var date = m[3];
var creator = m[10];
var nice_date = (m[4] && JiraTimeStringToDate(m[4])) || (m[5] && new Date(m[5],m[6],m[7],m[8],m[9]))
var name = m[1] || link.textContent.trim()
m = /([\d]+(?:\.[\d]+)?) ([kTGM]B)/.exec(size.textContent);
var bytes = parseFloat(m[1]);
switch(m[2])
{
case "TB":
bytes *= 1024;
case "GB":
bytes *= 1024;
case "MB":
bytes *= 1024;
case "kB":
bytes *= 1024;
break;
}
//GM_log([num,icon,link,size,m[3],m[2]].join(", "));
var crl = $X("//a[text()=\""+creator+"\" and @style]") || $X("//a[text()=\""+creator+"\"]");
var cre = document.createElement("a")
cre.appendChild(document.createTextNode(creator));
//*
if(crl)
{
cre.href = crl.getAttribute("href");
//cre.className = crl.className;
cre.className = (" "+crl.className+" ").replace(" user-hover "," user-no-hover ").trim();//hover doesn't work!
if(crl.style.cssText)
cre.style.cssText = crl.style.cssText;
}
//*/
//unsafeWindow.console.log(crl)
//unsafeWindow.console.log(cre)
var simple_size = size.cloneNode(false);
simple_size.appendChild(document.createTextNode(m[0]));
obj = {
number: [document.createTextNode(num), parseInt(num)],
name:[link.cloneNode(true), name.toLowerCase()],
size:[simple_size, bytes],
date:[document.createTextNode(date), (new Date()) - nice_date],
creator:[cre, creator.toLowerCase()],
latest:[document.createTextNode(latest?"Latest":" "), latest],
}
if(icon)
obj.type = [icon.cloneNode(true), $X("./img",icon).alt];
return obj;
}
function FileSetAttributes(file, obj)
{
for(var a in obj)
file.setAttribute(a, obj[a][1]);
if(typeof(obj.latest) !== "undefined")
file.className = (file.className + (obj.latest[1]?" latest":" stale")).trim();
}
function File(num, icon, link, size){
obj = FileObj(num, icon, link, size);
tr =document.createElement("tr");
tr.className="row";
[obj.number, obj.type, obj.name, obj.size, obj.date, obj.creator, obj.latest].forEach(function (i){
tr.appendChild(td = document.createElement("td"));
td.appendChild(i[0]);
})
FileSetAttributes(tr, obj);
return tr;
}
function generic_list_click(ol, sorter){
return function (event) {
var type = parseInt(this.getAttribute("type"));
var a_type = Math.abs(type);
var order = ol.getAttribute("order");
if(order == "" || order == null)
order = [1];
else
order = order.split(",").map(function(f){return parseInt(f);});
var k;
// GM_log("------------------------------------------------");
if(Math.abs(order[0]) == a_type)
order[0] = -order[0];
else if(type == 1)
order = [1];//numbers are unique a good opertunity to clear the list.
else
(order = order.filter( function(r){return (Math.abs(r) != a_type);})).unshift(type);
ol.setAttribute("order", order.join(","));
//we cheated <.<
var rows = [];
$Z("li", function(r,i){ rows[i]=r; }, ol);
rows.sort(function(a, b){
var i = 0, j = 0, neg = (order[0] < 0);
//we don't bounds check this because every entry is unique.
//if we overflow order than there is something SERIOUSLY wrong with the data.
while(!(j = sorter(order[i], a, b)))
{
if(order[i] == null)
break;
neg ^= (order[++i] < 0);
}
return neg ? -j : j;
});
for(k = 0; k < rows.length; ++k)
ol.appendChild(remove(rows[k]));
// if(n = $X("li["+(k+2)+"]", ol))
// if(rows[k].getAttribute("number") != n.getAttribute("number"))
// insertAfter(rows[k], n);
//[2,4,1,3] -> [1,2,3,4]
//if(a != b)
/*
log({rows:rows.map(function(f){return f.getAttribute("number");}), order:order,
"order-names":order.map(function(by){return tbody.rows[RS-1].cells[Math.abs(by) - 1].textContent;})});
//*/
delete rows;
}
}
function generic_click(RS, sorter, deshifter){
return function (event) {
var type = parseInt(this.getAttribute("type"));
var a_type = Math.abs(type);
var table = $X(".//ancestor::table[1]", this);
var tbody = $X("tbody", table);
var order = table.getAttribute("order");
if(order == "" || order == null)
order = [1];
else
order = order.split(",").map(function(f){return parseInt(f);});
var k;
// GM_log("------------------------------------------------");
if(Math.abs(order[0]) == a_type)
order[0] = -order[0];
else if(type == 1)
order = [1];//numbers are unique a good opertunity to clear the list.
else
(order = order.filter( function(r){return (Math.abs(r) != a_type);})).unshift(type);
table.setAttribute("order", order.join(","));
//we cheated <.<
var rows = new Array(table.rows.length - RS);
for(k = 0; k < rows.length; ++k)
rows[k] = table.rows[k + RS];
rows.sort(function(a, b){
var i = 0, j = 0, neg = (order[0] < 0);
//we don't bounds check this because every entry is unique.
//if we overflow order than there is something SERIOUSLY wrong with the data.
while(!(j = sorter(order[i], a, b)))
{
if(order[i] == null)
break;
neg ^= (order[++i] < 0);
}
return neg ? -j : j;
});
if(deshifter)
{
//keep the numbers in place
if(rows[0] != table.rows[RS])
swap(deshifter(rows[0]), deshifter(table.rows[RS]), "n[0]<->o[0]");
if(k = (rows.length - 1))
{
if(rows[0] == table.rows[k+RS]) //new[0] == old[last]
{
if(rows[k] != table.rows[RS])
swap(deshifter(rows[k]), deshifter(table.rows[RS]), "n[k]<->o[0]");
}
else
{
if(rows[k] != table.rows[k+RS])
swap(deshifter(rows[k]), deshifter(table.rows[k+RS]), "n[k]<->o[k]");
}
}
}
for(k = 0; k < rows.length; ++k)
if(rows[k] != table.rows[k+1])
insertAfter(rows[k], table.rows[k+1]);
/*
log({rows:rows.map(function(f){return f.getAttribute("number");}), order:order,
"order-names":order.map(function(by){return tbody.rows[RS-1].cells[Math.abs(by) - 1].textContent;})});
//*/
delete rows;
}
}
function CSSmulti(name, value){
var m = name+": "+value+"; ";
return ["-moz-", "-webkit-", "-ie-", ""].map(function(f){return f + m;}).join("");
}
function L2(r, i, p){
var summary = r.cells[1];
var key = document.createElement("td");
var priority = r.cells[2];
var status = r.cells[3];
insertBefore(key, summary);
r.className = r.className.split(" ").concat("row").join(" ");
r.setAttribute("number", i + 1);
var link = $X(".//font/a", summary);
var font = link.parentNode.cloneNode(false);
font.appendChild(link);
key.appendChild(font);
key.className = "key"
summary.title = link.title && link.title.trim();
var s = link.textContent.trim();
var e = s.lastIndexOf("-") + 1;
r.setAttribute("key", s.slice(0, e).concat(Array(9 + e - s.length).join("0"), s.slice(e)));
var s = $X(".//img", r.cells[3]).title.split(" - ", 1)[0];
var e = priorities.indexOf(s);
if(e == null || e == -1) e = priorities.length;
r.setAttribute("priority", e + 1);
var s = $X(".//img", r.cells[4]).title.split(" - ", 1)[0];
var e = statuses[s];
if(e == null || e == -1) e = statuses.large;
r.setAttribute("status", e);
}
function log()
{
var arg;
switch(arguments.length)
{
case 1:
arg = arguments[0];
break;
case 0:
arg = null;
break;
default:
arg = arguments;
break;
}
var f = JSON.stringify(arg);
if(typeof(unsafeWindow.console) != "undefined" && typeof(unsafeWindow.console.log) != "undefined")
unsafeWindow.console.log(f);
else
GM_log(f);
return arg;
}
//*/
function $X(_xpath, node){//to search in a frame, you must traverse it's .contentDocument attribute.
var doc = (node)?(node.ownerDocument || node):(node = document);
return doc.evaluate(_xpath, node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotItem(0);
}
function $Y(_xpath, node){
var doc = (node)?(node.ownerDocument || node):(node = document);
return doc.evaluate(_xpath, node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
}
function $Z(_xpath, func, node){
var doc = (node)?(node.ownerDocument || node):(node = document);
var res = doc.evaluate(_xpath, node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
var args = Array.prototype.slice.call(arguments, 3);
var i = 0;
for (; i < res.snapshotLength; ++i)
func.apply(func, [res.snapshotItem(i), i].concat(args));
return i;
}
function insertAfter(insert, after){return after.parentNode.insertBefore(insert, after.nextSibling);}
function insertBefore(insert, before){return before.parentNode.insertBefore(insert, before);}
function remove(r){return r.parentNode.removeChild(r);}
function replace(old, New){return old.parentNode.replaceChild(New,old);}
function swap(a, b, comment){
if(a != b)
{
var c = a.nextSibling;
var ap = a.parentNode;
var bp = b.parentNode;
bp.insertBefore(ap.removeChild(a), b);
ap.insertBefore(bp.removeChild(b), c);
// GM_log([comment, a.src?a.src:a, b.src?b.src:b].join("\n"));
}
}
function findParent(node, parent){
return $X(".//ancestor::"+parent+"[1]", node);
}
function init(){
if(typeof(String.prototype.trim) == "undefined")
String.prototype.trim = function() {return this.replace(/^\s+|\s+$/g, "");}
if(typeof(String.prototype.leftPad) == "undefined")
String.prototype.leftPad = function (len, text) { return new Array(len - this.length + 1).join(text || '0') + this; }
}
function JiraTimeStringToDate(str){
return new Date(str.replace(/^(\d{2})\/([A-Z][a-z]{2})\/(\d{2})/, "$2 $1 20$3"));
}