diff --git a/js/common.js b/js/common.js index 5bd674fc06..c61cd6b2cc 100644 --- a/js/common.js +++ b/js/common.js @@ -37,16 +37,19 @@ var PMA_commonParams = (function () { */ setAll: function (obj) { var reload = false; + var updateNavigation = false; for (var i in obj) { if (params[i] !== undefined && params[i] !== obj[i]) { reload = true; } - // To expand the database in use and collapse the previous one - if(i == 'db' && obj[i] !== '') { - PMA_autoExpandDatabaseInUse(params['db'], obj[i]); + if (i == 'db' || i == 'table') { + updateNavigation = true; } params[i] = obj[i]; } + if (updateNavigation) { + PMA_showCurrentNavigation(); + } if (reload) { PMA_querywindow.refresh(); } @@ -74,10 +77,10 @@ var PMA_commonParams = (function () { if (params[name] !== undefined && params[name] !== value) { PMA_querywindow.refresh(); } - if(name == 'db' && value !== '') { - PMA_autoExpandDatabaseInUse(params['db'], value); - } params[name] = value; + if(name == 'db' || name == 'table') { + PMA_showCurrentNavigation(); + } return this; }, /** @@ -114,10 +117,8 @@ var PMA_commonActions = { */ setDb: function (new_db) { if (new_db != PMA_commonParams.get('db')) { - if(new_db !== '') { - PMA_autoExpandDatabaseInUse(PMA_commonParams.get('db'), new_db); - } PMA_commonParams.set('db', new_db); + PMA_showCurrentNavigation(); PMA_querywindow.refresh(); } }, diff --git a/js/navigation.js b/js/navigation.js index 74848515f7..31fb3c19cf 100644 --- a/js/navigation.js +++ b/js/navigation.js @@ -29,7 +29,12 @@ $(function() { $('#pma_navigation_tree a.expander').live('click', function(event) { event.preventDefault(); event.stopImmediatePropagation(); - PMA_expandNavigationTree($(this)); + var $icon = $(this).find('img'); + if ($icon.is('.ic_b_plus')) { + expandTreeNode($(this)); + } else { + collapseTreeNode($(this)); + } }); /** @@ -38,6 +43,9 @@ $(function() { */ $('#pma_navigation_reload').live('click', function (event) { event.preventDefault(); + $('#pma_navigation .throbber') + .first() + .css('visibility', 'visible'); PMA_reloadNavigation(); }); @@ -156,54 +164,42 @@ $(function() { event.preventDefault(); PMA_createViewDialog($(this)); }); + + PMA_showCurrentNavigation(); }); /** - * Expands/collapses the navigation tree and sets to view the expanded + * Expands a node in navigation tree. * - * @param object $expandElem the element that initiated the expanding - * @return void + * @param $expandElem expander + * @param callback callback function + * + * @returns void */ -function PMA_expandNavigationTree($expandElem) { +function expandTreeNode($expandElem, callback) +{ var $children = $expandElem.closest('li').children('div.list_container'); var $icon = $expandElem.find('img'); if ($expandElem.hasClass('loaded')) { if ($icon.is('.ic_b_plus')) { $icon.removeClass('ic_b_plus').addClass('ic_b_minus'); $children.show('fast'); - } else { - $icon.removeClass('ic_b_minus').addClass('ic_b_plus'); - $children.hide('fast'); + } + if (callback && typeof callback == 'function') { + callback.call(); } } else { - var $destination = $expandElem.closest('li'); - if($icon.siblings('.throbber').length <= 0) { - var $throbber = $('#pma_navigation .throbber') - .first() - .clone() - .css('visibility', 'visible'); - $icon.hide(); - $throbber.insertBefore($icon); - } + var $throbber = $('#pma_navigation .throbber') + .first() + .clone() + .css('visibility', 'visible') + .click(false); + $icon.hide(); + $throbber.insertBefore($icon); - var searchClause = PMA_fastFilter.getSearchClause(); - var searchClause2 = PMA_fastFilter.getSearchClause2($expandElem); - - var params = { - aPath: $expandElem.find('span.aPath').text(), - vPath: $expandElem.find('span.vPath').text(), - pos: $expandElem.find('span.pos').text(), - pos2_name: $expandElem.find('span.pos2_name').text(), - pos2_value: $expandElem.find('span.pos2_value').text(), - searchClause: searchClause, - searchClause2: searchClause2 - }; - var url = $('#pma_navigation').find('a.navigation_url').attr('href'); - $.get(url, params, function (data) { + loadChildNodes($expandElem, function(data) { if (data.success === true) { - $expandElem.addClass('loaded'); - $destination.find('div.list_container').remove(); // FIXME: Hack, there shouldn't be a list container there - $destination.append(data.message); + var $destination = $expandElem.closest('li'); $icon.removeClass('ic_b_plus').addClass('ic_b_minus'); $destination .children('div.list_container') @@ -213,18 +209,20 @@ function PMA_expandNavigationTree($expandElem) { .find('a.expander.container') .click(); } + if (callback && typeof callback == 'function') { + callback.call(); + } } else { PMA_ajaxShowMessage(data.error, false); } $icon.show(); - if($icon.siblings('.throbber').length) - $icon.siblings('.throbber').remove(); + $throbber.remove(); }); } $expandElem.blur(); } -/* +/** * Auto-scrolls the newly chosen database * * @param object $element The element to set to view @@ -242,36 +240,224 @@ function scrollToView($element, $container) { } } -/* - * Auto-expands the newly chosen database +/** + * Collapses a node in navigation tree. * - * @param string $oldDb The previous database - * @param string $newDb The newly chosen database + * @param $expandElem expander * + * @returns void */ -function PMA_autoExpandDatabaseInUse($oldDb, $newDb) { - var $expandElem, $icon; - //Collapse the previous database - if($oldDb !== '' && $oldDb !== $newDb) { - $expandElem = $('#pma_navigation_tree a.dbLink:contains("' + $oldDb + '")') - .parent().find('a.expander').eq(0); - $icon = $expandElem.find('img'); - if ($icon.is('.ic_b_minus')) - PMA_expandNavigationTree($expandElem); - } - //expand the newly chosen database - $expandElem = $('#pma_navigation_tree a.dbLink:contains("' + $newDb + '")') - .parent().find('a.expander').eq(0); - $icon = $expandElem.find('img'); - if ($icon.is('.ic_b_plus')) { - PMA_expandNavigationTree($expandElem); - } - //scroll to new database - if ($oldDb !== $newDb) { - setTimeout(function() { - scrollToView($expandElem.closest('li'), $('#pma_navigation_tree_content')); - }, 200); +function collapseTreeNode($expandElem) { + var $children = $expandElem.closest('li').children('div.list_container'); + var $icon = $expandElem.find('img'); + if ($expandElem.hasClass('loaded')) { + if ($icon.is('.ic_b_minus')) { + $icon.removeClass('ic_b_minus').addClass('ic_b_plus'); + $children.hide('fast'); + } } + $expandElem.blur(); +} + +/** + * Loads child items of a node and executes a given callback + * + * @param $expandElem expander + * @param callback callback function + * + * @returns void + */ +function loadChildNodes($expandElem, callback) { + var $destination = $expandElem.closest('li'); + + var searchClause = PMA_fastFilter.getSearchClause(); + var searchClause2 = PMA_fastFilter.getSearchClause2($expandElem); + + var params = { + aPath: $expandElem.find('span.aPath').text(), + vPath: $expandElem.find('span.vPath').text(), + pos: $expandElem.find('span.pos').text(), + pos2_name: $expandElem.find('span.pos2_name').text(), + pos2_value: $expandElem.find('span.pos2_value').text(), + searchClause: searchClause, + searchClause2: searchClause2 + }; + + var url = $('#pma_navigation').find('a.navigation_url').attr('href'); + $.get(url, params, function (data) { + if (data.success === true) { + $expandElem.addClass('loaded'); + $destination.find('div.list_container').remove(); // FIXME: Hack, there shouldn't be a list container there + $destination.append(data.message); + if (callback && typeof callback == 'function') { + callback(data); + } + } + }); +} + +/** + * Expand the navigation and highlight the current database or table/view + * + * @returns void + */ +function PMA_showCurrentNavigation() +{ + var db = PMA_commonParams.get('db'); + var table = PMA_commonParams.get('table'); + $('#pma_navigation_tree') + .find('li.selected') + .removeClass('selected'); + if (db && table) { // if we are at the table/view level + // open the database in the tree + var $dbItem = highlightLoadedItem( + $('#pma_navigation_tree > div'), db, 'database', false, false + ); + // open the table in the tree and select it + var $expander = $dbItem.children('div:first').children('a.expander'); + // if not loaded or loaded but collapsed + if (! $expander.hasClass('loaded') + || $expander.find('img').is('.ic_b_plus') + ) { + expandTreeNode($expander, function() { + loadAndHighlightTableOrView($dbItem, table); + }); + } else { + loadAndHighlightTableOrView($dbItem, table); + } + } else if (db) { // if we are at the database level + // open in the tree and select the database + highlightLoadedItem( + $('#pma_navigation_tree > div'), db, 'database', true, true + ); + } + + function highlightLoadedItem($container, name, clazz, doSelect, doOpen) { + var ret = false; + $container.children('ul').children('li').each(function() { + var $li = $(this); + // this is a navigation group, recurse + if ($li.is('.navGroup')) { + var $container = $li.children('div.list_container'); + var $childRet = highlightLoadedItem( + $container, name, clazz, doSelect, doOpen + ); + if ($childRet) { + ret = $childRet; + return false; + } + } else { // this is a real navigation item + // name and class matches + if ($li.is('.' + clazz) && $li.children('a').text() == name) { + if (doSelect) { + $li.addClass('selected'); + } + if (doOpen) { + var $expander = $li.find('div:first').children('a.expander'); + if ($expander.length > 0) { + expandTreeNode($expander, function() { + scrollToView($li, $('#pma_navigation_tree_content')); + }); + } + } + // taverse up and expand and parent navigation groups + $li.parents('.navGroup').each(function() { + $cont = $(this).children('div.list_container'); + if (! $cont.is(':visible')) { + $(this) + .children('div:first') + .children('a.expander') + .click(); + } + }); + ret = $li; + return false; + } + } + }); + return ret; + } + + function loadAndHighlightTableOrView($dbItem, table) { + var $container = $dbItem.children('div.list_container'); + var $tableContainer = $container + .children('ul') + .children('li.tableContainer'); + var $viewContainer = $container + .children('ul') + .children('li.viewContainer'); + + if ($tableContainer.length > 0) { + var $expander = $tableContainer + .children('div:first') + .children('a.expander'); + + if (! $expander.hasClass('loaded') ) { + loadChildNodes($expander, function(data) { + highlightTableOrView($tableContainer, $viewContainer, table); + }); + } else { + highlightTableOrView($tableContainer, $viewContainer, table); + } + } else if ($viewContainer.length > 0) { + highlightView($viewContainer, table); + } else { + // no containers, highlight the item + highlightLoadedItem($container, table, 'table', true, false); + } + } + + function highlightTableOrView($tableContainer, $viewContainer, table) + { + if (isItemInContainer($tableContainer, table, 'table')) { + var $expander = $tableContainer + .children('div:first') + .children('a.expander'); + if ($expander.find('img').is('.ic_b_plus')) { + expandTreeNode($expander); + } + highlightLoadedItem( + $tableContainer.children('div.list_container'), + table, 'table', true, false + ); + } else if ($viewContainer.length > 0) { + highlightView($viewContainer, table); + } + } + + function isItemInContainer($container, name, clazz) + { + $items = $container.find('li.' + clazz); + var found = false; + $items.each(function() { + if ($(this).children('a').text() == name) { + found = true; + return false; + } + }); + return found; + } + + function highlightView($viewContainer, view) { + var $expander = $viewContainer + .children('div:first') + .children('a.expander'); + if (! $expander.hasClass('loaded') + || $expander.find('img').is('.ic_b_plus') + ) { + expandTreeNode($expander, function() { + highlightLoadedItem( + $viewContainer.children('div.list_container'), + view, 'view', true, false + ); + }); + } else { + highlightLoadedItem( + $viewContainer.children('div.list_container'), + view, 'view', true, false + ); + } + } } /** @@ -323,13 +509,17 @@ function PMA_reloadNavigation(callback) { }); var url = $('#pma_navigation').find('a.navigation_url').attr('href'); $.post(url, params, function (data) { + // Hide throbber if it's visible + $('#pma_navigation .throbber') + .first() + .css('visibility', 'hidden'); if (data.success) { $('#pma_navigation_tree').html(data.message).children('div').show(); + PMA_showCurrentNavigation(); // Fire the callback, if any if (typeof callback === 'function') { callback.call(); } - PMA_autoExpandDatabaseInUse('', PMA_commonParams.get('db')); } else { PMA_ajaxShowMessage(data.error); } diff --git a/libraries/navigation/NavigationTree.class.php b/libraries/navigation/NavigationTree.class.php index bb6e1d1d4f..24eaf93312 100644 --- a/libraries/navigation/NavigationTree.class.php +++ b/libraries/navigation/NavigationTree.class.php @@ -881,7 +881,6 @@ class PMA_NavigationTree $retval .= ""; } - $dblinkclass = ' class="dbLink"'; $linkClass = ''; $haveAjax = array( 'functions', @@ -933,7 +932,7 @@ class PMA_NavigationTree $retval .= htmlspecialchars($node->name); $retval .= ""; } else { - $retval .= ""; + $retval .= ""; $retval .= htmlspecialchars($node->real_name); $retval .= ""; } diff --git a/libraries/navigation/Nodes/Node_Database.class.php b/libraries/navigation/Nodes/Node_Database.class.php index 45ff0c12a0..ba823dd281 100644 --- a/libraries/navigation/Nodes/Node_Database.class.php +++ b/libraries/navigation/Nodes/Node_Database.class.php @@ -35,6 +35,7 @@ class Node_Database extends Node 'icon' => 'db_operations.php?server=' . $GLOBALS['server'] . '&db=%1$s&token=' . $GLOBALS['token'] ); + $this->classes = 'database'; } /** diff --git a/libraries/navigation/Nodes/Node_Table.class.php b/libraries/navigation/Nodes/Node_Table.class.php index 08d620888f..b27e0da8c8 100644 --- a/libraries/navigation/Nodes/Node_Table.class.php +++ b/libraries/navigation/Nodes/Node_Table.class.php @@ -38,6 +38,7 @@ class Node_Table extends Node . '?server=' . $GLOBALS['server'] . '&db=%2$s&table=%1$s&token=' . $GLOBALS['token'] ); + $this->classes = 'table'; } /** diff --git a/libraries/navigation/Nodes/Node_Table_Container.class.php b/libraries/navigation/Nodes/Node_Table_Container.class.php index 3d3ef146d1..0efa9fc116 100644 --- a/libraries/navigation/Nodes/Node_Table_Container.class.php +++ b/libraries/navigation/Nodes/Node_Table_Container.class.php @@ -35,7 +35,8 @@ class Node_Table_Container extends Node $this->separator = $GLOBALS['cfg']['NavigationTreeTableSeparator']; $this->separator_depth = (int)($GLOBALS['cfg']['NavigationTreeTableLevel']); } - $this->real_name = 'tables'; + $this->real_name = 'tables'; + $this->classes = 'tableContainer'; $new = PMA_NodeFactory::getInstance('Node', _pgettext('Create new table', 'New')); $new->isNew = true; diff --git a/libraries/navigation/Nodes/Node_View.class.php b/libraries/navigation/Nodes/Node_View.class.php index 3f47579a7e..f9d3cfcb6c 100644 --- a/libraries/navigation/Nodes/Node_View.class.php +++ b/libraries/navigation/Nodes/Node_View.class.php @@ -38,6 +38,7 @@ class Node_View extends Node . '&db=%2$s&table=%1$s' . '&token=' . $GLOBALS['token'] ); + $this->classes = 'view'; } } diff --git a/libraries/navigation/Nodes/Node_View_Container.class.php b/libraries/navigation/Nodes/Node_View_Container.class.php index ada9027ff4..39544fb177 100644 --- a/libraries/navigation/Nodes/Node_View_Container.class.php +++ b/libraries/navigation/Nodes/Node_View_Container.class.php @@ -31,6 +31,7 @@ class Node_View_Container extends Node 'icon' => 'db_structure.php?server=' . $GLOBALS['server'] . '&db=%1$s&token=' . $GLOBALS['token'], ); + $this->classes = 'viewContainer'; $this->real_name = 'views'; $new = PMA_NodeFactory::getInstance('Node', _pgettext('Create new view', 'New')); diff --git a/themes/original/css/navigation.css.php b/themes/original/css/navigation.css.php index 0d88478d25..fd91206d9c 100644 --- a/themes/original/css/navigation.css.php +++ b/themes/original/css/navigation.css.php @@ -128,6 +128,10 @@ if (! defined('PMA_MINIMUM_COMMON') && ! defined('TESTSUITE')) { color: ; background-color: ; } +#pma_navigation_tree li.selected { + color: ; + background-color: ; +} #pma_navigation_tree ul { clear: both; padding: 0; diff --git a/themes/pmahomme/css/navigation.css.php b/themes/pmahomme/css/navigation.css.php index 7d30f11e14..0d747f73da 100644 --- a/themes/pmahomme/css/navigation.css.php +++ b/themes/pmahomme/css/navigation.css.php @@ -113,6 +113,10 @@ if (! defined('PMA_MINIMUM_COMMON') && ! defined('TESTSUITE')) { color: ; background-color: ; } +#pma_navigation_tree li.selected { + color: ; + background-color: ; +} #pma_navigation_tree ul { clear: both; padding: 0;