/**
* @package DJ-MegaMenu
* @copyright Copyright (C) 2022 DJ-Extensions.com, All rights reserved.
* @license DJ-Extensions.com Proprietary Use License
* @author url: https://dj-extensions.com
* @author email [email protected]
* @developer Szymon Woronowski, Artur Kaczmarek
*/
var DJMegaMobile;
(function($) {
DJMegaMobile = function () {
this.mega = [];
this.timer = null;
this.init();
};
DJMegaMobile.prototype.init = function () {
var self = this;
// init mobile menu
$('.dj-megamenu:not(.dj-megamenu-sticky)').each(function() {
var menu = $(this);
var mobile = $('#'+menu.prop('id')+'mobile');
var offcanvas = $('#'+menu.prop('id')+'offcanvas');
var idx = self.mega.length;
self.mega[idx] = {};
self.mega[idx].id = menu.prop('id');
self.mega[idx].trigger = menu.data('trigger');
self.mega[idx].menu = menu;
self.mega[idx].menuHandler = $('<div />');
self.mega[idx].mobile = mobile.length ? mobile : null;
self.mega[idx].mobileHandler = $('<div />');
self.mega[idx].offcanvas = offcanvas.length ? offcanvas : null;
self.mega[idx].offcanvasHandler = $('<div />');
var wrapper = $('#'+menu.prop('id')+'mobileWrap');
if(wrapper.length) {
wrapper.empty().append(self.mega[idx].mobile);
}
if(self.mega[idx].mobile) {
// remove hidden menu items from the DOM
self.mega[idx].mobile.find('.dj-hideitem').remove();
if(self.mega[idx].mobile.hasClass('dj-megamenu-offcanvas')) {
self.createOffcanvas(self.mega[idx].mobile);
} else if(self.mega[idx].mobile.hasClass('dj-megamenu-accordion')) {
self.createAccordion(self.mega[idx].mobile);
}
// fix double collapse Joomla!3 Protostar
self.mega[idx].mobile.parents('.nav-collapse').addClass('collapse in').css('height', 'auto').prev('.navbar').remove();
// fix double collapse Joomla!4 Cassiopeia
self.mega[idx].mobile.parents('.navbar-collapse').addClass('show').prev('.navbar-toggler').remove();
}
});
$(window).resize(self.switchMenu.bind(self));
self.switchMenu();
$(document).on('click', '.dj-offcanvas-open', function(e) {
if( $(e.target).parents('.dj-offcanvas').length || $(e.target).hasClass('dj-offcanvas')) return;
//if clicked outside offcanvas close it
$('.dj-offcanvas-opened').find('.dj-offcanvas-close-btn').click();
});
$(document).on('djmegamobile:pageload', function() {
for(var idx = 0; idx < self.mega.length; idx++) {
if(self.mega[idx].mobile) {
if(self.mega[idx].mobile.hasClass('dj-megamenu-select')) {
self.createSelectMenu(self.mega[idx].menu, self.mega[idx].mobile);
}
}
}
});
};
DJMegaMobile.prototype.createSelectMenu = function(menu, mobile) {
// Create the dropdown base
var id = menu.attr('id');
var name = mobile.attr('data-label') || 'menu';
var btn_open = mobile.find('.dj-mobile-open-btn');
var select = $('<select id="'+ id +'select" class="inputbox dj-select" />');
select.on('click blur', function() {
btn_open.toggleClass('active');
});
select.on('change', function() {
btn_open.removeClass('active');
if($(this).val) window.location = $(this).val();
});
var label = $('<label class="hidden" aria-hidden="true" for="'+ id +'select">' + name + '</label>')
var list = menu.find('li.dj-up');
this.addOptionsFromDJMegaMenu(list, select, 0);
label.appendTo(mobile);
select.appendTo(mobile);
btn_open.on('click', function(e){
e.stopPropagation();
e.preventDefault();
var element = select[0];
if (document.createEvent) { // all browsers
var ev = document.createEvent("MouseEvents");
ev.initMouseEvent("mousedown", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
element.dispatchEvent(ev);
} else if (element.fireEvent) { // ie
element.fireEvent("onmousedown");
}
});
};
DJMegaMobile.prototype.addOptionsFromDJMegaMenu = function(items, select, level) {
var self = this;
var sep = '',
active = false;
for(var i=0;i<level;i++) {
sep += '- ';
}
//console.log(items);
items.each(function(){
var item = $(this);
var link = item.find('> a').first();
var kids = item.find('> .dj-subwrap > .dj-subwrap-in > .dj-subcol > .dj-submenu > li, > .dj-subtree > li');
if(link.length) {
var text = '';
var img = link.find('img').first();
if(img.length) {
text = sep + img.attr('alt');
} else {
text = link.html().replace(/(<small[^<]+<\/small>)/ig,"");
text = sep + text.replace(/(<([^>]+)>)/ig,"");
}
//console.log(text);
var option = $('<option value="'+link.prop('href')+'">'+ text +'</option>').appendTo(select);
if(!link.prop('href')) { option.prop('disabled',true); }
if(item.hasClass('active')) {
select.val(option.val());
active = true;
}
}
if(kids) self.addOptionsFromDJMegaMenu(kids, select, level+1);
});
if(!level && !active) {
//$('<option value="">Menu</option>').prependTo(select);
select.val('');
}
};
DJMegaMobile.prototype.initAccordion = function(mobile) {
//console.log('initAccordion');
var focusTimer = null;
var btn_close = mobile.find('.dj-offcanvas-close-btn');
mobile.find('ul.dj-mobile-nav > li, ul.dj-mobile-nav-child > li').each(function(){
var menu = $(this);
var anchor = menu.find('> a').first();
if(anchor.length) {
var subs = menu.find('> ul.dj-mobile-nav-child > li:not(:empty)');
if( !subs.length ) {
menu.removeClass('parent');
menu.find('ul.dj-mobile-nav-child').remove();
}
if( menu.hasClass('parent') ) {
if( menu.hasClass('active') ) {
anchor.attr('aria-expanded', true);
menu.find('> ul').slideDown(400);
} else {
anchor.attr('aria-expanded', false);
}
anchor.append('<span class="toggler"></span>');
}
anchor.on('click',function(e) {
var $this = $(this);
var is_toggler = $(e.target).hasClass('toggler');
var _href = $this.attr('href');
var _hash = ( _href != undefined && _href.length > 1 && _href.indexOf('#') !== -1 ) ? true : false;
clearTimeout(focusTimer);
//detect hash, close off-canvas
if ( _hash && ! is_toggler && e.which ) { //e.which detects if a real click
$(document.body).addClass('dj-offcanvas-no-effects');
btn_close.click();
} else if( menu.hasClass('parent') && !menu.hasClass('active') ) {
e.preventDefault(); //first click - open submenu
} else if( is_toggler ) { //second click in toggler - close submenu
e.preventDefault();
e.stopPropagation();
menu.removeClass('active').find('> ul').slideUp(400);
$this.attr('aria-expanded', false);
}
});
anchor.on('focus',function() {
var $this = $(this);
mobile.find('[aria-expanded]').attr('aria-expanded', false);
$this.parents('.active').find('> [aria-expanded]').attr('aria-expanded', true);
$this.attr('aria-expanded', true);
focusTimer = setTimeout(function(){
menu.click();
}, 250);
});
}
menu.on('click', function( e ) {
menu.siblings().removeClass('active').find('> ul').slideUp(400);
menu.addClass('active').find('> ul').slideDown(400);
});
});
};
DJMegaMobile.prototype.createOffcanvas = function(mobile) {
var isJoomla4 = mobile.parents('[data-joomla4]').length ? true : false;
var template = mobile.parents('[data-tmpl]').attr('data-tmpl');
var FXnotSupported = ( 'cassiopeia' === template ) ? true : false;
var content = null;
var wrapper = $('.dj-offcanvas-wrapper').first();
var pusher = $('.dj-offcanvas-pusher').first();
var pusherIn = $('.dj-offcanvas-pusher-in').first();
if( ! wrapper.length ) {
content = $(document.body).children();
wrapper = $('<div class="dj-offcanvas-wrapper" />');
pusher = $('<div class="dj-offcanvas-pusher" />');
pusherIn = $('<div class="dj-offcanvas-pusher-in" />');
}
var allOffcanvas = $('.dj-offcanvas');
var offcanvas = mobile.find('.dj-offcanvas').first();
var fx = ( FXnotSupported || ! wrapper.length || allOffcanvas.length > 1 ) ? '1' : offcanvas.data('effect');
var simple_fx = ( fx == 1 ) ? true : false; //effect slide in on top
$(document.body).addClass('dj-megamenu-offcanvas dj-offcanvas-effect-' + fx);
//if simple effect, no need to add pushers
if( !simple_fx ) {
if(content) $(document.body).prepend(wrapper);
if(fx == 3 || fx == 6 || fx == 7 || fx == 8 || fx == 14) {
pusher.append(offcanvas);
} else {
wrapper.append(offcanvas);
}
if(content) {
wrapper.append(pusher);
pusher.append(pusherIn);
pusherIn.append(content);
}
} else {
$(document.body).append(offcanvas); //move offcanvas to the end
}
allOffcanvas.hide();
var timer = null;
var btn_open = mobile.find('.dj-mobile-open-btn');
var btn_close = offcanvas.find('.dj-offcanvas-close-btn');
var last_item = offcanvas.find('button, a, input:not([type="hidden"]), select, textarea, [tabindex]:not([tabindex="-1"])').last();
btn_open.on('click', function(e){
e.stopPropagation();
e.preventDefault();
if( $(document.body).hasClass('dj-offcanvas-open') ) {
btn_open.removeClass('active');
btn_close.click();
} else {
btn_open.addClass('active');
clearTimeout(timer);
offcanvas.data('scroll', $(window).scrollTop());
$(document.body).addClass('dj-offcanvas-anim').removeClass('dj-offcanvas-no-effects');
setTimeout(function(){
$(document.body).addClass('dj-offcanvas-open');
}, 50 );
if( ! simple_fx ) {
pusherIn.css('top', -offcanvas.data('scroll'));
}
allOffcanvas.hide();
offcanvas.show();
offcanvas.removeAttr('aria-hidden');
offcanvas.attr('role', 'dialog');
offcanvas.attr('aria-modal', 'true');
offcanvas.addClass('dj-offcanvas-opened');
if( ! $('.dj-megamenu-offcanvas-overlay').length ) {
offcanvas.parent().append('<div class="dj-megamenu-offcanvas-overlay" />');
}
//move focus to offcanvas
setTimeout(function(){
btn_close.focus();
}, 250 );
}
});
btn_close.on('click', function(e) {
e.stopPropagation();
e.preventDefault();
if($(document.body).hasClass('dj-offcanvas-open')) {
btn_open.removeClass('active');
$(document.body).removeClass('dj-offcanvas-open');
if( $(document.body).hasClass('dj-offcanvas-no-effects') ) {
if( !simple_fx ) pusherIn.css('top', 0);
$(document.body).removeClass('dj-offcanvas-anim dj-offcanvas-no-effects');
offcanvas.hide();
btn_open.focus();
} else {
timer = setTimeout(function(){
if( !simple_fx ) pusherIn.css('top', 0);
$(document.body).removeClass('dj-offcanvas-anim');
$(window).scrollTop($(window).scrollTop() + offcanvas.data('scroll'));
offcanvas.hide();
btn_open.focus();
}, 250 );
}
offcanvas.attr('aria-hidden', 'true');
offcanvas.removeAttr('role');
offcanvas.removeAttr('aria-modal');
offcanvas.removeClass('dj-offcanvas-opened');
$(document.body).find('.dj-megamenu-offcanvas-overlay').remove();
}
});
btn_close.on('keydown', function(event){
if(event.key == 'Tab' && event.shiftKey) {
event.preventDefault();
last_item.focus();
}
});
last_item.on('keydown', function(event){
if(event.key == 'Tab' && !event.shiftKey) {
event.preventDefault();
btn_close.focus();
}
});
offcanvas.on('keydown', function(e) {
if (e.key === "Escape") {
btn_close.click();
}
});
this.initAccordion(offcanvas);
};
DJMegaMobile.prototype.createAccordion = function(mobile) {
var btn_open = mobile.find('.dj-mobile-open-btn');
btn_open.on('click', function(e){
e.stopPropagation();
e.preventDefault();
$(this).toggleClass('active');
mobile.find('.dj-accordion-in').slideToggle('fast');
});
$(document).on('click', function(e){
if(!$(e.target).closest('.dj-accordion-in').length) {
btn_open.removeClass('active');
if(mobile.find('.dj-accordion-in').is(':visible')) mobile.find('.dj-accordion-in').slideUp('fast');
}
});
this.initAccordion(mobile);
};
DJMegaMobile.prototype.switchMenu = function() {
var self = this;
window.clearTimeout(self.timer);
self.timer = window.setTimeout(function(){
for(var idx = 0; idx < self.mega.length; idx++) {
if(self.mega[idx].mobile) {
if(window.matchMedia("(max-width: "+self.mega[idx].trigger+"px)").matches) {
$(document.body).addClass('dj-megamenu-mobile');
$(document.body).addClass(self.mega[idx].id+'-mobile');
// we need only one menu in DOM
if($.contains(document, self.mega[idx].menu[0])) {
self.mega[idx].menu.after(self.mega[idx].menuHandler);
self.mega[idx].menu.detach();
}
if($.contains(document, self.mega[idx].mobileHandler[0])) {
self.mega[idx].mobileHandler.replaceWith(self.mega[idx].mobile);
}
if($.contains(document, self.mega[idx].offcanvasHandler[0])) {
self.mega[idx].offcanvasHandler.replaceWith(self.mega[idx].offcanvas);
}
} else {
$(document.body).removeClass('dj-megamenu-mobile dj-offcanvas-open dj-offcanvas-anim');
$(document.body).removeClass(self.mega[idx].id+'-mobile');
// we need only one menu in DOM
if($.contains(document, self.mega[idx].mobile[0])) {
self.mega[idx].mobile.after(self.mega[idx].mobileHandler);
self.mega[idx].mobile.detach();
}
if(self.mega[idx].offcanvas && $.contains(document, self.mega[idx].offcanvas[0])) {
self.mega[idx].offcanvas.after(self.mega[idx].offcanvasHandler);
self.mega[idx].offcanvas.detach();
}
if($.contains(document, self.mega[idx].menuHandler[0])) {
self.mega[idx].menuHandler.replaceWith(self.mega[idx].menu);
}
}
}
}
}, 100);
};
})(jQuery);
var initMobile = function() {
if (typeof jQuery == 'undefined') {
console.log('DJ-Megamenu: jQuery missing');
} else {
new DJMegaMobile;
}
}
if (document.readyState !== 'loading') {
initMobile();
} else {
document.addEventListener('DOMContentLoaded', function() {
initMobile();
});
}
window.addEventListener('load', function() {
if (typeof jQuery == 'undefined') {
console.log('DJ-Megamenu: jQuery missing');
} else {
jQuery(document).trigger('djmegamobile:pageload');
}
});