How to link to a specific tab through a #id link in the url

Permalink Browser Info Environment
The do this make a small change your Magic Tabs template to set the current tab from the url #.

In more detail. Magic tabs already has a mechanism for preserving continuity of the tab shown between visits to a page. By default this is on, but could be disabled by an option in the tab template (see the 'Template configuration quick reference' at the end of the documentation page http://www.concrete5.org/marketplace/addons/magic-tabs/documentatio... ).

You can subvert this mechanism to make Magic Tabs open whatever tab you like from the url by adding a snippet of php to a custom template to get the #id part of the url and then call $ch->set_current_tab().
$setname ... // already set up by the template.
$cID = Page::getCurrentPage()->getCollectionID();
$tabid = ... ; //#id extracted from URL, may depend on server .
$ch->set_current_tab($cID,$setname,$tabid);


To find the #id of a tab (so you can add it to a link from another page), use the developer console to look at the href="" part of the 'a' element in the actual tab.

For example, the development tab ofhttp://www.c5magic.co.uk/ has an id of '#jl_magic_tabs_development_gix2'. If I added code based on the above to my own Magic Tabs template, the url would be:
http://www.c5magic.co.uk/#jl_magic_tabs_development_gix2...

(Note that in this case it won't work because my C5magic site does NOT have such a modified template).

EDIT - IMPORTANT - THERE IS A GLITCH WITH THIS - SEE BELOW FOR A WORKAROUND
http://www.concrete5.org/marketplace/addons/magic-tabs/forums/how-t...

Type: Discussion
Status: Archived
JohntheFish
View Replies: View Best Answer
carl101lee replied on at Permalink Reply
carl101lee
Hi Their

I have this add-on, and it works very well, But I am trying to get the URL link to work form this example.

Can you give me soem advise on why its not working.


Thanks
Carl Lee
JohntheFish replied on at Permalink Reply
JohntheFish
There are 2 things you need to make sure of:
1. Disable the tab continuity, otherwise, tab continuity will override whatever you do with the #.
2. Extract the tabid cleanly from the url of the page.

If the above do not spark what you need to do to get it working, please attach your template to a post here and I will have a look at it.

John
carl101lee replied on at Permalink Reply 1 Attachment
carl101lee
Hi John

Thanks, for the assistance, its quite a simple template, I can't get it working so would be very pleased if you can have a look at the attached php for me.


Thanks
Carl
JohntheFish replied on at Permalink Reply 1 Attachment
JohntheFish
There are a few issues, you took my code above a little too literally, as if it were a finished thing rather than an example to develop from. You have also commented out a critical part of the template. Near the top, this part must remain unchanged:
/*
Used to manage communication and continuity within and 
between magic tabs blocks.
This MUST be present for magic tabs to work. 
DO NOT mess with it !!
*/
$ch = Loader::helper('jl_magic_tabs_continuity','jl_magic_tabs');
$ch->update_continuity($this->block->getAreaHandle());
$setname = $ch->get_setname();


Further down the ideal code would be:
$ch->set_param ('insert_location','immediate');
$cID = Page::getCurrentPage()->getCollectionID();
$url_parts = parse_url ($_SERVER['REQUEST_URI']); // Glitch here - see note below
$tabid = $url_parts['fragment'];
if($tabid){
  $ch->set_current_tab($cID,$setname,'#'.$tabid);
}

The objective being that from another page you could link to:
http://www.yoursite.com/yourpage/#desired_tab_id...

However, while changing your template I have also found there is a glitch in the way some concrete5 versions processes #id fragments (they can get lost). So I have extended the code with a workround for that using a path string parameter 'tab' instead of an id fragment:
$ch->set_param ('insert_location','immediate');
$cID = Page::getCurrentPage()->getCollectionID();
$url_parts = parse_url ($_SERVER['REQUEST_URI']);
$tabid = $url_parts['fragment'];
if(empty($tabid)){
  $tabid = $_GET['tab'];
}
if($tabid){
  $ch->set_current_tab($cID,$setname,'#'.$tabid);
}


So from another page you could now link to:
http://www.yoursite.com/yourpage/?tab=desired_tab_id...

You get the desired_tab_id by looking at the link href in the magic tabs using the developer console. It must be without a '#' at the front for this to work, and the code above puts the'#' back in.

The revised template is attached.
carl101lee replied on at Permalink Reply
carl101lee
Afternoon John

Thank you for your help. Ya i commented out the top part to see what happens. I am not the best at php so i was attempting to rebuild it 1 step at a time.


I guessed a variable would be needed its how i did tabs before when i hard coded them in. But as you addon looked good i thought i would use it rather than coding the tabs in.

Will leave a good review Thanks that worked

Carl
mikrov replied on at Permalink Reply
mikrov
Hi John!

I have tried everything shown here - but the desired tab is not shown :(

Here's the code - without comments:
$ch = Loader::helper('jl_magic_tabs_continuity','jl_magic_tabs');
$ch->update_continuity($this->block->getAreaHandle());
$setname = $ch->get_setname();
if($ch->show_proforma($jl_magic_tabs_global)){
   ?>
   <div   id="<?php  echo $setname;?>_proforma"
         class="jl_magic_tabs_proforma <?php  echo $setname;?>"
         style="display:none"
         data-selected-class="jl_magic_selected"
      >
      <ul id="<?php  echo $setname;?>_proforma_inner_container">
      <li id="<?php  echo $setname;?>_proforma_tab_element"></li>
      </ul>
      <div style="clear:both"></div>
   </div>


The url called looks something like this:
http://mydomain.com/en/products/?tab=jl_magic_tabs_apps_gix4


Every tab has been assigned the custom template "Plain UI List", and I have made the appropriate override of view.php (and I have seen that it decodes the tab param by enabling the above HELLO echo statement). I can click the links that are generated, and the tab navigation operates as desired. But it always opens the first tab, regardless of the params passed in the url.

I hope you can give some hints to solve this problem.

Best Regards,
Lars
JohntheFish replied on at Permalink Reply
JohntheFish
What you have looks correct, especially as you have verified you are decoding the required tab ID with the "echo hello:".

A trivial point to check, that you should link to a url

mysite.com/page/?tab=tabid

and NOT to the url

mysite.com/page/?tab=#tabid

(or magic tabs will be lost looking for a tab with the hash inserted twice!)

Also double check that the tabid in the url is the same as the href="#tabid" in the tab on the page.
mikrov replied on at Permalink Reply
mikrov
Thanks for the reply!

I can confirm that the tabid indeed is the same, as the one from autogenerated link (I just copied the link). And I have of course removed the hash-mark - so apart from the obviously invalid domain above, everything after the last / is "real".

Could it be some JavaScript (or jQuery) code which is somehow not executed - because of conflicts with other plugins?

The environment is this:

# concrete5 Version
5.6.2.1

# concrete5 Add-on pakker
Advanced Forms (1.11.5), Advanced Page Selector Attributes (1.0), Are You A Human (0.9.2), Automatic Email Obfuscator (1.2.3), Backup Voodoo (2.3.2), Blocks by AJAX (1.1.2), Constants Driller (0.9.1), Data Display (2.7.1), Fileset attribute (1.0), FlexSlider (2.1.2), Indholds designer (3.1.1), Internationalization (1.3), Magic Tabs (1.1.0.1), Magic Toggle (1.0.0.1), Multi-File Attribute (1.01), MVN Contact info (1.97), Quick Files (2.0.1), Quick Links (2.0.1), reCAPTCHA (0.9.0), RSS Feed Creator (1.24), Social Sharing (0.9.7), Solid_Ground (1.2), Toolbar Buttons (1.0.0), Url Director (1.6.5).

# concrete5 Overrides
blocks/sixeightforms, blocks/mvn_facts, blocks/page_list, blocks/mvn_nav, blocks/valuemessages, blocks/mvn_tiles, blocks/jl_magic_tabs, blocks/mvn_targetgroup, blocks/mvn_slide, blocks/mvn_mypackages, blocks/mvn_product_list, blocks/autonav, blocks/mvn_myproducts, blocks/mvn_event_dates, blocks/d3_social_sharing, blocks/mvn_tile_content, blocks/mvn_department, blocks/mvn_newsslider, blocks/content, controllers/dashboard, helpers/email_obfuscation.php, helpers/translated_pages.php, jobs/mvn_import_packages.php, jobs/generate_multilingual_sitemap.php, jobs/mvn_import_products.php, jobs/mvn_import_components.php, languages/sv_SE, languages/da_DK, languages/nb_NO, libraries/router.php, libraries/mvn_utils.php, libraries/mv_web_services.php, models/attribute, models/area.php, single_pages/my_product_list.php, single_pages/feed.php, single_pages/nagios.php, single_pages/page_not_found.php, single_pages/dashboard, themes/mvn, themes/mv

# Software på webserver
Apache/2.2.22 (Ubuntu)

# Webservers API
apache2handler

# PHP version
5.3.10-1ubuntu3.9

# PHP udvidelser
apache2handler, bcmath, bz2, calendar, Core, ctype, curl, date, dba, dom, ereg, exif, fileinfo, filter, ftp, gd, gettext, hash, iconv, intl, json, libxml, mbstring, mhash, mysql, mysqli, openssl, pcre, PDO, pdo_mysql, Phar, posix, Reflection, session, shmop, SimpleXML, soap, sockets, SPL, standard, sysvmsg, sysvsem, sysvshm, tokenizer, wddx, xml, xmlreader, xmlwriter, zip, zlib.

# PHP indstillinger
max_execution_time - 30
log_errors_max_len - 1024
max_file_uploads - 20
max_input_nesting_level - 64
max_input_time - 60
max_input_vars - 1000
memory_limit - 128M
post_max_size - 32M
safe_mode - Off
safe_mode_exec_dir - <i>no value</i>
safe_mode_gid - Off
safe_mode_include_dir - <i>no value</i>
sql.safe_mode - Off
upload_max_filesize - 25M
mysql.max_links - Unlimited
mysql.max_persistent - Unlimited
mysqli.max_links - Unlimited
mysqli.max_persistent - Unlimited
pcre.backtrack_limit - 1000000
pcre.recursion_limit - 100000
session.cache_limiter - nocache
session.gc_maxlifetime - 7200
soap.wsdl_cache_limit - 5
safe_mode_allowed_env_vars - PHP_
safe_mode_protected_env_vars - LD_LIBRARY_PATH
JohntheFish replied on at Permalink Reply
JohntheFish
A script error would show up in the developer console or firebug. I don't know of any compatibility issues with the addons in your list.

Forgetting the external tab url for now, if you comment out the set_current_tab line, does the tab continuity mechanism work for your template?
mikrov replied on at Permalink Reply
mikrov
If I change the code to the following:
// immediate or top, immediate is default
$ch->set_param ('insert_location','immediate');
//$ch->set_param ('tab_continuity','off');   // <=== Enable tab continuity
$cID = Page::getCurrentPage()->getCollectionID();
$url_parts = parse_url ($_SERVER['REQUEST_URI']);
$tabid = $url_parts['fragment'];
$tabid = $_GET['id'];
if (empty($tabid)) {
  $tabid = $_GET['tab'];
}
if ($tabid) {
//echo "HELLO: $tabid";
//  $ch->set_current_tab($cID,$setname,'#'.$tabid);
}


I can click on a tab, and when I reload the page, the chosen tab remains open - that is: tab continuity seems to work as expected (or as I understand it should work...)
mikrov replied on at Permalink Reply
mikrov
With the following code, specifying a tab-id in the url now works:
// immediate or top, immediate is default
$ch->set_param ('insert_location','immediate');
//$ch->set_param ('tab_continuity','off');
$cID = Page::getCurrentPage()->getCollectionID();
$url_parts = parse_url ($_SERVER['REQUEST_URI']);
$tabid = $url_parts['fragment'];
if (empty($tabid)) {
  $tabid = $_GET['tab'];
}
if ($tabid) {
//echo "HELLO: $tabid";
  $ch->set_current_tab($cID,$setname,'#'.$tabid);
}


But that is in contradiction to the advice above, I think ...

Our intention was to always show the first tab, and occasionally (via internal links) show one of the other tabs initially.
JohntheFish replied on at Permalink Reply
JohntheFish
It does seem like a contradiction, but what is actually happening inside Magic Tabs is that the set_current_tab() is subverting the tab continuity mechanism to fix the tab being shown, so switching continuity off would disable the mechanism set_current_tab() is using.

Anyway, I a glad you have the problem solved and, for the purposes of anyone else coming to the thread, the important lesson is to not disable tab continuity.
mikrov replied on at Permalink Best Answer Reply
mikrov
With this code, I actually get what I want:
$cID = Page::getCurrentPage()->getCollectionID();
$url_parts = parse_url ($_SERVER['REQUEST_URI']);
$tabid = $url_parts['fragment'];
if (empty($tabid)) {
  $tabid = $_GET['tab'];
}
if ($tabid) {
  $ch->set_current_tab($cID,$setname,'#'.$tabid);
}
else {
  $ch->set_param('tab_continuity','off');
}


Always open the first tab if no specific tab indicated in the url, otherwise use tab-continuity mechanism to open the requested tab.

That might help anybody else having the same troubles :)

Thanks for your help!

Best Regards,
Lars
JohntheFish replied on at Permalink Reply
JohntheFish
I have marked you as best answer because your snippet of code contributes something useful for other users of Magic Tabs.
mikrov replied on at Permalink Reply
mikrov
An even simpler approach is to implement it in jQuery:
$(function() {
  var hash = $(location).attr('hash');
  if (hash != '') {
    $("a[href*="+hash+"]").trigger('click');
  }
});


You don't need the changes to the templates like the ones described above, so this little snippet works with the plugin out-of-the-box.

The jQuery selector actually enables you to be less accurate when passing the hash-tag in the request: e.g. #jl_magic_tabs_apps will trigger the click event as well as #jl_magic_tabs_apps_gix4 will do. This gives you the opportunity to reorder the tabs without breaking the links you may have used elsewhere in your site.

I have disabled tab-continuity for the previously mentioned reasons, but this little jQuery trick also works with tab-continuity enabled.

Best Regards,
Lars
JohntheFish replied on at Permalink Reply
JohntheFish
Again, thank you, though a word of caution - a javascript approach to changing tabs must execute after Magic Tabs has initialised or it won't have anything to trigger a click on, so needs to be declared later in the document than the Magic Tabs ready handler.
mikrov replied on at Permalink Reply
mikrov
Then, by pure luck :), I had my script placed in the footer as one of the last scripts included, and as I read the controller.php, the Magic Tab scripts are put in the header section.
Thanks for the caution!

/Lars
kimstone replied on at Permalink Reply
kimstone
Hi John,

I'm trying to achieve some cross linking between the tabs on the same page. I've set up 4 tabs, the first tab has a form, and the the following three tabs use your page list tools. The idea is that I'm using the tabs to create what kind of feels like a four step form; as the user moves through the tabs they end up completing a Bio Page that is displayed to the public.

I would like to place links at the bottom of each displayed tab that would send the user directly to the next tabular step.

I was able to achieve this with the javascript solution above, but never successfully achieved it with the suggested template rebuild. That said, I've still encountered a conflict.

To understand my conflict, please note my naming conventions. 'Tabs' refer to four tabular sections with headers titled tab 1, Tab 2, etc. If you click on the respective tab you go to that tab. 'Links' are at the bottom of each tab, if you click on link 2, you go to tab 2.

I placed a link, called link 2, in tab 1, that successfully links to tab 2. The problem is that once I'm at tab 2, and click back on tab 1 (the tab header called tab 1...not to be confused with a link in the footer), it takes me to tab 1 but the url doesn't refresh; it's still showing the full path identifying tab 2. So...now, when I'm back on tab 1, and click link 2, I'm not able to go to tab 2, I remain in tab 1 because the browser already has the url for tab 2 with it's id# in the window. Are you following?

Essentially clicking through the tabs (tab headers) doesn't refresh the url after I've clicked a link with the caller tab id#. I need the page url to refresh when I click the tabs in addition to the links in order to achieve my desired effect.

Any suggestions?
JohntheFish replied on at Permalink Reply
JohntheFish
Hi Kim

Yes, the mechanism described above only works for external links into a page with tabs, not for internal links. hence your problem with the address bar and that the page refreshes rather than simply swaps tabs.

You can get round it by writing some javascript to specifically handle internal links to tabs. What you need to do is to attach a handler to catch the click event of an on-page link, cancel the link action and then trigger a click event on the relevant tab header.

Something like (untested, so will need some further development)
<a id="my_link_to_tab" href="#target_tab_header_href">Go to Target Tab</a>

And then
$('#my_link_to_tab').on('click', function(ev){
  ev.preventDefault();
  var target_tab = $(this).attr('href');
  $('ul.jl_magic_tabs a[href="'+target_tab +'"]').trigger('click');
});


I have a big update of Magic Tabs under development that includes a more sophisticated development of this behaviour, picking up any link to a #tabname on page or incoming #tabname in the url from off page. There is still a bit of development work needed for all the new features I want to release with the update. I am just waiting for the free time needed to get it done (every time I think I have a gap in my schedule, customers keep hiring me for custom development projects).

John
kimstone replied on at Permalink Reply
kimstone
Thanks, for the prompt reply as usual, John.

I came up with a simple previous/next solution to simply achieve my goals. This works in this instance as I'm essentially trying to emulate a sequential stepped form. In this case, I simply dropped the previous link, and only used the next link, renaming it to reflect the next step in the sequence.

Easy breezy.

<script type="text/javascript">
 $('.btnNext').click(function(){
  $('.jl_magic_tabs > .active').next('li').find('a').trigger('click');
});
  $('.btnPrevious').click(function(){
  $('.jl_magic_tabs > .active').prev('li').find('a').trigger('click');
});
</script>


I'm looking forward to your updated version. Love all your products. they've helped me immensely.
kimstone replied on at Permalink Reply
kimstone
Not essential, but as I think about it, I would still love to find a way to return to the first tab from the last tab. I tinkered with the javascript you provided, but only found myself chasing my tail. How long do you think it would take you to create a solution if I were to commission you?

Thanks, again.

Kim
JohntheFish replied on at Permalink Reply
JohntheFish
I like the idea of previous/next buttons. I may build something like that into the new version when I get back to working on it.

For the first tab, you could adapt your code:
<script type="text/javascript">
 $('.btnFirst').click(function(){
  $('.jl_magic_tabs > .active').siblings('li').first().find('a').trigger('click');
});
</script>
JohntheFish replied on at Permalink Reply
JohntheFish
Bare in mind that such link traversal will only work consistently while there is only one set of tabs on a page. If you have more than one set of tabs, it will need additional selectors.
JohntheFish replied on at Permalink Reply
JohntheFish
v2.0 of Magic Tabs now includes a block for creating such contextual links 'Magic Tabs Jump'
JohntheFish replied on at Permalink Reply
JohntheFish
v2.0 of Magic Tabs now has a selection of mechanisms for direct linking into tabs, both from within a page and via the URL.

concrete5 Environment Information

Browser User-Agent String

Hide Post Content

This will replace the post content with the message: "Content has been removed by an Administrator"

Hide Content

Request Refund

You have not specified a license for this support ticket. You must have a valid license assigned to a support ticket to request a refund.