NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Jira Task Navigation Buttons // @namespace http://tampermonkey.net/ // @version 0.1 // @description Add "Previous Task" and "Next Task" buttons to Jira Cloud. // @author JombY // @license Apache-2.0 // @match https://*.atlassian.net/browse/* // @icon https://www.google.com/s2/favicons?domain=jira.com // @grant none // ==/UserScript== /* jshint esversion: 8 */ (function () { 'use strict'; const createNavigationButton = (text, icon) => { const button = document.createElement('button'); button.innerHTML = `<span style="font-size: 16px; margin-right: 5px;">${icon}</span> ${text}`; button.style.position = 'relative'; // Change to 'relative' from 'fixed' button.style.marginBottom = '10px'; // Add margin to separate buttons button.style.zIndex = '1'; // Ensure the buttons are above other elements return button; }; const navigateToTask = (direction) => { const taskNumMatch = window.location.href.match(/([A-Z]+-\d+)/); if (taskNumMatch) { const [, prefix, number] = taskNumMatch[1].match(/([A-Z]+)-(\d+)/); const newTaskNumber = direction === 'previous' ? Number(number) - 1 : Number(number) + 1; if (newTaskNumber > 0) { const newTaskUrl = `${prefix}-${newTaskNumber}`; window.location.href = window.location.href.replace(taskNumMatch[1], newTaskUrl); } } }; const addButtonToNav = () => { const navElement = document.querySelector('#jira-issue-header > div > div > div > nav'); if (navElement && !navElement.classList.contains('task-navigation-buttons-added')) { const previousTaskButton = createNavigationButton('Previous Task', '⟵'); previousTaskButton.addEventListener('click', () => navigateToTask('previous')); navElement.appendChild(previousTaskButton); const nextTaskButton = createNavigationButton('Next Task', '⟶'); nextTaskButton.addEventListener('click', () => navigateToTask('next')); navElement.appendChild(nextTaskButton); navElement.classList.add('task-navigation-buttons-added'); } }; const observerConfig = { childList: true, subtree: true }; const observerCallback = (mutationsList) => { for (const mutation of mutationsList) { if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { addButtonToNav(); } } }; const observer = new MutationObserver(observerCallback); // Wait for the DOM to be fully loaded if (document.readyState === 'complete' || document.readyState === 'interactive') { addButtonToNav(); } else { document.addEventListener('DOMContentLoaded', addButtonToNav); } // Start observing changes in the DOM observer.observe(document.body, observerConfig); })();