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>
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>
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);
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>
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>