Adds vibrant row hover effect, conditional status cell styling for test and sample status, static red background for emergency rows, and cleans up styles for specific elements.
Από την
// ==UserScript==
// @name Enhanced AG Grid Functionality with Clean Styles
// @version 3.8
// @description Adds vibrant row hover effect, conditional status cell styling for test and sample status, static red background for emergency rows, and cleans up styles for specific elements.
// @match *://his.kaauh.org/lab/*
// @author Hamad AlShegifi
// @grant GM_addStyle
// @namespace http://tampermonkey.net/
// ==/UserScript==
(function () {
'use strict';
// Inject CSS for hover effect, status cell styling, and emergency highlighting
GM_addStyle(`
.ag-row {
transition: background-color 0.3s ease;
}
.vibrant-hover {
/* Background color and text color are now applied to cells within the hovered row */
}
.ag-row.vibrant-hover .ag-cell {
background-color: #87dced !important; /* Light blue color */
color: black !important; /* Black text color */
font-weight: bold !important; /* Bold font */
}
.ag-cell[col-id="testStatus"].status-verified-level2,
.ag-cell[col-id="testStatus"].status-verified-level1 {
background-color: #90EE90 !important; /* Light green color */
}
.ag-cell[col-id="testStatus"].status-ordered {
background-color: #FFFFE0 !important; /* Light yellow color */
}
.ag-cell[col-id="testStatus"].status-resulted {
background-color: #FFA500 !important; /* Orange color */
color: black !important; /* Ensure text is readable on orange */
}
.ag-cell[col-id="testStatus"].status-cancelled {
background-color: #000000 !important; /* Brown color */
color: white !important; /* White text for contrast */
}
.emergency-row {
background-color: #ffe0e0 !important; /* Light red */
}
.ag-cell[col-id="sampleStatus"].status-received {
background-color: #90EE90 !important; /* Light green color for Received sample status */
}
`);
// Clean styles for specific links and spans
function applyCleanStyles() {
const anchor = document.querySelector('li > a[href="#/lab-orders/doctor-request"]');
if (anchor) {
anchor.style.setProperty('white-space', 'nowrap', 'important');
anchor.style.setProperty('font-size', '13px', 'important');
anchor.style.setProperty('overflow', 'visible', 'important');
anchor.style.setProperty('text-overflow', 'unset', 'important');
const spans = anchor.querySelectorAll('span');
spans.forEach(span => {
span.style.setProperty('display', 'inline', 'important');
span.style.setProperty('font-size', '13px', 'important');
span.style.setProperty('white-space', 'nowrap', 'important');
});
}
const simplifySpan = (selector) => {
const span = document.querySelector(selector);
if (span) {
span.style.setProperty('display', 'inline', 'important');
span.style.setProperty('font-size', '20px', 'important');
span.style.setProperty('white-space', 'nowrap', 'important');
span.style.setProperty('overflow', 'visible', 'important');
span.style.setProperty('text-overflow', 'unset', 'important');
span.textContent = span.textContent.replace(/\s+/g, ''); // Optional cleanup
}
};
simplifySpan('span.to-do');
simplifySpan('span.pending-orders');
}
// Debounce for applying clean styles
function debounce(func, wait) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}
const debouncedStyleUpdater = debounce(applyCleanStyles, 300);
const observer = new MutationObserver(debouncedStyleUpdater);
observer.observe(document.body, { childList: true, subtree: true });
// Apply hover effects
const targetColumnIdsForHover = [
"orderNo", "testId", "testDescription", "clusterMrn",
"hospitalMrn", "patientName", "dob", "nationalIqamaId",
"department", "clinic", "doctor", "analyzer",
"orderDateAndTime", "lastUpdatedDate", "sampleStatus",
"referenceLab", "accessionNo", "barcode", "sequenceNo",
"primaryPatientId", "referenceLabDesc", "testStatus",
"orderLastModifiedOnEpoch", "orderCreatedOnEpoch", "equipmentName", "doctorName", "localMrn",
"dateOfBirth", "idNumber"
];
function applyHoverEffect() {
document.querySelectorAll('.ag-cell').forEach(cell => {
const colId = cell.getAttribute('col-id');
if (colId && targetColumnIdsForHover.includes(colId)) {
const row = cell.closest('.ag-row'); // Find the parent row
if (row) {
// Add hover effect to the entire row on mouseenter
cell.addEventListener('mouseenter', () => {
row.classList.add('vibrant-hover'); // Add hover effect to the row
});
// Remove hover effect on mouseleave
cell.addEventListener('mouseleave', () => {
row.classList.remove('vibrant-hover'); // Remove hover effect from the row
});
}
}
});
}
// Apply conditional background color for test and sample statuses
function applyStatusCellStyle() {
document.querySelectorAll('.ag-cell[col-id="testStatus"]').forEach(cell => {
const statusValue = cell.textContent.trim();
cell.classList.remove('status-verified-level2', 'status-verified-level1', 'status-ordered', 'status-resulted', 'status-cancelled'); // Remove previous styles
if (statusValue === "VerifiedLevel2" || statusValue === "VerifiedLevel1") {
cell.classList.add('status-verified-level2');
} else if (statusValue === "Ordered") {
cell.classList.add('status-ordered');
} else if (statusValue === "Resulted") {
cell.classList.add('status-resulted');
} else if (statusValue === "Cancelled") {
cell.classList.add('status-cancelled'); // Apply brown color for Cancelled
}
});
// Apply style for Sample Status = Received
document.querySelectorAll('.ag-cell[col-id="sampleStatus"]').forEach(cell => {
if (cell.textContent.trim() === "Received") {
cell.classList.add('status-received');
} else {
cell.classList.remove('status-received'); // Ensure the class is removed if the value changes
}
});
}
// Highlight emergency rows based on clinic column
function highlightEmergencyRows() {
const rows = document.querySelectorAll('div[role="row"]');
rows.forEach(row => {
const clinicCell = row.querySelector('div[col-id="clinic"]');
if (clinicCell && clinicCell.textContent.trim() === 'EMERGENCY') {
row.classList.add('emergency-row');
} else {
row.classList.remove('emergency-row'); // Remove the class if the condition is no longer met
}
});
}
const observerForGrid = new MutationObserver(() => {
applyHoverEffect();
applyStatusCellStyle();
highlightEmergencyRows(); // Call highlightEmergencyRows on every DOM change
});
const gridBodyViewport = document.querySelector('.ag-body-viewport'); // Observe the grid body viewport
if (gridBodyViewport) {
observerForGrid.observe(gridBodyViewport, { childList: true, subtree: false }); // subtree should be false here as we are observing direct children (rows)
} else {
console.warn("AG Grid body viewport not found. Falling back to body observer.");
observerForGrid.observe(document.body, { childList: true, subtree: true });
}
window.addEventListener('load', () => {
applyHoverEffect();
applyStatusCellStyle();
highlightEmergencyRows(); // Initial call to highlight emergency rows
});
// Set the dropdown value for pagination to 100
function setDropdownValue() {
const dropdown = document.getElementById("dropdownPaginationPageSize");
if (dropdown && dropdown.value !== "100") {
dropdown.value = "100"; // Set the value to "100"
// Trigger the 'change' event
const event = new Event('change', { bubbles: true });
dropdown.dispatchEvent(event);
console.log("Dropdown value set to 100");
}
}
// Observe changes in the DOM for the dropdown
function observeDOMForDropdown() {
const observer = new MutationObserver(() => {
setDropdownValue(); // Check and set the dropdown value when changes are detected
});
// Observe the entire document for changes
observer.observe(document.body, {
childList: true,
subtree: true,
});
console.log("MutationObserver is active for dropdown");
}
window.addEventListener('load', () => {
setDropdownValue(); // Initial check
observeDOMForDropdown(); // Start observing for dynamic changes
});
})();