1

I would like to use a jquery 'click' event to change the class of the selected tab. The first tab is initially listed as selected. When I change tabs, I try to step into the click event but it is skipped. It reaches the function and then just skips over it. My project is MVC4 and my jquery library is 1.11.3.
This is my markup:

<header>
<div class="content-wrapper">            
    <p class="site-title">
        <img src="~/Images/logo.png" alt="" />
    </p>                        
    <nav>
        <ul id="menu" class="maintablist">
            <li class="selected">@Html.ActionLink("Home", "Index", "Home")</li>
            <li>@Html.ActionLink("About", "About", "Home")</li>
            <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
        </ul>
    </nav>              
</div>
</header>

This is my jquery function:

<script src="~/Scripts/jquery-1.11.3.js"></script>
<script>
    $("#menu li").click(function () {
        $("#menu li").removeClass("selected");
        $(this).addClass("selected");
    });
</script>

This is my style sheet stuff:

.maintablist {
    list-style:none;
    height: 2em;
    padding: 0;
    margin: 0;
    border: none;
}

.maintablist li {
    float: left;
    margin-right: 0.13em;
}

.maintablist li a {
    display:block;
    padding:0 1em;
    text-decoration:none;
    border:0.06em solid #000;
    border-bottom:0;
    font:bold 0.88em/2em arial,geneva,helvetica,sans-serif;
    color:#000;
    background-color:#ccc;

    /* CSS 3 elements */
    -webkit-border-top-right-radius:0.50em;
    -webkit-border-top-left-radius:0.50em;
    -moz-border-radius-topright:0.50em;
    -moz-border-radius-topleft:0.50em;
    border-top-right-radius:0.50em;
    border-top-left-radius:0.50em;
}

.maintablist li a:hover {
    background:#b5dbb6; 
    color:#fff;
    text-decoration:none;
}

.maintablist li.selected a {
    background-color: #b5dbb6;
    color: #fff;
}

Why isn't the click event recognized? I would like to do this on the client side and not have to go to the HomeController to do this. Thanks.

UPDATE Removed the 'click' event from within the 'ready' function and the class is removed. But the class is not added to my current selected tab. This is the code:

<script>
 $(".maintablist li").removeClass("selected");
 $(this).addClass("selected");
</script>

UPDATE Using this jquery function below, when a tab is clicked it removes the class attribute from all of the tabs. Then the clicked tab is displayed, the initial tab has the 'selected' coloring. All of the tabs should not have a class attribute defined but somehow the class attribute is reapplied to the initial tab yet the selected tab is displayed.

$(document).ready(function () {
    $("#mainmenu li").click(function () {
        $("#mainmenu li").removeClass("selected").removeAttr("class");
    });   
});   

UPDATE I only posted the information that I believe was needed. But below is the code in the file, _Layout.cshtml

<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title OnCall Schedule Tool</title>
    <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
    <meta name="viewport" content="width=device-width" />
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
    <link rel="stylesheet" href="~/Content/jquery-ui.css">
    <link rel='stylesheet' href='~/Content/fullcalendar.css' />
    <link rel='stylesheet' href='~/Content/spectrum.css'>
    <script src="~/Scripts/jquery-1.11.3.js"></script>
    <script src='~/Scripts/jquery.min.js'></script>
    <script src="~/Scripts/jquery-ui.js"></script>
    <script src='~/Scripts/moment.min.js'></script>
    <script src='~/Scripts/fullcalendar.js'></script>
    <script src="~/Scripts/spectrum.js"></script>
    <script src="~/Scripts/knockout-2.2.0.js"></script>
    <script type="text/javascript">
        $(document).ready(function () {
            $("#mainmenu li").click(function () {
                $("#mainmenu li").removeClass("selected").removeAttr("class");
            });   
        });              
    </script>
</head>
<body>
    <header>
        <div class="content-wrapper">            
            <p>
                <img src="~/Images/logo.png" alt="" />
            </p>                                     
            <nav>
                <ul id="mainmenu" class="maintablist">
                    <li class="selected">@Html.ActionLink("View OnCall Schedule", "ViewSchedule", "Home")</li>
                    <li>@Html.ActionLink("Edit OnCall Schedule", "EditSchedule", "Home")</li>
                    <li>@Html.ActionLink("Admin OnCall Application", "Admin", "Home")</li>
                </ul>
            </nav>                    
        </div>
    </header>
    <div id="body">
        @RenderSection("featured", required: false)
        <section class="content-wrapper main-content">
            @RenderBody()
        </section>
    </div> 
    @Scripts.Render("~/bundles/jquery")
    @RenderSection("scripts", required: false)
</body>
</html>
Gloria Santin
  • 2,066
  • 3
  • 51
  • 124

2 Answers2

1

This is what worked for me. Thanks Miodrag for your help but the jquery did not work. I found on another post. I am using MVC4 and it uses those attributes, no jquery. On each page set the PageName attribute of ViewBag on each page like so:

Top of file EditSchedule.cshtml

@{
    ViewBag.PageName = "EditSchedule";
}

Top of file ViewSchedule.cshtml

