SoFunction
Updated on 2025-03-03

How to customize alert, confirm and modal dialogs using Bootstrap's modal components

In this article, I will introduce to you the pop-up window component Modal in Bootstrap. This component is simple and easy to use, with a generous and beautiful effect and very practical!

Since the browser provides a poor experience of alert and confirm boxes, and the browser does not provide a standard pop-up function that displays custom HTML in the form of a dialog box, many projects will customize dialog components. This article introduces my experience in bootstrap-based modal components, custom alert, confirm and modal dialog boxes in the project. It is relatively simple and practical, and I hope it can be of some reference value to you.

1. Example display

The detailed code can be found through the download link given above to download the source code. The code volume is not large, and the total number of these three components is only more than 200 lines.

If you have experience in JavaScript component development, I believe you can understand the code at this level at once. In the source code, I also gave a demo, which simulates a scenario that is closer to the actual needs:

1) The user clicks a button on the interface to open a modal box defined previously:

2) The user fills in some forms in the open modal box. When clicking OK, some verification will be triggered:

When not filling in email:

After filling in the email:

These two tips are actually to demonstrate the effects of Alert and Confirm, and they may not actually have such awkward functions.

3) When prompting that Password is empty, careful people will find that the confirm button is in a disabled state. This consideration is because the confirm button will eventually complete some asynchronous tasks. Before the asynchronous task is successfully completed, I hope that the modal component will not be closed, and that the clicked button cannot be clicked repeatedly;

4) I used setTimeout to simulate an asynchronous task. This asynchronous task will only callback in 3s after clicking the OK button, and:

When email inputadmin@adminWhen the submission is successful, a prompt will be given, and after confirmation, all pop-up boxes will be closed:

When the email input is worth it, a message will be given that the submission fails, and the modal box will still be displayed there:

In the component definition, especially the registration button, I added some AOP programming processing, and used jquery's delay object to implement the asynchronous programming I need. Please read the source code for details. If you have any questions, you can communicate and give me advice in the comment area.

2. Component requirements

Sometimes, in order to write a useful component, you only need to determine its approximate prototype and the interface to be provided externally, and the most important work of writing this component has been completed, although the encoding has not yet begun. Taking the components to be written in this article, the prototype and call forms of the components I want are as follows:

1) Custom alert box

The prototype is:

At most two parameters are required when calling. One msg is used to pass the prompt content to be displayed, and the other onOk is used to handle the callback when confirming the button clicks. There are two types of call formats:

//1
Alert('The order status you selected does not meet the current operation conditions. Please refresh the list to display the latest data before continuing!  ');
//2
Alert({
msg: 'The order status you selected does not meet the current operation conditions. Please refresh the list to display the latest data before continuing!  ',
onOk: function(){
}
}); 

The first is the case where there is no callback, so just pass msg directly. The second is the case where there is a callback. Use the options object to pass the two parameters of msg and onOks callback. Regardless of whether the onOk callback is present or not, the pop-up box must be closed when clicking the button.

2) Custom confirm box

The prototype of this box is only one button different from the alert box:

There is only one form of call:

Confirm({
msg: 'The order status you selected does not meet the current operation conditions. Please confirm whether you want to continue the operation!  ',
onOk: function(){
},
onCancel: function(){
}
}); 

onCancel is a callback when the cancel button is clicked. Regardless of whether the onOk and onCancel callbacks are present or not, the pop-up box must be closed when clicking the button. The onCancel callback can be gone.

3) Customize the modal box

prototype:

Call form:

