Open jQuery UI Dialogs One After Another - jquery-ui

I have multiple jQuery UI dialogs that I would like to show one after another (one closes, the next in line opens). Currently, they all display modal, but one of the back ones is larger, and it looks bad/confusing in my opinion.
I would normally have the close functions of one dialog open the next, but these dialogs are called from separate functions, and they are kind of dynamic in the sense that not all of them are always displayed based on certain criteria.
I am contemplating a way to use $.Deferred, but am unsure if this would work as my understanding is it works more for things like AJAX calls.
Here is an (extremely) simplified example of how the code could be structured as-is.
<script>
function displayAlert1(){
$('<div/>', {text: 'Alert 1!'}).dialog({
modal: true,
autoOpen: true,
width: 400,
buttons: { OK: function(event, ui){ $(this).dialog('close'); } }
});
}
function displayAlert2(){
$('<div />', {text: 'Alert 2!'}).dialog({
modal: true,
autoOpen: true,
width: 200,
buttons: { OK: function(event, ui){ $(this).dialog('close'); } }
});
}
$(function(){
// These are actually met from data passed by AJAX
var condition1 = true;
var condition2 = true;
$('a').live('click', function(event, ui){
if(condition1) displayAlert1();
if(condition2) displayAlert2();
}
});
</script>
<!-- The links are actually dynamically produced from AJAX, thus the live() event handler -->
<a>Click Me!</a>
jsFiddle
My thinking is maybe I can have each alert function return a reference to the dialog element, or a $.Deferred object, but I'm not sure how to implement chaining from the main execution part (where the conditions are checked and the functions are called).
I would also like to make sure it chains to the next dialog no matter how the dialog before it is closed; whether by the X, by the 'close' method, or 'destroy' method.
Thank you for any input.

After thinking about the situation, I came up with the simplified method of using a stacked queue. I imagine I could have used the $.Deferred object, but it would be a little more complicated, and it essentially would be a stack in the end.
Below is my code. I basically initialized an array to use as my stack, and I will have each function push the dialog element into the stack. I bind into the close event of all future dialogs, and have it open the next one in the queue.
There are some obvious optimizations to do, but this is the barebones that works as I want.
function displayAlert1(){
return $('<div/>', {'class': 'alerts', text: 'Alert 1!'}).dialog({
modal: true,
autoOpen: false,
width: 400,
buttons: { OK: function(event, ui){ $(this).dialog('close'); } }
});
}
function displayAlert2(){
return $('<div/>', {'class': 'alerts', text: 'Alert 2!'}).dialog({
modal: true,
autoOpen: false,
width: 200,
buttons: { OK: function(event, ui){ $(this).dialog('close'); } }
});
}
$(function(){
// These are actually met from data passed by AJAX
condition1 = true;
condition2 = true;
// Dialog stack
dialogs = [];
$('a').live('click', function(event, ui){
if(condition1) dialogs.push(displayAlert1());
if(condition2) dialogs.push(displayAlert2());
// Grab the next dialog in queue
d = dialogs.shift();
// Check if it is valid, and open it
if(d && d.dialog){
d.dialog('open');
}
});
$('.alerts').live('dialogclose', function(event, ui){
// Grab the next dialog in queue
d = dialogs.shift();
// Check if it is valid, and open it
if(d && d.dialog){
d.dialog('open');
}
// Return false, or the close button (X) will glitch and re-create dialogs
return false;
});
});
jsFiddle

There are 2 things you can use to implement this:
1) have an identifier for each dialog ( you can add it as a 'id' attribute on the div)
2) listen to 'close' event on the dialog ( http://api.jqueryui.com/dialog/)
So, on the 'close' handler, you can check the current state, and based on that open/close the other dialogs.
Current State would be: which dialogs are currently open, and other params that you were using for condition1,condition2,etc.
http://jsbin.com/iwovob/1/

Related

Error: cannot call methods on dialog prior to initialization; attempted to call method 'open'

Just a little preface... I am fairly new to jQuery so if something looks wrong or redundant please feel free to offer any helpful suggestions.
Now for the issue. I have 2 modals that are initiated from 2 separate links on the page.
The first modal was fairly problem free. It is a simple form that posts back to the same page. If you are wondering what the items in the "close:" section are, they are form fields that I want to clear the values on when the dialog is closed.
Once I added the second one I have had problems. This modal calls a coldfusion page into a modal to display pictures. The problems occur after opening up the second one. I can not close the second modal from the "close" button. I get the following error.
Error: cannot call methods on dialog prior to initialization; attempted to call method 'close'
I have to close it from the "x" in the upper right hand corner of the modal. After I close it, I get an error when trying to open up the first on.
Error: cannot call methods on dialog prior to initialization; attempted to call method 'open'
Here is the code for it.
$(document).ready(function() {
$(".dig").click(function() {
//based on which we click, get the current values
var cItemName = $("#checklistItemName").attr( "title");
var c2id = $("#check2id").attr( "title");
$("#ItemName").html(cItemName);
$("#ItemID").html(c2id);
$("#objCheckItemName").val(cItemName);
$("#objCheck2ID").val(c2id);
console.log(cItemName);
console.log(c2id);
});
$( "#image-form" ).dialog({
autoOpen: false,
height: 450,
width: 650,
modal: true,
buttons: {
"Submit": function() {
$('#mForm').submit();
return true;
},
Cancel: function() {
$( this ).dialog( "close" );
}
},
close: function() {
$('#defaultSectionName')
.val('');
$('#defaultSectionDesc_hidden')
.val('');
$('#Photo')
.val('');
$('#objCheck2ID')
.val('');
$('#Check21')
.val('');
},
zIndex: 500
});
The next piece of code is where I believe the problems are occurring.
$( "#image_trigger" )
.click(function() {
$( "#image-form" ).dialog( "open" );
});
var dlg=$('#register').dialog({
title: 'Case Pictures',
resizable: true,
autoOpen:false,
modal: true,
hide: 'fade',
width:650,
height:450,
buttons: {
close: function() {
$( this ).dialog( "close" );
}
},
zIndex: 500
});
$('#reg_link').click(function(e) {
e.preventDefault();
var linkurl=('assets/includes/modalPictures.cfm' + '?'
+ 'id=' + $("#objCheck2ID").val()
);
dlg.load(linkurl, function(){
dlg.dialog('open');
});
});
jQuery UI: 1.10.1
jQuery: 1.9.1
Server Side: Coldfusion
The HTML is pretty extensive. If you need to see any part of it please let me know. Thanks for your help!
Upper case?
Close: function() {
You have to initialize your jquery dialog before calling the open function.
<script type="text/javascript">
$(document).ready(function () {
initializeDialog();
});
</script>
And change your js file to have the dialog code in initializeDialog() function.
function initializeDialog(){
$("#your-dialog-id").dialog({
autoOpen: false,
buttons: {
"Cancel": function() {
$(this).dialog("close");
}
},
modal: true,
resizable: false,
width: 600px,
height: 400px
});
}
Thanks #bpjoshi

Update jquery ui dialog from another jquery ui dialog

I have a jquery dialog and from this one, i open another dialog, where user insert some data. How can I update this user data from the second dialog to the first one, without closing them?
Is this possible? Are some examples in the web?
Thanks in advance
ok so this is my script, which opens the second dialog. I open this dialog with a link, which calls a function in my mvc controller, and this returns the partial view with the datas...
<script type="text/javascript">
$(document).ready(function () {
$("#dialog2").dialog({
bgiframe: false,
autoOpen: false,
height: 200,
resizable: false,
modal: true,
buttons: {
OK: function () {
$("#dialog2 > form").submit();
$(this).dialog('close');
},
Abbrechen: function () {
$(this).dialog('close');
}
}
});
$('#changePW').click(function () {
$('#dialog1').dialog('open')
});
});
</script>
#Roysvork: then I have to but this in the buttons OK function?
As a dialog is simply an html element underneath, you can still access said element using jQuery in the usual fashion:
var dialog1 = $("#dialog1");
var dialog2 = $("#dialog2");
dialog1.dialog("show");
dialog2.dialog("show");
So in your event handler for dialog 1 you can just do :
var value = dialog2.find("#inputbox").val();
dialog2.find("#textbox").val(value) ;
etc...

jQuery UI Dialog Will Not Close

Given the following script:
$(function () {
$(".editLink").button();
$('#editPersonDialog').dialog({
autoOpen: false,
width: 800,
resizable: false,
title: 'Edit Person',
modal: true,
buttons: {
"Save": function () {
$("#update-message").html('');
$("#updatePersonForm").submit();
},
"Close": function () {
$(this).dialog('close');
}
},
close: function (event, ui) {
$(this).dialog('close');
}
});
$(".editLink").click(function () {
var dialogDiv = $('#editPersonDialog');
var linkObj = $(this);
var viewUrl = linkObj.attr('href');
$.get(viewUrl, function (data) {
dialogDiv.html(data);
//validation
var $form = $("#updatePersonForm");
// unbind existing validation
$form.unbind();
$form.data("validator", null);
// check document for changes
$.validator.unobtrusive.parse(document);
// re-add validation with changes
$form.validate($form.data("unobtrusiveValidation").options);
// open dialog
dialogDiv.dialog('open');
});
return false;
});
});
function updateSuccess() {
if ($("#update-message").html() == "True") {
$('#editPersonDialog').dialog('close');
$("#commonMessage").html("Update Complete");
$("#commonMessage").delay(400).slideDown(400).delay(3000).slideUp(400);
}
else {
$("#update-message").show();
}
}
If I click the "X" button on the dialog the form closes fine. If I click the "Close" button then it does not close. I have verified that the code for the "Close" button is being called.
Both the "X" button and the "Close" button are both running the same statement: '$(this).dialog('close');'. Why would one work and the other not work?
As an aside the dialog will not open a second time unless I refresh the page. I imagine that these 2 problems may be related.
I have found many people with similar problems and a number of different solutions that worked for them. Unfortunately none of them worked for me.
Further Info:
The dialog displays a partial view in an Ajax form:
#using (Ajax.BeginForm("Edit", "Person", null,
new AjaxOptions
{
UpdateTargetId = "update-message",
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
OnSuccess = "updateSuccess"
},
new { #id = "updatePersonForm" }))
{
#Html.ValidationSummary(true)
<div id="update-message" class="hiddenDiv"></div>
<div class="blockGraygradient">
#Html.Partial("_CreateEditCommon")
#Html.HiddenFor(model => model.SelectedPerson.Id)
#Html.HiddenFor(model => model.SelectedPerson.RowVersion)
#Html.HiddenFor(model => model.SelectedPerson.CreateTime)
</div><p/>
}
Try using this instead.
$(this).dialog('destroy');
We had exactly the same problem. In the end, every time you re-opened the dialog it was actually re-injecting the dialog markup into the DOM. Then, when you click close (for the second time) it only closes the first occurrence of the dialog, but not necessarily the one that's open. You can check this using a run-time DOM inspector like FireBug or Chrome's built-in developer tools.
I found out that the cause of both problems (the close button not working and being unable to show the dialog more than once without refreshing the page) was that I had included references to my script files in both my main page and the partial view being displayed by the dialog. Once I removed the script references from the partial view the problems disappeared.
(As an aside this has now raised another problem to do with an Ajax update back onto the main page when the dialog is closed. I think this is the reason that I put the scripts into the partial view in the first place).
You have too much recursion. You don't need to subscribe to the close event of your jQuery dialog and invoke $(this).dialog('close'); inside it. Simply comment this line or remove completely the close event subscription:
$('#editPersonDialog').dialog({
autoOpen: false,
width: 800,
resizable: false,
title: 'Edit Person',
modal: true,
buttons: {
"Save": function () {
$("#update-message").html('');
$("#updatePersonForm").submit();
},
"Close": function () {
$(this).dialog('close');
}
}
});

How to get the event of the partialview button in a jQuery modal dialog

I have a partial view named xyz and I have a lot of buttons on it which implements different functionality.
$('#dialog').dialog({
autoOpen: false,
width: 700,
resizable: false,
modal: true,
open: function (event, ui) { $(this).load('<%=Url.Action("PushButton","Body",new {Parm="text",Parm1="Value"}) %>'); },
position: 'top'
});
I'm opening this partial view XYZ in a jQuery modal dialog box. I have some buttons in the partialview XYZ. I'm not getting how to fire the event explicitly. Like if I want to close the dialog box by click of the button created in Partialview.
You will need to wire the button events once the load is complete. You can add a callback to the load to notify you: http://api.jquery.com/load/
I had the same problem. I want my partial view to be independent and submit using Ajax. It's similar to creating a user control.
I am now planning to use a publisher/subscriber mechanism to listen to an event from my partial view. The parent can listen to this event and close the dialog box.
I came across Ben Alman's Pub/Sub gist.
Another good article for the observer pattern in JavaScript is Learning JavaScript Design Patterns, The Observer Pattern.
Here is the code for the callback on the load event:
$('#dialog').dialog({
autoOpen: false,
width: 700,
resizable: false,
modal: true,
open: function (event, ui) { $(this).load('<%=Url.Action("PushButton","Body",new {Parm="text",Parm1="Value"}) %>', function(){
$("#buttonId").click(function(){
//Stuff you want to do with the button here
});
}); },
position: 'top'
});
You can do this inside document.ready as well:
$(document).on('click', '#idOfControlInsideDialog', function() {
//Stuff you want to do here
});

How would I reference a dynamically created jQuery dialog box so I can close it programatically?

When I began using jQuery a little over a year ago, I needed to load remote content into a pop-up dialog box. After scouring the internet and trying out several suggested methods for doing this, I came upon a function that worked exactly as I needed it to. However, one problem I've never solved is how to reference the dynamic dialog box so it can be closed from an outside function.
Here's the function that creates the dialog box, appends it to the body, and then loads a page into it:
function openDynamicDialog() {
var url = 'mypage.cfm';
var dialog = $('`<div style="display:hidden"></div>`').appendTo('body');
$(dialog).dialog({
autoOpen: true,
title: 'My Title',
resizable: true,
modal: true,
width: 250,
height: 100,
close: function(ev, ui) {
$(this).remove(); // ensures any form variables are reset.
},
buttons: {
"Close": function(){
$(this).dialog("close");
}
}
});
// load remote content
dialog.load(
url,
{},
function (responseText, textStatus, XMLHttpRequest) {
dialog.dialog();
}
);
//prevent the browser from following the link
return false; };
I've considered giving that hidden div a hard-coded id value, but I'm not sure if there are drawbacks to that approach.
Any suggestions would be most appreciated.
I would use a hard-coded id value for the <div> element.
No there shouldn't be any drawback giving it an ID. If you fear of some kind of conflicts then you can give it a class instead, or save a reference to the div object in a global variable.
Well im not sure what the return false is at the end. so if you don't need that, do this:
function openDynamicDialog() {
var url = 'mypage.cfm';
var dialog = $('<div>').css('display','none').appendTo('body');
$(dialog).dialog({
autoOpen: true,
title: 'My Title',
resizable: true,
modal: true,
width: 250,
height: 100,
close: function(ev, ui) {
$(this).remove(); // ensures any form variables are reset.
},
buttons: {
"Close": function() {
$(this).dialog("close");
}
}
});
// load remote content
dialog.load(
url, {}, function(responseText, textStatus, XMLHttpRequest) {
dialog.dialog();
});
return dialog;
}
//call it like this:
var dialog = openDynamicDialog();
//..code
//close it:
dialog.dialog('close');
OR
if you still need that return false, you can do this on the var dialog line of the function:
var dialog = $('<div>', {id: 'dialog_id'}).css('display','none').appendTo('body');
and then reference it from the outside:
var dialog = $('#dialog_id');

Resources