简体   繁体   中英

My .remove() event isn't working

I've created a custom modal dialog that is added and removed from the screen when it is called. However, when I'm trying to remove it, the remove function doesn't seem to be working in certain circumstances.

This is the close function from the modal (triggered by clicking on the close button):

function modal_close() {
  $('.custom_block_page').fadeOut().remove();
  $(this).parent().fadeOut().remove();
};

This is how I call that function from the button inside the modal dialog:

MatchGame.closeWin = function() {
  $('.custom_modal_close').trigger('click');
  MatchGame.playGame();
};

If I just click the close button, the dialog is removed and everything works as expected. But when I trigger the close, the dialog fades to nothing, but remains in the body so it displays again the next time it is called.

Checking the console between I get:

$('.custom_block_page').length
1  // displayed the first time
$('.custom_block_page').length
0  // during the 2nd game (expected)
$('.custom_block_page').length
2  // displayed after the 2nd game; I expect this to be 1

I've tried putting a timeout on my playGame, but that didn't seem to help either.

Thanks for the help!

The issue you observe is due to .fadeOut() , which is implemented asynchronously in a whole series of later event threads.

Meanwhile, in the original event thread .remove() , subsequent statements, returning from the function and subsequent statements in the function's caller, ALL execute synchronously - well before .fadeOut() has completed.

The solution is to exploit .promise() , which will return a jQuery promise, from which you can chain .then() :

function modal_close() {
    return $('.custom_block_page').add($(this).parent()).fadeOut().promise().then(function() {
        $(this).remove();
    });
};

In the caller, .trigger() returns jQuery but you now need to work with the returned promise, therefore use .triggerHandler() .

MatchGame.closeWin = function() {
    $('.custom_modal_close').triggerHandler('click').then(function() {
        MatchGame.playGame();
    });
};

Edit:

Code from add_block_page() and add_popup_box() can be safely rolled into show_modal_box() to make one larger function.

By doing so, you will benefit from being able to access the variables $block_page , $pop_up , $close , $inner from the close button's click handler.

function show_modal_box() {
    var $block_page = $('<div class="custom_block_page"></div>').appendTo('body'); // dark background
    var $pop_up = $('<div class="custom_modal_box"></div>').appendTo($block_page);
    var $close = $('<a href="#" class="custom_modal_close"></a>').appendTo($pop_up);
    var $inner = $('<div class="custom_inner_modal_box">loading...</div>').appendTo($pop_up);
    if(options.name != '') {
        $pop_up.attr('id', options.name);
    }

    // Add the content - if url, load the page otherwise use the text
    if (options.url != '') {
        $inner.load(options.url);
    } else {
        var innerHTML = '';
        if(options.title[0] === "<") { // assume formatting
            innerHTML += options.title;
        } else {
            innerHTML += '<h2>' + options.title + '</h2>';
        }
        if(options.description[0] === "<") {
            innerHTML += options.description;
        } else {
            innerHTML += '<p>' + options.description + '</p>';
        }
        $inner.html(innerHTML);
    }

    $close.click(function() {
        // for example
        return $pop_up.fadeOut().promise().then(function() {
            $block_page.remove();
        });
    });
    $(window).off('resize.popup').on('resize.popup', add_styles).trigger('resize.popup'); // prevent accumulation of resize handlers

    // checkNeedScroll();
    $pop_up.fadeIn();
}

EDIT 2

I think I have it!

In the custom_modal_box plugin, the code below causes a click handler to be appended to this :

    return this.click(function(e) {
        show_modal_box();
    });

That's fine if the plugin is invoked just once on any particular element however in this game's code it is invoked on the same element, $('.win') , every time a game is completed.

To prevent an accumulation of click handlers on $('.win') , change that code to :

    return this.off('click.popup').on('click.popup', function(e) {
        show_modal_box();
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM