7
votes

I have a page containing a set of jQuery tabs. All the tabs point at the same target div, but load it with different content via ajax. When I perform the initial full page load I need to set the active tab differently depending upon various factors. The content in the target div is already set on the server for this initial load, so I don't need to click the tab, I just need to set the correct tab to 'selected'. I have tried setting the class of the relevant "li" html element to "ui-tabs-selected". This has the initial desired effect, but once the page is loaded then on selecting another tab the preselected one does not switch off, leaving two tabs selected.

So, does anyone know an alternative way to preselect a tab (without causing it to be clicked), or a solution to the strange "ui-tabs-selected" behaviour that I am seeing.

Thanks.

<script type="text/javascript">
    $(function() {
        $("#panelTabs").tabs({
            ajaxOptions: {
                error: function(xhr, status, index, anchor) {
                    $(anchor.hash).html("Couldn't load this tab. We'll try to fix this as soon as possible.");
                }
            }
        });

        $("#panelTabs").tabs({
            select: function(event, ui) {
                getPage('hps.aspx?cmd=zz_' + ui.tab.id, 'panelA');
            }
        });
    });
    </script>

And the C# fragment that builds the UL:

StringBuilder tabsLiteral = new StringBuilder();
            tabsLiteral.Append("<ul>");
            foreach (KeyValuePair<string, Tab> kvp in tabs)
            {
                tabsLiteral.Append("<li>");
                // Note - the kvp.Value.URI determines what should happen when the Tab is clicked
                tabsLiteral.Append("<a id=\"" + kvp.Value.URI + "\" href=\"#panelTabs\">" + kvp.Value.Caption + "</a>");
                tabsLiteral.Append("</li>");
            }
            tabsLiteral.Append("</ul>");
            _panelTabs.Controls.Add(new LiteralControl(tabsLiteral.ToString()));

            HtmlGenericControl ctl = new HtmlGenericControl();
            StringBuilder html = new StringBuilder();
            html.Append("<script type=\"text/javascript\">");
            html.Append("$(\"#panelTabs\").tabs({selected: 2});");
            html.Append("</script>");
            ctl.InnerHtml = html.ToString();
            _panelTabs.Controls.Add(ctl);

Another version:

StringBuilder tabsLiteral = new StringBuilder();
            tabsLiteral.Append("<ul>");
            foreach (KeyValuePair<string, Tab> kvp in tabs)
            {
                string active = "";
                if (currentTabCaption == kvp.Value.Caption)
                {
                    //active = " class=\"ui-tabs-selected\"";
                }
                tabsLiteral.Append("<li" + active + ">");
                // Note - the kvp.Value.URI determines what should happen when the Tab is clicked
                tabsLiteral.Append("<a id=\"" + kvp.Value.URI + "\" href=\"#panelTabs\">" + kvp.Value.Caption + "</a>");
                tabsLiteral.Append("</li>");
            }
            tabsLiteral.Append("</ul>");
            _panelTabs.Controls.Add(new LiteralControl(tabsLiteral.ToString()));

            HtmlGenericControl ctl = new HtmlGenericControl();
            StringBuilder html = new StringBuilder();
            html.Append("<script type=\"text/javascript\">");
            //html.Append("$(\"#panelTabs\").tabs('option','selected', 2);"); 
            html.Append(@"$(function() {
                alert('initialising tabs');
                $(""#panelTabs"").tabs({
                    ajaxOptions: {
                        error: function(xhr, status, index, anchor) {
                            $(anchor.hash).html(""Couldn't load this tab. We'll try to fix this as soon as possible."");
                        }
                    },
                    select: function(event, ui) {
                        getPage('hps.aspx?cmd=zz_' + ui.tab.id, 'panelA');
                    }
                });
            });");
            html.Append("$(\"#panelTabs\").tabs({selected: 2});");
            html.Append("</script>");
            ctl.InnerHtml = html.ToString();
            //_panelTabs.Controls.Add(ctl);
            Page.Controls.Add(ctl);
