1 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 * Handles the resizing of a menu according to the available screen width
5 * Uses themes/original/css/resizable-menu.css.php
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
14 * To trigger a resize operation:
15 * $('#myMenu').menuResizer('resize'); // Bind this to $(window).resize()
17 * To restore the menu to a state like before it was initialized:
18 * $('#myMenu').menuResizer('destroy');
23 function MenuResizer ($container, widthCalculator) {
25 self.$container = $container;
26 self.widthCalculator = widthCalculator;
27 var windowWidth = $(window).width();
29 if (windowWidth < 768) {
30 $('#pma_navigation_resizer').css({ 'width': '0px' });
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);
43 $('.scrollindicator--left').on('click', function () {
44 $('.navigationbar').scrollLeft($('.navigationbar').scrollLeft() - 70);
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');
53 $(PMA_getImage('b_more').toString()).prependTo(link);
55 var $submenu = $('<li></li>', { 'class': 'submenu' })
57 .append($('<ul></ul>'))
58 .on('mouseenter', function () {
59 if ($(this).find('ul .tabactive').length === 0) {
61 .addClass('submenuhover')
63 .addClass('tabactive');
66 .on('mouseleave', function () {
67 if ($(this).find('ul .tabactive').length === 0) {
69 .removeClass('submenuhover')
71 .removeClass('tabactive');
74 $container.children('.clearfloat').remove();
75 $container.append($submenu).append('<div class=\'clearfloat\'></div>');
76 setTimeout(function () {
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;
93 for (i = 0; i < l; i++) {
94 total_len += $($li[i]).outerWidth(true);
97 var hasVScroll = document.body.scrollHeight > document.body.clientHeight;
101 var navigationwidth = wmax;
102 if (windowWidth < 768) {
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
111 var el_width = el.outerWidth(true);
112 el.data('width', el_width);
114 total_len -= el_width;
115 el.prependTo($submenu_ul);
116 total_len += submenu_w;
119 total_len -= el_width;
120 el.prependTo($submenu_ul);
123 // If we didn't hide any tabs, then there might be some space to show some
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)
133 $($li2[i]).insertBefore($submenu);
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' });
145 $('.navigationbar').css({ 'width': 'auto' });
146 $('.navigationbar').css({ 'overflow': 'visible' });
147 if ($submenu_ul.find('li').length > 0) {
148 $submenu.addClass('shown');
150 $submenu.removeClass('shown');
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');
158 // Otherwise we align the submenu to the right edge of the tab
159 $submenu_ul.removeClass().addClass('notonly');
161 if ($submenu.find('.tabactive').length) {
166 .addClass('tabactive');
169 .removeClass('active')
172 .removeClass('tabactive');
175 MenuResizer.prototype.destroy = function () {
176 var $submenu = this.$container.find('li.submenu').removeData();
177 $submenu.find('li').appendTo(this.$container);
183 init: function (widthCalculator) {
184 return this.each(function () {
186 if (! $this.data('menuResizer')) {
189 new MenuResizer($this, widthCalculator)
194 resize: function () {
195 return this.each(function () {
196 var self = $(this).data('menuResizer');
202 destroy: function () {
203 return this.each(function () {
204 var self = $(this).data('menuResizer');
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]);
219 $.error('Method ' + method + ' does not exist on jQuery.menuResizer');