From fa5bdc3e08dc9119dbca9e2a864dbe09df221f56 Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Sat, 21 Jul 2012 13:12:20 +0100 Subject: [PATCH] Implemented fast filter for databases in the navigation tree --- js/functions.js | 40 +--- js/navigation.js | 195 +++++++++++------- .../navigation/NavigationHeader.class.php | 12 +- libraries/navigation/NavigationTree.class.php | 104 +++++++--- libraries/navigation/Nodes/Node.class.php | 21 ++ themes/original/css/navigation.css.php | 3 + themes/pmahomme/css/navigation.css.php | 3 + 7 files changed, 236 insertions(+), 142 deletions(-) diff --git a/js/functions.js b/js/functions.js index 7758a4f205..8fd60edf13 100644 --- a/js/functions.js +++ b/js/functions.js @@ -3167,44 +3167,12 @@ AJAX.registerOnload('functions.js', function() { $('select.pageselector').live('change', function(event) { event.stopPropagation(); // Check where to load the new content - // For the main page we don't need to do anything, - // but for the navigation we need to manually replace the content - if ($(this).closest("div#pma_navigation").length == 0) { + if ($(this).closest("#pma_navigation").length == 0) { + // For the main page we don't need to do anything, $(this).closest("form").submit(); } else { - var $this = $(this); - var $msgbox = PMA_ajaxShowMessage(); - var isDbSelector = $this.parent().closest('.pageselector').is('.dbselector'); - var params = $(this).closest("form").serialize() + '&ajax_request=true'; - if (isDbSelector) { - params += '&full=true'; - } else { - var $input = $this.closest('.list_container').find('.fast_filter input.searchClause'); - if ($input.length && $input.val() != $input[0].defaultValue) { - params += "&searchClause=" + $input.val(); - } - } - $.get('navigation.php', params, function (data) { - if (data.success) { - PMA_ajaxRemoveMessage($msgbox); - if (isDbSelector) { - $('#pma_navigation_tree').html(data.message).children('div').show(); - } else { - var $parent = $this.closest('.list_container').parent(); - var $input = $this.closest('.list_container').find('.fast_filter input.searchClause'); - var val = ''; - if ($input.length) { - val = $input.val(); - } - $this.closest('.list_container').html($(data.message).children().show()); - $parent.find('.fast_filter input.searchClause').val(val); - $parent.find('span.pos2_value:first').text($parent.find('span.pos2_value:last').text()); - $parent.find('span.pos3_value:first').text($parent.find('span.pos3_value:last').text()); - } - } else { - PMA_ajaxShowMessage(data.error); - } - }); + // but for the navigation we need to manually replace the content + PMA_navigationTreePagination($(this)); } }); diff --git a/js/navigation.js b/js/navigation.js index 71a3ef9130..0f2424c996 100644 --- a/js/navigation.js +++ b/js/navigation.js @@ -49,25 +49,8 @@ $(function() { $icon.hide(); $throbber.insertBefore($icon); - var $filterContainer = $(this).closest('div.list_container'); - var $filterInput = $([]); - while (1) { - if ($filterContainer.find('li.fast_filter input.searchClause').length != 0) { - $filterInput = $filterContainer.find('li.fast_filter input.searchClause'); - break; - } else if (! $filterContainer.is('div.list_container')) { - break; - } - $filterContainer = $filterContainer - .parent() - .closest('div.list_container'); - } - var searchClause = ''; - if ($filterInput.length != 0 - && $filterInput.val() != $filterInput[0].defaultValue - ) { - searchClause = $filterInput.val(); - } + var searchClause = PMA_fastFilter.getSearchClause(); + var searchClause2 = PMA_fastFilter.getSearchClause2($(this)); var params = { aPath: $(this).find('span.aPath').text(), @@ -75,7 +58,8 @@ $(function() { pos: $(this).find('span.pos').text(), pos2_name: $(this).find('span.pos2_name').text(), pos2_value: $(this).find('span.pos2_value').text(), - searchClause: searchClause + searchClause: searchClause, + searchClause2: searchClause2 }; var url = $('#pma_navigation').find('a.navigation_url').attr('href'); $.get(url, params, function (data) { @@ -130,52 +114,7 @@ $(function() { */ $('#pma_navigation_tree div.pageselector a.ajax').live('click', function (event) { event.preventDefault(); - var $this = $(this); - var isDbSelector = $this.closest('.pageselector').is('.dbselector'); - var $msgbox = PMA_ajaxShowMessage(); - var params = {ajax_request: true}; - if (isDbSelector) { - params['full'] = true; - } else { - var $input = $this - .closest('div.list_container') - .find('li.fast_filter input.searchClause'); - if ($input.length && $input.val() != $input[0].defaultValue) { - params['searchClause'] = $input.val(); - } - } - $.get($this.attr('href'), params, function (data) { - PMA_ajaxRemoveMessage($msgbox); - if (data.success) { - if (isDbSelector) { - $('#pma_navigation_tree') - .html(data.message) - .children('div') - .show(); - } else { - var $parent = $this.closest('div.list_container').parent(); - var $input = $this - .closest('div.list_container') - .find('li.fast_filter input.searchClause'); - var val = ''; - if ($input.length) { - val = $input.val(); - } - $this.closest('div.list_container').html( - $(data.message).children().show() - ); - $parent.find('li.fast_filter input.searchClause').val(val); - $parent.find('span.pos2_value:first').text( - $parent.find('span.pos2_value:last').text() - ); - $parent.find('span.pos3_value:first').text( - $parent.find('span.pos3_value:last').text() - ); - } - } else { - PMA_ajaxShowMessage(data.error); - } - }); + PMA_navigationTreePagination($(this)); }); /** @@ -334,6 +273,76 @@ function PMA_reloadNavigation() { }); }; + +/** + * Handles any requests to change the page in a branch of a tree + * + * This can be called from link click or select change event handlers + * + * @param object $this A jQuery object that points to the element that + * initiated the action of changing the page + * + * @return void + */ +function PMA_navigationTreePagination($this) +{ + var $msgbox = PMA_ajaxShowMessage(); + var isDbSelector = $this.closest('div.pageselector').is('.dbselector'); + if ($this[0].tagName == 'A') { + var url = $this.attr('href'); + var params = 'ajax_request=true'; + } else { // tagName == 'SELECT' + var url = 'navigation.php'; + var params = $this.closest("form").serialize() + '&ajax_request=true'; + } + var searchClause = PMA_fastFilter.getSearchClause(); + if (searchClause) { + params += '&searchClause=' + encodeURIComponent(searchClause); + } + if (isDbSelector) { + params += '&full=true'; + } else { + var searchClause2 = PMA_fastFilter.getSearchClause2($this); + if (searchClause2) { + params += '&searchClause2=' + encodeURIComponent(searchClause2); + } + } + $.post(url, params, function (data) { + PMA_ajaxRemoveMessage($msgbox); + if (data.success) { + if (isDbSelector) { + var val = PMA_fastFilter.getSearchClause(); + $('#pma_navigation_tree') + .html(data.message) + .children('div') + .show(); + if (val) { + $('#pma_navigation_tree') + .find('li.fast_filter input.searchClause') + .val(val); + } + } else { + var $parent = $this.closest('div.list_container').parent(); + var val = PMA_fastFilter.getSearchClause2($this); + $this.closest('div.list_container').html( + $(data.message).children().show() + ); + if (val) { + $parent.find('li.fast_filter input.searchClause').val(val); + } + $parent.find('span.pos2_value:first').text( + $parent.find('span.pos2_value:last').text() + ); + $parent.find('span.pos3_value:first').text( + $parent.find('span.pos3_value:last').text() + ); + } + } else { + PMA_ajaxShowMessage(data.error); + } + }); +}; + /** * @var ScrollHandler Custom object that manages the scrolling of the navigation */ @@ -658,6 +667,48 @@ var PMA_fastFilter = { this.request(); } }, + /** + * Gets the query string from the database fast filter form + * + * @return string + */ + getSearchClause: function () { + var retval = ''; + var $input = $('#pma_navigation_tree') + .find('li.fast_filter.db_fast_filter input.searchClause'); + if ($input.length && $input.val() != $input[0].defaultValue) { + retval = $input.val(); + } + return retval; + }, + /** + * Gets the query string from a second level item's fast filter form + * The retrieval is done by trasversing the navigation tree backwards + * + * @return string + */ + getSearchClause2: function ($this) { + var $filterContainer = $this.closest('div.list_container'); + var $filterInput = $([]); + while (1) { + if ($filterContainer.find('li.fast_filter:not(.db_fast_filter) input.searchClause').length != 0) { + $filterInput = $filterContainer.find('li.fast_filter:not(.db_fast_filter) input.searchClause'); + break; + } else if (! $filterContainer.is('div.list_container')) { + break; + } + $filterContainer = $filterContainer + .parent() + .closest('div.list_container'); + } + var searchClause2 = ''; + if ($filterInput.length != 0 + && $filterInput.first().val() != $filterInput[0].defaultValue + ) { + searchClause2 = $filterInput.val(); + } + return searchClause2; + }, /** * @var hash events A list of functions that are further * down the page bound to DOM events @@ -769,8 +820,14 @@ PMA_fastFilter.filter.prototype.request = function () that.xhr.abort(); } var url = $('#pma_navigation').find('a.navigation_url').attr('href'); - var results = that.$this.find('li:visible:not(.fast_filter)').length; - var params = that.$this.find('form.fast_filter').serialize() + "&results=" + results; + var results = that.$this.find('li:not(.hidden):not(.fast_filter):not(.navGroup)').not('[class^=new]').length; + var params = that.$this.find('> ul > li > form.fast_filter').first().serialize() + "&results=" + results; + if (that.$this.find('> ul > li > form.fast_filter:first input[name=searchClause]').length == 0) { + var $input = $('#pma_navigation_tree').find('li.fast_filter.db_fast_filter input.searchClause'); + if ($input.length && $input.val() != $input[0].defaultValue) { + params += '&searchClause=' + encodeURIComponent($input.val()); + } + } that.xhr = $.ajax({ url: url, type: 'post', @@ -791,7 +848,7 @@ PMA_fastFilter.filter.prototype.request = function () } } }); - }, 500); + }, 250); }; /** * Replaces the contents of the navigation branch with the search results diff --git a/libraries/navigation/NavigationHeader.class.php b/libraries/navigation/NavigationHeader.class.php index 19fa0ae74e..e14b9413a5 100644 --- a/libraries/navigation/NavigationHeader.class.php +++ b/libraries/navigation/NavigationHeader.class.php @@ -32,10 +32,11 @@ class PMA_NavigationHeader 'ajax_request' => true ) ); - $highlight = ''; + $class = ' class="list_container'; if ($GLOBALS['cfg']['NavigationTreePointerEnable']) { - $highlight = ' class="highlight"'; + $class .= ' highlight'; } + $class .= '"'; $buffer = '
'; $buffer .= '
'; $buffer .= '
'; @@ -52,7 +53,12 @@ class PMA_NavigationHeader $buffer .= $this->_links(); $buffer .= $this->_serverChoice(); $buffer .= $this->_recent(); - $buffer .= '
'; + $buffer .= $this->_commonFunctions->getImage( + 'ajax_clock_small.gif', + __('Loading'), + array('style' => 'visibility: hidden;', 'class' => 'throbber') + ); + $buffer .= '
'; return $buffer; } diff --git a/libraries/navigation/NavigationTree.class.php b/libraries/navigation/NavigationTree.class.php index abdb512baa..9586ee79b8 100644 --- a/libraries/navigation/NavigationTree.class.php +++ b/libraries/navigation/NavigationTree.class.php @@ -64,11 +64,19 @@ class PMA_NavigationTree private $_pos3_value = array(); /** - * @var string The search clause to use in SQL queries for fetching nodes + * @var string The search clause to use in SQL queries for + * fetching databases * Used by the asynchronous fast filter */ private $_searchClause = ''; + /** + * @var string The search clause to use in SQL queries for + * fetching nodes + * Used by the asynchronous fast filter + */ + private $_searchClause2 = ''; + /** * @var object A reference to the common functions object */ @@ -130,6 +138,9 @@ class PMA_NavigationTree if (isset($_REQUEST['searchClause'])) { $this->_searchClause = $_REQUEST['searchClause']; } + if (isset($_REQUEST['searchClause2'])) { + $this->_searchClause2 = $_REQUEST['searchClause2']; + } // Initialise the tree by creating a root node $node = new Node('root', Node::CONTAINER); $this->_tree = $node; @@ -190,7 +201,7 @@ class PMA_NavigationTree $retval = $this->_tree; // Add all databases unconditionally - foreach ($this->_tree->getData('', $this->_pos) as $db) { + foreach ($this->_tree->getData('databases', $this->_pos, $this->_searchClause) as $db) { $node = new Node_Database($db); $this->_tree->addChild($node); } @@ -258,7 +269,7 @@ class PMA_NavigationTree $dbData = $db->getData( $container->real_name, $pos2, - $this->_searchClause + $this->_searchClause2 ); foreach ($dbData as $item) { switch ($container->real_name) { @@ -536,6 +547,7 @@ class PMA_NavigationTree } foreach ($prefixes as $key => $value) { $this->groupNode($groups[$key]); + $groups[$key]->classes = "navGroup"; } } } @@ -552,23 +564,9 @@ class PMA_NavigationTree $node = $this->_buildPath(); $retval = false; if ($node !== false) { - $retval = PMA_commonFunctions::getInstance()->getListNavigator( - $this->_tree->getPresence(), - $this->_pos, - array('server' => $GLOBALS['server']), - 'navigation.php', - 'frame_navigation', - $GLOBALS['cfg']['MaxNavigationItems'], - 'pos', - array('dbselector') - ); - + $retval = $this->_fastFilterHtml($this->_tree); + $retval .= $this->_getPageSelector($this->_tree); $this->groupTree(); - $retval .= $this->_commonFunctions->getImage( - 'ajax_clock_small.gif', - __('Loading'), - array('style' => 'visibility: hidden;', 'class' => 'throbber') - ); $retval .= "
    "; $children = $this->_tree->children; usort($children, array('PMA_NavigationTree', 'sortNode')); @@ -616,11 +614,20 @@ class PMA_NavigationTree $retval .= "
"; $retval .= "
"; } - if (! empty($this->_searchClause)) { - $results = $node->realParent()->getPresence( - $node->real_name, - $this->_searchClause - ); + + if (! empty($this->_searchClause) || ! empty($this->_searchClause2)) { + if (! empty($this->_searchClause2)) { + $results = $node->realParent()->getPresence( + $node->real_name, + $this->_searchClause2 + ); + } else { + $results = $this->_tree->getPresence( + 'databases', + $this->_searchClause + ); + } + $clientResults = 0; if (! empty($_REQUEST['results'])) { $clientResults = (int)$_REQUEST['results']; @@ -691,7 +698,7 @@ class PMA_NavigationTree { $retval = ''; $paths = $node->getPaths(); - if ($node->hasSiblings()) { + if ($node->hasSiblings() || isset($_REQUEST['results'])) { if ( $node->type == Node::CONTAINER && count($node->children) == 0 && $GLOBALS['is_ajax_request'] != true @@ -879,13 +886,13 @@ class PMA_NavigationTree $buffer .= $this->_renderNode( $children[$i], true, - $node->classes + $children[$i]->classes ); } else { $buffer .= $this->_renderNode( $children[$i], true, - $node->classes . ' last' + $children[$i]->classes . ' last' ); } } @@ -901,7 +908,9 @@ class PMA_NavigationTree } } } - $retval .= ""; + if ($node->hasSiblings() || isset($_REQUEST['results'])) { + $retval .= ""; + } return $retval; } @@ -934,7 +943,23 @@ class PMA_NavigationTree private function _fastFilterHtml($node) { $retval = ''; - if (($node->type == Node::CONTAINER + if ($node === $this->_tree + && $this->_tree->getPresence() >= (int)$GLOBALS['cfg']['NavigationTreeDisplayDbFilterMinimum'] + ) { + $url_params = array( + 'pos' => 0 + ); + $retval .= "
    "; + $retval .= "
  • "; + $retval .= "
    "; + $retval .= PMA_getHiddenFields($url_params); + $retval .= ""; + $retval .= "X"; + $retval .= "
    "; + $retval .= "
  • "; + $retval .= "
"; + } else if (($node->type == Node::CONTAINER && ( $node->real_name == 'tables' || $node->real_name == 'views' || $node->real_name == 'functions' @@ -954,8 +979,8 @@ class PMA_NavigationTree $retval .= "
  • "; $retval .= "
    "; $retval .= PMA_getHiddenFields($url_params); - $retval .= ""; + $retval .= ""; $retval .= "X"; $retval .= "
    "; $retval .= "
  • "; @@ -974,7 +999,18 @@ class PMA_NavigationTree private function _getPageSelector($node) { $retval = ''; - if ($node->type == Node::CONTAINER && ! $node->is_group) { + if ($node === $this->_tree) { + $retval .= PMA_commonFunctions::getInstance()->getListNavigator( + $this->_tree->getPresence('databases', $this->_searchClause), + $this->_pos, + array('server' => $GLOBALS['server']), + 'navigation.php', + 'frame_navigation', + $GLOBALS['cfg']['MaxNavigationItems'], + 'pos', + array('dbselector') + ); + } else if ($node->type == Node::CONTAINER && ! $node->is_group) { $paths = $node->getPaths(); $level = isset($paths['aPath_clean'][4]) ? 3 : 2; @@ -994,9 +1030,9 @@ class PMA_NavigationTree } $num = $node->realParent()->getPresence( $node->real_name, - $this->_searchClause + $this->_searchClause2 ); - $retval = $this->_commonFunctions->getListNavigator( + $retval .= $this->_commonFunctions->getListNavigator( $num, $pos, $_url_params, diff --git a/libraries/navigation/Nodes/Node.class.php b/libraries/navigation/Nodes/Node.class.php index 3c13cb2fd4..6bd6ff1bb5 100644 --- a/libraries/navigation/Nodes/Node.class.php +++ b/libraries/navigation/Nodes/Node.class.php @@ -359,6 +359,13 @@ class Node { $query = "SELECT `SCHEMA_NAME` "; $query .= "FROM `INFORMATION_SCHEMA`.`SCHEMATA` "; + if (! empty($searchClause)) { + $query .= "WHERE `SCHEMA_NAME` LIKE '%"; + $query .= $this->_commonFunctions->sqlAddSlashes( + $searchClause, true + ); + $query .= "%' "; + } $query .= "ORDER BY `SCHEMA_NAME` ASC "; $query .= "LIMIT $pos, {$GLOBALS['cfg']['MaxNavigationItems']}"; return PMA_DBI_fetch_result($query); @@ -390,9 +397,23 @@ class Node if (! $GLOBALS['cfg']['Servers'][$GLOBALS['server']]['DisableIS']) { $query = "SELECT COUNT(*) "; $query .= "FROM `INFORMATION_SCHEMA`.`SCHEMATA` "; + if (! empty($searchClause)) { + $query .= "WHERE `SCHEMA_NAME` LIKE '%"; + $query .= $this->_commonFunctions->sqlAddSlashes( + $searchClause, true + ); + $query .= "%' "; + } $retval = (int)PMA_DBI_fetch_value($query); } else { $query = "SHOW DATABASES "; + if (! empty($searchClause)) { + $query .= "LIKE '%"; + $query .= $this->_commonFunctions->sqlAddSlashes( + $searchClause, true + ); + $query .= "%' "; + } $retval = PMA_DBI_num_rows(PMA_DBI_try_query($query)); } return $retval; diff --git a/themes/original/css/navigation.css.php b/themes/original/css/navigation.css.php index 5efb0717d2..d41c828123 100644 --- a/themes/original/css/navigation.css.php +++ b/themes/original/css/navigation.css.php @@ -201,6 +201,9 @@ li.fast_filter span { font-weight: bold; color: #800; } +li.fast_filter.db_fast_filter { + border: 0; +} /* Resize handler */ #pma_navigation_resizer { diff --git a/themes/pmahomme/css/navigation.css.php b/themes/pmahomme/css/navigation.css.php index 38d4203f18..0e8017abcd 100644 --- a/themes/pmahomme/css/navigation.css.php +++ b/themes/pmahomme/css/navigation.css.php @@ -196,6 +196,9 @@ li.fast_filter span { font-weight: bold; color: #800; } +li.fast_filter.db_fast_filter { + border: 0; +} /* Resize handler */ #pma_navigation_resizer {