How to hide an accordion tab on second click - javascript

Let's say I open an accordion tab with one click, and I want to close it with the second click.
This is the JS/jQuery I have so far:
var APP = window.APP = window.APP || {};
APP.accordion = (function () {
var $accordionHeader = $('.accordion__header');
var $accordionContent = $('.accordion__content');
var showAccordionContent = function(e) {
var $t = $(this);
$accordionHeader.removeClass('accordion__header--active');
$t.addClass('accordion__header--active');
$accordionContent.removeClass('accordion__content--expanded');
$t.next().addClass('accordion__content--expanded');
$('html, body').animate({
scrollTop: $t.offset().top - 60
}, 500);
e.preventDefault();
};
var bindEventsToUI = function () {
$accordionHeader.on('click', showAccordionContent);
};
var init = function () {
bindEventsToUI();
};
return {
init: init
};
}());
HTML:
<div class="accordion__tab">
<a href="#" class="accordion__header accordion__header--active">
Setting alerts
<span class="accordion__arrow"></span>
</a>
<div class="accordion__content">
<p>
{{!-- things --}}
</p>
<ul class="cf">
<li>
{{!-- more things --}}
</li>
</ul>
</div>
</div>
<div class="accordion__tab">
<a href="#" class="accordion__header">
Setting alerts
<span class="accordion__arrow"></span>
</a>
<div class="accordion__content">
<p>
{{!-- things --}}
</p>
<ul class="cf">
<li>
{{!-- more things --}}
</li>
</ul>
</div>
</div>
Suggestions?

I would do it like this, just some pseudos
var bindEventsToUI = function () {
$accordionHeader.on('click', toggleAccordionContent);
};
var toggleAccordionContent = function (e) {
var accordionIsOpen = $(this).classList.indexOf('accordion__header--active') >= 0; // may need to use another selector base on `this`
return accordionIsOpen ? hideAccordionContent.call(this) : showAccordionContent.call(this);
}

I guess you are looking for this. Modified showAccordionContent method logic a bit.
Hope this is what you are looking for.
This change will now close already open accordion on clicking it. And once you click on inactive accordion-header that will open. There might be a condition where user closes all the accordion after this code change.
var showAccordionContent = function(e) {
var $t = $(this);
/*Modified block logic*/
if($t.hasClass('accordion__header--active')){
$t.removeClass('accordion__header--active');
$t.next().removeClass('accordion__content--expanded');
}else{
$accordionHeader.removeClass('accordion__header--active');
$accordionContent.removeClass('accordion__content--expanded');
$t.addClass('accordion__header--active');
$t.next().addClass('accordion__content--expanded');
}
$('html, body').animate({
scrollTop: $t.offset().top - 60
}, 500);
e.preventDefault();
};

Related

Dropdown content with rotating arrow (css/js)

I'm stuck with my dropdown content. Trying to rotate arrows next to the clicked Button Titles. The first content is opened by default, so that arrow should be turned there by default.
The current code does not turn Content 1 arrow by default and
Click rotates all arrows as I don't know how to refer correctly to
current icon in JS.
Any advices are very welcome.
let dropdownModule = {
init: function(){
this.cacheDom();
this.bindEvents();
},
cacheDom: function(){
this.$el = $('.dropdown-container');
this.$dropdownBox = this.$el.find('.dropdown-box');
this.$dropdownContent = this.$el.find('.dropdown-content');
},
bindEvents:function(){
this.$dropdownBox.on('click', function(){
let currentContent = $(this).next('.dropdown-content');
currentContent.slideToggle(600);
$('.dropdown-content').not(currentContent).slideUp(600);
$('.fa-sort-down').toggleClass('r180');
})
}}
dropdownModule.init();
<div class="dropdown-container">
<div class="dropdown-box">Button Title 1<i class="fas fa-sort-down"></i>
</div>
<div style="display: block;" class="dropdown-content">
Content 1
</div>
</div>
<div class="dropdown-container">
<div class="dropdown-box">Button Title 2<i class="fas fa-sort-down"></i>
</div>
<div class="dropdown-content">
Content 2
</div>
</div>
.fa-sort-down {
transition: all 0.5s ease;
}
.r180 {
transform: rotate(180deg);
}
Basically, when you click on the dropdown it might be the tag getting clicked and you need to find the target first.
Change your js to:
let dropdownModule = {
init: function(){
this.cacheDom();
this.bindEvents();
},
cacheDom: function(){
this.$el = $('.dropdown-container');
this.$dropdownBox = this.$el.find('.dropdown-box');
this.$dropdownContent = this.$el.find('.dropdown-content');
},
bindEvents:function(){
this.$dropdownBox.on('click', function(e){
let target = $(e.target);
if(!$(e.target).hasClass("dropdown-box")){
target = $(e.target).parent();
}
$('.fa-sort-down').removeClass('r180');
let currentContent = target.next('.dropdown-content');
currentContent.slideToggle(600);
$('.dropdown-content').not(currentContent).slideUp(600);
target.find('.fa-sort-down').toggleClass('r180');
})
}}
dropdownModule.init();

