最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to fire a callback function after a for-loop is done in Jquery? - Stack Overflow

programmeradmin0浏览0评论

I have two functions that caluclate and adjust the height and width of elements on screen.

panelHeight sets the height of target elements to the available screen height, while panelWidth adjusts the width of elements.

My problem:
I cannot ensure the second functions (panelWidth) fires AFTER the first function (panelHeight) is done. If the target element is long and has a scrollbar, it will be removed by panelHeight but if this is not done before panelWidth fires, the set width will be off by the space taken up by the scrollbar (17px - still present when the width is calculated).

So I'm looking for a way to fire a function only after another function is done. Sort of like a callback, but I'm not sure who to fiddle this in below for-loop:

panelHeight: function (from) {
    var self = this,
        o = self.options,
        wrap = $('div:jqmData(wrapper="true").ui-page-active').last(),
        overthrow = wrap.jqmData("scrollmode") == "overthrow" && $('html').hasClass('ui-splitview-mode'),
        blacklist = $('html').hasClass('blacklist'),

        // calculationg toolbars
        // elements
        contents = TARGET_ELEMENT;

    if (overthrow) {
        for ( var i = 0; i < contents.length; i++){
            // calculate values 
            ...
            contents.eq(i).css({    
                        "max-height": setH, 
                        "margin-top": blacklist == true ? glbH + lclH : 0, 
                        "margin-bottom": blacklist == true ? glbF + lclF  : 0
                    })
            }

        } else {

            for ( var i = 0; i < contents.length; i++){
                // calculate values
                ...
                contents.eq(i).css({    
                            "max-height" : "", 
                            "height": o._iPadFixHeight, 
                            "margin-top": blacklist == true ? 
                                parseFloat( lclH.outerHeight() ) : 0, 
                            "margin-bottom": blacklist == true ? 
                                parseFloat( lclF.outerHeight() ) : 0
                        })
                }

            }   
            // USING THIS NOW, WHICH IS NOT NICE                
    window.setTimeout(function(){ self.panelWidth(false ); },65)
    },

So I'm either looping through the overthrow-if-or-else loop and only need to fire panelWidth *AFTER* the loop is finished.

Question:
Any idea how to get rid of the timeout and add the panelWidth function call to the end of the loop? I tried with queue, but this also requires a delay(xxx). Also I cannot fire panelWidth inside the for-loop. I need it to trigger once only once the height function is plete

EDIT:
Would this be possible:

// calling my panelHeight function like this: 
self.panelHeight("source").done(function() {
   // call panelWidth:
   self.panelWidth();
   });

If so, where would I have to put the var deferred = Deferred();?

SOLUTION:
Got it to work. Thanks all! Here is my solution:

When calling panelHeight, add done() handler

$(document).on('pagechange.fixedHeight', function() {
    self.panelHeight("pagechange").done( function() {
        self.panelWidth( false ) 
        });
    });

Inside panelHeight, declare defer and return resolved();

panelHeight: function (from) {  
    var deferred = $.Deferred();

    ... run function

    return deferred.resolve();
    }

I have two functions that caluclate and adjust the height and width of elements on screen.

panelHeight sets the height of target elements to the available screen height, while panelWidth adjusts the width of elements.

My problem:
I cannot ensure the second functions (panelWidth) fires AFTER the first function (panelHeight) is done. If the target element is long and has a scrollbar, it will be removed by panelHeight but if this is not done before panelWidth fires, the set width will be off by the space taken up by the scrollbar (17px - still present when the width is calculated).

So I'm looking for a way to fire a function only after another function is done. Sort of like a callback, but I'm not sure who to fiddle this in below for-loop:

panelHeight: function (from) {
    var self = this,
        o = self.options,
        wrap = $('div:jqmData(wrapper="true").ui-page-active').last(),
        overthrow = wrap.jqmData("scrollmode") == "overthrow" && $('html').hasClass('ui-splitview-mode'),
        blacklist = $('html').hasClass('blacklist'),

        // calculationg toolbars
        // elements
        contents = TARGET_ELEMENT;

    if (overthrow) {
        for ( var i = 0; i < contents.length; i++){
            // calculate values 
            ...
            contents.eq(i).css({    
                        "max-height": setH, 
                        "margin-top": blacklist == true ? glbH + lclH : 0, 
                        "margin-bottom": blacklist == true ? glbF + lclF  : 0
                    })
            }

        } else {

            for ( var i = 0; i < contents.length; i++){
                // calculate values
                ...
                contents.eq(i).css({    
                            "max-height" : "", 
                            "height": o._iPadFixHeight, 
                            "margin-top": blacklist == true ? 
                                parseFloat( lclH.outerHeight() ) : 0, 
                            "margin-bottom": blacklist == true ? 
                                parseFloat( lclF.outerHeight() ) : 0
                        })
                }

            }   
            // USING THIS NOW, WHICH IS NOT NICE                
    window.setTimeout(function(){ self.panelWidth(false ); },65)
    },

So I'm either looping through the overthrow-if-or-else loop and only need to fire panelWidth *AFTER* the loop is finished.

Question:
Any idea how to get rid of the timeout and add the panelWidth function call to the end of the loop? I tried with queue, but this also requires a delay(xxx). Also I cannot fire panelWidth inside the for-loop. I need it to trigger once only once the height function is plete

EDIT:
Would this be possible:

// calling my panelHeight function like this: 
self.panelHeight("source").done(function() {
   // call panelWidth:
   self.panelWidth();
   });

If so, where would I have to put the var deferred = Deferred();?

SOLUTION:
Got it to work. Thanks all! Here is my solution:

When calling panelHeight, add done() handler

$(document).on('pagechange.fixedHeight', function() {
    self.panelHeight("pagechange").done( function() {
        self.panelWidth( false ) 
        });
    });

Inside panelHeight, declare defer and return resolved();

panelHeight: function (from) {  
    var deferred = $.Deferred();

    ... run function

    return deferred.resolve();
    }
Share Improve this question edited Jun 15, 2012 at 9:26 frequent asked Jun 15, 2012 at 7:35 frequentfrequent 28.5k61 gold badges187 silver badges336 bronze badges 1
  • You don't have async functions in your code. And thus all code is blocking, there is no need to use a callback, just call the function at the end of your code. If this does not work, the problem is not the time of the call but rather something else. – Yoshi Commented Jun 15, 2012 at 8:26
Add a ment  | 

1 Answer 1

Reset to default 6

This is the purpose of the JQuery Deferred...

var deferred = $.Deferred();

somethingAsync(function() {
    // callback stuff here

    // now tell the deferred task it's ok to proceed
    deferred.resolve();
}

deferred.done(function() {
    // your finalize code here
});

Edit Since the resolve event needs to be tied to a dom resizing, maybe the Javascript resize event handler would work.

发布评论

评论列表(0)

  1. 暂无评论