RadTab sometimes not associated with the correct PageView when closing tabs client side

3 posts, 1 answers
  1. John
    John avatar
    9 posts
    Member since:
    Mar 2009

    Posted 17 Dec 2015 Link to this post

    Hello,

    I'm noticing some unexpected behavior when closing and selecting a tab using the client side javascript.  First, here's the code for my page:

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="Default" %>
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     
    <head runat="server">
        <title></title>
        <telerik:RadStyleSheetManager id="RadStyleSheetManager1" runat="server" />
    </head>
    <body>
        <form id="form1" runat="server">
        <telerik:RadScriptManager ID="RadScriptManager1" runat="server">
            <Scripts>
                <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.Core.js" />
                <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.jQuery.js" />
                <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.jQueryInclude.js" />
            </Scripts>
        </telerik:RadScriptManager>
        <script type="text/javascript">
            //Put your JavaScript code here.
     
            //This will hold a counter which will help us create unique IDs for elements
            var uniquePgVwIDCounter = 0;
     
     
            function addtab() {
                var tabStrip1 = $find('<%= mainTabStrip.ClientID %>');
                var multiPage1 = $find("<%= mainPageMultiPageCtrl.ClientID %>");
                var tab = new Telerik.Web.UI.RadTab();
                //Get the count of tabs so that we can use it as part of the tab name.
                //Since we haven't added the new tab yet, we need to add one to the
                //current tab count.
                tab.set_text("Root RadTab" + (tabStrip1.get_tabs().get_count() + 1));
                 
                //Add the tab to the tab strip.
                tabStrip1.get_tabs().add(tab);
     
                //Stash the paths for the icons here so we can reuse them.
                var blackCloseBtnPath = "<%= Page.ResolveUrl("~/images/Close.gif") %>";
                var redCloseBtnPath = "<%= Page.ResolveUrl("~/images/Red-X-with-box.gif") %>";
     
                //Store a reference to the jQuery object so that we can use it below.
                var jTabElm = $(tab.get_innerWrapElement());
     
                //Create a close button element.  Attach a hover function to change the close
                //icon on mouseover and mouseout and attach a click function to handle the
                //closing of the tab.
                var closeBtn = $("<img alt=\"Close this tab\" src=" + blackCloseBtnPath + " />")
                    .hover(
                        function() {
                            $(this).attr("src", redCloseBtnPath);
                        },
                        function() {
                            $(this).attr("src", blackCloseBtnPath);
                        }
                    ).click(
                        function(e){
                            //Use the closure of this function to capture the
                            //reference to the newly created tab so that we can
                            //work with it easily below.
                            //Grab a reference to the tab that should be selected
                            //after this one is closed.
                            var tabToSelect = tab.get_nextTab();
                            if (!tabToSelect){
                                tabToSelect = tab.get_previousTab();
                            }
     
                            //Grab a reference to the tab's PageView so that we can
                            //remove it below.
                            var pvToRemove = tab.get_pageView();
                             
                            //Remove the tab
                            tabStrip1.get_tabs().remove(tab);
     
     
                            //Select the next tab
                            if (tabToSelect){
                                tabToSelect.select();
                            }
     
                            //Remove the tab's PageView
                            multiPage1.get_pageViews().remove(pvToRemove);
     
                            //Cancel the event bubbling.
                            if(e){
                                e.cancelBubble = true;
                                if(e.stopPropagation){
                                    e.stopPropagation();
                                }
                            }
                        }
                    ).appendTo(jTabElm);
     
                //Create a new PageView for this tab to hold its content.
                var pageView = new Telerik.Web.UI.RadPageView();
                multiPage1.get_pageViews().add(pageView);
     
                //Check to see if this page view's ID exists yet.  If it does,
                //increment our unique ID counter and try again.
                var newPageViewID = tab.get_text() + "_" + uniquePgVwIDCounter;
                while(multiPage1.findPageViewByID(newPageViewID)){
                    uniquePgVwIDCounter++;
                    newPageViewID = tab.get_text() + "_" + uniquePgVwIDCounter;
                }
     
                pageView.set_id(newPageViewID);
                pageView.get_element().innerHTML = "<iframe src=\"Content_1.aspx\" frameborder=\"0\"></iframe>";
     
                //Associate the new PageView with the new tab.
                tab.set_pageViewID(pageView.get_id());
     
                //Select the tab since we just opened it
                tab.select();
     
                //Increment our unique ID counter
                uniquePgVwIDCounter++;
            }
        </script>
        <telerik:RadAjaxManager ID="RadAjaxManager1" runat="server">
        </telerik:RadAjaxManager>
        <div>
            <telerik:RadMenu ID="topRadMenu" runat="server" ResolvedRenderMode="Classic">
                <Items>
                    <telerik:RadMenuItem runat="server" Text="Root RadMenuItem1">
                        <Items>
                            <telerik:RadMenuItem runat="server" Text="Child RadMenuItem 1">
                            </telerik:RadMenuItem>
                            <telerik:RadMenuItem runat="server" Text="Child RadMenuItem 2">
                            </telerik:RadMenuItem>
                        </Items>
                    </telerik:RadMenuItem>
                    <telerik:RadMenuItem runat="server" Text="Root RadMenuItem2">
                        <Items>
                            <telerik:RadMenuItem runat="server" Text="Child RadMenuItem 1">
                            </telerik:RadMenuItem>
                            <telerik:RadMenuItem runat="server" Text="Child RadMenuItem 2">
                            </telerik:RadMenuItem>
                        </Items>
                    </telerik:RadMenuItem>
                    <telerik:RadMenuItem runat="server" Text="Root RadMenuItem3">
                        <Items>
                            <telerik:RadMenuItem runat="server" Text="Child RadMenuItem 1">
                            </telerik:RadMenuItem>
                            <telerik:RadMenuItem runat="server" Text="Child RadMenuItem 2">
                            </telerik:RadMenuItem>
                        </Items>
                    </telerik:RadMenuItem>
                    <telerik:RadMenuItem runat="server" Text="Root RadMenuItem4">
                        <Items>
                            <telerik:RadMenuItem runat="server" Text="Child RadMenuItem 1">
                            </telerik:RadMenuItem>
                            <telerik:RadMenuItem runat="server" Text="Child RadMenuItem 2">
                            </telerik:RadMenuItem>
                        </Items>
                    </telerik:RadMenuItem>
                </Items>
            </telerik:RadMenu>
            <div>
                <telerik:RadTabStrip ID="mainTabStrip" runat="server"
                   MultiPageID="mainPageMultiPageCtrl">
                    <Tabs>
                        <telerik:RadTab runat="server" Selected="true" Text="Root RadTab1"
                          PageViewID="mainTabPageView"></telerik:RadTab>
                    </Tabs>
                </telerik:RadTabStrip>
                <telerik:RadMultiPage ID="mainPageMultiPageCtrl" runat="server"
                  SelectedIndex="0" Width="100%">
                    <telerik:RadPageView ID="mainTabPageView" runat="server" Height="100%">
                        <iframe src="Main.aspx" class="KRFrame" frameborder="0"></iframe>
                    </telerik:RadPageView>
                </telerik:RadMultiPage>
                <input id="Button1" type="button" value="Add Tab" onclick="addtab()" />
                <input id="SubmitBtn" type="submit" value="Submit" />
            </div>
        </div>
        </form>
    </body>
    </html>

    This produces a page that looks somewhat like image1.png after adding some tabs.  Note, in the code behind of the Content_1.aspx page, I just have static text and a label populated by DateTime.Now. 

    The strange thing that's happening is when I close a tab that's not the selected tab, the PageView doesn't always get hidden correctly.  Other times it does.  For example, looking at image1.png, let's say that I've got Root RadTab5 selected and I close Root RadTab2.  Root RadTab3 will correctly get selected but, if I then select Root RadTab5 with the mouse, it will have Root RadTab3's PageView as well as its own.  This is illustrated in image2.png which shows Root RadTab3 after closing Root RadTab2 and then image3.png which shows Root RadTab5 after selecting it with the mouse.

    This is happening because the PageView isn't getting its css classes changed properly as can be seen in image4.png.

    If I then click Root RadTab3 and then click back on Root RadTab5, everything seems to get back "in sync" and the PageViews display correctly again, as can be seen in image5.png.

    I've been trying all sorts of things to get this resolved.  For instance, I've tried hiding the PageView, unselecting it, etc. but none of those resolve the problem.  The only thing that fixes the problem is not removing the page view and just leaving it in the RadMultiPage.  Because I'm manually assigning PageViewIDs to tabs, those PageViews never display again but they continue to build up in the HTML. 

    Oh, one other weird thing is that this problem only seems to happen when I am on a tab and close a tab 2 or more in front of it (or when selected index is n and the closed tab index is < n-3).  For example, Let's say I have tabs 1, 2, 3, 4, and 5 open.  If I am on tab 5 (at index n = 4) and I close tab 2 (at index n-3 = 1), the problem happens.  On the other hand, if I'm on tab 5 (at index n = 4) and I close tab 3 (at index n-2 = 2), no problem occurs.  Alternatively, let's say I have tabs 1, 2, 3, 4, 5, and 6 open.  If I am on tab 6 (at index n = 5) and I close either tab 2 (at index n-4 = 1) or tab 3 (and index n-3 = 2), the problem occurs.  If I close tab 4 (at index n-2 = 2), no problem.

    Am I doing something wrong or is this a weird bug?  I've been trying to get this figured out but I just can't seem to crack this.  Any help would be much appreciated.

    Regards,
    John

  2. Answer
    Ivan Danchev
    Admin
    Ivan Danchev avatar
    836 posts

    Posted 22 Dec 2015 Link to this post

    Hello John,

    It seems the issue is related to the tab removal and next tab selection performed in a quick succession. We added a slight delay (100 ms) to the selection of the tab and also an extra "for" loop which makes sure no PageView is selected in between the tab removal and the selection and at our end it resulted in a single PageView being displayed without duplication. Here's the section of the addtab() function we changed:
    Before:
    //Select the next tab
    if (tabToSelect) {
        tabToSelect.select();
    }
    After:
    //Select the next tab
    if (tabToSelect) {
        var views = multiPage1.get_pageViews()
        for (var j = 0; j < views.get_count() ; j++) {
            views.getPageView(j).unselect();
        }
     
        setTimeout(function () {
            tabToSelect.select();
        }, 100);
    }

    Regards,
    Ivan Danchev
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  3. UI for ASP.NET Ajax is Ready for VS 2017
  4. John
    John avatar
    9 posts
    Member since:
    Mar 2009

    Posted 18 Jan in reply to Ivan Danchev Link to this post

    Hi Ivan,

    Thanks so much for getting back to me.  I tried out your solution and that fixed the problem.  Thanks for your help and for pointing me in the right direction.

Back to Top