Remove class if id's the correct ID

Looking to remove a class if a certain button is clicked.
<div class="slide-container">
<section class="about" id="slide-0">
<div class="menu-total">
<nav class="nav">
<button class="nav_link home" onclick="slideTo('slide-2')">HOME</button>
<button class="nav_link about" onclick="slideTo('slide-0')">ABOUT</button>
<button class="nav_link fun-stuff" onclick="slideTo('slide-1')">FUN STUFF</button>
<button class="nav_link professional" onclick="slideTo('slide-3')">PROFESSIONAL</button>
<button class="nav_link contact" onclick="slideTo('slide-4')">CONTACT</button>
</nav>
<div class="hamburger">
<span class="hamburger__patty"></span>
<span class="hamburger__patty"></span>
<span class="hamburger__patty"></span>
</div>
</div>
The one I want to remove the class on is the HOME button. So "slideTo('slide-2)". If it's clicked on the others then the class is kept. I believe someone is either wrong with my loop or not getting the ID correctly of the items/
function slideTo(slideId) {
const slide = document.getElementById(slideId);
slide.scrollIntoView({
behavior: 'smooth'
})
// above this line works fine
let nonHome = document.querySelectorAll('.slide-container section');
let nonHomeID = document.getElementById('slide-2');
var i;
setTimeout(function(){
for (i=0; i < nonHome.length; i++ ){
// i believe it's somewhere here it is wrong
if (nonHome[i].id != nonHomeID){
nonHome[i].classList.add("nav-visibility");
} else{
nonHomeID.classList.remove("nav-visibility");
}
}
}, 1000)
}
If you can use jquery library, you can write in the HTML:
<button class="nav_link" data-value="home">HOME</button>
...
and then in the JS code:
$(".nav_link").on("click", function() {
var valueClicked = $(this).data("value"); // Get the data-value clicked
$(".nav_link").each(function() { // Loop through all elements of the class 'nav-link'
var v = $(this).data("value");
if (v == valueClicked) {
$(this).removeClass("nav-visibility");
} else {
$(this).addClass("nav-visibility");
}
)
}
Not much simpler, but the HTML is cleaner.
Simpler version if it is not required to browse through all buttons at each button click:
$(".nav_link").on("click", function() {
var valueClicked = $(this).data("value"); // The value of the button clicked by the user
if (valueClicked == "home") {
$(this).removeClass("nav-visibility");
console.log('remove')
} else { $(this).addClass("nav-visibility");
console.log('add')
}
});

Drop down refreshes the page something with href

My problem here is that when I click the other lang it does not change the drop down to that particular lang, my code was working fine it was changing until the moment I added href to
$(document).ready(function(){
var itaImgLink = "http://www.roemheld.de/IT/Data/Images/Address/Italien.gif";
var engImgLink = "http://www.roemheld.de/IT/Data/Images/Address/Grossbritanien.gif";
var deuImgLink = "http://www.roemheld.de/IT/Data/Images/Address/Deutschland.gif";
var fraImgLink = "http://www.roemheld.de/IT/Data/Images/Address/Frankreich.gif";
var imgBtnSel = $('#imgBtnSel');
var imgBtnIta = $('#imgBtnIta');
var imgBtnEng = $('#imgBtnEng');
var imgBtnDeu = $('#imgBtnDeu');
var imgBtnFra = $('#imgBtnFra');
var imgNavSel = $('#imgNavSel');
var imgNavIta = $('#imgNavIta');
var imgNavEng = $('#imgNavEng');
var imgNavDeu = $('#imgNavDeu');
var imgNavFra = $('#imgNavFra');
var spanNavSel = $('#lanNavSel');
var spanBtnSel = $('#lanBtnSel');
imgBtnSel.attr("src",itaImgLink);
imgBtnIta.attr("src",itaImgLink);
imgBtnEng.attr("src",engImgLink);
imgBtnDeu.attr("src",deuImgLink);
imgBtnFra.attr("src",fraImgLink);
imgNavSel.attr("src",itaImgLink);
imgNavIta.attr("src",itaImgLink);
imgNavEng.attr("src",engImgLink);
imgNavDeu.attr("src",deuImgLink);
imgNavFra.attr("src",fraImgLink);
var engLink = "{{url('language/en')}}";
var deuLink = "{{url('language/de')}}";
var fraLink = "{{url('language/fr')}}";
var itaLink = "{{url('language/it')}}";
var linkNavIta = $('#navIta');
var linkNavEng = $('#navEng');
var linkNavDeu = $('#navDeu');
var linkNavFra = $('#navFra');
var linkNavSel = $('#linkNavSel');
$( ".language" ).on( "click", function( event ) {
var currentId = $(this).attr('id');
if(currentId == "navIta") {
imgNavSel.attr("src",itaImgLink);
spanNavSel.text("IT");
linkNavSel.attr("href",itaLink);
} else if (currentId == "navEng") {
imgNavSel.attr("src",engImgLink);
spanNavSel.text("EN");
linkNavSel.attr("href",engLink);
}
else if (currentId == "navDeu") {
imgNavSel.attr("src",deuImgLink);
spanNavSel.text("DE");
linkNavSel.attr("href",deuLink);
} else if (currentId == "navFra") {
imgNavSel.attr("src",fraImgLink);
spanNavSel.text("FR");
linkNavSel.attr("href",fraLink);
}
});
});
.icon-small
{
height:18px;
margin:0;
padding:0;
}
.icon-medium
{
height:22px;
margin:0;
padding:0;
}
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<!------ Include the above in your HEAD tag ---------->
<body>
<ul class="nav navbar-nav">
<li class="dropdown">
<img id="imgNavSel" src="" alt="..." class="img-thumbnail icon-small">  <span id="lanNavSel">ITA</span> <span class="caret"></span>
<ul class="dropdown-menu" role="menu">
<li><a id="navIta" href="#" class="language"> <img id="imgNavIta" src="" alt="..." class="img-thumbnail icon-small">  <span id="lanNavIta">Italiano</span></a></li>
<li><a id="navDeu" href="#" class="language"> <img id="imgNavDeu" src="" alt="..." class="img-thumbnail icon-small">  <span id="lanNavDeu">Deutsch</span></a></li>
<li><a id="navFra" href="#" class="language"><img id="imgNavFra" src="" alt="..." class="img-thumbnail icon-small">  <span id="lanNavFra">Francais</span></a></li>
<li><a id="navEng" href="#" class="language"><img id="imgNavEng" src="" alt="..." class="img-thumbnail icon-small">  <span id="lanNavEng">English</span></a></li>
</ul>
</li>
</ul>
</body>
Here it works as you can see, since the links that I am using are from local host and know it cannot show, but when I try the links appear on each language and I can click the language that I want, it changes that but as soon as I click that it refreshes the page and It stays the first one the italian again it does not change to the other that I selected, I am using Laravel here, I think I has something to do with href link Can someone help me.
In your click event use preventDefault to over-ride the value you've set to the href attribute :
$( ".language" ).on( "click", function( event ) {
event.preventDefault();
.
. // rest of your code
}
All you have to do is cancel the click event with JavaScript to prevent the default action from happening. So when someone clicks the link with JavaScript enabled, the click event is cancelled as you are returning false and prevents the browser from refreshing.
You have to add this code in your jQuery snippet:
$('a').click(function() {
//you can write something else here if you want
return false; // cancel the event
});

Few object in one place

I have one selector: #circle-timer and I have few objects which target is this selector. Is any options to display only the selected item?
Example:
function timer(time){
var target = $('.value');
var counter = time;
var id = setInterval(function() {
counter--;
if(counter < 0) {
clearInterval(id);
} else {
target.text(counter);
}
}, 1000);
}
var p = timer(60);
var c = timer(33)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="timer" id="round">
<div id="circle-timer" class="circle-timer">
<div class="time">
<p class="value">00</p>
</div>
</div>
</div>
<ul>
<li>show first timer</li>
<li>show second timer</li>
</ul>
But is showing all in one time. I want show selected timer (when click show first timer), not all.
Maybe this would help
jsFiddle
$('li').click(function(){
$(".value2").toggle();
$(".value1").toggle();
})
function timer(time,element){
var target = $('p.'+element);
var counter = time;
var id = setInterval(function() {
counter--;
if(counter < 0) {
clearInterval(id);
} else {
target.text(counter);
}
}, 1000);
}
var p = timer(60,'value1');
var c = timer(33,'value2')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="timer" id="round">
<div id="circle-timer" class="circle-timer">
<div class="time">
<p class="value1">00</p>
<p class="value2" style='display:none'>00</p>
</div>
</div>
</div>
<ul>
<li class="value1">show second timer</li>
<li class="value2" style='display:none'>show first timer</li>
</ul>

Javascript accordion - collapse all

I have created a javascript accordion, which works when one accordion is always open, I was wondering how I might modify my code so that the accordion, can also be closed when clicked again - so that all are collapsed?
$('.accordion-bottom').hide();
$('.accordion-link').on('click', global.toggleAccordian);
};
global.toggleAccordian = function(e){
var $Arrow = $(this).find('.arrow');
var $parentDiv = $(this).parent();
var $bottomAccordion = $parentDiv.siblings('.accordion-bottom');
var $accordionLi = $parentDiv.parents().eq('1');
var $siblingLis = $accordionLi.siblings('li');
var $siblingBotAccordions = $siblingLis.find('.accordion-bottom');
var $siblingArrows = $siblingLis.find('.arrow');
$siblingArrows.addClass('arrow-down');
if (!$accordionLi.hasClass('active')){
$bottomAccordion.slideDown('slow');
$Arrow.removeClass('arrow-down');
$siblingBotAccordions.stop().slideUp('slow');
}
e.preventDefault();
return false;
}
html:
<ul class="accordion">
<li>
<div class="item-inner-padding accordion-item">
<div class="accordion-top">
Title<span class="arrow arrow-down">Down</span>
</div>
<div class="accordion-bottom">
</div>
</div>
</li>
</ul>

Categories