quilkin
quilkin

Reputation: 1427

Trying to make a modal popup menu

I'm trying to create a modal popup (e.g. for a yes/no confirmation)such that code doesn't continue to execute until the popup is answered. I know that the recommended method is to add callbacks to each button (menu item), but this method gives a problem when the menu is part of a loop and one of the results may be a 'break' from the loop, rather than function call. Anyway, I came up with the code here, using a jquery 1.3 popup widget:

var $popUp;
var popupResult;
function wait()
{
    if (popupResult == null) {
        setTimeout(wait, 100);
    }
    else
        return;
}

function CreatePopupMenu(title)
{
    popupResult = null;
    // for safety, timeout the popup if it isn't answered
    setTimeout(function(){ popupResult = false;  }, 3000);
    $popUp = $("<div/>").popup({
        dismissible: false,
        theme: "c",
        afteropen: function () {
            while (popupResult == null)
                wait();
        }
    }).on("popupafterclose", function ()
    {
        $(this).remove();
    });
    $("<h4/>", {  text: title }).appendTo($popUp);
}

The problem is, the popup doesn't actually appear, the code runs straight into the 'afteropen' callback. If the popup doesn't appear the user cannot use a button to set 'popupResult' so the wait continues forever. If I remove the 'afteropen' callback, the popup appears as expected, but now 'popupResult' remains null (it will be set by callbacks on the buttons which are appended to the menu before it is opened). A subsidiary question is, why doesn't my 'get-out clause' with the longer timeout ever fire?

Upvotes: 2

Views: 1131

Answers (3)

metadings
metadings

Reputation: 3848

Change

afteropen: function () {
    while (popupResult == null)
        wait();
}

to

afteropen: wait

or

afteropen: function () { wait(); }

Currently you endless do wait and never leave the loop. That also creates unlimited timeouts.

Using the change you are doing once 'wait' - that does re-setTimeout until popupResult is no more not !


BTW: This line may not do and even interfere your intentions. If this is executed by the browser right between the user chooses the answer and the next 'wait' timeout - this would reset user's changes.

setTimeout(function(){ popupResult = false;  }, 3000);

Better save the waitTimeout in wait

var waitTimeout;

function wait() {
    if (!popupResult) {
        waitTimeout = setTimeout(wait, 100);
    }
}

So you can do clearTimeout and auto-close the popup:

setTimeout(function () {
    if (waitTimeout) {
        clearTimeout(waitTimeout);
        waitTimeout = undefined;
    }
    popupResult = undefined;
    $popUp.close();
}, 3000);

Upvotes: 1

hamstu
hamstu

Reputation: 1644

As was mentioned, you can probably find a pre-made solution to your problem; there are tons of jQuery modal popups and boxes out there (Google is your friend.) That said, I can see at least one problem:

$popUp = $("<div/>").popup({
  dismissible: false,
  theme: "c",
  afteropen: function () {
    /* while (popupResult == null) */ // <-- REMOVE THIS LINE
    wait();
  }
})

That while loop is unnecessary. In fact you'll very rarely want to use a while loop in this context; you're essentially starting an infinite loop (since it will block execution of other code, browser rendering, etc.). Try removing it, and your code should work more as expected. (I haven't tested this.)


A better way to do this would be to structure your popups in HTML like so: (you could create this code in jQuery too, similar to your example)

<div class='popup' id='myPopup'>
  <h2>Popup Title</h2>
  <a href='#' class='action' data-action='close'>Close</a>
  <a href='#' class='action' data-action='other'>Press Me!</a>
</div>

Then you would simply attach event handlers (i.e., callbacks) to the links/buttons.

$('.popup a.action').on('click', function(event) {
   var action = $(this).data('action');
   // Do something... (Close popup, etc.)
});

I hope that makes sense.

Upvotes: 2

Kyle Muir
Kyle Muir

Reputation: 3925

Can you use JQuery UI? It ships with it's own Modal Dialog.

http://jqueryui.com/dialog/#modal

Upvotes: 0

Related Questions