Translated using Weblate (Slovenian)
[phpmyadmin.git] / js / menu-resizer.js
blob3f70505d6470ebebee1d278ca1997586cda7c3fe
1 /* vim: set expandtab sw=4 ts=4 sts=4: */
2 /**
3  * Handles the resizing of a menu according to the available screen width
4  *
5  * Uses themes/original/css/resizable-menu.css.php
6  *
7  * To initialise:
8  * $('#myMenu').menuResizer(function () {
9  *     // This function will be called to find out how much
10  *     // available horizontal space there is for the menu
11  *     return $('body').width() - 5; // Some extra margin for good measure
12  * });
13  *
14  * To trigger a resize operation:
15  * $('#myMenu').menuResizer('resize'); // Bind this to $(window).resize()
16  *
17  * To restore the menu to a state like before it was initialized:
18  * $('#myMenu').menuResizer('destroy');
19  *
20  * @package PhpMyAdmin
21  */
22 (function ($) {
23     function MenuResizer ($container, widthCalculator) {
24         var self = this;
25         self.$container = $container;
26         self.widthCalculator = widthCalculator;
27         var windowWidth = $(window).width();
29         if (windowWidth < 768) {
30             $('#pma_navigation_resizer').css({ 'width': '0px' });
31         }
32         // Sets the image for the left and right scroll indicator
33         $('.scrollindicator--left').html($(PMA_getImage('b_left').toString()));
34         $('.scrollindicator--right').html($(PMA_getImage('b_right').toString()));
36         // Set the width of the navigation bar without scroll indicator
37         $('.navigationbar').css({ 'width': widthCalculator.call($container) - 60 });
39         // Scroll the navigation bar on click
40         $('.scrollindicator--right').on('click', function () {
41             $('.navigationbar').scrollLeft($('.navigationbar').scrollLeft() + 70);
42         });
43         $('.scrollindicator--left').on('click', function () {
44             $('.navigationbar').scrollLeft($('.navigationbar').scrollLeft() - 70);
45         });
47         // create submenu container
48         var link = $('<a></a>', { href: '#', 'class': 'tab nowrap' })
49             .text(PMA_messages.strMore)
50             .on('click', false); // same as event.preventDefault()
51         var img = $container.find('li img');
52         if (img.length) {
53             $(PMA_getImage('b_more').toString()).prependTo(link);
54         }
55         var $submenu = $('<li></li>', { 'class': 'submenu' })
56             .append(link)
57             .append($('<ul></ul>'))
58             .on('mouseenter', function () {
59                 if ($(this).find('ul .tabactive').length === 0) {
60                     $(this)
61                         .addClass('submenuhover')
62                         .find('> a')
63                         .addClass('tabactive');
64                 }
65             })
66             .on('mouseleave', function () {
67                 if ($(this).find('ul .tabactive').length === 0) {
68                     $(this)
69                         .removeClass('submenuhover')
70                         .find('> a')
71                         .removeClass('tabactive');
72                 }
73             });
74         $container.children('.clearfloat').remove();
75         $container.append($submenu).append('<div class=\'clearfloat\'></div>');
76         setTimeout(function () {
77             self.resize();
78         }, 4);
79     }
80     MenuResizer.prototype.resize = function () {
81         var wmax = this.widthCalculator.call(this.$container);
82         var windowWidth = $(window).width();
83         var $submenu = this.$container.find('.submenu:last');
84         var submenu_w = $submenu.outerWidth(true);
85         var $submenu_ul = $submenu.find('ul');
86         var $li = this.$container.find('> li');
87         var $li2 = $submenu_ul.find('li');
88         var more_shown = $li2.length > 0;
89         // Calculate the total width used by all the shown tabs
90         var total_len = more_shown ? submenu_w : 0;
91         var l = $li.length - 1;
92         var i;
93         for (i = 0; i < l; i++) {
94             total_len += $($li[i]).outerWidth(true);
95         }
97         var hasVScroll = document.body.scrollHeight > document.body.clientHeight;
98         if (hasVScroll) {
99             windowWidth += 15;
100         }
101         var navigationwidth = wmax;
102         if (windowWidth < 768) {
103             wmax = 2000;
104         }
106         // Now hide menu elements that don't fit into the menubar
107         var hidden = false; // Whether we have hidden any tabs
108         while (total_len >= wmax && --l >= 0) { // Process the tabs backwards
109             hidden = true;
110             var el = $($li[l]);
111             var el_width = el.outerWidth(true);
112             el.data('width', el_width);
113             if (! more_shown) {
114                 total_len -= el_width;
115                 el.prependTo($submenu_ul);
116                 total_len += submenu_w;
117                 more_shown = true;
118             } else {
119                 total_len -= el_width;
120                 el.prependTo($submenu_ul);
121             }
122         }
123         // If we didn't hide any tabs, then there might be some space to show some
124         if (! hidden) {
125             // Show menu elements that do fit into the menubar
126             for (i = 0, l = $li2.length; i < l; i++) {
127                 total_len += $($li2[i]).data('width');
128                 // item fits or (it is the last item
129                 // and it would fit if More got removed)
130                 if (total_len < wmax ||
131                     (i === $li2.length - 1 && total_len - submenu_w < wmax)
132                 ) {
133                     $($li2[i]).insertBefore($submenu);
134                 } else {
135                     break;
136                 }
137             }
138         }
139         // Show/hide the "More" tab as needed
140         if (windowWidth < 768) {
141             $('.navigationbar').css({ 'width': windowWidth - 80 - $('#pma_navigation').width() });
142             $submenu.removeClass('shown');
143             $('.navigationbar').css({ 'overflow': 'hidden' });
144         } else {
145             $('.navigationbar').css({ 'width': 'auto' });
146             $('.navigationbar').css({ 'overflow': 'visible' });
147             if ($submenu_ul.find('li').length > 0) {
148                 $submenu.addClass('shown');
149             } else {
150                 $submenu.removeClass('shown');
151             }
152         }
153         if (this.$container.find('> li').length === 1) {
154             // If there is only the "More" tab left, then we need
155             // to align the submenu to the left edge of the tab
156             $submenu_ul.removeClass().addClass('only');
157         } else {
158             // Otherwise we align the submenu to the right edge of the tab
159             $submenu_ul.removeClass().addClass('notonly');
160         }
161         if ($submenu.find('.tabactive').length) {
162             $submenu
163                 .addClass('active')
164                 .find('> a')
165                 .removeClass('tab')
166                 .addClass('tabactive');
167         } else {
168             $submenu
169                 .removeClass('active')
170                 .find('> a')
171                 .addClass('tab')
172                 .removeClass('tabactive');
173         }
174     };
175     MenuResizer.prototype.destroy = function () {
176         var $submenu = this.$container.find('li.submenu').removeData();
177         $submenu.find('li').appendTo(this.$container);
178         $submenu.remove();
179     };
181     /** Public API */
182     var methods = {
183         init: function (widthCalculator) {
184             return this.each(function () {
185                 var $this = $(this);
186                 if (! $this.data('menuResizer')) {
187                     $this.data(
188                         'menuResizer',
189                         new MenuResizer($this, widthCalculator)
190                     );
191                 }
192             });
193         },
194         resize: function () {
195             return this.each(function () {
196                 var self = $(this).data('menuResizer');
197                 if (self) {
198                     self.resize();
199                 }
200             });
201         },
202         destroy: function () {
203             return this.each(function () {
204                 var self = $(this).data('menuResizer');
205                 if (self) {
206                     self.destroy();
207                 }
208             });
209         }
210     };
212     /** Extend jQuery */
213     $.fn.menuResizer = function (method) {
214         if (methods[method]) {
215             return methods[method].call(this);
216         } else if (typeof method === 'function') {
217             return methods.init.apply(this, [method]);
218         } else {
219             $.error('Method ' +  method + ' does not exist on jQuery.menuResizer');
220         }
221     };
222 }(jQuery));