@{
    ViewBag.PageName = "ViewSchedule";
}

Top of file Admin.cshtml

@{
    ViewBag.PageName = "Admin";
}

In _Layout.cshtml

<nav>
    <ul id="mainmenu" class="maintablist">
        <li class="@((ViewBag.PageName == "ViewSchedule") ? "selected" : "")">@Html.ActionLink("View OnCall Schedule", "ViewSchedule", "Home")</li>
        <li class="@((ViewBag.PageName == "EditSchedule") ? "selected" : "")">@Html.ActionLink("Edit OnCall Schedule", "EditSchedule", "Home")</li>
        <li class="@((ViewBag.PageName == "Admin") ? "selected" : "")">@Html.ActionLink("Admin OnCall Application", "Admin", "Home")</li>
    </ul>
</nav>   

In Style.css file defining the look of the tabs:

.maintablist {
    list-style:none;
    height: 2em;
    padding: 0;
    margin-top: 20px;
    margin-bottom: 0;
}

.maintablist li {
    float: left;
    margin-right: 0.13em;
}

.maintablist li a {
    display:block;
    padding:0 1em;
    text-decoration:none;
    border:0.06em solid #000;
    border-bottom:0;
    font:bold 0.88em/2em arial,geneva,helvetica,sans-serif;
    color:#000;
    background-color:#ccc;

    /* CSS 3 elements */
    -webkit-border-top-right-radius:0.50em;
    -webkit-border-top-left-radius:0.50em;
    -moz-border-radius-topright:0.50em;
    -moz-border-radius-topleft:0.50em;
    border-top-right-radius:0.50em;
    border-top-left-radius:0.50em;
}

.maintablist li a:hover {
    background: #b5dbb6;
    color:#fff;
    text-decoration:none;
}

.maintablist li.selected a{
    background-color: #b5dbb6;
    color: #fff;
    border-bottom: 0;
}
Gloria Santin
  • 2,066
  • 3
  • 51
  • 124
0

You should put your javascript code into $(document).ready() function:

<script>
    $(document).ready(function() {
        <!-- put your javascript code here -->
    });
</script>

UPDATE

It just was in front of our eyes: You also need to prevent default behavior of anchor elements which causes page refreshing by returning false.

$("#mainmenu li").click(function () {
    $(this).siblings().removeClass("selected");
    $(this).addClass("selected");
    return false;
});

Additionally, I have to mention you use three references to jQuery. It should be only one and referenced anywhere before its first use (for example, before document ready function).

mdr
  • 16
  • 4
  • It is still skipping the click function. I can step into the .ready function but it will not step into the click function. – Gloria Santin Sep 24 '15 at 19:30
  • There are no other issues with code you posted. If you don't catch click event it could mean that jquery selector isn't right. Do you have another html element on the page with id="menu"? – mdr Sep 24 '15 at 20:36
  • There is not another element with that ID. I changed the selector to use the class name 'maintablist'. When I select another tab from the initial tab, it initially changes to the 'selected' color but after the page loads the tab changes back to the 'unselected' color. – Gloria Santin Sep 25 '15 at 14:43
  • A trick to preserve state across multiple pages would be to place navigation into their layout, that is a common practice. If that isn't the case, please post another code which could interfere with already posted one. – mdr Sep 25 '15 at 19:40
  • I was able to at least step into the ready document function by removing the click event. This now makes sense since the 'ready' event just initializes stuff. However, the class is removed. But I cannot figure out how to add a class to the selected tab. I added my code above, under 'UPDATE' – Gloria Santin Sep 25 '15 at 20:58
  • You cannot do like that. For example _this_ in that way references to window object not to clicked list item element. – mdr Sep 25 '15 at 21:39
  • Yes. That does not work. I changed the coloring so that hover is different than 'active'. When I click on the tab, the tab does change to the 'active' coloring when clicked. But it does not remain. The coloring does back to the original coloring after the click event. I need it to stay. I cannot figure out how to add a class to the selected tab. – Gloria Santin Sep 28 '15 at 15:00
  • Highlighting a selected tab should not be this difficult. Can anyone provide any more help? – Gloria Santin Sep 28 '15 at 16:16
  • You posted html markup, js code and css styles, but you haven't posted how they are connected. Please post code in detail not just fragments. – mdr Sep 28 '15 at 18:26
  • I posted the complete cshtml page, _Layout.cshtml. Is this all you need? – Gloria Santin Sep 28 '15 at 18:48
  • Please check out the answer updated a couple days ago. – mdr Sep 30 '15 at 19:22
  • Thanks for the update. When I use your answer above, the tabs change to the active color but the page does not change. Removing 'return false', as you point out, changes the page and the coloring temporarily until the refresh. Then the highlight changes back to the initial page. – Gloria Santin Oct 01 '15 at 13:26
  • Ah, that's true. In the world of a full page refresh/postback it's not really possible to do it in that way. Actually here in stackoverflow there are a couple solutions for the same problem you have. Just one of them: http://stackoverflow.com/a/6323032/5373433 – mdr Oct 01 '15 at 19:16