How to get the modal dialog instance through the Bootstrap programmatic API? - javascript

The scenario I'm trying to solve is to disable that the escape-button closes the dialog AFTER the modal has been instaniated (the dialog is set to a loading state). So in other words after I have instaniated my modal like this:
(this.$el).modal("show");
The user presses a submit button and the dialog is set to a loading state and I want to disable the escape-button since the user should not be able to close the dialog in this state.
I have tried this:
(this.$el).modal({ keyboard: false });
But it does not work, it seems that Bootstrap only reads those options when it instaniates the modal dialog...
So my question is if it is possible to get a hold of the actual bootstrap modal-instance to be able to change the options-object? According to the documentation it should be possible (or have I misunderstood the docs?), but I cannot figure out how.
Here is what it says in the documentation (http://getbootstrap.com/javascript/):
If you'd like to get a particular plugin instance, retrieve it directly from an element:
$('[rel="popover"]').data('popover').
Any ideas?

Ok, I figured out how to get ahold of the modal dialog instance after some experimentation:
var bootstrapModalInstance = this.$el.data("bs.modal");
And then I could set the options on the instance like this:
bootstrapModalInstance.options.keyboard = !this.model.isSyncing;
Sadly enough, this did not solve the problem since the escape-key-event-listener is setup during the modal instaniation like this:
From bootstrap.js
Modal.prototype.escape = function () {
if (this.isShown && this.options.keyboard) { // The event listener is setup on initalization
this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
e.which == 27 && this.hide() // !!! Does not check the instance options.keyboard flag status, so I had to add && this.options.keyboard here
}, this))
} else if (!this.isShown) {
this.$element.off('keydown.dismiss.bs.modal')
}
}
And as I wrote in the code comment above adding the instance options.keyboard check in the event listener solved the issue.

Related

How to re-open Bootstrap modal accidentally closed

I have a few different modals on a page, and it all works as it should, but if a user makes some input on form fields in a modal and then accidentally clicks outside of the modal (which closes it), they loose their changes, since if the user clicks the same button they pressed to open the modal, the data they entered will be overwritten with data pulled from the database.
So I'd like to have a function for "reopen last closed modal" that simply shows the modal again in it's last used state - with whatever data was in it.
Essentially like a Ctrl-Z for accidentally closing a modal.
It's really simple if you know the ID of the modal. Such as:
$('#myModal1').modal('show'); });
But because I have several different modals available on a page, and I don't want to have a bunch of "restore" buttons, I need to be able to detect the ID of the last closed modal.
If there's not a simpler way, I could capture the ID each time a modal is closed, and then use that ID if the modal needs to be reopened without changing its data. Something like this:
$('#myModal1').on('hidden.bs.modal', function (e) {
var LastModal = '#myModal1';
})
$('#myModal2').on('hidden.bs.modal', function (e) {
var LastModal = '#myModal2';
})
function reOpen() {
$(LastModal).modal('show');
}
But I'm guessing there's a way that's simpler and doesn't require me to state all my modals ID's in JS/jQuery. Any ideas?
I've made a few tweaks, and this is working well for me now, with essentially no other hassle than a few short lines of code in my script file.
var LastModal;
$('.modal').on('hidden.bs.modal', (e) => {LastModal = $(e.target).attr('id'); })
function reOpen() { $('#'+LastModal).modal('show');}
Just use the style class "modal" for your modals, and to call the "reOpen", just have something like:
<span onclick='reOpen();'>Reopen</span>
Thanks #marekful for your suggestion!
Also, if you want to access this (or any other function) by pressing Ctrl+Z, you can add this:
// press Ctrl+Z to restore modal
$(document).keydown(function(evt){
if (evt.keyCode==90 && (evt.ctrlKey)){
evt.preventDefault();
reOpen();
}
});

Updating options / config in open Bootstrap 4 modal

I am upgrading a modal from Bootstrap 3 to 4. I have some code which will update the options (specifically the backdrop and keyboard options) of an open modal. In Bootstrap 3 I had accomplished this by running:
$('.modal').data('bs.modal').options.backdrop = newBackdropValue;
$('.modal').data('bs.modal').options.keyboard = newKeyboardValue;
When I upgraded this to Bootstrap 4 I got the error that options was undefined. I then tried moving this to use _config as that seems to where these options are now housed but it didn't actually update the behavior of the modal.
In looking into the Bootstrap 4 code I noticed that on show it calls the _setEscapeEvent which seems to put a listener on the keyboard but I couldn't find public functions which removed this listener.
Would appreciate any insights into how people had done this before I start rooting around and trying to use private methods on the Modal.
for disable
$('#modal').off('keydown.dismiss.bs.modal');
for enable
$('#modal').on('keydown.dismiss.bs.modal', function(event) {
if (event.which === 27) {
event.preventDefault();
$('#detailselector').modal('hide')
}
});
You should be able to use the _config object in the data to update the modal. Just make sure it's done before the modal is shown...
Demo: https://codeply.com/go/DhB7TXVdfc
$('#myModal').on('show.bs.modal',function(){
// change the options that were set in data-attributes
$('#myModal').data("bs.modal")._config.backdrop = false;
$('#myModal').data("bs.modal")._config.keyboard = false;
});
Remember too that the modal must have tabindex="-1" in order for the ESC keyboard option to work!