5
Do you have a code sample showing this in action?spinon
Note sure if this is what you're after, but here is the C# fragment that builds the li: if (currentTabCaption == kvp.Value.Caption) { active = " class=\"ui-tabs-selected\""; } tabsLiteral.Append("<li" + active + ">"); // Note - the kvp.Value.URI determines what should happen when the Tab is clicked tabsLiteral.Append("<a id=\"" + kvp.Value.URI + "\" href=\"#panelTabs\">" + kvp.Value.Caption + "</a>"); tabsLiteral.Append("</li>");DEH

5 Answers

22
votes

What you're looking for is the selected option. E.g.

$("#MyTabs").tabs({
  selected: 2 
});
4
votes

You could have the first line inside of your tab toggle function remove the selected class:

var uiTabsSelected = '.ui-tabs-selected';
$(uiTabsSelected).removeClass(uiTabsSelected);
1
votes

Change this:

html.Append("$(\"#panelTabs\").tabs({selected: 2});");

To this:

html.Append("$(\"#panelTabs\").tabs('option','selected', 2);");

Edit: and...

$(function() {
        $("#panelTabs").tabs({
            ajaxOptions: {
                error: function(xhr, status, index, anchor) {
                    $(anchor.hash).html("Couldn't load this tab. We'll try to fix this as soon as possible.");
                }},
            select: function(event, ui) {
                getPage('hps.aspx?cmd=zz_' + ui.tab.id, 'panelA');
            }
        });    

    });
1
votes

In case anyone else comes here looking for the answer, the current (as of this date) way to select a tab (jQuery UI 1.10) is to use the "active" option:

Initialize the tabs with the active option specified:

$( ".selector" ).tabs({ active: 1 });

http://api.jqueryui.com/tabs/#option-active

0
votes

The solution was to add and remove classes, as ethagnawl suggested. The following C# shows both the UL being built, plus the required jQuery script injection. The important bit is in the show: function where the classes are being manipulated. It is this code that works around the problem.

StringBuilder tabsLiteral = new StringBuilder();
            tabsLiteral.Append("<ul>");
            foreach (KeyValuePair<string, Tab> kvp in tabs)
            {
                //string tabClass = " class=\"ui-state-default\"";
                string tabClass = " class=\"ui-state-default\"";
                if (currentTabCaption == kvp.Value.Caption)
                {
                    tabClass = " class=\"ui-tabs-selected\"";
                }
                tabsLiteral.Append("<li" + tabClass + ">");
                //tabsLiteral.Append("<li>");
                // Note - the kvp.Value.URI determines what should happen when the Tab is clicked
                tabsLiteral.Append("<a id=\"" + kvp.Value.URI + "\" href=\"#panelTabs\">" + kvp.Value.Caption + "</a>");
                tabsLiteral.Append("</li>");
            }
            tabsLiteral.Append("</ul>");
            _panelTabs.Controls.Add(new LiteralControl(tabsLiteral.ToString()));

            HtmlGenericControl ctl = new HtmlGenericControl();
            StringBuilder html = new StringBuilder();
            html.Append("<script type=\"text/javascript\">");
            //html.Append("$(\"#panelTabs\").tabs('option','selected', 2);"); 
            html.Append(@"$(function() {
                $('#panelTabs').tabs({
                    select: function(event, ui) {
                        getPage('hps.aspx?cmd=zz_' + ui.tab.id, 'panelA');
                    },
                    show: function(event, ui) {
                        // You MUST set both 'ui-state-active' AND 'ui-tabs-selected' for tab UI to operate properly - if either are missing it doesn't work
                        $('.ui-tabs-selected').removeClass('ui-state-active').removeClass('ui-tabs-selected'); 
                        $(ui.tab).addClass('ui-state-active').addClass('ui-tabs-selected'); 

                        //$('#panelTabs').tabs('selected',idx); // WOULD have been nice if this had worked, but UI does not keep up
                     }
                });
            });");
            html.Append("</script>");
            ctl.InnerHtml = html.ToString();
            //Page.Header.Controls.Add(ctl); // NEVER place script in the page header when the script must survive an AJAX delivery - it won't run
            Page.Controls.Add(ctl); // Acceptable to place script on the page, as it WILL survive AJAX delivery