1(function($) { "use strict"; 2 3document.addEventListener('DOMContentLoaded', function () { 4 var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')) 5 var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) { 6 return new bootstrap.Tooltip(tooltipTriggerEl) 7 }) 8}); 9 10jQuery(document).ready(function($) { 11 12$('body').addClass('loaded'); 13 14flyoutMenuToggle(); 15flyoutMenuSubMenus(); 16externalLinks(); 17contentAjax(); 18loadHeroBackground(); 19accountMenu(); 20addNavPills(); 21 22 23}); 24 25function flyoutMenuToggle() { 26 const $navToggle = $(".nav-toggle"); 27 const $flyoutMenu = $("nav.flyout-menu"); 28 29 // Toggle menu on button click 30 $(".nav-toggle, .flyout-menu .close-btn").on("click", function (e) { 31 e.stopPropagation(); // Prevent the click from bubbling up 32 $navToggle.toggleClass("active"); 33 $flyoutMenu.toggleClass("active"); 34 }); 35 36 // Close menu if clicking outside 37 $(document).on("click", function (e) { 38 if (!$flyoutMenu.is(e.target) && $flyoutMenu.has(e.target).length === 0 && 39 !$navToggle.is(e.target) && $navToggle.has(e.target).length === 0) { 40 // Remove active classes 41 $navToggle.removeClass("active"); 42 $flyoutMenu.removeClass("active"); 43 } 44 }); 45} 46 47function flyoutMenuSubMenus() { 48 49 50 const menuItems = document.querySelectorAll(".flyout-menu .menu > li"); 51 52 menuItems.forEach((item) => { 53 const subMenu = item.querySelector(".sub-menu"); 54 55 if (subMenu) { 56 // Create toggle button 57 const toggleBtn = document.createElement("button"); 58 toggleBtn.classList.add("submenu-toggle"); 59 toggleBtn.setAttribute("aria-label", "Toggle submenu"); 60 toggleBtn.innerHTML = ` 61 <svg class="caret-icon" width="16" height="16" viewBox="0 0 24 24"> 62 <path d="M6 9l6 6 6-6" fill="none" stroke="currentColor" stroke-width="2"/> 63 </svg> 64 `; 65
66 // Append toggle button after the anchor link 67 const link = item.querySelector("a"); 68 link.after(toggleBtn); 69 70 // Toggle logic 71 toggleBtn.addEventListener("click", function () { 72 subMenu.classList.toggle("active"); 73 this.classList.toggle("open"); 74 // Swap the icon direction 75 this.querySelector("path").setAttribute( 76 "d", 77 subMenu.classList.contains("active") 78 ? "M6 15l6-6 6 6" // up 79 : "M6 9l6 6 6-6" // down 80 ); 81 }); 82 } 83 }); 84 85 86} 87 88 89function externalLinks() { 90 91 const links = document.querySelectorAll('a[href^="http"]'); 92 links.forEach(function (link) { 93 // Only apply to external links 94 if (link.hostname !== window.location.hostname) { 95 link.setAttribute('target', '_blank'); 96 link.setAttribute('rel', 'noopener noreferrer'); 97 } 98 }); 99 100} 101 102function loadHeroBackground() { 103 104 const imageUrl = document.getElementById('background-image')?.value; 105 106 if (imageUrl) { 107 const bg = document.createElement('div'); 108 bg.className = 'background-image'; 109 bg.style.backgroundImage = `url('${imageUrl}')`; 110 111 const heroContainer = document.querySelector('.page-hero'); 112 113 if (heroContainer) { 114 // Calculate total height including padding 115 const computedStyle = window.getComputedStyle(heroContainer); 116 const height = heroContainer.offsetHeight; 117 const paddingTop = parseFloat(computedStyle.paddingTop); 118 const paddingBottom = parseFloat(computedStyle.paddingBottom); 119 const totalHeight = height + paddingTop + paddingBottom; 120 121 bg.style.height = `${totalHeight}px`; 122 123 // Insert background before other content 124 heroContainer.insertBefore(bg, heroContainer.firstChild); 125 126 // Trigger fade-in after a tiny delay to allow initial render 127 requestAnimationFrame(() => { 128 bg.classList.add('visible'); 129 }); 130 } 131 } 132 133} 134 135 136 137function accountMenu() { 138 $(".account-menu .trigger").on("click", function(e) { 139 e.stopPropagation(); 140 $(this).toggleClass("active"); 141 $(".account-menu nav").toggleClass("active"); 142 }); 143 144 $(document).on("click", function(e) { 145 if (!$(e.target).closest(".account-menu").length) { 146 $(".account-menu .trigger").removeClass("active"); 147 $(".account-menu nav").removeClass("active"); 148 } 149 }); 150} 151 152 153 154function addNavPills() { 155 // Check if WordPress output the logged-in body class 156 const isLoggedIn = document.body.classList.contains('logged-in'); 157 158 // Define the menu items 159 const items = [ 160 { text: 'Home', href: '/', activeOn: ['page-id-1663'] }, 161 { 162 text: 'Courses', 163 href: isLoggedIn ? '/my-courses' : '/hernia-a-to-z-fundamentals/', // <-- Swaps based on body class 164 activeOn: ['page-id-43868'] 165 }, 166 { text: 'Upcoming Events', href: '/events', activeOn: ['page-id-994'] }, 167 { text: 'Videos', href: '/videos', activeOn: ['page-id-43873'] }, 168 { text: 'Lectures', href: '/lectures', activeOn: ['page-id-12106'] }, 169 { text: 'IHS', href: '/ihs', activeOn: ['page-id-44114'] }, 170 { text: 'Podcasts', href: '/podcast', activeOn: ['page-id-44428'] } 171 ]; 172 173 // Create the main nav container 174 const navDiv = document.createElement('div'); 175 navDiv.className = 'nav-pills alt'; 176 177 const ul = document.createElement('ul'); 178 179 // Loop through items and build each <li> 180 items.forEach(item => { 181 const li = document.createElement('li'); 182 183 // Check if any of the "activeOn" classes are present on <body> 184 const isActive = item.activeOn.some(cls => document.body.classList.contains(cls)); 185 if (isActive) { 186 li.classList.add('active'); 187 } 188 189 const a = document.createElement('a'); 190 a.href = item.href; 191 a.textContent = item.text; 192 193 li.appendChild(a); 194 ul.appendChild(li); 195 }); 196 197 navDiv.appendChild(ul); 198 199 const wrapperDiv = document.createElement('div'); 200 wrapperDiv.className = 'sub-nav-menu'; 201 202 wrapperDiv.appendChild(navDiv); 203 204 // Prepend to .entry-content .wp-block-group.container 205 const entryContent = document.querySelector('.entry-content .wp-block-group.container'); 206 if (entryContent) {
207 entryContent.prepend(wrapperDiv); 208 } 209} 210 211 212function contentAjax() { 213 214 jQuery(document).on('click', '.load-more', function() { 215 var button = jQuery(this); 216 217 var page = parseInt(button.attr('data-current-page')) + 1; 218 var max = parseInt(button.attr('data-max-pages')); 219 var type = button.data('post-type'); 220 var per = button.data('posts-per-page'); 221 var tax = button.data('taxonomy'); 222 var term = button.data('term'); 223 var sortby = button.data('sort'); 224 225 jQuery.ajax({ 226 url: ajax_loadmore_params.ajaxurl, 227 type: 'POST', 228 data: { 229 action: 'loadmore_posts', 230 page: page, 231 post_type: type, 232 posts_per_page: per, 233 taxonomy: tax, 234 term: term, 235 sort_by: sortby 236 }, 237 beforeSend: function() { 238 button.text('Loading...'); 239 }, 240 success: function(data) { 241 if (data) { 242 button.text('Load More'); 243 button.attr('data-current-page', page); 244 jQuery('.grid-posts').append(data); 245 246 if (page >= max) { 247 button.remove(); 248 } 249 } else { 250 button.remove(); 251 } 252 } 253 }); 254 }); 255 256} 257 258 259 260})(jQuery); 261 262
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.