0

I am trying to find the easiest way to execute a function (resetMenuPosition()) in javascript (or jQuery) only when the prior function (collapseExpandMainMenu(this)) is complete.

ORIGINAL CODE

$('.trmenuClass').click(function () {
    $.when(collapseExpandMainMenu(this))
     .done(function () {
         resetMenuPosition();
     });
});

I've tried different variations of jQuery but I think I am mis-using jQuery as I don't completely grasp the idea of deferred objects.

Any javascript or jQuery suggestions are appreciated.

Thanks, -Tim

EDITED TO INCLUDE collapseExpandMainMenu(this) CODE

function collapseExpandMainMenu(i, callback) {
    isCollapsing = ($(i).find('div').attr('class')) == 'minusSign';
    currentScrollTop = $('#contents').scrollTop();

    var fav, Dash, Conn, Hire, Retain, Activityreports;
    var favSubmnuHt = 0, dashSubmnuHt = 0, connSubmnuHt = 0, hireSubmnuHt = 0, retainSubmnuHt = 0, activityreportsSubmnuHt = 0;

    /*submenu height determination*/
    $('.trmenuClass').each(function () {
        if ($('tr.favtrClass').toggle().is(":visible")) {
            fav = 1;
        }
        else {
            fav = 0;
        }

        if ($('tr.dashboardtrClass').toggle().is(":visible")) {
            Dash = 1;
        }
        else {
            Dash = 0;
        }

        if ($('tr.connecttrClass').toggle().is(":visible")) {
            Conn = 1;
        }
        else {
            Conn = 0;
        }

        if ($('tr.hiretrClass').toggle().is(":visible")) {
            Hire = 1;
        }
        else {
            Hire = 0;
        }

        if ($('tr.retaintrClass').toggle().is(":visible")) {
            Retain = 1;
        }
        else {
            Retain = 0;
        }

        if ($('tr.activityreportstrClass').toggle().is(":visible")) {
            Activityreports = 1;
        }
        else {
            Activityreports = 0;
        }

    })

    /*This gets the height of each dynamically created submenu along with bottom border*/
    var favBottomBorder = 0; var dashBottomBorder = 0; var connectBottomBorder = 0; var hireBottomBorder = 0;
    var retainBottomBorder = 0; var activityreportsBottomBorder = 0;
    $('.favtrClass').each(function () {
        favSubmnuHt = favSubmnuHt + 35;
        favBottomBorder = favBottomBorder + 1;
    })

    $('.dashboardtrClass').each(function () {
        dashSubmnuHt = dashSubmnuHt + 35;
        dashBottomBorder = dashBottomBorder + 1;
    })

    $('.connecttrClass').each(function () {
        connSubmnuHt = connSubmnuHt + 35;
        connectBottomBorder = connectBottomBorder + 1;
    })

    $('.hiretrClass').each(function () {
        hireSubmnuHt = hireSubmnuHt + 35;
        hireBottomBorder = hireBottomBorder + 1;
    })

    $('.retaintrClass').each(function () {
        retainSubmnuHt = retainSubmnuHt + 35;
        retainBottomBorder = retainBottomBorder + 1;
    })

    $('.activityreportstrClass').each(function () {
        activityreportsSubmnuHt = activityreportsSubmnuHt + 35;
        activityreportsBottomBorder = activityreportsBottomBorder + 1;
    })

    /*submenu height determination */
    var varFav = favSubmnuHt - favBottomBorder;
    var varDash = dashSubmnuHt - dashBottomBorder;
    var varConn = connSubmnuHt - connectBottomBorder;
    var varHire = hireSubmnuHt - hireBottomBorder;
    var varRetain = retainSubmnuHt - retainBottomBorder;
    var varActivityreports = activityreportsSubmnuHt - activityreportsBottomBorder;
    var rowCount = ($('#contents tr').length) * 35;

    /*determination which submenu is open and which is closed*/
    if (fav == 1) { favSubmnuHt; }
    else if (fav == 0) { rowCount = rowCount - favSubmnuHt; }

    if (Dash == 1) { dashSubmnuHt; }
    else if (Dash == 0) { rowCount = rowCount - dashSubmnuHt; }

    if (Conn == 1) { connSubmnuHt; }
    else if (Conn == 0) { rowCount = rowCount - connSubmnuHt; }

    if (Hire == 1) { hireSubmnuHt; }
    else if (Hire == 0) { rowCount = rowCount - hireSubmnuHt; }

    if (Retain == 1) { retainSubmnuHt; }
    else if (Retain == 0) { rowCount = rowCount - retainSubmnuHt; }

    if (Activityreports == 1) { activityreportsSubmnuHt; }
    else if (Activityreports == 0) { rowCount = rowCount - activityreportsSubmnuHt; }


    var heightOfSubMenuCombined = 0;
    var idTotoggleSubMenu = $(i).closest('tr').attr('id');  // changes from "this" to "i"
    if (idTotoggleSubMenu == "favoritestrId") {
        $('tr.favtrClass').toggle(browserVar, function () { });
        if (fav == 1) {
            rowCount = rowCount - favSubmnuHt;
            if (rowCount > $('#contents').height()) {
                $('.scrollDownArrow').css({ visibility: "visible" });

            }
            else {
                $('.scrollDownArrow').css({ visibility: "hidden" });
                $('.scrollUpArrow').hide();
                $('.scrollUpArrow').css({ visibility: "hidden" });
                $(document).ready(resizingScrollbar);

            }
        }
        else if (fav == 0) {
            rowCount = rowCount + varFav;

            if (rowCount > $('#contents').height()) {
                $('.scrollDownArrow').css({ visibility: "visible" });
            }
            else {
                $('.scrollDownArrow').css({ visibility: "hidden" });
                $('.scrollUpArrow').hide();
                $('.scrollUpArrow').css({ visibility: "hidden" });
                $(document).ready(resizingScrollbar);

            }
        }
        /*Code to toggle plus and minus sign*/
        if ($('#favoritesMinusSignId').hasClass('minusSign')) {
            $('#favoritesMinusSignId').addClass('plusSign').removeClass('minusSign');
        }
        else if ($('#favoritesMinusSignId').hasClass('plusSign')) {
            $('#favoritesMinusSignId').addClass('minusSign').removeClass('plusSign');
        }

    }
    else if (idTotoggleSubMenu == "dashboardtrId") {
        /*Code to toggle submenu and make bottom scrolling arrow slide up and down*/

        $('tr.dashboardtrClass').toggle(browserVar, function () { });

        if (Dash == 1) {
            rowCount = rowCount - dashSubmnuHt;
            if (rowCount > $('#contents').height()) {
                $('.scrollDownArrow').css({ visibility: "visible" });
            }
            else {
                $('.scrollDownArrow').css({ visibility: "hidden" });
                $('.scrollUpArrow').hide();
                $('.scrollUpArrow').css({ visibility: "hidden" });
                $(document).ready(resizingScrollbar);

            }
        }
        else if (Dash == 0) {
            rowCount = rowCount + varDash;

            if (rowCount > $('#contents').height()) {
                $('.scrollDownArrow').css({ visibility: "visible" });
            }
            else {
                $('.scrollDownArrow').css({ visibility: "hidden" });
                $('.scrollUpArrow').hide();
                $('.scrollUpArrow').css({ visibility: "hidden" });
                $(document).ready(resizingScrollbar);
            }
        }

        /*Code to toggle plus and minus sign*/
        if ($('#dashboardMinusSignId').hasClass('minusSign')) {
            $('#dashboardMinusSignId').addClass('plusSign').removeClass('minusSign');
        }
        else if ($('#dashboardMinusSignId').hasClass('plusSign')) {
            $('#dashboardMinusSignId').addClass('minusSign').removeClass('plusSign');
        }

    }
    else if (idTotoggleSubMenu == "connecttrId") {
        /*Code to toggle submenu and make bottom scrolling arrow slide up and down*/
        $('tr.connecttrClass').toggle(browserVar, function () { });

        if (Conn == 1) {
            rowCount = rowCount - connSubmnuHt;

            if (rowCount > $('#contents').height()) {
                $('.scrollDownArrow').css({ visibility: "visible" });
            }
            else {
                $('.scrollDownArrow').css({ visibility: "hidden" });
                $('.scrollUpArrow').hide();
                $('.scrollUpArrow').css({ visibility: "hidden" });
                $(document).ready(resizingScrollbar);
            }
        }
        else if (Conn == 0) {
            rowCount = rowCount + varConn;

            if (rowCount > $('#contents').height()) {
                $('.scrollDownArrow').css({ visibility: "visible" });
            }
            else {
                $('.scrollDownArrow').css({ visibility: "hidden" });
                $('.scrollUpArrow').hide();
                $('.scrollUpArrow').css({ visibility: "hidden" });
                $(document).ready(resizingScrollbar);
            }
        }

        /*Code to toggle plus and minus sign*/
        if ($('#connectMinusSignId').hasClass('minusSign')) {
            $('#connectMinusSignId').addClass('plusSign').removeClass('minusSign');
        }
        else if ($('#connectMinusSignId').hasClass('plusSign')) {
            $('#connectMinusSignId').addClass('minusSign').removeClass('plusSign');
        }
    }
    else if (idTotoggleSubMenu == "hiretrId") {
        /*Code to toggle submenu and make bottom scrolling arrow slide up and down*/
        $('tr.hiretrClass').toggle(browserVar, function () { });

        if (Hire == 1) {
            rowCount = rowCount - hireSubmnuHt;

            if (rowCount > $('#contents').height()) {
                $('.scrollDownArrow').css({ visibility: "visible" });
            }
            else {
                $('.scrollDownArrow').css({ visibility: "hidden" });
                $('.scrollUpArrow').hide();
                $('.scrollUpArrow').css({ visibility: "hidden" });
                $(document).ready(resizingScrollbar);
            }
        }
        else if (Hire == 0) {
            rowCount = rowCount + varHire;

            if (rowCount > $('#contents').height()) {
                $('.scrollDownArrow').css({ visibility: "visible" });
            }
            else {
                $('.scrollDownArrow').css({ visibility: "hidden" });
                $('.scrollUpArrow').hide();
                $('.scrollUpArrow').css({ visibility: "hidden" });
                $(document).ready(resizingScrollbar);
            }
        }

        /*Code to toggle plus and minus sign*/
        if ($('#hireMinusSignId').hasClass('minusSign')) {
            $('#hireMinusSignId').addClass('plusSign').removeClass('minusSign');
        }
        else if ($('#hireMinusSignId').hasClass('plusSign')) {
            $('#hireMinusSignId').addClass('minusSign').removeClass('plusSign');
        }

    }
    else if (idTotoggleSubMenu == "retaintrId") {
        /*Code to toggle submenu and make bottom scrolling arrow slide up and down*/
        $('tr.retaintrClass').toggle(browserVar, function () { });

        if (Retain == 1) {
            rowCount = rowCount - retainSubmnuHt;

            if (rowCount > $('#contents').height()) {
                $('.scrollDownArrow').css({ visibility: "visible" });
            }
            else {
                $('.scrollDownArrow').css({ visibility: "hidden" });
                $('.scrollUpArrow').hide();
                $('.scrollUpArrow').css({ visibility: "hidden" });
                $(document).ready(resizingScrollbar);
            }
        }
        else if (Retain == 0) {
            rowCount = rowCount + varRetain;

            if (rowCount > $('#contents').height()) {
                $('.scrollDownArrow').css({ visibility: "visible" });
            }
            else {
                $('.scrollDownArrow').css({ visibility: "hidden" });
                $('.scrollUpArrow').hide();
                $('.scrollUpArrow').css({ visibility: "hidden" });
                $(document).ready(resizingScrollbar);
            }
        }

        /*Code to toggle plus and minus sign*/
        if ($('#retainMinusSignId').hasClass('minusSign')) {
            $('#retainMinusSignId').addClass('plusSign').removeClass('minusSign');
        }
        else if ($('#retainMinusSignId').hasClass('plusSign')) {
            $('#retainMinusSignId').addClass('minusSign').removeClass('plusSign');
        }
    }
    else if (idTotoggleSubMenu == "activityreportstrId") {
        /*Code to toggle submenu and make bottom scrolling arrow slide up and down*/
        $('tr.activityreportstrClass').toggle(browserVar, function () { });

        if (Activityreports == 1) {
            rowCount = rowCount - activityreportsSubmnuHt;

            if (rowCount > $('#contents').height()) {
                $('.scrollDownArrow').css({ visibility: "visible" });
            }
            else {
                $('.scrollDownArrow').css({ visibility: "hidden" });
                $('.scrollUpArrow').hide();
                $('.scrollUpArrow').css({ visibility: "hidden" });
                $(document).ready(resizingScrollbar);
            }
        }
        else if (Activityreports == 0) {
            rowCount = rowCount + varActivityreports;

            if (rowCount > $('#contents').height()) {
                $('.scrollDownArrow').css({ visibility: "visible" });
            }
            else {
                $('.scrollDownArrow').css({ visibility: "hidden" });
                $('.scrollUpArrow').hide();
                $('.scrollUpArrow').css({ visibility: "hidden" });
                $(document).ready(resizingScrollbar);
            }
        }

        /*Code to toggle plus and minus sign*/
        if ($('#activityreportsMinusSignId').hasClass('minusSign')) {
            $('#activityreportsMinusSignId').addClass('plusSign').removeClass('minusSign');
        }
        else if ($('#activityreportsMinusSignId').hasClass('plusSign')) {
            $('#activityreportsMinusSignId').addClass('minusSign').removeClass('plusSign');
        }
    }

    //setTimeout(function () {
        callback.call();
    //}, 400);
}

