1/* THIS JS WAS COMPILED AND OPTIMIZED, USING THE WP COMPILER PLUGIN */ 2/* https://bytes.co */ 3/* Last Compiled: 2023-03-14 11:12:34 UTC */ 4 5/* @@ START FILE: comments.js*/ 6jQuery(document).ready(function($) { 7 var form_validation = $(".comment-form-url input, .comment-form-author input, .comment-form-email input, .comment-form-comment textarea"); 8 $(form_validation).blur(function() { 9 if (!$(this).val()) { 10 $(this).parent().removeClass("keydesign-not-empty"); 11 } else { 12 $(this).parent().addClass("keydesign-not-empty"); 13 } 14 }); 15 var contact_form = $(".keydesign-label input, .keydesign-label textarea"); 16 $(contact_form).blur(function() { 17 if (!$(this).val()) { 18 $(this).closest(".keydesign-label").removeClass("keydesign-not-empty"); 19 } else { 20 $(this).closest(".keydesign-label").addClass("keydesign-not-empty"); 21 } 22 }); 23 24}); 25/* @@ END FILE: comments.js*/ 26 27; 28 29/* @@ START FILE: navigation.js*/ 30/** 31 * @Author: Roni Laukkarinen 32 * @Date: 2021-04-23 13:10:51 33 * @Last Modified by: Roni Laukkarinen 34 * @Last Modified time: 2022-05-12 15:10:04 35 */ 36// TODO: Refactor file 37/* eslint-disable default-case, camelcase, eqeqeq, no-restricted-globals, no-undef, no-var, vars-on-top, max-len, prefer-destructuring, no-redeclare, no-plusplus, no-use-before-define, no-unused-vars, block-scoped-var, func-names */ 38/* 39An accessible menu for WordPress 40 41https://github.com/theme-smith/accessible-nav-wp 42Kirsten Smith ([email protected]) 43Licensed GPL v.2 (http://www.gnu.org/licenses/gpl-2.0.html) 44 45This work derived from: 46https://github.com/WordPress/twentysixteen (GPL v.2) 47https://github.com/wpaccessibility/a11ythemepatterns/tree/master/menu-keyboard-arrow-nav (GPL v.2) 48*/ 49 50/*! 51 * Check if an element is out of the viewport 52 * (c) 2018 Chris Ferdinandi, MIT License, https://gomakethings.com 53 * @param {Node} elem The element to check 54 * @return {Object} A set of booleans for each side of the element 55 * @source https://gomakethings.com/how-to-check-if-any-part-of-an-element-is-out-of-the-viewport-with-vanilla-js/ 56 */ 57var isOutOfViewport = function(elem) { 58 // Get element's bounding 59 var bounding = elem.getBoundingClientRect(); 60 61 // Check if it's out of the viewport on each side 62 var out = {}; 63 out.top = bounding.top < 0; 64 out.left = bounding.left < 0; 65 out.bottom = bounding.bottom > (window.innerHeight || document.documentElement.clientHeight); 66 out.right = bounding.right > (window.innerWidth || document.documentElement.clientWidth); 67 out.any = out.top || out.left || out.bottom || out.right; 68 69 return out; 70}; 71 72// Navigation.js start 73(function($) { 74 // Responsive nav width 75 var responsivenav = 1025; 76 var html; 77 var body; 78 var container; 79 var button; 80 var menu; 81 var menuWrapper; 82 var links; 83 var subMenus; 84 var i; 85 var len; 86 var focusableElements; 87 var firstFocusableElement; 88 var lastFocusableElement; 89 90 // Hover intent 91 const menuItems = document.querySelectorAll('.menu-item'); 92 // const hoverIntentTimeout = 1000; 93 94 menuItems.forEach((li) => { 95 li.addEventListener('mouseover', function() { 96 this.classList.add('hover-intent'); 97 this.parentNode.classList.add('hover-intent'); 98 99 document.addEventListener('keydown', (keydownMouseoverEvent) => { 100 if (keydownMouseoverEvent.key === 'Escape') { 101 li.classList.remove('hover-intent'); 102 li.parentNode.classList.remove('hover-intent'); 103 li.parentNode.parentNode.classList.remove('hover-intent'); 104 } 105 }); 106 }); 107 108 li.addEventListener('mouseleave', function() { 109 // setTimeout(() => { 110 this.classList.remove('hover-intent'); 111 this.parentNode.classList.remove('hover-intent'); 112 // }, hoverIntentTimeout); 113 114 document.addEventListener('keydown', (keydownMouseleaveEvent) => { 115 if (keydownMouseleaveEvent.key === 'Escape') { 116 li.classList.remove('hover-intent'); 117 li.parentNode.classList.remove('hover-intent'); 118 li.parentNode.parentNode.classList.remove('hover-intent'); 119 } 120 }); 121 }); 122 });
123 124 // Init isOut check 125 checkForSubmenuOverflow(); 126 127 function checkForSubmenuOverflow() { 128 menuItems.forEach((li) => { 129 // Find sub menus 130 var subMenusUnderMenuItem = li.querySelectorAll('.sub-menu'); 131 132 // Loop through sub menus 133 subMenusUnderMenuItem.forEach((subMenu) => { 134 // First let's check if submenu exists 135 if (typeof subMenusUnderMenuItem !== 'undefined') { 136 // Check if the sub menu is out of viewport or not 137 var isOut = isOutOfViewport(subMenu); 138 139 // At least one side of the element is out of viewport 140 if (isOut.right) { 141 subMenu.classList.add('is-out-of-viewport'); 142 subMenu.parentElement.parentElement.classList.add('is-out-of-viewport'); 143 } else { 144 subMenu.classList.remove('is-out-of-viewport'); 145 subMenu.parentElement.parentElement.classList.remove('is-out-of-viewport'); 146 } 147 } 148 }); 149 }); 150 } 151 152 // Reinit viewport check on resize event 153 window.addEventListener('resize', checkForSubmenuOverflow); 154 155 // Define menu items 156 var menuContainer = $('.nav-container'); 157 var menuToggle = menuContainer.find('#nav-toggle'); 158 var siteHeaderMenu = menuContainer.find('#main-navigation-wrapper'); 159 var siteNavigation = menuContainer.find('#nav'); 160 161 var screenReaderText = { "expand": "Expand child menu", "collapse": "Collapse child menu" }; 162 163 // Close focused dropdowns when pressing esc 164 $('.menu-item a, .dropdown button').on('keyup', function(e) { 165 // Checking are menu items open or not 166 const isSubMenuDropdownOpen = $(this).parent().parent().parent() 167 .find('.sub-menu') 168 .prev('.dropdown-toggle') 169 .attr('aria-expanded'); 170 const isMainMenuDropdownOpen = $(this).closest('.menu-item').find('.dropdown-toggle').attr('aria-expanded'); 171 const areWeInDropdown = $(this).parent().parent().hasClass('sub-menu'); 172 173 if (isSubMenuDropdownOpen === 'true' || isMainMenuDropdownOpen === 'true') { 174 if ($('.dropdown').find(':focus').length !== 0) { 175 // Close menu using Esc key but only if dropdown is open 176 if (e.code === 'Escape') { 177 // Close the dropdown menu 178 var thisDropdown = $(this).parent().parent().parent(); 179 180 var screenReaderSpan = thisDropdown.find('.screen-reader-text'); 181 var dropdownToggle = thisDropdown.find('.dropdown-toggle'); 182 thisDropdown.find('.sub-menu').removeClass('toggled-on'); 183 thisDropdown.find('.dropdown-toggle').removeClass('toggled-on'); 184 thisDropdown.find('.dropdown').removeClass('toggled-on'); 185 dropdownToggle.attr('aria-expanded', 'false'); 186 // jscs:enable 187 screenReaderSpan.text(screenReaderText.expand); 188 // Move focus back to previous dropdown select 189 // But only if we are not already in the toggle of the first dropdown menu 190 if (areWeInDropdown === true) { 191 thisDropdown.find('.dropdown-toggle:first').trigger('focus'); 192 } 193 } 194 } 195 } 196 197 if (window.innerWidth > responsivenav) { 198 // Close previous dropdown if we are on main level 199 var prevDropdown = $(this).parent().prev(); 200 201 var screenReaderSpanPrev = prevDropdown.find('.screen-reader-text'); 202 var dropdownTogglePrev = prevDropdown.find('.dropdown-toggle'); 203 prevDropdown.find('.sub-menu').removeClass('toggled-on'); 204 prevDropdown.find('.dropdown-toggle').removeClass('toggled-on'); 205 prevDropdown.find('.dropdown').removeClass('toggled-on'); 206 dropdownTogglePrev.attr('aria-expanded', 'false'); 207 screenReaderSpanPrev.text(screenReaderText.expand); 208 209 // Close next dropdown if we are on main level 210 var nextDropdown = $(this).parent().next(); 211 212 var screenReaderSpanNext = nextDropdown.find('.screen-reader-text'); 213 var dropdownToggleNext = nextDropdown.find('.dropdown-toggle'); 214 nextDropdown.find('.sub-menu').removeClass('toggled-on'); 215 nextDropdown.find('.dropdown-toggle').removeClass('toggled-on'); 216 nextDropdown.find('.dropdown').removeClass('toggled-on'); 217 dropdownToggleNext.attr('aria-expanded', 'false'); 218 screenReaderSpanNext.text(screenReaderText.expand); 219 } 220 });
221 222 // Adds aria attribute 223 siteHeaderMenu.find('.menu-item-has-children').attr('aria-haspopup', 'true'); 224 225 // Add default dropdown-toggle label 226 $('.dropdown-toggle').each(function() { 227 $(this).attr('aria-label', `${screenReaderText.expand_for} ${$(this).prev().text()}`); 228 }); 229 230 // Toggles the sub-menu when dropdown toggle button accessed 231 siteHeaderMenu.find('.dropdown-toggle').on('click', function(e) { 232 var dropdownMenu = $(this).nextAll('.sub-menu'); 233 234 $(this).toggleClass('toggled-on'); 235 dropdownMenu.toggleClass('toggled-on'); 236 237 // jscs:disable 238 $(this).attr( 239 'aria-expanded', 240 $(this).attr('aria-expanded') === 'false' ? 'true' : 'false', 241 ); 242 // jscs:enable 243 // Change screen reader open/close labels 244 245 $(this).attr( 246 'aria-label', 247 $(this).attr('aria-label') === `${screenReaderText.collapse_for} ${$(this).prev().text()}` ? 248 `${screenReaderText.expand_for} ${$(this).prev().text()}` : 249 `${screenReaderText.collapse_for} ${$(this).prev().text()}`, 250 ); 251 }); 252 253 // Adds a class to sub-menus for styling 254 $('.sub-menu .menu-item-has-children') 255 .parent('.sub-menu') 256 .addClass('has-sub-menu'); 257 258 // Keyboard navigation 259 $('.menu-item a, button.dropdown-toggle').on('keydown', function(e) { 260 if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].indexOf(e.code) == -1) { 261 return; 262 } 263 264 switch (e.code) { 265 case 'ArrowLeft': // Left key 266 e.stopPropagation(); 267 268 if ($(this).hasClass('dropdown-toggle')) { 269 $(this).prev('a').trigger('focus'); 270 } else if ( 271 $(this).parent().prev().children('button.dropdown-toggle').length 272 ) { 273 $(this).parent().prev().children('button.dropdown-toggle') 274 .trigger('focus'); 275 } else { 276 $(this).parent().prev().children('a') 277 .trigger('focus'); 278 } 279 280 if ($(this).is('ul ul ul.sub-menu.toggled-on li:first-child a')) { 281 $(this) 282 .parents('ul.sub-menu.toggled-on li') 283 .children('button.dropdown-toggle') 284 .trigger('focus'); 285 } 286 287 break; 288 289 case 'ArrowRight': // Right key 290 e.stopPropagation(); 291 292 if ($(this).next('button.dropdown-toggle').length) { 293 $(this).next('button.dropdown-toggle').trigger('focus'); 294 } else if ($(this).parent().next().find('input').length) { 295 $(this).parent().next().find('input') 296 .trigger('focus'); 297 } else { 298 $(this).parent().next().children('a') 299 .trigger('focus'); 300 } 301 302 if ($(this).is('ul.sub-menu .dropdown-toggle.toggled-on')) { 303 $(this).parent().find('ul.sub-menu li:first-child a').trigger('focus'); 304 } 305 306 break; 307 308 case 'ArrowDown': // Down key 309 e.stopPropagation(); 310 311 if ($(this).next().length) { 312 $(this).next().find('li:first-child a').first() 313 .trigger('focus'); 314 } else if ($(this).parent().next().find('input').length) { 315 $(this).parent().next().find('input') 316 .trigger('focus'); 317 } else { 318 $(this).parent().next().children('a') 319 .trigger('focus'); 320 } 321 322 if ( 323 $(this).is('ul.sub-menu a') && 324 $(this).next('button.dropdown-toggle').length 325 ) { 326 $(this).parent().next().children('a') 327 .trigger('focus'); 328 } 329 330 if ( 331 $(this).is('ul.sub-menu .dropdown-toggle') && 332 $(this).parent().next().children('.dropdown-toggle').length 333 ) { 334 $(this).parent().next().children('.dropdown-toggle') 335 .trigger('focus'); 336 } 337 338 break; 339 340 case 'ArrowUp': // Up key 341 e.stopPropagation(); 342 343 if ($(this).parent().prev().length) { 344 $(this).parent().prev().children('a') 345 .trigger('focus'); 346 } else { 347 $(this) 348 .parents('ul') 349 .first() 350 .prev('.dropdown-toggle.toggled-on') 351 .trigger('focus'); 352 } 353 354 if ( 355 $(this).is('ul.sub-menu .dropdown-toggle') && 356 $(this).parent().prev().children('.dropdown-toggle').length 357 ) { 358 $(this).parent().prev().children('.dropdown-toggle') 359 .trigger('focus'); 360 } 361 362 break; 363 } 364 });
365 366 container = document.getElementById('nav'); 367 if (!container) { 368 return; 369 } 370 371 button = document.getElementById('nav-toggle'); 372 if (typeof button === 'undefined') { 373 return; 374 } 375 376 // Set vars. 377 html = document.getElementsByTagName('html')[0]; 378 body = document.getElementsByTagName('body')[0]; 379 menu = container.getElementsByTagName('ul')[0]; 380 menuWrapper = document.getElementById('main-navigation-wrapper'); 381 382 function mobileNav() { 383 var mobileNavInstance; 384 385 // Toggles the menu button 386 if (!menuToggle.length) { 387 return; 388 } 389 390 // Do not set aria-expanded false on desktop 391 if (window.innerWidth < responsivenav) { 392 menuToggle.add(siteNavigation).attr('aria-expanded', 'false'); 393 } 394 395 menuToggle.on('click', function() { 396 $(this).add(siteHeaderMenu).toggleClass('toggled-on'); 397 398 // Change screen reader expanded state 399 $(this).attr( 400 'aria-expanded', 401 $(this).attr('aria-expanded') === 'false' ? 'true' : 'false', 402 ); 403 404 // Change screen reader open/close labels 405 $('#nav-toggle-label').text( 406 // eslint-disable-next-line no-undef 407 $('#nav-toggle-label').text() === screenReaderText.expand_toggle ? 408 screenReaderText.collapse_toggle : 409 screenReaderText.expand_toggle, 410 ); 411 412 $(this).attr( 413 'aria-label', 414 $(this).attr('aria-label') === screenReaderText.expand_toggle ? 415 screenReaderText.collapse_toggle : 416 screenReaderText.expand_toggle, 417 ); 418 419 // jscs:disable 420 $(this) 421 .add(siteNavigation) 422 .attr( 423 'aria-expanded', 424 $(this).add(siteNavigation).attr('aria-expanded') === 'false' ? 425 'true' : 426 'false', 427 ); 428 429 // Scroll to top when triggering mobile navigation 430 // to ensure no gaps are between header and navigation 431 // Please note, if you use sticky-nav, comment out the next line 432 window.scrollTo(0, 0); 433 // jscs:enable 434 }); 435 436 // Hide menu toggle button if menu is empty and return early. 437 if (typeof menu === 'undefined') { 438 button.style.display = 'none'; 439 return; 440 } 441 442 // Do not set aria-expanded false on desktop 443 if (window.innerWidth < responsivenav) { 444 menu.setAttribute('aria-expanded', 'false'); 445 } 446
447 if (menu.className.indexOf('nav-menu') === -1) { 448 menu.className += ' nav-menu'; 449 } 450 451 // Focus trap for mobile navigation 452 if (window.innerWidth < responsivenav) { 453 firstFocusableElement = null; 454 lastFocusableElement = null; 455 456 // Select nav items 457 var navElements = container.querySelectorAll([ 458 '.nav-primary a[href]', 459 '.nav-primary button', 460 ]); 461 462 // Listen for key events on nav elements and the toggle button 463 // to trigger focus trap 464 for (var ii = 0; ii < navElements.length; ii++) { 465 navElements[ii].addEventListener('keydown', focusTrap); 466 } 467 } 468 469 // What happens when clicking menu toggle 470 button.onclick = function() { 471 if (container.className.indexOf('is-active') !== -1) { 472 closeMenu(); // Close menu. 473 } else { 474 html.className += ' disable-scroll'; 475 body.className += ' js-nav-active'; 476 container.className += ' is-active'; 477 button.className += ' is-active'; 478 button.setAttribute('aria-expanded', 'true'); 479 menu.setAttribute('aria-expanded', 'true'); 480 481 // Add focus trap when menu open 482 button.addEventListener('keydown', focusTrap, false); 483 } 484 }; 485 486 // Close menu using Esc key. 487 document.addEventListener('keyup', (event) => { 488 if (event.code == 'Escape' || event.code == 'Esc') { 489 if (container.className.indexOf('is-active') !== -1) { 490 closeMenu(); // Close menu. 491 } 492 } 493 }); 494 495 // Close menu clicking menu wrapper area. 496 menuWrapper.onclick = function(e) { 497 if ( 498 e.target == menuWrapper && 499 container.className.indexOf('is-active') !== -1 500 ) { 501 closeMenu(); // Close menu. 502 } 503 }; 504 } 505 if (window.innerWidth < responsivenav) { 506 mobileNav(); // fire right away for mobile devices 507 } 508 509 // Close menu function. 510 function closeMenu() { 511 button.removeEventListener('keydown', focusTrap, false); 512 html.className = html.className.replace(' disable-scroll', ''); 513 body.className = body.className.replace(' js-nav-active', ''); 514 container.className = container.className.replace(' is-active', ''); 515 button.className = button.className.replace(' is-active', ''); 516 button.setAttribute('aria-expanded', 'false'); 517 menu.setAttribute('aria-expanded', 'false'); 518 $('#nav-toggle-label').text(screenReaderText.expand_toggle); 519 520 // Return focus to nav-toggle 521 button.focus(); 522 } 523 524 // Get all the link elements within the menu. 525 links = menu.getElementsByTagName('a'); 526 subMenus = menu.getElementsByTagName('ul'); 527 528 // Each time a menu link is focused or blurred, toggle focus. 529 for (i = 0, len = links.length; i < len; i++) { 530 links[i].addEventListener('focus', toggleFocus, true); 531 links[i].addEventListener('blur', toggleFocus, true); 532 } 533 534 /** 535 * Sets or removes .focus class on an element. 536 */ 537 function toggleFocus() { 538 var self = this; 539 540 // Move up through the ancestors of the current link until we hit .nav-menu.
541 while (self.className.indexOf('nav-menu') === -1) { 542 // On li elements toggle the class .focus. 543 if (self.tagName.toLowerCase() === 'li') { 544 if (self.className.indexOf('focus') !== -1) { 545 self.className = self.className.replace(' focus', ''); 546 } else { 547 self.className += ' focus'; 548 } 549 } 550 551 self = self.parentElement; 552 } 553 } 554 555 function focusTrap(e) { 556 // Set focusable elements inside main navigation. 557 focusableElements = [...container.querySelectorAll( 558 'a, button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])', 559 )].filter((el) => !el.hasAttribute('disabled')).filter((el) => !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length)); 560 561 firstFocusableElement = focusableElements[0]; 562 lastFocusableElement = focusableElements[focusableElements.length - 1]; 563 564 // Redirect last Tab to first focusable element. 565 if (lastFocusableElement === e.target && e.code === 'Tab' && !e.shiftKey) { 566 button.focus(); // Set focus on first element - that's actually close menu button. 567 } 568 569 // Redirect first Shift+Tab to toggle button element. 570 if (firstFocusableElement === e.target && e.code === 'Tab' && e.shiftKey) { 571 button.focus(); // Set focus on last element. 572 } 573 574 // Redirect Shift+Tab from the toggle button to last focusable element. 575 if (button === e.target && e.code === 'Tab' && e.shiftKey) { 576 lastFocusableElement.focus(); // Set focus on last element. 577 } 578 } 579 580 $(window).on('resize', () => { 581 if (window.innerWidth > responsivenav && body.className.indexOf('js-nav-active') !== -1) { 582 closeMenu(); // Close menu. 583 } else if (window.innerWidth < responsivenav && typeof window.mobileNavInstance == 'undefined') { 584 mobileNav(); 585 } 586 }); 587}(jQuery)); 588 589/* @@ END FILE: navigation.js*/
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.