Targeting a toggle button within an accordion - javascript

I'm trying to target my on/off toggle control which is embedded in a link that also toggles an accordion when you tap on it. Both toggles work, but I want them to work independently of each other. The on/off switch is not supposed to toggle the accordion. I'm using Ratchet as the framework, if that means anything. Here's my JS Fiddle
<li class="table-view-cell toggle-handle accordion">
Kitchen Light
<div class="toggle">
<div class="toggle-handle"></div>
</div>
<!-- toggle -->
</li>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui, officiis asperiores totam. Amet, beatae explicabo placeat consequatur repellendus quia rerum saepe cumque autem facilis! Perferendis, exercitationem eius vitae alias ad.</p>
</div>
li.accordion {
curser: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
li.accordion.active,
button.accordion:hover {
background-color: #ddd;
}
li.accordian:after {
content: '\002B';
color: #777;
font-weight: bold;
float: right;
margin-left: 5px;
}
div.panel {
padding: 0 18px;
background-color: white;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
}
div.toggle {
z-index: 1;
}
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].onclick = function() {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + 'px';
}
}
} //end function

The key piece you are missing is event.stopPropagation(); as this prevents the toggle from also triggering the accordion.
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].getElementsByClassName("toggle")[0].onclick = function() {
event.stopPropagation();
this.classList.toggle("active");
}
acc[i].onclick = function() {
var panel = this.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + 'px';
}
}
} //end function
li.accordion {
/* change the button tag to li tag */
curser: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
li.accordion.active,
button.accordion:hover {
background-color: #ddd;
}
li.accordian:after {
content: '\002B';
color: #777;
font-weight: bold;
float: right;
margin-left: 5px;
}
div.panel {
padding: 0 18px;
background-color: white;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
}
div.toggle {
z-index: 1;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/ratchet/2.0.2/css/ratchet.css" rel="stylesheet"/>
<li class="table-view-cell toggle-handle accordion">
Kitchen Light
<div class="toggle">
<div class="toggle-handle"></div>
</div>
<!-- toggle -->
</li>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui, officiis asperiores totam. Amet, beatae explicabo placeat consequatur repellendus quia rerum saepe cumque autem facilis! Perferendis, exercitationem eius vitae alias ad.</p>
</div>
<!-- end panel -->

I have functional your button
https://jsfiddle.net/Lpppha37/5/
I have updated some html code
<li class="table-view-cell toggle-handle accordion ">
Kitchen Light
<div class="toggle toggle-handle accordion">
<div class="toggle-handle "></div>
</div>
<!-- toggle -->
</li>

Use JavaScript to handle the click event of the target element. That's it really. Just use the .classList toggle method.

Related

Accordion using javscript

I'm trying to create an accordion,it is almost fine but what i cant acheive that everytime when i reload the page the first accordion should be open by default.
second is that im using ajax,after ajax what do i need that the same accordion that i click before the ajax accordion also stay open
Now the first accordion is open what i wanna acheive that when i click the second or any other accordion it should close.
const acc_btns = document.querySelectorAll(".accordion-header");
const acc_contents = document.querySelectorAll(".accordion-body");
acc_btns.forEach((btn) => {
btn.addEventListener("click", (e) => {
acc_contents.forEach((acc) => {
if (
e.target.nextElementSibling !== acc &&
acc.classList.contains("active")
) {
acc.classList.remove("active");
acc_btns.forEach((btn) => btn.classList.remove("active"));
}
});
const panel = btn.nextElementSibling;
panel.classList.toggle("active");
btn.classList.toggle("active");
});
});
window.onclick = (e) => {
if (!e.target.matches(".accordion-header")) {
acc_btns.forEach((btn) => btn.classList.remove("active"));
acc_contents.forEach((acc) => acc.classList.remove("active"));
}
};
.accordion {
width: 450px;
margin: 0 auto;
overflow: hidden;
border-radius: 4px;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
}
.accordion-header {
display: flex;
justify-content: space-between;
padding: 0.75rem 1rem;
width: 100%;
background: #1f8dd6;
border: none;
outline: none;
border-bottom: 1px solid #54a0ff;
color: #f3f3f3;
cursor: pointer;
}
.accordion-header.active {
background-color: #1070b1;
}
.accordion-header.active i {
transform: rotate(180deg);
transition: all 0.3s ease-in-out;
}
.accordion-body {
padding: 0 1rem;
background-color: #f3f3f3;
max-height: 0;
overflow: hidden;
transition: all 0.3s ease-in-out;
}
.accordion-body.active {
max-height: 10rem;
padding: 1rem;
}
.accordion-body.open {
max-height: 10rem;
padding: 1rem;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css" />
<div class="accordion">
<div class="accordion-item">
<button class="accordion-header">
<strong>Accordion 1</strong><i class="fas fa-angle-down"></i>
</button>
<div class="accordion-body open">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Nobis atque, voluptates minima quod quisquam et quasi debitis officia non illo harum iure eos reprehenderit quaerat, veritatis asperiores facilis qui neque.
</div>
</div>
<div class="accordion-item">
<button class="accordion-header">
<strong>Accordion 2</strong><i class="fas fa-angle-down"></i>
</button>
<div class="accordion-body">
Dignissimos perspiciatis amet, qui soluta aliquid, ipsa ea alias quidem officiis vel, inventore quod labore aspernatur exercitationem fugit explicabo rerum dolores quo unde assumenda reprehenderit vero temporibus? Magni, nesciunt vero?
</div>
</div>
<div class="accordion-item">
<button class="accordion-header">
<strong>Accordion 3</strong><i class="fas fa-angle-down"></i>
</button>
<div class="accordion-body">
Amet fuga ipsum velit, quae illo doloremque? Id quidem harum placeat porro ipsam, animi voluptatem vel mollitia, quae rerum suscipit modi at consequatur ipsum vitae cum aspernatur itaque non quam?
</div>
</div>
<div class="accordion-item">
<button class="accordion-header">
<strong>Accordion 4</strong><i class="fas fa-angle-down"></i>
</button>
<div class="accordion-body">
Nihil consectetur ipsum nobis eligendi facilis sed corrupti, ab fugit ducimus dolorem rem nulla excepturi impedit sint ea, eveniet provident quos repudiandae a quas reiciendis aut, incidunt corporis? Laboriosam, labore.
</div>
</div>
</div>
Somehow i ll be able to figure it out.
const accordionItemHeaders = document.querySelectorAll(".accordion-item-header");
accordionItemHeaders.forEach(accordionItemHeader => {
accordionItemHeader.addEventListener("click", event => {
// Uncomment in case you only want to allow for the display of only one collapsed item at a time!
const currentlyActiveAccordionItemHeader = document.querySelector(".accordion-item-header.active");
if(currentlyActiveAccordionItemHeader && currentlyActiveAccordionItemHeader!==accordionItemHeader) {
currentlyActiveAccordionItemHeader.classList.toggle("active");
currentlyActiveAccordionItemHeader.nextElementSibling.style.maxHeight = 0;
}
accordionItemHeader.classList.toggle("active");
const accordionItemBody = accordionItemHeader.nextElementSibling;
if(accordionItemHeader.classList.contains("active")) {
accordionItemBody.style.maxHeight = accordionItemBody.scrollHeight + "px";
}
else {
accordionItemBody.style.maxHeight = 0;
}
});
});
accordionItemHeaders[0].click();
#import url('https://fonts.googleapis.com/css?family=Montserrat');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Montserrat', sans-serif;
background-color: #34495e;
color: #fff;
}
h1 {
text-align: center;
margin: 2rem 0;
font-size: 2.5rem;
}
.accordion {
width: 90%;
max-width: 1000px;
margin: 2rem auto;
}
.accordion-item {
background-color: #fff;
color: #111;
margin: 1rem 0;
border-radius: 0.5rem;
box-shadow: 0 2px 5px 0 rgba(0,0,0,0.25);
}
.accordion-item-header {
padding: 0.5rem 3rem 0.5rem 1rem;
min-height: 3.5rem;
line-height: 1.25rem;
font-weight: bold;
display: flex;
align-items: center;
position: relative;
cursor: pointer;
}
.accordion-item-header::after {
content: "\002B";
font-size: 2rem;
position: absolute;
right: 1rem;
}
.accordion-item-header.active::after {
content: "\2212";
}
.accordion-item-body {
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
}
.accordion-item-body-content {
padding: 1rem;
line-height: 1.5rem;
border-top: 1px solid;
border-image: linear-gradient(to right, transparent, #34495e, transparent) 1;
}
#media(max-width:767px) {
html {
font-size: 14px;
}
}
<h1>FAQ</h1>
<div class="accordion">
<div class="accordion-item">
<div class="accordion-item-header">
What is Web Development?
</div>
<div class="accordion-item-body">
<div class="accordion-item-body-content">
Web Development broadly refers to the tasks associated with developing functional websites and applications for the Internet. The web development process includes web design, web content development, client-side/server-side scripting and network security configuration, among other tasks.
</div>
</div>
</div>
<div class="accordion-item">
<div class="accordion-item-header">
What is HTML?
</div>
<div class="accordion-item-body">
<div class="accordion-item-body-content">
HTML, aka HyperText Markup Language, is the dominant markup language for creating websites and anything that can be viewed in a web browser.
</div>
</div>
</div>
<div class="accordion-item">
<div class="accordion-item-header">
What are some basic technical skills of a Front-End developer?
</div>
<div class="accordion-item-body">
<div class="accordion-item-body-content">
<ul style="padding-left: 1rem;">
<li>HTML, CSS, JavaScript</li>
<li>Frameworks (CSS and JavaScript frameworks)</li>
<li>Responsive Design</li>
<li>Version Control/Git</li>
<li>Testing/Debugging</li>
<li>Browser Developer Tools</li>
<li>Web Performance</li>
<li>SEO (Search Engine Optimization)</li>
<!-- <li>CSS Preprocessing</li> -->
<li>Command Line</li>
<li>CMS (Content Management System)</li>
</ul>
</div>
</div>
</div>
<div class="accordion-item">
<div class="accordion-item-header">
What is HTTP?
</div>
<div class="accordion-item-body">
<div class="accordion-item-body-content">
HTTP, aka HyperText Transfer Protocol, is the underlying protocol used by the World Wide Web and this protocol defines how messages are formatted and transmitted, and what actions Web servers and browsers should take in response to various commands.
</div>
</div>
</div>
<div class="accordion-item">
<div class="accordion-item-header">
What is CORS?
</div>
<div class="accordion-item-body">
<div class="accordion-item-body-content">
CORS, aka Cross-Origin Resource Sharing, is a mechanism that enables many resources (e.g. images, stylesheets, scripts, fonts) on a web page to be requested from another domain outside the domain from which the resource originated.
</div>
</div>
</div>
</div>

hide open/active accordion when another accordion is clicked

I suspect the issue is with the line const active = document.querySelector(".accordion.active"); in JS code below. It doesn't seem to be retrieving that element. Could you please help me debug it? Or should I use something else instead of querySelector? It is also found that this.classList.add("active"); is not adding the "active class" to the accordion element when it is clicked.
document.addEventListener("DOMContentLoaded", function(event) {
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
const active = document.querySelector(".accordion.active");
console.log(active);
if (active) {
active.classList.remove('active'); // remove active class from accordions
}
this.classList.add("active"); // add it to this one
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
});
}
});
.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 1.5rem;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
.active,
.accordion:hover {
background-color: #ccc;
}
.panel {
padding: 0 18px;
display: none;
background-color: white;
overflow: hidden;
background: red;
}
.active+.panel {
display: block;
}
<div class="row">
<button class="accordion"><div class="question"><?php echo $label; ?></div></button>
<div class="panel">
<p class="answer">
<?php echo $answer; ?>
</p>
</br>
</div>
</div>
<div class="row">
<button class="accordion"><div class="question"><?php echo $label; ?></div></button>
<div class="panel">
<p class="answer">
<?php echo $answer; ?>
</p>
</br>
</div>
</div>
You probably should re-think your approach since in your case, you will not even be in need of JavaScript - for the basics! If you need a custom accordion, then you can use JavaScript, and I try to explain to you how.
What you need is a clean HTML with <details> and <summary>. See this example:
<details class="accordion">
<summary>Question 1</summary>
<strong>Answer:</strong> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus molestias ex, rem ducimus quibusdam nihil aliquam corporis id sint aperiam dolores, accusantium culpa adipisci similique doloremque eius reiciendis. Veniam, perferendis.
</details>
<details class="accordion">
<summary>Question 2</summary>
<strong>Answer:</strong> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laborum doloribus tenetur tempore esse consectetur incidunt, distinctio eaque suscipit error fugit tempora, quas accusantium recusandae autem voluptatibus qui quasi molestiae odit.
</details>
With CSS you can style it the way you want it. If you want to remove the arrows, you can try it with details > summary { list-style: none; }. Also, you can use any other characters. In this example, we use the signs + (plus) and when the accordion is already opened, it should be - (minus.):
details > summary {
list-style-type: '+ ';
}
details[open] > summary {
list-style-type: "- ";
}
details > summary::-webkit-details-marker {
display: none;
}
summary {
background-color: #ccc;
}
<details class="accordion">
<summary>Question 1</summary>
<strong>Answer:</strong> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus molestias ex, rem ducimus quibusdam nihil aliquam corporis id sint aperiam dolores, accusantium culpa adipisci similique doloremque eius reiciendis. Veniam, perferendis.
</details>
<details class="accordion">
<summary>Question 2</summary>
<strong>Answer:</strong> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laborum doloribus tenetur tempore esse consectetur incidunt, distinctio eaque suscipit error fugit tempora, quas accusantium recusandae autem voluptatibus qui quasi molestiae odit.
</details>
As you can see, all open questions remain open. If you want only the active question to stay open, you may use JavaScript.
document.querySelectorAll('details').forEach((accordion) => {
accordion.addEventListener('click', (e) => {
document.querySelectorAll('details').forEach((event) => {
if (accordion !== event) {
event.removeAttribute('open');
}
});
});
});
details > summary {
list-style-type: '+ ';
}
details[open] > summary {
list-style-type: "- ";
}
details > summary::-webkit-details-marker {
display: none;
}
summary {
background-color: #ccc;
}
<details class="accordion">
<summary>Question 1</summary>
<strong>Answer:</strong> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus molestias ex, rem ducimus quibusdam nihil aliquam corporis id sint aperiam dolores, accusantium culpa adipisci similique doloremque eius reiciendis. Veniam, perferendis.
</details>
<details class="accordion">
<summary>Question 2</summary>
<strong>Answer:</strong> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laborum doloribus tenetur tempore esse consectetur incidunt, distinctio eaque suscipit error fugit tempora, quas accusantium recusandae autem voluptatibus qui quasi molestiae odit.
</details>
You don't need to manipulate the display of the active element, your CSS already does that. Also you should not both add and toggle the active class on this - that is equivalent to removing it.
I've also added an if statement to check if the clicked element is already active so that collapsing it again works.
document.addEventListener("DOMContentLoaded", function(event) {
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
const active = document.querySelector(".accordion.active");
console.log(active);
if (active) {
active.classList.remove('active'); // remove active class from accordions
}
if (active !== this) {
this.classList.toggle("active");
}
});
}
});
.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 1.5rem;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
.active,
.accordion:hover {
background-color: #ccc;
}
.panel {
padding: 0 18px;
display: none;
background-color: white;
overflow: hidden;
background: red;
}
.active+.panel {
display: block;
}
<div class="row">
<button class="accordion"><div class="question">Label1</div></button>
<div class="panel">
<p class="answer">
Answer goes here
</p>
</div>
</div>
<div class="row">
<button class="accordion"><div class="question">Label2</div></button>
<div class="panel">
<p class="answer">
Second answer
</p>
</div>
</div>
//
this.classList.add("active"); is not adding the "active class" to the accordion element when it is clicked.
//
It is adding. But immediately the class is toggled, so it is removed. That toogle class line is commented.
I have added the css for green color to active accordion, which you can see after moving the cursor off the accordion element.
document.addEventListener("DOMContentLoaded", function(event) {
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
const active = document.querySelector(".accordion.active");
console.log(active);
if (active) {
active.classList.remove('active'); // remove active class from accordions
// this is if other heading is clicked
}
// this.classList.toggle("active"); // not needed
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
this.classList.remove("active"); // remove it to this one
panel.style.display = "none";
} else {
this.classList.add("active"); // add it to this one
panel.style.display = "block";
}
});
}
});
.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 1.5rem;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
.accordion.active{
background:green;
}
.active,
.accordion:hover {
background-color: #ccc;
}
.panel {
padding: 0 18px;
display: none;
background-color: white;
overflow: hidden;
background: red;
}
.active+.panel {
display: block;
}
<div class="row">
<button class="accordion"><div class="question">Accordion Label 1</div></button>
<div class="panel">
<p class="answer">
Accordion Answer 1
</p>
</br>
</div>
</div>
<div class="row">
<button class="accordion"><div class="question">Accordion Label 2</div></button>
<div class="panel">
<p class="answer">
Accordion Answer 1
</p>
</br>
</div>
</div>
I always prefer delegation.
I am wrapping the accordion in a DIV and delegate the clicks from there
No need to show / hide the panes since the CSS .active+.panel { display: block; } does that for us
document.addEventListener("DOMContentLoaded", function(event) { // when page has loaded
const acc = document.getElementById("accodionContainer"); // the container
const buttons = acc.querySelectorAll(".accordion"); // the buttons in the container
acc.addEventListener("click", e => { // any click in the container
const currentButton = e.target.closest(".accordion"); // you have stuff inside the relevant element, make sure we use the .accordion element
if (!currentButton) return // something not a (in a ) button was clicked
// toggle clicked button, remove active from the rest
buttons.forEach(acc => acc.classList[acc === currentButton ? "toggle" : "remove"]("active"));
});
});
.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 1.5rem;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
.active,
.accordion:hover {
background-color: #ccc;
}
.panel {
padding: 0 18px;
display: none;
background-color: white;
overflow: hidden;
}
.active+.panel {
display: block;
}
.accordion.active span::after {
content: "➖";
}
.accordion span::after {
content: "➕";
}
<div id="accodionContainer">
<div class="row">
<button class="accordion"><span></span> Question 1</button>
<div class="panel">
<p class="answer">
Answer 1
</p>
</div>
</div>
<div class="row">
<button class="accordion"><span></span> Question 2</button>
<div class="panel">
<p class="answer">
Answer 2
</p>
</div>
</div>
</div>
The below answer is not related to the question, but it is good to have the html hierarchy.
const accordionToggles = document.querySelectorAll('.accordion-toggle');
const accordionItems = document.querySelectorAll('.accordion-item');
const flush = true; // set to true,if only one accordion bodyto be open. set false, to open multiple accordion-body
accordionToggles.forEach((toggleBtn) => {
toggleBtn.addEventListener('click', (event) => {
const accordionItem = event.target.closest(".accordion-item");
if (!flush) {
accordionItem.classList.toggle('active');
return;
}
if (accordionItem.classList.contains('active')) {
accordionItem.classList.toggle('active');
return;
}
accordionItems.forEach((item) => {
item.classList.remove('active');
})
accordionItem.classList.add('active');
})
});
.accordion {}
.accordion-item {
border: 1px solid gray;
}
.accordion-item+.accordion-item {
border-top: none;
}
.accordion-header {}
.accordion-toggle {
width: 100%;
border: none;
height: 30px;
border-bottom: 1px solid black;
text-align: left;
position: relative;
}
.accordion-toggle:after {
position: absolute;
top: 5px;
right: 5px;
font-size: 18px;
}
.accordion-body {
padding: 10px;
display: none;
}
.accordion-item.active .accordion-body {
display: block;
}
.accordion-item .accordion-toggle:after {
content: "+"
}
.accordion-item.active .accordion-toggle:after {
content: "-"
}
<div class="accordion">
<div class="accordion-item">
<div class="accordion-header">
<button class="accordion-toggle">Title 1</button>
</div>
<div class="accordion-body">
Accordion Content 1
</div>
</div>
<div class="accordion-item">
<div class="accordion-header">
<button class="accordion-toggle">Title 2</button>
</div>
<div class="accordion-body">
Accordion Content 2
</div>
</div>
</div>

