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

Adds text to the search field on GHES pages

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 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();
	}

})();