Trigger jQuery events one after another - javascript

Hi I am trying to create an animation where one class is added only after the one before it is finished triggered.
$('.flipper').click(function(){
$('#first').addClass('first-flip');
$('#second').addClass('second-flip');
$('#fourth').addClass('fourth-flip');
});
so
$('#second').addClass('second-flip');
would only trigger when
$('#first').addClass('first-flip');
has finished its process.
so another way of explaining this would be.
Block A has a rotate effect added to it, after Block A is rotated, only then will Block B move 20 px right.
I basically just want to know how to create Jquery effects that trigger in sequential order.

You want to tie into transitionend or animationend. Here is an example using transitionend. After the box has finished moving, a new class is added which begins the next transition to turn the box blue.
var mydiv = document.querySelector("#mydiv");
document.querySelector("button").addEventListener("click", buttonHandler);
mydiv.addEventListener("transitionend", onEndHandler)
function buttonHandler() {
mydiv.classList.add("move-left");
}
function onEndHandler() {
mydiv.classList.add("turn-blue");
}
#mydiv {
background: red;
width: 10em;
height: 10em;
transition: 1s;
}
#mydiv.move-left {
transform: translateX(100px);
}
#mydiv.turn-blue {
background: blue;
}
<div id="mydiv"></div>
<button>Move div</button>
If you need the jQuery version, it's here:
var mydiv = $("#mydiv");
$("button").on("click", buttonHandler);
mydiv.on("transitionend", onEndHandler)
function buttonHandler() {
mydiv.addClass("move-left");
}
function onEndHandler() {
mydiv.addClass("turn-blue");
}
Nice resource: https://davidwalsh.name/css-animation-callback

Related

Add css keyframe animation every image switch

I have an image tag where in every 3 seconds it changes to a different image and I want to add into it an animation style where every time the image switch, a css animation keyframe will take effect. It seems that I cant figure out how to apply the animation in javascript. Here's what Ive tried so far:
My javascript,:
let indexObj = {
imageChange: document.getElementById("imageChanger"), //id of the image tag
imagePath: ["images/Ps_Logo.png", "images/Pencil.png"],
indexPos: 0,
ChangeImage: () => {
setInterval(() => {
indexObj.imageChange.src = indexObj.imagePath[indexObj.indexPos];
indexObj.imageChange.classList.add("imageToChange"); // imageToChange is the name of the css class where the animation is written on.
indexObj.indexPos++;
if (indexObj.indexPos === 2) {
indexObj.indexPos = 0;
}
}, 3000)
}
}
indexObj.ChangeImage();
Here is my css code. The class and animation keyframe:
.imageToChange {
height: 55px;
width: 70x;
border-radius: 20%;
animation-name: animateImage;
animation-duration: .5s;
animation-fill-mode: forwards;
}
#keyframes animateImage {
0% {
margin-top: 2px;
opacity: 0;
}
50% {
margin-top: 7;
}
100% {
opacity: 1;
margin-top: 9px;
}
}
The animation only runs the first time you add the .imageToChange class (and it does work with your code).
You need to either remove the class after the animation or switch to a different class each time you iterate an image.
Have you tried adding and removing (toggling on and off) on your animateImage class? Consider adding the animation class and then toggling it after the animation is completed.
You could use the addClass("imageToChange") and removeClass("imageToChange") jQuery methods: https://api.jquery.com/addClass/
Or using Vanilla JS toggle a class: https://www.w3schools.com/howto/howto_js_toggle_class.asp
Just be sure to retrigger the event the desired number of times.

Getting the (final) height of an element while its dimensions are being transitioned via CSS