CODE USING JQUERY .THEN

$('.trmenuClass').click(function () {
    (collapseExpandMainMenu(this)).then(
        function () { resetMenuPosition(); },
        function () { alert("Please close and re-open the menu."); }
    );
});

OPENING LINES OF resetMenuPosition()

    console.log('#menuTableId.height: ' + $('#menuTableId').css('height').replace(/px/g, ''));
    alert('pause');
    console.log('#menuTableId.height: ' + $('#menuTableId').css('height').replace(/px/g, ''));
6
  • 2
    what does collapseExpandMainMenu do? is it a jQuery animation? Commented Aug 21, 2012 at 16:21
  • 1
    You will have to show us the code for collapseExpandMainMenu in order to be able to help you. Commented Aug 21, 2012 at 16:22
  • Is collapseExpandMainMenu returning a deferred object? Commented Aug 21, 2012 at 16:23
  • @ianpgall, collapseExpandMainMenu basically collapses/expands sub-menu items when a main menu item is clicked. The specific problem I am running into is the menu is not completely redone after the click before I am looking for the entire menu height in the second function. Granted the code in collapseExpandMainMenu was poorly written and could use some refactoring. Commented Aug 21, 2012 at 17:02
  • Are you able to edit the collapseExpandMainMenu function? If so, can you provide the code for it, as the others have suggested? It might be easier to pass a callback to the function and have that run in the complete of the animation. Commented Aug 21, 2012 at 17:10

