Brian Read a369b719c5 * Tue Apr 22 2025 Brian Read <brianr@koozali.org> 11.0.0-2.sme
- Add some styling to the hardware information and quick navigation
2025-04-22 15:54:58 +01:00

195 lines
6.4 KiB
JavaScript

/**
* Table Navigation Dropdown - JavaScript Only Solution for Mojolicious Sites
*
* This script automatically creates a dropdown menu to navigate between tables
* on a page without requiring any HTML modifications.
*
* Compatible with all modern browsers and IE11+.
*
* How to use:
* 1. Add this script to your Mojolicious site using a <script> tag
* 2. The script will automatically run when the page loads
* 3. A dropdown menu will be created at the top of the page
*/
(function() {
// Function to run when DOM is fully loaded
function initTableNavigation() {
// Find all tables with class 'node' (based on your HTML structure)
var tables = document.querySelectorAll('table.node');
if (!tables || tables.length === 0) {
console.log('No tables found with class "node"');
return;
}
// Create container for the dropdown
var navContainer = document.createElement('div');
navContainer.style.position = 'sticky';
navContainer.style.top = '0';
navContainer.style.backgroundColor = '#fff';
navContainer.style.padding = '10px 0';
navContainer.style.marginBottom = '20px';
navContainer.style.zIndex = '100';
navContainer.style.borderBottom = '1px solid #ddd';
navContainer.style.width = '300px';
// Create the select element
var select = document.createElement('select');
select.style.width = '100%';
select.style.padding = '10px';
select.style.fontSize = '16px';
select.style.border = '1px solid #ddd';
select.style.borderRadius = '4px';
select.style.backgroundColor = '#f8f8f8';
select.style.cursor = 'pointer';
// Add default option
var defaultOption = document.createElement('option');
defaultOption.value = '';
defaultOption.textContent = '-- Jump to a table --';
select.appendChild(defaultOption);
// Process each table and add to dropdown
for (var i = 0; i < tables.length; i++) {
var table = tables[i];
// Try to get table ID from the first row if it contains "id:"
var tableId = 'table-' + i;
var tableName = 'Table ' + (i + 1);
// Look for the ID in the table header
var idCell = table.querySelector('thead td.first');
var idValue = table.querySelector('thead td.second');
if (idCell && idValue && idCell.textContent.trim().toLowerCase() === 'id:') {
// Get the ID value (might be in a div with class 'id')
var idDiv = idValue.querySelector('.id');
if (idDiv) {
tableId = idDiv.textContent.trim();
tableName = tableId;
} else if (idValue.textContent.trim()) {
tableId = idValue.textContent.trim();
tableName = tableId;
}
}
// Try to get a better name from the description if available
var descRows = table.querySelectorAll('tbody tr');
for (var j = 0; j < descRows.length; j++) {
var descRow = descRows[j];
var descCell = descRow.querySelector('td.first');
var descValue = descRow.querySelector('td.second');
if (descCell && descValue &&
descCell.textContent.trim().toLowerCase().includes('description') &&
descValue.textContent.trim()) {
tableName = descValue.textContent.trim() + ' (' + tableName + ')';
break;
}
}
// Create a unique ID for the table if it doesn't have one
if (!table.id) {
// Clean the ID to make it valid for HTML
var safeId = tableId.replace(/[^a-z0-9]/gi, '_').toLowerCase();
table.id = safeId;
}
// Add option to dropdown
var option = document.createElement('option');
option.value = table.id;
option.textContent = tableName;
select.appendChild(option);
// Add scroll margin to the table
table.style.scrollMarginTop = '70px';
}
// Add event listener to the select element
if (select.addEventListener) {
// Modern browsers
select.addEventListener('change', handleSelectChange);
} else if (select.attachEvent) {
// IE8 and below
select.attachEvent('onchange', handleSelectChange);
}
// Add the select to the container
navContainer.appendChild(select);
// Insert the container at the top of the body or after the first heading
var heading = document.querySelector('h1, h2');
if (heading && heading.parentNode) {
heading.parentNode.insertBefore(navContainer, heading.nextSibling);
} else {
var body = document.body;
if (body.firstChild) {
body.insertBefore(navContainer, body.firstChild);
} else {
body.appendChild(navContainer);
}
}
}
// Function to handle select change
function handleSelectChange() {
var selectedValue = this.value;
if (selectedValue) {
var element = document.getElementById(selectedValue);
if (element) {
// Scroll to the selected element
scrollToElement(element);
// Highlight the selected table briefly
var originalBackground = element.style.backgroundColor || '';
element.style.backgroundColor = '#ffffd0';
// Use setTimeout for the highlight effect
setTimeout(function() {
element.style.backgroundColor = originalBackground;
}, 1500);
}
}
}
// Cross-browser scroll function
function scrollToElement(element) {
// Check if scrollIntoView is supported
if (element.scrollIntoView) {
// Try smooth scrolling if supported
try {
element.scrollIntoView({ behavior: 'smooth' });
} catch (error) {
// Fallback for browsers that don't support smooth scrolling
element.scrollIntoView();
}
} else {
// Manual scroll fallback
var rect = element.getBoundingClientRect();
var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
var targetY = rect.top + scrollTop - 70; // 70px offset for the sticky header
window.scrollTo(0, targetY);
}
}
// Cross-browser DOM ready function
function ready(fn) {
if (document.readyState !== 'loading') {
fn();
} else if (document.addEventListener) {
document.addEventListener('DOMContentLoaded', fn);
} else {
document.attachEvent('onreadystatechange', function() {
if (document.readyState !== 'loading') {
fn();
}
});
}
}
// Initialize when DOM is ready
ready(initTableNavigation);
})();