I have the following header that will toggle between pages:
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-collapse collapse">
<form method="post">
<ul class="nav navbar-nav">
<li class="active">Active Tags</li>
<li>Archived Tags</li>
</ul>
</form>
</div>
</div>
</nav>
and the following jQuery to toggle the active li on click:
$('.navbar li').click(function(e) {
$('.navbar li.active').removeClass('active');
var $this = $(this);
if (!$this.hasClass('active')) {
$this.addClass('active');
}
e.preventDefault();
});
Moving between pages works only when e.preventDefault(); is commented out but the active class toggle won't work without this line... will I have to change my href's to sometype of onclick jQuery function or php $_POST of a hidden form to move between pages while retaining the toggle between active li's? Am new to javascript/html/php so as much detail and reasoning as possible is quite encouraged and encouraging.
Yes, you are right, e.preventDefault() will just toggle active class on li and restrict anchor to perform its operation.
While, changing it to e.stopPropagation() will allow both operation to perform at their own, without notifying regarding their event to parent handler.
Prevents the event from bubbling up the DOM tree, preventing any
parent handlers from being notified of the event.
Therefore, you can change it to:
$('.navbar li').click(function(e) {
e.stopPropagation();
$('.navbar li.active').removeClass('active');
var $this = $(this);
if (!$this.hasClass('active')) {
$this.addClass('active');
}
});
DEMO
Related
I have searched a lot for adding active class to the parent menu using javascript.
I found many more examples but not a single one is working for me, below is my code
HTML
<div id="menu1" class="hmenu">
<ul>
<li>Item1
<ul>
<li>SubItem1
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
<li>SubItem2 </li>
<li>SubItem3
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
</ul>
</li>
<li>Item2</li>
<li>Item3
<ul>
<li>SubItem1
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
</ul>
</li>
</ul>
<br style="clear: left" />
</div>
My requirement is when i click on SubItem1 then both Item1 and SubItem1 should be active.
And when i click on SubSubItem1 then SubSubItem1 ,SubItem1 and Item1 should be active.
Means when click on any link then its all parent link and the same link should be active.
I have tried with this javascript code :
$(document).ready(function () {
$('.hmenu ul li ul').find('li').click(function () {
//removing the previous selected menu state
$('.hmenu').find('li.active').removeClass('active');
//adding the state for this parent menu
$(this).parents('li').addClass('active');
});
});
Actually i don't have any experience with javascript coding and unable to figure out the problem in my code.
Can anyone suggest me for the same.
The issue comes from .find('li').click().
As you use nestsed <li>, this will cause the event to be fired two times when you click on a child <li>. This causes problems. Can not you add the click() to <a> elements?
$(document).ready(function () {
$('.hmenu a').click(function () {
//removing the previous selected menu state
$('.hmenu').find('li.active').removeClass('active');
//adding the state for this parent menu
$(this).parents("li").addClass('active');
});
});
It works just fine: https://jsfiddle.net/6put8tdx/
Note that your page will be bumped to the top while clicking to a tab because of # anchor. If you want to prevent this, you may pass the event to the function .click(function (event) {...} and add event.preventDefault inside.
If you need the click target to be the LI element (as opposed to Delgan's answer)
you can use .not() over the targeted LI's parents to prevent messing with the bubbling event targets:
$(document).ready(function () {
$('.hmenu').find('li').click(function(event) {
event.preventDefault(); // Prevent page jumps due to anchors
var $par = $(event.target).parents("li"); // get list of parents
$(".hmenu .active").not( $par ).removeClass("active"); // not them
$(this).addClass('active'); // let the event propagation do the work
});
});
$(document).ready(function () {
$('.hmenu').find('li').click(function(event) {
event.preventDefault();
var $par = $(event.target).parents("li");
$(".hmenu .active").not($par).removeClass("active");
$(this).addClass('active');
});
});
.active > a{
background: gold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="menu1" class="hmenu">
<ul>
<li>Item1
<ul>
<li>SubItem1
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
<li>SubItem2 </li>
<li>SubItem3
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
</ul>
</li>
<li>Item2</li>
<li>Item3
<ul>
<li>SubItem1
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
</ul>
</li>
</ul>
<br style="clear: left" />
</div>
To better understand the above
The following example works out-of-the-box, and the clicked one and all it's LI parents get the "active" class.
Why? Cause the event target is li, means any li of .hmenu - so that click is attached to any of them, and clicking the subsub LI the event will propagate to the LI parents - triggering the same click behavior (this add class)!
$(".hmenu").on("click", "li", function(){
$(this).addClass("active"); // Wow! Event propagation rulez!!
});
But we need to remove existing .active and here it gets messy...
$(".hmenu").on("click", "li", function(){
$(".active").removeClass("active"); // triggered on every event bubble :(
$(this).addClass("active"); // leaving only the main parent with active class
});
That's caused by the concurrency that happens while the event bubbles and triggers the same actions for the parent elements.
One way to prevent that concurrency would be using a setTimeout of 1ms:
$(".hmenu").on("click", "li", function(){
$(".active").removeClass("active");
setTimeout(function(){ // Let the previous finish the bubbling mess
$(this).addClass("active"); // Yey! all fine! Every LI has the active class
}, 1);
});
But here the timeout of 1ms can lead to visual "blinking" issues.
Try this:
$(function () {
$("li a")
.on("click", function () {
$(this).toggleClass("active");
$(this).closest("ul").parent().children("li a").toggleClass("active")
.parent().parent().parent().children("li a").toggleClass("active");
});
});
fiddle
Traverse from the clicked element. And use toggleClass() to avoid the mundane checking if hasclass removeClass ...
Hi I have a navbar in my home.scala.html as follows-
<ul class="nav nav-justified">
<li>#Messages("views.main.apps")</li>
<li >#Messages("views.main.activity")</li>
<li>#Messages("views.main.devices")</li>
<li>#Messages("views.main.account")</li>
<li id="logout">#Messages("views.main.logout")</li>
</ul>
I am trying to set active class on click as follows-
<script>
$(document).ready(function () {
$('ul.nav > li').click(function (e) {
$('ul.nav > li').removeClass('active');
$(this).addClass('active');
});
});
</script>
However on running the application only the li elements which have href="#" get set as active ,the other li elements remain inactive on click even though the page is redirected to the link of the tag.
Any help would be appreciated.
Thanks
Edit:The structure of the main.scala.html is
<html>
<head></head><body>
<ul class="nav nav-justified">
<li>#Messages("views.main.apps")</li>
<li >#Messages("views.main.activity")</li>
<li>#Messages("views.main.devices")</li>
<li>#Messages("views.main.account")</li>
<li id="logout">#Messages("views.main.logout")</li>
</ul>
</div>
</nav>
<div id="showsspData">
#content
</div>
</div>
</body>
</html>
Then the apps.scala.html will be as-
#main("string to pass"){
//html content for page
}
You need to use e.preventDefault() to prevent default action of the anchor and target .click() handler on the anchors instead:
$(document).ready(function () {
$('ul.nav > li a').click(function (e) {
e.preventDefault();
$('ul.nav > li').removeClass('active');
$(this).closest('li').addClass('active');
});
});
I have a tab control on my page with two tabs. When I click on the second tab, the page scrolls down to the tab control. I don't want to have any focus on the tab control and maintain the page where it was. I know it happens due to the href on the <li> but if I remove the href I don't see any data.
My html code is as below:
<div id="tabContainer" class="Container">
<ul class="maintabs">
<li>Description</li>
<li>Terms</li>
</ul>
<div class="tabDetails">
<div id="tabDescription" class="tabContents">
<div id="divDescription" runat="server"></div>
</div>
<div id="tabTerms" class="tabContents">
<div id="divterms" runat="server"></div>
</div>
</div>
</div>
Javascript:
<script type="text/javascript">
$(document).ready(function () {
$(".tabContents").hide();
$(".tabContents:first").show();
$("#tabContainer ul li a").click(function () {
var activeTab = $(this).attr("href");
$("#tabContainer ul li a").removeClass("active");
$(this).addClass("active");
$(".tabContents").hide();
$(activeTab).show();
});
});
</script>
You need to disable the default behavior of the link from occurring.
For your click action, accept the first argument, e (for event) and call JQuery's preventDefault function on it. This will stop the browser from following the link.
$("#tabContainer ul li a").click(function (e) {
// hey browser, don't handle this link--we'll take it from here
e.preventDefault();
// ...
});
You can call that anywhere in the function (e.g., at the end).
I have a jQuery code that: onlick on #icon toggles parents class, and onclick on body changes changes the class back if clicked before.
What I need is to have the same thing happen when clicked on #item5 or #item4 like its clicked on #icon.
<div id="header_wrap">
<div id="logo"></div>
<div class="contact" id="ccontainer">
<div id="form"></div>
<div id="icon"><span id="getintouch">GET IN TOUCH</span></div>
</div>
<div id="menu_wrap">
<ul id="menu">
<li id="item1">Home</li>
<li id="item2">About us</li>
<li id="item3">What we do</li>
<li id="item4">Portfolio</li>
<li id="item5">Contact us</li>
</ul>
</div>
</div>
jQuery code....I tried writing my own to add the functionality but I can't seem to get it working.. very little experience with js/jq.
$('#icon').on('click', function(e){
$(this).parent()
.toggleClass('contact')
.toggleClass('contactexpand');
});
$('body').on('click', function(e){
$('#ccontainer')
.removeClass('contactexpand')
.addClass('contact');
});
$('#ccontainer').on('click', function(e){
e.stopPropagation();
});
You have to call event.stopPropagation from the click handler to keep it from "bubbling" up the DOM (i.e., to keep it from activating the click event on all ancestor elements).
$(document).ready(function(){
$('#icon, ul li').on('click', function(event){
event.stopPropagation();
$('#icon').parent()
.toggleClass('contact')
.toggleClass('contactexpand');
});
$('body').on('click', function(e){
$('#ccontainer')
.removeClass('contactexpand')
.addClass('contact');
});
});
Change the js to:
$('#icon, #ul > li').on('click', function(e){
$("#ccontainer")
or $(this).parent() *not entirely sure what you wanted to get*
.toggleClass('contact')
.toggleClass('contactexpand');
});
$('body:not(#icon, #ul > li)').on('click', function(e){
$('#ccontainer')
.removeClass('contactexpand')
.addClass('contact');
});
$('#ccontainer').on('click', function(e){
e.stopPropagation();
});
The #ul > li refers to all #item(number)s
I have the following code structure:
<ul class='menu'>
<li>
Main Menu
<ul class='hide'>
<li>SubMenu1</li>
<li>SubMenu2</li>
</ul>
</li>
<li>
Main2
<ul class='hide'>
<li>Sub1</li>
</ul>
</li>
</ul>
Is there a way for me to have a jQuery click event on Main Menu and Main2 in a generic way that will remove the class 'hide' of the correct children each time?
Here is another way, which uses event delegation and only runs when the li element and not its children was clicked:
$('ul.menu').on('click', 'ul.menu > li', function(e) {
if(e.target === this) {
$(this).children('ul').toggleClass('hide');
}
});
DEMO
$("ul.menu > li").on("click", function () {
$(this).children("ul").removeClass("hide");
});
Example: http://jsfiddle.net/dpkBL/
Dont always do what the crowd tells you, at least think about it for a while!
I bet people will recommend you to use a selector such as ul.menu > li, but please remember that this will not only trigger a click event when you click on the text "Main Menu", but also when you click on any of the other content inside the matching li.
If you'd like to implement a show/hide toggle you are far better off wrapping the text "Main Menu" inside it's on element, and then use something as the below to alter what you may want to alter.
$(<main menu text selector>).siblings (<siblings selector>);
Still want/have to follow the crowd?
If this is the case I'd recommend you to at least do it with a little twist to prevent what I previously described.
(edit: revised version after reading the jquery documentation for elements)
$('ul.menu > li').click (function(e){
if (e.target === this) {
$(this).children ('.hide').removeClass ('hide');
}
});
$("ul.menu > li").click (function () {
$(this).find ('.hide').removeClass ('hide');
});
$("ul.menu > li > *").click (function () {
return false; // prevent event from bubbling up
});
Sample implementation of recommended version
The below will bind a click-event-listener to .menu-toggle, when the event is fired the siblings (ie. the tags who are in the same scope as the clicked .menu-toggle) matching .hide will have their class="hide" removed.
Javascript
$(".menu-toggle").click (function () {
$(this).siblings ('.hide').removeClass ('hide');
});
HTML
<ul class='menu'>
<li>
<span class="menu-toggle">Main Menu</span>
<ul class='hide'>
<li>SubMenu1</li>
<li>SubMenu2</li>
</ul>
</li>
<li>
<span class="menu-toggle">Main2</span>
<ul class='hide'>
<li>Sub1</li>
</ul>
</li> </ul>
Take a look at the child selectors. I think that is what you want.
$('.menu > li').click(function () {
$(this).children('ul').removeClass('hidden');
});