Animation: Fade in when creating an element and fade out when deleting - javascript

I'm having trouble with the following situation.
I have a button which acts like a normal toggle. When I click on the "Animate" button, I want the <p>This is new Div</p> to fade in when I again click on the Animate button, this <p> should fade out.
How can I achieve this?
const main = document.getElementById('main');
const btn = document.getElementById('btn');
let show = false;
btn.addEventListener('click', () => {
if(show) {
const newDiv = document.getElementById("new-div");
newDiv.remove();
show = false;
} else {
const newDiv = document.createElement('div');
newDiv.id = "new-div";
newDiv.innerHTML = "<p>This is new Div</p>";
main.appendChild(newDiv);
show = true;
}
})
#new-div {
transition: all 2s ease-in-out;
}
<div id="main">
<button id="btn">Animate</button>
</div>
I'm actually building a gallary layout app, which requires to fade in when clicked on a image + show in full screen, then fade out to its original position when clicked. Since there will be many images, I want to use JS to dynamically work on this.
And the biggest hurdle so far is to implement fade-out, because the element is being deleted.

Based on your information I've made a refined version, pls see fiddle and code below: https://jsfiddle.net/Kenvdb/8nsbp16o/
JavaScript:
const main = document.getElementById('main');
const btn = document.getElementById('btn');
let toggledDiv = null;
btn.addEventListener('click', () => {
if (!toggledDiv) {
show();
} else {
hide();
}
})
const show = () => {
toggledDiv = document.createElement('div');
toggledDiv.id = "content";
toggledDiv.style.opacity = "1";
toggledDiv.innerHTML = "<p>This is new Div</p>";
main.appendChild(toggledDiv);
}
const hide = () => {
toggledDiv.style.animation = "fade-out 0.5s ease-in";
toggledDiv.style.opacity = "0";
toggledDiv.addEventListener('animationend', remove);
toggledDiv.addEventListener('webkitAnimationEnd', remove);
}
const remove = () => {
toggledDiv.remove();
toggledDiv = null;
};
CSS:
#content {
opacity: 0;
animation: fade-in 0.5s ease-in;
}
#keyframes fade-in {
0% { opacity: 0; }
100% { opacity: 1; }
}
#keyframes fade-out {
0% { opacity: 1; }
100% { opacity: 0; }
}
HTML:
<div id="main">
<button id="btn">Animate</button>
</div>

You'll need to set the opacity to 0 first. Then you can apply a keyframe animation.
Otherwise, the element has nothing to transition from.
See below.
#new-div {
opacity: 1;
animation: fadeIn 2s ease-in-out;
}
#keyframes fadeIn {
from {
opacity: 0;
}
}