var modal = new Modal({
title: '',
content: '',
width: 600,
buttons: [
{
html: '<button type="button" class="btn btn-sm btn-primary btn-ok">Sure</button>',
selector: '.btn-ok',
callback: function(){
//Click the callback of the OK button}
},
{
html: '<button type="button" class="btn btn-sm btn-default btn-cancel">Cancel</button>',
selector: '.btn-cancel',
callback: function(){
//Click the callback of the Cancel button}
}
],
onContentReady: function(){
// When the modal is added to the DOM and initialized, this callback will only be triggered once per modal instance},
onContentChange: function(){
// Event callback when a similar method is called changes the modal content},
onModalShow: function(){
// Event callbacks that will be triggered when a similar method is called to display modal},
onModalHide: function(){
// Event callbacks that will be triggered when a similar method is called to hide modal}
});
$('#btn-audit').click(function(){
();
}); 

Unlike Alert and Confirm, only one instance of Alert and Confirm is needed in a page, but multiple instances of Modal may be needed, so each Modal object needs to be new separately. Since what each Modal has to do is different, so:

A title parameter is needed to set the name to express what the Modal is dealing with;

The content parameter represents the html content of the Modal;

The width parameter sets the width of the Modal and the height of the Modal remains auto;

The buttons parameter is used to configure the buttons on this Modal. Generally, the Modal component only needs two buttons (determine and cancel) to be enough, but there are a few cases where multiple buttons are needed, so the way to configure the button is relatively flexible. Each button is configured with three parameters. HTML represents the html structure of the button. The selector is convenient for handling through event delegation when registering a callback. Callback configures the callback when the button is clicked;

The onContentReady event callback can actively initialize some components of the Modal internal html when the Modal is initialized; since component initialization is usually only performed once, it is most suitable to put it in this callback;

The onContentChange callback will come in handy when a Modal needs to be used as a different scenario and displays different HTML content, but it is not very useful, and the logic will be a little more complicated to process. If a Modal instance only does one thing, the onContentChange callback will not be used;

The onModalShow callback will be displayed every time the Modal is displayed. There are many scenarios used, such as a Modal is used to fill in some form content. Next time you fill in it, you need to reset the form to be used by the user. This kind of processing is more appropriate in this callback;

The callback onModalHide is useful, but there are not many scenarios that can be used, so it is considered a reserved interface.

4) Other requirements

All types of pop-up boxes are made into virtual modes, and a mask is added to the display box at the same time;

All boxes do not need to support drag and resize;

The titles of the alert and dialog boxes, the number of buttons, button position, and button text are all fixed.

In fact:

The bootstrap modal component itself supports this effect;

Drag and resize, this feature is icing on the cake, but it must have a lot of extra benefits for the software itself, so I chose not to do this kind of redundant treatment;

Alert and dialog do not need to be too personalized. They can unify the style and change the browser's native pop-up experience.

5) Calling instances in DEMO

Next, let’s demonstrate how I call these components during actual use after completing the development of these three components:

var modal = new Modal({
title: 'Test modal',
content: $('#modal-tpl').html(),
width: 500,
onOk: function(){
var $form = this.$('form');
var data = $();
var postData = {};
(function(obj){
postData[] = ;
});
if(!) {
Alert('Please enter EMAIL!');
return false;
}
var deferred = $.Deferred();
if(!) {
Confirm({
msg: 'Password is empty, do you want to continue?  ',
onOk: function(){
_post();
},
onCancel: function(){
();
}
})
} else {
_post();
}
return $.when(deferred);
function _post(){
//Simulate asynchronous taskssetTimeout(function(){
if( === 'admin@admin') {
Alert({
msg: 'Submission was successful!  ',
onOk: function(){
();
}
});
} else {
Alert({
msg: 'Submission failed!  ',
onOk: function(){
();
}
});
}
},3000);
}
},
onModalShow: function () {
var $form = this.$('form');
$form[0].reset();
}
});
$('#btn-modal').click(function () {
();
}); 

3. Key points of implementation

1) The most basic point is to understand the source code of bootstrap's modal component:

Initialization method: $()

Open: $('show')

Close: $(hide)

Event: Most of the events of the components with transition effects of bootstrap are paired, and one is present and the other is completed. The modal component defines two pairs:

and, and.

These two pairs of events are fired before and after the transition effect of the on and off is performed. From the component requirements I want to define, when defining a component, you need to use these two events. When listening to bootstrap's modal component dispatches these two events, you send the events of the component you defined:

modalShow and modalHide.

Options:

backdrop: Whether to display mask;
keyboard: Whether keyboard callbacks are supported;
show: Whether it is displayed immediately after initialization is completed.

All three options are true by default, but when I define the component, I configured it to false. The keyboard callback feature is not considered for the time being, so it is configured to true;

Of course, the pop-up box cannot be displayed immediately when calling bootstrap's modal initialization, so it cannot be configured to true; the reason why backdrop is configured to false is introduced in the next point.

2) Mask processing

