UNPKG

csdsolutions-csdjs

Version:

Libreria per i progetti di CSD Solutions

589 lines (486 loc) 19.2 kB
// Utility Functions function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } // Segment Component function initializeSegment(element) { const $element = $CSD(element); const $buttons = $element.find('.csd-segment-button'); const $indicator = $element.find('.csd-segment-indicator'); const containerStyle = window.getComputedStyle(element); const segmentPadding = parseFloat(containerStyle.paddingLeft); function updateIndicatorPosition(selectedButton) { if (!selectedButton || !$indicator.length) return; const containerRect = element.getBoundingClientRect(); const $buttonElements = $element.find('.csd-segment-button'); const buttonElements = $buttonElements.elements; const isFirstButton = buttonElements[0] === selectedButton; const isLastButton = buttonElements[buttonElements.length - 1] === selectedButton; $buttonElements.removeClass('before-checked'); const selectedIndex = buttonElements.indexOf(selectedButton); if (!isFirstButton && selectedIndex > 0) { $CSD(buttonElements[selectedIndex - 1]).addClass('before-checked'); } const buttonWidth = selectedButton.getBoundingClientRect().width; let translateX = 0; for (let i = 0; i < selectedIndex; i++) { translateX += buttonElements[i].getBoundingClientRect().width; } if (isFirstButton) { translateX = 0; } else if (isLastButton) { translateX = containerRect.width - buttonWidth - (segmentPadding * 2); } else { translateX += segmentPadding; } requestAnimationFrame(() => { $indicator[0].style.width = `${buttonWidth}px`; $indicator[0].style.transform = `translateX(${translateX}px)`; }); } function updateIndicator(selectedButton) { updateIndicatorPosition(selectedButton); const $icons = $CSD(selectedButton).find('ion-icon'); if ($icons.length > 0) { setTimeout(() => { updateIndicatorPosition(selectedButton); setTimeout(() => updateIndicatorPosition(selectedButton), 300); }, 50); } } function selectButton(selectedButton) { if ($CSD(selectedButton).hasClass('active')) return; $buttons.removeClass('active'); $CSD(selectedButton).addClass('active'); updateIndicator(selectedButton); const contentId = $CSD(selectedButton).attr('content-id'); if (contentId) { // Nascondi tutti i contenuti // Mostra il contenuto corrispondente const targetContent = document.getElementById(contentId); if (targetContent) { const segmentContents = targetContent.closest('.csd-segment-contents'); segmentContents.querySelector('.csd-segment-content.active')?.classList.remove('active'); targetContent.classList.add('active'); } } element.dispatchEvent(new CustomEvent('segment-change', { detail: { value: $CSD(selectedButton).attr('value'), contentId: contentId } })); } const $activeButton = $element.find('.csd-segment-button.active'); if ($activeButton.length) { updateIndicator($activeButton[0]); } $buttons.each(button => { $CSD(button).on('click', () => { if (!$CSD(button).prop('disabled')) { selectButton(button); } }); }); const debouncedResize = debounce(() => { const $activeButton = $element.find('.csd-segment-button.active'); if ($activeButton.length) { updateIndicator($activeButton[0]); } }, 100); window.addEventListener('resize', debouncedResize); } // Tab Component function initializeTab(element) { const $element = $CSD(element); const $tabs = $element.find('.csd-tab'); const $panels = $element.find('.csd-tab-panel'); const $indicator = $element.find('.csd-tab-indicator'); const $tabList = $element.find('.csd-tab-list'); function updateIndicatorPosition(selectedTab) { if (!selectedTab || !$indicator.length) return; const tabRect = selectedTab.getBoundingClientRect(); const listRect = $tabList[0].getBoundingClientRect(); const translateX = tabRect.left - listRect.left; requestAnimationFrame(() => { $indicator .css('width', `${tabRect.width}px`) .css('transform', `translateX(${translateX}px)`); }); } function selectTab(selectedTab, index) { const $selectedTab = $CSD(selectedTab); if ($selectedTab.hasClass('active')) return; $tabs.removeClass('active'); $selectedTab.addClass('active'); $panels.each((panelIndex, panel) => { $CSD(panel).toggleClass('active', panelIndex === index); }); updateIndicatorPosition(selectedTab); } $tabs.each((tab) => { $CSD(tab).on('click', () => { const index = $CSD(tab).index(); selectTab(tab, index); }); }); const $activeTab = $element.find('.csd-tab.active'); if ($activeTab.length) { updateIndicatorPosition($activeTab[0]); } const debouncedResize = debounce(() => { const $activeTab = $element.find('.csd-tab.active'); if ($activeTab.length) { updateIndicatorPosition($activeTab[0]); } }, 100); $CSD(window).on('resize', debouncedResize); } // Menu Component function initializeMenu(element) { const $element = $CSD(element); const $menuItems = $element.find('.csd-menu-item'); const $subMenuItems = $element.find('.has-submenu'); $menuItems.on('click', function() { const $this = $CSD(this); if (!$this.hasClass('has-submenu')) { $menuItems.removeClass('active'); $this.addClass('active'); } }); $subMenuItems.on('click', function(e) { e.preventDefault(); $CSD(this).toggleClass('expanded'); }); } // Toolbar Component function initializeToolbar(element) { // Aggiungi qui la logica specifica per la toolbar se necessaria } function initializeDropdown(element) { if (!element) return; const $element = $CSD(element); const $toggle = $element.find('.csd-dropdown-toggle'); const $menu = $element.find('.csd-dropdown-menu, .csd-mega-menu'); if (!$toggle.length || !$menu.length) return; const isMegaMenu = $menu.hasClass('csd-mega-menu'); $toggle.on('click', function(e) { e.preventDefault(); e.stopPropagation(); const $openMenus = $CSD('.csd-dropdown-menu.show, .csd-mega-menu.show'); $openMenus.each(function() { const $openMenu = $CSD(this); if (!$openMenu.is($menu)) { $openMenu.removeClass('show') .closest('.csd-dropdown') .find('.csd-dropdown-toggle') .removeClass('active'); } }); $menu.toggleClass('show'); $toggle.toggleClass('active'); if (isMegaMenu) { const $menuBar = $element.closest('.csd-menubar'); if ($menuBar.length) { const dropdownRect = element.getBoundingClientRect(); const menuRect = $menu[0].getBoundingClientRect(); const viewportWidth = window.innerWidth; const leftOffset = Math.max(0, dropdownRect.left - ((menuRect.width - dropdownRect.width) / 2)); const rightEdge = leftOffset + menuRect.width; const finalLeftOffset = rightEdge > viewportWidth ? viewportWidth - menuRect.width : leftOffset; $menu.css('left', `${-finalLeftOffset}px`); } } }); $menu.on('click', function(e) { e.stopPropagation(); }); } // Close dropdowns when clicking outside $CSD(document).on('click', function(e) { const $target = $CSD(e.target); if (!$target.closest('.csd-dropdown').length) { const $openMenus = $CSD('.csd-dropdown-menu.show, .csd-mega-menu.show'); $openMenus.each(function() { $CSD(this) .removeClass('show') .closest('.csd-dropdown') .find('.csd-dropdown-toggle') .removeClass('active'); }); } }); function initializeSubmenu(element) { if (!element) return; const $element = $CSD(element); const $toggle = $element.find('> a'); if (!$toggle.length) return; $toggle.on('click', function(e) { e.preventDefault(); e.stopPropagation(); const $parent = $CSD(this).closest('.has-submenu').parent(); if ($parent.length) { $parent.find('.has-submenu.open').not($element).removeClass('open'); } $element.toggleClass('open'); }); const $submenuItems = $element.find('.csd-sidebar-submenu .csd-sidebar-item > a'); $submenuItems.on('click', function(e) { const $this = $CSD(this); const href = $this.attr('href'); if (!href || href === '#') { e.preventDefault(); } e.stopPropagation(); }); } function initializeNavigation(element) { // Initialize navigation } function closeAllDropdowns() { $CSD('.csd-dropdown-menu.show, .csd-mega-menu.show').each(function() { $CSD(this) .removeClass('show') .closest('.csd-dropdown') .find('.csd-dropdown-toggle') .removeClass('active'); }); } function closeAllSubmenus() { $CSD('.has-submenu.open').removeClass('open'); } // Initialize Sidebar Toggle function initializeSidebar() { const $sidebarToggle = $CSD('#sidebarToggle'); const $sidebar = $CSD('.csd-sidebar'); const $sidebarOverlay = $CSD('#sidebarOverlay'); const $sidebarPositionSwitch = $CSD('#sidebarPosition'); const $demoContainer = $sidebar.length ? $sidebar.closest('.demo-container') : null; if (!$sidebar.length || !$sidebarOverlay.length || !$sidebarToggle.length) return; if ($sidebarPositionSwitch.length) { $sidebarPositionSwitch.prop('checked', true); $sidebarPositionSwitch.on('change', function() { if ($CSD(this).prop('checked')) { if ($sidebar.length && $demoContainer.length) { $sidebar.removeClass('csd-sidebar-fixed'); $demoContainer.append($sidebar); } } else { if ($sidebar.length && $demoContainer.length) { $sidebar.addClass('csd-sidebar-fixed'); $demoContainer.parent().append($sidebar); } } }); } if ($sidebarToggle.length && $sidebar.length && $sidebarOverlay.length) { const $toggleIcon = $sidebarToggle.find('ion-icon'); $sidebarToggle.on('click', function() { if ($sidebar.hasClass('csd-sidebar-fixed')) { $sidebar.toggleClass('show'); $sidebarOverlay.toggleClass('active'); } else { $sidebar.toggleClass('active'); } const isActive = $sidebar.hasClass('active') || $sidebar.hasClass('show'); $toggleIcon.attr('name', isActive ? 'close-outline' : 'menu-outline'); }); $sidebarOverlay.on('click', function() { if ($sidebar.hasClass('csd-sidebar-fixed')) { $sidebar.removeClass('show'); } else { $sidebar.removeClass('active'); } $sidebarOverlay.removeClass('active'); $toggleIcon.attr('name', 'menu-outline'); }); } const $submenuItems = $CSD('.has-submenu'); $submenuItems.each(function() { const $item = $CSD(this); const $link = $item.find('a'); if ($link.length) { $link.on('click', function(e) { e.preventDefault(); $item.toggleClass('open'); }); } }); } function initializeStepper(element) { if (!element) return; const $element = $CSD(element); const $stepper = $element.find('.csd-stepper'); if (!$stepper.length) return; const $steps = $stepper.find('.csd-step'); const $panels = $element.find('.csd-step-panel'); const $prevBtn = $element.find('.prev-step'); const $nextBtn = $element.find('.next-step'); const isVertical = $stepper.hasClass('vertical'); function updateProgressLine($progress, index) { const $currentIndicator = $steps.eq(index).find('.csd-step-indicator'); const $nextIndicator = $steps.eq(index + 1).find('.csd-step-indicator'); const stepperRect = $stepper[0].getBoundingClientRect(); if (isVertical) { const currentRect = $currentIndicator[0].getBoundingClientRect(); const nextRect = $nextIndicator[0].getBoundingClientRect(); $progress.css({ 'top': `${currentRect.bottom - stepperRect.top + 6}px`, 'height': `${nextRect.top - currentRect.bottom - 12}px`, 'left': `${currentRect.left - stepperRect.left + currentRect.width / 2}px` }); } else { const currentRect = $currentIndicator[0].getBoundingClientRect(); const nextRect = $nextIndicator[0].getBoundingClientRect(); $progress.css({ 'left': `${currentRect.right - stepperRect.left + 12}px`, 'width': `${nextRect.left - currentRect.right - 24}px`, 'top': `${currentRect.top - stepperRect.top + currentRect.height / 2}px` }); } } $steps.each(function(step, index) { if (index < $steps.length - 1) { const $progress = $CSD('<div>') .addClass('csd-step-progress') .attr('data-step', index + 1); $stepper.append($progress); updateProgressLine($progress, index); } }); let currentStep = 1; const totalSteps = $steps.length; function updateProgress() { const $activeStep = $stepper.find('.csd-step.active'); if (!$activeStep.length) return; const stepIndex = $activeStep.index(); $stepper.find('.csd-step-progress').each(function(progress, index) { const $progress = $CSD(progress); updateProgressLine($progress, index); $progress.toggleClass('completed', index < stepIndex); }); } function goToStep(step) { currentStep = step; $steps.each(function(step, index) { const $s = $CSD(step); $s.toggleClass('active', index + 1 === currentStep); $s.toggleClass('completed', index + 1 < currentStep); }); $panels.each(function(panel, index) { $CSD(panel).toggleClass('active', index + 1 === step); }); if ($prevBtn.length) $prevBtn.prop('disabled', currentStep === 1); if ($nextBtn.length) $nextBtn.prop('disabled', currentStep === totalSteps); updateProgress(); } $steps.each(function(step, index) { const $indicator = $CSD(step).find('.csd-step-indicator'); if ($indicator.length) { $indicator.on('click', () => goToStep(index + 1)); } }); if ($prevBtn.length) { $prevBtn.on('click', () => { if (currentStep > 1) goToStep(currentStep - 1); }); } if ($nextBtn.length) { $nextBtn.on('click', () => { if (currentStep < totalSteps) goToStep(currentStep + 1); }); } $CSD(window).on('load', () => { goToStep(1); $CSD(window).on('resize', updateProgress); }); } // Accordion Component function initializeAccordion(element) { if (!element) return; const $element = $CSD(element); const $accordionItems = $element.find('.csd-accordion-item'); const isMultiple = $element.hasClass('multiple'); $accordionItems.each(function(item) { const $item = $CSD(item); const $header = $item.find('.csd-accordion-header'); if ($header.length && !$header.prop('disabled')) { $header.on('click', function() { const $currentItem = $CSD(this).closest('.csd-accordion-item'); if (!isMultiple) { $accordionItems.not($currentItem).removeClass('open'); } $currentItem.toggleClass('open'); }); } }); } // Gestione click globale $CSD(document).on('click', function(e) { const $target = $CSD(e.target); const $dropdownToggle = $target.closest('.csd-dropdown-toggle'); if ($dropdownToggle.length) { e.preventDefault(); const $dropdown = $dropdownToggle.closest('.csd-dropdown'); const $menu = $dropdown.find('.csd-dropdown-menu'); if ($menu.hasClass('show')) { $menu.removeClass('show'); $dropdownToggle.removeClass('active'); } else { closeAllDropdowns(); $menu.addClass('show'); $dropdownToggle.addClass('active'); } return; } const $submenuToggle = $target.closest('.has-submenu > a'); if ($submenuToggle.length) { e.preventDefault(); const $submenuItem = $submenuToggle.parent(); if ($submenuItem.hasClass('open')) { $submenuItem.removeClass('open'); } else { const $siblings = $submenuItem.parent().children(); $siblings.each(function(index, sibling) { const $sibling = $CSD(sibling); if (!$sibling.is($submenuItem) && $sibling.hasClass('has-submenu')) { $sibling.removeClass('open'); } }); $submenuItem.addClass('open'); } return; } if (!$target.closest('.csd-dropdown').length) { closeAllDropdowns(); } }); // Previeni il redirect sui link # che non sono submenu o dropdown $CSD(document).on('click', 'a[href="#"]', function(e) { const $target = $CSD(this); if (!$target.closest('.has-submenu').length && !$target.closest('.csd-dropdown-menu').length) { e.preventDefault(); } }); export { initializeDropdown, initializeSubmenu, initializeSidebar, initializeStepper, initializeAccordion, initializeSegment, initializeTab, initializeMenu, initializeToolbar, closeAllSubmenus, initializeNavigation };