There's several ways of doing this. You can set the opacity of the newly added element using the style attribute:
const main = document.getElementById('main');
const btn = document.getElementById('btn');
let show = false;
let fading = false;
btn.addEventListener('click', () => {
if (fading) return;
if (show) {
const newDiv = document.getElementById("new-div");
newDiv.style = "opacity: 0"; // start the fade
fading = true;
window.setTimeout(function() {
fading = false; // disable showing/hiding while fading
newDiv.remove(); // remove after fade completed
show = false;
}, 2000);
} else {
show = true;
const newDiv = document.createElement('div');
newDiv.id = "new-div";
newDiv.innerHTML = "<p>This is new Div</p>";
main.appendChild(newDiv);
window.setTimeout(function() {
newDiv.style = "opacity: 1"; // Start fading after a minimal time
});
}
})
#new-div {
transition: all 2s ease-in-out;
opacity: 0;
}
<div id="main">
<button id="btn">Animate</button>
</div>
Or you can use jQuery, which significantly reduce the code:
$("#btn").on('click', () => {
var newDiv = $("#new-div");
if (newDiv.length) {
newDiv.stop().fadeOut(2000, function() {
newDiv.remove();
});
} else {
$(`<div id='new-div'>
<p>This is new Div</p>
</div`).appendTo("#main").hide().fadeIn(2000);
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="main">
<button id="btn">Animate</button>
</div>

You can do it simply using both of fadeIn() and fadeOut() methods in jQuery.
Here is an example:
let alreadyClicked = false;
$("#btn").click(function() {
if(alreadyClicked == false) {
$("p").remove(); //Remove the paragraph if already created.
$("#main").append("<p style='display: none;'>Hello, world!</p>"); //Create a paragraph.
$("p").fadeIn(); //Show it by fading it in.
alreadyClicked = true;
} else {
$("p").fadeOut(); //Fade it out
alreadyClicked = false;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="main">
<button id="btn">Animate</button>
</div>

Related

javascript onclick css fade in each time, not just 1st time

How can I have text fade in on each click and not just the first time using css transition and JavaScript?
Here is what I have so far
<style>
#data {
transition: .7s;
}
</style>
<h1 id="data"></h1>
click 1
document.getElementById('data').style.opacity = 0;
function go(event){
event.preventDefault();
document.getElementById('data').style.opacity = 1;
document.getElementById('data').innerHTML = 'test';
}
document.getElementById('clicker').addEventListener('click', go);
It can also be done using Element.animate():
const dataElement = document.getElementById('data')
dataElement.style.opacity = 0
function go(event) {
event.preventDefault()
dataElement.animate({
opacity: [0, 1]
}, 700).onfinish = () => dataElement.style.opacity = 1
}
document.getElementById('clicker').addEventListener('click', go)
<h1 class="fade-in" id="data">test</h1>
click 1
EDIT:
In the above snippet onfinish event handler was used to maintain the final opacity value since it was being set back to 0 after the animation ends. But I found that this can also be achieved by setting fill: 'forwards' in the keyframe options:
const dataElement = document.getElementById('data')
dataElement.style.opacity = 0
function go(event) {
event.preventDefault()
dataElement.animate({
opacity: [0, 1]
}, {
duration: 700,
fill: 'forwards'
})
}
document.getElementById('clicker').addEventListener('click', go)
<h1 class="fade-in" id="data">test</h1>
click 1
Also you might want to check browser compatibility before implementing those approaches
And if you want a safer approach you may use css animations:
const data = document.getElementById('data')
data.style.opacity = 0
const clicker = document.getElementById('clicker')
clicker.addEventListener('click', () => {
data.classList.remove('fade-in')
data.offsetWidth // required to trigger a reflow and restart the animation
data.classList.add('fade-in')
})
.fade-in {
animation-name: fadein-animation;
animation-duration: 700ms;
animation-fill-mode: forwards;
}
#keyframes fadein-animation {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
<h1 id="data">test</h1>
click 1
setTimeout might work for you. On click set it invisible immediately and use setTimeout to have a delay then show it again.
document.getElementById('data').style.opacity = 0;
document.getElementById('data').innerHTML = 'test';
function go(event){
event.preventDefault();
document.getElementById('data').style.opacity = 0;
setTimeout(() => {
document.getElementById('data').style.opacity = 1;
}, 1000);
}
document.getElementById('clicker').addEventListener('click', go);
#data {
transition: .7s;
}
<h1 id="data"></h1>
click 1
<h1 id="data" style="opacity:0"> </h1>
<button type="button" id="clicker">Fade In</button>
<script>
var data = document.getElementById('data');
function fadeIn(){
data.innerHTML = 'Data entered successfully.';
data.animate({opacity:[0,1]},{duration:400,fill:'forwards'});
}
document.getElementById('clicker').addEventListener('click',fadeIn);
</script>

Using vanilla JavaScript, is it possible to add a DOM element and fade in using CSS transition, without using setTimeout or CSS animation?

Is it possible to add an element to the page, but have it fade it, without using setTimeout()?
I am thinking that for CSS transition, it has to first have a value (opacity 0), and then, let it have another value (opacity 1), so that the transition can occur, so a setTimeout() is needed.
The snippet below can add the new row, but is it possible to make it fade in, again, not using jQuery's fadeIn(), setTimeout(), or CSS animation? Is it possible to do it using CSS transition delay?
const tableElement = document.querySelector("#tbl");
document.querySelector("#btn").addEventListener("click", ev => {
tableElement.innerHTML = `${tableElement.innerHTML}<tr><td>Hi There ${Math.random()}</td></tr>`;
});
tr {
transition: all 1s
}
tr {
opacity: 0.2
}
<button id="btn">Click</button>
<table id="tbl"></table>
fadeIn without setTimeout and css animation ;)
const tableElement = document.querySelector('#tbl');
const btn = document.querySelector('#btn');
btn.addEventListener('click', () => {
btn.setAttribute('disabled', true);
tableElement.innerHTML = `${tableElement.innerHTML}<tr><td class='hidden'>Hi There ${Math.random()}</td></tr>`;
const el = document.querySelector('.hidden');
el.classList.remove('hidden');
fadeIn(el);
});
function fadeIn(el, display) {
el.style.opacity = 0;
el.style.display = display || 'block';
(function fade() {
let val = parseFloat(el.style.opacity);
let proceed = !(((val += 0.04) > 1));
if (parseInt(el.style.opacity) === 1) {
btn.removeAttribute('disabled');
}
if (proceed) {
el.style.opacity = val;
requestAnimationFrame(fade);
}
})();
}
.hidden {
display: none;
}
<button id="btn">Click</button>
<table id="tbl"></table>

How could I make this active onclick?

var span = document.getElementById('loading_dots');
var int = setInterval(function() {
if ((span.innerHTML += '●').length == 4)
span.innerHTML = '';
}, 400);
(function(){
var loading_dots = document.getElementById("loading_dots"),
show = function(){
loading_dots.style.display = "block";
setTimeout(hide, 5000); // 5 seconds
},
hide = function(){
loading_dots.style.display = "none";
};
show();
})();
How can I make it so loading_dots start on the click of a button, and re-activates everytime I click the button? the bottom function is to stop it after 5 seconds, maybe could merge it into one function?
Needs to work for 3 seperate buttons and relaunch on click of each, also needs to display inside of <span class="loading_dots" id="loading_dots"></span> any method is fine, css, jquery, or javascript
here is a jQuery version:
(function ( $ ) {
$.fn.loader = function( options ) {
var settings = $.extend({
text:"●",
spn: undefined
}, options );
$.each(this, function(){
var btn = this;
var int;
var spn;
if (settings.spn === undefined) {
spn = $("<span/>" , { "class":"loading_dots" });
$(btn).append(spn);
} else {
spn= $(settings.spn);
}
var show = function(){
btn.setAttribute("disabled", "disabled")
clearInterval(int);
spn.show();
int = setInterval(function() {
if ((spn[0].innerHTML += settings.text).length == 4)
spn.html("");
}, 400);
setTimeout(hide, 5000); // 5 seconds
}
var hide = function (){
spn.hide();
btn.removeAttribute("disabled", "disabled")
clearInterval(int);
}
btn.addEventListener("click", show);
});
};
}( jQuery ));
// now bind it by its class, this only need to be run once every time new button is added to the html
$(".btn").loader({spn:".loading_dots"});
// and you could also specify the text by
// $(".btn").loader({text: "*"});
.loading_dots {
color:red;
display:none;
width:100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<span class="loading_dots"></span>
<button class="btn" type="button" >
submit
</button>
<button class="btn" type="button" >
submit
</button>
</div>
If you want to add an event listener for a button click, just select the buttons, and add the listeners in a loop:
document.querySelectorAll("button").forEach(e => e.addEventListener("click", myFunc));
Alternatively, listen for any click, then check if the event's target is a button:
document.addEventListener("click", (e) => if (e.target.tagName == "BUTTON") myFunc());
You could use CSS for the most part of your code, and than simply toggle a show class on the parent #loading element:
const Loading = () => {
let tOut = null;
const el = document.querySelector("#loading");
const show = () => {
el.classList.add('show');
tOut = setTimeout(hide, 5000);
};
const hide = () => {
el.classList.remove('show');
clearTimeout(tOut);
};
return {
show,
hide
};
};
const loadingDots = Loading();
const loadBtns = document.querySelectorAll('.load');
[...loadBtns].forEach(el => el.addEventListener('click', loadingDots.show));
// you can always use loadingDots.hide() to hide when needed (before the 5sec ticks out)
#loading {
position: fixed;
z-index: 100;
top:0;
left: 0;
width:100vw;
height:100vh;
display:flex;
background: rgba(0,0,0,0.5);
color: #fff;
font-size: 3em;
align-items: center;
justify-content:center;
visibility: hidden;
opacity: 0;
transition: 0.4s;
}
#loading.show {
opacity: 1;
visibility: visible;
}
#keyframes blink {
50% {opacity: 1;}
}
#loading i:after {content: "\25cf";}
#loading i { opacity: 0; animation: blink 1.2s infinite; }
#loading i:nth-child(2) { animation-delay: .2s; }
#loading i:nth-child(3) { animation-delay: .4s; }
<div id="loading"><i></i><i></i><i></i></div>
<button class="load">LOAD</button>
<button class="load">LOAD</button>
<button class="load">LOAD</button>
A plain javascript version with the option to programmatically/manually stop displaying the loading dots. Just pass the id of the parent element you want the loading to be attached to. By default the loading will be appended to the parent but you can optionally pass an object as the last parameter with a position property.
function removeLoading(id) {
var parent = document.getElementById(id);
var spans = parent.getElementsByClassName("loading_dots");
while (spans.length > 0) {
var span = spans[0];
if (span.dataset.timerId) {
clearTimeout(span.dataset.timerId);
}
span.remove();
}
}
function addLoading(id, options) {
options = options || {};
var parent = document.getElementById(id);
var existingSpans = parent.getElementsByClassName("loading_dots");
if (existingSpans.length > 0) {
removeLoading(id);
}
var span = document.createElement("span");
span.setAttribute("class", "loading_dots");
if (options.timerId) {
span.dataset.timerId = options.timerId;
}
parent.insertAdjacentElement(options.position || "beforeend", span);
setInterval(function () {
if ((span.innerHTML += '●').length == 4)
span.innerHTML = '';
}, 400)
}
function addLoadingWithTimeout(id, ms, options) {
options = options || {};
var timerId = setTimeout(function () { removeLoading(id) }, ms);
options.timerId = timerId;
addLoading(id, options);
}
<p id="load1">Load 1 - Will stop automatically in 3 seconds after starting. </p>
<button onclick="addLoadingWithTimeout('load1', 3000)">Start Load 1</button>
<button onclick="removeLoading('load1')">Stop Load 1</button>
<p id="load2">Load 2 - Only manual Stop </p>
<button onclick="addLoading('load2')">Start Load 2</button>
<button onclick="removeLoading('load2')">Stop Load 2</button>
Here you go. on the HTML side, you just pass the event to the button that you want and then the id, as a string, of the span/div where you want the load icons to appear.
HTML:
<button id="btn" onclick="load(event, 'loadDiv')">Load</button>
<div>
<span id="loadDiv"></span>
</div>
Below, we are getting the btn id from event so you don't have to manually pass it everytime. Then we are defining function for the innerhtml icons. Lastly, we are running the showIcon function every .4s and then clearing the interval after 5 seconds.
JS:
function load(e, location) {
var btn = document.getElementById(e.srcElement.id)
var loadDiv = document.getElementById(location)
function showLoad() {
if (loadDiv.innerHTML.length < 3) {
return loadDiv.innerHTML += '●'
}
loadDiv.innerHTML = ''
}
(function() {
var loadIcons = setInterval(function() {
showLoad()
}, 400)
var clear = setTimeout(function() {
clearInterval(loadIcons)
}, 5000)
})()
}
Hope this helps!
You can define your code in a function and add click handler to the button.
function myFunc() {
var span = document.getElementById('loading_dots');
var int = setInterval(function() {
if ((span.innerHTML += '●').length == 4)
span.innerHTML = '';
}, 400);
(function(){
var loading_dots = document.getElementById("loading_dots"),
show = function(){
loading_dots.style.display = "block";
setTimeout(hide, 5000); // 5 seconds
},
hide = function(){
loading_dots.style.display = "none";
};
show();
})();
}
document.getElementById("myBtn1").addEventListener("click", myFunc);
document.getElementById("myBtn2").addEventListener("click", myFunc);

Setting timeOut in javascript on changing display of element

I have a simple script that hides and shows certain element on the site by changing display to either "none" or "block". I want it to be animated, meaning that elements will slowly fade-out. I'm fairly new to javascript and I know that there is setTimeout and setInterval, but I'm not sure how to use it. How can I "animate" this functions? Here is my code:
var rysunki = document.querySelectorAll(".rysunek");
var projekty = document.querySelectorAll(".projekt");
var btnAll = document.getElementById("allItems");
var btnProjekty = document.getElementById("projects");
var btnRysunki = document.getElementById("drawings");
function removeDrawings() {
var i;
for (i = 0; i < rysunki.length; i++) {
rysunki[i].style.display = "none";
};
};
function showDrawings(){
var i;
for (i = 0; i < rysunki.length; i++) {
rysunki[i].style.display = "block";
};
};
function removeProjects() {
var i;
for (i = 0; i < projekty.length; i++) {
projekty[i].style.display = "none";
};
};
function showProjects() {
var i;
for (i = 0; i < projekty.length; i++) {
projekty[i].style.display = "block";
};
};
function showAll() {
showProjects();
showDrawings();
}
btnProjekty.addEventListener("click", function(){
showProjects();
removeDrawings();
});
btnRysunki.addEventListener("click", function(){
removeProjects();
showDrawings();
});
btnAll.addEventListener("click", showAll);
Is it even possible? Should I add something with opacity of the elements I'm hiding?
No jQuery please, only Vanilla JS.
Edit:
As requested, here is the HTML. Basically there are 2 different elements:
<figure class="projects-panel__item col-md-3 projekt">
<img src="img/1.jpg" alt="" />
</figure>
<figure class="projects-panel__item col-md-3 rysunek">
<img src="img/1.jpg" alt="" />
</figure>
Heres an simple example of how to do it with mix of JS and CSS.
In JS I am just changing class of container, in response to button click.
In CSS I've defined transition: opacity (this is how stuff is being animated) on .projects and .drawings
I've also added two classes which will modify value of opacity on those two classes above.
Feel free to ask questions if You do not understand something.
const container = document.querySelector('#container')
const showDrawings = () => {
container.classList.remove('showProjects')
container.classList.add('showDrawings')
}
const showProjects = () => {
container.classList.remove('showDrawings')
container.classList.add('showProjects')
}
const showAll = () => {
container.classList.add('showDrawings')
container.classList.add('showProjects')
}
document.querySelector('#drawingsButton').addEventListener('click', showDrawings)
document.querySelector('#projectsButton').addEventListener('click', showProjects)
document.querySelector('#allButton').addEventListener('click', showAll)
.drawings,
.projects {
display: inline-block;
width: 200px;
height: 200px;
opacity: 0;
transition: opacity .3s .1s;
}
.drawings {
background: red;
}
.projects {
background: blue;
}
.showDrawings .drawings {
opacity: 1;
}
.showProjects .projects {
opacity: 1;
}
<div id="container">
<div class="drawings"></div>
<div class="projects"></div>
</div>
<button id="drawingsButton">Drawings</button>
<button id="projectsButton">Projects</button>
<button id="allButton">All</button>

Javascript function to FadeIn and FadeOut html item - working solution

HTML
<div id="notifyProductName">
Angualar JS
<a href="" ng-click="cart.addItem(product.name,product.price, 1);cart.ShowItem(product.name)">
JavaScript
cart.prototype.ShowItem = function (productName)
{
document.getElementById("notifyProductName").innerHTML = productName";
document.getElementById("notifyProductName").fadeOut(400);
}
I want to display the productName in a html message box and then fade the message box out after a few seconds.
Set a 3 second setTimeout() function and use a CSS class with transition on opacity for the fade.
cart.prototype.ShowItem = function (productName)
{
var el = document.getElementById("notifyProductName");
el.innerHTML = productName;
el.classList.remove('fade');
el.classList.add('show');
var timeout = setTimeout(function() {
el.classList.add('fade');
}, 3000);
}
.notifyProductName {
opacity: 0;
}
.show {
opacity: 1;
}
.fade {
opacity: 0;
transition: opacity .5s;
}
<div id="notifyProductName" class="notifyProductName"></div>

Categories