Changing display after animation - javascript

I'm trying to change an element's display to none after a CSS transition. This is because I want elements below the removed to move up (or down) to take the removed element's place. The transition is working, but it doesn't change the display.
.glossary-item {
margin: 20px 0;
padding: 20px;
box-sizing: border-box;
border: 1px solid;
opacity: 1;
}
.hidden {
display: none;
}
.transition.hidden {
display: block;
opacity: 0;
}
.transition {
transition: opacity 1s ease;
}
<input type="text" id="glossaryFilter" onkeyup="myFunction()" placeholder="Search..">
<div id="glossary-container">
<div class="glossary-item">
<div class="glossary-body">
<h5 class="glossary-title">Title</h5>
<p>Content</p>
</div>
</div>
<div class="glossary-item">
<div class="glossary-body">
<h5 class="glossary-title">Other</h5>
<p>Stuff</p>
</div>
</div>
</div>
function myFunction() {
var input, filter, cards, cardContainer, h5, title, i;
input = document.getElementById("glossaryFilter");
filter = input.value.toUpperCase();
cardContainer = document.getElementById("glossary-container");
cards = cardContainer.getElementsByClassName("glossary-item");
for (i = 0; i < cards.length; i++) {
title = cards[i].querySelector(".glossary-body h5.glossary-title");
if (title.innerText.toUpperCase().indexOf(filter) > -1) {
cards[i].classList.add('transition');
cards[i].classList.remove('hidden');
} else {
cards[i].classList.add('transition');
cards[i].classList.add('hidden');
}
}
}

the class:
displayNone{
display: none;
}
some js:
const afterAnimate = (()=>{
setTimeout(()=>{
//change "elem" to the fitting element
elem.classList.add("displayNone");
}, 1000);
})
//add the function-call to your event which triggers the animation
afterAnimate();

Related

Show/hide div in JS

I'm pretty fresh to JS.
For n amount of bar divs I have n amount foo divs. By clicking on bar[1], I want foo[1] to show or hide. The same goes for bar[2]/foo[2], bar[5]/foo[5], bar[3]/foo[3],...bar[n]/foo[n] in no exact order.
With this code I am able to show and hide, but only all of the divs at the same time. What should I change, so that I am able to hide or show only one of the divs?
function getContent() {
var x = document.getElementsByClassName("foo");
for (var i = 0; i < x.length; i++) {
if (x[i].style.display === "none") {
x[i].style.display = "block";
} else {
x[i].style.display = "none";
}
}
}
document.querySelector(".bar").addEventListener("click", getContent);
.foo {
display: none;
}
.bar {
padding: 5px;
display: block;
}
<div>
<div class="bar" onclick="getContent()">bar</div>
</div>
<div class="foo">foo</div>
No need to use JS here, HTML is more powerful than you think: if you want to show-or-hide information, the <details> element's got you covered.
.all-or-nothing summary {
display: inline-block;
cursor: pointer;
}
<details class="all-or-nothing">
<summary>Toggle all divs</summary>
<div>
The first div
</div>
<div>
The second div
</div>
<div>
The third div
</div>
</details>
Use a variable to hold the index of the current DIV to show, rather than looping over all the DIVs.
let fooIndex = 0;
let allFoo = document.querySelectorAll(".foo");
function getContent() {
if (fooIndex < allFoo.length) {
allFoo[fooIndex].classList.toggle("foo");
allFoo[fooIndex].classList.toggle("bar");
fooIndex++;
}
}
document.querySelector(".bar").addEventListener("click", getContent);
.foo {
display: none;
}
.bar {
padding: 5px;
display: block;
}
<div>
<div class="bar">bar</div>
</div>
<div class="foo">foo1</div>
<div class="foo">foo2</div>
<div class="foo">foo3</div>
<div class="foo">foo4</div>
//let fooIndex = 0;
function getContent() {
var x = $(".card");
x.append('<div class="foo" onclick="hideContent(this)">foo1</div>');
//$(this).addClass('bar');
}
function hideContent(a) {
$(a).removeClass('foo');
$(a).addClass('bar');
}
.foo {
display: none;
}
.bar {
padding: 5px;
display: block;
}
<div class="card">
<div onclick="getContent();" class="bar">bar</div>
</div>

