Access label of currently active tab?

Is there a way that I can access the label of the current tab and render it in a template? jQuery, perhaps?

I saw this thread, and Zach’s answer:

var TABSET_ID = 'FruitTabs';<br>var TAB_ID = 'Bananas';<br>var $ = skuid.$;<br>var tabset = $('#'+TABSET_ID);<br>var tabPanels = tabset.children('.ui-tabs-panel');<br>var targetTabIndex = tabPanels.filter('#'+TAB_ID).index() - 1;<br>tabset.tabs('option','active',targetTabIndex); 

So, could I use something like…

var $ = skuid.$;
var tabset = $(’#MyTabsetID’);


var currentlabel = tabset.tabs [ … something here??]

OR var currentlabel = tabset.children.ui-tabs-panel ??

Hi Matt -

The key to this is that you need to locate the tag for the tab and get its innerHtml or text. The anchor tab is actually not inside of the panel itself but instead it’s a child of a UL element that is a sibling to the panel but higher up in the DOM. There are several ways to locate this but one would be:

// this can be written more efficiently but accomplishes the goal for this purpose
// see the code snippet on the sample page for a full version
$(‘a[href="#’ + tabId + ‘"]’).text();

You could also use the aria-labelledby property value from the tab panel itself and then search the DOM for the the element who’s ID matches that value. This would be a more direct approach but does introduce a little risk if the jQuery UI stuff were to ever change.

I created a sample page (see below) which has a couple of scenarios addressed:

  1. First Tab - On page load (document.ready) build a comma delimited list of all tabs within the tabset and set a template field to contain the delimited list. Note that the template on the 1st tab has a fixed Unique Id of tabnames.

  2. All Other Tabs - As each tab is clicked (tabshow), update template field on the tab with its label. Each tab (except the first) contains a template field with a element that has a class of “.tabname” The tabshow event is hooked so that each tab is clicked, a generic block of code runs, finds the text for the current tab and updates the span with that text.

A few notes:

  1. The sample contains two different “search” approaches - one using the tab id and one using the aria-labelledby attribute. In each case, the code is not 100% tuned for optimization of DOM searching as it’s intended to demonstrate where everything lives while accomplishing the goal of identifying the label text.
  2. in this case, since tab labels don’t support HTML it doesn’t matter but as a general rule, you could use .html() instead of .text() to grab HTML instead of the inner text value of a DOM element.

Hope this helps.

<skuidpage unsavedchangeswarning="yes" tabtooverride="Account" showsidebar="true" showheader="true"> <models> <model id="Account" limit="1" query="true" createrowifnonefound="false" sobject="Account"> <fields> <field id="Name" /> <field id="CreatedDate" /> </fields> <conditions> <condition type="param" value="id" operator="=" field="Id" enclosevalueinquotes="true" /> </conditions> <actions /> </model> </models> <components> <tabset uniqueid="tabdemo" renderas="" defertabrendering="true" rememberlastusertab="false"> <tabs> <tab name="Reinvent" uniqueid="tabReinvent"> <components> <template model="Account" multiple="false" allowhtml="true" cssclass=""> <contents>All Tabs: &amp;lt;span id="tabnames"&amp;gt;&amp;lt;/span&amp;gt;</contents> </template> </components> </tab> <tab name="your" uniqueid="tabYour" loadlazypanels="true"> <components> <template model="Account" multiple="false" cssclass=""> <contents>Tab Name: &amp;lt;span class="tabname"&amp;gt;&amp;lt;/span&amp;gt;</contents> </template> </components> </tab> <tab name="UI" uniqueid="tabUI" loadlazypanels="true"> <components> <template model="Account" multiple="false" cssclass=""> <contents>Tab Name: &amp;lt;span class="tabname"&amp;gt;&amp;lt;/span&amp;gt;</contents> </template> </components> </tab> <tab name="With" uniqueid="tabWith" loadlazypanels="true"> <components> <template model="Account" multiple="false" cssclass=""> <contents>Tab Name: &amp;lt;span class="tabname"&amp;gt;&amp;lt;/span&amp;gt;</contents> </template> </components> </tab> <tab name="Skuid" uniqueid="tabSkuid" loadlazypanels="true"> <components> <template model="Account" multiple="false" cssclass=""> <contents>Tab Name: &amp;lt;span class="tabname"&amp;gt;&amp;lt;/span&amp;gt;</contents> </template> </components> </tab> </tabs> </tabset> </components> <resources> <labels /> <css /> <javascript> <jsitem name="tabListener" url="" cachelocation="false" location="inline">(function(skuid){ // jquery shortcut var $ = skuid.$; // helper to locate the text by using tab Id var getTabById = function(tab) { // get the id of the tab var tabId = $(tab).attr('id'); // this could be optimized but as it is written // it will search up from the tab to find the tabset // then down for the navigate &amp;lt;ul&amp;gt; element // then look for the first &amp;lt;a&amp;gt; element that has an href // property of the tab Id return $(tab).closest('.ui-tabs').children('.ui-tabs-nav').find('a[href="#' + tabId + '"]:first').text(); }; // helper to locate the text using aria-labelledby attribute var getTabByAriaLabelledBy = function(tab) { // get the aria-labelledby attribute value which represents which element points to this element (this elements 'label') var tabId = $(tab).attr('aria-labelledby'); // this could be optimized but as it is written // it will search up from the tab to find the tabset // then down for the navigate &amp;lt;ul&amp;gt; element // then look for the element who's id is th tabId return $(tab).closest('.ui-tabs').children('.ui-tabs-nav').find('#' + tabId).text(); }; // helper to get the text of the anchor tag which is the label for the tab var getTabLabel = function(tab) { // search using the tab's id return getTabById(tab); // search by looking for the tab's 'label' //return getTabByAriaLabelledBy(tab); }; // document ready function $(function(){ // hook the tabshow event so that as user clicks on tab // we update the template field with the label from the tab $('body').on('tabshow',function(event){ var tabLabel = getTabLabel(event.target); // lookup the label text for the tab // update the text of the span with the name from the tab label $(event.target).find('span.tabname').text(tabLabel); }); var tabSet = $('#tabdemo') // find the tabset , tabs = $(tabSet).children('.ui-tabs-panel') // find all the tabs for the tabeset , tabIds = ''; // helper variable that we'll use to build the list of tab labels // iterate the tabs $.each(tabs, function() { // build a comma delimited list of the tab labels tabIds += (tabIds ? ', ' : '') + getTabLabel($(this)); }); // update the span with the concatenated list $('#tabnames').text(tabIds); }); })(skuid);</jsitem> </javascript> </resources> </skuidpage>

Barry, you’re the man.

Thanks again, Barry!

My application requires one template field above the tabset to display the name of the tab. This way, I can eliminate tab names for a long tabset and just use icons, but the user can still see the label of the tab.

Here’s the code I ended up with:

(function(skuid){ var $ = skuid.$;
// helper to locate the text by using tab Id
var getTabById = function(tab) {
    // get the id of the tab
    var tabId = $(tab).attr('id');
    // return the label text
        return $(tab).closest('.ui-tabs').children('.ui-tabs-nav').find('a[href="#' + tabId + '"]:first').text();
};
// update the text of the span with the name from the tab label
var setTabName = function(target){
    var tabLabel = getTabById(target); // lookup the label text for the tab
        // update the text of the span with the name from the tab label
        $('span.tabname').text(tabLabel);
};
// document ready function
    $(function(){
    // hook the tabshow event so that as user clicks on tab
    // we update the template field with the label from the tab
        $('body').on('tabshow',function(event){
            return setTabName(event.target);
        });
        
        // get first tab name to set template on page load
        var tabSet = $('#tabdemo'), // find the tabset
            firstTab = $(tabSet).children('.ui-tabs-panel:first');
        return setTabName(firstTab);
});
})(skuid);

And the XML demo page, if anyone’s interested:

<skuidpage unsavedchangeswarning="yes" tabtooverride="Account" showsidebar="true" showheader="true">
   <models>
      <model id="Account" limit="1" query="true" createrowifnonefound="false" sobject="Account">
         <fields>
            <field id="Name"/>
            <field id="CreatedDate"/>
         </fields>
         <conditions>
            <condition type="param" value="id" operator="=" field="Id" enclosevalueinquotes="true"/>
         </conditions>
         <actions/>
      </model>
   </models>
   <components>
<template model="Account" multiple="false" cssclass="" allowhtml="false">
                     <contents>&amp;lt;h1&amp;gt;&amp;lt;span class="tabname"&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/h1&amp;gt;</contents>
                  </template>
      <tabset uniqueid="tabdemo" renderas="" defertabrendering="true" rememberlastusertab="false">
         <tabs>
            <tab name="Reinvent" uniqueid="tabReinvent">
               <components>
                  
               </components>
            </tab>
            <tab name="your" uniqueid="tabYour" loadlazypanels="true">
               <components>
                  
               </components>
            </tab>
            <tab name="UI" uniqueid="tabUI" loadlazypanels="true">
               <components>
                  
               </components>
            </tab>
            <tab name="With" uniqueid="tabWith" loadlazypanels="true">
               <components>
                  
               </components>
            </tab>
            <tab name="Skuid" uniqueid="tabSkuid" loadlazypanels="true">
               <components>
                  
               </components>
            </tab>
         </tabs>
      </tabset>
   </components>
   <resources>
      <labels/>
      <css/>
      <javascript>
         <jsitem location="inline" name="tabNameDisplay" cachelocation="false" url="">(function(skuid){
var $ = skuid.$;
// helper to locate the text by using tab Id
var getTabById = function(tab) {
    // get the id of the tab
    var tabId = $(tab).attr('id');
    // return the label text
        return $(tab).closest('.ui-tabs').children('.ui-tabs-nav').find('a[href="#' + tabId + '"]:first').text();
};
// update the text of the span with the name from the tab label
var setTabName = function(target){
    var tabLabel = getTabById(target); // lookup the label text for the tab
        // update the text of the span with the name from the tab label
        $('span.tabname').text(tabLabel);
};
// document ready function
    $(function(){
    // hook the tabshow event so that as user clicks on tab
    // we update the template field with the label from the tab
        $('body').on('tabshow',function(event){
            return setTabName(event.target);
        });
        
        // get first tab name to set template on page load
        var tabSet = $('#tabdemo'), // find the tabset
            firstTab = $(tabSet).children('.ui-tabs-panel:first');
        return setTabName(firstTab);
});
})(skuid);</jsitem>
</javascript>
   </resources>
</skuidpage>

Is there a better way to get the name of the first tab? I’m just making things up as I go, here… :slight_smile:

So… I realized that if I’m not displaying the tab names, they’re not in the html for jQuery to find. What’s the best way to find a tab’s unique ID?

Hey Matt - Unfortunately there isn’t a tabshow event fired for the first tab that is displayed.  The way you found the first tab (document ready & first) would be the best way to approach if you don’t have the option “Remember user’s last tab” enabled.  If you do have it enabled, the first tab isn’t necessarily what is displayed on initial page load.

To make sure you get the correct tab in all cases, I’d suggest the following:

firstTab = $(tabSet).children('.ui-tabs-panel:visible');

Nevermind… we were already getting that with .attr(‘id’).

Sweet!

Hey Matt -

The getById function in the sample page will get you the tab’s unique Id.

If I’m understanding what you are trying to do correctly, you want to have a “label” for the tab but display the current tab’s label above the tabset instead of in the tab itself.  To do this, you are leaving the “Tab Label” property empty, correct?  

If so, having the unique id would allow you to write some javascript to evaluate the current ID and have code that grabs the correct label text.  If I’m on the right track, I think the best approach would be to avoid having to have hardcoded strings for the label text in your code - or even have to use skuid.labels.  Instead, you could use some CSS tricks and just hide the actual label on the tab.  The label would still be there for you to grab the text, but wouldn’t be visible in the UI.  This way you could still build everything declaritvely text wise.

If my assumptions are correct, create your tab as you normally would, putting in an icon and label text.  Then add the following CSS:

#tabdemo .ui-tabs-anchor &gt; .nx-template {&nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp;display: none !important;<br>}

Hey Barry,

I’m not actually leaving the tab label empty. I’m doing this: https://community.skuidify.com/skuid/topics/toggle-tab-labels-on-off
So, the label on teach tab looks something like:

{{#$Model.ShowTabs.data.0.Chart_Tab_Names__c}}Case Summary{{/$Model.ShowTabs.data.0.Chart_Tab_Names__c}}

If the user has Chart_Tab_Names__c = true, the label shows up, otherwise, we just see the icon.

I’d like to be able to show the tab label above the tabset in a template either way.

I decided to go ahead and use the unique ID. I had to include a ‘replace’, because I wanted spaces in my display, but you can’t have spaces in the unique id.

Here’s my new code:

(function(skuid){ var $ = skuid.$;<br>// helper to locate the text by using tab Id<br>var getTabById = function(tab) {<br> &nbsp; &nbsp;// get the id of the tab<br> &nbsp; &nbsp;var tabId = $(tab).attr('id');<br> &nbsp; &nbsp;return tabId.replace("_"," ");<br>};<br>// update the text of the span with the name from the tab label<br>var setTabName = function(tab){<br> &nbsp; &nbsp;var tabLabel = getTabById(tab); // lookup the label text for the tab<br>&nbsp; &nbsp; &nbsp; &nbsp; $('span.tabname').text(tabLabel);<br>};<br>// document ready function<br>&nbsp; &nbsp; $(function(){<br> &nbsp; &nbsp;// hook the tabshow event so that as user clicks on tab<br> &nbsp; &nbsp;// we update the template field with the label from the tab<br>&nbsp; &nbsp; &nbsp; &nbsp; $('body').on('tabshow',function(event){<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return setTabName(event.target);<br>&nbsp; &nbsp; &nbsp; &nbsp; });<br>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; // get first tab name to set template on page load<br>&nbsp; &nbsp; &nbsp; &nbsp; var tabSet = $('#tabdemo'), // find the tabset<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; firstTab = $(tabSet).children('.ui-tabs-panel:visible');<br>&nbsp; &nbsp; &nbsp; &nbsp; return setTabName(firstTab);<br>});<br>})(skuid);






Conditional labels, I like it!

One other approach you could take to avoid all the merge syntax and the replace is the following. 

1) Put your text in the Tab Label field as normal (no merge syntax)

2) On document ready, check your ShowTabs model for true/false and show/hide the labels

$(function(){&nbsp; &nbsp; // hook the tabshow event so that as user clicks on tab<br>&nbsp; &nbsp; // we update the template field with the label from the tab<br>&nbsp; &nbsp; $('body').on('tabshow',function(event){<br>&nbsp; &nbsp; &nbsp; &nbsp; return setTabName(event.target);<br>&nbsp; &nbsp; });<br>&nbsp; &nbsp;&nbsp;<br>&nbsp; &nbsp; // show/hide labels<br>&nbsp; &nbsp; var showTabsModel = skuid.model.getModel('ShowTabs')<br>&nbsp; &nbsp; &nbsp; &nbsp; , showTabsRow = showTabsModel.getFirstRow()<br>&nbsp; &nbsp; &nbsp; &nbsp; , showLabels = showTabsRow__Chart_Tab_Names__c;<br>&nbsp; &nbsp;&nbsp;<br>&nbsp; &nbsp; // get all the labels<br>&nbsp; &nbsp; var tabLabels = $('#tabdemo').find('.ui-tabs-anchor').find('div.nx-template');<br>&nbsp; &nbsp;&nbsp;<br>&nbsp; &nbsp; if (showLabels) {<br>&nbsp; &nbsp; &nbsp; &nbsp; tabLabels.show();<br>&nbsp; &nbsp; } else {<br>&nbsp; &nbsp; &nbsp; &nbsp; tabLabels.hide();<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp;&nbsp;<br>&nbsp; &nbsp; // get first tab name to set template on page load<br>&nbsp; &nbsp; var tabSet = $('#tabdemo') // find the tabset<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;, firstTab = $(tabSet).children('.ui-tabs-panel:visible');<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br>&nbsp; &nbsp; setTabName(firstTab);<br>});

Nice approach! I think this would allow me to update the tab labels when the value for Chart_Tab_Names__c changes. What is the event handle for that?

Also, I think we want

showLabels = showTabsRow.Chart_Tab_Names__c;

not 

showLabels = showTabsRow__Chart_Tab_Names__c; 


Correct?

Correct, typo on my part, sorry about that.

For the toggling here is what I would do:

1) Add a model action on ShowTabs model for when field Chart_Tab_Names__c is updated
2) In the action call a snippet (e.g. toggleLabels)
3) In the snippet check the value and show/hide accordingly

Loving it!

Thanks for all your help, Barry!