Remember last clicked tab
rsmith5 - January 4, 2009 - 18:16
| Project: | Quick Tabs |
| Version: | 6.x-2.x-dev |
| Component: | Code |
| Category: | feature request |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | active |
Jump to:
Description
Hi,
I was wondering if it would be possible to save which tab was last open for a user and bring that tab up immediately when navigating to a page that has the quick tab block.
Thanks.

#1
Hello,
I thought I would bump this request. I have been trying to do something similar. I'm trying to have the tabs 'save' the active tab when navigating to a story so that a user can keep that tab active when clicking through articles on the tab.
I labeled this as a support request, really I just wanted some pointers from a developer who's more experienced with this module on how to implement this.
Thanks,
Monsterweb
#2
in 6.x-2.0 you can open any tab if you use this format:
http://example.com/mypage?quicktabs_42=2where 42 is the qtid (quicktab id) and 2 is the tabpage id (normally 0 is the first tabpage). so if you add this parameter to the links then the selected tab will be opened.
if you want to automatically scroll down to the quicktab you can use:
http://example.com/mypage?quicktabs_42=2#quicktabs-42for 5.x-1.x I do not have a solution..
#3
I was thinking more along the lines of saving the last clicked tab in the $_SESSION variable. Seems like it would be fairly straight-forward to implement since you already have it working for taking the argument from the url bar.
#4
subscribing! this would be a wonderful feature... otherwise one always has to click back to the tab, when going through the different nodes.
thank you!
#5
Hello,
What do you mean by 'one has to click back to the tab, when going through the different nodes' ?
Right now I am trying to provide a way to go through different nodes under a tab. I have 2 tabs with views in them. When users click a node inside a view, I want to show the Full Node inside current tab. But currently when user clicks a node in a view, it goes to that Node's page and completely leaves the tabbed page. Do you know how we can go through different nodes of a view under the same tab?
Thanks a lot!
#6
Basically, what they meant is that when someone click on a tab in a page that have quicktab. Then they navigates away from that page, and then click the "Back" button to return to the page where they clicked a quicktab last. It should remember the status of the quicktab and restores it as if they didn't navigates away from that page. Rather then jumping back to the default tab.
This is more of a usability issue, but I agree it is a good one.
#7
The quicktabs module has no control about the content of your tabpages. It does not know about the links what you have inside it. The links inside the quicktab are absolutely the same as outside the quicktab.
You need to format your links (inside the tabpage) to achieve the desired functionality. The format is described in comment #2.
It is not possible to store every active tabpage in the SESSION variable, because (1) you may use more quicktabs on the same page, and (2) I do not know when this information should be cleared..
this is much more than quicktabs module is capable of, sorry.. You may open a new feature request, but I have no idea how should I do that.. Maybe it is possible with Panels module, but I am not sure..
#8
@Pascalle
Dont get me wrong, I really love this module, it's one of the best I've seen, but without remembering the last clicked TAB the practical use of it is very limited. I just cant expect my clients / users to click back to the TAB they've been, every time they go through - let's say - several FAQs on the website which are located in a third TAB.
is there any automated way i can add the ?quicktabs_42=2 (example from comment #2) to my links in the TABs?
thank you very much!
#9
(1) If you use an associative array in the SESSION variable, and key it based on the quicktab id, you can store which tab is clicked across the entire site, independent of how many are on a page.
(2) I believe the SESSION variable is stored per user in the databases, and cleared automatically upon logout. You shouldn't even need to worry about it.
#10
@drupalok, that's not how you're supposed to use quicktabs. For main page content create tabs in theme. The quicktab urls would not be SEO friendly anyway.
#11
Hi,
Do you have any code sample which does number 1?
Thanks!
#12
There would need to be an event listener (probably with javascript) that sent out a POST when a tab was clicked. The POST would include the quicktab-id and which tab was clicked. The POST would fire a php function that did something like:
$_SESSION += array( $quicktab_id => $clicked_tab );Then, whenever a page was loaded there would be something like:
if($_SESSION[$this_quicktab_id]){$clicked_tab = $_SESSION[$this_quicktab_id];
}
#13
Just an fyi comment: I was assisting someone with trying to locate this functionality and noticed that magic_tabs lists it as a feature so it can definitely be done. Perhaps a look at how it's done there would be helpful.
#14
changing to feature request. Keeping the version for now, but most probably it won't be fixed within 2.x
this is a duplicate of #248798: Tab reset with page load., but let's keep both issues open as there is some discussion in both..
#15
Something like this:
http://www.shopdev.co.uk/blog/cookies-with-jquery-designing-collapsible-...
Perhaps?
#16
I came up with a quick and dirty fix for this, thanks to Flying Drupalist's suggestion of using cookies.
In quicktabs.js
var quicktabsClick = function() {
var tab = new Drupal.quicktabs.tab(this);
// Set clicked tab to active.
$(this).parents('li').siblings().removeClass('active');
$(this).parents('li').addClass('active');
//add cookie for active qtab ***add these lines***
var active_tab_id = this.id.split('-')[3]; //active tab Id number
var qtid = this.id.split('-')[2]; //quicktab Id number
document.cookie = "quicktabs" + qtid + "=" + active_tab_id + "; path=/"; //create cookie for quicktab
// Hide all tabpages.
tab.container.children().hide();
. . .
and in quicktabs.module
function _quicktabs_get_active_tab($quicktabs) {$active_tab = isset($_COOKIE['quicktabs' . $quicktabs['qtid']]) ? $_COOKIE['quicktabs' . $quicktabs['qtid']] : key($quicktabs['tabs']); //check cookie for active tab***add this line***
$active_tab2 = isset($_GET['quicktabs_' . $quicktabs['qtid']]) ? $_GET['quicktabs_' . $quicktabs['qtid']] : $active_tab; //check for args after cookies to override cookies***change this line***
if (isset($active_tab2) && isset($quicktabs['tabs'][$active_tab2])) { ***change to $active_tab2***
return $active_tab2;
}
return NULL;
}
When a tab is clicked, it saves or changes a cookie that represents that quicktab's current state. When quicktab renders the page, it checks the cookie for the active tab number, if there is one. So simple and yet works well enough for my needs. If the same tab is printed on multiple pages, they'll all have the same active tab because the cookie is based on the qtid.
I'm surprised it took a year until someone came up with a solution. This is kind of an important feature, if only to keep your customers happy when they're using a pager on the second tab, which of course refreshes the page back to the first tab.
#17
if it is an ajax view, then the pager does not reload the page..
#18
mmader's solution works. if you'd rather use SESSIONS, see below:
Create a php page in your drupal root which will set the session.
Example /qt_session_set.php with the following code:
<?phpinclude('./includes/bootstrap.inc');
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
if(array_key_exists('qt_index',$_GET) && array_key_exists('qt_id',$_GET))
$_SESSION[str_replace('-','_',$_GET['qt_id'])] = $_GET['qt_index'];
?>
In your page.tpl.php have this jQuery function:
$(document).ready(function() {//set session cookie
$('a.qt_tab').click(function(e) {
var qt_parent_id = $(this).parents('.quicktabs_wrapper')[0].id;
var qt_index = this.id.split('-')[3];
jQuery.get('<?php print $base_path; ?>/qt_session_set.php', {'qt_id':qt_parent_id, 'qt_index':qt_index});
})
});
And then finally in the quicktabs.module file, in the _quicktabs_get_active_tab function, change the line that says:
<?php$active_tab = isset($_GET['quicktabs_'. $quicktabs['qtid']]) ? $_GET['quicktabs_'. $quicktabs['qtid']] : key($quicktabs['tabs']);
?>
TO:
<?php
if($_SESSION['quicktabs_'.$quicktabs['qtid']])
$active_tab = $_SESSION['quicktabs_'.$quicktabs['qtid']];
else if(isset($_GET['quicktabs_'. $quicktabs['qtid']]))
$_GET['quicktabs_'. $quicktabs['qtid']];
else
key($quicktabs['tabs']);
?>
VOILA!
#19
ospinto,
Excellet solution. Your code didn't work perfectly for me, so I changed a few things.
I used cookies in stead of sessions, so my PHP-file qt_session_set.php in the root looks like this
<?phpinclude('./includes/bootstrap.inc');
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
if(array_key_exists('qt_index',$_GET) && array_key_exists('qt_id',$_GET))
setcookie(str_replace('-','_',$_GET['qt_id']), $_GET['qt_index']);
?>
I put my JavaScript in the bottom of page.tpl.php and it is basically the same as yours, but I removed the slash before the file name to avoid double slashes, which made it fail here:
<script>$(document).ready(function() {
//set cookie
$('a.qt_tab').click(function(e) {
var qt_parent_id = $(this).parents('.quicktabs_wrapper')[0].id;
var qt_index = this.id.split('-')[3];
jQuery.get('<?php print $base_path; ?>qt_session_set.php', {'qt_id':qt_parent_id, 'qt_index':qt_index});
})
});
</script>
My new _quicktabs_get_active_tab function for quicktabs.module looks like this:
<?php
/**
* Helper function to determine active tab from the url.
*/
function _quicktabs_get_active_tab($quicktabs) {
if(isset($_GET['quicktabs_'. $quicktabs['qtid']]))
$active_tab = $_GET['quicktabs_'. $quicktabs['qtid']];
else if($_COOKIE['quicktabs_'.$quicktabs['qtid']])
$active_tab = $_COOKIE['quicktabs_'.$quicktabs['qtid']];
else
key($quicktabs['tabs']);
if (isset($active_tab) && isset($quicktabs['tabs'][$active_tab])) {
return $active_tab;
}
return NULL;
}
?>
I have the $_GET-element before the $_COOKIE-element to enable controlling the tab via the URL even if the cookie is set. I also made a couple of other small adjustments.
This would be a great function to have in the module. A simple checkbox in the setup of each QuickTab could decide whether the single QuickTab should "remember" its tab or not, and the setting of the cookie could be fully enclosed in a small JavaScript-file, which could be included by the module. That would avoid the separate PHP-file in the root, and leave everything to the module.
Even without this, this is a great module! It has saved me a lot of work on a project, so thanks to all who contributed!
Martin
#20
I agree, this is a great module. I still hesitates to add this remember tab function since it is not verified but it is certainly worth considering.
In my opinion, it appear that using cookie is probably a better choice. Session might be nice but it would probably create extra query that might not be necessary
#21
is there a patch available which incorporates all of the above code (in #16, #18 and #19) into a working solution?
#22
Has anyone done this for QT for Drupal 5?
#23
#16 works ok
only on non cached pages, this makes it useless at the time being, does anyone knows how to make it work with cached content?for anonymous and authenticated users.it worked after clearing, disabling and enabling again drupal core cache
#19 produces empty tabs for me
colapsiblock module http://drupal.org/project/collapsiblock remembers last state correctly, just for reference
#24
#25
All-Javascript patch, inspired by JQueryUI Tabs; tested with non-AJAX tabs:
--- modules/quicktabs/js/quicktabs.js (revision 17)
+++ modules/quicktabs/js/quicktabs.js (working copy)
@@ -24,7 +24,21 @@
// Search for the active tab.
var $active_tab = $(el).children('.quicktabs_tabs').find('li.active a');
- if ($active_tab.hasClass('qt_tab') || $active_tab.hasClass('qt_ajax_tab')) {
+ // recall state
+ var cookie_name = "quicktabs" + qtid;
+ var cookie_start = document.cookie.indexOf( cookie_name + "=" );
+ var cookie_end = document.cookie.indexOf( ";", cookie_start );
+ if (
+ document.cookie.length > 0
+ && cookie_start != -1
+ && cookie_end != -1
+ ) {
+ cookie_start = cookie_start + cookie_name.length + 1;
+ active_tab = document.cookie.substring( cookie_start,cookie_end );
+ var active_id = "quicktabs-tab-" + qtid + "-" + active_tab;
+ $(el).children('.quicktabs_tabs').find("a#" + active_id).trigger('click');
+ }
+ else if ($active_tab.hasClass('qt_tab') || $active_tab.hasClass('qt_ajax_tab')) {
$active_tab.trigger('click');
}
else {
@@ -144,6 +158,11 @@
$(this).parents('li').siblings().removeClass('active');
$(this).parents('li').addClass('active');
+ // store state
+ var active_tab_id = this.id.split('-')[3];
+ var qtid = this.id.split('-')[2];
+ document.cookie = "quicktabs" + qtid + "=" + active_tab_id + "; path=/";
+
// Hide all tabpages.
tab.container.children().hide();
#26
Yitzchas Javascript worked perfectly for me.
I have a custom cck node add/edit form embedded in the third tab (a thorough survey for the content).
Upon submission of invalid data/incomplete form, the page would reload and the first tab would be selected.. now everything works how I want it to! awesome!
This is definitely something that should be incorporated into quicktabs (with current behavior the default of course).