Guest User

Untitled

a guest
Aug 27th, 2025
14
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.71 KB | None | 0 0
  1. /*
  2. * Implements the hamburger menu behaviour
  3. *
  4. *
  5. * @since 4.8 moved from avia.js to own file as some user request to customize this feature
  6. */
  7. (function($)
  8. {
  9. "use strict";
  10.  
  11. $(function()
  12. {
  13. $.avia_utilities = $.avia_utilities || {};
  14.  
  15. if( 'undefined' == typeof $.avia_utilities.isMobile )
  16. {
  17. if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) && 'ontouchstart' in document.documentElement )
  18. {
  19. $.avia_utilities.isMobile = true;
  20. }
  21. else
  22. {
  23. $.avia_utilities.isMobile = false;
  24. }
  25. }
  26.  
  27. //activates the hamburger mobile menu
  28. avia_hamburger_menu();
  29.  
  30. $(window).trigger( 'resize' );
  31.  
  32. });
  33.  
  34. $.avia_utilities = $.avia_utilities || {};
  35.  
  36. function avia_hamburger_menu()
  37. {
  38. var header = $('#header'),
  39. header_main = $('#main .av-logo-container'), //check if we got a top menu that is above the header
  40. menu = $('#avia-menu'),
  41. burger_wrap = $('.av-burger-menu-main a'),
  42. htmlEL = $('html').eq(0),
  43. overlay = $('<div class="av-burger-overlay" role="menu" aria-orientation="vertical"></div>'),
  44. overlay_scroll = $('<div class="av-burger-overlay-scroll"></div>').appendTo(overlay),
  45. inner_overlay = $('<div class="av-burger-overlay-inner"></div>').appendTo(overlay_scroll),
  46. bgColor = $('<div class="av-burger-overlay-bg"></div>').appendTo(overlay),
  47. animating = false,
  48. first_level = {},
  49. logo_container = $('.av-logo-container .inner-container'),
  50. menu_in_logo_container = logo_container.find('.main_menu'),
  51. cloneFirst = htmlEL.is('.html_av-submenu-display-click.html_av-submenu-clone, .html_av-submenu-display-hover.html_av-submenu-clone'),
  52. menu_generated = false,
  53. cloned_menu_cnt = 0;
  54.  
  55. if( ! htmlEL.hasClass( 'html_av-submenu-hidden' ) )
  56. {
  57. htmlEL.addClass( 'html_av-submenu-visible' );
  58. }
  59.  
  60. /**
  61. * Check for alternate mobile menu
  62. */
  63. var alternate = $('#avia_alternate_menu');
  64. if( alternate.length > 0 )
  65. {
  66. menu = alternate;
  67. }
  68.  
  69. var set_list_container_height = function()
  70. {
  71. //necessary for ios since the height is usually not 100% but 100% - menu bar which can be requested by window.innerHeight
  72. if($.avia_utilities.isMobile)
  73. {
  74. overlay_scroll.outerHeight(window.innerHeight);
  75. }
  76. },
  77. create_list = function( items , append_to )
  78. {
  79. if( ! items )
  80. {
  81. return;
  82. }
  83.  
  84. var list, link, current, subitems, megacolumns, sub_current, sub_current_list, new_li, new_ul;
  85.  
  86. items.each(function()
  87. {
  88. current = $(this);
  89. subitems = current.find(' > .sub-menu > li'); //find sublists of a regular defined menu
  90. if( subitems.length == 0 )
  91. {
  92. subitems = current.find(' > .children > li'); //find sublists of a fallback menu
  93. }
  94. megacolumns = current.find( '.avia_mega_div > .sub-menu > li.menu-item' );
  95.  
  96. // href = '#': we have a custom link that should not link to something - is also in use by megamenu for titles
  97. var cur_menu = current.find('>a');
  98. var clone_events = true;
  99.  
  100. if( cur_menu.length )
  101. {
  102. var cur_menu_elem = cur_menu.get(0);
  103.  
  104. if( cur_menu_elem && (cur_menu_elem.hash == '#' || typeof cur_menu.attr('href') === 'undefined' || cur_menu.attr('href') == '#') )
  105. {
  106. // eventhandler conflict 'click' by megamenu (returns false) - ignore all handlers
  107. if( subitems.length > 0 || megacolumns.length > 0 )
  108. {
  109. clone_events = false;
  110. }
  111. }
  112. }
  113.  
  114. link = cur_menu.clone(clone_events).attr('style','');
  115.  
  116. // megamenus can have '' as url in top menu - allow click event in burger
  117. if( 'undefined' == typeof cur_menu.attr('href') )
  118. {
  119. link.attr( 'href', '#' );
  120. }
  121.  
  122. new_li = $('<li>').append( link );
  123. new_li.attr( 'role', 'menuitem' );
  124.  
  125. // Copy user set classes for menu items - these must not start with menu-item, page-item, page_item (used by default classes)
  126. var cls = [];
  127. if( 'undefined' != typeof current.attr('class') )
  128. {
  129. cls = current.attr('class').split(/\s+/);
  130. $.each( cls, function( index, value ){
  131. if( ( value.indexOf('menu-item') != 0 ) && ( value.indexOf('page-item') < 0 ) && ( value.indexOf('page_item') != 0 ) && ( value.indexOf('dropdown_ul') < 0 ) )
  132. {
  133. // 'current-menu-item' is also copied !!
  134. new_li.addClass( value );
  135. }
  136. return true;
  137. });
  138. }
  139.  
  140. if( 'undefined' != typeof current.attr('id') && '' != current.attr('id') )
  141. {
  142. new_li.addClass(current.attr('id'));
  143. }
  144. else
  145. {
  146. // fallback menu has no id -> try to find page id in class
  147. $.each( cls, function( index, value ){
  148. if( value.indexOf('page-item-') >= 0 )
  149. {
  150. new_li.addClass(value);
  151. return false;
  152. }
  153. });
  154. }
  155.  
  156. append_to.append(new_li);
  157.  
  158. if(subitems.length)
  159. {
  160. new_ul = $('<ul class="sub-menu">').appendTo(new_li);
  161.  
  162. var link_elem = link.get(0);
  163.  
  164. if (
  165. cloneFirst &&
  166. link_elem &&
  167. link_elem.hash != '#' &&
  168. link.attr('href') != '#'
  169. )
  170. {
  171. new_li.clone(true).prependTo(new_ul);
  172. }
  173.  
  174. new_li.addClass('av-width-submenu').find('>a').append('<span class="av-submenu-indicator">');
  175.  
  176. create_list( subitems , new_ul);
  177. }
  178. else if(megacolumns.length) //if we got no normal sublists try megamenu columns and sublists
  179. {
  180. new_ul = $('<ul class="sub-menu">').appendTo(new_li);
  181.  
  182. var link_elem = link.get(0);
  183.  
  184. if (cloneFirst && link_elem && link_elem.hash != '#' && link.attr('href') != '#') {
  185. new_li.clone(true).prependTo(new_ul);
  186. }
  187.  
  188. megacolumns.each(function(iteration)
  189. {
  190. var megacolumn = $(this),
  191. mega_current = megacolumn.find( '> .sub-menu' ), // can be 0 if only a column is used without submenus
  192. mega_title = megacolumn.find( '> .mega_menu_title' ),
  193. mega_title_link = mega_title.find('a').attr('href') || "#",
  194. current_megas = mega_current.length > 0 ? mega_current.find('>li') : null,
  195. mega_title_set = false,
  196. mega_link = new_li.find('>a'),
  197. hide_enty = '';
  198.  
  199. // ignore columns that have no actual link and no subitems
  200. if( ( current_megas === null ) || ( current_megas.length == 0 ) )
  201. {
  202. if( mega_title_link == '#' )
  203. {
  204. hide_enty = ' style="display: none;"';
  205. }
  206. }
  207.  
  208. if(iteration == 0) new_li.addClass('av-width-submenu').find('>a').append('<span class="av-submenu-indicator">');
  209.  
  210. //if we got a title split up submenu items into multiple columns
  211. if(mega_title.length && mega_title.text() != "")
  212. {
  213. mega_title_set = true;
  214.  
  215. //if we are within the first iteration we got a new submenu, otherwise we start a new one
  216. if(iteration > 0)
  217. {
  218. var check_li = new_li.parents('li').eq(0);
  219.  
  220. if(check_li.length) new_li = check_li;
  221.  
  222. new_ul = $('<ul class="sub-menu">').appendTo(new_li);
  223. }
  224.  
  225.  
  226. new_li = $('<li' + hide_enty + '>').appendTo(new_ul);
  227. new_ul = $('<ul class="sub-menu">').appendTo(new_li);
  228.  
  229. $('<a href="'+mega_title_link+'"><span class="avia-bullet"></span><span class="avia-menu-text">' +mega_title.text()+ '</span></a>').insertBefore(new_ul);
  230. mega_link = new_li.find('>a');
  231.  
  232. // Clone if we have submenus
  233. if(cloneFirst && ( mega_current.length > 0 ) && ( mega_link.length && mega_link.get(0).hash != '#' && mega_link.attr('href') != '#' ))
  234. {
  235. new_li.clone(true).addClass('av-cloned-title').prependTo(new_ul);
  236. }
  237.  
  238. }
  239.  
  240. // do not append av-submenu-indicator if no submenus (otherwise link action is blocked !!!)
  241. if( mega_title_set && ( mega_current.length > 0 ) )
  242. {
  243. new_li.addClass('av-width-submenu').find('>a').append('<span class="av-submenu-indicator">');
  244. }
  245.  
  246. create_list( current_megas , new_ul);
  247. });
  248.  
  249. }
  250.  
  251. });
  252.  
  253. burger_wrap.trigger( 'avia_burger_list_created' );
  254. return list;
  255. };
  256.  
  257. var burger_ul, burger;
  258.  
  259. //prevent scrolling of outer window when scrolling inside
  260. $('body').on( 'mousewheel DOMMouseScroll touchmove', '.av-burger-overlay-scroll', function (e)
  261. {
  262. var height = this.offsetHeight,
  263. scrollHeight = this.scrollHeight,
  264. direction = e.originalEvent.wheelDelta;
  265.  
  266. if(scrollHeight != this.clientHeight)
  267. {
  268. if( ( this.scrollTop >= (scrollHeight - height) && direction < 0) || (this.scrollTop <= 0 && direction > 0) )
  269. {
  270. e.preventDefault();
  271. }
  272. }
  273. else
  274. {
  275. e.preventDefault();
  276. }
  277. });
  278.  
  279. //prevent scrolling for the rest of the screen
  280. $(document).on( 'mousewheel DOMMouseScroll touchmove', '.av-burger-overlay-bg, .av-burger-overlay-active .av-burger-menu-main', function (e)
  281. {
  282. e.preventDefault();
  283. });
  284.  
  285. //prevent scrolling on mobile devices
  286. var touchPos = {};
  287.  
  288. $(document).on('touchstart', '.av-burger-overlay-scroll', function(e)
  289. {
  290. touchPos.Y = e.originalEvent.touches[0].clientY;
  291. });
  292.  
  293. $(document).on('touchend', '.av-burger-overlay-scroll', function(e)
  294. {
  295. touchPos = {};
  296. });
  297.  
  298. //prevent rubberband scrolling http://blog.christoffer.me/six-things-i-learnt-about-ios-safaris-rubber-band-scrolling/
  299. $(document).on( 'touchmove', '.av-burger-overlay-scroll', function (e)
  300. {
  301. if(!touchPos.Y)
  302. {
  303. touchPos.Y = e.originalEvent.touches[0].clientY;
  304. }
  305.  
  306. var differenceY = e.originalEvent.touches[0].clientY - touchPos.Y,
  307. element = this,
  308. top = element.scrollTop,
  309. totalScroll = element.scrollHeight,
  310. currentScroll = top + element.offsetHeight,
  311. direction = differenceY > 0 ? "up" : "down";
  312.  
  313. $('body').get(0).scrollTop = touchPos.body;
  314.  
  315. if( top <= 0 )
  316. {
  317. if( direction == "up" )
  318. {
  319. e.preventDefault();
  320. }
  321.  
  322. }
  323. else if( currentScroll >= totalScroll )
  324. {
  325. if( direction == "down" )
  326. {
  327. e.preventDefault();
  328. }
  329. }
  330. });
  331.  
  332. $(window).on( 'debouncedresize', function (e)
  333. {
  334. var close = true;
  335.  
  336. // @since 4.8.3 we support portrait/landscape screens to switch mobile menu
  337. if( $.avia_utilities.isMobile && htmlEL.hasClass( 'av-mobile-menu-switch-portrait' ) && htmlEL.hasClass( 'html_text_menu_active' ) )
  338. {
  339. var height = $( window ).height();
  340. var width = $( window ).width();
  341.  
  342. if( width <= height )
  343. {
  344. // in portrait mode we only need to remove added class
  345. htmlEL.removeClass( 'html_burger_menu' );
  346. }
  347. else
  348. {
  349. // in landscape mode
  350. var switch_width = htmlEL.hasClass( 'html_mobile_menu_phone' ) ? 768 : 990;
  351. if( height < switch_width )
  352. {
  353. htmlEL.addClass( 'html_burger_menu' );
  354. close = false;
  355. }
  356. else
  357. {
  358. htmlEL.removeClass( 'html_burger_menu' );
  359. }
  360. }
  361. }
  362.  
  363.  
  364. // close burger menu when returning to desktop
  365. if( close && burger && burger.length )
  366. {
  367. if( ! burger_wrap.is(':visible') )
  368. {
  369. burger.filter(".is-active").parents('a').eq(0).trigger('click');
  370. }
  371. }
  372.  
  373. set_list_container_height();
  374. });
  375.  
  376. //close overlay on overlay click
  377. $('.html_av-overlay-side').on( 'click', '.av-burger-overlay-bg', function (e)
  378. {
  379. e.preventDefault();
  380. burger.parents('a').eq(0).trigger('click');
  381. });
  382.  
  383. //close overlay when smooth scrollign begins
  384. $(window).on('avia_smooth_scroll_start', function()
  385. {
  386. if(burger && burger.length)
  387. {
  388. burger.filter(".is-active").parents('a').eq(0).trigger('click');
  389. }
  390. });
  391.  
  392.  
  393. //toogle hide/show for submenu items
  394. $('.html_av-submenu-display-hover').on( 'mouseenter', '.av-width-submenu', function (e)
  395. {
  396. $(this).children("ul.sub-menu").slideDown('fast');
  397. });
  398.  
  399. $('.html_av-submenu-display-hover').on( 'mouseleave', '.av-width-submenu', function (e)
  400. {
  401. $(this).children("ul.sub-menu").slideUp('fast');
  402. });
  403.  
  404. $('.html_av-submenu-display-hover').on( 'click', '.av-width-submenu > a', function (e)
  405. {
  406. e.preventDefault();
  407. e.stopImmediatePropagation();
  408. });
  409.  
  410. // for mobile we use same behaviour as submenu-display-click
  411. $('.html_av-submenu-display-hover').on( 'touchstart', '.av-width-submenu > a', function (e)
  412. {
  413. var menu = $(this);
  414. toggle_submenu( menu, e );
  415. });
  416.  
  417.  
  418. //toogle hide/show for submenu items
  419. $('.html_av-submenu-display-click').on( 'click', '.av-width-submenu > a', function (e)
  420. {
  421. var menu = $(this);
  422. toggle_submenu( menu, e );
  423. });
  424.  
  425.  
  426. // close mobile menu if click on active menu item
  427. $('.html_av-submenu-display-click, .html_av-submenu-visible').on( 'click', '.av-burger-overlay a', function (e)
  428. {
  429. var loc = window.location.href.match(/(^[^#]*)/)[0];
  430. var cur = $(this).attr('href').match(/(^[^#]*)/)[0];
  431.  
  432. if( cur == loc )
  433. {
  434. e.preventDefault();
  435. e.stopImmediatePropagation();
  436.  
  437. burger.parents('a').eq(0).trigger('click');
  438. return false;
  439. }
  440.  
  441. return true;
  442. });
  443.  
  444.  
  445. function toggle_submenu( menu, e )
  446. {
  447. e.preventDefault();
  448. e.stopImmediatePropagation();
  449.  
  450. var parent = menu.parents('li').eq(0);
  451.  
  452. parent.toggleClass('av-show-submenu');
  453.  
  454. if(parent.is('.av-show-submenu'))
  455. {
  456. parent.children("ul.sub-menu").slideDown('fast');
  457. }
  458. else
  459. {
  460. parent.children("ul.sub-menu").slideUp('fast');
  461. }
  462. };
  463.  
  464.  
  465. (function normalize_layout()
  466. {
  467. //if we got the menu outside of the main menu container we need to add it to the container as well
  468. if( menu_in_logo_container.length )
  469. {
  470. return;
  471. }
  472.  
  473. var menu2 = $('#header .main_menu').clone(true),
  474. ul = menu2.find('ul.av-main-nav'),
  475. id = ul.attr('id');
  476.  
  477. if( 'string' == typeof id && '' != id.trim() )
  478. {
  479. ul.attr('id', id + '-' + cloned_menu_cnt++ );
  480. }
  481. menu2.find('.menu-item:not(.menu-item-avia-special)').remove();
  482. menu2.insertAfter(logo_container.find('.logo').first());
  483.  
  484. //check if we got social icons and append it to the secondary menu
  485. var social = $('#header .social_bookmarks').clone(true);
  486. if( ! social.length )
  487. {
  488. social = $('.av-logo-container .social_bookmarks').clone(true);
  489. }
  490.  
  491. if( social.length )
  492. {
  493. menu2.find('.avia-menu').addClass('av_menu_icon_beside');
  494. menu2.append(social);
  495. }
  496.  
  497. //re select the burger menu if we added a new one
  498. burger_wrap = $('.av-burger-menu-main a');
  499. }());
  500.  
  501.  
  502.  
  503. burger_wrap.on('click', function(e)
  504. {
  505. if( animating )
  506. {
  507. return;
  508. }
  509.  
  510. burger = $(this).find('.av-hamburger'),
  511. animating = true;
  512.  
  513. if(!menu_generated)
  514. {
  515. menu_generated = true;
  516. burger.addClass("av-inserted-main-menu");
  517.  
  518. burger_ul = $('<ul>').attr( {id:'av-burger-menu-ul', class:'', 'aria-haspopup': 'true', 'aria-controls': 'menu2'} );
  519. var first_level_items = menu.find('> li:not(.menu-item-avia-special)'); //select all first level items that are not special items
  520. var list = create_list( first_level_items , burger_ul);
  521.  
  522. burger_ul.find('.noMobile').remove(); //remove any menu items with the class noMobile so user can filter manually if he wants
  523. burger_ul.appendTo(inner_overlay);
  524. first_level = inner_overlay.find('#av-burger-menu-ul > li');
  525.  
  526. if($.fn.avia_smoothscroll)
  527. {
  528. $('a[href*="#"]', overlay).avia_smoothscroll(overlay);
  529. }
  530. }
  531.  
  532. if(burger.is(".is-active"))
  533. {
  534. burger.removeClass("is-active");
  535. htmlEL.removeClass("av-burger-overlay-active-delayed");
  536.  
  537. overlay.animate({opacity:0}, function()
  538. {
  539. overlay.css({display:'none'});
  540. htmlEL.removeClass("av-burger-overlay-active");
  541. animating = false;
  542. });
  543.  
  544. }
  545. else
  546. {
  547. set_list_container_height();
  548.  
  549. var offsetTop = header_main.length ? header_main.outerHeight() + header_main.position().top : header.outerHeight() + header.position().top;
  550.  
  551. overlay.appendTo($(e.target).parents('.avia-menu'));
  552.  
  553. burger_ul.css({padding:( offsetTop ) + "px 0px"});
  554.  
  555. first_level.removeClass('av-active-burger-items');
  556.  
  557. burger.addClass("is-active");
  558. htmlEL.addClass("av-burger-overlay-active");
  559. overlay.css({display:'block'}).animate({opacity:1}, function()
  560. {
  561. animating = false;
  562. });
  563.  
  564. setTimeout(function()
  565. {
  566. htmlEL.addClass("av-burger-overlay-active-delayed");
  567. }, 100);
  568.  
  569. first_level.each(function(i)
  570. {
  571. var _self = $(this);
  572. setTimeout(function()
  573. {
  574. _self.addClass('av-active-burger-items');
  575. }, (i + 1) * 125);
  576. });
  577.  
  578. }
  579.  
  580. e.preventDefault();
  581. });
  582. }
  583.  
  584. })( jQuery );
  585.  
Advertisement
Add Comment
Please, Sign In to add comment