2 Answers 2

2

Your collapseExpandMainMenu needs to return a $.Deferred() (or a promise) object and resolve/reject when it is finished. Here's a simple example:

var collapseExpandMainMenu = function () {
    var deferred = $.Deferred();

    setTimeout(function () {
        // some processing
        deferred.resolve('success!');
    }, 5000);

    return deferred.promise();
};

$.when(collapseExpandMainMenu(this))
    .done(function (message) {
        console.log(message); // logs "success!" after 5 seconds
    }
);

Working example: http://jsfiddle.net/3sGZh/

Side note: a promise is a deferred that cannot be resolved/rejected - you give this to consumers so they can respond to resolve/reject, but not execute it themselves.

Sign up to request clarification or add additional context in comments.

6 Comments

Is it possible to have the second function run immediately after the first one is complete instead of waiting for a set timeout period?
@TimS.: Nobody said you'd need to use a timeout. Just resolve it in the callback function of your asynchronous functionality - show us your code of collapseExpandMainMenu
@jbabey: Why do you use $.when?
@Bergi it was in his original example. If it were me, i'd use collapseExpandMainMenu(this).then(...); instead.
@TimS. the setTimeout was to illustrate an asynchronous delay. you don't need to do it in your function.
|
0

Just use a callback :

$('.trmenuClass').on('click', function () {
    collapseExpandMainMenu(this, function() {
        console.log('success!'); // logs "success!" when animation completes
        resetMenuPosition();
    });
});

function collapseExpandMainMenu(elem, callback) {
     //do your stuff first, then call the callback
     $(elem).fadeIn(1000, function() {
          callback.call(); //waits until animation is complete
     });
}

3 Comments

Thanks this worked perfectly. Although ideally I'd like to call the second function upon the initial function completing instead of waiting for some fixed timeout period. Is this possible?
@TimS. - Yes, you can call the callback function whenever your function is complete, I just used a timeout to demonstrate it. You can call the callback either at the bottom of the code or in some other callback for a jQuery function etc, depends on how the collapseExpandMainMenu function is set up, and what the last performed action in that function is, and then you just call the callback when everything else is completed. Edited my answer to show another version ?
Will this approach work for multiple clicks? For example the user may expand/collapse the same item or they may collapse multiple main menu items all without a page refresh. I only see the console log logging the first instance. After that I am getting my second function running too soon?

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.