Meteor pass value from modal click event to parent template

I am trying to make a re-useable confirm modal in Meteor. I have the modal working in the sense it opens and displays the content. The idea is I can use this anywhere and it will return a value if the user clicks confirm then I can run any server side method I choose. The confirm template js is simple and looks like this:
Template.confirm.events({
'click .confirm': function() {
// I want to let the template that opened the modal know the user has confirmed. How do I pass this information?
},
'click .cancel': function() {
//Close the modal
}
});
I know there are solutions e.g sweet alerts but I am using Zurb Foundation for my UI and want to keep everything within this framework for consistency and control. Can anyone help point me in the right direction?
Many thanks in advance.
There's no standard way to go about this, but I'd suggest passing the modal a reactiveVar that you observe outside the modal and trigger your server-side method when the reactiveVar changes to the value you want. Some skeleton code might look like:
html
{{> confirm triggerVar=myReactiveVar}}
modal js
Template.confirm.events({
'click .confirm': function() {
this.triggerVar.set(true);
},
'click .cancel': function() {
this.triggerVar.set(false);
}
});
in your controller js
Template.someTemplate.onCreated(function() {
this.myReactiveVar = new ReactiveVar();
})
Template.someTemplate.onRendered(function() {
// observe changes on your fancy reactiveVar
this.autorun(() => {
if (this.myReactiveVar.get() === true) {
// fire whatever server-side action you want
}
})
})

PageDown with a Bootstrap 3 modal dialog, the background mask is causing many problems

Edit:
Check the bottom of this post for a solution, but now it introduces a new problem.
I'm using the most recent version of PageDown with Bootstrap 3.
This series of events causes the following error:
Uncaught TypeError: Cannot call method 'removeChild' of null
At which point the wmd-background mask is visible and over takes my page.
The error happens after step 4:
Open the custom modal dialog
Close the custom modal dialog (Using ok or cancel does not matter)
Open the custom modal dialog
Close the custom modal dialog (Using ok or cancel does not matter)
Here's the custom javascript code:
var insert_image = $("#insert-image");
var submit_image = $("#insert-image-submit");
var insert_image_close = $("#insert-image-close-x, #insert-image-close");
var file_url = $("#file_url", insert_image);
var file_local = $("#file_local", insert_image);
editor.hooks.set("insertImageDialog", function(callback) {
submit_image.on("click", function(event) {
event.preventDefault();
console.log("submit image");
insert_image.modal("hide");
return callback(file_url.val().length > 0 ? file_url.val() : null);
});
insert_image_close.on("click", function() {
console.log("cancel");
return callback(null);
});
insert_image.modal("show");
return true;
});
editor.run();
I did not see any solutions posted to this specific problem. I also tried hooking into Bootstrap's modal events and tried to either append my own or hide/show the wmd-background mask but I can't figure out a solution that results with no errors and has no extra background mask.
I should add too that I also have data-backdrop="" set in my html for when I build the modal dialog but this doesn't do anything other than prevent the background from being extra dark.
Solution:
I patched the library and changed:
Old broken version:
background.parentNode.removeChild(background);
New semi-working version:
if (document.contains(background)) { background.parentNode.removeChild(background); }
New problem:
The callback for both submit and cancel keep occurring more and more, as you open and close the form.
I get 1 then 2 then 4 then 6 then 10 console.log messages each time I close the form as I keep opening and closing it manually.
I fixed this temporarily by adding this to the top of the editor hook:
submit_image.unbind("click")
insert_image_close.unbind("click")
This seems like a hack, surely there's a better way to handle memoizing an event handler rather than unbind it + rebind it?

Change Bootstrap modal option once it already exists