If you enable bootstrap mask, you will find that when you click on the mask part, the pop-up box will automatically be turned off. This is not the virtual modal effect I expect, so backdrop must be configured to false. However, after configuring this option to false, a new problem will be caused, that is, the component has no mask effect, so in order to take into account these two problems, you can only write a simple mask to handle it yourself:

var $body = $(),
BackDrop = (function () {
var $backDrop,
count = 0,
create = function () {
$backDrop = $('<div class="modal-backdrop fade in"></div>').appendTo($body);
};
return {
show: function () {
!$backDrop && create();
$backDrop[0]. = 'block';
count++;
},
hide: function () {
count--;
if (!count) {
$();
$backDrop = undefined;
}
}
}
})(); 

The reason for introducing the count variable in this code is that BackDrop is a global singleton object. When multiple modal instances open method are called, BackDrop's show method will be called. In order to ensure that when calling BackDrop's hide method, Backdrop can be hidden after all modal instances are closed, a count variable is added to record how many times BackDrop's show method has been called. Only when count is 0, the BackDrop's hide method will truly hide BackDrop.

3) Definition of default value of component options

 = {
title: '',
content: '',
width: 600,
buttons: [
{
html: '&lt;button type="button" class="btn btn-sm btn-primary btn-ok"&gt;Sure&lt;/button&gt;',
selector: '.btn-ok',
callback: getDefaultBtnCallbackProxy('onOk')
},
{
html: '&lt;button type="button" class="btn btn-sm btn-default btn-cancel"&gt;Cancel&lt;/button&gt;',
selector: '.btn-cancel',
callback: getDefaultBtnCallbackProxy('onCancel')
}
],
onOk: $.noop,
onCancel: $.noop,
onContentReady: $.noop,
onContentChange: $.noop,//Callback after content replacementonModalShow: $.noop,
onModalHide: $.noop//Callback after modal is closed}; 

Configure two default buttons through buttons, determine and cancel. In order to simplify the callback configuration of these two default buttons, the interfaces of these two buttons are further extended to the previous level. OnOk and onCancel will be called when clicking OK and cancel. These two options are completely function callbacks, unlike onContentReady, which are event callbacks. getDefaultBtnCallbackProxy is used to assist in registering onOk and onCancel:

var getDefaultBtnCallbackProxy = function (callbackName) {
return function () {
var opts = ,
callback = opts[callbackName] && typeof opts[callbackName] === 'function' ? opts[callbackName] : '';
return callback && (this, arguments);
}
}

This inside will be bound to the modal instance.

4) Constructor:

function ModalDialog(options) {
 = (options);
this.$modal = undefined;
this.$modalTitle = undefined;
this.$modalBody = undefined;
this.$modalFooter = undefined;
 = undefined;
}

This mainly declares some instance variables used.

5) Key prototype methods and functions

open: function (state) {
 = state;
!this.$modal && initModal(this, );
();
this.$('show');
}

This is a prototype method, and the initialization of the component is also performed when this method is called (delayed initialization).

initModal = function (that, opts) {
var $modal = createModal(that);
();
();
();
();
bindHandler(that, opts);
$();//Calling bootstrap's Modal component$('contentReady');
}

This is a function to initialize the component. in:

setTitle is a prototype method used to set the title of the modal;

setContent is a prototype method used to set the html content of the modal;

addButtons is a prototype method used to register buttons;

setWidth is a prototype method used to set the width of the modal;

bindHandler is a function that registers the events of modal;

The penultimate step calls $() to initialize bootstrap's modal component;

The last step triggers the contentReady event.

bindHandler source code:

bindHandler = function (that, opts) {
var $modal = that.$modal;
typeof  === 'function' && $('contentChange', $.proxy(, that));
typeof  === 'function' && $('contentReady', $.proxy(, that));
typeof  === 'function' && $('modalShow', $.proxy(, that));
typeof  === 'function' && $('modalHide', $.proxy(, that));
$('', function () {
$('modalShow');
});
$('', function () {
$('modalHide');
});
}

