Translated using Weblate (Slovenian)
[phpmyadmin.git] / js / menu_resizer.js
blob0417f1257f2ab646cd36a2f10d0502a62c4538fe
1 /**
2  * Handles the resizing of a menu according to the available screen width
3  *
4  * Uses themes/original/css/resizable-menu.css.php
5  *
6  * To initialise:
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
11  * });
12  *
13  * To trigger a resize operation:
14  * $('#myMenu').menuResizer('resize'); // Bind this to $(window).resize()
15  *
16  * To restore the menu to a state like before it was initialized:
17  * $('#myMenu').menuResizer('destroy');
18  *
19  * @package PhpMyAdmin
20  */
21 (function ($) {
22     function MenuResizer ($container, widthCalculator) {
23         var self = this;
24         self.$container = $container;
25         self.widthCalculator = widthCalculator;
26         var windowWidth = $(window).width();
28         if (windowWidth < 768) {
29             $('#pma_navigation_resizer').css({ 'width': '0px' });
30         }
32         // create submenu container
33         var link = $('<a></a>', {
34             'href': '#',
35             'class': 'nav-link dropdown-toggle',
36             'id': 'navbarDropdown',
37             'role': 'button',
38             'data-toggle': 'dropdown',
39             'aria-haspopup': 'true',
40             'aria-expanded': 'false'
41         }).text(Messages.strMore);
43         var img = $container.find('li img');
44         if (img.length) {
45             $(Functions.getImage('b_more').toString()).prependTo(link);
46         }
47         var $submenu = $('<li></li>', { 'class': 'nav-item dropdown d-none' })
48             .append(link)
49             .append($('<ul></ul>', {
50                 'class': 'dropdown-menu dropdown-menu-right',
51                 'aria-labelledby': 'navbarDropdown'
52             }));
53         $container.append($submenu);
54         setTimeout(function () {
55             self.resize();
56         }, 4);
57     }
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;
70         var i;
71         for (i = 0; i < l; i++) {
72             totalLen += $($li[i]).outerWidth(true);
73         }
75         var hasVScroll = document.body.scrollHeight > document.body.clientHeight;
76         if (hasVScroll) {
77             windowWidth += 15;
78         }
79         if (windowWidth < 768) {
80             wmax = 2000;
81         }
83         // Now hide menu elements that don't fit into the menubar
84         var hidden = false; // Whether we have hidden any tabs
85         while (totalLen >= wmax && --l >= 0) { // Process the tabs backwards
86             hidden = true;
87             var el = $($li[l]);
88             el.removeClass('nav-item').addClass('dropdown-item');
89             var elWidth = el.outerWidth(true);
90             el.data('width', elWidth);
91             if (! moreShown) {
92                 totalLen -= elWidth;
93                 el.prependTo($submenuUl);
94                 totalLen += submenuW;
95                 moreShown = true;
96             } else {
97                 totalLen -= elWidth;
98                 el.prependTo($submenuUl);
99             }
100         }
101         // If we didn't hide any tabs, then there might be some space to show some
102         if (! hidden) {
103             // Show menu elements that do fit into the menubar
104             for (i = 0, l = $li2.length; i < l; i++) {
105                 totalLen += $($li2[i]).data('width');
106                 // item fits or (it is the last item
107                 // and it would fit if More got removed)
108                 if (totalLen < wmax ||
109                     (i === $li2.length - 1 && totalLen - submenuW < wmax)
110                 ) {
111                     $($li2[i]).removeClass('dropdown-item').addClass('nav-item');
112                     $($li2[i]).insertBefore($submenu);
113                 } else {
114                     break;
115                 }
116             }
117         }
118         // Show/hide the "More" tab as needed
119         if (windowWidth < 768) {
120             $('.navbar-collapse').css({ 'width': windowWidth - 80 - $('#pma_navigation').width() });
121             $submenu.addClass('d-none');
122             $('.navbar-collapse').css({ 'overflow': 'hidden' });
123         } else {
124             $('.navbar-collapse').css({ 'width': 'auto' });
125             $('.navbar-collapse').css({ 'overflow': 'visible' });
126             if ($submenuUl.find('li').length > 0) {
127                 $submenu.removeClass('d-none');
128             } else {
129                 $submenu.addClass('d-none');
130             }
131         }
132     };
133     MenuResizer.prototype.destroy = function () {
134         var $submenu = this.$container.find('.nav-item.dropdown').removeData();
135         $submenu.find('li').appendTo(this.$container);
136         $submenu.remove();
137     };
139     /** Public API */
140     var methods = {
141         init: function (widthCalculator) {
142             return this.each(function () {
143                 var $this = $(this);
144                 if (! $this.data('menuResizer')) {
145                     $this.data(
146                         'menuResizer',
147                         new MenuResizer($this, widthCalculator)
148                     );
149                 }
150             });
151         },
152         resize: function () {
153             return this.each(function () {
154                 var self = $(this).data('menuResizer');
155                 if (self) {
156                     self.resize();
157                 }
158             });
159         },
160         destroy: function () {
161             return this.each(function () {
162                 var self = $(this).data('menuResizer');
163                 if (self) {
164                     self.destroy();
165                 }
166             });
167         }
168     };
170     /** Extend jQuery */
171     $.fn.menuResizer = function (method) {
172         if (methods[method]) {
173             return methods[method].call(this);
174         } else if (typeof method === 'function') {
175             return methods.init.apply(this, [method]);
176         } else {
177             $.error('Method ' +  method + ' does not exist on jQuery.menuResizer');
178         }
179     };
180 }(jQuery));