jQuery modal dialog does not stop for user input - javascript

I am new to jQuery but have already implemented successfully several modal dialogs using the jqueryUI dialog widget. In trying to implement another one, the modal dialog opens, but the code continues on to execute without stopping for user input. Using jQuery 1.7.1 and jquery-ui-1.8.16.
Here is the definition of a "prototype" of the dialog (it is a "prototype" because it doesn't take the actions on the "OK" selection that would be needed to meet requirements):
var $confirm = $('#confirm');
$confirm.dialog(
{
autoOpen:false,
width:440,
modal:true,
buttons:
{
OK: function()
{
$( this ).dialog( 'close' );
},
Cancel: function()
{
$( this ).dialog( 'close' );
}
}
});
Here is some test code that opens the dialog:
[ some javascript that does error checking]
alert('stop1');
$('#confirm').dialog('open');
alert('stop2');
[ more javascript including submitting the form]
What happens is the the first alert displays. Upon clicking on it the dialog opens along with the second alert, indicating that the dialog is not waiting for user input. The second alert is modal and prevents the dialog from being accessed. When it is clicked on, the form submits. This sequence shows that the dialog is not waiting for user input.
I have looked and looked at my other successfully implemented modal dialogs and do not see what might be causing this one to fail.

The dialog won't wait. Instead you'll want to use this as a point to decide what you want to happen. So instead of including additional code that you may or may not want to run after the dialog modal, let that be the last part of the function.
Then, with your OK or Cancel functions, make the call there to continue on with the workflow if they chose ok, or just hide and do whatever cancel stuff needs to be done with the cancel.
In short, the modal dialog will not pause execution of the javascript, it will just run the code to open the modal and keep on going.

You should use a promise:
function deferredConfirm(message) {
$('<div></div>').html(message).dialog({
dialogClass: 'confirmDialog',
buttons:
[{
text: buttonText,
click: function () {
$(this).dialog("close");
defer.resolve();
}
},
{
text: buttonText2,
click: function () {
$(this).dialog("close");
defer.reject();
}
}],
close: function () {
$(this).remove();
}
});
return defer.promise();
}
And to call it:
deferredConfirm("Oh No!").then(function() {
//do something if dialog confirmed
});

Related

Close jQuery UI Dialog on mouse click outside of box

So I have some jQuery UI Dialogs and for user usability I think it would be best if users would be able to close the dialog box when clicking outside the box instead of having to click the small close button on the dialog box.
jQuery Code:
$(document).ready(function() {
var dlg=$('#createTeam').dialog({
title: 'Create a Team',
resizable: true,
autoOpen:false,
modal: true,
hide: 'fade',
width:600,
height:285,
clickOutside: true, // clicking outside the dialog will close it
clickOutsideTrigger: "#addEngineer",
close: function(event, ui) {
location.reload();
}
});
$('#createTeamLink').click(function(e) {
dlg.load('admin/addTeam.php');
e.preventDefault();
dlg.dialog('open');
});
});
Can anyone advise on what I need to add to the code above to be able to close the dialog box on mouse click outside of the box?
I'm not sure why the clickOutside : true property isn't working though I can provide a simple workaround. On the page with the modal, you can catch body click events like so:
$(document).click(function() {
dlg.dialog('close');
});
However, this will be ANY click event on the page, so we have to exclude clicking on the modal from firing this event handler. It seems you have already done this with e.preventDefault() however, so add the above code and it should work. A better solution would be to include a modal backdrop in your modal HTML, and catch click events on that. If you provide your HTML I'll give you an example of this.

Choosing to Continue or Not Continue after Clicking on Link

I am attempting to do something pretty simple: click on a link, modal pops up to continue or cancel to the link's URL, continue to the URL or cancel (essentially hide the modal). My issue is the "waiting" period when the modal pops up, when the user is prompted to continue or cancel. Right now, my code never seems to run past the first waitForModalEvent() call:
<a href="someURL" onclick='return handleClick()'> Click Here </a>
function handleClick() {
if (dataChanged()) {
returnValue = false;
displayModal();
returnValue = waitForModalEvent();
//never called at or past this point. Tested with alert()
return returnValue;
} else {
return true;
}
}
var continueClicked = false;
var cancelClicked = false;
function waitForModalEvent() {
while(!continueClicked && !cancelClicked) {
waitForModalEvent(); //I know this gives the browser some troubles
}
if (continueClicked) {
return true;
} else {
return false;
}
}
I know this code is faulty (especially the hideous waitForModalEvent() recursive call that never ends). However, I'm stuck at how to resolve this, and return true or false in handleClick() after the user clicks on either continue or cancel. Is my setup using the <a href>'s onclick inherently a bad setup for what I'm trying to accomplish?
I've read up on callbacks, but can't grasp how I could use callbacks for my situation (if any). Would appreciate any sort of suggestions or insight!
You've generated an infinite loop which locks up the JavaScript event loop. Until the while loop finished the variables you are testing in it can never changed.
If you want to do something based on a DOM based dialogue, you have to do it with callbacks. There is no way (outside of a host environment provided function like confirm) to block while waiting for a user interaction.
The general approach to using callbacks here would be to always cancel the default action of clicking the link, and then have the callback replicate its functionality (or just put a regular link in the dialogue).
Check this codepen for an illustration of callbacks and modal dialogues with jQuery UI:
http://codepen.io/anon/pen/KdaRmP
$('button.showModal').click(function() {
$( "#dialog-confirm" ).dialog({
resizable: false,
modal: true,
buttons: {
"Proceed to The Dividing Line": function() {
$( this ).dialog( "close" );
location.href='http://www.thedividingline.com/';
},
Cancel: function() {
$('DIV.output').text('Canceled.');
$( this ).dialog( "close" );
}
}
});
});
I used an example from jQuery UI docs here: https://jqueryui.com/dialog/#modal-confirmation (some things I needed to change).
EDIT
Now callback invokes a hyperlink.

How to create a dialog box that appears without any event triggered in jQuery?

I'm using jQuery 1.9.1, and jQuery Mobile 1.3.1, and I want to create a dialog box, with only one button, informing the user that their time is up in my game. The point is that, as long as I can see dialogs in jQuery appear after certain eventType. For example, after a button is clicked the dialog can appear. But in my situation I don't have any event, it must just appear automatically when the condition in the if statement is true. And when the user clicks OK button on the widget, he/she should be transferred to the page referred below. Any idea how to achieve it?
function showTimer() {
if (timestamp.getMinutes().pad(2) == "59" && timestamp.getSeconds().pad(2) == "59") {
// dialog goes here...
$.mobile.navigate("#finalPage");
}
return false;
}
It's all possible using jQuery:
//Initialise the dialog first
var dialog = $('<p>Are you sure?</p>').dialog({
autoOpen:false,
buttons: {
"Cancel": function () {
$.mobile.navigate("#finalPage"); // Your custom code for navigation on button click
}
}
});
setTimeout(function(){ // When your condition is met, just call the dialog using this code
dialog.dialog('open');
},2000);
Here,I have used timeout just to show how you can open the dialog at any stage without triggering any click.
Demo : http://jsfiddle.net/lotusgodkk/GCu2D/175/
start a timer with setInterval, and check the condition every x milliseconds

Remove beforeClose event handler - jQuery UI Dialog

I have a jQuery UI dialog box with a form inside it. I'm trying to implement a feature where if a field in the form has been modified, we'll be showing a confirmation message using noty
Now, unlike an javaScript confirmation box, noty does not stop script execution. So, in the dialog beforeClose event, I'm -
Showing a noty confirmation if form data is modified and then returning false.
Simply returning true if the form data has not been modified.
All is working well. Now we ask the user -
The data in the form has been modified. Are you sure you want to close?
If he clicks no - we simply close the noty and keep the dialog box open.
But if he clicks yes, we try to close the dialog box, which triggers the beforeClose event handler again and we go into the loop again.
I've tried calling .off on the div that has been converted to a dialog box before calling the close event, but that doesn't seem to be removing the click.
Here is a simple pseudo code to explain the issue -
DialogCloseEvent() {
if data has been modified {
Show noty {
// IMPORTANT - This is executed after return false.
in noty user clicks NO - do not close dialog box {
close noty and done
}
in noty user clicks YES - close the dialog box {
// This calls the DialogCloseEvent again.
call the close method of the dialog box.
close noty
}
}
return false
}
no it has not been modifed {
// Closes the dialog without calling the event again
return true;
}
}
Expanding on your pseudo code you could add a flag to force close the dialog:
var forceClose = false;
DialogCloseEvent() {
if data has been modified and !forceClose {
Show noty {
// IMPORTANT - This is executed after return false.
in noty user clicks NO - do not close dialog box {
close noty and done
}
in noty user clicks YES{
forceClose = true;
- close the dialog box {
// This calls the DialogCloseEvent again.
call the close method of the dialog box.
close noty
}
}
}
return false
}
no it has not been modifed {
// Closes the dialog without calling the event again
return true;
}
}
UPDATE with code
var forceClose = false;
$("#dialog").dialog({
open: function (event, ui) {
forceClose = false; //reset the flag each time
},
beforeClose: function (event, ui) {
if(forceClose){
return true;
}
//your dialog close event
//set the flag to true when you want to close the jqueryui dialog
}
});
According to the code for the close API for Jquery UI dialog, there is no way not to force close a dialog without firing events. Ideally there should be an API which just executes the functionality without triggering events. I tried just a way to enable this by replicating the method for now. Best way as an addition to the API itself. So the change is something on the lines of this,
// code from existing
if(!forceClose && this._trigger("beforeClose") === false){
return;
}
// continue with existing
Have a fiddle for the same here http://jsfiddle.net/Lj3Nk/1/
Going to submit a feature/pull request to jquery ui now. Will update with details when done. In the mean while, let me know if this helps.
UPDATE
Jquery ui ticket - http://bugs.jqueryui.com/ticket/9943
Pull request - https://github.com/jquery/jquery-ui/pull/1218
Example 1
Based on the flag approach:
var notyStatus = null;
$("#dialog").dialog({
beforeClose: function (event, ui) {
// possible values for notyStatus are
// null: preventDefault and show the warning
// else: do nothing and let the dialog close
if (notyStatus === null) {
event.preventDefault();
$('<p title="Replace me with noty">Close the dialog?</p>').dialog({
modal: true,
buttons: {
"Close": function () {
notyStatus = true;
$(this).dialog("close");
$("#dialog").dialog("close");
},
"Keep Open": function () {
$(this).dialog("close");
}
}
});
}
}
});
Demo 1
Example 2
Remove the beforeClose event handler. You can use .dialog("option", "beforeClose") to get, set or unset the event handler. The code looks like this:
$("#dialog").dialog({
beforeClose: function (event, ui) {
event.preventDefault();
$('<p title="Replace me with noty">Close the dialog?</p>').dialog({
modal: true,
buttons: {
"Close": function () {
$(this).dialog("close");
$("#dialog")
.dialog("option", "beforeClose", null)
.dialog("close");
},
"Keep Open": function () {
$(this).dialog("close");
}
}
});
}
});
Demo 2
In both examples, replace the inner jQuery UI confirmation dialog code with noty. It allows you to create action buttons with callbacks so the code will be similar.
You can use the dialog widget's "option" method to change or remove the beforeClose event handler.
So when the user clicks 'yes', you could get the dialog to close by executing:
$('#myDialog')
.dialog('option', 'beforeClose', function() {})
.dialog('close');
Here's a fiddle that shows how it works: http://jsfiddle.net/BrDE7/1/
Jquery UI documentation on the "option" method: http://api.jqueryui.com/dialog/#method-option

How can I provide a hook in a jQuery ui dialog button click?

I don't know much about writing good javascript so perhaps I am thinking about this in the wrong way, but here is the situation.
I have a page which contains various plugins, each with an edit button.
So there is for example an HTML plugin, a Twitter plugin etc.
Once you click on the edit button a jQuery UI dialog box is displayed via a common function which all of the edit buttons call.
The content of the dialog is filled with that particular plugin's update form.
The dialog created by this common function also provides a "Save" and a "Cancel" button automatically.
Since both of these "Save" and "Cancel" buttons are created by the dialog they are both assigned closures to the "click" option.
What I want to do, if possible, is provide some sort of hook function which can be run when the "Save" button is clicked, which can be defined by the javascript in each of the plugin's update forms.
I think I have explained enough now so here is some sample code:
This would tell each of the edit buttons to create a dialog box and fill it with the appropriate content.
// This function is called by each edit button
// on a click event which passes the required ids
function update_form_dialog(plugin_id) {
$.post(
'/get_plugin_update_form',
{
'plugin_id': plugin_id
},
function(response) {
var dialog = $('<div class="update_form"></div>').appendTo('body');
dialog.dialog({
open: function() {
dialog.html(response);
},
show: 'fade',
modal: true,
title: 'Update plugin',
width: 'auto',
height: 'auto',
buttons: [
{
text: 'Save',
click: function() {
// Call a hook defined in the plugin update
// form then send update data
}
},
{
text: 'Cancel',
click: function() {
// Close the dialog here
}
}
]
});
}
);
}
As you can see in the above code what I have is pretty simple, but I don't know how I can add a hook to the start of the "Save" button's click function.
Each plugin's update form is stored in the response variable and that is where the plugin update form's javascript is written.
Is there a way that I can tell the save button what to do before it runs its normal code when the "Save" button is clicked?
If anyone needs more explanation please let me know.
Any help on how I could write this would be much appreciated.
Edit:
It seems I'm having trouble explaining my problem so hopefully this edit will help make things clearer.
What I want is to execute some code which would be optionally defined in the content of the dialog box when it has been opened. This code, if defined, should be executed once the save button is clicked but before the actual click function is executed. Is this possible?
You can use a plugin for subscribing and attaching to some events like:
http://weblog.bocoup.com/publishsubscribe-with-jquery-custom-events/
http://archive.plugins.jquery.com/project/jQuerySubscribe
http://www.novasoftware.com/download/jquery/publish-subscribe.aspx
This way, on the save you can publish that the save has been done and all subscribers code will be executed.
with the third link you can do something like the following:
$(document).ready(function(){ $('.save').subscribe('save',function(){//dosomething;}})
Later on the save code you can do this:
$.publish('save');
And the code will be executed
hope it helps.
You're close!
buttons: {
'Save': function() {
// Call a hook defined in the plugin update
var code = $('textarea#input').val();
eval(code);
// form then send update data
$('form').submit();
// $.ajax({....
},
'Cancel': function() {
// Close the dialog here
}
}

Categories

Resources