How to unclick other button using 1 button

I have 15 buttons, each button has content, but when I clicked button1 and followed by button 2, the button 1 is still open. How can I close the button 1 if I click button2?
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].onclick = function() {
this.classList.toggle("active");
this.nextElementSibling.classList.toggle("show");
}
}
div.panel {
position: absolute;
max-width: 0;
overflow: hidden;
opacity: 0;
}
div.panel.show {
opacity: 1;
max-width: 900px;
}
<button class="accordion">The Ball</button>
<div class="panel">
<h1>The Ball</h1>
</div>
<button class="accordion">The Cat</button>
<div class="panel">
<h1>The Cat</h1>
</div>
<button class="accordion">The Dog</button>
<div class="panel">
<h1>The Dog</h1>
</div>
You need to remove active and show classes from previous div before adding them to clicked div.
Your JS Code will be:
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].onclick = function() {
var previous = document.querySelector(".active"); //select previous button
if (previous) { // check because when first time no button has active class
previous.classList.remove("active");
previous.nextElementSibling.classList.remove("show");
}
this.classList.add("active");
this.nextElementSibling.classList.add("show");
};
}
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].onclick = function() {
var previous = document.querySelector(".active");
if (previous) {
previous.classList.remove("active");
previous.nextElementSibling.classList.remove("show");
}
this.classList.add("active");
this.nextElementSibling.classList.add("show");
};
}
div.panel {
position: absolute;
max-width: 0;
overflow: hidden;
opacity: 0;
}
div.panel.show {
opacity: 1;
max-width: 900px;
}
<button class="accordion">The Ball</button>
<div class="panel">
<h1>The Ball</h1>
</div>
<button class="accordion">The dog</button>
<div class="panel">
<h1>The dog</h1>
</div>
<button class="accordion">The cat</button>
<div class="panel">
<h1>The cat</h1>
</div>
So select the active one. If it is active remove it. If the current one is not the active class add it.
// select all the buttons
var btns = document.querySelectorAll('.accordion')
// loop over
btns.forEach(function (btn) {
// bind the click
btn.addEventListener('click', function (evt) {
// stop button click
evt.preventDefault()
// find the active one
var active = document.querySelector('.accordion.active')
// see if active button is the clicked button
var isSame = active == btn
// if we have an active button, remove the class
if (active) active.classList.remove('active')
// if the current button was not the active one add the class
if (!isSame) btn.classList.add('active')
})
})
button {
display: block;
}
button + div {
max-height: 0;
transition: max-height 0.25s ease-out;
overflow: hidden;
}
button.active {
background-color: green;
}
button.active + div {
max-height: 500px;
transition: max-height 0.5s ease-in;
}
<button class="accordion">The Ball 1</button>
<div><p>Ball 1</p><p>bounce bounce poounce</p></div>
<button class="accordion">The Ball 2</button>
<div><p>Ball 2</p><p> bounce pop</p></div>
<button class="accordion">The Ball 3</button>
<div><p>Ball 3</p><p>bounce bounce over the fence</p></div>
An alternative using JQuery.
I have changed the CSS to remove max-width and opacity and have set .panel elements to be display: none; initially:
div.panel {
position: absolute;
display: none;
}
And using JQuery, whenever we click an .accordion element, we hide the .panel elements (in case any others are showing), and then show the one that relates to the specifically clicked .accordion element.
// register clicks on accordion elements
$('.accordion').click(function() {
// hide each .panel related to every .accordion element
$('.accordion').next().hide();
// show the .panel next to our clicked .accordion element
$(this).next().show();
})

How to Output chosen DIV elements that are stored in an array

