您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
When booking more than ~10 slots, you can't see all bookings under "My bookings" which
当前为
// ==UserScript== // @name Aeronautica.fi edit note button // @namespace Violentmonkey Scripts // @match https://book.aeronautica.fi/customer-bookings* // @grant none // @version 1.0 // @author buq2 / Matti Jukola // @description When booking more than ~10 slots, you can't see all bookings under "My bookings" which // is only place with the edit button for notes. This script adds edit button under // "Customer bookings" page which can display all your bookings. // @source https://github.com/buq2/UserScripts/aeronautica.fi-add-missing-note-edit-button.user.js // @license MIT // @run-at document-idle // ==/UserScript== /** * A utility function for userscripts that detects and handles AJAXed content. * * @example * waitForKeyElements("div.comments", (element) => { * element.innerHTML = "This text inserted by waitForKeyElements()."; * }); * * waitForKeyElements(() => { * const iframe = document.querySelector('iframe'); * if (iframe) { * const iframeDoc = iframe.contentDocument || iframe.contentWindow.document; * return iframeDoc.querySelectorAll("div.comments"); * } * return null; * }, callbackFunc); * * @param {(string|function)} selectorOrFunction - The selector string or function. * @param {function} callback - The callback function; takes a single DOM element as parameter. * If returns true, element will be processed again on subsequent iterations. * @param {boolean} [waitOnce=true] - Whether to stop after the first elements are found. * @param {number} [interval=300] - The time (ms) to wait between iterations. * @param {number} [maxIntervals=-1] - The max number of intervals to run (negative number for unlimited). */ function waitForKeyElements(selectorOrFunction, callback, waitOnce, interval, maxIntervals) { if (typeof waitOnce === "undefined") { waitOnce = true; } if (typeof interval === "undefined") { interval = 300; } if (typeof maxIntervals === "undefined") { maxIntervals = -1; } if (typeof waitForKeyElements.namespace === "undefined") { waitForKeyElements.namespace = Date.now().toString(); } var targetNodes = (typeof selectorOrFunction === "function") ? selectorOrFunction() : document.querySelectorAll(selectorOrFunction); var targetsFound = targetNodes && targetNodes.length > 0; if (targetsFound) { targetNodes.forEach(function (targetNode) { var attrAlreadyFound = `data-userscript-${waitForKeyElements.namespace}-alreadyFound`; var alreadyFound = targetNode.getAttribute(attrAlreadyFound) || false; if (!alreadyFound) { var cancelFound = callback(targetNode); if (cancelFound) { targetsFound = false; } else { targetNode.setAttribute(attrAlreadyFound, true); } } }); } if (maxIntervals !== 0 && !(targetsFound && waitOnce)) { maxIntervals -= 1; setTimeout(function () { waitForKeyElements(selectorOrFunction, callback, waitOnce, interval, maxIntervals); }, interval); } } /** * Extracts the booking ID from the 'unbook' button's href attribute. * * @param {HTMLElement} button - The 'unbook' button element. * @returns {string} - The booking ID extracted from the button's href. */ function getBookingIdFromButton(button) { const unbookLink = button.getAttribute('href'); const match = /booking_id=(\d+)/.exec(unbookLink); return match ? match[1] : null; // Return null if booking ID is not found. } /** * Retrieves all 'Unbook' buttons on the page. * * @returns {HTMLElement[]} - Array of 'Unbook' button elements. */ function getUnbookButtons() { return Array.from(document.querySelectorAll('.btn')).filter(el => el.textContent.trim() === 'Unbook'); } /** * Creates an "Edit Note" button next to the provided 'Unbook' button. * * @param {HTMLElement} unbookButton - The 'Unbook' button to base the new button on. */ function createEditNoteButton(unbookButton) { const bookingId = getBookingIdFromButton(unbookButton); if (!bookingId) { console.error('Booking ID not found.'); return; // Prevent creating button if booking ID is missing. } const parent = unbookButton.parentElement; const editNoteButton = unbookButton.cloneNode(true); editNoteButton.setAttribute('onClick', `popupBookingNote(${bookingId})`); editNoteButton.removeAttribute('href'); // Prevent redirect on click. editNoteButton.textContent = "Note"; // Change text to "Note". parent.appendChild(editNoteButton); // Append the new button. } // Call `waitForKeyElements` to wait for the unbook buttons and create "Edit Note" buttons for them. waitForKeyElements(getUnbookButtons, createEditNoteButton);