Reputation: 1427
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
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
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
Reputation: 3925
Can you use JQuery UI? It ships with it's own Modal Dialog.
http://jqueryui.com/dialog/#modal
Upvotes: 0