I'm creating a card game where the user chooses 2 out of 3 cards. I then store those cards into an array and want to be able to print out the cards that were stored in the array with the actual image of the cards that the user chose.
I've tried looping through the array and then using innerHTML to push the results to a specific div but I keep getting "[object HTMLDivElement]". It also prints that out 3 times instead of 2 (since we are choosing 2 cards there should only be two elements to print out, I suspect the loop is running an extra time).
The below is the loop I have tried but I also am including a codepen for further clarity.
https://codepen.io/cramos2/pen/pMVjez
var holder = document.getElementById("cardResults");
for(var i=0; i < chosenCards.length; i++){
holder.innerHTML += "<p>" + chosenCards[i] + "</p><br>";
}
let chosenCards = new Array();
class tarot {
//constructor
constructor(cards) {
this.cardsArray = cards;
}
startReading() {
this.shuffleCards(this.cardsArray);
//call shuffle method
}
//Adds class "flipped" to the cards
flipCard(card, cards) {
if (this.canFlipCard(card)) {
if (chosenCards.length >= 2) {
console.log("removing1");
//from here
for (let card0 in cards) {
let list = card0.classList;
if (list) {
if (!list.contains('visible')) {
card0.removeEventListener('click', card0.fn);
}
}
}
} //to here
else if (!card.classList.contains('visible')) {
debugger;
card.classList.add('visible');
chosenCards.push(card);
console.log(chosenCards);
//this is where print out
var holder = document.getElementById("cardResults");
for (var i = 0; i < chosenCards.length; i++) {
holder.innerHTML += "<p>" + chosenCards[i] + "</p><br>";
}
card.removeEventListener('click', card.fn);
}
}
}
//Need a Shuffle method in here
shuffleCards(cardsArray) {
for (let i = cardsArray.length - 1; i > 0; i--) {
const randIndex = Math.floor(Math.random() * (i + 1));
[cardsArray[i], cardsArray[randIndex]] = [cardsArray[randIndex], cardsArray[i]];
}
cardsArray = cardsArray.map((card, index) => {
card.style.order = index;
});
}
//gets the card
getCardType(card) {
return card.getElementsByClassName('card-value')[0].src;
}
//returns card
canFlipCard(card) {
return card
}
}
//this will call the reading to start when page is loaded
if (document.readyState == 'loading') {
document.addEventListener('DOMContentLoaded', ready)
} else {
ready()
}
function ready() {
//declares card's' & sets it to the card class in HTML
let cards = Array.from(document.getElementsByClassName('card'));
//creates new instance of tarot class
let tarotReading = new tarot(cards);
let over = Array.from(document.getElementsByClassName('over'));
over.forEach(overlay => {
overlay.addEventListener('click', () => {
overlay.classList.remove('visible');
tarotReading.startReading();
});
});
//flips the cards
cards.forEach(card => {
card.addEventListener('click', card.fn = function clicked() {
tarotReading.flipCard(card, cards);
//remove cards that dont have visible tag
});
})
console.log(chosenCards[0]);
}
h1 {
color: #7B68EE;
padding left: 50px;
padding right: 50px;
padding-top: 5px;
text-align: center;
}
.container {
display: grid;
grid-template-columns: repeat(6, auto);
grid-gap: 10px;
margin: 50px;
justify-content: center;
perspective: 500px;
}
.card {
position: relative;
height: 175px;
width: 125px;
}
.card-face {
position: absolute;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
backface-visibility: hidden;
border-radius: 12px;
border-width: 1px;
border-style: solid;
transition: transform 500ms ease-in-out;
}
.card.visible .card-back {
transform: rotateY(-180deg);
}
.card.visible .card-front {
transform: rotateY(0)
}
.card-back {
background-color: black;
border-color: white;
color: white;
}
.card-front {
background-color: black;
border-color: white;
color: white;
transform: rotateY(180deg);
}
<body>
<h1>Tarot</h1>
<div class="container">
<div class="card">
<div class="card-back card-face card1" id="card1">
<p> 1
<p>
</div>
<div class="card-front card-face">
<p> The Hermit
<p>
</div>
</div>
<div class="card">
<div class="card-back card-face card2">
2
</div>
<div class="card-front card-face">
The Fool
</div>
</div>
<div class="card">
<div class="card-back card-face card3">
3
</div>
<div class="card-front card-face">
The Empress
</div>
</div>
</div>
<button type="button" class="over container">Shuffle</button>
</div>
<hr>
<div id="cardResults">
</div>
</body>
The expected result would be the flipped over card with the text (not the number of the card) that the user has chosen.
You could try something like this:
for(var i=0; i < chosenCards.length; i++){
holder.appendChild(chosenCards[i].cloneNode(true));
}

