2 * Handles the resizing of a menu according to the available screen width
4 * Uses themes/original/css/resizable-menu.css.php
7 * $('#myMenu').menuResizer(function () {
8 * // This function will be called to find out how much
9 * // available horizontal space there is for the menu
10 * return $('body').width() - 5; // Some extra margin for good measure
13 * To trigger a resize operation:
14 * $('#myMenu').menuResizer('resize'); // Bind this to $(window).resize()
16 * To restore the menu to a state like before it was initialized:
17 * $('#myMenu').menuResizer('destroy');
22 function MenuResizer ($container, widthCalculator) {
24 self.$container = $container;
25 self.widthCalculator = widthCalculator;
26 var windowWidth = $(window).width();
28 if (windowWidth < 768) {
29 $('#pma_navigation_resizer').css({ 'width': '0px' });
32 // create submenu container
33 var link = $('<a></a>', {
35 'class': 'nav-link dropdown-toggle',
36 'id': 'navbarDropdown',
38 'data-bs-toggle': 'dropdown',
39 'aria-haspopup': 'true',
40 'aria-expanded': 'false'
41 }).text(Messages.strMore);
43 var img = $container.find('li img');
45 $(Functions.getImage('b_more').toString()).prependTo(link);
47 var $submenu = $('<li></li>', { 'class': 'nav-item dropdown d-none' })
49 .append($('<ul></ul>', {
50 'class': 'dropdown-menu dropdown-menu-end',
51 'aria-labelledby': 'navbarDropdown'
53 $container.append($submenu);
54 setTimeout(function () {
58 MenuResizer.prototype.resize = function () {
59 var wmax = this.widthCalculator.call(this.$container);
60 var windowWidth = $(window).width();
61 var $submenu = this.$container.find('.nav-item.dropdown').last();
62 var submenuW = $submenu.outerWidth(true);
63 var $submenuUl = $submenu.find('.dropdown-menu');
64 var $li = this.$container.find('> li');
65 var $li2 = $submenuUl.find('.dropdown-item');
66 var moreShown = $li2.length > 0;
67 // Calculate the total width used by all the shown tabs
68 var totalLen = moreShown ? submenuW : 0;
69 var l = $li.length - 1;
71 for (i = 0; i < l; i++) {
72 totalLen += $($li[i]).outerWidth(true);
75 // eslint-disable-next-line compat/compat
76 var hasVScroll = document.body.scrollHeight > document.body.clientHeight;
80 if (windowWidth < 768) {
84 // Now hide menu elements that don't fit into the menubar
85 var hidden = false; // Whether we have hidden any tabs
86 while (totalLen >= wmax && --l >= 0) { // Process the tabs backwards
89 el.removeClass('nav-item').addClass('dropdown-item');
90 var elWidth = el.outerWidth(true);
91 el.data('width', elWidth);
94 el.prependTo($submenuUl);
99 el.prependTo($submenuUl);
102 // If we didn't hide any tabs, then there might be some space to show some
104 // Show menu elements that do fit into the menubar
105 for (i = 0, l = $li2.length; i < l; i++) {
106 totalLen += $($li2[i]).data('width');
107 // item fits or (it is the last item
108 // and it would fit if More got removed)
109 if (totalLen < wmax ||
110 (i === $li2.length - 1 && totalLen - submenuW < wmax)
112 $($li2[i]).removeClass('dropdown-item').addClass('nav-item');
113 $($li2[i]).insertBefore($submenu);
119 // Show/hide the "More" tab as needed
120 if (windowWidth < 768) {
121 $('.navbar-collapse').css({ 'width': windowWidth - 80 - $('#pma_navigation').width() });
122 $submenu.addClass('d-none');
123 $('.navbar-collapse').css({ 'overflow': 'hidden' });
125 $('.navbar-collapse').css({ 'width': 'auto' });
126 $('.navbar-collapse').css({ 'overflow': 'visible' });
127 if ($submenuUl.find('li').length > 0) {
128 $submenu.removeClass('d-none');
130 $submenu.addClass('d-none');
134 MenuResizer.prototype.destroy = function () {
135 var $submenu = this.$container.find('.nav-item.dropdown').removeData();
136 $submenu.find('li').appendTo(this.$container);
142 init: function (widthCalculator) {
143 return this.each(function () {
145 if (! $this.data('menuResizer')) {
148 new MenuResizer($this, widthCalculator)
153 resize: function () {
154 return this.each(function () {
155 var self = $(this).data('menuResizer');
161 destroy: function () {
162 return this.each(function () {
163 var self = $(this).data('menuResizer');
174 * @param {string} method
178 $.fn.menuResizer = function (method) {
179 if (methods[method]) {
180 return methods[method].call(this);
181 } else if (typeof method === 'function') {
182 return methods.init.apply(this, [method]);
184 $.error('Method ' + method + ' does not exist on jQuery.menuResizer');