Why won't my jQuery-ui modal dialog display two custom buttons? - javascript

I have a generic Javascript function for displaying a jQuery-ui modal dialog with two buttons -- essentially "Continue" and "Cancel", though the text varies. I'm calling it in three places in my application. What's happening is that only the second button, the "Cancel" button is being displayed. Here's the function: (String.Format is an external function I always use since Javascript doesn't have one built-in - I know it isn't the problem.)
function DisplayModalDialog(titleText, bodyText, continueText, cancelText) {
//add the dialog div to the page
$('body').append(String.Format("<div id='theDialog' title='{0}'><p>{1}</p></div>", titleText, bodyText));
//create the dialog
$('#theDialog').dialog({
width: 400,
height: "auto",
modal: true,
resizable: false,
draggable: false,
close: function (event, ui) {
$('body').find('#theDialog').remove();
$('body').find('#theDialog').destroy();
},
buttons: [
{
text: continueText,
click: function () {
$(this).dialog('close');
return true;
},
text: cancelText,
click: function () {
$(this).dialog('close');
return false;
}
}]
});
return false;
}
And here's a snippet showing how I'm calling it:
if(CheckFormDataChanged() {
var changeTitle = "Data has been changed";
var changeText = "You have updated information on this form. Are you sure you wish to continue without saving?";
var changeContinue = "Yes, continue without saving";
var changeCancel = "No, let me save";
if (DisplayModalDialog(changeTitle, changeText, changeContinue, changeCancel)) {
if (obj) obj.click();
return true;
}
}
What's wrong with my function (or the call)?
UPDATE: Here's what I'm working with now. I realized that on one of the modal dialogs I didn't need a cancel button, just an acknowledge button:
function DisplayModalDialog(titleText, bodyText, continueText, cancelText, suppressCancel) {
var def = new $.Deferred();
//add the dialog div to the page
$('body').append(String.Format("<div id='theDialog' title='{0}'><p>{1}</p></div>", titleText, bodyText));
//create the button array for the dialog
var buttonArray = [];
buttonArray.push({ text: continueText, click: function () { $(this).dialog('close'); def.resolve(); } });
if (!suppressCancel) {
buttonArray.push({ text: cancelText, click: function () { $(this).dialog('close'); def.reject(); } });
}
//create the dialog
$('#theDialog').dialog({
... dialog options ...
close: function (event, ui) { $('body').find('#theDialog').remove(); },
buttons: buttonArray
});
return def.promise();
}
And the usage:
DisplayModalDialog(changeTitle, changeText, changeContinue, changeCancel, false)
.done(function () { if (obj) obj.click(); return true; })
.fail(function () { return false; });
Just to give you some context, obj is an ASP.Net Button being passed to the client-side function; if the function returns true, the server-side OnClick event is triggered; if false, it isn't. In this case, the server-side OnClick advances to the next tab in a TabContainer (among other things). What's happening is that it's moving to the next tab anyway, even though I'm returning false in the fail() function.

Your curly braces are off:
[{
text: continueText,
click: function () {
$(this).dialog('close');
return true;
}
}, {
text: cancelText,
click: function () {
$(this).dialog('close');
return false;
}
}]
As you have it, you only have one object in your buttons array.

I can't tell yet why the button doesn't display EDIT, ah, yes I can, there's a missing curly brace.
What I can tell you that your return lines simply won't work.
The dialog box gets displayed, your function returns immediately, and processing continues, so the click callback return values are completely ignored.
What you can do instead is return a promise:
function DisplayModalDialog(titleText, bodyText, continueText, cancelText) {
var def = $.Deferred();
...
buttons: [
{
text: continueText,
click: function () {
$(this).dialog('close');
def.resolve();
}
},
{ // ah - here's your button bug - a missing brace
text: cancelText,
click: function () {
$(this).dialog('close');
def.reject();
}
}
...
return def.promise();
}
with usage:
DisplayModalDialog(changeTitle, changeText, changeContinue, changeCancel)
.done(function() {
// continue was clicked
}).fail(function() {
// cancel was clicked
});

Related

How to prevent closing bootbox while using async function?

What I'm trying to get is if an user gets any validation error, then bootbox will show that "this is required". Till now, I've achieved this. But the main problem is that - it closes the window of boot box if the user clicks "Yes" button.
I'm getting this because I had to use g async callback in bootbox. For this reason, even after returning false, the bootbox is closing. But I want users to show the box until they press the cancel button. If they click Yes, then it should show the validation, with the box opened. This is my code:
bootbox.confirm({
message: 'Test',
buttons: {
confirm: {
label: 'Yes',
className: 'btn-primary'
},
cancel: {
label: 'No',
className: 'btn-danger'
}
},
callback: async function (result) {
var isValid = $('#form').valid();
if (result && !isValid) {
return false; //it's not working. It's closing the bootbox
}
if (result && isValid) {
/* for this await function I had to use async callback,
without this bootbox is opend
*/
var data = await self.createData();
$.ajax({
type: "POST",
success: function (result) {
},
}).then(function () {
});
}
}
});
How can I resolve this?
It does not appear to me that bootbox.confirm() has any sort of support for async callbacks like you are trying to use. The bootbox closes when your callback returns which will be at the point you hit your first await unless you explicitly return false, but an async callback function ALWAYS returns a promise which is not explicitly false. You cannot change that.
What you can do is make your callback a regular callback function, not async that can return false if validation fails and then create an embedded async function where you can use await that you call from within that first callback like is shown below. Note that the bootbox will close before your asynchronous code completes so if there are any errors in the bootbox code, you will need to new way to present those errors, perhaps putting up a new bootbox. Here's one way to do this code while still using await.
bootbox.confirm({
message: 'Test',
buttons: {
confirm: {
label: 'Yes',
className: 'btn-primary'
},
cancel: {
label: 'No',
className: 'btn-danger'
}
},
callback: function (result) {
var isValid = $('#form').valid();
if (result) {
if (!isValid) {
// keep prompt open until user presses Cancel
return false;
}
async function run() {
const data = await self.createData();
const result = await $.ajax({ ... });
// do something with result
}
// now call async function here (dialog will close)
run().catch(err => {
// do something with an error here
console.log(err);
});
}
return true;
}
});
Alternatively, you could avoid using await and only use .then() and .catch() and then you wouldn't need this extra layer of function:
bootbox.confirm({
message: 'Test',
buttons: {
confirm: {
label: 'Yes',
className: 'btn-primary'
},
cancel: {
label: 'No',
className: 'btn-danger'
}
},
callback: function (result) {
var isValid = $('#form').valid();
if (result) {
if (!isValid) {
// keep prompt open until user presses Cancel
return false;
}
self.createData().then(data => {
return $.ajax({ ... }).then(result => {
// do something with result
});
}).catch(err => {
// do something with error here
console.log(err);
});
}
return true;
}
});

Wait for modal window to close and then execute the following lines in javascript

I have a modal Window which pops up and wait for 5 seconds and then closes.
The code is as follows
function callMe()
{
//alert("entering");
$("#dialog").dialog({
modal: true,
//title: "Confirm",
resizable: false,
width: 300,
height: 150,
open: function (event, ui)
{
setTimeout(function () { $("#dialog").dialog("close");}, 5000);
},
buttons: {
Ok: function () {
// $(this).dialog("close"); //closing on Ok
},
Cancel: function () {
// $(this).dialog("close"); //closing on Cancel
}
}
});
alert("Some Text");
}
callMe() function is called on load of the HTML file. Here I want to show the alert message "Some Text" after the modal window closes in 5 second. But every time when I run this it shows both the modal window and alert box together. I want the modal window to display first , wait for 5 sec and then show the alert box.I tried using sleep but its still coming the same way.
You have 2 options
function callMe()
{
//alert("entering");
$("#dialog").dialog({
modal: true,
//title: "Confirm",
resizable: false,
width: 300,
height: 150,
open: function (event, ui)
{
setTimeout(function () { $("#dialog").dialog("close");}, 5000);
},
buttons: {
Ok: function () {
// $(this).dialog("close"); //closing on Ok
},
Cancel: function () {
// $(this).dialog("close"); //closing on Cancel
}
},
close: function(){
alert("Some Text");
}
});
$('#dialog').on('dialogclose', function(event) {
alert('Some Text');
});
}
USE "close" method
use on dialogueClose event both examples are given in code above
It would be nicer if you can tell us what plugin you use for the dialog. I'm guessing the dialog has a close option that accepts a function. So try this:
...
open: function (event, ui)
{
setTimeout(function () { $("#dialog").dialog("close");}, 5000);
},
close: function() {
alert("Some Text");
},
...
You can put the alert inside the setTimeout, just after you close the window.
JAVASCRIPT
open: function (event, ui)
{
setTimeout(function () {
$("#dialog").dialog("close");
alert("Some Text");
}, 5000);
},

Replace javascript confirm by jquery confirm

I use the following code to use default javascript confirm by jquery ui dialogue.
jQuery.extend({
confirm: function(message, title, okAction) {
jQuery("<div></div>").dialog({
// Remove the closing 'X' from the dialog
open: function(event, ui) { jQuery(".ui-dialog-titlebar-close").hide(); },
buttons: {
"Ok": function() {
jQuery(this).dialog("close");
return true;
},
"Cancel": function() {
jQuery(this).dialog("close");
return false;
}
},
close: function(event, ui) { jQuery(this).remove(); },
resizable: false,
title: title,
modal: true
}).text(message);
}
});
jQuery.confirm(
"LogOut",
"Do you want to log out",
function() {
});
Now I need to use this same code in a log out action. So that I can replace the javascript confirm in the code.
<a class="homeImage" onclick="return confirm('Do you want to logout?');" href="/future/myhome/head?$event=logout">LOG OUT</a>
The problem I am facing now is, when I replace the confirm with another function and wait for its return value to make the decision, the dialogue box doesn't return the value to a variable. These two functions are executed simultaniously(its showing the alert, but it also get directed to the href target). Is there any way that the method can return a true or false value and hence proceed to the href target.
reference: jQuery Extend,jQuery UI Replacement for alert
related question : js override confirm
I don't know if you could actually do that as the jQuery.dialog function is asynchronous.
You could use a promise library to setup the button click events. But then you cannot simply specify a method in the onclick attribute and have to do it through code
var d = jQuery.Deferred();
d.resolve(true); // resolve is used then to mark the function as complete
return d.promise(); // return the promise
jsFiddle
jQuery.extend({
confirm: function(message, title, okAction) {
var d = jQuery.Deferred();
jQuery("<div></div>").dialog({
// Remove the closing 'X' from the dialog
open: function(event, ui) { jQuery(".ui-dialog-titlebar-close").hide(); },
buttons: {
"Ok": function() {
jQuery(this).dialog("close");
d.resolve(true);
return true;
},
"Cancel": function() {
jQuery(this).dialog("close");
d.resolve(false);
return false;
}
},
close: function(event, ui) { jQuery(this).remove(); },
resizable: false,
title: title,
modal: true
}).text(message);
return d.promise();
}
});
For more info about jQuery promise library see jQuery reference
Edit: Another way to to set it up: jsFiddle
The problem is that default confirm dialog is synchronus and block the whole browser UI. JQuery dialog is asynchronous and does not block UI (because it needs it to render).
So the answer to your problem is following. You need to change:
buttons: {
"Ok": function() {
window.location = "/future/myhome/head?$event=logout"
},
and
<a class="homeImage" onclick="return jQuery.confirm('Do you want to logout?');return false;" href="/future/myhome/head?$event=logout">LOG OUT</a>
Personally, I use confirm more for conditional execution of a function or posting a form...
So, using your example, I'd have made the following small changes:
buttons: {
"Ok": function() {
jQuery(this).dialog("close");
okAction();
},
And then called the Confirm as follows:
onclick="jQuery.confirm('Do you want to logout?','Confirm:',function(){window.location='/future/myhome/head?$event=logout'}); return false;">LOG OUT</a>

jQueryUI Dialog with Ajax Form Won't Close with $(this).dialog("close");

I have a jQueryUI Dialog loading up a form from an external url, the form renders fine and posts ok but neither the save or cancel buttons seem to close the form yet the dialog close icon does it's job just fine.
Here is my script that spawns the dialog and should handle the buttons:
$(function () {
$('a.modal').on('click', function() {
var href = $(this).attr('href');
$("#modalAdd").html("")
.dialog({
title: $(this).attr("title"),
width: 400,
height: 300,
buttons: {
"Save": function() {
$.post(href,
$("form").serialize(),
function() {
$(this).dialog("close");
});
},
Cancel: function() {
$(this).dialog("close");
}
}
})
.load(href, function() {
$(this).dialog("open");
});
return false;
});
});
The final solution was to declare the variable outside of the scope of the dialog declaration as follows:
$(function () {
$('a.modal').on('click', function() {
var href = $(this).attr('href');
var modal = $("#modalAdd");
modal.html("")
.dialog({
title: $(this).attr("title"),
width: 400,
height: 300,
buttons: {
"Save": function() {
$.post(href,
$("form").serialize(),
function() {
modal.dialog("close");
});
},
Cancel: function() {
modal.dialog("close");
}
}
})
.load(href, function() {
**modal**.dialog("open");
});
return false;
});
});
It's because of variable scope, as soon as you start the call back function for the $.post call, this is no longer the dialog box. Try calling $("#modalAdd").dialog('close'); instead.
If you don't mind expanding your $.post() and $.load() calls, you can set the context of this to a certain element using the full $.ajax() method. See the "context" option in the docs.
this is changed in the ajax callback function, you need to cache to a local variable.
"Save": function () {
var $this = $(this);
$.post(href, $("form").serialize(), function () {
$this.dialog("close");
});
},

Conditional If statements within jQueryUI's options?

I have a JavaScript function that I'm passing an argument to, that opens a jQueryUI Dialog. I want the dialog to have either one or two buttons, based on the value of the argument. How should I do this?
So far I've tried:
function foo(hasFile) {
$('#dialog').dialog({
buttons: {
Close: function() { $(this).dialog('close'); },
if (hasFile)
"Download": // do something
}
});
}
and
function foo(hasFile) {
$('#dialog').dialog({
buttons:
if (hasFile)
{
"Download": // do something
Close: function() { $(this).dialog('close'); }
}
else
{
Close: function() { $(this).dialog('close'); }
}
});
}
both of which have thoroughly broken my page.
buttons is a JavaScript literal object. You could do something like this:
function foo(hasFile) {
var buttons = {
Close: function() { $(this).dialog('close'); }
};
if (hasFile) {
buttons.Download = function(){
// Do something.
};
}
$('#dialog').dialog({
buttons: buttons
});
}
A general way to do that is like this:
foo.dialog({
// ...
buttons: (function() {
function CloseHandler() {
// close ...
};
function DownloadHandler() {
// download ...
};
return condition ?
{ "Download": DownloadHandler, "Close": CloseHandler } :
{ "Close": CloseHandler };
})(),
// ...
});
The idea is that you create a function where you can make decisions, and then return the result you decide upon.

Categories