UNPKG

gentelella

Version:

Gentelella Admin is a free to use Bootstrap admin template

438 lines (377 loc) 12.6 kB
/** * Modern Init.js - jQuery Eliminated * This is the new, modernized version of init.js with all jQuery dependencies removed * Only contains functionality that hasn't been moved to separate modules */ // Use the centralized DOM utilities const DOM = window.DOM; /** * NOTE: DataTables initialization moved to modern tables module * No longer uses jQuery - uses DataTables 2.x native JavaScript API * See: /modules/tables-modern.js */ /** * Date Picker Initialization - MODERNIZED * Uses modern date picker libraries instead of jQuery UI */ async function initializeDatePickers() { // Check if there are any date picker elements on the page const datePickerElements = DOM.selectAll('.datepicker, [data-datepicker]'); if (datePickerElements.length === 0) { return; } // Check if TempusDominus is available, if not try to load forms module if (typeof TempusDominus === 'undefined') { try { if (typeof window.loadModule === 'function') { await window.loadModule('forms'); } else { return; } } catch (error) { if (process.env.NODE_ENV === 'development') { console.error('Failed to load forms module for date pickers:', error); } return; } } // Initialize date pickers if TempusDominus is now available if (typeof TempusDominus !== 'undefined') { datePickerElements.forEach(element => { try { new TempusDominus(element, { display: { components: { clock: false, seconds: false } }, localization: { format: 'MM/dd/yyyy' } }); } catch (error) { if (process.env.NODE_ENV === 'development') { console.error('Failed to initialize date picker:', error); } } }); } } /** * Panel Toolbox Functionality - MODERNIZED FROM JQUERY * Handles collapse/expand and close functionality for x_panel elements */ function initializePanelToolbox() { // Collapse/Expand functionality DOM.selectAll('.collapse-link').forEach(link => { DOM.on(link, 'click', function(event) { event.preventDefault(); const panel = DOM.closest(link, '.x_panel'); const icon = DOM.find(link, 'i'); const content = DOM.find(panel, '.x_content'); if (!panel || !content) return; // Check if panel is currently collapsed const isCollapsed = content.style.display === 'none'; if (isCollapsed) { // Expand DOM.slideDown(content); DOM.removeClass(icon, 'fa-chevron-down'); DOM.addClass(icon, 'fa-chevron-up'); panel.style.height = 'auto'; } else { // Collapse DOM.slideUp(content); DOM.removeClass(icon, 'fa-chevron-up'); DOM.addClass(icon, 'fa-chevron-down'); } }); }); // Close panel functionality DOM.selectAll('.close-link').forEach(link => { DOM.on(link, 'click', function(event) { event.preventDefault(); const panel = DOM.closest(link, '.x_panel'); if (panel) { // Fade out and remove panel panel.style.transition = 'opacity 0.3s ease'; panel.style.opacity = '0'; setTimeout(() => { panel.remove(); }, 300); } }); }); } /** * Progress Bar Animations - MODERNIZED FROM JQUERY * Animates progress bars with data-transitiongoal attribute */ function initializeProgressBars() { DOM.selectAll('.progress-bar[data-transitiongoal]').forEach(bar => { const goal = bar.getAttribute('data-transitiongoal'); if (goal) { // Reset to 0 and animate to goal bar.style.width = '0%'; bar.style.transition = 'width 1.5s ease-in-out'; // Use setTimeout to ensure the transition triggers setTimeout(() => { bar.style.width = goal + '%'; }, 100); } }); // Animate regular progress bars on page load DOM.selectAll('.progress-bar:not([data-transitiongoal])').forEach(bar => { const currentWidth = bar.style.width; if (currentWidth) { bar.style.width = '0%'; bar.style.transition = 'width 1.2s ease-out'; setTimeout(() => { bar.style.width = currentWidth; }, 200); } }); } /** * Form Validation - MODERNIZED FROM JQUERY * Uses HTML5 validation APIs instead of jQuery validation plugin */ function initializeFormValidation() { DOM.selectAll('form[data-validate], .needs-validation').forEach(form => { DOM.on(form, 'submit', function(event) { if (!form.checkValidity()) { event.preventDefault(); event.stopPropagation(); // Add visual feedback for invalid fields DOM.selectAll(':invalid', form).forEach(field => { DOM.addClass(field, 'is-invalid'); // Show custom error message if provided const errorMsg = field.getAttribute('data-error-message'); if (errorMsg) { let errorDiv = DOM.find(field.parentNode, '.invalid-feedback'); if (!errorDiv) { errorDiv = document.createElement('div'); errorDiv.className = 'invalid-feedback'; field.parentNode.appendChild(errorDiv); } errorDiv.textContent = errorMsg; } }); } DOM.addClass(form, 'was-validated'); }); // Remove error styling when field becomes valid DOM.selectAll('input, select, textarea', form).forEach(field => { DOM.on(field, 'input', function() { if (field.checkValidity()) { DOM.removeClass(field, 'is-invalid'); DOM.addClass(field, 'is-valid'); } }); }); }); } /** * Tabs and Accordion - MODERNIZED FROM JQUERY * Uses Bootstrap 5 native JavaScript API */ function initializeTabsAndAccordions() { // Bootstrap 5 tabs - no additional initialization needed // They work automatically with data attributes // Custom tab functionality for non-Bootstrap tabs DOM.selectAll('.custom-tabs').forEach(tabContainer => { const tabButtons = DOM.selectAll('.tab-button', tabContainer); const tabPanes = DOM.selectAll('.tab-pane', tabContainer); tabButtons.forEach(button => { DOM.on(button, 'click', function() { const targetId = this.getAttribute('data-target'); const targetPane = DOM.select(targetId); if (targetPane) { // Hide all panes tabPanes.forEach(pane => { DOM.removeClass(pane, 'active'); pane.style.display = 'none'; }); // Remove active class from all buttons tabButtons.forEach(btn => DOM.removeClass(btn, 'active')); // Show target pane and activate button DOM.addClass(targetPane, 'active'); targetPane.style.display = 'block'; DOM.addClass(this, 'active'); } }); }); }); } /** * Modals - MODERNIZED FROM JQUERY * Uses Bootstrap 5 native Modal API */ function initializeModals() { // Bootstrap 5 modals work automatically, but we can add custom functionality DOM.selectAll('.modal').forEach(modalElement => { if (typeof bootstrap !== 'undefined' && bootstrap.Modal) { const modal = new bootstrap.Modal(modalElement); // Store modal instance for external access modalElement.modalInstance = modal; // Custom event handlers modalElement.addEventListener('shown.bs.modal', function() { // Auto-focus first input in modal const firstInput = DOM.select('input, textarea, select', this); if (firstInput) firstInput.focus(); }); } }); } /** * Drag and Drop - MODERN HTML5 IMPLEMENTATION * Replaces jQuery UI sortable with native HTML5 drag and drop */ function initializeDragAndDrop() { DOM.selectAll('.sortable, [data-sortable]').forEach(container => { const items = DOM.selectAll('.sortable-item, [data-sortable-item]', container); items.forEach(item => { item.draggable = true; DOM.on(item, 'dragstart', function(e) { e.dataTransfer.setData('text/plain', ''); DOM.addClass(this, 'dragging'); }); DOM.on(item, 'dragend', function() { DOM.removeClass(this, 'dragging'); }); }); DOM.on(container, 'dragover', function(e) { e.preventDefault(); const dragging = DOM.select('.dragging', this); const siblings = [...DOM.selectAll('.sortable-item:not(.dragging)', this)]; const nextSibling = siblings.find(sibling => { return e.clientY <= sibling.getBoundingClientRect().top + sibling.offsetHeight / 2; }); this.insertBefore(dragging, nextSibling); }); }); } /** * Search and Filter - MODERNIZED FROM JQUERY * Native JavaScript search functionality */ function initializeSearchAndFilter() { DOM.selectAll('.search-input, [data-search]').forEach(searchInput => { const targetSelector = searchInput.getAttribute('data-target') || '.searchable-item'; const targetElements = DOM.selectAll(targetSelector); DOM.on(searchInput, 'input', function() { const query = this.value.toLowerCase().trim(); targetElements.forEach(element => { const text = element.textContent.toLowerCase(); const matches = text.includes(query); element.style.display = matches ? '' : 'none'; // Add/remove highlight class if (matches && query) { DOM.addClass(element, 'search-match'); } else { DOM.removeClass(element, 'search-match'); } }); // Show count of visible items const visibleCount = targetElements.filter(el => el.style.display !== 'none').length; const countElement = DOM.select('.search-count'); if (countElement) { countElement.textContent = `${visibleCount} items found`; } }); }); } /** * Keyboard Shortcuts - MODERN IMPLEMENTATION * Replaces jQuery hotkeys with native keyboard event handling */ function initializeKeyboardShortcuts() { const shortcuts = { 'Ctrl+/': () => DOM.select('.search-input')?.focus(), 'Escape': () => { // Close modals DOM.selectAll('.modal.show').forEach(modal => { if (modal.modalInstance) { modal.modalInstance.hide(); } }); // Clear search DOM.selectAll('.search-input').forEach(input => { input.value = ''; input.dispatchEvent(new Event('input')); }); } }; document.addEventListener('keydown', function(e) { const key = (e.ctrlKey ? 'Ctrl+' : '') + (e.altKey ? 'Alt+' : '') + (e.shiftKey ? 'Shift+' : '') + (e.key === ' ' ? 'Space' : e.key); if (shortcuts[key]) { e.preventDefault(); shortcuts[key](); } }); } /** * Main Initialization - MODERNIZED FROM JQUERY * Coordinates all modern initialization functions */ async function initializeModernComponents() { try { // Initialize components that still need initialization await initializeDatePickers(); initializePanelToolbox(); initializeProgressBars(); initializeFormValidation(); initializeTabsAndAccordions(); initializeModals(); initializeDragAndDrop(); initializeSearchAndFilter(); initializeKeyboardShortcuts(); // DataTables now handled by modern tables module (jQuery-free) } catch (error) { if (process.env.NODE_ENV === 'development') { console.error('Failed to initialize modern components:', error); } } } /** * Module Loading Status Indicator */ function showLoadingStatus() { const statusElement = document.createElement('div'); statusElement.id = 'module-loading-status'; statusElement.style.cssText = ` position: fixed; top: 10px; right: 10px; background: #26B99A; color: white; padding: 8px 12px; border-radius: 4px; font-size: 12px; z-index: 9999; transition: opacity 0.3s; `; statusElement.textContent = '✅ Modern components loaded'; document.body.appendChild(statusElement); // Auto-hide after 3 seconds setTimeout(() => { statusElement.style.opacity = '0'; setTimeout(() => statusElement.remove(), 300); }, 3000); } // Initialize when DOM is ready if (typeof document !== 'undefined') { document.addEventListener('DOMContentLoaded', async () => { await initializeModernComponents(); }); } // Export for external use export { initializeModernComponents, initializeDatePickers, initializeFormValidation, DOM };