Updating options / config in open Bootstrap 4 modal - javascript

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!

Related

tabindex conflict between Alertify and bootstrap 4 modal

I'm calling an Alertify Confirmation dialog while running a Bootstrap 4 Modal, and the problem is that the tab focus is not working in the first, while it is stucking in the last.
I believe it is something to do with the "tabindex=-1" which is added to the modal class Div based on Bootstrap 4 standards, so I've tried more than one concept trying resolving the problem, and still not working...
One of the concepts that I've thought will work was to toggle the "tabindex=-1" from the "modal" class div elements during the Alertify onshow and onclose events, and still not working!
let mymessage = "Update entry?";
alertify.confirm().set({title: "Confirm!"})
.set({labels: {ok:"Yes", cancel:"No"}})
.set("defaultFocus", "ok");
.set({onshow:function(){$(".modal").attr("tabindex","-2");}})
.set({onclose:function(){$(".modal").attr("tabindex","-1");}});
// Show confirmation message
alertify.confirm(mymessage, function(e){
if(e){
editRow();
} else {
alertify.notify("Entry update has been canceled!");
}
}).bringToFront();
Take a look at the tab sequence is still in the Modal Div while it is missing from the Alertify Confirmation dialog!
I will be appreciated for any support!
The following code resolves the issue:
let mymessage = "Update entry?";
// custom OK and Cancel label to Yes and No
alertify.confirm().set({title: "Confirm!"})
.set({labels: {ok:"Yes", cancel:"No"}})
.set("defaultFocus", "ok")
.set({onshow:function(){$(".modal").removeAttr("tabindex");}})
.set({onclose:function(){$(".modal").attr("tabindex","-1");
}});
// Show confirmation message
alertify.confirm(mymessage, function(e){
if(e){
editRow();
} else {
alertify.notify("Editing entry has been canceled!");
}
});

Foundation 6 how to make changes during going over between tabs

I use Foundation 6 and now I got the problem.
There are 2 tabs "entrance" & "registration" into modal window "authorization".
I want to make such thing "If you fill inputs for example in "registration" tab but don't push button and go over to "entrance" tab, inputs in "registration" tab should be clear".
I wrote this code and tried it but it is not working
$("#authorization-tab-link").click(function(){
$("#register-alert").removeClass("callout alert success").empty();
$("#email-register-input").val("");
$("#name-register-input").val("");
$("#first-password-register-input").val("");
$("#second-password-register-input").val("");
});
I did the same by using bootstrap and it is working. That's odd.
I don't know why <a> .click() is not handling.
According to the Foundation6 Documentation, you can use an event to do this:
$(document).on('change.zf.tabs',function(){
$("#register-alert").removeClass("callout alert success").empty();
$("#email-register-input").val("");
$("#name-register-input").val("");
$("#first-password-register-input").val("");
$("#second-password-register-input").val("");
});
Normally this should work. If not, try the .on() on your Tab element. e.g.:
$('#my-tab-wrapper').on('change.zf.tabs',function(){ /* do stuff here */ });
EDIT:
$('#my-tab-wrapper').on('change.zf.tabs', function(e, target){
});
Check what the target var returns and build an if/else. This should work .

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

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.

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