您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add copy ID CTA to easily copy Jira ticket IDs and make copy buttons permanently visible
// ==UserScript== // @name Jira Copy Ticket ID // @namespace urn://https://www.georgegillams.co.uk/api/greasemonkey/jira_copy_id // @version 0.0.1 // @description Add copy ID CTA to easily copy Jira ticket IDs and make copy buttons permanently visible // @author You // @include *atlassian.net/browse* // @exclude none // @icon https://www.google.com/s2/favicons?sz=64&domain=atlassian.net // @grant none // @license MIT // ==/UserScript== function extractTicketId() { // Try to get ticket ID from URL first const urlMatch = window.location.pathname.match(/\/browse\/([A-Z]+-\d+)/); if (urlMatch) { return urlMatch[1]; } // Fallback: try to get from the breadcrumb link const breadcrumbLink = document.querySelector( '[data-testid="issue.views.issue-base.foundation.breadcrumbs.current-issue.item"]', ); if (breadcrumbLink) { const hrefMatch = breadcrumbLink.href.match(/\/browse\/([A-Z]+-\d+)/); if (hrefMatch) { return hrefMatch[1]; } // Try getting from text content const textContent = breadcrumbLink.textContent.trim(); if (/^[A-Z]+-\d+$/.test(textContent)) { return textContent; } } return null; } function makeCopyButtonsVisible() { // Find the copy link button wrapper and make it always visible const copyButtonWrapper = document.querySelector( '[data-testid="issue.common.component.permalink-button.button.copy-link-button-wrapper"]', ); if (copyButtonWrapper) { // Remove any hover-only styles by adding permanent visibility copyButtonWrapper.style.opacity = '1'; copyButtonWrapper.style.visibility = 'visible'; copyButtonWrapper.style.transform = 'none'; // Find any child elements that might be hidden and make them visible const hiddenElements = copyButtonWrapper.querySelectorAll('*'); hiddenElements.forEach((el) => { if (el.style.opacity === '0' || el.style.visibility === 'hidden') { el.style.opacity = '1'; el.style.visibility = 'visible'; } // Also remove any transform styles that might hide elements if (el.style.transform && el.style.transform.includes('translate')) { el.style.transform = 'none'; } }); } } function processJiraPage() { // First, make existing copy buttons visible makeCopyButtonsVisible(); const ticketId = extractTicketId(); if (!ticketId) { console.log('Could not find ticket ID, retrying in 1 second...'); setTimeout(processJiraPage, 1000); return; } console.log('Found ticket ID:', ticketId); // Find the copy link button wrapper const copyButtonWrapper = document.querySelector( '[data-testid="issue.common.component.permalink-button.button.copy-link-button-wrapper"]', ); if (!copyButtonWrapper) { console.log('Copy button wrapper not found, retrying in 1 second...'); setTimeout(processJiraPage, 1000); return; } // Check if we already added our button if (copyButtonWrapper.querySelector('.jira-copy-id-button')) { return; } // Create and add the copy ID button const copyIdButton = document.createElement('button'); copyIdButton.textContent = 'Copy ID'; copyIdButton.className = 'jira-copy-id-button'; copyIdButton.style.cssText = ` margin-left: 8px; padding: 4px 8px; background-color: #0052cc; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px; transform: translateY(-1px); &:focus { background-color: #0747a6; } &:hover { background-color: #0747a6; } &:active { background-color: #0052cc; } `; // Add click handler copyIdButton.addEventListener('click', async function (e) { e.preventDefault(); e.stopPropagation(); try { await navigator.clipboard.writeText(ticketId); const originalText = this.textContent; this.textContent = 'Copied!'; this.style.backgroundColor = '#00875a'; setTimeout(() => { this.textContent = originalText; this.style.backgroundColor = '#0052cc'; }, 1500); } catch (err) { console.error('Failed to copy: ', err); // Fallback for older browsers const textArea = document.createElement('textarea'); textArea.value = ticketId; document.body.appendChild(textArea); textArea.select(); document.execCommand('copy'); document.body.removeChild(textArea); const originalText = this.textContent; this.textContent = 'Copied!'; this.style.backgroundColor = '#00875a'; setTimeout(() => { this.textContent = originalText; this.style.backgroundColor = '#0052cc'; }, 1500); } }); // Append the button to the wrapper copyButtonWrapper.appendChild(copyIdButton); } function checkAndAddCopyButton() { const copyButton = document.querySelector('.jira-copy-id-button'); if (copyButton) { return; } processJiraPage(); } function doWork() { // Wait for page to load, then process the Jira page if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', checkAndAddCopyButton); } else { // Document already loaded checkAndAddCopyButton(); } // Also watch for navigation changes in single-page applications let lastUrl = location.href; new MutationObserver(() => { const url = location.href; if (url !== lastUrl) { lastUrl = url; setTimeout(checkAndAddCopyButton, 500); // Small delay for page to update } }).observe(document, { subtree: true, childList: true }); } doWork(); setInterval(checkAndAddCopyButton, 1000);
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址