Focus on Input when Bootstrap Modal closes - javascript

After a blur event on an input field "bootbox1", I want to use a Bootstrap Modal for an message, after the modal closes the focus would go to the input field "bootbox2". But the input field does not get focus.
What am I doing wrong?
Demo
HTML
<input type="text" id="bootbox" />
<input type="text" id="bootbox2" />
<div id="myModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<!-- dialog body -->
<div class="modal-body">
<button type="button" class="close" data-dismiss="modal">×</button>Hello world!</div>
<!-- dialog buttons -->
<div class="modal-footer">
<button type="button" class="btn btn-primary">OK</button>
</div>
</div>
</div>
</div>
JS
$('#bootbox').on('blur', function checkSelection(e) {
$("#myModal").on("show", function () { // wire up the OK button to dismiss the modal when shown
$("#myModal a.btn").on("click", function (e) {
console.log("button pressed"); // just as an example...
$("#myModal").modal('hide');
$('#bootbox2').focus();
// dismiss the dialog
});
});
$("#myModal").on("hide", function () { // remove the event listeners when the dialog is dismissed
$("#myModal a.btn").off("click");
$('#bootbox2').focus();
});
$("#myModal").on("hidden", function () { // remove the actual elements from the DOM when fully hidden
$("#myModal").remove();
});
$("#myModal").modal({ // wire up the actual modal functionality and show the dialog
"backdrop": "static",
"keyboard": true,
"show": true // ensure the modal is shown immediately
});
});
//this works
$('#bootbox2').on('blur', function checkSelection(e) {
$('#bootbox').focus();
});

You need to wait for the hidden.bs.modal event to fire, not the hide.bs.modal.
According to the Bootstrap Docs for the event hide.bs.modal
This event is fired immediately when the hide instance method has been
called.
Whereas hidden.bs.modal
This event is fired when the modal has finished being hidden from the
user (will wait for CSS transitions to complete).
Since your focus is being called before the overlay has been removed the input cannot take the keyboard focus yet.

Related

Focus trap in a dialog modal and after exiting, focus on the last element clicked