Style is being added to the last child among a set of elements, instead of the last child of the selected element

var NavLinks = document.querySelectorAll('.nav-link');
var circuses = document.querySelectorAll('.circle');
for (var i = 0; i < NavLinks.length; i++) {
var navLink = NavLinks[i];
navLink.addEventListener('click', function () {
for (var i = 0; i < circuses.length; i++) {
var circle = circuses[i];
circle.style.display='none';
}
var theLastChild = navLink.lastChild;
theLastChild.style.display='block';
}
);
}
.nav-container{
height: 10px;
background: white;
padding: 30px 0px 40px 0px;
margin-left: 18%;
margin-right: 18%;
}
.nav-body ul{
text-align: right;
}
.nav-body ul li{
display: inline- block;
float: left;
margin-right: 30px;
}
#logo{
margin-right: 0px;
}
.nav-body ul li{
line-height: 0.6;
}
#logo{
margin-top: -10px;
}
#logo-light-blue{
color: #5dc5ef;
font-weight: 900;
}
#logo-dark-blue{
color: #1885c8;
font-weight: 900;
}
.circle {
display: none;
width: 8px;
height: 8px;
background: #5dc5ef;
/* -moz-border-radius: 50px;
-webkit-border-radius: 50px; */
border-radius: 4px;
margin: auto;
margin-top: 7px;
}
<header class="nav-container">
<nav class="nav-body">
<ul>
<li class="nav-link">צור קשר
<div class="circle"></div></li>
<li class="nav-link">המלצות ומאמרים
<div class="circle"></div></li>
<li class="nav-link">שאלות נפוצות
<div class="circle"></div></li>
<li class="nav-link">אודות ד"ר שי מרון אלדר
<div class="circle"></div></li>
<li class="nav-link">אודות ההליכים
<div class="circle"></div></li>
<li class="nav-link">ראשי
<div class="circle"></div></li>
<li id="logo"> <h3> <span id="logo-light-blue"> ד"ר </span><span id="logo-dark-blue"> שי מרון אלדר </span></h3><br>
<h6> פתרונות כירורגיים להשמנת יתר וניתוחים זעיר פולשניים</h6></li>
</ul>
</nav>
</header>
I need to make a blue circle under that category menu, which I pressed. But now blue circle added only to last menu category. Doesn't matter which one was pressed.
I looking for the last child of that menu category which was pressed. But it shows me every time last child of all menu categories.
What is wrong?
>
You have errors in HTML. Span tags need to be closed.
<li id="logo">
<h3>
<span id="logo-light-blue"> ד"ר </span>
<span id="logo-dark-blue"> שי מרון אלדר </span>
</h3>
<br>
<h6> פתרונות כירורגיים להשמנת יתר וניתוחים זעיר פולשניים</h6>
</li>
And Id attributes should be unique to the element, you are repeating the circle as an Id all over the place.
<div id="circle"></div></li>
It this doesn't solve it, try explaining the question better since even in the demo you have put result is all over the place. Are we missing some CSS or a style lib?
EDIT: I think I know what you wanna, is it this? Have a look at fiddle:
fiddle here
Do you need circle removed from other elements once you click your element?
If you need the circle to be only on 1 element, it needs to be removed from others.
Here is a fiddle showing that:
fiddle with only 1 circle
Difference is in:
var NavLinks = document.querySelectorAll('.nav-link');
for (var i = 0; i < NavLinks.length; i++) {
var navLink = NavLinks[i];
navLink.addEventListener('click', function (event) {
var allNavs = document.querySelectorAll('.nav-link div');
for (var it = 0; it < allNavs.length; it++){
console.log(allNavs[it]);
allNavs[it].classList.add('invisible');
allNavs[it].classList.remove('circleVisible');
}
console.log(allNavs);
var targetElement = event.target || event.srcElement;
var circleDiv = targetElement.parentNode.querySelectorAll('div');
console.log(circleDiv[0]);
circleDiv[0].classList.add('circleVisible');
circleDiv[0].classList.remove('invisible');
console.log(circleDiv[0]);
}
);
}
I have left console.logs, so you see how it works, remove them when running the code for real :)
The first big problem I see is you have nested for loops but are using the same iterator variable of i. If you are going to next the loops, you need the inner loop to have a different variable. In situations like this, I will often use ii just because it's easy.
Furthermore, you seem to be doing this in a roundabout way. I'm not entirely sure what you need, but if it is as it appears, then this solution is simpler.
CSS
.circle {
display: none;
... other attributes
}
.active-menu-item > .circle {
display: block;
}
JavaScript
var NavLinks = document.querySelectorAll('.nav-link');
for (var i = 0; i < NavLinks.length; i++) {
var navLink = NavLinks[i];
navLink.addEventListener('click', function () {
for (var ii = 0; ii < NavLinks.length; ii++) {
NavLinks[ii].classList.remove("active-menu-item");
}
navLink.classList.add("active-menu-item");
});
}