When requesting the dimensions of an element currently in a CSS transition, jQuery will return the current value of the element's height at the given time of when the dimensions are requested.
While this is right and well, it often isn't what's needed. I have many cases in which I'd like to retrieve the final dimensions that the element will have after the transition, but while the transition is still in progress.
How can I reliably retrieve the dimensions of an element while its still in transition?
$(document).ready(function() {
$('#one').on('click', function() {
$(this).addClass('trans');
$('#output').text($(this).height());
var self = $(this);
setTimeout(function() {
$('#output').text(self.height());
}, 200);
});
});
#output {}
#one {
width: 200px;
height: 200px;
background: red;
transition: all 1s linear;
}
#one.trans {
height: 600px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<div id="output">...</div>
<div id="one"></div>
See this codepen example
The thing about using setTimeout is that you're forced to use a somewhat arbitrary value. You can use requestAnimationFrame, which should force the code to execute after the transition
A lot of times, you need to wait until the second animation frame, so:
requestAnimationFrame(function() {
requestAnimationFrame(function() {
$('#output').text(self.height());
});
});

CSS fade out multiple times

I'm making a website which will let you update an SQL table, and I want to add some sort of feedback when a button is clicked. I have made an invisible button (opacity=0) which lies to the right of each row as a status. I made this JS fade() function to set the opacity to 1, then slowly bring it back to 0, so a message pops up then fades away.
function fade () {
var invis = document.getElementById("invis".concat(num.toString()));
if(invis.style.opacity > .990) {
invis.style.opacity = (invis.style.opacity) - .001;
setTimeout(fade, 50);
} else if(invis.style.opacity > 0) {
invis.style.opacity = (invis.style.opacity) - .05;
setTimeout(fade, 50);
}
}
The trouble is, since webpages are single-threaded, any other action will interrupt the animation and leave behind a half-faded status. So that's no good. So now I am trying to set up the invisible buttons to change class when a new row is updated. The new class looks like this:
.invisible_anim {
...
opacity: 0;
animation:trans 3000ms;
}
#keyframes trans {
0% {
opacity: 1;
}
50% {
opacity: 1;
}
This works fine, except it only works once. From here I cannot get the animation to play a second time. I have tried changing the class back to "invisible" then "invisible_anim" with no luck. I also can't use JQuery or Webkit. I'm wondering if there's some flag you can set for a button without actually clicking on it so I can reset the class when I need to? Or even some way to thread my JS function so I can stick with that.
If you would like to play the animation multiple times (see docs here: https://developer.mozilla.org/en-US/docs/Web/CSS/animation), if you would like to play it twice only.
so this:
.invisible_anim {
...
opacity: 0;
animation:trans 3000ms;
}
#keyframes trans {
0% {
opacity: 1;
}
50% {
opacity: 1;
}
would turn to
.invisible_anim {
...
opacity: 0;
animation:trans 3s 2 ;
}
#keyframes trans {
0% {
opacity: 1;
}
50% {
opacity: 1;
}
EDIT:
Apparently the requirements are different than what I thought. Instead the solution seems to be to key off the animation event located at https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_animations and then when that animation done do what you need to do: so in JS-only
var e = document.getElementById("watchme");
e.addEventListener("animationend", listener, false);
function listener(){
//do what you need to do here
}
Just be careful, the reason for this is that most browsers have different "animationend" events that fire at different times. So definitely will need to be tested in different browsers to make sure that the animation event is firing at the right time. There's a post at (https://css-tricks.com/controlling-css-animations-transitions-javascript/) that details some of the issues you might encounter.
Have you considered using the CSS property "transition"? JavaScript has an event listener called "transitionend" that can trigger when your transition has ended, which you can use to reset the button.
First set the area for your alert button with the id invis.
CSS:
#invis {
opacity: 1;
transition: opacity 3s;
}
Then in JavaScript, generate your button and its content, which will appear at opacity 1, then transition to opacity 0. Your addEventListener will trigger when the animation is done, remove the button and reset the opacity for the next trigger.
JavaScript:
var invis = getElementByID("invis");
function fade() {
var button = document.createElement("button");
invis.appendChild(button);
invis.style.opacity = ("0");
invis.addEventListener("transitionend", function(){
invis.removeChild(button);
invis.style.opacity = ("1");
});
}
You can add the fade() function to your EventListener for the user "click."
This is my first time answering on StackOverflow, I hope this helps!
You need to start transparent then show then hide:
#keyframes trans {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}
Then simply add your class (remove after the 3000ms time period)

