Toggle class on element, ignore all but one child - javascript

Having a hard time solving this even after reading jQuery stopPropagation for only some class of elements, Javascript toggle class on element and countless other references.
I want to toggle class "active" when clicking on nav > ul > li AND .dd-toggle (a child of .dropdown) but NOT .dropdown itself or anything within it (other than .dd-toggle).
<nav class="nav-dropdowns" role="navigation">
<ul>
<li class="">
<span class="dropdown-title">Price</span>
<div class="dropdown">
<a class="dd-toggle">X</a>
<div id="field-price" class="field"><label>Price Range</label>
<div class="details"></div>
</div>
</div> <button type="submit" class="extra-submit buttonstyle">Search</button>
</div>
</li>
<li class="">
<span class="dropdown-title">Type</span>
<div class="dropdown">
<a class="dd-toggle">X</a>
<div id="field-type" class="field"><label>Property Type</label>
<div class="details"></div>
</div> <button type="submit">Search</button>
</div>
</li>
<li class="search-submit">
<button class="search-button" type="submit">Search</button>
</li>
</ul>
</nav>
I have tried numerous variations starting with:
jQuery(document).ready(function($){
$( "nav > ul > li" ).click(function() {
$( this ).closest().toggleClass( "active" );
});
});
then
jQuery(document).ready(function($){
$( "nav > ul > li" ).click(function() {
$( this ).toggleClass( "active" );
});
$('.dropdown').click(function(e) {
return false;
});
});
and finally
jQuery(document).ready(function($){
$( "nav > ul > li" ).click(function( event ) {
event.stopImmediatePropagation();
$( this ).toggleClass( "active" ).not('.dropdown');
});
});
I get ignoring the children of or closest to, but can't figure out how to do that but still observe a child of the child. Perhaps only first child of?
Ignore .dropdown but NOT .dd-toggle
Am I close?