For convenience, I bound the context of the onContentChange callbacks to the current modal instance. The last two event listening is to encapsulate the bootstrap event into the modal event I defined.

addButtons source code:

addButtons: function (buttons) {
var buttons = !$.isArray(buttons) ? [] : buttons,
that = this,
htmlS = [];
(function (btn) {
();
 &amp;&amp; that.$('click', , $.proxy(function (e) {
var self = this,
$btn = $();
//Disable the button first$btn[0].disabled = true;
var callback = typeof  === 'function' ?  : '',
ret = callback &amp;&amp; (self, arguments);
if (ret === false) {
$btn[0].disabled = false;
return;
}
if (typeof(ret) === 'object' &amp;&amp; 'done' in ret &amp;&amp; typeof ret['done'] === 'function') {
//Asynchronous tasks can only close Modal when a successful callback is completed(function () {
();
}).always(function () {
$btn[0].disabled = false;
});
} else {
$btn[0].disabled = false;
();
}
}, that));
});
this.$($(('')));
}

From this code, we can see:

When the button is clicked, the button will be disabled;

When the button returns false, the button will be restored, but the modal will not be closed, which means that some current operations have been blocked by the code;

When the button returns a delay object, the button will be restored until the delay object is completed, and the modal will be closed only when the delay object resolves;

Otherwise, the button will be restored and the modal will be closed automatically.

Considered in this code:

Anti-repeated clicks of buttons, automatic closing of modals, and processing of asynchronous tasks.

6) Encapsulate Alert and Confirm

Alert and Confirm are actually a special modal. In addition, these two components can also share a modal. After understanding these basics, the components can be defined as follows:

var Alert, Confirm;
(function () {
var modal,
Proxy = function (isAlert) {
return function () {
if ( != 1) return;
var msg = typeof arguments[0] === 'string' &amp;&amp; arguments[0] || arguments[0].msg || '',
onOk = typeof arguments[0] === 'object' &amp;&amp; typeof arguments[0].onOk === 'function' &amp;&amp; arguments[0].onOk,
onCancel = typeof arguments[0] === 'object' &amp;&amp; typeof arguments[0].onCancel === 'function' &amp;&amp; arguments[0].onCancel,
width = typeof arguments[0] === 'object' &amp;&amp; arguments[0].width || 400,
_onModalShow = function () {
(width);
(msg);
this[(isAlert ? 'hide' : 'show') + 'Button']('.btn-cancel');
},
_onModalHide = function () {
('');
};
//Delay initialization of modalif(!modal) {
modal = new Modal({
'title': 'Operation prompt',
onModalShow: _onModalShow,
onModalHide: _onModalHide,
onContentReady: function(){
this.$({
'padding-top': '30px',
'padding-bottom': '30px'
})
}
});
} else {
//If the modal has been initialized, you need to relisten the eventvar $modal = modal.$modal;
$('modalShow modalHide');
$('modalShow modalHide');
$('modalShow', $.proxy(_onModalShow, modal));
$('modalHide', $.proxy(_onModalHide, modal));
}
({
onOk: onOk || $.noop,
onCancel: onCancel || $.noop
});
();
}
};
Alert = Proxy(true);
Confirm = Proxy();
})(); 

In this code:

First, consider the delayed initialization of this global modal component;

Since the two callbacks of onModalHide and onModalShow are event callbacks, when initializing the component, the parameters passed in through options cannot be changed by modifying options, and can only be handled by re-registration; while onOk and onCancel are function callbacks, and as long as the reference in options is changed, the callback can be changed;

Considering the length of Alert and Confirm contents, a new parameter width has been added to adjust the width of the box.

4. Summary

This article introduces some methods and practices in the process of defining js components. There are a lot of codes and it is not easy to arouse people's interest in reading, but the methods introduced in the article are relatively simple, and I have used these three components in several projects. From the current perspective, they can solve all my needs for pop-ups, so I recommend it, hoping to help people in need.