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
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

monsterweb - January 12, 2009 - 16:11
Version:5.x-1.x-dev» 6.x-2.0-rc1
Category:feature request» support request

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

Pasqualle - January 12, 2009 - 21:57

in 6.x-2.0 you can open any tab if you use this format:

http://example.com/mypage?quicktabs_42=2

where 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-42

for 5.x-1.x I do not have a solution..

#3

rsmith5 - January 19, 2009 - 18:02

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

drupalok - February 5, 2009 - 16:58

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

sidal1 - February 26, 2009 - 23:41

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

EkaMei - February 27, 2009 - 00:20

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

Pasqualle - February 27, 2009 - 01:52

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..

When users click a node inside a view, I want to show the Full Node inside current tab.

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

drupalok - February 27, 2009 - 09:42

@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

rsmith5 - March 8, 2009 - 20:46

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..

(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

Flying Drupalist - March 9, 2009 - 21:43

@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

sidal1 - March 9, 2009 - 22:54

Hi,

Do you have any code sample which does number 1?

Thanks!

#12

rsmith5 - March 10, 2009 - 04:00

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

WorldFallz - March 15, 2009 - 20:08

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

Pasqualle - April 4, 2009 - 15:59
Version:6.x-2.0-rc1» 6.x-2.x-dev
Category:support request» feature request

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

Flying Drupalist - June 9, 2009 - 16:41

#16

mmader - July 16, 2009 - 21:19

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

Pasqualle - July 15, 2009 - 04:04

using a pager on the second tab, which of course refreshes the page back to the first tab

if it is an ajax view, then the pager does not reload the page..

#18

ospinto - July 18, 2009 - 00:27

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:

<?php
include('./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

vertikal.dk - July 22, 2009 - 10:16

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

<?php
include('./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

EkaMei - July 25, 2009 - 19:47

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

tayzlor - September 30, 2009 - 15:38

is there a patch available which incorporates all of the above code (in #16, #18 and #19) into a working solution?

#22

jpdaut - October 1, 2009 - 16:21
Version:6.x-2.x-dev» 5.x-1.4

Has anyone done this for QT for Drupal 5?

#23

jannalexx - October 15, 2009 - 19:50

#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

jannalexx - October 15, 2009 - 23:33
Version:5.x-1.4» 6.x-2.x-dev

#25

yitzchas - October 26, 2009 - 20:08

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

Ryan Aslett - November 29, 2009 - 03:29

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).

 
 

Drupal is a registered trademark of Dries Buytaert.