I have multiple modals with different id's.
<div id="#Modal" tabindex="-1" class= active" style="left: Opx;" role="dialog" >
<div id="#Modal-text' tabindex="0">
<div class="container">
<div class= close-btn">
<a class="closer noprint href=" javascript:void(0) aria-label="Close dialog" tabindex="0"></a>
</div>
</div>
<div class= content">..modal content goes here</div>
<div class="focus-guard" tabindex="0"></div>
</div>
<div id="#Modal-anothertext' tabindex="0"></div>
<div id="#Modal-sample' tabindex="0"></div>
</div>
The jquery function add a focus guard div and add an event listener to it whenever a tab or keyboard navigation, through it, it will go again to the close button:
"use strict"
jquery(document).ready(function ($) {
// Check if modal exists
if ($(" [id+='Modal-']").length {
// Check id's if containstring of 'Modal-' and check if modal has child with #focus-guard
if ($("[id*='Modal-']").find("focus-guard").length === 0) {
console.log("does not exist");
const focusGuard = document.createElement("div");
focusGuard.setAttribute("class", "focus-guard");
focusGuard.setAttribute("tabindex", "0");
// Add focus guard to parent
$("[id*='Modal-']").append(focusGuard);
// The closer button is being added in the DOM upon clicking modal, that's why I used DOMNodeInserted
$(document).bind("DOMNodeInserted", function (e) {
if (e.target.className="container") {
const close = document.querySelector(".closer");
console.log(close);
focusGuard.addEventListener("focus", () => {
close.focus();
});
}
});
}
});
}
Have tried also some possible selectors and isolating a single modal.
Unfortunately, the eventlistener on focus guard div does not trigger and I cannot target speciffically the "closer noprint" class.
I know it's not right to have a selector like an array("[id=Modal-]"*) to refer to the parent element of the modal but since it's multiple, not sure if this will be the right thing to do. Might there be a simple solution for this one.
Also stuck with a function that focuses on the last item clicked after dismissing the modal.

Parent's stopPropagation is disabling grandchild's functionality

I have a modal which when open gets this jquery statement:
$(".modal-inner").on("click", function(e) {
e.stopPropagation();
});
The trouble is, nested within this modal body, I have a child element that I'm using Clipboard.js on so a user may copy text. HTML as follows:
<div class="modal-inner"> <!-- stopPropagation applied to parent -->
<div class="modal-close" for="modal-1"></div>
<h1>Let's Connect</h1>
<i class="e"></i>
<p>You can reach me at:</p>
<p class="em">
<input id="emailToCopy" value="this.email#gmail.com"/>
<!-- This grandchild's functionality is now disabled -->
<button class="clip-btn" id="thisClip" data-clipboard-action="copy" data-clipboard-target="#emailToCopy" value="clipBtn">copy email</button>
</p>
</div>
The stopPropagation on .modal-inner keeps the modal from closing if the user clicks inside. This in turn disables my button which executes a script when clicked. I need this button to bypass the stopPropagation from the parent element.
You could just check if the button is clicked, and stop propagation conditionally
$(".modal-inner").on("click", function(e) {
if ( $(e.target).closest('#thisClip').length > 0 ) { // this is the button
e.stopPropagation();
}
});
This is probably not elegant but I believe will work:
$(".modal-inner").on("click", function(e) {
if (!$("button").is(":hover")) e.stopPropagation();
});
You may try testing the event target id and tagName:
$('.modal-inner').on("click", function(e) {
//
// you may also use:
// if ( $(e.target).is('#thisClip') ) {
//
if (e.target.id = 'thisClip' && e.target.tagName == 'BUTTON') {
e.stopPropagation();
console.log('You clicked the button: stop propagation');
} else {
console.log('You did not click the button');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="modal-inner"> <!-- stopPropagation applied to parent -->
<div class="modal-close" for="modal-1"></div>
<h1>Let's Connect</h1>
<i class="e"></i>
<p>You can reach me at:</p>
<p class="em">
<input id="emailToCopy" value="this.email#gmail.com"/>
<!-- This grandchild's functionality is now disabled -->
<button class="clip-btn" id="thisClip" data-clipboard-action="copy" data-clipboard-target="#emailToCopy" value="clipBtn">copy email</button>
</p>
</div>

Using bootstrap on confirm message onclick()

I'm new with bootstrap, and I've code for message confirmation.
How can I put my onclick() using this code below?
$("#myModal").on("show", function() { // wire up the OK button to dismiss the modal when shown
$("#myModal a.btn").on("click", function(e) {
console.log("button pressed"); // just as an example...
$("#myModal").modal('hide'); // dismiss the dialog
});
});
$("#myModal").on("hide", function() { // remove the event listeners when the dialog is dismissed
$("#myModal a.btn").off("click");
});
$("#myModal").on("hidden", function() { // remove the actual elements from the DOM when fully hidden
$("#myModal").remove();
});
$("#myModal").modal({ // wire up the actual modal functionality and show the dialog
"backdrop" : "static",
"keyboard" : true,
"show" : true // ensure the modal is shown immediately
});
Html of bootbox:
HTML (image)
onclick() input:
<input type='submit' name='actualiza_noticia' class='button' onClick="" value='Atualizar notícia'>
You can use either use the jQuery function $(elem).modal('show') function, or the Bootstrap html data attributes:
Using data attributes:
<input type='submit' data-toggle="modal" data-target="#myModal" name='actualiza_noticia' class='button' value='Atualizar notícia' >
Using Jquery function:
<input onclick="$('#myModal').modal('show')" type='submit' name='actualiza_noticia' class='button' value='Atualizar notícia' >
These shuold both trigger your events, although the 'show' event is 'shown.bs.modal' to be in compliance with Bootstrap 3:
$("#myModal").on('shown.bs.modal', function() { // wire up the OK button to dismiss the modal when shown
$("#myModal a.btn").on("click", function(e) {
console.log("button pressed"); // just as an example...
$("#myModal").modal('hide'); // dismiss the dialog
});
});
Read more about bootstrap modal here.
According to the image that reports your html my proposal is:
change $("#myModal").on("show", function() { to `$("#myModal").on("shown.bs.modal", function() {
change $("#myModal a.btn").on("click", function(e) { to $("#myModal button.button.btn.btn-primary").on("click", function(e) {
change $("#myModal").on("hide", function() { to $("#myModal").on("hide.bs.modal", function() {
change $("#myModal a.btn").off("click"); to $("#myModal button.btn.btn-primary").off("click");
For details see bootstrap modals
$(function () {
$("#myModal").on("shown.bs.modal", function() { // wire up the OK button to dismiss the modal when shown
$("#myModal button.btn.btn-primary").on("click", function(e) {
console.log("button pressed"); // just as an example...
$("#myModal").modal('hide'); // dismiss the dialog
});
});
$("#myModal").on("hide.bs.modal", function() { // remove the event listeners when the dialog is dismissed
$("#myModal button.btn.btn-primary").off("click");
});
$("#myModal").on("hidden", function() { // remove the actual elements from the DOM when fully hidden
$("#myModal").remove();
});
$("#myModal").modal({ // wire up the actual modal functionality and show the dialog
"backdrop" : "static",
"keyboard" : true,
"show" : true // ensure the modal is shown immediately
});
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-1.12.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<div id="myModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<!-- dialog box -->
<div class="modal-body">
<button type="btn btn-default" class="close" data-dismiss="modal">×</button>
Hello world!
</div>
<!-- dialog buttons -->
<div class="modal-footer">
<button type="btn btn-default" class="btn btn-primary">OK</button>
</div>
</div>
</div>
</div>

Handling Errors Within a Modal

I have modal's that are loaded with a link (see below). Whenever there is an error loading the modal (i.e. loading the data in the modal via a wcf service call), there is just a grey screen, as if a modal is trying to open and no modal is loaded. An error is shown in chrome developer tools console which is expected
Additionally, if I click a modal link that loads properly, close that modal, and then click a modal link that generates an error, the previous modal is loaded.
How can I have it so either an error modal is loaded or so a user is redirected to the error page when an error occurs?
Layout (partial view)
<div class="container">
<div class="row">
<div id="modal-container" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content col-sm-8 col-lg-offset-2">
</div>
</div>
</div>
</div>
</div>
// some code here...
$(document).on('show.bs.modal', '.modal', function() {
var zIndex = 1040 + (10 * $('.modal:visible').length);
$(this).css('z-index', zIndex);
setTimeout(function() {
$('.modal-backdrop').not('.modal-stack').css('z-index', zIndex - 1).addClass('modal-stack');
}, 0);
});
$('body').on('click', '.modal-link', function(e) {
e.preventDefault();
$(this).attr('data-target', '#modal-container');
$(this).attr('data-toggle', 'modal');
});
// Attach listener to .modal-close-btn's so that when the button is pressed the modal dialog disappears
$('body').on('click', '.modal-close-btn', function() {
$('#modal-container').modal('hide');
});
//clear modal cache, so that new content can be loaded
$('#modal-container').on('hidden.bs.modal', function() {
$(this).removeData('bs.modal');

How to clear all input fields in bootstrap modal when clicking data-dismiss button?

How to clear all input fields in a Bootstrap V3 modal when clicking the data-dismiss button?
http://getbootstrap.com/javascript/#modals shows an event for when a modal is hidden. Just tap into that:
$('#modal1').on('hidden.bs.modal', function (e) {
$(this)
.find("input,textarea,select")
.val('')
.end()
.find("input[type=checkbox], input[type=radio]")
.prop("checked", "")
.end();
})
http://jsfiddle.net/5LCSU/
I would suggest the above as it bind the clearing to the modal itself instead of the close button, but I realize this does not address your specific question. You could use the same clearing logic bound to the dismiss buttons:
$('[data-dismiss=modal]').on('click', function (e) {
var $t = $(this),
target = $t[0].href || $t.data("target") || $t.parents('.modal') || [];
$(target)
.find("input,textarea,select")
.val('')
.end()
.find("input[type=checkbox], input[type=radio]")
.prop("checked", "")
.end();
})
http://jsfiddle.net/jFyH2/
There is a more easy and beautiful way:
$('#MyModal').on('hidden.bs.modal', function () {
$(this).find('form').trigger('reset');
})
reset is dom build-in funtion, you can also use $(this).find('form')[0].reset();
And Bootstrap's modal class exposes a few events for hooking into modal functionality, detail at here.
hide.bs.modal This event is fired immediately when the hide instance
method has been called.
hidden.bs.modal This event is fired when the modal has finished being
hidden from the user (will wait for CSS transitions to complete).
If you are using a form in the modal then you can use
$("#form_id").trigger("reset");
I did it in the following way.
Give your form element (which is placed inside the modal) anID.
Assign your data-dimiss an ID.
Call the onclick method when data-dimiss is being clicked.
Use the trigger() function on the form element.
I am adding the code example with it.
$(document).ready(function()
{
$('#mod_cls').on('click', function () {
$('#Q_A').trigger("reset");
console.log($('#Q_A'));
})
});
<div class="modal fade " id="myModal2" role="dialog" >
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" ID="mod_cls" data-dismiss="modal">×</button>
<h4 class="modal-title" >Ask a Question</h4>
</div>
<div class="modal-body">
<form role="form" action="" id="Q_A" method="POST">
<div class="form-group">
<label for="Question"></label>
<input type="text" class="form-control" id="question" name="question">
</div>
<div class="form-group">
<label for="sub_name">Subject*</label>
<input type="text" class="form-control" id="sub_name" NAME="sub_name">
</div>
<div class="form-group">
<label for="chapter_name">Chapter*</label>
<input type="text" class="form-control" id="chapter_name" NAME="chapter_name">
</div>
<button type="submit" class="btn btn-default btn-success btn-block"> Post</button>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button><!--initially the visibility of "upload another note" is hidden ,but it becomes visible as soon as one note is uploaded-->
</div>
</div>
</div>
</div>
Hope this will help others as I was struggling with it since a long time.
Put the contents in your modal inside a form and give it an ID which is equal to "myForm".
When the close button is clicked, give an onclick to the function "myFunction()".
<button class="btn btn-default" data-dismiss="modal" onclick="myFunction()">Cancel</button>
function myFunction() {
document.getElementById("myForm").reset();
}
$('[data-dismiss=modal]').on('click', function (e)
{
var $t = $(this),
target = $t[0].href || $t.data("target") || $t.parents('#myModal') || [];
$(target)
.find("input")
.val('')
.end()
.find("input[type=checkbox]")
.prop("checked", " ")
.end();
$("span.inerror").html(' ');
$("span.inerror").removeClass("inerror");
document.getElementById("errorDiv1").innerHTML=" ";
})
This code can be used on close(data-dismiss)of modal.(to clear all fields)
Here I have cleared my input fields and my div as id="errorDiv1" which holds all validation errors.
With this code I can also clear other validation errors having class as inerror which is specified in span tag with class inerror
and which was not possible using document.getElementsByClassName
This is helpfull, its work for me..
$('.bd-example-modal-sm').on('hidden.bs.modal', function () {
$(this).find("select").val('').end(); // Clear dropdown content
$("ul").empty(); // Clear li content
});
The following worked for me:
$(':input').val('');
However, it is submitting the form, so it might not be what you are looking for.
In addition to #Malk, I wanted to clear all fields in the popup, except the hidden fields.
To do that just use this:
$('.modal').on('hidden.bs.modal', function () {
$(this)
.find("input:not([type=hidden]),textarea,select")
.val('')
.end()
.find("input[type=checkbox], input[type=radio]")
.prop("checked", "")
.end();
});
This will clear all fields, except the hidden ones.
enclose your modal body inside a form with an id="myform"
and then
$("#activatesimModal").on("hidden.bs.modal",function(){
myform.reset();
});
should do the trick

Categories

Resources