- Implemented comprehensive trainer navigation system:
  * Horizontal and vertical navigation layouts
  * Multi-level menu with dropdowns for Events, Venues, Organizers, Profile
  * Responsive mobile navigation with hamburger menu
  * Keyboard navigation support (Arrow keys, Enter, Escape)
  * Active page highlighting
  * Master trainer menu items for users with appropriate role
- Created breadcrumb system:
  * Automatic breadcrumb generation based on URL structure
  * Shortcode support [hvac_breadcrumbs]
  * SEO-friendly with structured data (Schema.org)
  * Multiple style options (default, pills, arrows)
  * Responsive design
- Technical implementation:
  * HVAC_Trainer_Navigation class for menu management
  * HVAC_Breadcrumbs class for breadcrumb generation
  * CSS for both navigation and breadcrumbs
  * JavaScript for interactive menu behaviors
  * Template part for easy inclusion
Navigation provides easy access to all trainer features and improves UX.
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
		
	
			
		
			
				
	
	
		
			257 lines
		
	
	
		
			No EOL
		
	
	
		
			8.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			257 lines
		
	
	
		
			No EOL
		
	
	
		
			8.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  * HVAC Trainer Navigation JavaScript
 | |
|  *
 | |
|  * @package HVAC_Community_Events
 | |
|  * @version 2.0.0
 | |
|  */
 | |
| 
 | |