while having elements slide, make wrapper div width decrease

I have a simple div wrapper called .falling within this div I have 10 small images. I created a simple function that allows them to 'slide down' when I desire. That code is below.
JS:
function slide(){
$(".falling").delay(100).fadeIn().animate({opacity: 1, top:"300px"},'slow');}
slide();
CSS:
.falling {
width: 500px;
left: 600px;
top: 60px;
position: absolute;
display:none;
}
The problem is; 2 things. One, at the end of the 'slide down' I would like to have the .falling wrapper width to DECREASE so down to maybe 250px; because I want the illusion the images are grouping together at the end. Each img has a shared class called .imgfall I would like to use this to make the images smaller in width at the bottom as well. So, maybe max-width: 25px;
function slide(){
$(".falling").delay(100).fadeIn().animate({opacity: 1, top:"300px"},'slow');
$(".falling").css("width", "250px"); // tried this before and after slide but doesn't resize after slide but instead before, so not working!
}
slide();
By calling a function as the last parameter in jquery's animate function, you basically call an 'on complete'. See: http://api.jquery.com/animate/
var $fallingShell = $(".falling");
var animateSlides = function(){
function slide(){
$fallingShell.delay(100).fadeIn().animate({opacity: 1, top:"300px"},'slow', function(){
$fallingShell.animate({"width":"250px"}, 500);
});
}
}
And the replay needs the inline css create by the js reset. See: http://api.jquery.com/css/
I think this is everything you need to reset, but this is a best guess having not seen the code.
var resetSlides = function(){
$(".falling").css(
"width":"auto",
"opacity":"0",
"top":"0px"
);
}
So then you can tie it all together with a click or timer or something, or even call the reset at the start of animateSlides();
$('button').on('click', function(){
resetSlides();
animateSlides();
});

I can add an overlay, but I can't remove it (jQuery)

This function adds an overlay with the following properties to the entire browser screen,
$('a.cell').click(function() {
$('<div id = "overlay" />').appendTo('body').fadeIn("slow");
});
#overlay
{
background-color: black;
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
display: none;
z-index: 100;
opacity: 0.5;
}
And this function is supposed to remove it.
$('#overlay').click(function() {
$(this).fadeOut("slow").remove();
});
But it seems to do absolutely nothing and now my page is stuck with a black overly over it. What's wrong with the removal?
The problem is that when you're adding the click handler, there isn't any overlay, so you're adding the handler to an empty set of elements.
To fix this, use the live method to bind your handler to all elements that match #overlay, whenever they are created.
Also, fadeOut is not a blocking call, so it returns before the element finishes fading out. Therefore, you're calling remove right after the element starts fading out.
To fix this, use fadeOut's callback parameter to call remove after the animation finishes.
For example:
$('#overlay').live(function() {
$(this).fadeOut("slow", function() { $(this).remove(); });
});
Here you go. This should fix the problem and let the overlay fade out before removing it.
$('#overlay').live("click", function() {
$(this).fadeOut("slow", function() { $(this).remove() });
});
Remove should be in the callback to fadeout, like so:
$('#overlay').live('click', function() {
$(this).fadeOut("slow", function() {
$(this).remove();
});
});
Try:
$('#overlay').live('click', function() {
$(this).fadeOut("slow").remove();
});
My recommendation is to use the jquery.tools overlay plugin. Your overlay will have a trigger (usually a button or link), but you can load or clear it with a javascript command, e.g.:
js:
var config = { closeOnClick:true, mask:{opacity:0.7, color:'#333', loadSpeed:1} }
$("#myTrigger").overlay(config); // add overlay functionality
$("#myTrigger").data("overlay").load(); // make overlay appear
$("#myTrigger").data("overlay").close(); // make overlay disappear
html:
<div id="myOverlay" style="display:none;">Be sure to set width and height css.</div>
<button id="myTrigger" rel="#myOverlay">show overlay</button>

Categories