I would really recommend reading:
Decoupling Your HTML, CSS, and JavaScript. It will really reduce your tightly coupled code.
Everything in Green will change to red, unless you are in blue (in green). Although I'm not sure (because you're question isn't clear) if you're asking for active on either the li and the .dd-toggle (as it is now) or only the li which wouldn't be hard.
If you need active only on the li simply change the .dd-toggle code to:
$(this).parents('li').first().toggleClass('active');
CodePen.IO Working Example
$(document).ready(function() {
$("nav > ul > li").on("click", function(e) {
if ($(e.target).parents('.dropdown').length === 0 &&
!$(e.target).hasClass('dropdown')) {
$(this).toggleClass("active");
}
});
$(".dd-toggle").on("click", function(e) {
$(this).toggleClass("active");
});
});
nav > ul > li, .dd-toggle {
border: 2px solid green;
cursor: pointer;
user-select: none;
}
.active {
border: 2px solid red;
}
.dropdown {
border: 2px solid blue;
cursor: default;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav class="nav-dropdowns" role="navigation">
<ul>
<li class="">
<span class="dropdown-title">Price</span>
<div class="dropdown">
<a class="dd-toggle">X</a>
<div id="field-price" class="field"><label>Price Range</label>
<div class="details"></div>
</div>
</div> <button type="submit" class="extra-submit buttonstyle">Search</button>
</div>
</li>
<li class="">
<span class="dropdown-title">Type</span>
<div class="dropdown">
<a class="dd-toggle">X</a>
<div id="field-type" class="field"><label>Property Type</label>
<div class="details"></div>
</div> <button type="submit">Search</button>
</div>
</li>
<li class="search-submit">
<button class="search-button" type="submit">Search</button>
</li>
</ul>
</nav>

Related

Add/remove class/id to nav when scrolling to that posistion

right now i have this code to indicate on the nav links what id i am on.
But how can i also add a scroll function, if i scroll down to specific id then add the class to the right nav link. Thank you.
$(window).load(function(){
$("nav.site-nav ul.open.desktop li a").click(function() {
$('.current_yes').removeClass('current_yes');
$(this).addClass("current_yes");
});
});
jQuery(document).ready(function($){
var url = window.location.href;
$('nav.site-nav ul.open.desktop li a').filter(function() {
return this.href == url;
}).closest('a').addClass('current_yes');
});
and the nav look like this:
<div class="wrapper">
<nav class="site-nav">
<div class="menu-toggle">
<div class="hamburger"></div>
</div>
<ul class="open desktop">
<li><a id="link1" href="index.php#"><i class="site-nav--icon"></i>Hem</a></li>
<li><a id="link2" href="index.php#products-anchor"><i class="site-nav--icon"></i>Produkter</a></li>
<li><a id="link3" href="index.php#uthyres-anchor"><i class="site-nav--icon"></i>Uthyres</a></li>
<li><a id="link4" href="#rent"><i class="site-nav--icon"></i>Kontakta</a></li>
</ul>
</nav>
</div>
The css for current link:
.current_yes {
border-bottom: 2px solid #732813;
}

Javascript change effect for <ul><li> is not working correctly

I am new to Javascript. I want to click on the Navi bar to change some effect(underline to the words)
Coding for HTML
<div class="nav" id="nav">
<ul>
<li>Home</li>
<li>text1</li>
<li>text2</li>
</ul>
</div>
<div id="text1"> <!--> jump to here<-->
.....
</div>
<div id="text2"> <!--> jump to here<-->
.....
</div>
<script>
function SetTabState(dom){
$("#nav ul li").find('.underline_text').removeClass('underline_text');
$(dom).addClass('underline_text');
}
</script>
Just like the screenshot, when clicking "text1" tab, the home underline is removed and "text1" underline is added...
However, for my coding, when clicking on "text1", the underline is not changing and remain at "home". Anyone knows the problem here? Thx!
This is because from your html
<a href="index.html#text2" onclick="SetTabState(this)">
this refer to <a>, so dom is actually an <a>
From your SetTabState(dom), dom suppose to be a <li>?
You can add a event delegation to the <ul> with delegate to the <li>, like
function SetTabState(dom) {
$("#nav ul li").find('.underline_text').removeClass('underline_text');
$(dom).addClass('underline_text');
}
$(document).ready(function() {
$("#nav ul").on('click', 'li', function() {
SetTabState(this)
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="nav" id="nav">
<ul>
<li>Home</li>
<li>text1</li>
<li>text2</li>
</ul>
</div>
<div id="text1">
<!-->jump to here
<-->
.....
</div>
<div id="text2">
<!-->jump to here
<-->
.....
</div>
As others have said, the dom variable refers to the <a> element, but you're trying to remove the class from the <li>. Instead of using .find, you can directly select the element with the underline_text class:
<script>
function SetTabState(dom){
$("#nav ul li .underline_text").removeClass('underline_text');
$(dom).addClass('underline_text');
}
</script>
You can do like this :-
function SetTabState(dom){
$("#nav ul li a").removeClass('underline_text');
$(dom).addClass('underline_text');
}
ul {
padding: 0;
margin: 0;
list-style: none;
}
ul li a {
text-decoration: none;
}
ul li a.underline_text {
border-bottom: 1px solid #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="nav" id="nav">
<ul>
<li>Home</li>
<li>text1</li>
<li>text2</li>
</ul>
</div>
Because you need to change the state of the other elements rather than the only element you clicked, I suggest you use a function for the whole group of elements instead of handle click event on each element. This is my code:
function initClickableNav(nav) {
var navItems = nav.querySelectorAll('a');
var activeClass = 'underline_text';
nav.addEventListener('click', function (event) {
[].forEach.call(navItems, function (navItem) {
if (navItem === event.target || navItem.contains(event.target)) {
navItem.classList.add(activeClass);
} else {
navItem.classList.remove(activeClass);
}
});
});
}
initClickableNav(document.querySelector('#nav'));
HTML
<div class="nav" id="nav">
<ul>
<li><span>Home</span></li>
<li>text1</li>
<li>text2</li>
</ul>
</div>

Two active tabs at the same time! How do I do?

The website I am working on has two panels side by side with tabs. It needs to have two panels active at the same time. If I switch panels on the right side, the panel on the left side should still display its content. Now, only one tab is active after I have chosen to switch tab on any of the panels.
I did begin to use Bootstrap, but it was decided that it should be removed from the project. I have then written new SCSS, modified the HTML and created a new javascript file.
Here are some code snippets: First the Javascript file, which handles the logic. Then you can see the code for the left bar, and the content on the panels, and so on.
$(document).ready(function() { /*Javascript for the left bar */
$('ul.nav li').click(function() {
var tab_id = $(this).attr('data-tab');
$('ul.nav li').removeClass('current');
$('.tab-content').removeClass('current');
$(this).addClass('current');
$("#" + tab_id).addClass('current');
});
$('ul.cor.li').click(function() { /*Javascript for the right bar */
var tab_id = $(this).attr('data-tab');
$('ul.cor.li').removeClass('active');
$('.tab-content').removeClass('active');
$(this).addClass('active');
$("#" + tab_id).addClass('active');
});
});
ul.nav li {
list-style-type: none;
display: inline;
overflow: hidden;
padding: 3px 15px;
cursor: pointer;
}
.tab-content {
display: none;
background: white;
padding: 15px;
}
.tab-content.current {
display: inherit;
}
.navbar-light {
border-left-color: black;
}
.nav,
.tabs {}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<!-- left side bar -->
<div class="flex-container">
<div class="overview-flexbox-mid">
<div id="leftPanel">
<ul class="nav nav-tabs navbar-light bg-light" id="leftTabs">
<li class="nav-item nav-link current" data-tab="tab-1"><i class="fa fa-compress" aria-hidden="true"></i> Subject1
</li>
<li class="nav-item nav-link" data-tab="tab-2"><i class="fa fa-book" aria-hidden="true"></i> Subject2
</li>
</ul>
</div>
</div>
</div>
<div id="tab-1" class="tab-content current">
<div class="flex-container-horizontal" id="leftPanelContent1">
<h1>Some text</h1>
</div>
</div>
<!-- left side content -->
<div id="tab-2" class="tab-content">
<h1>More text</h1>
</div>
<!-- right side bar -->
<div class="overview-flexbox-mid">
<div id="rightPanel">
<ul class="cor nav nav-tabs navbar-light bg-light" id="rightTabs">
<li class="nav-item nav-link active" data-tab="tab-5"><i class="fa fa-bar-chart" aria-hidden="true"></i> Subject3
</li>
<li class="nav-item nav-link" data-tab="tab-6"><i class="fa fa-signal" aria-hidden="true"></i> Subject4
</li>
</ul>
</div>
</div>
<!--right side content-->
<div id="tab-5" class="tab-content active">
<div class="flex-container-horizontal">
<h1>Content</h1>
</div>
</div>
<div id="tab-6" class="tab-content">
<h1>Content 2</h1>
</div>
wrap the left and right tab bars in a div with a class of wrap, select to remove the current class based on that class
<div class="wrap">
......
<div id="leftPanel"></div>
......
</div>
<div class="wrap">
......
<div id="rightPanel"></div>
......
</div>
js:
$('.nav li').click(function() {
var tab_id = $(this).attr('data-tab');
$(this).closest('.wrap').find('ul.nav li,.tab-content').removeClass('current');
$(this).addClass('current');
$("#" + tab_id).addClass('current');
})
demo
You trying to remove active class from an activated tab content but while both tab content has same class name, both will lose their active class. modify like this:
$(document).ready(function () {
$('ul.nav li').click(function () {
var tab_id = $(this).attr('data-tab');
$(this).removeClass('current');
$(this).find('.tab-content').removeClass('current');// modify this
$(this).addClass('current');
$("#" + tab_id).addClass('current');
});
$('ul.cor.li').click(function () {
var tab_id = $(this).attr('data-tab');
$(this).removeClass('active');
$(this).find('.tab-content').removeClass('active');
$(this).addClass('active');
$("#" + tab_id).addClass('active');
});
});

Toggle list items after button click using jQuery

So i managed to get my buttons to show the list items in the unordered list. But now every time i click a button all the list items nested in unordered list appears and disappears when the button is clicked again.
This is my updated HTML:
<div class="container-fluid text-center bg-black" id="services">
<div class="services">
<h2>SERVICES</h2>
<br>
<div class="row">
<div class="col-sm-3 iconpad-even">
<img src="img/icons/icon_data_edit.png" alt="data"/>
<button class="icon-btn" data-button="btnData">DATA</button>
<ul class="showData">
<li>Design</li>
<li>Cable Installation</li>
<li>Testing</li>
<li>CAT5e, CAT6, CAT6A</li>
</ul>
</div>
<div class="col-sm-3 iconpad-odd">
<img src="img/icons/fiber-icon-edit.png" alt="fiber-icon" />
<button class="icon-btn" data-button="btnFiber">FIBER</button>
<ul class="showData">
<li>Consultancy</li>
<li>Building to Building</li>
<li>Network Backbone</li>
<li>Testing</li>
</ul>
</div>
Basically i have 6 div's that are structured the exact same way, only difference is the content on the list items.
I've removed the display:none on the services ul li and added it to the css .showData class as suggested by #Mohammed-Yusef
Here's the current jQuery:
$(function() {
$('.icon-btn').on('click', function() {
$('.showData').toggle();
});
});
The jquery syntax of the click function should be as given below and also in your css you are hiding all the li elements. So you have to toggle them back with the selector $('.showData li') instead of $('.showData'). Also use .icon-btn instead of .icon-button as you don't have such a class mentioned in your html.
$('.icon-btn').on('click', function() {
$('.showData li').toggle();
});
Working snippet,
$(function() {
$('.icon-btn').on('click', function() {
//$('.showData li').toggle();
$(this).next('.showData').find('li').toggle();
});
});
.services ul li {
display: none;
margin-left: -1.8em;
/*color: #fff;*/
list-style: none;
margin-bottom: 1em;
font-size: 20px;
font-weight: bold;
font-family: 'Oswald', 'open-sans';
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container-fluid text-center bg-black" id="services">
<div class="services">
<h2>SERVICES</h2>
<br>
<div class="row">
<div class="col-sm-3 iconpad-even">
<img src="img/icons/icon_data_edit.png" alt="data"/>
<button class="icon-btn" data-button="btnData">DATA</button>
<ul class="showData">
<li>Design</li>
<li>Cable Installation</li>
<li>Testing</li>
<li>CAT5e, CAT6, CAT6A</li>
</ul>
</div>
<div class="col-sm-3 iconpad-odd">
<img src="img/icons/fiber-icon-edit.png" alt="fiber-icon" />
<button class="icon-btn" data-button="btnFiber">FIBER</button>
<ul class="showData">
<li>Consultancy</li>
<li>Building to Building</li>
<li>Network Backbone</li>
<li>Testing</li>
</ul>
</div>
Please try it
$( "body" ).on( "click", ".icon-button", function(){
$('.showData').toggle();
});
The problem is that you don't have an element with a class icon-button your button has a class icon-btn so use $('.icon-btn') instead of $('.icon-button')
and you can use
$(function() {
$('.icon-btn').on('click', function() {
$('.showData').toggle();
});
});
and in css use
.showData{
display: none;
}
and remove display:none from .services ul li
Note: be sure to include jquery

Appended content do not get the proper CSS effect

I want append an HTML element into a DIV, but this one do not get the proper CSS like the original ones.
I have a dropdown menu, and want append on it new <li> rows.
My HTML code:
<br/><br/>
Append it
<div class="container">
<div class="row">
<div class="col-sm-3">
<h5>Normal Dropdown Button</h5>
<div class="panel panel-default">
<div class="panel-body">
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span data-bind="label">Select One</span> <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<div id="append">
</div>
<li>Item 1</li>
<li>Another item</li>
<li>This is a longer item that will not fit properly</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<br/><br/>
My Javascript code:
$( document.body ).on( 'click', '.append', function( event ) {
$("#append").append("<li>Item 1</li>");
return false;
});
Here a live example: http://jsfiddle.net/dJDHd/2136/
EDITED WITH MY MAIN PROBLEM:
https://jsfiddle.net/Lr7gn020/1/
Click on APPEND IT, and then check the appended element by clicking on Select One button (Dropdown menu), and you will see that it do not get the proper CSS like the others (Item Test).
You've nested a div in the ul and the styles target .dropdown-menu>li>a so the div is breaking that. A div can't be a direct child of a ul and li can't be a direct child of a div. Instead of nesting a div in the ul, then appending li's to the div, you can $.prepend() li's directly to the menu, if you want them to appear at the beginning of the menu when you add them. If you don't care where they appear, you can $.append() them to the bottom instead.
$(document.body).on('click', '.append', function(event) {
$(".dropdown-menu").prepend("<li>Item Test</li>");
return false;
});
.btn-input {
display: block;
}
.btn-input .btn.form-control {
text-align: left;
}
.btn-input .btn.form-control span:first-child {
left: 10px;
overflow: hidden;
position: absolute;
right: 25px;
}
.btn-input .btn.form-control .caret {
margin-top: -1px;
position: absolute;
right: 10px;
top: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<br/><br/>
Append it
<div class="container">
<div class="row">
<div class="col-sm-3">
<h5>Normal Dropdown Button</h5>
<div class="panel panel-default">
<div class="panel-body">
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span data-bind="label">Select One</span> <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li>Item 1</li>
<li>Another item</li>
<li>This is a longer item that will not fit properly</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<br/><br/>
The reason behind the appended option having different css is due to the fact that you are appending it inside a div element.
The current CSS of the li elements comes from the bootstrap css with this selector.
dropdown-menu>li>a
Since you have a div node inside ul (which is wrong and make html invalid) and you are appending a new li inside this div with JS, the above selector will not reach this node and CSS will not be applied.
You should add the li node directly under the ul node.
Fiddle : http://jsfiddle.net/9med3Lou/
Change your jquery part.
$( document.body ).on( 'click', '.append', function( event ) {
$(".dropdown-menu").append("<li>Item 1</li>"); //append with ul, not div
return false;
});

Categories