How to blur background of webpage and make it not interactable in certain areas?

I'm basically trying to implement a popup that blurs the background and makes it so that the user can't touch the buttons and other components in the background.
You can disable the whole div by using css.
#div-id{
pointer-events: none;
}
This will disable all the elements inside the div.
If you want the blur effect you can add opacity: 0.2; to the div css.
You can add this class on your main element container to blur the whole background
.blured {
filter: blur(2px);
-webkit-filter: blur(2px);
}
And add pointer-events: none; on your modal or popup
By using css backdrop-filter property and pointer-events you can achieve what u need .. see example below
* {
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
font-size: 1rem;
}
body {
margin: 0;
padding: 0;
}
.disabled{
pointer-events: none;
color : grey;
}
.modal {
position: fixed;
inset: 0;
isolation: isolate;
background-color: rgba(19, 128, 119, 0.5);
display: flex;
align-items: center;
justify-content: center;
}
.popup {
position: absolute;
z-index: 1;
width: 400px;
background-color: black;
color: white;
padding: 1rem;
}
.blur{
position: absolute;
inset: 0;
z-index: -1;
backdrop-filter: blur(0.2rem);
}
<div class="text">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquid dolorum illo, non incidunt earum natus neque architecto a autem maxime voluptatibus tempora minima, provident expedita quidem cumque ab. Error, tenetur?
</div>
<div class="modal">
<div class="blur"></div>
<div class="popup">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Animi quam architecto minima nihil aliquid quis unde
illo mollitia iure. Quia.
<br /> <br /> <br />
<a href="#" class="disabled">
I am a disabled link !
</a>
</div>
</div>
References : pointer-events and backdrop-filter.
Note: Also remember using pointer events doesn't means you can't use keyboard to focus.. To prevent keyboard tab focus you might need to use tabindex attribute on the link
body{
position:relative;
///rest of your style
}
.backdrop {//create a div inside body // <div class".backdrop"></div>
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
z-index: 1;
backdrop-filter: blur(5px);
}
.backdrop:enabled { //here we have disable all pevnts
pointer-events: none;
}

