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

Adds text to the search field on GHES pages

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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();
	}

})();