This jQuery toggle() function is working great. What is good practice for doing the same in vanilla javascript (ES6 preferred)?
$("#sign_up_btn").click(function(e) {
$(signUpForm).toggle("hide");
$(loginForm).toggle("hide");
});
$("#login_btn").click(function(e) {
$(signUpForm).toggle("hide");
$(loginForm).toggle("hide");
});
Native Toggle
Class can be toggled natively via Element.classList.toggle:
const button = document.querySelector('#sign_up_btn');
button.addEventListener('click', e => {
document.querySelector('.content').classList.toggle('hide')
})
.hide {
display: none;
}
<button id="sign_up_btn">toggle</button>
<div class="content">Toggle this content</div>
You can do something like this:
Note: the CSS is just so we can test here.
document.getElementById('sign_up_btn').addEventListener('click', () => {
var signUpForm = document.getElementById('signUpForm');
var loginForm = document.getElementById('loginForm');
if(window.getComputedStyle(signUpForm).display === "block") {
signUpForm.style.display = "none";
loginForm.style.display = "block";
} else {
signUpForm.style.display = "block";
loginForm.style.display = "none";
}
});
#signUpForm {
position: relative;
float: left;
background-color: #09f;
width: 100px;
height: 100px;
display: block;
margin-right: 20px;
}
#loginForm {
position: relative;
float: left;
background-color: #f00;
width: 100px;
height: 100px;
display: none;
}
#sign_up_btn {
position: relative;
float: left;
margin-right: 20px;
}
<input type="button" id="sign_up_btn" value="Sign up" />
<div id="signUpForm">Sign up form</div>
<div id="loginForm">Log in form</div>
You can do this way.
var show = function (elem) {
elem.style.display = 'block';
};
var hide = function (elem) {
elem.style.display = 'none';
};
var toggle = function (elem) {
// If the element is visible, hide it
if (window.getComputedStyle(elem).display === 'block') {
hide(elem);
return;
}
// Otherwise, show it
show(elem);
};
// Listen for click events
document.addEventListener('click', function (event) {
// Make sure clicked element is our toggle
if (!event.target.classList.contains('toggle')) return;
// Prevent default link behavior
event.preventDefault();
// Get the content
var content = document.querySelector(event.target.hash);
if (!content) return;
// Toggle the content
toggle(content);
}, false);
<p>
<a class="toggle" href="#example">Toggle Div</a>
</p>
<div class="toggle-content" id="example">
Here's some text we want to toggle visibility of. Let's do it!
</div>
If signUpForm and loginForm are ids then you can try the following:
document.getElementById('sign_up_btn').addEventListener('click', function(){
elToggle();
});
document.getElementById('login_btn').addEventListener('click', function(){
elToggle();
});
function elToggle(){
var s = document.getElementById('signUpForm');
if (s.style.display == "none") {
s.style.display = "block";
} else {
s.style.display = "none";
}
var l = document.getElementById('loginForm');
if (l.style.display == "none") {
l.style.display = "block";
} else {
l.style.display = "none";
}
}
Related
I have this script but need to have the class to be changed to "go" or "stop". currently I can turn both to change to the class but it should change to one or the other
Code
var form = document.querySelector("form");
form.addEventListener("click", function(event) {
event.preventDefault();
const classId = event.target.id;
if (classId == "go") {
event.target.className = "go";
} else if (classId == "stop") {
event.target.className = "stop";
}
});
.go {
background: green;
color: white;
}
.stop {
background: red;
color: white;
}
<form action="">
<button id="go">GO!</button>
<button id="stop">STOP!</button>
</form>
You're adding the class to the clicked button, but never removing the class from the other button.
var form = document.querySelector("form");
const goButton = document.querySelector("#go");
const stopButton = document.querySelector("#stop");
form.addEventListener("click", function(event) {
event.preventDefault();
if (event.target == goButton) {
goButton.classList.add("go");
stopButton.classList.remove("stop");
} else if (event.target == stopButton) {
stopButton.classList.add("stop");
goButton.classList.remove("go");
}
});
.go {
background: green;
color: white;
}
.stop {
background: red;
color: white;
}
<form action="">
<button id="go">GO!</button>
<button id="stop">STOP!</button>
</form>
I am trying to replace an image with another image when something is dragged and dropped on it. This is my current code.
What should I add in the document.addEventListener("drop", function(event) to make the image invisible, and replace it with another image when the dragtarget is dropped on it?
/* Events fired on the drag target */
document.addEventListener("dragstart", function(event) {
event.dataTransfer.setData("Text", event.target.id);
document.getElementById("demo").innerHTML = "Started to drag the p element.";
event.target.style.opacity = "0.4";
});
document.addEventListener("drag", function(event) {
document.getElementById("demo").style.color = "red";
});
document.addEventListener("dragend", function(event) {
document.getElementById("demo").innerHTML = "Finished dragging the p element.";
event.target.style.opacity = "1";
});
document.addEventListener("dragenter", function(event) {
if (event.target.className == "droptarget") {
event.target.style.border = "5px dotted red";
}
});
document.addEventListener("dragover", function(event) {
event.preventDefault();
});
document.addEventListener("dragleave", function(event) {
if (event.target.className == "droptarget") {
event.target.style.border = "";
}
});
document.addEventListener("drop", function(event) {
event.preventDefault();
if (event.target.className == "droptarget") {
document.getElementById("demo").style.color = "";
document.getElementByClass("droptarget").style.visibility = 'hidden';
}
});
.dragtarget {
float: left;
width: 100px;
height: 35px;
margin: 15px;
padding: 10px;
border: 1px solid #aaaaaa;
}
.droptarget {
float: left;
width: auto;
height: auto;
margin: 15px;
padding: 10px;
}
<p>Drag and drop the p element on the image:</p>
<div class="dragtarget">
<p draggable="true" id="dragtarget">Drag me!</p>
</div>
<div class="droptarget"><img src="https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/49ec1464-d899-400a-b608-c48c76b500d2/ddlby97-f31bd202-49ef-4391-995a-e08a03e9a0f8.jpg/v1/fit/w_150,h_150,q_70,strp/baby_yoda_by_patrickbrown_ddlby97-150.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9OTAwIiwicGF0aCI6IlwvZlwvNDllYzE0NjQtZDg5OS00MDBhLWI2MDgtYzQ4Yzc2YjUwMGQyXC9kZGxieTk3LWYzMWJkMjAyLTQ5ZWYtNDM5MS05OTVhLWUwOGEwM2U5YTBmOC5qcGciLCJ3aWR0aCI6Ijw9OTAwIn1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmltYWdlLm9wZXJhdGlvbnMiXX0.F2FTXKUhT4EtaU-LcDHGU-e6TKzIADYXo3UIRgrv8jU"></div>
<p id="demo"></p>
This could be one of the many implementations (let's say a very basic one) :-
const mando = new Image(150, 150);
mando.src = 'https://starwarsblog.starwars.com/wp-content/uploads/2019/12/the-mandalorian-announce-tall.jpg';
/* Events fired on the drag target */
document.addEventListener("dragstart", function(event) {
event.dataTransfer.setData("Text", event.target.id);
document.getElementById("demo").innerHTML = "Started to drag the p element.";
event.target.style.opacity = "0.4";
});
document.addEventListener("drag", function(event) {
document.getElementById("demo").style.color = "red";
});
document.addEventListener("dragend", function(event) {
document.getElementById("demo").innerHTML = "Finished dragging the p element.";
event.target.style.opacity = "1";
});
document.addEventListener("dragenter", function(event) {
if (event.target.className == "droptarget") {
event.target.style.border = "5px dotted red";
}
});
document.addEventListener("dragover", function(event) {
event.preventDefault();
});
document.addEventListener("dragleave", function(event) {
if (event.target.className == "droptarget") {
event.target.style.border = "";
}
});
document.addEventListener("drop", function(event) {
event.preventDefault();
const dropTarget = event.target.closest('.droptarget');
if (dropTarget) {
document.querySelector("#demo").style.color = "";
event.target.remove();
dropTarget.append(mando);
}
});
.dragtarget {
float: left;
width: 100px;
height: 35px;
margin: 15px;
padding: 10px;
border: 1px solid #aaaaaa;
}
.droptarget {
float: left;
width: auto;
height: auto;
margin: 15px;
padding: 10px;
}
<p>Drag and drop the p element on the image:</p>
<div class="dragtarget">
<p draggable="true" id="dragtarget">Drag me!</p>
</div>
<div class="droptarget"><img src="https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/49ec1464-d899-400a-b608-c48c76b500d2/ddlby97-f31bd202-49ef-4391-995a-e08a03e9a0f8.jpg/v1/fit/w_150,h_150,q_70,strp/baby_yoda_by_patrickbrown_ddlby97-150.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9OTAwIiwicGF0aCI6IlwvZlwvNDllYzE0NjQtZDg5OS00MDBhLWI2MDgtYzQ4Yzc2YjUwMGQyXC9kZGxieTk3LWYzMWJkMjAyLTQ5ZWYtNDM5MS05OTVhLWUwOGEwM2U5YTBmOC5qcGciLCJ3aWR0aCI6Ijw9OTAwIn1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmltYWdlLm9wZXJhdGlvbnMiXX0.F2FTXKUhT4EtaU-LcDHGU-e6TKzIADYXo3UIRgrv8jU" width='150' height = '150'>
</div>
<p id="demo"></p>
Your event.target is the img element. So I have used the closest() function to get the nearest parent node with class of droptarget and then simply removed the existing image (again event.target) with a preloaded image.
I have a menu that open a sub-menu section onclick (let's name the container: "sub-menu").
I would like "sub-menu" to disapear if the user click outside of it / on the rest of the page.
It seems to be solved on How do I detect a click outside an element?
But I can't get how to use the code snipet from the second most popular answer:
export function hideOnClickOutside(selector) {
const outsideClickListener = (event) => {
const $target = $(event.target);
if (!$target.closest(selector).length && $(selector).is(':visible')) {
$(selector).hide();
removeClickListener();
}
}
const removeClickListener = () => {
document.removeEventListener('click', outsideClickListener)
}
document.addEventListener('click', outsideClickListener)
}
Could you please guide me on how to use it?
I edited, and included a basic example. -> I want sub menu to also close when clicking on the "white" space. But not on the parent "main menu" element.
document.getElementById("main-menu").addEventListener("click", function() {bouttonexpand('sub-menu-class')});
function bouttonexpand(id) {
var elemeacacher = document.getElementsByClassName(id);
if (elemeacacher[0].style.display != "none"){
for(var y=0;y<elemeacacher.length;y++)
elemeacacher[y].style.display = "none";
}
else {
for(var y=0;y<elemeacacher.length;y++)
elemeacacher[y].style.display = "block";
}
}
#main-menu {
display:inline-block;
height:20px;
width:100px;
background: blue;
padding: 5%;
}
#sub-menu {
display:inline-block;
height:50px;
width:50px;
background: red;
display: none;
}
<div><div id="main-menu">Main menu</div></div>
<div><div id="sub-menu" class="sub-menu-class">Sub menu</div></div>
Thanks
By using jQuery, you can bind to the document click event and hides the div container when the clicked element isn’t the container itself or descendant of the div element.
var container = $("#sub-menu");
if (!container.is(event.target) && !container.has(event.target).length) {
container.hide();
}
If you want to hide that container without being tested the container itself or descendant of the div element just remove the condition and simply use container.hide();.
Also, rather than setting display: none; on sub-menu in the CSS, set it manually so that you can toggle the sub-menu from the very first click.
Have a look at the snippet below:
var x = document.getElementById("sub-menu");
x.style.display = "none";
$(document).click(function (evt) {
if ($(evt.target).is('#main-menu')) { // control click event if it's main-menu
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
else {
var container = $("#sub-menu");
if (!container.is(event.target) && !container.has(event.target).length) { // if you don't want that remove the condition and write container.hide(); only
container.hide();
}
}
});
#main-menu {
display: inline-block;
height: 20px;
width: 100px;
background: blue;
padding: 5%;
}
#sub-menu {
display: inline-block;
height: 50px;
width: 50px;
background: red;
}
<script src="https://code.jquery.com/jquery-3.5.1.min.js"
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<div id="main-menu">Main menu</div>
<div id="sub-menu" class="sub-menu-class">Sub menu</div>
I am trying to add to my accordion minus sign to appear after clicking on the row.
I've tried adding minus/plus let and tried to add display.styles for it. But it seems really buggy and not working properly. How can I set this up properly? And it only works for first element instead of all.
const tabs = document.querySelectorAll(".faq__tab").forEach(button => {
button.addEventListener("click", () => {
const tabsContent = button.nextElementSibling;
button.classList.toggle('active-faq');
let minus = document.querySelector(".plus")
let plus = document.querySelector(".minus")
if (button.classList.contains('active-faq')) {
tabsContent.style.maxHeight = tabsContent.scrollHeight + 'px';
plus.style.display = 'none';
minus.style.display = 'flex';
} else {
tabsContent.style.maxHeight = 0;
minus.style.display = 'none';
plus.style.display = 'flex';
}
})
});
.plus {
padding-left: 10px;
}
.minus {
padding-left: 10px;
display: none;
}
.faq__panel {
max-height: 0px;
overflow: hidden;
}
<button class="faq__tab">Question
<img src='img/plus.svg' alt="Show" class="plus">
<img src='img/minus-svg.png' alt="Hide" class="minus">
</button>
<div class="faq__panel">
<p>Answerr
</p>
</div>
You probably need to use inline-flex instead of flex:
const tabs = document.querySelectorAll(".faq__tab").forEach(button => {
button.addEventListener("click", () => {
const tabsContent = button.nextElementSibling;
button.classList.toggle('active-faq');
let minus = button.querySelector(".plus");//instead of document use button to target the corresponding element
let plus = button.querySelector(".minus");//instead of document use button to target the corresponding element
if (button.classList.contains('active-faq')) {
tabsContent.style.maxHeight = tabsContent.scrollHeight + 'px';
minus.style.display = 'none';
plus.style.display = 'inline-flex';
} else {
tabsContent.style.maxHeight = 0;
plus.style.display = 'none';
minus.style.display = 'inline-flex';
}
})
});
.plus {
padding-left: 10px;
}
.minus {
padding-left: 10px;
display: none;
}
.faq__panel {
max-height: 0px;
overflow: hidden;
}
<button class="faq__tab">Question1
<img src='img/plus.svg' alt="Show" class="plus">
<img src='img/minus-svg.png' alt="Hide" class="minus">
</button>
<div class="faq__panel">
<p>Answer1</p>
</div>
<button class="faq__tab">Question2
<img src='img/plus.svg' alt="Show" class="plus">
<img src='img/minus-svg.png' alt="Hide" class="minus">
</button>
<div class="faq__panel">
<p>Answer2</p>
</div>
The problem in that you're setting image display to flex, either give the button faq__tab display: flex in the css file, or set display: inline to images
if (button.classList.contains('active-faq')) {
tabsContent.style.maxHeight = tabsContent.scrollHeight + 'px';
plus.style.display = 'none';
minus.style.display = 'inline';
} else {
tabsContent.style.maxHeight = 0;
minus.style.display = 'none';
plus.style.display = 'inline';
}
When I open my webpage, the navigation bar (located in the footer), is already opened, while it should be hidden. It would show up if you click an icon and will hide again when clicked the same icon again.
The code is working because footer hiden and shows up when clicked on the icon, but the only thing that should be changed is that the footer should be hidden immediately when the webpage is loaded.
var mijnKnop = document.getElementById("toggleMenu");
console.log(mijnKnop);
var mijnMenu = document.getElementById("navigatie");
console.log(mijnMenu);
var toggleStatus = 1;
console.log('status begin:' + toggleStatus);
mijnKnop.addEventListener("click", function() {
console.log('mijnknop click event');
if (toggleStatus == 1) {
console.log('status is 1');
mijnMenu.style.display = "none";
toggleStatus = 0;
} else if (toggleStatus == 0) {
console.log('status is 0');
mijnMenu.style.display = "flex";
toggleStatus = 1;
}
});
footer {
width: 100vw;
height: 8vh;
background-color: #ededed;
position: fixed;
bottom: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
}
ul {
font-size: 1.7rem;
font-family: 'Concert One', cursive;
text-align: center;
}
li {
display: inline-block;
color: #847d7d;
margin: 0 100px 0 100px;
}
a {
text-decoration: none;
color: black;
opacity: 0.5;
}
a:hover {
opacity: 1;
}
<div class="foto"></div>
<div id="toggleMenu"></div>
<footer id="navigatie">
<nav>
<ul>
<li>
Who are we
</li>
<li>
History
</li>
</ul>
</nav>
</footer>
Add
mijnMenu.style.display = "none";
after
var mijnMenu = document.getElementById("navigatie");
and change this
if (toggleStatus == 1) {
console.log('status is 1');
mijnMenu.style.display = "none";
toggleStatus = 0;
}
else if (toggleStatus == 0) {
console.log('status is 0');
mijnMenu.style.display = "flex";
toggleStatus = 1;
}
to this
if (toggleStatus == 1) {
console.log('status is 1');
mijnMenu.style.display = "flex";
toggleStatus = 0;
}
else if (toggleStatus == 0) {
console.log('status is 0');
mijnMenu.style.display = "none";
toggleStatus = 1;
}
You only need to set up the initial value of your footer to "display: none" :
<footer id="navigatie" style="display: none">
If you are talking about a general sense of "webpage getting loaded", then all you need to do is set the display of your footer element to none :-
<footer id="navigate" style="display: none;">
If you meant specifically "page load" i.e the event fired when page is loaded, add the following code to the end of your JavaScript:
addEventListener('load', function() {
document.getElementById('navigate').style.display = 'none';
});
Hope I helped :-)