Unable to insert element before and after (both) in jQuery

I am using jQuery 3.x. I am trying to append a dynamically created element before and after an element using insertBefore() and insertAfter(). However, only insertBefore() is working, and another one is ignored. When I am commenting one then other is working. why?
p = $("<p></p>").text("This is a dynamicly created element");
p.insertAfter($('nav'));
p.insertBefore($('nav'));
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-size: 20px;
}
header,
nav,
main,
aside,
footer {
padding: 10px 15px;
border: 1px solid mediumseagreen;
text-align: center;
}
header {
background: dodgerBlue;
}
nav {
background: mediumSeaGreen;
}
main {
background: #d3d3d3;
}
main,
aside {
height: 1200px;
}
main {
width: 80%;
float: left;
}
aside {
width: 20%;
float: right;
}
div::after {
content: " ";
float: none;
clear: both;
display: table;
}
main {
text-align: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>
This is header
</header>
<nav>
This is navbar
</nav>
<main>
<article>
<h2>This is heading</h2>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Cum atque fuga, eos neque ipsum enim id inventore necessitatibus laboriosam quo nobis, repellendus maxime veritatis error ut expedita, velit aspernatur asperiores!
</p>
</article>
</main>
<aside>
This is side bar
</aside>
<div></div>
<footer>
This is footer
</footer>
The issue is because the p references only a single element. You insert it in to the DOM in the insertAfter() call, then move the same element to a new location using insertBefore().
To do what you require you can clone() the element before the second insertion. Also note that you don't need to create an entire jQuery object to select nav, you can just pass the selector as a string. Try this:
let p = $("<p />", {
text: "This is a dynamicly created element"
});
p.insertAfter('nav');
p.clone().insertBefore('nav');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-size: 20px;
}
header,
nav,
main,
aside,
footer {
padding: 10px 15px;
border: 1px solid mediumseagreen;
text-align: center;
}
header {
background: dodgerBlue;
}
nav {
background: mediumSeaGreen;
}
main {
background: #d3d3d3;
}
main,
aside {
height: 1200px;
}
main {
width: 80%;
float: left;
}
aside {
width: 20%;
float: right;
}
div::after {
content: " ";
float: none;
clear: both;
display: table;
}
main {
text-align: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>This is header</header>
<nav>This is navbar</nav>
<main>
<article>
<h2>This is heading</h2>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Cum atque fuga, eos neque ipsum enim id inventore necessitatibus laboriosam quo nobis, repellendus maxime veritatis error ut expedita, velit aspernatur asperiores!
</p>
</article>
</main>
<aside>This is side bar</aside>
<div></div>
<footer>This is footer</footer>
One other thing to mention, I would suggest researching flexbox layouts. They're a much more modern and extensible technique than forcing display: table on a div to create a multi-column layout.

How to make a slide(up/down) without jQuery?

I am trying to make a slide(up/down) system for my collapse components (like bootstrap) but I can't get the height of the elements to animate(without height there is no possible way to animate the element I think so- if this is wrong, then how can I animate the element?)!
NOTE: [I want to use pure javascript]
document.getElementById('btn').addEventListener('click', function(){
this.nextElementSibling.classList.toggle('active');
})
body{
font-family: Segoe UI;
font-size: 1rem;
line-height: 1.5;
}
.collapse{
border: 1px solid #e7e7e7;
border-radius: .25rem;
overflow: hidden;
}
#btn{
padding: .75rem 1.25rem;
width: 100%;
border: none;
font-size: inherit;
background-color: #fff;
cursor: pointer;
}
#btn:focus{
outline: 0;
}
.collapse-content{
font-size: 95%;
padding: .75rem .75rem;
display: none;
}
.collapse-content.active{
display: block;
}
<div class="collapse">
<button id="btn"> Click Me </button>
<div class="collapse-content">
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Mollitia ut explicabo nesciunt minima pariatur saepe eveniet officia ducimus perferendis suscipit?
</div>
</div>
Bare-bones vanilla javascript implementation that'll account for any internal height (with consistent transition speed) can be achieved with some minor changes to the markup.
<div class="collapse">
<button id="btn"> Click Me </button>
<div class="collapse-wrapper">
<div class="collapse-content">
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Mollitia ut explicabo nesciunt minima pariatur saepe eveniet officia ducimus perferendis suscipit?
</div>
</div>
</div>
Note the addition of the collapse-wrapper div. This'll allow you to render the content and measure its height without actually displaying the content. Then it's just a simple case of showing/hiding the content on click:
* {
box-sizing: border-box;
}
.collapse-wrapper {
overflow: hidden;
transition: all 300ms ease-in;
}
const wrapper = document.querySelector('.collapse-wrapper')
const content = document.querySelector('.collapse-content')
const button = document.getElementById('btn')
let open = true
// Set initial height to content height, if shown by default
if (open) {
wrapper.style.height = `${content.getBoundingClientRect().height}px`
}
function toggleOpen () {
if (open) {
wrapper.style.height = '0px'
open = false
} else {
const height = content.getBoundingClientRect().height
wrapper.style.height = `${height}px`;
open = true
}
}
button.addEventListener('click', toggleOpen)
Here's a fiddle
You need to use max-height. Yes, it's nasty, since it means you need to set some arbitrary max height that may need to be adjusted later if the content grows. However, you cannot animate height in this situation because the height is not defined before the content opens.
Something like:
.collapse-content{
font-size: 95%;
padding: .75rem .75rem;
max-height: 0;
transition: max-height .3s;
}
.collapse-content.active{
max-height: 200px; //something bigger than what you need
}
function slide(){
document.getElementById("sliding").style.maxHeight = "1000px";
}
#sliding{
transition: 0.5s;
max-height: 0px;
overflow: hidden;
}
<button onclick ="slide();">Slide it</button>
<div id = "sliding">
<h1>It works</h1>
<p>Hello there</p>
</div>
This is sort of hacky because you have to set maxHeight to the largest you think your content will get.
Source: How can I transition height: 0; to height: auto; using CSS?

Categories