您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Makes Links and Files sections of Issues into tables that can be sorted
// ==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")); }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址