Sandbox
This is a Sandbox, please make a subpage and try out stuff 🙂
[Home.Labs.SSH Lab Booking.\.SSH Booking Admin.WebPreferences, Facilities Rename.Laboratories.House rules using lab facilities.Furniture.WebHome, Home.PageTemplate.WebHome, Facilities Rename.LIBC MRI Scanner.Video And USB Diagram.WebHome, Main.Spaces, Facilities Rename.WebHome, Labs and Facilities.LIBC MRI Scanner.\.LIBC Scanner Admin.WebHome, Labs and Facilities.HPC Clusters.SHARK Cluster.SHARK-ALICE Data Transfer.WebPreferences, Labs and Facilities.HPC Clusters.SHARK Cluster.WebHome, Main.Search, Labs and Facilities.Laboratories.WebHome, Facilities Rename.Lab Computers.\.Lab Computer Admin.WebPreferences, Main.OverviewTemplate.WebHome, Facilities Rename.LIBC MRI Scanner.WebPreferences, Home.Labs.Responsibilities.WebHome, Facilities Rename.HPC Clusters.SHARK Cluster.SHARK-ALICE Data Transfer.WebPreferences, Labs and Facilities.SSH Lab Booking.\.SSH Booking Admin.WebHome, Labs and Facilities.HPC Clusters.ALICE Cluster.WebHome, Home.Labs.SSH Lab Booking.WebHome, Clusters.WebPreferences, Facilities.SSH Lab Booking.\.SSH Booking Admin.WebHome, Safety.Personal hygiene.WebHome, Clusters.SHARK Cluster.SHARK-ALICE Data Transfer.WebHome, Lab.LIBC MRI Scanner.Video And USB Diagram.WebPreferences, Lab.LIBC MRI Scanner.Video And USB Diagram.WebHome, Facilities Rename.LIBC MRI Scanner.\.LIBC Scanner Admin.\.LIBC PC replacement guide.WebHome, Safety.Personal protection measures.Disposable gloves protocol.WebHome, Facilities Rename.Lab Computers.\.Lab Computer Admin.WebHome, Clusters.ALICE Cluster.ALICE XRDP Guide.WebHome, Home.Labs.Safety.WebHome, Facilities Rename.HPC Clusters.SHARK Cluster.WebHome, Physiology.Scent.WebHome, Clusters.\.Cluster Support.WebHome, Labs and Facilities.HPC Clusters.\.Cluster Support.WebPreferences, Labs and Facilities.HPC Clusters.WebHome, Online Research.Lab Reservation.\.RoomBooking Admin Manual.WebHome, Facilities Rename.Laboratories.WebHome, Home.Labs.Safety.Hygiene Protocol.Incidin Plus® EEG Cleaning protocol.WebHome, Labs and Facilities.LIBC MRI Scanner.Video And USB Diagram.WebHome, Safety.Hygiene Protocol.Incidin Plus® EEG Cleaning protocol.WebHome, Home.OverviewTemplate.WebHome, Main.DatabaseSearch, Safety.Calamity protocol.WebHome, Facilities Rename.Laboratories.House rules using lab facilities.Research Checklist.WebHome, Safety.Hygiene Protocol.WebHome, Lab.LIBC MRI Scanner.Audio Diagram.WebHome, Facilities Rename.Storage space.WebHome, Safety.Personal protection measures.WebHome, Home.Labs.Safety.Calamity protocol.WebHome, Safety.Four eyes principle.WebHome, Hardware.Tobii Eye Trackers.Tobii Tips and Tricks.WebHome, Home.Labs.Knowledge and Training.WebHome, Labs and Facilities.Laboratories.EEG Chair.WebHome, Home.Labs.Safety.Lab safety.Safety inspection of research equipment protocol.WebHome, Safety.WebHome, Facilities Rename.HPC Clusters.SHARK Cluster.SHARK-FSW Data Transfer.WebHome, Main.MessageSenderMacro, Labs and Facilities.WebHome, Clusters.SHARK Cluster.SHARK-FSW Data Transfer.WebHome, Facilities Rename.HPC Clusters.\.Cluster Support.WebPreferences, Labs and Facilities.Laboratories.House rules using lab facilities.Research Checklist.WebHome, Main.PageTemplateProvider.WebHome, Facilities Rename.Researchdata analysis room.WebHome, Facilities Rename.SSH Lab Booking.\.SSH Booking Admin.WebPreferences, Labs and Facilities.HPC Clusters.SHARK Cluster.SHARK-FSW Data Transfer.WebHome, Safety.Personal hygiene.Personal hygiene protocol.WebHome, Safety.Personal hygiene.Hand hygiene protocol.WebHome, Labs and Facilities.Freezers.WebHome, Labs and Facilities.Laboratories.House rules using lab facilities.Furniture.WebHome, Physiology.Nutritional supplements.WebHome, Home.Labs.Safety.Personal protection measures.Breathing-protective-facemask protocol.WebHome, Home.Labs.Lab Coordinator.WebHome, Labs and Facilities.HPC Clusters.SHARK Cluster.SHARK-FSW Data Transfer.WebPreferences, Labs and Facilities.LIBC MRI Scanner.WebPreferences, Lab.LIBC MRI Scanner.WebHome, Facilities Rename.HPC Clusters.ALICE Cluster.ALICE XRDP Guide.WebHome, Online Research.Lab Reservation.\.RoomBooking Admin Manual.WebPreferences, Facilities Rename.LIBC MRI Scanner.\.LIBC Scanner Admin.\.LIBC PC replacement guide.WebPreferences, Home.Labs.WebPreferences, Home.Labs.Safety.Personal protection measures.Disposable gloves protocol.WebHome, Safety.Adverse Events.WebHome, Facilities.SSH Lab Booking.WebHome, Home.Labs.Safety.Personal protection measures.WebHome, Main.WebPreferences, Facilities Rename.HPC Clusters.SHARK Cluster.SHARK-ALICE Data Transfer.WebHome, Facilities Rename.HPC Clusters.SHARK Cluster.WebPreferences, Labs and Facilities.HPC Clusters.SHARK Cluster.WebPreferences, Main.SpaceIndex, Labs and Facilities.Lab Computers.\.Lab Computer Admin.WebHome, Safety.Needle stick injuries.WebHome, Clusters.ALICE Cluster.WebHome, Home.OverviewTemplate.WebPreferences, Main.OverviewTemplateProvider.WebHome, Home.Labs.Lab Access.WebHome, Labs and Facilities.LIBC MRI Scanner.Video And USB Diagram.WebPreferences, Home.Labs.Principles.WebHome, Main.PageTemplate.WebHome, Labs and Facilities.SSH Lab Booking.WebHome, Facilities Rename.Freezers.WebHome, Facilities Rename.Laboratories.EEG Chair.WebPreferences, Labs and Facilities.LIBC MRI Scanner.\.LIBC Scanner Admin.\.LIBC PC replacement guide.WebHome, Home.Labs.Safety.Needle stick injuries.WebHome, Home.Labs.Safety.Personal protection measures.Surgical facemask protocol.WebHome, Home.Labs.Costs.WebHome, Main.Tags, Home.Labs.Intake.WebHome, Home.Labs.Safety.Hygiene Protocol.WebHome, Home.Labs.Introduction.WebHome, Clusters.SHARK Cluster.WebPreferences, Facilities Rename.HPC Clusters.WebHome, Clusters.SHARK Cluster.SHARK-ALICE Data Transfer.WebPreferences, Facilities Rename.HPC Clusters.SHARK Cluster.SHARK-FSW Data Transfer.WebPreferences, Facilities Rename.LIBC MRI Scanner.\.LIBC Scanner Admin.WebHome, Home.Labs.WebHome, Labs and Facilities.LIBC MRI Scanner.\.LIBC Scanner Admin.\.LIBC PC replacement guide.WebPreferences, Facilities Rename.SSH Lab Booking.\.SSH Booking Admin.WebHome, Home.Labs.Safety.Four eyes principle.WebHome, Labs and Facilities.HPC Clusters.\.Cluster Support.WebHome, Labs and Facilities.LIBC MRI Scanner.Audio Diagram.WebHome, Safety.Personal protection measures.Surgical facemask protocol.WebHome, Welcome.WebHome, Facilities Rename.LIBC MRI Scanner.Video And USB Diagram.WebPreferences, Home.Labs.Safety.Personal hygiene.Personal hygiene protocol.WebHome, Labs and Facilities.HPC Clusters.WebPreferences, Home.Labs.Safety.Personal hygiene.Hand hygiene protocol.WebHome, Safety.Lab safety.Safety inspection of research equipment protocol.WebHome, Facilities Rename.SSH Lab Booking.WebHome, Labs and Facilities.LIBC MRI Scanner.WebHome, Labs and Facilities.Storage space.WebHome, Clusters.SHARK Cluster.WebHome, Home.Labs.Extension of Lab and Equipment.WebHome, Lab.1B02.WebHome, Facilities Rename.LIBC MRI Scanner.Audio Diagram.WebHome, Clusters.WebHome, Facilities.SSH Lab Booking.\.SSH Booking Admin.WebPreferences, Facilities Rename.HPC Clusters.\.Cluster Support.WebHome, Facilities Rename.Laboratories.Locations.WebHome, Labs and Facilities.Researchdata analysis room.WebHome, Home.Labs.SSH Lab Booking.\.SSH Booking Admin.WebHome, Facilities Rename.Laboratories.House rules using lab facilities.WebHome, Lab.LIBC MRI Scanner.Peripherals Diagram.WebHome, Online Research.Lab Reservation.WebHome, Labs and Facilities.SSH Lab Booking.\.SSH Booking Admin.WebPreferences, Labs and Facilities.Lab Computers.\.Lab Computer Admin.WebPreferences, Labs and Facilities.Laboratories.House rules using lab facilities.WebHome, Facilities Rename.HPC Clusters.ALICE Cluster.WebHome, Facilities Rename.LIBC MRI Scanner.WebHome, Main.UserDirectory, Clusters.\.Cluster Support.WebPreferences, Labs and Facilities.LIBC MRI Scanner.\.LIBC Scanner Admin.WebPreferences, Safety.Personal protection measures.Breathing-protective-facemask protocol.WebHome, Main.WebSearch, Main.AllDocs, Main.WebHome, Facilities Rename.LIBC MRI Scanner.\.LIBC Scanner Admin.WebPreferences, Facilities Rename.LIBC MRI Scanner.Peripherals Diagram.WebHome, Clusters.SHARK Cluster.SHARK-FSW Data Transfer.WebPreferences, Labs and Facilities.HPC Clusters.ALICE Cluster.ALICE XRDP Guide.WebHome, Labs and Facilities.LIBC MRI Scanner.Peripherals Diagram.WebHome, Labs and Facilities.HPC Clusters.SHARK Cluster.SHARK-ALICE Data Transfer.WebHome, Facilities Rename.Laboratories.EEG Chair.WebHome, Labs and Facilities.Laboratories.Locations.WebHome, Facilities Rename.HPC Clusters.WebPreferences, Home.Labs.Safety.Personal hygiene.WebHome, Safety.Lab safety.WebHome, Home.Labs.Safety.Lab safety.WebHome, Labs and Facilities.Laboratories.EEG Chair.WebPreferences, Home.Labs.Safety.Adverse Events.WebHome]
document.observe("xwiki:dom:loaded", function(){
var tableCounter = 0;
var tableIdPrefix = "macro_modal_tables_";
if(debugp){console.log("Step 1: going through tables");};
$$("#xwikicontent table").each(function(table) {
if (table.getAttribute('class') !== null && table.getAttribute('class').indexOf('xwiki-livetable') >= 0) {
// ignore livetables; they take care of themselves
console.log("Ignoring table: class" + table.getAttribute('class'));
return;
}
tableCounter++;
if (macro_tables==="all" || macro_tables.includes(table.getAttribute('id'))) {
if(debugp){console.log("Step 2: for table id " + table.getAttribute('id') + " and table count: " + tableCounter);};
// if default apply to all
if (!table.getAttribute('id') || !table.getAttribute('id').includes(tableIdPrefix)) {
if(debugp){console.log("Step 3: Table selected");};
const tableId = tableIdPrefix + tableCounter;
table.setAttribute('id', tableId);
if(debugp){console.log("Settings: default filters= ", macro_defaultFilter);};
if(debugp){console.log("Settings: hide columns all= ", macro_hideColumns);};
if(debugp){console.log("Settings: hide columns guest= ", macro_hideColumnsAll);};
// if default filter is needed, the listener on the table needs to be added downstream
//if(!(macro_defaultFilter==="none")){
//if(debugp){console.log("Preparing with default filters");};
observeFilterRow(table,macro_defaultFilter,"mainPage");
// }else{
// if(debugp){console.log("Preparing without default filters");};
//
// };
table.classList.add('table-modal');
//document.getElementById(tableId).addEventListener('click',() => openModal(tableId));
document.getElementById(tableId).classList.add('table-modal');
};
};
})
});
// function to hide column
function hideColumn(table, columnsString) {
if(debugp){console.log("Starting hide column function");};
const columns = columnsString.split(",").map(col => col.trim().toLowerCase());
const headerRow = table.querySelector("tr.sortHeader");
if (!headerRow) return;
const headers = headerRow.querySelectorAll("th");
const indexesToHide = [];
headers.forEach((th, index) => {
const headerText = th.textContent.trim().toLowerCase();
if (columns.includes(headerText)) {
indexesToHide.push(index);
}
});
if (indexesToHide.length === 0) return;
// Get filter row and its cells
const filterRow = table.querySelector("tbody tr:nth-child(1)");
const filterCells = filterRow.querySelectorAll("td");
// Move buttons if last column is hidden
const lastIndex = headers.length - 1;
if (indexesToHide.includes(lastIndex)) {
if(debugp){console.log("Moving buttons to other column");};
const buttonCell = filterCells[lastIndex];
const buttons = buttonCell.querySelectorAll("input.btnflt, input[type='button']");
if (buttons.length > 0) {
// Find last visible cell
let targetCell = null;
for (let i = filterCells.length - 1; i >= 0; i--) {
if (!indexesToHide.includes(i)) {
targetCell = filterCells[i];
break;
}
}
if (targetCell) {
buttons.forEach(btn => targetCell.appendChild(btn));
}
}
addResetButton(table);
}
// Hide header cells
indexesToHide.forEach(idx => {
headers[idx].style.display = "none";
});
// Hide all cells in those columns
const rows = table.querySelectorAll("tr");
rows.forEach(row => {
const cells = row.querySelectorAll("td, th");
indexesToHide.forEach(idx => {
if (cells[idx]) {
cells[idx].style.display = "none";
}
});
});
}
// Mutation observer so we can act when the filter row is created
function observeFilterRow(table,macro_defaultFilter,calledFrom) {
if(debugp){console.log("Starting mutation observer function");};
const observer = new MutationObserver(() => {
const filterRow = table.querySelector("tbody tr:nth-child(1)");
if (filterRow && filterRow.querySelector("input")) {
console.log("Filter row mutation found");
observer.disconnect(); // stop observing
addResetButton(table); // add the reset button
if(!(macro_defaultFilter==="none")){applyDefaultFilter(table,macro_defaultFilter,calledFrom);}; // apply default filters
if(calledFrom==="mainPage" && macro_defaultFilter==="none"){table.addEventListener('click',() => openModal(table.id));}; // set listener if no default filters
if(macro_guest==="true" && !(macro_hideColumns==="none")){hideColumn(table,macro_hideColumns);}; // hide columns if relevant
if(!(macro_hideColumnsAll==="none")){hideColumn(table,macro_hideColumnsAll);}; // hide columns if relevant
// to enable sticky top rows
filterRow.classList.add('stickyHeader');
const firstRowHeight = filterRow.offsetHeight;
table.querySelectorAll("tbody tr:nth-child(2)").forEach(cell => {
cell.style.top = firstRowHeight + 'px';
});
};
});
observer.observe(table, { childList: true, subtree: true });
}
// ✅ Add Reset Filters button underneath the filter button
function addResetButton(table){
if(debugp){console.log("Starting addResetButton function");};
const filterButton = table.querySelector('input[type="button"], button');
if (filterButton) {
const resetBtn = document.createElement('button');
resetBtn.textContent = "Reset";
resetBtn.style.marginTop = "5px";
resetBtn.style.display = "block"; // Ensures it appears below
resetBtn.addEventListener('click', function () {
// Clear all filter inputs
const filterInputs = table.querySelectorAll('input[type="text"]');
filterInputs.forEach(input => input.value = "");
// Call Filter() from tablefilterNsort.js to refresh table
if (typeof Filter === "function") {
Filter(table.id);
}
});
// Insert the reset button right after the filter button
filterButton.insertAdjacentElement('afterend', resetBtn);
};
};
// To apply default filters
function applyDefaultFilter(table,macro_defaultFilter,calledFrom){
if(debugp){console.log("Starting default filter function");};
const filters = macro_defaultFilter.split(",").map(pair => {
const [col, val] = pair.split("=").map(s => s.trim());
return { column: col.trim().toLowerCase(), value: val };
});
if (!table) return;
// Get header row (second row with class sortHeader)
const headerRow = table.querySelector("tr.sortHeader");
if (!headerRow) return;
const headers = headerRow.querySelectorAll("th");
// Get filter row
const filterRow = table.querySelector("tbody tr:nth-child(1)");
const filterCells = filterRow.querySelectorAll("td");
filters.forEach(({ column, value }) => {
let targetIndex = -1;
headers.forEach((th, index) => {
if (th.textContent.trim().toLowerCase() === column) {
targetIndex = index;
}
});
if (targetIndex === -1) {
console.warn(`Column '${column}' not found`);
return;
}
const filterInput = filterCells[targetIndex]?.querySelector("input");
if (!filterInput) {
console.warn(`Filter input for column '${column}' not found`);
return;
}
// Set value
filterInput.value = value;
});
// Option 2: Click the Filter button (if required)
const filterButton = filterRow.querySelector("input.btnflt");
if (filterButton) {
console.log("clicking!")
filterButton.click();
}
// add the click listener for the modal after filter button is pressed (is this needed?)
if(calledFrom === "mainPage"){
table.addEventListener('click',() => openModal(table.id,"withFilter"));
};
};
function openModal(tableId) {
if(debugp){console.log("Starting Opening modal for table: " + tableId);};
const modal = document.getElementById('modal');
const modalWrapper = document.getElementById('modalTableWrapper');
const mainTable = document.getElementById(tableId);
// Clone the original table
const clonedTable = mainTable.cloneNode(true);
const modalTableId = tableId + "_modal";
clonedTable.id = modalTableId;
//Add observer for default filter
observeFilterRow(clonedTable,macro_defaultFilter,"modal");
clonedTable.classList.remove("table-modal");
clonedTable.classList.add("table-modal-popup");
// Clear previous modal content and append cloned table
modalWrapper.innerHTML = "";
modalWrapper.appendChild(clonedTable);
// Display modal
modal.style.display = 'flex';
console.log("before the sort function");
if(macro_sortable==="yes" || clonedTable.classList.contains('sortable') ){
console.log("in the sort function");
console.log("header row: " + getHeaderRow(clonedTable));
// Ensure cloned table has required classes
if (!clonedTable.classList.contains('sortable')) {
clonedTable.classList.add('sortable');
};
if (clonedTable.classList.contains('filterable')) {
// Remove the top row (first <tr>) from the cloned table
const firstRow = clonedTable.querySelector('tr');
if (firstRow) {
firstRow.remove();
};
}else{
clonedTable.classList.add('filterable');
};
// After cloning and removing unwanted rows
const headerRow = clonedTable.querySelector('tr');
if (headerRow) {
headerRow.classList.add('sortHeader', 'stickyHeader'); // Mark as header row
}
// ✅ Reinitialize sorting and filtering for the cloned table
ts_makeSortable(clonedTable);
setFilterGrid(modalTableId, getHeaderRow(clonedTable));
};
console.log("Modal table initialized with sorting and filtering.");
};
function closeModal() {
modal.classList.remove('show');
setTimeout(() => {
modal.style.display = 'none';
}, 300); // Matches CSS transition
}
// Close when clicking outside modal-content
modal.addEventListener('click', (e) => {
if (e.target === modal) {
closeModal();
}
});
// Close when pressing Escape
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
closeModal();
}
});