1(function(){ 2 function qs(s,root){ return (root||document).querySelector(s); } 3 var header = qs('#hron-custom-header'); 4 if(!header) return; 5 6 var siteLogo = qs('.hron-site-logo', header); 7 var defaultLogoSrc = 'https://hr-on.com/wp-content/uploads/2025/11/logo-blue.svg'; 8 var whiteLogoSrc = 'https://hr-on.com/wp-content/uploads/2025/11/logo-white.svg'; 9 var lastIsScrolled = null; 10 11 function updateScrolledState(){ 12 var isScrolled = (window.scrollY || window.pageYOffset) > 10; 13 if (isScrolled !== lastIsScrolled) { 14 header.classList.toggle('is-scrolled', isScrolled); 15 if (siteLogo) { 16 siteLogo.setAttribute('src', isScrolled ? whiteLogoSrc : defaultLogoSrc); 17 } 18 lastIsScrolled = isScrolled; 19 } 20 } 21 22 var ticking = false; 23 window.addEventListener('scroll', function(){ 24 if (!ticking) { 25 window.requestAnimationFrame(function(){ 26 updateScrolledState(); 27 ticking = false; 28 }); 29 ticking = true; 30 } 31 }); 32 33 // Initialize scroll state on page load 34 updateScrolledState(); 35 36 // Also check when page is fully loaded, in case initial load scroll position wasn't detected 37 window.addEventListener('load', function() { 38 // Use a small delay to ensure everything is settled 39 setTimeout(updateScrolledState, 100); 40 }); 41 42 // Also check when DOM content is fully loaded 43 if (document.readyState === 'loading') { 44 document.addEventListener('DOMContentLoaded', function() { 45 setTimeout(updateScrolledState, 100); 46 }); 47 } 48 49 // Add a more aggressive check - poll for the first few seconds 50 var checkCount = 0; 51 var maxChecks = 20; // Check for 2 seconds (20 * 100ms) 52 var pollInterval = setInterval(function() { 53 checkCount++; 54 updateScrolledState(); 55 56 if (checkCount >= maxChecks) { 57 clearInterval(pollInterval); 58 } 59 }, 100); 60 61 var toggle = qs('.hron-toggle', header); 62 var menu = qs('#hron-custom-header-menu', header); 63 64 if (toggle && menu) { 65 toggle.addEventListener('click', function(){ 66 var expanded = this.getAttribute('aria-expanded') === 'true'; 67 this.setAttribute('aria-expanded', String(!expanded)); 68 header.classList.toggle('is-open', !expanded); 69 }); 70 71 // use pointerdown instead of click 72 document.addEventListener('pointerdown', function(e){ 73 // only left button (0) and ignore right-clicks (2) 74 if (e.button !== 0) return; 75 if (!header.contains(e.target)) { 76 toggle.setAttribute('aria-expanded', 'false'); 77 header.classList.remove('is-open'); 78 } 79 }); 80 } 81 82 document.addEventListener('keydown', function(e){ 83 if (e.key === 'Escape') { 84 if (toggle) toggle.setAttribute('aria-expanded', 'false'); 85 header.classList.remove('is-open'); 86 var lang = qs('.hron-lang', header); 87 if (lang) { 88 lang.classList.remove('is-open'); 89 var btn = qs('.hron-lang-current', lang); 90 if (btn) btn.setAttribute('aria-expanded', 'false'); 91 } 92 var login = qs('.hron-login', header); 93 if (login) { 94 login.classList.remove('is-open'); 95 var icon = qs('.hron-login-icon', login); 96 if (icon) icon.setAttribute('aria-expanded', 'false'); 97 } 98 } 99 }); 100 101 function setupDropdown(wrapperSelector, btnSelector, iconSelector) { 102 var wrapper = qs(wrapperSelector, header); 103 if (!wrapper) return; 104 var btn = btnSelector ? qs(btnSelector, wrapper) : null; 105 var icon = iconSelector ? qs(iconSelector, wrapper) : null; 106 var timeout; 107 108 if (btn || icon) { 109 wrapper.addEventListener('mouseenter', function(){ 110 clearTimeout(timeout); 111 var other = wrapperSelector === '.hron-lang' ? qs('.hron-login', header) : qs('.hron-lang', header); 112 if (other) { 113 other.classList.remove('is-open'); 114 var otherBtn = qs('.hron-lang-current', other); 115 var otherIcon = qs('.hron-login-icon', other); 116 if (otherBtn) otherBtn.setAttribute('aria-expanded', 'false'); 117 if (otherIcon) otherIcon.setAttribute('aria-expanded', 'false'); 118 } 119 (btn || icon).setAttribute('aria-expanded', 'true'); 120 wrapper.classList.add('is-open'); 121 }); 122 123 wrapper.addEventListener('mouseleave', function(){ 124 timeout = setTimeout(function(){ 125 (btn || icon).setAttribute('aria-expanded', 'false'); 126 wrapper.classList.remove('is-open'); 127 }, 300); 128 }); 129 130 // also use pointerdown here 131 document.addEventListener('pointerdown', function(e){ 132 // Ignore right-clicks (2) and middle clicks (1) 133 if (e.button !== 0) return; 134 if (!wrapper.contains(e.target)) { 135 (btn || icon).setAttribute('aria-expanded', 'false'); 136 wrapper.classList.remove('is-open'); 137 } 138 }); 139 } 140 } 141 142 setupDropdown('.hron-lang', '.hron-lang-current'); 143 setupDropdown('.hron-login', null, '.hron-login-icon'); 144 145 // Prevent right-click from closing mega menus and handle hover states with JS 146 var megaMenuItems = document.querySelectorAll('.hron-custom-item'); 147 var closeTimers = new WeakMap();
148 megaMenuItems.forEach(function(item) { 149 var megaMenu = item.querySelector('.hron-mega'); 150 if (!megaMenu) return; 151 152 // Prevent context menu from closing mega menu 153 item.addEventListener('contextmenu', function(e) { 154 e.preventDefault(); 155 e.stopPropagation(); 156 // Keep the menu open when right-clicking 157 item.classList.add('is-mega-open'); 158 return false; 159 }); 160 161 // Add mouseenter/mouseleave event handlers 162 item.addEventListener('mouseenter', function() { 163 var t = closeTimers.get(item); 164 if (t) { clearTimeout(t); closeTimers.delete(item); } 165 item.classList.add('is-mega-open'); 166 }); 167 168 item.addEventListener('mouseleave', function() { 169 var timer = setTimeout(function(){ 170 item.classList.remove('is-mega-open'); 171 closeTimers.delete(item); 172 }, 180); 173 closeTimers.set(item, timer); 174 }); 175 176 // Keep open when moving over the panel itself 177 megaMenu.addEventListener('mouseenter', function(){ 178 var t = closeTimers.get(item); 179 if (t) { clearTimeout(t); closeTimers.delete(item); } 180 item.classList.add('is-mega-open'); 181 }); 182 megaMenu.addEventListener('mouseleave', function(){ 183 var timer = setTimeout(function(){ 184 item.classList.remove('is-mega-open'); 185 closeTimers.delete(item); 186 }, 180); 187 closeTimers.set(item, timer); 188 }); 189 }); 190 191 // Prevent right-click event bubbling on mega menu items 192 document.querySelectorAll('.hron-mega, .hron-mega *').forEach(function(element) { 193 element.addEventListener('contextmenu', function(e) { 194 e.preventDefault(); 195 e.stopPropagation(); 196 197 // Find the parent menu item and keep it open 198 var menuItem = element.closest('.hron-custom-item'); 199 if (menuItem) { 200 menuItem.classList.add('is-mega-open'); 201 } 202 203 return false; 204 }); 205 }); 206 207 // Handle submenus separately 208 document.querySelectorAll('.hron-submenu').forEach(function(submenu) { 209 submenu.addEventListener('mouseenter', function() { 210 this.classList.add('is-open'); 211 }); 212 213 submenu.addEventListener('mouseleave', function() { 214 this.classList.remove('is-open'); 215 }); 216 217 submenu.addEventListener('contextmenu', function(e) { 218 e.preventDefault(); 219 e.stopPropagation(); 220 this.classList.add('is-open'); 221 return false; 222 }); 223 224 // Handle clicks on submenu toggles 225 var toggle = submenu.querySelector('.hron-submenu-toggle'); 226 if (toggle) { 227 toggle.addEventListener('contextmenu', function(e) { 228 e.preventDefault(); 229 e.stopPropagation(); 230 submenu.classList.add('is-open'); 231 return false; 232 }); 233 } 234 }); 235 236 // Handle add-on links to improve interaction 237 document.querySelectorAll('.hron-mega-list a, .hron-addon-content').forEach(function(link) { 238 link.addEventListener('click', function(e) { 239 // Allow the click to proceed to the link's href 240 // but prevent it from immediately closing the mega menu 241 e.stopPropagation(); 242 }); 243 244 // Add hover persistence for better UX 245 link.addEventListener('mouseenter', function() { 246 var menuItem = this.closest('.hron-custom-item'); 247 if (menuItem) { 248 menuItem.classList.add('is-mega-open'); 249 menuItem.classList.add('hover-persistent'); 250 } 251 }); 252 }); 253 254 function initKunderCarousel() { 255 var reviewCard = qs('.kunder-review-card', header); 256 if (!reviewCard) return; 257 258 var reviewItems = reviewCard.querySelectorAll('.krc-review-item'); 259 var dots = reviewCard.querySelectorAll('.krc-dots i'); 260 if (reviewItems.length === 0 || dots.length === 0) return; 261 262 var currentIndex = 0; 263 var autoSlideInterval = null; 264 var isHovered = false; 265 266 function setActiveReview(index) { 267 if (index < 0 || index >= reviewItems.length) return; 268 269 reviewItems.forEach(function(item, i) { 270 item.classList.toggle('active', i === index); 271 }); 272 273 dots.forEach(function(dot, i) { 274 dot.classList.toggle('active', i === index); 275 }); 276 277 var activeItem = reviewItems[index]; 278 var reviewType = activeItem.getAttribute('data-review'); 279 reviewCard.setAttribute('data-review', reviewType); 280 281 var bgColor = '#0B5FFF'; 282 var borderColor = 'rgba(11,95,255,0.2)'; 283 284 if (reviewType === 'staff') { 285 bgColor = '#FF7000'; 286 borderColor = 'rgba(255,112,0,0.3)'; 287 } else if (reviewType === 'wellbeing') { 288 bgColor = '#00A37A'; 289 borderColor = 'rgba(0,163,122,0.3)'; 290 } else if (reviewType === 'boarding') { 291 bgColor = '#FF9F00'; 292 borderColor = 'rgba(255,159,0,0.3)'; 293 } 294 295 reviewCard.style.background = bgColor; 296 reviewCard.style.borderColor = borderColor; 297 298 currentIndex = index; 299 } 300 301 function nextReview() { 302 if (isHovered) return; 303 var nextIndex = (currentIndex + 1) % reviewItems.length; 304 setActiveReview(nextIndex); 305 } 306 307 function startAutoSlide() { 308 if (autoSlideInterval) clearInterval(autoSlideInterval); 309 autoSlideInterval = setInterval(nextReview, 5000); 310 } 311 312 function stopAutoSlide() { 313 if (autoSlideInterval) { 314 clearInterval(autoSlideInterval); 315 autoSlideInterval = null; 316 } 317 } 318
319 dots.forEach(function(dot, index) { 320 dot.addEventListener('click', function() { 321 setActiveReview(index); 322 stopAutoSlide(); 323 setTimeout(startAutoSlide, 3000); 324 }); 325 }); 326 327 reviewCard.addEventListener('mouseenter', function() { 328 isHovered = true; 329 stopAutoSlide(); 330 }); 331 332 reviewCard.addEventListener('mouseleave', function() { 333 isHovered = false; 334 startAutoSlide(); 335 }); 336 337 startAutoSlide(); 338 } 339 340 initKunderCarousel(); 341 342 // Office hours status indicator 343 function initOfficeHoursStatus() { 344 var statusIndicator = qs('#hron-status-indicator', header); 345 if (!statusIndicator) return; 346 347 function checkOfficeHours() { 348 // Get current time in Europe/Copenhagen timezone 349 var now = new Date(); 350 var copenhagenDate = new Date(now.toLocaleString("en-US", {timeZone: "Europe/Copenhagen"})); 351 var day = copenhagenDate.getDay(); // 0 = Sunday, 1 = Monday, ..., 5 = Friday, 6 = Saturday 352 var hour = copenhagenDate.getHours(); 353 var minute = copenhagenDate.getMinutes(); 354 var currentTime = hour * 60 + minute; // Convert to minutes for easier comparison 355 356 // Office hours: Monday (1) to Friday (5), 9 AM (540 minutes) to 3 PM (900 minutes) 357 // 3 PM = 15:00 = 900 minutes, but we check < 900 to exclude 3 PM exactly 358 var isOpen = (day >= 1 && day <= 5) && (currentTime >= 540 && currentTime < 900); 359 360 if (isOpen) { 361 statusIndicator.classList.add('is-open'); 362 } else { 363 statusIndicator.classList.remove('is-open'); 364 } 365 } 366 367 // Check immediately 368 checkOfficeHours(); 369 370 // Check every minute to update status in real-time 371 setInterval(checkOfficeHours, 60000); 372 373 // Also check when page becomes visible (user switches tabs) 374 document.addEventListener('visibilitychange', function() { 375 if (!document.hidden) { 376 checkOfficeHours(); 377 } 378 }); 379 } 380 381 initOfficeHoursStatus(); 382 383})();
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.