diff --git a/js/ajax.js b/js/ajax.js
index ea77103082..3060ab1c33 100644
--- a/js/ajax.js
+++ b/js/ajax.js
@@ -615,8 +615,7 @@ AJAX.cache = {
// Remove duplicate wrapper
// TODO: don't send it in the response
.children().first().remove();
- menuPrepare($('#topmenu'));
- menuResize($('#topmenu'));
+ $('#topmenu').menuResizer(PMA_mainMenuResizerCallback);
}
}
};
diff --git a/js/functions.js b/js/functions.js
index ec1877f4d2..1b66a3230c 100644
--- a/js/functions.js
+++ b/js/functions.js
@@ -2813,138 +2813,17 @@ AJAX.registerOnload('functions.js', function() {
PMA_showHints();
});
-/**
- * This function handles the resizing of the content frame
- * and adjusts the top menu according to the new size of the frame
- *
- * @param object $container jquery object, menu container object
- *
- * @return void
- */
-function menuResize($container)
-{
- if ($container.length == 0) {
- return;
- }
- var wmax = $container.innerWidth();
- wmax -= $('#pma_navigation').width();
- wmax -= $('#pma_navigation_resizer').width();
- wmax -= 5 ; // 5 px margin for jumping menu in Chrome
- var $submenu = $container.find('.submenu');
- var submenu_w = $submenu.outerWidth(true);
- var $submenu_ul = $submenu.find('ul');
- var $li = $container.find('> li');
- var $li2 = $submenu_ul.find('li');
- var more_shown = $li2.length > 0;
-
- // Calculate the total width used by all the shown tabs
- var total_len = more_shown ? submenu_w : 0;
- var l = $li.length - 1;
- for (var i = 0; i < l; i++) {
- total_len += $($li[i]).outerWidth(true);
- }
-
- // Now hide menu elements that don't fit into the menubar
- var hidden = false; // Whether we have hidden any tabs
- while (total_len >= wmax && --l >= 0) { // Process the tabs backwards
- hidden = true;
- var el = $($li[l]);
- var el_width = el.outerWidth(true);
- el.data('width', el_width);
- if (! more_shown) {
- total_len -= el_width;
- el.prependTo($submenu_ul);
- total_len += submenu_w;
- more_shown = true;
- } else {
- total_len -= el_width;
- el.prependTo($submenu_ul);
- }
- }
-
- // If we didn't hide any tabs, then there might be some space to show some
- if (! hidden) {
- // Show menu elements that do fit into the menubar
- for (var i = 0, l = $li2.length; i < l; i++) {
- total_len += $($li2[i]).data('width');
- // item fits or (it is the last item
- // and it would fit if More got removed)
- if (total_len < wmax
- || (i == $li2.length - 1 && total_len - submenu_w < wmax)
- ) {
- $($li2[i]).insertBefore($submenu);
- } else {
- break;
- }
- }
- }
-
- // Show/hide the "More" tab as needed
- if ($submenu_ul.find('li').length > 0) {
- $submenu.addClass('shown');
- } else {
- $submenu.removeClass('shown');
- }
-
- if ($container.find('> li').length == 1) {
- // If there is only the "More" tab left, then we need
- // to align the submenu to the left edge of the tab
- $submenu_ul.removeClass().addClass('only');
- } else {
- // Otherwise we align the submenu to the right edge of the tab
- $submenu_ul.removeClass().addClass('notonly');
- }
-
- if ($submenu.find('.tabactive').length) {
- $submenu.addClass('active').find('> a').removeClass('tab').addClass('tabactive');
- } else {
- $submenu.removeClass('active').find('> a').addClass('tab').removeClass('tabactive');
- }
+function PMA_mainMenuResizerCallback() {
+ // 5 px margin for jumping menu in Chrome
+ return $('body').width() - 5;
}
-
-/**
- * Prepares a horizontal menu for adapting to the screen width
- *
- * @param object $container jquery object, menu container object
- *
- * @return void
- */
-function menuPrepare($container)
-{
- if ($container.length == 0) {
- return;
- }
- // create submenu container
- var link = $('', {href: '#', 'class': 'tab'})
- .text(PMA_messages['strMore'])
- .bind('click', false); // same as event.preventDefault()
- var img = $container.find('li img');
- if (img.length) {
- $(PMA_getImage('b_more.png').toString()).prependTo(link);
- }
- var $submenu = $('
', {'class': 'submenu'})
- .append(link)
- .append($(''))
- .mouseenter(function() {
- if ($(this).find('ul .tabactive').length == 0) {
- $(this).addClass('submenuhover').find('> a').addClass('tabactive');
- }
- })
- .mouseleave(function() {
- if ($(this).find('ul .tabactive').length == 0) {
- $(this).removeClass('submenuhover').find('> a').removeClass('tabactive');
- }
- });
- $container.append($submenu);
-}
-
// This must be fired only once after the inital page load
$(function() {
- menuPrepare($('#topmenu'));
- // populate submenu and register resize event
- menuResize($('#topmenu'));
+ // Initialise the menu resize plugin
+ $('#topmenu').menuResizer(PMA_mainMenuResizerCallback);
+ // register resize event
$(window).resize(function (){
- menuResize($('#topmenu'));
+ $('#topmenu').menuResizer('resize');
});
});
@@ -3651,7 +3530,7 @@ AJAX.registerOnload('functions.js', function() {
'padding-top',
$('#floating_menubar').outerHeight(true)
);
- menuResize($('#topmenu'));
+ $('#topmenu').menuResizer('resize');
}
/**
diff --git a/js/jquery/jquery.menuResizer-1.0.js b/js/jquery/jquery.menuResizer-1.0.js
new file mode 100644
index 0000000000..1627ca729e
--- /dev/null
+++ b/js/jquery/jquery.menuResizer-1.0.js
@@ -0,0 +1,168 @@
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Handles the resizing of a menu according to the available screen width
+ *
+ * Uses themes/original/css/resizable-menu.css.php
+
+ * @package PhpMyAdmin
+ */
+(function ($) {
+ function MenuResizer($container, widthCalculator) {
+ var self = this;
+ self.$container = $container;
+ self.widthCalculator = widthCalculator;
+ // create submenu container
+ var link = $('', {href: '#', 'class': 'tab nowrap'})
+ .text(PMA_messages['strMore'])
+ .bind('click', false); // same as event.preventDefault()
+ var img = $container.find('li img');
+ if (img.length) {
+ $(PMA_getImage('b_more.png').toString()).prependTo(link);
+ }
+ var $submenu = $('', {'class': 'submenu'})
+ .append(link)
+ .append($(''))
+ .mouseenter(function() {
+ if ($(this).find('ul .tabactive').length == 0) {
+ $(this)
+ .addClass('submenuhover')
+ .find('> a')
+ .addClass('tabactive');
+ }
+ })
+ .mouseleave(function() {
+ if ($(this).find('ul .tabactive').length == 0) {
+ $(this)
+ .removeClass('submenuhover')
+ .find('> a')
+ .removeClass('tabactive');
+ }
+ });
+ $container.append($submenu);
+ setTimeout(function () {
+ self.resize();
+ }, 4);
+ }
+ MenuResizer.prototype.resize = function () {
+ var wmax = this.widthCalculator.call(this.$container);
+ var $submenu = this.$container.find('.submenu:last');
+ var submenu_w = $submenu.outerWidth(true);
+ var $submenu_ul = $submenu.find('ul');
+ var $li = this.$container.find('> li');
+ var $li2 = $submenu_ul.find('li');
+ var more_shown = $li2.length > 0;
+ // Calculate the total width used by all the shown tabs
+ var total_len = more_shown ? submenu_w : 0;
+ var l = $li.length - 1;
+ for (var i = 0; i < l; i++) {
+ total_len += $($li[i]).outerWidth(true);
+ }
+ // Now hide menu elements that don't fit into the menubar
+ var hidden = false; // Whether we have hidden any tabs
+ while (total_len >= wmax && --l >= 0) { // Process the tabs backwards
+ hidden = true;
+ var el = $($li[l]);
+ var el_width = el.outerWidth(true);
+ el.data('width', el_width);
+ if (! more_shown) {
+ total_len -= el_width;
+ el.prependTo($submenu_ul);
+ total_len += submenu_w;
+ more_shown = true;
+ } else {
+ total_len -= el_width;
+ el.prependTo($submenu_ul);
+ }
+ }
+ // If we didn't hide any tabs, then there might be some space to show some
+ if (! hidden) {
+ // Show menu elements that do fit into the menubar
+ for (var i = 0, l = $li2.length; i < l; i++) {
+ total_len += $($li2[i]).data('width');
+ // item fits or (it is the last item
+ // and it would fit if More got removed)
+ if (total_len < wmax
+ || (i == $li2.length - 1 && total_len - submenu_w < wmax)
+ ) {
+ $($li2[i]).insertBefore($submenu);
+ } else {
+ break;
+ }
+ }
+ }
+ // Show/hide the "More" tab as needed
+ if ($submenu_ul.find('li').length > 0) {
+ $submenu.addClass('shown');
+ } else {
+ $submenu.removeClass('shown');
+ }
+ if (this.$container.find('> li').length == 1) {
+ // If there is only the "More" tab left, then we need
+ // to align the submenu to the left edge of the tab
+ $submenu_ul.removeClass().addClass('only');
+ } else {
+ // Otherwise we align the submenu to the right edge of the tab
+ $submenu_ul.removeClass().addClass('notonly');
+ }
+ if ($submenu.find('.tabactive').length) {
+ $submenu
+ .addClass('active')
+ .find('> a')
+ .removeClass('tab')
+ .addClass('tabactive');
+ } else {
+ $submenu
+ .removeClass('active')
+ .find('> a')
+ .addClass('tab')
+ .removeClass('tabactive');
+ }
+ };
+ MenuResizer.prototype.destroy = function () {
+ var $submenu = this.$container.find('li.submenu').removeData();
+ $submenu.find('li').appendTo(this.$container);
+ $submenu.remove();
+ };
+
+ /** Public API */
+ var methods = {
+ init: function(widthCalculator) {
+ return this.each(function () {
+ var $this = $(this);
+ if (! $this.data('menuResizer')) {
+ $this.data(
+ 'menuResizer',
+ new MenuResizer($this, widthCalculator)
+ );
+ }
+ });
+ },
+ resize: function () {
+ return this.each(function () {
+ var self = $(this).data('menuResizer');
+ if (self) {
+ self.resize();
+ }
+ });
+ },
+ destroy: function () {
+ return this.each(function () {
+ var self = $(this).data('menuResizer');
+ if (self) {
+ self.destroy();
+ }
+ });
+ }
+ };
+
+ /** Extend jQuery */
+ $.fn.menuResizer = function(method) {
+ if (methods[method]) {
+ return methods[method].call(this);
+ } else if (typeof method === 'function') {
+ return methods.init.apply(this, [method]);
+ } else {
+ $.error('Method ' + method + ' does not exist on jQuery.menuResizer');
+ }
+ };
+})(jQuery);
diff --git a/js/navigation.js b/js/navigation.js
index 3b0cf4c3e0..fc6dc0f48b 100644
--- a/js/navigation.js
+++ b/js/navigation.js
@@ -528,6 +528,9 @@ var ResizeHandler = function () {
this.left,
(pos - $('#pma_navigation_scrollbar').width()) + 'px'
);
+ setTimeout(function (){
+ $(window).trigger('resize');
+ }, 4);
};
/**
* Returns the horizontal position of the mouse,
@@ -598,7 +601,7 @@ var ResizeHandler = function () {
event.data.resize_handler.active = false;
$('body').css('cursor', '');
$.cookie('pma_navi_width', event.data.resize_handler.getPos(event));
- menuResize($('#topmenu'));
+ $('#topmenu').menuResizer('resize');
}
};
/**
@@ -638,7 +641,7 @@ var ResizeHandler = function () {
// If we have a cookie, set the width of the panel to its value
var pos = Math.abs(parseInt($.cookie('pma_navi_width'), 10));
this.setWidth(pos);
- menuResize($('#topmenu'));
+ $('#topmenu').menuResizer('resize');
}
// Register the events for the resizer and the collapser
$('#pma_navigation_resizer')
diff --git a/js/tbl_structure.js b/js/tbl_structure.js
index ff3b5981c0..cdc6f78364 100644
--- a/js/tbl_structure.js
+++ b/js/tbl_structure.js
@@ -252,6 +252,7 @@ AJAX.registerOnload('tbl_structure.js', function() {
buttons: button_options_error
}); // end dialog options
} else {
+ $('#fieldsForm ul.table-structure-actions').menuResizer('destroy');
// sort the fields table
var $fields_table = $("table#tablestructure tbody");
// remove all existing rows and remember them
@@ -277,6 +278,7 @@ AJAX.registerOnload('tbl_structure.js', function() {
}
PMA_ajaxShowMessage(data.message);
$this.dialog('close');
+ $('#fieldsForm ul.table-structure-actions').menuResizer(PMA_tbl_structure_menu_resizer);
}
});
};
@@ -337,12 +339,44 @@ function reloadFieldForm(message) {
$("#addColumns").replaceWith($temp_div.find("#addColumns"));
$('#move_columns_dialog ul').replaceWith($temp_div.find("#move_columns_dialog ul"));
$("#moveColumns").removeClass("move-active");
- /* Call the function to display the more options in table */
- $table_clone = false;
- $("div.replace_in_more").hide(); // fix "more" dropdown
- moreOptsMenuResize();
+ /* reinitialise the more options in table */
+ $('#fieldsForm ul.table-structure-actions').menuResizer(PMA_tbl_structure_menu_resizer_callback);
setTimeout(function() {
PMA_ajaxShowMessage(message);
}, 500);
});
}
+
+function PMA_tbl_structure_menu_resizer_callback() {
+ var pagewidth = $('body').width();
+ var $page = $('#page_content');
+ pagewidth -= $page.outerWidth(true) - $page.outerWidth();
+ var columnsWidth = 0;
+ var $columns = $('#tablestructure').find('tr:eq(1)').find('td,th');
+ $columns.not(':last').each(function (){
+ columnsWidth += $(this).outerWidth(true)
+ })
+ var totalCellSpacing = $('#tablestructure').width();
+ $columns.each(function (){
+ totalCellSpacing -= $(this).outerWidth(true);
+ });
+ return pagewidth - columnsWidth - totalCellSpacing - 15; // 15px extra margin
+};
+
+/** Handler for "More" dropdown in structure table rows */
+AJAX.registerOnload('tbl_structure.js', function() {
+ if ($('#fieldsForm').hasClass('HideStructureActions')) {
+ $('#fieldsForm ul.table-structure-actions').menuResizer(PMA_tbl_structure_menu_resizer_callback);
+ }
+});
+AJAX.registerTeardown('tbl_structure.js', function() {
+ $('#fieldsForm ul.table-structure-actions').menuResizer('destroy');
+});
+$(function () {
+ $(window).resize($.throttle(function () {
+ var $list = $('#fieldsForm ul.table-structure-actions');
+ if ($list.length) {
+ $list.menuResizer('resize');
+ }
+ }));
+});
diff --git a/libraries/Header.class.php b/libraries/Header.class.php
index 13cbb76ca6..5fb986dcf8 100644
--- a/libraries/Header.class.php
+++ b/libraries/Header.class.php
@@ -154,6 +154,7 @@ class PMA_Header
$this->_scripts->addFile('jquery/timepicker.js');
$this->_scripts->addFile('jquery/jquery.ba-hashchange-1.3.js');
$this->_scripts->addFile('jquery/jquery.debounce-1.0.5.js');
+ $this->_scripts->addFile('jquery/jquery.menuResizer-1.0.js');
$this->_scripts->addFile('jquery/jquery.qtip-1.0.0-rc3.js');
if ($GLOBALS['cfg']['CodemirrorEnable']) {
diff --git a/libraries/Menu.class.php b/libraries/Menu.class.php
index 3adeb27ad2..201c0028cd 100644
--- a/libraries/Menu.class.php
+++ b/libraries/Menu.class.php
@@ -107,7 +107,7 @@ class PMA_Menu
} else {
$tabs = $this->_getServerTabs();
}
- return PMA_Util::getHtmlTabs($tabs, $url_params);
+ return PMA_Util::getHtmlTabs($tabs, $url_params, 'topmenu', true);
}
/**
diff --git a/libraries/Theme.class.php b/libraries/Theme.class.php
index b89b43d14a..bf1ee8f6f8 100644
--- a/libraries/Theme.class.php
+++ b/libraries/Theme.class.php
@@ -76,7 +76,8 @@ class PMA_Theme
'pmd',
'rte',
'codemirror',
- 'jqplot'
+ 'jqplot',
+ 'resizable-menu'
);
/**
diff --git a/libraries/Util.class.php b/libraries/Util.class.php
index dc8fc6c7bc..5d9b07340e 100644
--- a/libraries/Util.class.php
+++ b/libraries/Util.class.php
@@ -1830,14 +1830,20 @@ class PMA_Util
* @param array $tabs one element per tab
* @param string $url_params additional URL parameters
* @param string $menu_id HTML id attribute for the menu container
+ * @param bool $resizable whether to add a "resizable" class
*
* @return string html-code for tab-navigation
*/
- public static function getHtmlTabs($tabs, $url_params, $menu_id = 'topmenu')
+ public static function getHtmlTabs($tabs, $url_params, $menu_id, $resizable = false)
{
+ $class = '';
+ if ($resizable) {
+ $class = ' class="resizable-menu"';
+ }
+
$tab_navigation = '