1var sparklethemes = sparklethemes || {}; 2 3// Set a default value for scrolled. 4sparklethemes.scrolled = 0; 5 6// event "polyfill" 7sparklethemes.createEvent = function( eventName ) { 8 var event; 9 if ( typeof window.Event === 'function' ) { 10 event = new Event( eventName ); 11 } else { 12 event = document.createEvent( 'Event' ); 13 event.initEvent( eventName, true, false ); 14 } 15 return event; 16}; 17 18/***** 19 * Cover Modals 20*/ 21sparklethemes.coverModals = { 22 23 init: function() { 24 if ( document.querySelector( '.cover-modal' ) ) { 25 // Handle cover modals when they're toggled. 26 this.onToggle(); 27 28 // When toggled, untoggle if visitor clicks on the wrapping element of the modal. 29 this.outsideUntoggle(); 30 31 // Close on escape key press. 32 this.closeOnEscape(); 33 34 // Hide and show modals before and after their animations have played out. 35 this.hideAndShowModals(); 36 } 37 }, 38 // Handle cover modals when they're toggled. 39 onToggle: function() { 40 document.querySelectorAll( '.cover-modal' ).forEach( function( element ) { 41 element.addEventListener( 'toggled', function( event ) { 42 var modal = event.target, 43 body = document.body; 44 45 if ( modal.classList.contains( 'active' ) ) { 46 body.classList.add( 'showing-modal' ); 47 } else { 48 body.classList.remove( 'showing-modal' ); 49 body.classList.add( 'hiding-modal' ); 50 51 // Remove the hiding class after a delay, when animations have been run. 52 setTimeout( function() { 53 body.classList.remove( 'hiding-modal' ); 54 }, 500 ); 55 } 56 } ); 57 } ); 58 }, 59 // Close modal on outside click. 60 outsideUntoggle: function() { 61 document.addEventListener( 'click', function( event ) { 62 var target = event.target; 63 var modal = document.querySelector( '.cover-modal.active' ); 64 65 if ( target === modal ) { 66 this.untoggleModal( target ); 67 } 68 }.bind( this ) ); 69 }, 70 // Close modal on escape key press. 71 closeOnEscape: function() { 72 document.addEventListener( 'keydown', function( event ) { 73 if ( event.keyCode === 27 ) { 74 event.preventDefault(); 75 document.querySelectorAll( '.cover-modal.active' ).forEach( function( element ) { 76 this.untoggleModal( element ); 77 }.bind( this ) ); 78 } 79 }.bind( this ) ); 80 }, 81 // Hide and show modals before and after their animations have played out. 82 hideAndShowModals: function() { 83 var _doc = document, 84 _win = window, 85 modals = _doc.querySelectorAll( '.cover-modal' ), 86 htmlStyle = _doc.documentElement.style, 87 adminBar = _doc.querySelector( '#wpadminbar' ); 88 89 function getAdminBarHeight( negativeValue ) { 90 var height, 91 currentScroll = _win.pageYOffset; 92 93 if ( adminBar ) { 94 height = currentScroll + adminBar.getBoundingClientRect().height; 95 96 return negativeValue ? -height : height; 97 } 98 99 return currentScroll === 0 ? 0 : -currentScroll; 100 } 101 102 function htmlStyles() { 103 var overflow = _win.innerHeight > _doc.documentElement.getBoundingClientRect().height; 104 105 return { 106 'overflow-y': overflow ? 'hidden' : 'scroll', 107 position: 'fixed', 108 width: '100%', 109 top: getAdminBarHeight( true ) + 'px', 110 left: 0 111 }; 112 } 113 114 // Show the modal. 115 modals.forEach( function( modal ) { 116 modal.addEventListener( 'toggle-target-before-inactive', function( event ) { 117 var styles = htmlStyles(), 118 offsetY = _win.pageYOffset, 119 paddingTop = ( Math.abs( getAdminBarHeight() ) - offsetY ) + 'px', 120 mQuery = _win.matchMedia( '(max-width: 600px)' ); 121 122 if ( event.target !== modal ) { 123 return; 124 } 125 126 Object.keys( styles ).forEach( function( styleKey ) { 127 htmlStyle.setProperty( styleKey, styles[ styleKey ] ); 128 } ); 129 130 _win.sparklethemes.scrolled = parseInt( styles.top, 10 ); 131 132 if ( adminBar ) { 133 _doc.body.style.setProperty( 'padding-top', paddingTop ); 134 135 if ( mQuery.matches ) { 136 if ( offsetY >= getAdminBarHeight() ) { 137 modal.style.setProperty( 'top', 0 ); 138 } else { 139 modal.style.setProperty( 'top', ( getAdminBarHeight() - offsetY ) + 'px' ); 140 } 141 } 142 } 143 144 modal.classList.add( 'show-modal' ); 145 } ); 146 147 // Hide the modal after a delay, so animations have time to play out. 148 modal.addEventListener( 'toggle-target-after-inactive', function( event ) { 149 if ( event.target !== modal ) { 150 return; 151 } 152 153 setTimeout( function() { 154 var clickedEl = sparklethemes.toggles.clickedEl; 155 156 modal.classList.remove( 'show-modal' ); 157
158 Object.keys( htmlStyles() ).forEach( function( styleKey ) { 159 htmlStyle.removeProperty( styleKey ); 160 } ); 161 162 if ( adminBar ) { 163 _doc.body.style.removeProperty( 'padding-top' ); 164 modal.style.removeProperty( 'top' ); 165 } 166 167 if ( clickedEl !== false ) { 168 clickedEl.focus(); 169 clickedEl = false; 170 } 171 172 _win.scrollTo( 0, Math.abs( _win.sparklethemes.scrolled + getAdminBarHeight() ) ); 173 174 _win.sparklethemes.scrolled = 0; 175 }, 500 ); 176 } ); 177 } ); 178 }, 179 180 // Untoggle a modal. 181 untoggleModal: function( modal ) { 182 var modalTargetClass, 183 modalToggle = false; 184 185 // If the modal has specified the string (ID or class) used by toggles to target it, untoggle the toggles with that target string. 186 // The modal-target-string must match the string toggles use to target the modal. 187 if ( modal.dataset.modalTargetString ) { 188 modalTargetClass = modal.dataset.modalTargetString; 189 190 modalToggle = document.querySelector( '*[data-toggle-target="' + modalTargetClass + '"]' ); 191 } 192 193 // If a modal toggle exists, trigger it so all of the toggle options are included. 194 if ( modalToggle ) { 195 modalToggle.click(); 196 197 // If one doesn't exist, just hide the modal. 198 } else { 199 modal.classList.remove( 'active' ); 200 } 201 } 202 203}; // sparklethemes.coverModals 204 205 206/***** 207 * Mobile Menu Cover Modals 208*/ 209sparklethemes.modalMenu = { 210 211 init: function() { 212 // If the current menu item is in a sub level, expand all the levels higher up on load. 213 this.expandLevel(); 214 this.keepFocusInModal(); 215 }, 216 217 expandLevel: function() { 218 var modalMenus = document.querySelectorAll( '.modal-menu' ); 219 220 modalMenus.forEach( function( modalMenu ) { 221 var activeMenuItem = modalMenu.querySelector( '.current-menu-item' ); 222 223 if ( activeMenuItem ) { 224 sparklethemesFindParents( activeMenuItem, 'li' ).forEach( function( element ) { 225 var subMenuToggle = element.querySelector( '.sub-menu-toggle' ); 226 if ( subMenuToggle ) { 227 sparklethemes.toggles.performToggle( subMenuToggle, true ); 228 } 229 } ); 230 } 231 } ); 232 }, 233 234 keepFocusInModal: function() { 235 var _doc = document; 236 237 _doc.addEventListener( 'keydown', function( event ) { 238 var toggleTarget, modal, selectors, elements, menuType, bottomMenu, activeEl, lastEl, firstEl, tabKey, shift
238Key, 239 clickedEl = sparklethemes.toggles.clickedEl; 240 241 if ( clickedEl && _doc.body.classList.contains( 'showing-modal' ) ) { 242 toggleTarget = clickedEl.dataset.toggleTarget; 243 selectors = 'input, a, button'; 244 modal = _doc.querySelector( toggleTarget ); 245 if( !modal ) return; 246 elements = modal.querySelectorAll( selectors ); 247 elements = Array.prototype.slice.call( elements ); 248 249 if ( '.menu-modal' === toggleTarget ) { 250 menuType = window.matchMedia( '(min-width: 1000px)' ).matches; 251 menuType = menuType ? '.expanded-menu' : '.mobile-menu'; 252 253 elements = elements.filter( function( element ) { 254 return null !== element.closest( menuType ) && null !== element.offsetParent; 255 } ); 256 257 elements.unshift( _doc.querySelector( '.close-nav-toggle' ) ); 258 259 bottomMenu = _doc.querySelector( '.menu-bottom > nav' ); 260 261 if ( bottomMenu ) { 262 bottomMenu.querySelectorAll( selectors ).forEach( function( element ) { 263 elements.push( element ); 264 } ); 265 } 266 } 267 268 lastEl = elements[ elements.length - 1 ]; 269 firstEl = elements[0]; 270 activeEl = _doc.activeElement; 271 tabKey = event.keyCode === 9; 272 shiftKey = event.shiftKey; 273 274 if ( ! shiftKey && tabKey && lastEl === activeEl ) { 275 event.preventDefault(); 276 firstEl.focus(); 277 } 278 279 if ( shiftKey && tabKey && firstEl === activeEl ) { 280 event.preventDefault(); 281 lastEl.focus(); 282 } 283 } 284 } ); 285 } 286 287}; // sparklethemes.modalMenu 288 289/***** 290 * Primary Menu Mobile Menu 291*/ 292sparklethemes.primaryMenu = { 293 294 init: function() { 295 this.focusMenuWithChildren(); 296 }, 297 298 // The focusMenuWithChildren() function implements Keyboard Navigation in the Primary Menu 299 // by adding the '.focus' class to all 'li.menu-item-has-children' when the focus is on the 'a' element. 300 // The focusMenuWithChildren() function implements Keyboard Navigation in the Primary Menu 301 // by adding the '.focus' class to all 'li.menu-item-has-children' when the focus is on the 'a' element. 302 focusMenuWithChildren: function() { 303 304 // Get all the link elements within the primary menu. 305 var links, i, len, 306 menu = document.querySelector( '.box-header-nav' ); 307 308 if ( ! menu ) { 309 return false; 310 } 311 312 links = menu.getElementsByTagName( 'a' ); 313 314 // Each time a menu link is focused or blurred, toggle focus. 315 for ( i = 0, len = links.length; i < len; i++ ) { 316 links[i].addEventListener( 'focus', toggleFocus, true ); 317 links[i].addEventListener( 'blur', toggleFocus, true ); 318 } 319 320 //Sets or removes the .focus class on an element. 321 function toggleFocus() { 322 323 var self = this; 324 325 // Move up through the ancestors of the current link until we hit .primary-menu. 326 while ( -1 === self.className.indexOf( 'main-menu' ) ) { 327 // On li elements toggle the class .focus. 328 if ( 'li' === self.tagName.toLowerCase() ) { 329 if ( -1 !== self.className.indexOf( 'focus' ) ) { 330 self.className = self.className.replace( ' focus', '' ); 331 } else { 332 self.className += ' focus'; 333 } 334 } 335 self = self.parentElement; 336 } 337 } 338 } 339}; // sparklethemes.primaryMenu 340 341 342/***** 343 * categoryMenu Main Menu 344*/ 345sparklethemes.categoryMenu = { 346 347 init: function() { 348 this.focusMenuWithChildren(); 349 }, 350 351 // The focusMenuWithChildren() function implements Keyboard Navigation in the Primary Menu 352 // by adding the '.focus' class to all 'li.menu-item-has-children' when the focus is on the 'a' element. 353 // The focusMenuWithChildren() function implements Keyboard Navigation in the Primary Menu 354 // by adding the '.focus' class to all 'li.menu-item-has-children' when the focus is on the 'a' element. 355 focusMenuWithChildren: function() { 356 357 // Get all the link elements within the primary menu. 358 var links, i, len, 359 menu = document.querySelector( '.verticalmenu-content.menu-category' ); 360 361 if ( ! menu ) { 362 return false;
363 } 364 365 links = menu.getElementsByTagName( 'a' ); 366 367 // Each time a menu link is focused or blurred, toggle focus. 368 for ( i = 0, len = links.length; i < len; i++ ) { 369 links[i].addEventListener( 'focus', toggleFocus, true ); 370 links[i].addEventListener( 'blur', toggleFocus, true ); 371 } 372 373 //Sets or removes the .focus class on an element. 374 function toggleFocus() { 375 376 var self = this; 377 378 // Move up through the ancestors of the current link until we hit .primary-menu. 379 while ( -1 === self.className.indexOf( 'vertical-menu' ) ) { 380 // On li elements toggle the class .focus. 381 if ( 'li' === self.tagName.toLowerCase() ) { 382 if ( -1 !== self.className.indexOf( 'focus' ) ) { 383 self.className = self.className.replace( ' focus', '' ); 384 } else { 385 self.className += ' focus'; 386 } 387 } 388 self = self.parentElement; 389 } 390 } 391 } 392}; // sparklethemes.categoryMenu 393 394/***** 395 * Mobile Menu Toggles 396*/ 397sparklethemes.toggles = { 398 399 clickedEl: false, 400 401 init: function() { 402 // Do the toggle. 403 this.toggle(); 404 405 // Check for toggle/untoggle on resize. 406 this.resizeCheck(); 407 408 // Check for untoggle on escape key press. 409 this.untoggleOnEscapeKeyPress(); 410 }, 411 412 performToggle: function( element, instantly ) { 413 var target, timeOutTime, classToToggle, 414 self = this, 415 _doc = document, 416 // Get our targets. 417 toggle = element, 418 targetString = toggle.dataset.toggleTarget, 419 activeClass = 'active'; 420 421 // Elements to focus after modals are closed. 422 if ( ! _doc.querySelectorAll( '.show-modal' ).length ) { 423 self.clickedEl = _doc.activeElement; 424 } 425 426 if ( targetString === 'next' ) { 427 target = toggle.nextSibling; 428 } else { 429 target = _doc.querySelector( targetString ); 430 } 431 432 // Trigger events on the toggle targets before they are toggled. 433 if ( target.classList.contains( activeClass ) ) { 434 target.dispatchEvent( sparklethemes.createEvent( 'toggle-target-before-active' ) ); 435 } else { 436 target.dispatchEvent( sparklethemes.createEvent( 'toggle-target-before-inactive' ) ); 437 } 438 439 // Get the class to toggle, if specified. 440 classToToggle = toggle.dataset.classToToggle ? toggle.dataset.classToToggle : activeClass; 441 442 // For cover modals, set a short timeout duration so the class animations have time to play out. 443 timeOutTime = 0; 444 445 if ( target.classList.contains( 'cover-modal' ) ) { 446 timeOutTime = 10; 447 } 448 449 // if( target.dataset.modalTargetShow == 'relative'){ 450 // target.style.setProperty( 'top', ( toggle.offsetTop ) + 'px' ); 451 // } 452 453 setTimeout( function() { 454 var focusElement, 455 subMenued = target.classList.contains( 'sub-menu' ), 456 newTarget = subMenued ? toggle.closest( '.menu-item' ).querySelector( '.sub-menu' ) : target, 457 duration = toggle.dataset.toggleDuration; 458 459 // Toggle the target of the clicked toggle. 460 if ( toggle.dataset.toggleType === 'slidetoggle' && ! instantly && duration !== '0' ) { 461 sparklethemesMenuToggle( newTarget, duration ); 462 } else { 463 newTarget.classList.toggle( classToToggle ); 464 } 465 466 // If the toggle target is 'next', only give the clicked toggle the active class. 467 if ( targetString === 'next' ) { 468 toggle.classList.toggle( activeClass ); 469 } else if ( target.classList.contains( 'sub-menu' ) ) { 470 toggle.classList.toggle( activeClass ); 471 } else { 472 // If not, toggle all toggles with this toggle target. 473 _doc.querySelector( '*[data-toggle-target="' + targetString + '"]' ).classList.toggle( activeClass ); 474 } 475 476 // Toggle aria-expanded on the toggle. 477 sparklethemesToggleAttribute( toggle, 'aria-expanded', 'true', 'false' ); 478 479 if ( self.clickedEl && -1 !== toggle.getAttribute( 'class' ).indexOf( 'close-' ) ) { 480 sparklethemesToggleAttribute( self.clickedEl, 'aria-expanded', 'true', 'false' ); 481 } 482 483 // Toggle body class. 484 if ( toggle.dataset.toggleBodyClass ) { 485 _doc.body.classList.toggle( toggle.dataset.toggleBodyClass ); 486 } 487 488 // Check whether to set focus. 489 if ( toggle.dataset.setFocus ) { 490 focusElement = _doc.querySelector( toggle.dataset.setFocus ); 491
492 if ( focusElement ) { 493 if ( target.classList.contains( activeClass ) ) { 494 focusElement.focus(); 495 } else { 496 focusElement.blur(); 497 } 498 } 499 } 500 501 // Trigger the toggled event on the toggle target. 502 target.dispatchEvent( sparklethemes.createEvent( 'toggled' ) ); 503 504 // Trigger events on the toggle targets after they are toggled. 505 if ( target.classList.contains( activeClass ) ) { 506 target.dispatchEvent( sparklethemes.createEvent( 'toggle-target-after-active' ) ); 507 } else { 508 target.dispatchEvent( sparklethemes.createEvent( 'toggle-target-after-inactive' ) ); 509 } 510 }, timeOutTime ); 511 }, 512 513 // Do the toggle. 514 toggle: function() { 515 var self = this; 516 517 document.querySelectorAll( '*[data-toggle-target]' ).forEach( function( element ) { 518 element.addEventListener( 'click', function( event ) { 519 event.preventDefault(); 520 self.performToggle( element ); 521 } ); 522 } ); 523 }, 524 525 // Check for toggle/untoggle on screen resize. 526 resizeCheck: function() { 527 if ( document.querySelectorAll( '*[data-untoggle-above], *[data-untoggle-below], *[data-toggle-above], *[data-toggle-below]' ).length ) { 528 window.addEventListener( 'resize', function() { 529 var winWidth = window.innerWidth, 530 toggles = document.querySelectorAll( '.toggle' ); 531 532 toggles.forEach( function( toggle ) { 533 var unToggleAbove = toggle.dataset.untoggleAbove, 534 unToggleBelow = toggle.dataset.untoggleBelow, 535 toggleAbove = toggle.dataset.toggleAbove, 536 toggleBelow = toggle.dataset.toggleBelow; 537 538 // If no width comparison is set, continue. 539 if ( ! unToggleAbove && ! unToggleBelow && ! toggleAbove && ! toggleBelow ) { 540 return; 541 } 542 543 // If the toggle width comparison is true, toggle the toggle. 544 if ( 545 ( ( ( unToggleAbove && winWidth > unToggleAbove ) || 546 ( unToggleBelow && winWidth < unToggleBelow ) ) && 547 toggle.classList.contains( 'active' ) ) || 548 ( ( ( toggleAbove && winWidth > toggleAbove ) || 549 ( toggleBelow && winWidth < toggleBelow ) ) && 550 ! toggle.classList.contains( 'active' ) ) 551 ) { 552 toggle.click(); 553 } 554 } ); 555 } ); 556 } 557 }, 558 559 // Close toggle on escape key press. 560 untoggleOnEscapeKeyPress: function() { 561 document.addEventListener( 'keyup', function( event ) { 562 if ( event.key === 'Escape' ) { 563 document.querySelectorAll( '*[data-untoggle-on-escape].active' ).forEach( function( element ) { 564 if ( element.classList.contains( 'active' ) ) { 565 element.click(); 566 } 567 } ); 568 } 569 } ); 570 } 571 572}; // sparklethemes.toggles 573 574/** 575 * Is the DOM ready? 576 * 577 * This implementation is coming from https://gomakethings.com/a-native-javascript-equivalent-of-jquerys-ready-method/ 578 * 579 * @param {Function} fn Callback function to run. 580 */ 581function sparklethemesDomReady( fn ) { 582 if ( typeof fn !== 'function' ) { 583 return; 584 } 585 586 if ( document.readyState === 'interactive' || document.readyState === 'complete' ) { 587 return fn(); 588 } 589 590 document.addEventListener( 'DOMContentLoaded', fn, false ); 591} 592 593sparklethemesDomReady( function() { 594 sparklethemes.toggles.init(); // Handle toggles. 595 sparklethemes.coverModals.init(); // Handle cover modals. 596 sparklethemes.modalMenu.init(); // Modal Menu. 597 sparklethemes.primaryMenu.init(); // Primary Menu. 598 sparklethemes.categoryMenu.init(); // Vertical Category Menu. 599} ); 600 601/*----------------------------------------------------------------------------------------------- 602 603--------------------------------------------------------------------------------------------------- */ 604/***** 605 * Helper functions ( Toggle an Attribute ) 606*/ 607function sparklethemesToggleAttribute( element, attribute, trueVal, falseVal ) { 608 if ( trueVal === undefined ) { 609 trueVal = true; 610 } 611 if ( falseVal === undefined ) { 612 falseVal = false; 613 } 614 if ( element.getAttribute( attribute ) !== trueVal ) { 615 element.setAttribute( attribute, trueVal ); 616 } else { 617 element.setAttribute( attribute, falseVal ); 618 } 619} 620 621/** 622 * Toggle a menu item on or off. 623 * 624 * @param {HTMLElement} target 625 * @param {number} duration 626 */ 627function sparklethemesMenuToggle( target, duration ) { 628 var initialParentHeight, finalParentHeight, menu, menuItems, transitionListener, 629 initialPositions = [], 630 finalPositions = []; 631 632 if ( ! target ) { 633 return; 634 } 635 636 menu = target.closest( '.menu-wrapper' ); 637 638 // Step 1: look at the initial positions of every menu item. 639 menuItems = menu.querySelectorAll( '.menu-item' ); 640
641 menuItems.forEach( function( menuItem, index ) { 642 initialPositions[ index ] = { x: menuItem.offsetLeft, y: menuItem.offsetTop }; 643 } ); 644 initialParentHeight = target.parentElement.offsetHeight; 645 646 target.classList.add( 'toggling-target' ); 647 648 // Step 2: toggle target menu item and look at the final positions of every menu item. 649 target.classList.toggle( 'active' ); 650 651 menuItems.forEach( function( menuItem, index ) { 652 finalPositions[ index ] = { x: menuItem.offsetLeft, y: menuItem.offsetTop }; 653 } ); 654 finalParentHeight = target.parentElement.offsetHeight; 655 656 // Step 3: close target menu item again. 657 // The whole process happens without giving the browser a chance to render, so it's invisible. 658 target.classList.toggle( 'active' ); 659 660 /* 661 * Step 4: prepare animation. 662 * Position all the items with absolute offsets, at the same starting position. 663 * Shouldn't result in any visual changes if done right. 664 */ 665 menu.classList.add( 'is-toggling' ); 666 target.classList.toggle( 'active' ); 667 menuItems.forEach( function( menuItem, index ) { 668 var initialPosition = initialPositions[ index ]; 669 if ( initialPosition.y === 0 && menuItem.parentElement === target ) { 670 initialPosition.y = initialParentHeight; 671 } 672 // menuItem.style.transform = 'translate(' + initialPosition.x + 'px, ' + initialPosition.y + 'px)'; 673 } ); 674 675 /* 676 * The double rAF is unfortunately needed, since we're toggling CSS classes, and 677 * the only way to ensure layout completion here across browsers is to wait twice. 678 * This just delays the start of the animation by 2 frames and is thus not an issue. 679 */ 680 requestAnimationFrame( function() { 681 requestAnimationFrame( function() { 682 /* 683 * Step 5: start animation by moving everything to final position. 684 * All the layout work has already happened, while we were preparing for the animation. 685 * The animation now runs entirely in CSS, using cheap CSS properties (opacity and transform) 686 * that don't trigger the layout or paint stages. 687 */ 688 menu.classList.add( 'is-animating' ); 689 menuItems.forEach( function( menuItem, index ) { 690 var finalPosition = finalPositions[ index ]; 691 if ( finalPosition.y === 0 && menuItem.parentElement === target ) { 692 finalPosition.y = finalParentHeight; 693 } 694 if ( duration !== undefined ) { 695 menuItem.style.transitionDuration = duration + 'ms'; 696 } 697 // menuItem.style.transform = 'translate(' + finalPosition.x + 'px, ' + finalPosition.y + 'px)'; 698 } ); 699 if ( duration !== undefined ) { 700 target.style.transitionDuration = duration + 'ms'; 701 } 702 } ); 703 704 // Step 6: finish toggling. 705 // Remove all transient classes when the animation ends. 706 transitionListener = function() { 707 menu.classList.remove( 'is-animating' ); 708 menu.classList.remove( 'is-toggling' ); 709 target.classList.remove( 'toggling-target' ); 710 menuItems.forEach( function( menuItem ) { 711 menuItem.style.transform = ''; 712 menuItem.style.transitionDuration = ''; 713 } ); 714 target.style.transitionDuration = ''; 715 target.removeEventListener( 'transitionend', transitionListener ); 716 }; 717 718 target.addEventListener( 'transitionend', transitionListener ); 719 } ); 720} 721 722/** 723 * Traverses the DOM up to find elements matching the query. 724 * 725 * @param {HTMLElement} target 726 * @param {string} query 727 * @return {NodeList} parents matching query 728 */ 729function sparklethemesFindParents( target, query ) { 730 var parents = []; 731 732 // Recursively go up the DOM adding matches to the parents array. 733 function traverse( item ) { 734 var parent = item.parentNode; 735 if ( parent instanceof HTMLElement ) { 736 if ( parent.matches( query ) ) { 737 parents.push( parent ); 738 } 739 traverse( parent ); 740 } 741 } 742 743 traverse( target ); 744 745 return parents; 746}
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.