| jQuery(document).ready(function($) {
 | |
|     // Cache DOM elements
 | |
|     const $nav = $('.hvac-trainer-nav');
 | |
|     const $mobileToggle = $('.hvac-nav-mobile-toggle');
 | |
|     const $body = $('body');
 | |
|     
 | |
|     // Initialize navigation
 | |
|     function initNavigation() {
 | |
|         // Handle mobile toggle
 | |
|         if ($mobileToggle.length) {
 | |
|             $mobileToggle.on('click', function(e) {
 | |
|                 e.preventDefault();
 | |
|                 toggleMobileNav();
 | |
|             });
 | |
|         }
 | |
|         
 | |
|         // Handle submenu behavior based on data attribute
 | |
|         const submenuBehavior = $nav.data('submenu');
 | |
|         
 | |
|         if (submenuBehavior === 'click') {
 | |
|             initClickSubmenus();
 | |
|         } else if (submenuBehavior === 'hover') {
 | |
|             initHoverSubmenus();
 | |
|         }
 | |
|         
 | |
|         // Handle keyboard navigation
 | |
|         initKeyboardNav();
 | |
|         
 | |
|         // Handle responsive behavior
 | |
|         initResponsive();
 | |
|     }
 | |
|     
 | |
|     // Toggle mobile navigation
 | |
|     function toggleMobileNav() {
 | |
|         $body.toggleClass('hvac-nav-mobile-open');
 | |
|         
 | |
|         // Update aria attributes
 | |
|         const isOpen = $body.hasClass('hvac-nav-mobile-open');
 | |
|         $mobileToggle.attr('aria-expanded', isOpen);
 | |
|         
 | |
|         // Prevent body scroll when mobile nav is open
 | |
|         if (isOpen) {
 | |
|             $body.css('overflow', 'hidden');
 | |
|         } else {
 | |
|             $body.css('overflow', '');
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     // Initialize click-based submenus
 | |
|     function initClickSubmenus() {
 | |
|         $('.hvac-nav-has-submenu > .hvac-nav-link').on('click', function(e) {
 | |
|             const $link = $(this);
 | |
|             const href = $link.attr('href');
 | |
|             
 | |
|             // If link is just '#', prevent default and toggle submenu
 | |
|             if (href === '#') {
 | |
|                 e.preventDefault();
 | |
|                 toggleSubmenu($link.parent());
 | |
|             }
 | |
|         });
 | |
|         
 | |
|         // Close submenus when clicking outside
 | |
|         $(document).on('click', function(e) {
 | |
|             if (!$(e.target).closest('.hvac-nav-has-submenu').length) {
 | |
|                 closeAllSubmenus();
 | |
|             }
 | |
|         });
 | |
|     }
 | |
|     
 | |
|     // Initialize hover-based submenus
 | |
|     function initHoverSubmenus() {
 | |
|         // Add hover intent to prevent accidental triggers
 | |
|         let hoverTimeout;
 | |
|         
 | |
|         $('.hvac-nav-has-submenu').on('mouseenter', function() {
 | |
|             const $item = $(this);
 | |
|             clearTimeout(hoverTimeout);
 | |
|             
 | |
|             hoverTimeout = setTimeout(function() {
 | |
|                 openSubmenu($item);
 | |
|             }, 200);
 | |
|         }).on('mouseleave', function() {
 | |
|             const $item = $(this);
 | |
|             clearTimeout(hoverTimeout);
 | |
|             
 | |
|             hoverTimeout = setTimeout(function() {
 | |
|                 closeSubmenu($item);
 | |
|             }, 300);
 | |
|         });
 | |
|     }
 | |
|     
 | |
|     // Toggle submenu
 | |
|     function toggleSubmenu($item) {
 | |
|         if ($item.hasClass('hvac-nav-open')) {
 | |
|             closeSubmenu($item);
 | |
|         } else {
 | |
|             // Close other submenus first
 | |
|             closeAllSubmenus();
 | |
|             openSubmenu($item);
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     // Open submenu
 | |
|     function openSubmenu($item) {
 | |
|         $item.addClass('hvac-nav-open');
 | |
|         $item.find('.hvac-nav-submenu').stop(true, true).slideDown(200);
 | |
|         
 | |
|         // Update aria attributes
 | |
|         $item.find('> .hvac-nav-link').attr('aria-expanded', 'true');
 | |
|     }
 | |
|     
 | |
|     // Close submenu
 | |
|     function closeSubmenu($item) {
 | |
|         $item.removeClass('hvac-nav-open');
 | |
|         $item.find('.hvac-nav-submenu').stop(true, true).slideUp(200);
 | |
|         
 | |
|         // Update aria attributes
 | |
|         $item.find('> .hvac-nav-link').attr('aria-expanded', 'false');
 | |
|     }
 | |
|     
 | |
|     // Close all submenus
 | |
|     function closeAllSubmenus() {
 | |
|         $('.hvac-nav-has-submenu').each(function() {
 | |
|             closeSubmenu($(this));
 | |
|         });
 | |
|     }
 | |
|     
 | |
|     // Initialize keyboard navigation
 | |
|     function initKeyboardNav() {
 | |
|         $('.hvac-nav-link, .hvac-nav-sublink').on('keydown', function(e) {
 | |
|             const $link = $(this);
 | |
|             const $item = $link.parent();
 | |
|             
 | |
|             switch(e.key) {
 | |
|                 case 'Enter':
 | |
|                 case ' ':
 | |
|                     if ($item.hasClass('hvac-nav-has-submenu') && $link.attr('href') === '#') {
 | |
|                         e.preventDefault();
 | |
|                         toggleSubmenu($item);
 | |
|                     }
 | |
|                     break;
 | |
|                     
 | |
|                 case 'Escape':
 | |
|                     if ($item.closest('.hvac-nav-submenu').length) {
 | |
|                         e.preventDefault();
 | |
|                         const $parentItem = $item.closest('.hvac-nav-has-submenu');
 | |
|                         closeSubmenu($parentItem);
 | |
|                         $parentItem.find('> .hvac-nav-link').focus();
 | |
|                     }
 | |
|                     break;
 | |
|                     
 | |
|                 case 'ArrowDown':
 | |
|                     e.preventDefault();
 | |
|                     focusNextMenuItem($link);
 | |
|                     break;
 | |
|                     
 | |
|                 case 'ArrowUp':
 | |
|                     e.preventDefault();
 | |
|                     focusPrevMenuItem($link);
 | |
|                     break;
 | |
|                     
 | |
|                 case 'ArrowRight':
 | |
|                     if ($item.hasClass('hvac-nav-has-submenu')) {
 | |
|                         e.preventDefault();
 | |
|                         openSubmenu($item);
 | |
|                         $item.find('.hvac-nav-sublink').first().focus();
 | |
|                     }
 | |
|                     break;
 | |
|                     
 | |
|                 case 'ArrowLeft':
 | |
|                     if ($item.closest('.hvac-nav-submenu').length) {
 | |
|                         e.preventDefault();
 | |
|                         const $parentItem = $item.closest('.hvac-nav-has-submenu');
 | |
|                         closeSubmenu($parentItem);
 | |
|                         $parentItem.find('> .hvac-nav-link').focus();
 | |
|                     }
 | |
|                     break;
 | |
|             }
 | |
|         });
 | |
|     }
 | |
|     
 | |
|     // Focus next menu item
 | |
|     function focusNextMenuItem($currentLink) {
 | |
|         const $allLinks = $('.hvac-nav-link:visible, .hvac-nav-sublink:visible');
 | |
|         const currentIndex = $allLinks.index($currentLink);
 | |
|         
 | |
|         if (currentIndex < $allLinks.length - 1) {
 | |
|             $allLinks.eq(currentIndex + 1).focus();
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     // Focus previous menu item
 | |
|     function focusPrevMenuItem($currentLink) {
 | |
|         const $allLinks = $('.hvac-nav-link:visible, .hvac-nav-sublink:visible');
 | |
|         const currentIndex = $allLinks.index($currentLink);
 | |
|         
 | |
|         if (currentIndex > 0) {
 | |
|             $allLinks.eq(currentIndex - 1).focus();
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     // Initialize responsive behavior
 | |
|     function initResponsive() {
 | |
|         let windowWidth = $(window).width();
 | |
|         
 | |
|         $(window).on('resize', function() {
 | |
|             const newWidth = $(window).width();
 | |
|             
 | |
|             // Check if we've crossed the mobile breakpoint
 | |
|             if ((windowWidth > 768 && newWidth <= 768) || (windowWidth <= 768 && newWidth > 768)) {
 | |
|                 // Reset mobile nav state
 | |
|                 $body.removeClass('hvac-nav-mobile-open');
 | |
|                 $body.css('overflow', '');
 | |
|                 closeAllSubmenus();
 | |
|             }
 | |
|             
 | |
|             windowWidth = newWidth;
 | |
|         });
 | |
|     }
 | |
|     
 | |
|     // Highlight current page in navigation
 | |
|     function highlightCurrentPage() {
 | |
|         const currentPath = window.location.pathname;
 | |
|         
 | |
|         // Remove any existing active classes
 | |
|         $('.hvac-nav-active').removeClass('hvac-nav-active');
 | |
|         
 | |
|         // Find matching link
 | |
|         $('.hvac-nav-link, .hvac-nav-sublink').each(function() {
 | |
|             const $link = $(this);
 | |
|             const href = $link.attr('href');
 | |
|             
 | |
|             if (href && href !== '#' && currentPath.indexOf(href) !== -1) {
 | |
|                 $link.parent().addClass('hvac-nav-active');
 | |
|                 
 | |
|                 // If it's a submenu item, also highlight parent
 | |
|                 const $parentItem = $link.closest('.hvac-nav-has-submenu');
 | |
|                 if ($parentItem.length) {
 | |
|                     $parentItem.addClass('hvac-nav-active');
 | |
|                 }
 | |
|             }
 | |
|         });
 | |
|     }
 | |
|     
 | |
|     // Initialize everything
 | |
|     if ($nav.length) {
 | |
|         initNavigation();
 | |
|         highlightCurrentPage();
 | |
|     }
 | |
| }); |