display a div below a selected input field? No JQuery

how to display a div everytime a user focus on a input field. there is already a div and it is hidden. the position of the div will change depending on the position of the selected field and it will be display below
this is my code
formFieldListWrapper.style.top = ((((formSelectedFieldInput.offsetTop > (formWrapper.offsetHeight/2))?((formSelectedFieldInput.offsetTop-(formWrapper.offsetHeight/2))-(formSelectedFieldInput.offsetHeight+formWrapper.offsetHeight*0.02)):(formSelectedFieldInput.offsetTop))/formWrapper.offsetHeight)*100) + "%";
formFieldListWrapper.style.left = ((formSelectedFieldInput.offsetLeft/formWrapper.offsetWidth)*100) + "%";
Why use javascript? This could be chieved by using CSS only
HTML
<div class="holder">
<input type="text" />
<div class="dropdown">
<p>Testing</p>
<p>Css ONLY</p>
<p>Dropdown</p>
</div>
</div>
CSS
.holder {
position: relative;
}
.dropdown {
position: absolute;
border: 1px solid red;
display: none;
}
input:focus + .dropdown {
display: block;
}
UPDATE
little bit misred the question, if You need to position div dynamically like in this fiddle, You cloud use:
HTML
<div class="holder">
<input type="text" />
</div>
<div class="holder" style="margin-top: 30px;">
<input type="text" />
</div>
<div class="dropdown">
<p>Testing</p>
<p>Css ONLY</p>
<p>Dropdown</p>
</div>
CSS
.holder {
position: relative;
}
.dropdown {
position: absolute;
border: 1px solid red;
display: none;
z-index: 1;
background: white;
}
input:focus + .dropdown {
display: block;
}
Javascript to position dropdown div
var inputs = document.querySelectorAll('input');
for (var i = 0; i < inputs.length; i++) {
inputs[i].addEventListener('focus', function(){
this.parentNode.appendChild(document.querySelector('.dropdown'));
});
}
Try the following:
formSelectedFieldInput.addEventListener("focus", setDivToInput, false);
function setDivToInput(e)
{
var inputElement = e.target; //e.target refers to the element that fired the event.
formFieldListWrapper.style.top = inputElement.offsetTop + formFieldListWrapper.offsetHeight + "px";
formFieldListWrapper.style.left= inputElement.offsetLeft + "px";
formFieldListWrapper.style.display = "block";
}
The first line adds a focus event to the input. This sets the div to the input based upon it's position on the page. This is very basic and doesn't behave well when the div runs of the screen. You need to add logic for that.
Now for multiple inputs in a form
var nodes = form.querySelectorAll("input"); //replace with your form element
for (var i = 0; i < nodes.length; ++i)
{
nodes[i].addEventListener("focus", setDivToInput, false);
}
function setDivToInput(e)
{
var node = e.target;
formFieldListWrapper.style.top = node.offsetTop + formFieldListWrapper.offsetHeight + "px";
formFieldListWrapper.style.left= node.offsetLeft + "px";
formFieldListWrapper.style.display = "block";
}
This code sets the focus event to all inputs in the form.

Categories