Showing Bootstrap modal dialogs in sequence - javascript

I have a Bootstrap modal dialog, which when Yes is selected returns a resolved promise. Upon the promise being resolved, the modal should be displayed again. The line to display the modal is hit, but the modal does not display. What am I doing wrong?
$(function() {
showModalDialog('Confirm1', "Select Yes or No", 'Yes', 'No')
.done(function() {
alert('You selected Yes once!');
showModalDialog('Confirm2', "Select Yes or No", 'Yes', 'No')
.done(function() {
alert('You selected Yes twice!');
});
});
});
function showModalDialog(title, message, button1Caption, button2Caption) {
var deferred = $.Deferred();
$('#modalTitle').html(title);
$('#modalMessage').html(message);
$('#modalButton1').html(button1Caption);
$('#modalButton2').html(button2Caption);
$('#modalButton1').one('click', function() {
deferred.resolve();
});
$('#modalButton2').one('click', function() {
deferred.reject();
});
$('#modalDialog').one('hidden.bs.modal', function() {
//remove the handler for the button in case it was never invoked, otherwise it will
//still be there the next time the dialog is shown
$('#modalButton1').off('click');
deferred.reject();
})
$('#modalDialog').modal();
return deferred.promise();
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div class="modal fade" id="modalDialog" tabindex="-1" role="dialog" aria-labelledby="modalTitle" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<!--<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>-->
<h4 class="modal-title" id="modalTitle"></h4>
</div>
<div class="modal-body" id="modalMessage"></div>
<div class="modal-footer">
<button type="button" id="modalButton1" class="btn btn-default" data-dismiss="modal"></button>
<button type="button" id="modalButton2" class="btn btn-default" data-dismiss="modal"></button>
</div>
</div>
</div>
</div>

Blame the animations! :)
The animation of the hiding modal takes some finite time to complete. If you try to "show" the modal again during this time, it will not work. A simple workaround is to delay the "show" action slightly.
For example, delaying it by one second will work just fine:
setTimeout(function() {
showModalDialog('Confirm2', "Select Yes or No", 'Yes', 'No')
.done(function() {
alert('You selected Yes twice!');
});
}, 1000);
$(function() {
showModalDialog('Confirm1', "Select Yes or No", 'Yes', 'No')
.done(function() {
alert('You selected Yes once!');
setTimeout(function() {
showModalDialog('Confirm2', "Select Yes or No", 'Yes', 'No')
.done(function() {
alert('You selected Yes twice!');
});
}, 1000);
});
});
function showModalDialog(title, message, button1Caption, button2Caption) {
var deferred = $.Deferred();
$('#modalTitle').html(title);
$('#modalMessage').html(message);
$('#modalButton1').html(button1Caption);
$('#modalButton2').html(button2Caption);
$('#modalButton1').one('click', function() {
deferred.resolve();
});
$('#modalButton2').one('click', function() {
deferred.reject();
});
$('#modalDialog').one('hidden.bs.modal', function() {
//remove the handler for the button in case it was never invoked, otherwise it will
//still be there the next time the dialog is shown
$('#modalButton1').off('click');
deferred.reject();
})
$('#modalDialog').modal();
return deferred.promise();
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div class="modal fade" id="modalDialog" tabindex="-1" role="dialog" aria-labelledby="modalTitle" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<!--<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>-->
<h4 class="modal-title" id="modalTitle"></h4>
</div>
<div class="modal-body" id="modalMessage"></div>
<div class="modal-footer">
<button type="button" id="modalButton1" class="btn btn-default" data-dismiss="modal"></button>
<button type="button" id="modalButton2" class="btn btn-default" data-dismiss="modal"></button>
</div>
</div>
</div>
</div>
Note: I haven't checked the source code or experimented with these modals enough to know the minimum amount of delay required to make this work. But I don't mind a delay of one second anyway as it is barely noticeable.
Update
As you suggest, waiting for Bootstrap's hidden.bs.modal event is a better in this case. As described in the v3 Docs here:
This event is fired when the modal has finished being hidden from the user (will wait for CSS transitions to complete).
So moving the promise.resolved to the event handler for hidden.bs.modal would also do the trick.
To do that, I've added a variable modalResult which keeps track of user's choice, and triggers deferred.resolve or deferred.reject accordingly.
$(function() {
showModalDialog('Confirm1', "Select Yes or No", 'Yes', 'No')
.done(function() {
alert('You selected Yes once!');
showModalDialog('Confirm2', "Select Yes or No", 'Yes', 'No')
.done(function() {
alert('You selected Yes twice!');
});
});
});
function showModalDialog(title, message, button1Caption, button2Caption) {
var modalResult = false;
var deferred = $.Deferred();
$('#modalTitle').html(title);
$('#modalMessage').html(message);
$('#modalButton1').html(button1Caption);
$('#modalButton2').html(button2Caption);
$('#modalButton1').one('click', function() {
// Wait for the modal to get hidden.
// deferred.resolve();
modalResult = true;
});
$('#modalButton2').one('click', function() {
// Wait for the modal to get hidden.
// deferred.reject();
modalResult = false;
});
$('#modalDialog').one('hidden.bs.modal', function() {
//remove the handler for the button in case it was never invoked, otherwise it will
//still be there the next time the dialog is shown
$('#modalButton1').off('click');
if(modalResult) {
deferred.resolve();
} else {
deferred.reject();
}
})
$('#modalDialog').modal();
return deferred.promise();
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div class="modal fade" id="modalDialog" tabindex="-1" role="dialog" aria-labelledby="modalTitle" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<!--<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>-->
<h4 class="modal-title" id="modalTitle"></h4>
</div>
<div class="modal-body" id="modalMessage"></div>
<div class="modal-footer">
<button type="button" id="modalButton1" class="btn btn-default" data-dismiss="modal"></button>
<button type="button" id="modalButton2" class="btn btn-default" data-dismiss="modal"></button>
</div>
</div>
</div>
</div>

Related

bootstrap modal window not closed immediately after 'Yes' button is clicked

I have a bootstrap modal window that I am using in my ASP.NET MVC application.
This modal window is parametrized, I can specify title and message text.
Below is the modal window, MyConfirmModalDialog.cshtml:
<div class="modal fade" id="confirmModalDialog" tabindex="-1" role="dialog" aria-labelledby="modalCenterTitle" aria-hidden="true"
style="padding:0px;margin-left:0px;left:42%;min-width:15%">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="modalTitle">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"
style="margin-top:-30px">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Modal body
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" id="confirmCancel">No</button>
<button type="button" class="btn btn-primary" id="confirmOk">Yes</button>
</div>
</div>
</div>
</div>
This modal window is placed within another view using razor helper:
#Html.Partial("MyConfirmModalDialog");
Then I use it like below to show it to the user:
showConfirmation = function (title, message, success, cancel) {
var modal = $("#confirmModalDialog");
modal.find(".modal-title").html(title).end()
.find(".modal-body").html(message).end()
.modal({ backdrop: 'static', keyboard: false });
var fClose = function () {
modal.modal("hide");
};
modal.modal("show");
$("#confirmOk").unbind().one('click', success).one('click', fClose);
$("#confirmCancel").unbind().one("click", fClose);
};
function onPerformActions() {
var title = "Warning";
var message = "Do you wish to continue?";
var success = function () {
performActions();
};
var cancel = function () {
// Do nothing
};
showConfirmation(title, message, success, cancel);
}
If user clicks on 'Yes' button, from success function I call the method peformActions as above code shows. Below method performActions, basically in performs an ajax asynchronous call to an action in the controller:
function performActions()
{
$.ajax({
url: '#Url.Action("DoActions", "MyController", new { area = "MyArea" })',
type: "POST",
async: true,
success: function (resp) {
// Do some things on success
},
error: function () {
// Do some things on error
}
});
}
The problem I have is that modal window is not closed immediately when user clicks on 'Yes' button, it takes some seconds, and then this modal window is overlapped with the next modal window that is shown afterwards in the process.

Is there a way to get e.relatedTarget of bootstrap modal in document.ready ()?

I have two buttons that invoke the same modal, I have set data-button attribute to detect which button invoked the modal.
<button type="button" id="another" data-toggle="modal" data-target="#modal" class="btn btn-warning" data-button='another'>Add another</button>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#modal" data-button="lab">Add lab</button>
what I wanted to do is to change a label inside a modal depending on the button invoker. I did so :
<script>
$('#modal').on('show.bs.modal', function(e) {
var $trigger = $(e.relatedTarget);
$('#vv_type').val($trigger.data('button'));
v_type = $trigger.data('button');
if (v_type == 'lab') {
$('#ModalLabel').html('changed label');
$("label[for='id_date_of_label']").html('label inside modal changed');
}
})
</script>
it works as expected only the first time when modal is shown , and after that the same changed label is always displayed whenever I click on the buttons, and this is logic due to $('#modal').on('show.bs.modal', function (e) {
Is there a way to declare v_type variable and send it to document.ready() function so that I make sure that the script will run every time I click on buttons invoking the modal (not only the first time?)
Your original code still works for me. The only part missing is the else condition for if (v_type == 'lab') {. I can see the label change on each button click.
$('#myModal').on('show.bs.modal', function (e) {
var $trigger = $(e.relatedTarget);
//$('#vv_type').val($trigger.data('button'));
v_type = $trigger.data('button');
if (v_type == 'lab') {
$('#buttonText').html(v_type);
//$("label[for='id_date_of_label']").html('label inside modal changed');
}
else
{
$('#buttonText').html(v_type);
//$("label[for='id_date_of_label']").html('label inside modal changed');
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<button type="button" data-button="lab" class="btn btn-info btn-lg" data-toggle="modal" data-target="#myModal">Open Modal</button>
<button type="button" data-button="lab 123" class="btn btn-info btn-lg" data-toggle="modal" data-target="#myModal">Open Modal</button>
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<p id="buttonText"></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
I have solved this by getting the data-button from a hidden input vv_type on the modal (my modal has already a form in it ) and I added this script which is ran each time a modal is shown:
<script>
$(document).ready(function () {
$('.modal').on('show.bs.modal', function (e) {
if ($('#vv_type').val() == 'lab') {
$('#ModalLabel').html('changed label');
$("label[for='id_date_of_label']").html('label inside modal changed');
}
else {
$('#ModalLabel').html('origin label');
$("label[for='id_date_of_label']").html('label inside modal origin');
}
});
});
</script>

Submit confirmation via Bootstrap Modal

I wanted to have a Submit Modal Confirmation But I have failed to do it correctly.
Here is my JS:
function warning(){
$('#ModalSubmitCart').modal('show');
var yes = document.getElementById('confirm').value;
if (yes == 'yes') {
return true;
}
else {
return false;
}
}
part of my modal:
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary" id="confirm" value="yes">Yes</button>
</div>
my form
<form onSubmit="return warning()" method="POST" action="submitcart.php">
I wanted to have something like confirm() but in a Modal form.
There is no direct callback functions for the bootstrap modal.
I have done a slight hack here.
What I have done:
Added a class to both the buttons on the modal.
Attached a click callback handler for the buttons & verify by the textof the button whether a close button is or yes button .
JS Code:
$(function () {
$('#show').on('click', function () {
console.log('clicked');
warning();
});
$('.buttons').on('click', function () {
var yes = $(this).text();
if (yes === 'Yes') {
console.log('yes');
//return true;
} else {
console.log('close');
//return false;
}
});
});
function warning() {
$('#ModalSubmitCart').modal('show', function (data) {
console.log('data:' + data);
});
}
Live Demo # JSFiddle:http://jsfiddle.net/dreamweiver/wccqyzej/
You can wrap your modal in a FORM and use a submit button, as you're doing.
<form action="/echo/html/" method="POST" name="modalForm" id="modalForm">
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content panel-warning">
<div class="modal-header panel-heading">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Modal title</h4>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</form>
and use jQuery to intercept the submit event.
$('#modalForm').on('submit', function(e){
if (!confirm('are you sure?'))
{
e.preventDefault();
return false;
}
});
You can see how it works in this fiddle.
I think you should use this way your jquery code
function warning(){
$('#ModalSubmitCart').modal('show');
var yes = $('#confirm').attr("value");
if (yes == 'yes') {
return true;
}
else {
return false;
}
}

Rails4 - why hidden.bs.modal is not firing?

I have bootstrap 3.3.1 in my gemfile. Did bundle install.
I have the following in my view
<div class="row text-center">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://apis.google.com/js/platform.js" async defer></script>
<button type="button" class="btn mybtn-primary" data-toggle="modal" data-target="#myModal">
Start Practice Group
</button>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h4 class="modal-title" id="myModalLabel">Select Language</h4>
</div>
<div class="modal-body">
<button type="button" class="btn" data-dismiss="modal">Close</button>
<button type="button" class="btn" id="submit_form">Submit</button>
<!--<div class='modal-body1'>-->
<!-- <h3>Close and open, I will be gone!</h3>-->
<!--</div>-->
</div>
<div class="modal-body2">
<div id="placeholder-div1">
</div>
</div>
<div class="modal-footer">
</div>
<script type="text/javascript">
var render_button = function() {
var data = $('#lang').val() + " " + $('#level').val();
console.log(data);
gapi.hangout.render('placeholder-div1', {
'render': 'createhangout',
'initial_apps': [{'app_id' : '1097853', 'start_data' : $('#lang').val() + " " + $('#level').val(), 'app_type' : 'ROOM_APP' }]
});
}
$(function(){
$('#submit_form').click(function(){
console.log("Submitted");
render_button();
});
});
// $(function(){
// $('#myModal').on('hidden.bs.modal', function (e) {
// console.log("Modal hidden");
// $("#placeholder-div1").html(" ");
// });
// });
$(document).ready(function() {
console.log("Document Loaded");
$('#myModal').on("hidden.bs.modal", function() {
console.log("Modal hidden");
$(".modal-body1").html("Where did he go?!?!?!");
});
});
$(document).ready(function() {
$('#myModal').on('hidden.bs.modal', function () {
alert('hidden event fired!');
});
$('#myModal').on('shown.bs.modal', function () {
alert('show event fired!');
});
});
</script>
</div>
</div>
</div>
</div>
The modal shows and closes perfectly.
But the following is not getting triggered.
$('#myModal').on("hidden.bs.modal", function() {
console.log("Modal hidden");
$(".modal-body1").html("Where did he go?!?!?!");
});
and also
alert('hidden event fired!');
alert('show event fired!');
You need to bind those events to the show handler. In other words change this:
$('#myModal').on("hidden.bs.modal", function() {
console.log("Modal hidden");
$(".modal-body1").html("Where did he go?!?!?!");
});
to
$('#myModal').on("hidden.bs.modal", function() {
console.log("Modal hidden");
$(".modal-body1").html("Where did he go?!?!?!");
}).modal('show');

What closed the modal?

I am using a twitter bootsrap modal. It contains the buttons "Save", "Cancel" and the arrow for closing. How do handle the case (and recognize it) when the modal is closed by the arrow and when by a button?
$("#myModal).on('hidden.bs.modal', function () {
// ??? Arrow or button is the initiator
});
You need to hook into the button/icon clicks yourself and dismiss the modal from javascript. Here is an example:
$(function () {
var myModal = $("#myModal");
$("#btnShow").on("click", function () {
myModal.modal("show");
});
myModal.find(".closeIcon").on("click", function () {
console.log("Close Icon clicked.");
myModal.trigger("myModal.dismiss.closeIcon");
myModal.modal("hide");
}).end().find(".closeButton").on("click", function () {
console.log("Close Button clicked.");
myModal.trigger("myModal.dismiss.closeButton");
myModal.modal("hide");
}).end().find(".saveButton").on("click", function () {
console.log("Save Button clicked.");
myModal.trigger("myModal.dismiss.saveButton");
myModal.modal("hide");
});
myModal.on("myModal.dismiss.closeIcon", function () {
console.log("Close Icon Handler called.");
}).on("myModal.dismiss.closeButton", function () {
console.log("Close Button Handler called.");
}).on("myModal.dismiss.saveButton", function () {
console.log("Save Button Handler called.");
});
});
Basic Modal HTML (with classes for closeIcon, closeButton, and saveButton added to be able to dispatch the events).
<button id="btnShow">Show Modal</button>
<div id="myModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close closeIcon" aria-hidden="true">×</button>
<h4 class="modal-title">Modal title</h4>
</div>
<div class="modal-body">
<p>One fine body…</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default closeButton" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary saveButton">Save changes</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
jsfiddle here.
Its not possible to track event while closing the modal with data-toggles like data-dismiss="modal".
Try to use the events on each of them to get resolved.

Categories

Resources