views:

256

answers:

6

The following confirmDialog function is called midway through another jquery function. When this confirmDialog returns true the other function is supposed to continue... but it doesn't. The reason for this seems to be that the entire confirmDialog function has already executed (returning false) by the time the continue button gets clicked. How can I delay it returning anything until after the buttons have been clicked?

(Or, if I'm completely on the wrong track, what is the problem and how do I fix it?)

function confirmDialog(message) {
....
    $('input#continue', conf_dialog).click(function() {
        $(this).unbind();
        $('p',conf_dialog).fadeOut().text('Are you really sure you want to '+message).fadeIn();
        $(this).click(function() {
            $(conf_dialog).remove();
            return true;
        });
    }); 
    $('input#cancel', conf_dialog).click(function() {
        $(conf_dialog).remove();
        return false;
    }); 
}
A: 

try this plugin: http://www.evanbot.com/article/jquery-delay-plugin/4

Adolfo Abegg
+1  A: 

Im' not sure you can. AFAIK only built-in function like confirm, alert or prompt can be blocking while asking for an answer.

The general workaround is to refactor your code to use callbacks (or use the built-in functions). So that would mean splitting your caller function in two, and executing the second part when the input is obtained.

streetpc
A: 

You could add a timeout before the next function is called

http://www.w3schools.com/htmldom/met_win_settimeout.asp

Jonathan Mayhak
+1  A: 

In confirmDialog, you're setting up event handlers, that will execute when events are fired, not when confirmDialog is run. Another issue, is that you return true or false inside the event function, so that won't apply to the outer function confirmDialong.

The part that relies on the button presses would need to be re-factored. Perhaps put it in another function, and call it from the click handlers:

var afterConfirm = function(bool) {
    if(bool) {
     //continue clicked
    } else {
     //cancel clicked
    }
    //do for both cases here
}

//inside confirmDialog input#continue
$(this).click(function() {
    $(conf_dialog).remove();
    afterConfirm(true);
});
seanmonstar
A: 
function callingFunction() {
  $('a').click(function() {
    confirmDialog('are you sure?', dialogConfirmed);
    // the rest of the function is in dialogConfirmed so doesnt 
    // get run unless the confirm button is pressed
  })
}

function dialogConfirmed() {
  // put the rest of your function here
}

function confirmDialog(message, callback) {
  ...
  $('input#continue', conf_dialog).click(function() {
    callback()
    $(conf_dialog).remove();
    return false;
  }),
  $('input#cancel', conf_dialog).click(function() {
    $(conf_dialog).remove();
    return false;
  })
  ...
}
thief
Thsi is pretty much the approach I followed.One thing I'd add is that if your original function takes variables you have to pass these to, and then out of, the confirmDialog function.
wheresrhys
A: 

You may want to look into using Deferred objects. Here are two links that explain them.

http://www.sitepen.com/blog/2009/03/31/queued-demystifying-deferreds/

http://api.dojotoolkit.org/jsdoc/1.3/dojo.Deferred

Using a Deferred you could take your calling function:

function doSomething () {
  // this functions does something before calling confirmDialog
  if (confirmDialog) {
    // handle ok
  } else {
    // handle cancel
  }
  // just to be difficult lets have more code here
}

and refactor it to something like this:

function doSomethingRefactored() {
  // this functions does something before calling confirmDialog

  var handleCancel = function() { /* handle cancel */};
  var handleOk = function() { /* handle ok */};
  var doAfter = function() { /* just to be difficult lets have more code here */};

  var d = new dojo.deferred();
  d.addBoth(handleOk, handleCancel);
  d.addCallback(doAfter);
  confirmDialog(message, d);
  return d;
}
  • ConfirmDialog would have to be updated to call d.callback() or d.errback() instead of returning true or false
  • if the function that calls doSomething needs to wait for doSomething to finish it can add its own functions to the callback chain

Hope this helps... it will make a lot more sense after reading the sitepen article.

Lawrence Barsanti