Trying to figure out how to do this with plain javascript and css, below is code working with jquery.
In this example a user clicks a link, the script checks to see if there is content in a div, if there is, it fades out the content, then loads by ajax the new content and fades it in.
I know I can toggle a css class, but wondering how to go about using a callback to see when the css animation has completed to be able to fire the ajax request and then fade in.
<section>
<a href="#" data-file="data1">Load data 1</a>
<a href="#" data-file="data2">Load data 2</a>
<div id="content"></div>
</section>
$(document).ready(function(){
$('body').on('click','a',function(event){
event.preventDefault();
var datafile = $(this).data('file');
console.log(datafile);
if($('#content').html().length){
$('#content').fadeOut(700,function(){
$('#content').load(datafile + '.php').hide().fadeIn(700);
console.log('has content, fadeout then load fadein ' + datafile);
})
} else {
$('#content').load(datafile + '.php').hide().fadeIn(700);
console.log('no content, load fadein ' + datafile);
}
});
});
contents of data1.php and data2.php are filled with lorem ipsum just for testing purposes, in production they would be interface screens for a cms.
here is a jsfiddle
https://jsfiddle.net/nomadwebdesign/cfvd6uk4/
Looking at Dan Dascalescu’s answer and how to expand upon this How to do fade-in and fade-out with JavaScript and CSS
I’ve also been trying to use the on(‘transitionend’) event listener, however it goes into a loop because after loading by ajax I remove the css class causing the transition again.
I am able to do this by using setTimeout and matching the transition duration however this seems flaky.
At this point I would just like to know how to do this with jQuery and CSS without using fadeIn() and fadeOut()
the sequence is
click -> fade out previous content -> fade in ajax loaded content
UPDATE
Here is a working solution using jQuery without fadeIn() or fadeOut() but with CSS opacity transition
<section id="section2">
<a href="#" data-file="data1">Load data 1</a>
<a href="#" data-file="data2">Load data 2</a>
<div id="dataContent"></div>
</section>
$(document).ready(function(){
$('body').on('click','#section2 a',function(event){
event.preventDefault();
var datafile = $(this).data('file');
var dataContent = $('#dataContent');
// if there is content fade it out first
if(dataContent.html().length){
dataContent.addClass('opa fade');
// check for completed transition
dataContent.one('transitionend', function(){
dataContent.load(datafile + '.php', function(){
dataContent.removeClass('fade');
});
});
} else {
// if there is no content just load and fade in
dataContent.addClass('fade');
dataContent.load(datafile + '.php', function(){
dataContent.removeClass('fade');
dataContent.addClass('opa');
});
}
});
});
#dataContent.opa {
opacity: 1;
transition: opacity .700s;
}
#dataContent.fade {
opacity: 0;
}
Still looking for a solution to this without jQuery using vanilla javaScript
referencing these posts for help
https://blog.teamtreehouse.com/using-jquery-to-detect-when-css3-animations-and-transitions-end
https://jonsuh.com/blog/detect-the-end-of-css-animations-and-transitions-with-javascript/
After spending all day thoughtfully researching this and pulling everything I could find from the web together I have a working solution. This is an example using plain vanilla JavaScript Ajax and CSS3 transitions. I have found this to be a popular trend in the last few years (2017-2019) as browsers have advanced an older browsers have fallen away. Also, with the dependency upon jQuery less and less it seems more people are looking for plain js versions and leveraging css3 transitions and animations. I believe this question and answer to be of more detail than the others linked here on stackoverflow and believe this example will be of use to many others.
Here is the working solution
css
#dataContent.opa {
opacity: 1;
transition: opacity .400s;
}
#dataContent.fade {
opacity: 0;
}
html
<section id="section">
<a href="#" class="clicker" data-file="data1">Load data 1</a>
<a href="#" class="clicker" data-file="data2">Load data 2</a>
<a href="#" class="clicker" data-file="data3">Load data 3</a>
<div id="dataContent"></div>
</section>
var classname = document.getElementsByClassName('clicker');
ajaxf = function(event){
var xhttp = new XMLHttpRequest();
event.preventDefault();
var datafile = this.getAttribute('data-file');
var dataContent = document.getElementById('dataContent');
if(dataContent.innerHTML.length){
dataContent.classList.add('opa','fade');
dataContent.addEventListener('transitionend',handler);
function handler(event) {
event.target.removeEventListener(event.type,arguments.callee);
xhttp.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
dataContent.innerHTML = this.responseText;
dataContent.classList.remove('fade');
};
if(this.status == 404){
dataContent.classList.remove('fade');
dataContent.innerHTML = 'there was an error retrieving data';
}
};
xhttp.open('GET',datafile + '.php',true);
xhttp.send();
}
} else {
dataContent.classList.add('fade');
xhttp.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
dataContent.innerHTML = this.responseText;
dataContent.classList.remove('fade');
dataContent.classList.add('opa');
};
if(this.status == 404){
dataContent.innerHTML = 'there was an error retrieving data';
dataContent.classList.remove('fade');
dataContent.classList.add('opa');
}
};
xhttp.open('GET',datafile + '.php',true);
xhttp.send();
}
};
for(var i = 0; i < classname.length; i++){
classname[i].addEventListener('click',ajaxf,false);
};
One of the main keys in this process is creating an event listener for the transitionend and then removing the event listener (to repeat the function when the 2nd transition fires)
4
Answers
One of the main keys in this process is creating an event listener for the transitionend and then removing the event listener (to repeat the function when the 2nd transition fires).
This method checks to see if there is content in the div and if so it will first fade that content out (using CSS3) and then do an ajax call and fade the new content in. If there is no content it will simply do the ajax call with a fade in.
You can use a simpler and modern approach to ajax using fetch API. Also, using a combination of data-* attribute and CSS simplify fading in and out.
Set this example:
you can use this URL:
https://css-tricks.com/dynamic-page-replacing-content/
, there’s a Demo in it (https://css-tricks.com/examples/DynamicPage/) that just does what do you want
EDIT:
have you tried to add a class name to your code container with animation set for a specific time then remove that class name and a class name with a class name to hide the content when replace the content using AJAX then remove the class came and add a class name for the appearing animations?
You could use for this purpose,
fetch()
CSS
animationanimationstart
,animationend
event listeners to manipulate output towards yourdiv.dataContent
element;The difference with your approach is that
fetch
starts onanimationstart
event and the result is appended to#dataContent
element uponanimationend
event;The example below is something you could use for your
onclick
logic.EDIT
The same fade-out effect can be achieved using:
fetch()
transitionstart
,transitionend
event listeners to manipulate output towards yourdiv.dataContent
element;