You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
5.6 KiB
208 lines
5.6 KiB
/** |
|
* Handles the resizing of a menu according to the available screen width |
|
* |
|
* Uses themes/original/css/resizable-menu.css.php |
|
* |
|
* To initialize: |
|
* $('#myMenu').menuResizer(function () { |
|
* // This function will be called to find out how much |
|
* // available horizontal space there is for the menu |
|
* return $('body').width() - 5; // Some extra margin for good measure |
|
* }); |
|
* |
|
* To trigger a resize operation: |
|
* $('#myMenu').menuResizer('resize'); // Bind this to $(window).resize() |
|
* |
|
* To restore the menu to a state like before it was initialized: |
|
* $('#myMenu').menuResizer('destroy'); |
|
* |
|
* @package PhpMyAdmin |
|
*/ |
|
(function ($) { |
|
function MenuResizer($container, widthCalculator) { |
|
var self = this; |
|
self.$container = $container; |
|
self.widthCalculator = widthCalculator; |
|
var windowWidth = $(window).width(); |
|
|
|
if (windowWidth < 768) { |
|
$('#pma_navigation_resizer').css({ |
|
'width': '0px' |
|
}); |
|
} // create submenu container |
|
|
|
|
|
var link = $('<a></a>', { |
|
'href': '#', |
|
'class': 'nav-link dropdown-toggle', |
|
'id': 'navbarDropdown', |
|
'role': 'button', |
|
'data-bs-toggle': 'dropdown', |
|
'aria-haspopup': 'true', |
|
'aria-expanded': 'false' |
|
}).text(Messages.strMore); |
|
var img = $container.find('li img'); |
|
|
|
if (img.length) { |
|
$(Functions.getImage('b_more').toString()).prependTo(link); |
|
} |
|
|
|
var $submenu = $('<li></li>', { |
|
'class': 'nav-item dropdown d-none' |
|
}).append(link).append($('<ul></ul>', { |
|
'class': 'dropdown-menu dropdown-menu-end', |
|
'aria-labelledby': 'navbarDropdown' |
|
})); |
|
$container.append($submenu); |
|
setTimeout(function () { |
|
self.resize(); |
|
}, 4); |
|
} |
|
|
|
MenuResizer.prototype.resize = function () { |
|
var wmax = this.widthCalculator.call(this.$container); |
|
var windowWidth = $(window).width(); |
|
var $submenu = this.$container.find('.nav-item.dropdown').last(); |
|
var submenuW = $submenu.outerWidth(true); |
|
var $submenuUl = $submenu.find('.dropdown-menu'); |
|
var $li = this.$container.find('> li'); |
|
var $li2 = $submenuUl.find('.dropdown-item'); |
|
var moreShown = $li2.length > 0; // Calculate the total width used by all the shown tabs |
|
|
|
var totalLen = moreShown ? submenuW : 0; |
|
var l = $li.length - 1; |
|
var i; |
|
|
|
for (i = 0; i < l; i++) { |
|
totalLen += $($li[i]).outerWidth(true); |
|
} // eslint-disable-next-line compat/compat |
|
|
|
|
|
var hasVScroll = document.body.scrollHeight > document.body.clientHeight; |
|
|
|
if (hasVScroll) { |
|
windowWidth += 15; |
|
} |
|
|
|
if (windowWidth < 768) { |
|
wmax = 2000; |
|
} // Now hide menu elements that don't fit into the menubar |
|
|
|
|
|
var hidden = false; // Whether we have hidden any tabs |
|
|
|
while (totalLen >= wmax && --l >= 0) { |
|
// Process the tabs backwards |
|
hidden = true; |
|
var el = $($li[l]); |
|
el.removeClass('nav-item').addClass('dropdown-item'); |
|
var elWidth = el.outerWidth(true); |
|
el.data('width', elWidth); |
|
|
|
if (!moreShown) { |
|
totalLen -= elWidth; |
|
el.prependTo($submenuUl); |
|
totalLen += submenuW; |
|
moreShown = true; |
|
} else { |
|
totalLen -= elWidth; |
|
el.prependTo($submenuUl); |
|
} |
|
} // If we didn't hide any tabs, then there might be some space to show some |
|
|
|
|
|
if (!hidden) { |
|
// Show menu elements that do fit into the menubar |
|
for (i = 0, l = $li2.length; i < l; i++) { |
|
totalLen += $($li2[i]).data('width'); // item fits or (it is the last item |
|
// and it would fit if More got removed) |
|
|
|
if (totalLen < wmax || i === $li2.length - 1 && totalLen - submenuW < wmax) { |
|
$($li2[i]).removeClass('dropdown-item').addClass('nav-item'); |
|
$($li2[i]).insertBefore($submenu); |
|
} else { |
|
break; |
|
} |
|
} |
|
} // Show/hide the "More" tab as needed |
|
|
|
|
|
if (windowWidth < 768) { |
|
$('.navbar-collapse').css({ |
|
'width': windowWidth - 80 - $('#pma_navigation').width() |
|
}); |
|
$submenu.addClass('d-none'); |
|
$('.navbar-collapse').css({ |
|
'overflow': 'hidden' |
|
}); |
|
} else { |
|
$('.navbar-collapse').css({ |
|
'width': 'auto' |
|
}); |
|
$('.navbar-collapse').css({ |
|
'overflow': 'visible' |
|
}); |
|
|
|
if ($submenuUl.find('li').length > 0) { |
|
$submenu.removeClass('d-none'); |
|
} else { |
|
$submenu.addClass('d-none'); |
|
} |
|
} |
|
}; |
|
|
|
MenuResizer.prototype.destroy = function () { |
|
var $submenu = this.$container.find('.nav-item.dropdown').removeData(); |
|
$submenu.find('li').appendTo(this.$container); |
|
$submenu.remove(); |
|
}; |
|
/** Public API */ |
|
|
|
|
|
var methods = { |
|
init: function (widthCalculator) { |
|
return this.each(function () { |
|
var $this = $(this); |
|
|
|
if (!$this.data('menuResizer')) { |
|
$this.data('menuResizer', new MenuResizer($this, widthCalculator)); |
|
} |
|
}); |
|
}, |
|
resize: function () { |
|
return this.each(function () { |
|
var self = $(this).data('menuResizer'); |
|
|
|
if (self) { |
|
self.resize(); |
|
} |
|
}); |
|
}, |
|
destroy: function () { |
|
return this.each(function () { |
|
var self = $(this).data('menuResizer'); |
|
|
|
if (self) { |
|
self.destroy(); |
|
} |
|
}); |
|
} |
|
}; |
|
/** |
|
* Extend jQuery |
|
* |
|
* @param {string} method |
|
* |
|
* @return {any} |
|
*/ |
|
|
|
$.fn.menuResizer = function (method) { |
|
if (methods[method]) { |
|
return methods[method].call(this); |
|
} else if (typeof method === 'function') { |
|
return methods.init.apply(this, [method]); |
|
} else { |
|
$.error('Method ' + method + ' does not exist on jQuery.menuResizer'); |
|
} |
|
}; |
|
})(jQuery); |