Add Text to Search Field in GHES and jump to lines with specific keywords

Adds text to the search field on GHES pages

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name         Add Text to Search Field in GHES and jump to lines with specific keywords
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Adds text to the search field on GHES pages
// @author       chaoscreater
// @match        https://github.asbbank.co.nz/*/*/actions/runs/*/job/*
// @match        https://github.com/*/*/actions/runs/*/job/*
// @grant        none
// ==/UserScript==

(function() {
	'use strict';

	// Function to get the search field (works for both ADO and GHES)
	function getSearchField() {
		// Try GHES GitHub Actions selector first
		let searchField = document.querySelector('.CheckRun-search-input');
		// Fall back to ADO selector
		if (!searchField) {
			searchField = document.querySelector('.find-box input.bolt-textfield-input');
		}
		return searchField;
	}

	// Function to add text to the search field
	function addTextToSearchField() {
		// Try ADO search button
		const searchButton = document.querySelector('button#__bolt-log-search');
		if (searchButton) {
			searchButton.click(); // Click on the search button
			// Wait for a short delay to ensure the search field is fully populated
			setTimeout(() => {
				const searchField = getSearchField();

				if (searchField) {
					// set the input value using the native setter
					const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;
					nativeInputValueSetter.call(searchField, 'to add');

					// Dispatch an input event to simulate user input
					searchField.dispatchEvent(new Event('input', {
						bubbles: true
					}));
				}
			}, 1000); // Adjust delay time as needed
		}
	}

	// Function to append the buttons with CSS styling
	function appendButtons() {
		const button = createButton('Jump to Terraform action start', 'green', Terraform_action_start_handleButtonClick, 'jumpToTerraformActionStart', '990px');
		const button2 = createButton('Jump to Plan line', 'orange', Terraform_plan_line_handleButtonClick, 'jumpToPlanLine', '1213px');
		const button3 = createButton('Jump to No Changes', 'orange', Terraform_plan_no_changes_line_handleButtonClick, 'jumpToNoChanges', '1350px');
		document.body.appendChild(button);
		document.body.appendChild(button2);
		document.body.appendChild(button3);
	}

	// Function to create a button with specified properties
	function createButton(text, color, clickHandler, id, left) {
		const button = document.createElement('button');
		button.textContent = text;
		button.style.position = 'fixed';
		button.style.top = '100px'; // Adjusted top position
		button.style.left = left;
		button.style.zIndex = '9999';
		button.style.backgroundColor = color;
		button.setAttribute('data-button-id', id);
		button.addEventListener('click', clickHandler);
		return button;
	}

	// Function to remove the appended buttons
	function removeButtons() {
		const buttons = document.querySelectorAll('button[data-button-id="jumpToTerraformActionStart"], button[data-button-id="jumpToPlanLine"], button[data-button-id="jumpToNoChanges"]');
		buttons.forEach(button => button.remove());
	}

	// Function to expand the search button
	function expandSearchButton() {
		const searchButton = document.querySelector('button[data-is-focusable="true"][aria-label="Search phrases"]');
		if (searchButton) {
			setTimeout(() => {
				searchButton.click(); // Click on the search button to expand it
			}, 1200);
		}
	}

	// Function to handle button click event
	function Terraform_action_start_handleButtonClick() {
		const searchField = getSearchField();
		if (searchField) {
			searchField.focus(); // Focus on the search field
			const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;
			nativeInputValueSetter.call(searchField, 'Terraform will perform the following actions:');

			// Dispatch an input event to simulate user input
			searchField.dispatchEvent(new Event('input', {
				bubbles: true
			}));
		}
	}

	// Function to handle button click event
	function Terraform_plan_line_handleButtonClick() {
		const searchField = getSearchField();
		if (searchField) {
			searchField.focus(); // Focus on the search field
			const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;
			nativeInputValueSetter.call(searchField, 'to add');

			// Dispatch an input event to simulate user input
			searchField.dispatchEvent(new Event('input', {
				bubbles: true
			}));
		}
	}

	// Function to handle button click event
	function Terraform_plan_no_changes_line_handleButtonClick() {
		const searchField = getSearchField();
		if (searchField) {
			searchField.focus(); // Focus on the search field
			const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;
			nativeInputValueSetter.call(searchField, 'No changes.');

			// Dispatch an input event to simulate user input
			searchField.dispatchEvent(new Event('input', {
				bubbles: true
			}));
		}
	}

	// Function to check if current URL matches the @match patterns
	function isMatchingUrl() {
		const pathname = window.location.pathname;
		// Match pattern: /*/*/actions/runs/*/job/*
		const pattern = /^\/[^/]+\/[^/]+\/actions\/runs\/[^/]+\/job\/[^/]+/;
		return pattern.test(pathname);
	}

	// Initialize: Wait for page to load, then append buttons
	function init() {
		// Check if we're on a matching GitHub Actions job page
		if (isMatchingUrl()) {
			// Wait a bit for the page to fully load
			setTimeout(() => {
				appendButtons();
			}, 1500);
		} else {
			// Remove buttons if they exist but we're not on a matching page
			removeButtons();
		}
	}

	// Monitor URL changes for single-page navigation
	let lastUrl = window.location.href;
	const urlObserver = new MutationObserver(() => {
		const currentUrl = window.location.href;
		if (currentUrl !== lastUrl) {
			lastUrl = currentUrl;
			// Re-run init when URL changes
			init();
		}
	});

	// Start observing URL changes
	urlObserver.observe(document.body, {
		childList: true,
		subtree: true
	});

	// Run initialization when DOM is ready
	if (document.readyState === 'loading') {
		document.addEventListener('DOMContentLoaded', init);
	} else {
		init();
	}

})();