menu_resizer.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. "use strict";
  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 initialize:
  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();
  28. if (windowWidth < 768) {
  29. $('#pma_navigation_resizer').css({
  30. 'width': '0px'
  31. });
  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);
  42. var img = $container.find('li img');
  43. if (img.length) {
  44. $(Functions.getImage('b_more').toString()).prependTo(link);
  45. }
  46. var $submenu = $('<li></li>', {
  47. 'class': 'nav-item dropdown d-none'
  48. }).append(link).append($('<ul></ul>', {
  49. 'class': 'dropdown-menu dropdown-menu-right',
  50. 'aria-labelledby': 'navbarDropdown'
  51. }));
  52. $container.append($submenu);
  53. setTimeout(function () {
  54. self.resize();
  55. }, 4);
  56. }
  57. MenuResizer.prototype.resize = function () {
  58. var wmax = this.widthCalculator.call(this.$container);
  59. var windowWidth = $(window).width();
  60. var $submenu = this.$container.find('.nav-item.dropdown').last();
  61. var submenuW = $submenu.outerWidth(true);
  62. var $submenuUl = $submenu.find('.dropdown-menu');
  63. var $li = this.$container.find('> li');
  64. var $li2 = $submenuUl.find('.dropdown-item');
  65. var moreShown = $li2.length > 0; // Calculate the total width used by all the shown tabs
  66. var totalLen = moreShown ? submenuW : 0;
  67. var l = $li.length - 1;
  68. var i;
  69. for (i = 0; i < l; i++) {
  70. totalLen += $($li[i]).outerWidth(true);
  71. }
  72. var hasVScroll = document.body.scrollHeight > document.body.clientHeight;
  73. if (hasVScroll) {
  74. windowWidth += 15;
  75. }
  76. if (windowWidth < 768) {
  77. wmax = 2000;
  78. } // Now hide menu elements that don't fit into the menubar
  79. var hidden = false; // Whether we have hidden any tabs
  80. while (totalLen >= wmax && --l >= 0) {
  81. // Process the tabs backwards
  82. hidden = true;
  83. var el = $($li[l]);
  84. el.removeClass('nav-item').addClass('dropdown-item');
  85. var elWidth = el.outerWidth(true);
  86. el.data('width', elWidth);
  87. if (!moreShown) {
  88. totalLen -= elWidth;
  89. el.prependTo($submenuUl);
  90. totalLen += submenuW;
  91. moreShown = true;
  92. } else {
  93. totalLen -= elWidth;
  94. el.prependTo($submenuUl);
  95. }
  96. } // If we didn't hide any tabs, then there might be some space to show some
  97. if (!hidden) {
  98. // Show menu elements that do fit into the menubar
  99. for (i = 0, l = $li2.length; i < l; i++) {
  100. totalLen += $($li2[i]).data('width'); // item fits or (it is the last item
  101. // and it would fit if More got removed)
  102. if (totalLen < wmax || i === $li2.length - 1 && totalLen - submenuW < wmax) {
  103. $($li2[i]).removeClass('dropdown-item').addClass('nav-item');
  104. $($li2[i]).insertBefore($submenu);
  105. } else {
  106. break;
  107. }
  108. }
  109. } // Show/hide the "More" tab as needed
  110. if (windowWidth < 768) {
  111. $('.navbar-collapse').css({
  112. 'width': windowWidth - 80 - $('#pma_navigation').width()
  113. });
  114. $submenu.addClass('d-none');
  115. $('.navbar-collapse').css({
  116. 'overflow': 'hidden'
  117. });
  118. } else {
  119. $('.navbar-collapse').css({
  120. 'width': 'auto'
  121. });
  122. $('.navbar-collapse').css({
  123. 'overflow': 'visible'
  124. });
  125. if ($submenuUl.find('li').length > 0) {
  126. $submenu.removeClass('d-none');
  127. } else {
  128. $submenu.addClass('d-none');
  129. }
  130. }
  131. };
  132. MenuResizer.prototype.destroy = function () {
  133. var $submenu = this.$container.find('.nav-item.dropdown').removeData();
  134. $submenu.find('li').appendTo(this.$container);
  135. $submenu.remove();
  136. };
  137. /** Public API */
  138. var methods = {
  139. init: function init(widthCalculator) {
  140. return this.each(function () {
  141. var $this = $(this);
  142. if (!$this.data('menuResizer')) {
  143. $this.data('menuResizer', new MenuResizer($this, widthCalculator));
  144. }
  145. });
  146. },
  147. resize: function resize() {
  148. return this.each(function () {
  149. var self = $(this).data('menuResizer');
  150. if (self) {
  151. self.resize();
  152. }
  153. });
  154. },
  155. destroy: function destroy() {
  156. return this.each(function () {
  157. var self = $(this).data('menuResizer');
  158. if (self) {
  159. self.destroy();
  160. }
  161. });
  162. }
  163. };
  164. /** Extend jQuery */
  165. $.fn.menuResizer = function (method) {
  166. if (methods[method]) {
  167. return methods[method].call(this);
  168. } else if (typeof method === 'function') {
  169. return methods.init.apply(this, [method]);
  170. } else {
  171. $.error('Method ' + method + ' does not exist on jQuery.menuResizer');
  172. }
  173. };
  174. })(jQuery);