Trigger a function when a CSS animation reaches its completion

I am working on a small jQuery function that needs to return its value within a subfunction. The purpose behind this is so that I can later chain this function with other jQuery functions. However, I want the next chained function to start only after the main function has returned the jQuery object.

app.h.aniend = 'webkitAnimationEnd oanimationend msAnimationEnd animationend';
$.fn.animate_scale = function( callback ) {
    var $this = $(this);
    $this.addClass('animate_scale').one( app.h.aniend, function() {
        $(this).removeClass('animate_scale');
        if( typeof callback === 'function' ) {
            callback($this);
        }
        return $this; // returning here...
    });
    // return $this;
};

Is there a way to instruct jQuery to wait until the subfunction returns the necessary jQuery objects for chaining?

$('#my_object').animate_scale().fadeOut(2000);

Answer №1

$('#my_object').animate_scale().fadeOut(2000);

If you wish for .fadeOut() to synchronize with the completion of animate_scale(), then animate_scale must be queued:

Cue your plugin:

Typically, when you link together fx methods like this example:

$("#ball").animate({left:200}).fadeOut();

You will observe the ball animating first, followed by it fading out only after the animation is complete.
Why? Because jQuery will place animate and fadeOut in a queue array and wait for each one to finish before executing the next method.

To achieve similar functionality within your plugin:

jsFiddle demo (Queue in action!)

$.fn.animate_scale = function( callback ) {
    var $this = this;
    return $this.queue(function() { 
        $this.addClass('animate_scale').on("animationend", function() {
            $this.dequeue();
            if (typeof callback == 'function') callback.call( $this );
        });
    });
};


$('#my_object').animate_scale(function() {
    console.log( "Scale is done!" );
}).fadeOut( 2000 ); // fadeOut will wait for animate_scale to dequeue (complete)

I prefer not to stack queues

If you want your plugin to run other chained fx Methods simultaneously, simply use the callback:

jsFiddle demo (no Queue)

$.fn.animate_scale = function( callback ) {
  var $this = $(this);
  return $this.addClass('animate_scale').on("animationend", function() {
      if (typeof callback == 'function') callback.call( this );
  });
};

$('#my_object').animate_scale(function(){
    console.log("Scale done.");
                  // use $(this).fadeOut(2000); here!! cause otherwise...
}).fadeOut(2000); // ...if chained here, will fade immediately!!!!!

Answer №2

An effective method is to utilize a callback function:

$('#my_object').trigger_animation(function(){ $(this).hide(1500) });

Alternatively, there exists a less recommended approach that achieves the desired outcome but has its drawbacks:

app.h.animend = 'webkitAnimationEnd oanimationend msAnimationEnd animationend';
$.fn.trigger_animation = function( callback ) {
    var $element = $(this);
    var hideTime;
    $element.addClass('trigger_animation').one( app.h.animend, function() {
        $(this).removeClass('trigger_animation');
        if( typeof callback === 'function' ) {
            callback($element);
        }
        if(hideTime) {
          $(this).hide(hideTime);
        }
    });
    return {
      hide: function(duration) { hideTime = duration; }
    };
};

This solution may seem excessive as it restricts you to only utilizing hide through a callback, however, it effectively stores the value until needed. If you choose not to call Hide, then hidingTime remains undefined and no hiding occurs.

Answer №3

One potential approach to consider is a versatile method that:

  • is not limited to a specific CSS3 selector
  • can replicate jQuery's pre-built animations like slideDown() or fadeIn().

