您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Collapse Jira swimlane columns upon click
- // ==UserScript==
- // @name Jira - Toggle columns
- // @description Collapse Jira swimlane columns upon click
- // @namespace jiramod
- // @license MIT
- // @version 1.0
- // @match https://*.atlassian.net/jira/*
- // @grant GM_addStyle
- // @grant GM_setValue
- // @grant GM_getValue
- // ==/UserScript==
- /* jshint esversion: 6 */
- (function () {
- "use strict";
- const collapsedWidth = 40;
- const toggled = {};
- let board = location.pathname;
- let mainArea = "#ghx-content-main";
- let clickArea = "#ghx-pool";
- let header = ".ghx-column-headers .ghx-column";
- let column = ".ghx-columns .ghx-column";
- let issues = ".ghx-wrap-issue";
- let overlay = ".ghx-zone-overlay-table .ghx-zone-overlay-column";
- let ticketCount = ".ghx-qty";
- let swimlaneHeader = ".ghx-swimlane-header";
- let hasSwimlaneHeaders = false;
- // getComputedStyle(document.querySelector('.ghx-column')).padding
- let columnPadding = "10px";
- let columnPaddingNarrow = columnPadding;
- let columnPaddingXtraNarrow = "5px";
- function rafAsync() {
- return new Promise((resolve) => {
- requestAnimationFrame(resolve); // Faster than setTimeout
- });
- }
- function checkElement(element) {
- if (document.querySelector(element) === null) {
- return rafAsync().then(() => checkElement(element));
- } else {
- return Promise.resolve(true);
- }
- }
- checkElement(mainArea).then((element) => {
- startJiraOverrides();
- });
- checkElement(clickArea).then((element) => {
- startClick();
- });
- function startJiraOverrides() {
- // `GH` functions overwrite Jira's own logic with slight modifications
- // Jira: Ignore collapsed columns when detecting narrow widths
- GH.SwimlaneView.updateIssueLayoutAccording2Size = function (e, firstWidth) {
- var widths = e
- .map(function () {
- return AJS.$(this).width();
- })
- .get(),
- uncollapsedWidth = widths.find(function (el) {
- return el > collapsedWidth;
- }),
- i = uncollapsedWidth <= GH.SwimlaneView.NARROW_CARD_WIDTH,
- l = uncollapsedWidth <= GH.SwimlaneView.XTRA_NARROW_CARD_WIDTH;
- e.toggleClass("ghx-narrow-card", i), e.toggleClass("ghx-xtra-narrow-card", l);
- };
- // Jira: Show simple ticket count in header if nonzero
- GH.tpl.rapid.swimlane.renderColumnCount = function (opt_data, opt_ignored) {
- return (
- '<div class="ghx-qty">' +
- (opt_data.column.stats.visible > 0 ? soy.$$escapeHtml(opt_data.column.stats.visible) : "") +
- "</div>"
- );
- };
- // Jira: Add token icons for each issue, to be rendered on collapsed columns
- GH.tpl.rapid.swimlane.renderColumnsHeader = function (opt_data, opt_ignored) {
- var output =
- '<div id="ghx-column-header-group" class="ghx-column-header-group' +
- (opt_data.statistics.fieldConfigured ? " ghx-has-stats" : "") +
- ' ghx-fixed"><ul id="ghx-column-headers" class="ghx-column-headers">';
- var columnList163 = opt_data.columns;
- var columnListLen163 = columnList163.length;
- for (var columnIndex163 = 0; columnIndex163 < columnListLen163; columnIndex163++) {
- var columnData163 = columnList163[columnIndex163];
- output +=
- '<li class="ghx-column' +
- (columnData163.minBusted ? " ghx-busted ghx-busted-min" : "") +
- (columnData163.maxBusted ? " ghx-busted ghx-busted-max" : "") +
- '" data-id="' +
- soy.$$escapeHtml(columnData163.id) +
- '" ><div class="ghx-column-header-flex"><div class="ghx-column-header-flex-1"><h2 data-tooltip="' +
- soy.$$escapeHtml(columnData163.name) +
- '" data-tokens="' +
- " ■".repeat(soy.$$escapeHtml({ column: columnData163 }.column.stats.visible)) +
- '">' +
- soy.$$escapeHtml(columnData163.name) +
- "</h2>" +
- (opt_data.statistics.fieldConfigured
- ? GH.tpl.rapid.swimlane.renderColumnCount({ column: columnData163 })
- : "") +
- "</div>" +
- (opt_data.statistics.fieldConfigured
- ? '<div class="ghx-limits">' +
- GH.tpl.rapid.swimlane.renderColumnConstraints({ column: columnData163 }) +
- "</div>"
- : "") +
- "</div></li>";
- }
- output +=
- "</ul>" +
- (!opt_data.isHorizontalScrollEnabled ? '<div id="ghx-swimlane-header-stalker"></div>' : "") +
- "</div>";
- return output;
- };
- }
- function startClick() {
- function toggle(index) {
- console.log("Toggling column", index);
- if (toggled[index] === undefined) {
- GM_addStyle(`
- body.hidden-${index} ${column}:nth-of-type(${index}),
- body.hidden-${index} ${header}:nth-of-type(${index}),
- body.hidden-${index} ${overlay}:nth-of-type(${index}) {
- width: ${collapsedWidth}px !important;
- }
- body.hidden-${index} ${column}:nth-of-type(${index}) ${issues} {
- display: none;
- }
- body.hidden-${index} ${header}:nth-of-type(${index}) {
- overflow: visible !important;
- }
- body.hidden-${index} ${header}:nth-of-type(${index}) h2 {
- overflow: visible !important;
- transform: rotate(90deg);
- transform-origin: left;
- font-weight: normal;
- margin-left: calc((${collapsedWidth}px / 2) - ${columnPadding});
- }
- body.hidden-${index} ${header}.ghx-narrow-card:nth-of-type(${index}) h2 {
- margin-left: calc((${collapsedWidth}px / 2) - ${columnPaddingNarrow});
- }
- body.hidden-${index} ${header}.ghx-xtra-narrow-card:nth-of-type(${index}) h2 {
- margin-left: calc((${collapsedWidth}px / 2) - ${columnPaddingXtraNarrow});
- }
- body.hidden-${index} ${header}:nth-of-type(${index}) h2::after {
- content: " " attr(data-tokens);
- white-space: pre;
- opacity: 0.2;
- }
- body.hidden-${index} ${header}:nth-of-type(${index}) ${ticketCount} {
- display: none;
- }
- `);
- if (hasSwimlaneHeaders) {
- // Hide column headers until hovered
- GM_addStyle(`
- body.hidden-${index} ${header}:nth-of-type(${index}) h2 {
- font-weight: 600;
- text-shadow:
- -1px -1px 0 #fff,
- -1px 1px 0 #fff,
- 1px -1px 0 #fff,
- 1px 1px 0 #fff,
- 0 0 12px #fff,
- 0 0 12px #fff,
- 0 0 12px #fff,
- 0 0 12px #fff,
- 0 0 12px #fff,
- 0 0 12px #fff,
- 0 0 12px #fff,
- 0 0 12px #fff,
- 0 0 24px #fff,
- 0 0 24px #fff,
- 0 0 24px #fff,
- 0 0 24px #fff,
- 0 0 24px #fff,
- 0 0 24px #fff,
- 0 0 24px #fff,
- 0 0 24px #fff;
- z-index: 100;
- visibility: hidden;
- }
- body.hidden-${index} ${header}:nth-of-type(${index}):hover h2 {
- visibility: visible;
- }
- `);
- }
- }
- toggled[index] = !toggled[index];
- if (toggled[index]) {
- document.body.classList.add(`hidden-${index}`);
- } else {
- document.body.classList.remove(`hidden-${index}`);
- }
- // Refresh in case it has been updated in another window
- globalToggled = JSON.parse(GM_getValue("globalToggled", "{}"));
- globalToggled[board] = toggled;
- GM_setValue("globalToggled", JSON.stringify(globalToggled));
- // Jira: Redraw issues as wide or narrow or extra-narrow
- GH.SwimlaneView.handleResizeEvent();
- }
- // Toggle columns on click
- document.querySelector(clickArea).addEventListener(
- "click",
- (e) => {
- let target = e.target;
- if (target.matches(column) || (target = target.closest(header))) {
- let index = [...target.parentElement.children].indexOf(target) + 1;
- toggle(index);
- }
- },
- true
- );
- // Hide collapsed column headers if swimlane headers are present
- if (document.querySelector(swimlaneHeader)) {
- hasSwimlaneHeaders = true;
- }
- // Collapse previously-toggled columns
- let globalToggled = JSON.parse(GM_getValue("globalToggled", "{}"));
- const loaded = globalToggled[board] === undefined ? {} : globalToggled[board];
- console.log("Previously-toggled columns:", loaded);
- Object.entries(loaded).forEach(([index, collapsed]) => {
- if (collapsed) toggle(index);
- });
- // Style cursor and column headers
- GM_addStyle(`
- ${header}, ${column} { cursor: pointer; }
- ${header} h2 {
- /* Shortened titles look nicer with some space */
- margin-left: 8px;
- margin-right: 8px;
- }
- `);
- }
- })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址