admin管理员组文章数量:1321606
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 pleted 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 /
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 pleted 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
/
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)
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 pleted 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/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 pleted 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./using-jquery-to-detect-when-css3-animations-and-transitions-end
https://jonsuh./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)
Share Improve this question edited Nov 9, 2019 at 1:28 drooh asked Oct 27, 2019 at 16:53 droohdrooh 6784 gold badges20 silver badges52 bronze badges 4- this question is asking for plain javascript answers, the linked questions are regarding jquery. – drooh Commented Oct 27, 2019 at 23:31
- 1 Re-opened so you can add your answer below. – Phil Commented Oct 28, 2019 at 4:32
- I provided a working answer below, however at of Nov 2 I created a bounty worth 200 to draw more attention. – drooh Commented Nov 2, 2019 at 16:55
- @drooh check an answer using CSS animation – user2560539 Commented Nov 9, 2019 at 13:35
4 Answers
Reset to default 8 +100You can use a simpler and modern approach to ajax using fetch API. Also, using a bination of data-* attribute and CSS simplify fading in and out.
Set this example:
var classname = document.getElementsByClassName('clicker');
let dataContent = document.getElementById("dataContent");
/*
* Manage transtion in and out in sucess and error callback
*/
function transition(content) {
dataContent.classList.add("fade");
var clickFunction = function(event) {
dataContent.innerHTML = content;
dataContent.classList.remove("fade");
};
dataContent.addEventListener("transitionend", clickFunction);
return true;
}
// Main function, to call fetch
function ajaxf() {
var datafile = this.getAttribute('data-file');
var opts = {
method: 'GET'
};
fetch(datafile, opts).then(function(response) {
/* If we dont get an OK response (200) then through an error to
trigger catch callback
*/
if (response.status !== 200)
throw new Error("Not 200 response")
/* Parse response to json. You can use text() as well
* https://developer.mozilla/en-US/docs/Web/API/Body
*/
return response.json();
})
.then(function(content) {
// check if content has been set previously
let hasContent = dataContent.getAttribute("data-hascontent");
if (hasContent != 'false')
return transition(content.body);
// Process empty div
dataContent.innerHTML = content.body;
dataContent.setAttribute("data-hascontent", "true");
}).catch(function(error) {
// Same as previous methid
let hasContent = dataContent.getAttribute("data-hascontent");
if (hasContent != 'false')
return transition(error);
dataContent.innerHTML = error;
dataContent.setAttribute("data-hascontent", "true");
});
}
// Attach Events
for (var i = 0; i < classname.length; i++) {
classname[i].addEventListener('click', ajaxf, false);
}
#dataContent {
opacity: 0;
transition: opacity .400s;
}
#dataContent[data-hascontent='true'] {
opacity: 1;
}
#dataContent[data-hascontent='true'].fade {
opacity: 0;
}
<section id="section">
<a href="#" class="clicker" data-file="https://jsonplaceholder.typicode./posts/1">Load data 1</a>
<a href="#" class="clicker" data-file="data2">Load data 2</a>
<a href="#" class="clicker" data-file="https://jsonplaceholder.typicode./posts/5">Load data 3</a>
<div id="dataContent" data-hascontent='false'></div>
</section>
<style>
#dataContent.opa {
opacity: 1;
transition: opacity .400s;
}
#dataContent.fade {
opacity: 0;
}
</style>
<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>
<script>
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);
};
</script>
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 this URL: https://css-tricks./dynamic-page-replacing-content/ , there's a Demo in it (https://css-tricks./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,
- content load via
fetch()
- a simple
CSS
animation - Use
animationstart
,animationend
event listeners to manipulate output towards yourdiv.dataContent
element;
The difference with your approach is that fetch
starts on animationstart
event and the result is appended to #dataContent
element upon animationend
event;
The example below is something you could use for your onclick
logic.
document.querySelectorAll('#section2 a').forEach((item) => {
item.addEventListener('click', (e) => {
let dataFile = e.target.dataset.file,
dataContent = document.getElementById('dataContent'),
myText = null;
dataContent.classList.add('fade');
dataContent.addEventListener('animationstart', (ev) => {
fetch(dataFile).then(async(response) => {
await response.text().then(async(text) => {
myText = await text;
});
}).catch(async(error) => {
myText = await error.toString().split(': ')[1];
});
});
dataContent.addEventListener('animationend', (ev) => {
dataContent.classList.remove('fade');
dataContent.innerHTML = myText;
});
});
});
#dataContent.fade {
animation: fade .950s;
}
@keyframes fade {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
<section id="section2">
<a href="#" data-file="https://www.w3/TR/PNG/iso_8859-1.txt">Load data 1</a>
<a href="#" data-file="http://25.io/toau/audio/sample.txt">Load data 2</a>
<div id="dataContent">Click any of the above links to retrieve new content!</div>
</section>
EDIT
The same fade-out effect can be achieved using:
- content load via
fetch()
- Use
transitionstart
,transitionend
event listeners to manipulate output towards yourdiv.dataContent
element;
document.querySelectorAll('#section2 a').forEach((item) => {
item.addEventListener('click', (e) => {
let dataFile = e.target.dataset.file,
dataContent = document.getElementById('dataContent'),
myText = null;
dataContent.classList.add('fade');
dataContent.addEventListener('transitionstart', (ev) => {
fetch(dataFile).then(async(response) => {
await response.text().then(async(text) => {
myText = await text;
});
}).catch(async(error) => {
myText = await error.toString().split(': ')[1];
});
});
dataContent.addEventListener('transitionend', (ev) => {
dataContent.classList.remove('fade');
dataContent.innerHTML = myText;
});
});
});
#dataContent.fade {
opacity: 0;
transition: opacity .950s;
}
#dataContent {
opacity: 1;
}
<section id="section2">
<a href="#" data-file="https://www.w3/TR/PNG/iso_8859-1.txt">Load data 1</a>
<a href="#" data-file="http://25.io/toau/audio/sample.txt">Load data 2</a>
<div id="dataContent">Click any of the above links to retrieve new content!</div>
</section>
本文标签:
版权声明:本文标题:jquery - Plain javascript trigger css fade out, ajax load content, fade in using CSS - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742104307a2420947.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论