If this method (let's name it .css3Animate()) needs to function in all of the following scenarios:

// method-chain
$('#my_object').css3Animate('animate_scale').fadeOut(1000);
// callback
$('#my_object').css3Animate('animate_scale', function() {
    $(this).fadeOut(1000);
});
// .promise().then()
$('#my_object').css3Animate('animate_scale').promise().then(function() {
    $(this).fadeOut(1000);
});

A particular jQuery plugin accomplishes these objectives...

(function($) {
    var aniend = 'webkitAnimationEnd oanimationend msAnimationEnd animationend';
    $.fn.css3Anim = function(cssClass, callback) {
        var $this = this; // In the context of a plugin, `this` already represents a jQuery collection.
        return this.queue(function(next) { // Add the CSS animation to the elements' fx queue.
            $this.queue(function(){}) // Halt the animation queue during the CSS transition.
            .one(aniend, function() {
                if(callback && typeof callback === 'function') {
                    callback.call(this);
                }
                $this.removeClass(cssClass) // Ready for another call
                .dequeue(); // Permit the fx animation queue to advance and fulfill the associated promise.
            })
            .addClass(cssClass); // Trigger the essential animation
            next(); // Move on to the queue blockage indicated above.
        });
    };
})(jQuery);

http://jsfiddle.net/sy51tyn5/1/

The behavior is satisfactory but not flawless. The plugin is meant to handle queuing two or more animations, yet it struggles with three or more.

In the demonstration, you'll notice that buttons are disabled while an animation is ongoing, preventing interference while the CSS3 animation plays out. If you uncheck the checkbox and repeatedly click the buttons, you'll easily disrupt the process.

This issue might stem from the unpredictability of next()'s progression to the queue blocker - external factors may intervene. Further investigation is required to address this. Perhaps someone adept could provide insight?

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Getting rid of unnecessary compiled CSS files in Compass

After making changes to files and running compass compile, the compiled files remain even if they are renamed or deleted. Similarly, compass clean does not remove these old files as it only focuses on cleaning up current files in use. I want to avoid compl ...

"Switching from vertical to horizontal time line in @devexpress/dx-react-scheduler-material-ui: A step-by-step guide

Is there a way to switch the Time to a horizontal line using @devexpress/dx-react-scheduler-material-ui? <WeekView startDayHour={7} endDayHour={20} timeTableCellComponent={TimeTableCell} dayScaleCellComponent={DayScaleCell} /> Click ...

Expanding Table Functionality with Javascript - Customizing Default Layout

I have a unique system where a calendar is constructed using individual <table> elements for each month. With the help of Javascript, I am able to expand or collapse each month as needed. Here is the Javascript code: $(function() { var $month = $(& ...

How do I utilize the Material-UI slider's activated (CSS API) feature to conceal the shadows?

Can someone please explain to me how I can use the activated class to change the style of the thumb and hide its shadows? According to the official website, the activated class is applied to the track and thumb elements to trigger JSS nested styles when a ...

Navigating a page without embedding the URL in react-router-dom

In my application, I am utilizing react-router-dom v5 for routing purposes. Occasionally, I come across routes similar to the following: checkup/step-1/:id checkup/step-2/:id checkup/step-3/:id For instance, when I find myself at checkup/step-1/:id, I int ...

Utilize jQuery to retrieve content from the URL http://imgur.com/gallery/hot/page/1.json

Hello, I'm attempting to retrieve this JSON data using $.getJSON and $.ajax(), but I'm not having any success. jQuery.ajax({ url: "http://imgur.com/gallery/hot/page/1.json", type: 'GET', ...

The "Overall Quantity" of items will vary as it goes through different numerical values, despite the fact that I employed --

I am currently working on an e-commerce website with a shopping cart feature. The cart displays the number of items added to it, which increases by one when 'Add to Cart' is clicked and decreases by one when 'Remove' is clicked. However ...

Revealing a concealed element by sliding it upwards on a single page, then repeating the

Can someone assist me in achieving a specific effect on my website? I have a top banner section with a button at the bottom. When the button is clicked, a form should slide up into view. The form will initially be hidden. I also need the same effect at the ...

Change to a dark theme using React hooks in typescript

Hello, I am new to React and English is not my first language, so please excuse any mistakes. I have been trying to enable a dark mode feature on my website. Most examples I have found involve toggling between dark and light modes where you need to specify ...

The form submits immediately after jquery is activated

One challenge I'm facing involves multiple forms on a single page being submitted using jQuery. Currently, I have the following code snippet: $("form").submit(function (e) { // Submit form via Ajax }); The problem arises when the form is only s ...

In PhantomJS, where is the location of the "exports" definition?

Consider the following code snippet from fs.js: exports.write = function (path, content, modeOrOpts) { var opts = modeOrOptsToOpts(modeOrOpts); // ensure we open for writing if ( typeof opts.mode !== 'string' ) { opts.mode = ...

The value is not being populated in the text area when the onchange event occurs

<textarea className="form-control queryheight box_xp" placeholder="Enter Dashboard Content" type="text" onChange={this.dashboardtextchartchange.bind(this)} value={this.state.textdashboard}> </textarea> Function triggered on change : dashb ...

Joi mistakenly demanding certain fields that should not be mandatory

I've encountered an issue with posts validation using @hapi/joi 17.1.1. In my schema, I have two fields: textfield and picture. Although both fields are not required, the validation is still indicating that the picture field is mandatory. posts valid ...

Receive information following submission

I've created a script that automatically logs in after submitting a form, changes the link, and I want to download the next page automatically. What should I add after the last line in the code below? Here is my current code: <?php $homepage = fi ...

The inline script in JQuery 3.5.1 was refused to execute due to violating a Content Security Policy directive

After upgrading jQuery from version 2.1.1 to 3.5.1, I encountered an issue related to Content Security Policy directives. The inline script execution was refused due to a violation of the following Content Security Policy directive: "script-src 'sel ...

What is the best way to create an automatic scroll feature for the div content in this scenario

I have integrated RSS Feeds to display news on my website using the following code: <div id="divRss"></div> $(document).ready(function() { $('#divRss').FeedEk( { FeedUrl: 'http://www.moneycontrol.com/rss/results ...

Why won't my redux application store the results of an asynchronous API request using redux-thunk's caching mechanism?

I am new to using Redux in my project. Currently, I am developing an application that displays a list of soccer leagues in each country. The process involves fetching a list of countries first, then using the country names to fetch the soccer leagues. Not ...

Modify table row background color using PHP based on its position in the table with the use of a function

I am having trouble formatting my table to highlight different rows in distinct colors. The top row should be one color, the second row another, and the bottom two rows a different color each. This is to represent winners, teams getting promoted, and tho ...

Transforming the header of a table in a CSV file into a schema field

My task is to create a schema for a CSV file using Mongoose, but upon inspecting the file, I discovered it contains nearly a hundred fields or columns. While I am familiar with defining schemas in Mongoose for files with only a few fields, I am unsure ho ...

Combining strings from an array while restricting repeated characters

I have an array of strings that need to be combined to form a single string, using a specific number referred to as the associatedNumber. This associatedNumber dictates that in the final result, all clusters of identical characters (from the array) should ...