Greasy Fork is available in English.

Buttons to Run Scripts with Toggle toast and Exclusion List

Add buttons to run custom scripts and handle duplicate test names with toggles for returning to the previous page. Save the last selection for checkboxes, with buttons aligned inline with the Next button. Includes toast auto-close functionality and an exclusion list for certain tests.

// ==UserScript==
// @name           Buttons to Run Scripts with Toggle toast and Exclusion List
// @version        3.8
// @namespace      Violentmonkey Scripts
// @icon           https://i.ibb.co/C8dM5x8/Screenshot.png
// @description    Add buttons to run custom scripts and handle duplicate test names with toggles for returning to the previous page. Save the last selection for checkboxes, with buttons aligned inline with the Next button. Includes toast auto-close functionality and an exclusion list for certain tests.
// @match          *://his.kaauh.org/lab/*
// @author         Hamad AlShegifi
// @grant          none
// ==/UserScript==

    // Add keyboard shortcuts for F7 and F8
    document.addEventListener('keydown', function(event) {
        if (event.key === 'F7') {
            console.log("F7 pressed: Triggering VERIFY1 button click");
            const verify1Button = document.querySelector('#custom-script-buttons button.btn-success');
            if (verify1Button) {
                verify1Button.click();
            } else {
                console.error("VERIFY1 button not found.");
            }
        } else if (event.key === 'F8') {
            console.log("F8 pressed: Triggering VERIFY2 button click");
            const verify2Button = document.querySelector('#custom-script-buttons button.btn-primary');
            if (verify2Button) {
                verify2Button.click();
            } else {
                console.error("VERIFY2 button not found.");
            }
        }
    });



    (function() {
    'use strict';

    // Load Font Awesome if not already loaded
    function loadFontAwesome() {
        const existingLink = document.querySelector('link[href*="font-awesome"]');
        if (!existingLink) {
            const link = document.createElement('link');
            link.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css';
            link.rel = 'stylesheet';
            document.head.appendChild(link);
            console.log('Font Awesome loaded');
        }
    }

    loadFontAwesome();

    // Variables to track the toggle states for buttons
    let verify1Toggle = localStorage.getItem('verify1Toggle') === 'true';
    let verify2Toggle = localStorage.getItem('verify2Toggle') === 'true';
    let verify1Clicked = false;
    let verify2Clicked = false;

    // Exclusion list: Words to skip from checkbox selection
    const excludeWords = ['culture', "gram's stain", 'stain', 'bacterial', 'fungal', 'culture','pcr','Meningitis','MRSA','Mid','stream','Cryptococcus'];

    // Function to check if the current URL starts with the required path
    function isCorrectPage() {
        const currentUrl = window.location.href;
        return currentUrl.startsWith('https://his.kaauh.org/lab/#/lab-orders/edit-lab-order/');
    }

    // Function to create and append buttons with toggles
    function addButtons() {
        if (document.getElementById('custom-script-buttons')) return;

        const nextButton = document.querySelector('button#btnNext');
        if (nextButton) {
            let buttonDiv = document.createElement('div');
            buttonDiv.id = 'custom-script-buttons';
            buttonDiv.style.display = 'inline-block';
            buttonDiv.style.marginLeft = '10px';

            let verify1Button = createButton('VERIFY1', 'btn btn-success btn-sm', () => {
                verify1Clicked = true;
                checkAllVisibleBoxesWithoutDuplicates();
                setTimeout(() => { clickCompleteVerificationButton(); }, 500);
            });

            let verify1Icon = createToggleIcon('verify1Icon', verify1Toggle, handleVerify1IconToggle);

            let verify2Button = createButton('VERIFY2', 'btn btn-primary btn-sm', () => {
                verify2Clicked = true;
                checkAllVisibleBoxesWithoutDuplicates();
                setTimeout(() => { performVerificationProcess(); }, 500);
            });

            let verify2Icon = createToggleIcon('verify2Icon', verify2Toggle, handleVerify2IconToggle);

            let modedByText = document.createElement('span');
            modedByText.textContent = "Moded by: Hamad AlShegifi";
            modedByText.style.fontSize = '12px';
            modedByText.style.fontWeight = 'bold';
            modedByText.style.color = '#ff0000';
            modedByText.style.position = 'relative';
            modedByText.style.left = '0px';
            modedByText.style.top = '0px';
            modedByText.style.border = '1.5px solid #ff0000';
            modedByText.style.borderRadius = '8px';
            modedByText.style.padding = '4px';
            modedByText.style.backgroundColor = 'white';

            buttonDiv.appendChild(verify1Button);
            buttonDiv.appendChild(verify1Icon);
            buttonDiv.appendChild(verify2Button);
            buttonDiv.appendChild(verify2Icon);
            buttonDiv.appendChild(modedByText);

            nextButton.parentNode.insertBefore(buttonDiv, nextButton.nextSibling);
        }
    }

    function createButton(label, className, onClick) {
        let button = document.createElement('button');
        button.type = 'button';
        button.innerHTML = label;
        button.className = className;

        // Define button colors based on class name
        let buttonColors = {
            'btn btn-success btn-sm': '#28a745',  // Green for VERIFY1
            'btn btn-primary btn-sm': '#2594d9'   // Blue for VERIFY2
        };

        // Apply custom button styles with !important to override existing styles
        button.style.cssText = `
            ffont-family: 'Times New Roman', serif;!important ;
            font-size: 13px !important;
            font-weight:  !important;
            color: #ffffff !important;
            background-color: ${buttonColors[className]} !important;
            padding: 8px 16px !important;
            border: none !important;
            border-radius: 5px !important;
            text-shadow: 0px 0px 0px #000000 !important;
            cursor: pointer !important;
            margin-right: 5px !important;
        `;

        button.onclick = onClick;
        return button;
    }

    function createToggleIcon(id, isActive, onClick) {
        let icon = document.createElement('span');
        icon.id = id;
        icon.innerHTML = `<i class="fa fa-arrow-circle-left" aria-hidden="true" style="color: ${isActive ? '#008000' : '#d1cfcf'};"></i>`;
        icon.style.cursor = 'pointer';
        icon.style.marginRight = '10px';
        icon.onclick = onClick;
        icon.title = "Select to go back after verification";
        return icon;
    }

    function handleVerify1IconToggle() {
        verify1Toggle = !verify1Toggle;
        localStorage.setItem('verify1Toggle', verify1Toggle);
        const icon = document.getElementById('verify1Icon').querySelector('i');
        icon.style.color = verify1Toggle ? '#008000' : '#d1cfcf';
    }

    function handleVerify2IconToggle() {
        verify2Toggle = !verify2Toggle;
        localStorage.setItem('verify2Toggle', verify2Toggle);
        const icon = document.getElementById('verify2Icon').querySelector('i');
        icon.style.color = verify2Toggle ? '#008000' : '#d1cfcf';
    }

    // Function to simulate clicking on all visible unchecked checkboxes, ensuring no duplicates
    function checkAllVisibleBoxesWithoutDuplicates() {
        const testDivs = document.querySelectorAll('div[col-id="TestDesc"]');
        let seenTests = new Set();
        testDivs.forEach(testDiv => {
            const testName = testDiv.textContent.trim().toLowerCase();
            // Skip tests that contain any word from the exclusion list
            if (excludeWords.some(word => testName.includes(word.toLowerCase()))) {
                return; // Skip this test
            }

            if (!seenTests.has(testName)) {
                seenTests.add(testName);
                const parentRow = testDiv.closest('.ag-row');
                if (parentRow) {
                    const checkbox = parentRow.querySelector('span.ag-icon-checkbox-unchecked[unselectable="on"]');
                    if (checkbox && isVisible(checkbox)) {
                        const event = new MouseEvent('click', { bubbles: true, cancelable: true, view: window });
                        checkbox.dispatchEvent(event);
                    }
                }
            }
        });
        console.log(`${seenTests.size} unique checkboxes were checked!`);
    }

    function isVisible(element) {
        return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length);
    }

    function clickCompleteVerificationButton() {
        const button = document.querySelector('button.dropdown-item[translateid="test-results.CompleteTechnicalVerification"]');
        if (button) {
            button.click();
            console.log("Complete Primary Verification button clicked!");
            setTimeout(() => { clickVerifyButton(); }, 700);
        } else {
            console.error("Complete Primary Verification button not found! Please ensure you are on the correct page.");
            alert("Error: Unable to find the Complete Primary Verification button.");
        }
    }

    function clickVerifyButton() {
        const verifyButton = document.querySelector('button.btn-success.btn-sm.min-width[translateid="test-verification.Verify"]');
        if (verifyButton) {
            verifyButton.click();
            console.log("Verify button clicked!");
        } else {
            console.error("Verify button not found!");
        }
    }

    function performVerificationProcess() {
        const completeMedicalButton = document.querySelector('button.dropdown-item[translateid="test-results.CompleteMedicalVerification"]');
        if (completeMedicalButton) {
            completeMedicalButton.click();
            console.log("Complete Medical Verification button clicked!");
            setTimeout(() => { clickVerifyButton(); }, 700);
        } else {
            console.log("Complete Medical Verification button not found!");
        }
    }

    // Function to continuously monitor and close toast notifications
function monitorToastNotifications() {
    const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
            const toastContainer = document.querySelector('#toast-container');
            if (toastContainer) {
                const closeButton = toastContainer.querySelector('button.toast-close-button[aria-label="Close"]');

                // التحقق من عنوان URL قبل الإغلاق
                const url = window.location.href;
                if (closeButton && (url.endsWith('/undefined') || url.endsWith('/-1/undefined'))) {
                    console.log("Toast close button detected on the correct page. Attempting to close...");
                    setTimeout(() => {
                        closeButton.click();
                        console.log("Toast notification closed.");
                    }, 300);
                }
            }
        });
    });

    observer.observe(document.body, { childList: true, subtree: true });
    console.log("Toast auto-close observer is active.");
}

// تشغيل المراقبة
monitorToastNotifications();
    // Observe changes to detect when the toast message is removed and go back to the previous page if toggled checkboxes are selected
    const toastObserver = new MutationObserver((mutations) => {
        mutations.forEach(mutation => {
            if (mutation.removedNodes.length) {
                mutation.removedNodes.forEach(node => {
                    if (node.matches && node.matches('.toast-success')) {
                        if (verify1Clicked && verify1Toggle) {
                            window.history.back();
                        } else if (verify2Clicked && verify2Toggle) {
                            window.history.back();
                        }
                        verify1Clicked = false;
                        verify2Clicked = false;
                    }
                });
            }
        });
    });

    toastObserver.observe(document.body, { childList: true, subtree: true });

    const observer = new MutationObserver(() => {
        if (isCorrectPage()) {
            addButtons();
        } else {
            const buttonDiv = document.getElementById('custom-script-buttons');
            if (buttonDiv) {
                buttonDiv.remove();
            }
        }
    });

    observer.observe(document.body, { childList: true, subtree: true });

    window.addEventListener('load', function() {
        console.log("Script loaded, ready to observe URL changes.");
    });

})();