0

I have a response handler that replaces content from ajax response. I want to fire an event after the content is replaced. This is the response handler:

function(response)
    {
        /* animate to top if called from bottom pagination */
        if ( caller === 'pag-bottom' && jq('#subnav').length ) {
            var top = jq('#subnav').parent();
            jq('html,body').animate({scrollTop: top.offset().top}, 'slow', function() {
                jq(target).fadeOut( 100, function() {
                    jq(this).html(response);
                    jq(this).fadeIn(100);
                });
            });

        } else {
            jq(target).fadeOut( 100, function() {
                jq(this).html(response);
                jq(this).fadeIn(100);
            });
        }
        jq('.item-list-tabs li.selected').removeClass('loading');
     // the event I want to trigger
        jq( document ).trigger( "buddyFilter:replaced", [ object, filter] );
    }

My problem is this event fires to early so my code that fires on event doesn't calculate the size of the div correctly and formatting is incorrect.

I have tried various combinations of trying to chain the event trigger but I can't get it right. I can't use a manual delay because then that will cause visual jump and not always work if loading time is slower than time.

How can I trigger this event the moment the html() value has rendered?

Edit:

Here is jsfiddle that is similar to my code but I had to change it about to get to work in fiddle. It shows that right after the event fires the div is 0 height

http://jsfiddle.net/jq7n4kfL/1/

2
  • Why not trigger the event once the animation is complete --- in the last fadeOuts callback? Commented Jun 18, 2015 at 0:57
  • I tried jq(this).fadeIn(100).trigger( "buddyFilter:replaced", [ object, filter] ); but it didn't work. Commented Jun 18, 2015 at 0:59

3 Answers 3

2

Try utilizing .promise() , .then()

    function success(response)
        {
            /* animate to top if called from bottom pagination */
            if ( caller === 'pag-bottom' && jq('#subnav').length ) {
                var top = jq('#subnav').parent();
                return jq('html,body').animate({scrollTop: top.offset().top}, 'slow', function() {
                    jq(target).fadeOut( 100, function() {
                        jq(this).html(response);
                        jq(this).fadeIn(100);
                        jq('.item-list-tabs li.selected').removeClass('loading');
                    });
                }).promise();

            } else {
               return jq(target).fadeOut( 100, function() {
                    jq(this).html(response);
                    jq(this).fadeIn(100);
                    jq('.item-list-tabs li.selected').removeClass('loading');
                }).promise();
            }             
        };

$.ajax().then(success).then(function() {
  // the event I want to trigger
  jq( document ).trigger( "buddyFilter:replaced", [ object, filter] );
}]);
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks! Is there any benefit to adding return before selector? I had a play with the fiddle and it works if I do promise().done(func) jsfiddle.net/jq7n4kfL/2
@Guerrilla Included return to return a jQuery promise value to next .then() , if any , in chain. Using .done() should return similar results as .then() to call .trigger(). Note, .done() returns original jQuery promise value , .then() can return a new jQuery promise value . See stackoverflow.com/questions/5436327/… .
1

You're triggering the event too early. Try this:

            jq(target).fadeOut( 100, function() {
                jq(this).html(response);
                jq(this).fadeIn(100, function() {
                   //trigger the event herer
                });
            });

Of course, you have to do it in two places.

1 Comment

It still fires too early, the content hasn't rendered in so my code gets incorrect div size. If I add in a 1 second delay then it works (with visual jump).
0

You just put the event firing right after the actual HTML replacement takes place:

jq(target).fadeOut( 100, function() {
    jq(this).html(response);
    jq( document ).trigger( "buddyFilter:replaced", [ object, filter] );
    jq(this).fadeIn(100);
});

Also note that you repeat exactly the same code twice so better DRY it by wrapping it in a method.

5 Comments

It still fires too early, the content hasn't rendered in so my code gets incorrect div size. If I add in a 1 second delay then it works (with visual jump).
Once jq(this).html(response) is called the content should be fully rendered before any further JS code is executed. I suggest you show a fiddle as the issue might be specific to your content or something.
here is fiddle that shows exactly what happens but I had to change the code around a bit but it highlights the issue jsfiddle.net/jq7n4kfL/1
I have put the event triggering into fadeIn callback (as @PeterKA pointed) and it worked: jsfiddle.net/xs0k65vy
Yes you are correct, I looked too hastily at the code and didn't put it correctly in the right callback.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.