I'm using Bootstrap Modal. I declare it, I call it, I show it...everything seems to be ok.
But what if I have an already existing modal previously shown with "keyboard" property to false and I want to change it on the go? I mean something like:
First, I create a Modal doing this (as you can see, I declare the modal putting keyboard property to false):
$('#myModal').modal({
show: false,
backdrop: true,
keyboard: false
});
But then I declare this event handler, that means that if "something" happens, I want the keyboard property to be set to true.
$('#myModal').on('shown', function(e) {
if (something){
$('#myModal').modal({keyboard: true});
}
}
So, when I go
$("#myModal").show();
The event handler is not doing what it is supposed to, as I am not getting to close the modal once Escape key is pressed. But I am completely sure that "something" is true and I have checked and re-checked that $('#myModal').modal({keyboard: true}) is executed.
Any clue as to why this isn't updating the value of configuration option?
To change configuration settings on already initiated Bootstrap plugin, such as the Modal, you need to access the plugin object attached to the element, like $('#pluginElement').data['somePlugin'] and then set the options in it.
For the Modal, you need:
$('#myModal').data('modal').options.keyboard = true;
JSFiddle Demo (old)
For Bootstrap 3 (as mentioned in comments by #Gerald ), you need bs.modal:
$('#myModal').data('bs.modal').options.keyboard = true;
Waiting Modal Example
A bit beyond the scope of the OP, but this is now twice I have searched for the same solution (my memory is crap) and twice that I came across this question which led me to my eventual answer. My issue was how to make an already init'ed and displayed modal, which was "closeable", into an "uncloseable" model. In the rare even that another user needs this answer, here is what I did based on the accepted answer:
*bootstrap3 used
$('#modal').off('keyup.dismiss.bs.modal'); // disable escape key
$('#modal').data('bs.modal').options.backdrop = 'static';
$('#modal button.close').hide();
Notice that I didn't change the options.keyboard property to false (followed by calling escape()) as suggested above. I could not get that to work, so after looking the Bootstrap source, I saw that all it was doing was simply removing an event listener for 'keyup.dismiss.bs.modal'.
To re-enabled things (in my scenario, when the model is hidden):
$('#modal').on('hidden.bs.modal', function (e) {
$(this).data('bs.modal').escape(); // reset keyboard
$(this).data('bs.modal').options.backdrop = true;
$('button.close', $(this)).show();
});
This seems COMPLETELY clumsy and will for sure break in coming versions of Bootstrap, but works for now...
Cheers :)
For bootstrap4
To disable closing modal on escape button:
$('#myModal').off('keydown.dismiss.bs.modal');
To disable closing modal on clicking on backdrop:
$('#myModal').data('bs.modal')._config.keyboard = false;
As warned by nocturnal, this may break in the future versions of bootstrap.
For Bootstrap 4.1
The options property should be replaced with _config.
E.G.
const modal = $('#modal');
/*
|------------------------------------------------------------------------------
| Now, let us assume you already opened the modal (via js or data attribute).
| If you want to access the options and modify.
|------------------------------------------------------------------------------
*/
// [Not Required] Let us see what the object is like.
console.log( modal.data('bs.modal')._config );
// Override the options to lock modal.
modal.data('bs.modal')._config.backdrop = 'static';
modal.data('bs.modal')._config.keyboard = false;
// [optional] You can also hide all data-dismiss buttons too.
modal.find("[data-dismiss='modal']").hide();
// Revert all actions above.
modal.data('bs.modal')._config.backdrop = true;
modal.data('bs.modal')._config.keyboard = true;
modal.find("[data-dismiss='modal']").show();
Setting backdrop and esckey not to close the modal when the modal is already open
$('div[name="modal"]').data('bs.modal').options.backdrop = 'static';
$('div[name="modal"]').off('keydown.dismiss.bs.modal');
Unset the backdrop and key esc purpose to not close the modal
$('div[name="user_profile_modal"]').data('bs.modal').options.backdrop = true;
$('div[name="user_profile_modal"]').data('bs.modal').escape();
You can also add an attribute in your HTML tag: data-keyboard="false"
<div id="myModal" class="modal hide fade" data-keyboard="false" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"></div>
It works for me!
Another option if you do not know if the modal has already been opened or not yet and you need to configure the modal options (Bootstrap 3):
var $modal = $('#modal');
var keyboard = false; // Prevent to close by ESC
var backdrop = 'static'; // Prevent to close on click outside the modal
if(typeof $modal.data('bs.modal') === 'undefined') { // Modal did not open yet
$modal.modal({
keyboard: keyboard,
backdrop: backdrop
});
} else { // Modal has already been opened
$modal.data('bs.modal').options.keyboard = keyboard;
$modal.data('bs.modal').options.backdrop = backdrop;
if(keyboard === false) {
$modal.off('keydown.dismiss.bs.modal'); // Disable ESC
} else { //
$modal.data('bs.modal').escape(); // Resets ESC
}
}
Thanks #nokturnal
For me this method works the best
$('#modal').on('hide.bs.modal', function () {
return false;
});
It prevents modal from closing by any possible scenario:
pressing escape key
clicking outside the modal
clicking close button
and even using of $('#modal').modal('hide')

Categories