Creating Custom Confirm Boxes with jQuery

Posted on May 16, 2012 (one year ago). Seen 14,595 times. 12 comments. Permalink Feed
Photo Adrien Gueret
Software Engineer
Marakana, Inc.
Member since Jul 22, 2011
Location: London
Stream Posts: 9

When we develop a web application, we have to take into account that the user can make some mistakes. This is especially important if this user has some privileges.

In this case, we must ask for confirmation when someone tries to do something risky, like this:

confirm('Do you really want to delete this file?');

As you can see, confirm boxes are not really beautiful…

Using jQuery, I propose a method to customize these ugly boxes by developing a small plugin from start to end.

You can find here what you'll be able to do after reading this tutorial.


Note If you don't know how to create a jQuery plugin, you should read this tutorial before continuing this one.

First step: what will our plugin do?

Before starting to code, we have to identify the goals of our plugin. This step is very short, but essential!

To be efficient, we have to answer some questions.

  • When will the plugin be called?

  • What do we want it to do exactly?

  • How do we accomplish this?

When will the plugin be called?

We want to create custom confirm boxes. This kind of window appears when the user clicks on something: our plugin will thus be called during a click event on any DOM element!

What do we want it to do exactly?

The plugin must permit its user to stylize the confirm as he wants. Unfortunately, we can't modify the windows generated by the browser…

So, we'll have to simulate a confirm box.

How to do that?

We can create a fake confirm box with a div tag. Thanks to CSS, we can give to it the same behavior as a real confirm box.

Then, we'll add into it some other tags like p or input. Since they are basic HTML elements, we can apply our own style on them with CSS!


Note Don't forget that we'll simulate confirm boxes, we can't stylize real ones!

Second step: the basic code

Now that we know how to proceed, we can start to develop.

In order to make a jQuery plugin, this basic code is necessary:

(function($)
{
    //We'll name our plugin "jConfirm"
    $.fn.jConfirm=function(options)
    {
        //We'll set defaults values later
        var defaults={};
        var parameters=$.extend(defaults, options);

        //Plugin code
        return this.each(function()
        {

        });
    };
})(jQuery);

Note If you don't understand this code, please read this tutorial before continuing with this one!
(function($)
{
    //We'll name our plugin "jConfirm"
    $.fn.jConfirm=function(options)
    {
        //We'll set defaults values later
        var defaults={};
        var parameters=$.extend(defaults, options);

        //Plugin code
        return this.each(function()
        {
            var $link=$(this); //<1>

            //If we click on the element
            $link.click(function(clickEvent) //<2>
            {
                clickEvent.preventDefault(); //<3>

                //Only for checking
                alert('It works!'); //<4>
            });
        });
    };
})(jQuery);
  1. It's always better to store the jQuery object in a variable.

  2. Furthermore, as we know that the plugin must be call during a click event, we can already write this:

  3. clickEvent.preventDefault(); is here to prevent default action. For example, if the plugin is applied on a link, the user will not follow the href attribute after clicking on it.

  4. The alert() is here just to check if our plugin is called or not. Fortunately, it is!

Third step: let's create a window!

Now we'll create a simple window. This window will be a div tag:

//[...]
$link.click(function(clickEvent)
{
    clickEvent.preventDefault();

    //We create the confirm window
    var $confirmWindow=$('<div></div>');
});

Don't forget the main goal of the plugin: to permit us to stylize the confirm boxes! To make it easier, we can add specific classes to the element of our window.

//[...]
$link.click(function(clickEvent)
{
    clickEvent.preventDefault();

    //We create the confirm window
    var $confirmWindow=$('<div></div>');
    $confirmWindow.addClass('jConfirmWindow');
});

If we want to distribute our plugin, we'll have to write a document explaining the different classes we'll add. In this way, a user can create a CSS file easily thanks to these classes!

But the plugin must specify some CSS properties: the confirm box must have its position set to fixed (in case of scrolling) and it has to be displayed in the foreground.

Of course, don't forget to append the confirm box to the body of the web page!

//[...]
$link.click(function(clickEvent)
{
    clickEvent.preventDefault();

    //We create the confirm window
    var $confirmWindow=$('<div></div>');
    $confirmWindow.addClass('jConfirmWindow').css(
    {
        'position': 'fixed',
        'left': '50%',
        'top': '50%',
        'z-index': 1000000
    }).hide().appendTo($('body'));
});

But if we want to test the code, we'll see nothing! Let's add this checking code to test it:

//[...]
$link.click(function(clickEvent)
{
    clickEvent.preventDefault();

    //We create the confirm window
    var $confirmWindow=$('<div></div>');
    $confirmWindow.addClass('jConfirmWindow').css(
    {
        'position': 'fixed',
        'left': '50%',
        'top': '50%',
        'z-index': 1000000
    }).hide().appendTo($('body'));

    //Only for checking
    $confirmWindow.css(
    {
        'width': '300px',
        'height': '300px',
        'background-color': '#000',
        'color': '#fff'
    }).text('Click to remove me!')
    .click(function()
    {
        $(this).remove();
    });
    //End of checking code

    $confirmWindow.fadeIn('slow');
});

Fourth step: writing some text

A confirm window must have some text input into it! I propose creating our first two parameters, the title of the window and its main content:

//[...]
//Defaults values
var defaults=
{
    'title': 'Are you sure?',
    'message': 'Do you really want to do that?'
};
//[...]

Now, it's not very complicated: we'll create the title of the window (a h1 tag) and its content (a div tag).

As the main window, we add some specific classes to make the creation of the CSS file easier.

//[...]
var $title=$('<h1>');
$title.addClass('jConfirmTitle').html(parameters.title).appendTo($confirmWindow);

var $message=$('<div>');
$message.addClass('jConfirmMessage').html(parameters.message).appendTo($confirmWindow);
//[...]

We can also center our confirm window!

//[...]
//Let's center the confirm Window
$confirmWindow.css(
{
    'margin-left': '-'+($confirmWindow.outerWidth())/2+'px',
    'margin-top': '-'+($confirmWindow.outerHeight())/2+'px'
});
//[...]

At this step, the whole code of our plugin is:

(function($)
{
    //We'll name our plugin "jConfirm"
    $.fn.jConfirm=function(options)
    {
        //Defaults values
        var defaults=
        {
            'title': 'Are you sure?',
            'message': 'Do you really want to do that?'
        };
        var parameters=$.extend(defaults, options);

        //Plugin code
        return this.each(function()
        {
            var $link=$(this);

            //If we click on the element
            $link.click(function(clickEvent)
            {
                clickEvent.preventDefault();

                //We create the confirm window
                var $confirmWindow=$('<div></div>');
                $confirmWindow.addClass('jConfirmWindow').css(
                {
                    'position': 'fixed',
                    'left': '50%',
                    'top': '50%',
                    'z-index': 1000000
                }).hide().appendTo($('body'));

                var $title=$('<h1>');
                $title.addClass('jConfirmTitle').html(parameters.title).appendTo($confirmWindow);

                var $message=$('<div>');
                $message.addClass('jConfirmMessage').html(parameters.message).appendTo($confirmWindow);

                //Only for checking
                $confirmWindow.css(
                {
                    'width': '300px',
                    'height': '300px',
                    'background-color': '#000',
                    'color': '#fff'
                }).click(function()
                {
                    $(this).remove();
                });
                //End of checking code

                //Let's center the confirm Window
                $confirmWindow.css(
                {
                    'margin-left': '-'+(confirmWindow.outerWidth())/2+'px',
                    'margin-top': '-'+(confirmWindow.outerHeight())/2+'px'
                });

                $confirmWindow.fadeIn('slow');
            });
        });
    };
})(jQuery);

And then, we can call the plugin this way:

$('#myID').jConfirm(
{
    'title': 'A wonderful title',
    'message': 'Message confirmation'
});

Fifth step: adding the buttons

The buttons are the key-elements in a confirm window. There are two buttons: one for confirming the action, the other for cancelling it.

It could be interesting if our plugin can modify the text on these buttons. Let's update the default values:

//[...]
var defaults=
{
    'validText': 'OK',
    'cancelText': 'Cancel',
    'title': 'Are you sure?',
    'message': 'Do you really want to do that?'
};
//[...]

It can be better to add a paragraph which will contain the buttons: once again, we have to remember that we want to stylize our confirm boxes!

And then, it's the same thing as the title and the main content: we add two input in this container, and this last will be appended to the window!

//[...]
//Buttons container
var $buttonsContainer=$('<p>');
$buttonsContainer.addClass('jConfirmButtonsContainer').appendTo($confirmWindow);

//Adding the OK button
var $validButton=$('<input/>');
$validButton.attr('type','button').attr('value',parameters.validText)
.addClass('jConfirmValidButton').click(function()
{
    //We close the window
    $confirmWindow.remove();
}).appendTo($buttonsContainer);

//Adding the Cancel button
var $cancelButton=$('<input/>');
$cancelButton.attr('type','button').attr('value',parameters.cancelText)
.addClass('jConfirmCancelButton').click(function()
{
    //We close the window
    $confirmWindow.remove();
}).appendTo($buttonsContainer);
//[...]

You can see that we close the window when the user clicks on the buttons: in fact, closing a window means removing it from the DOM. By the way, we can now delete the click method we've written in the checking code.

Now, if we call the plugin like this way:

$('#myID').jConfirm(
{
    'title': 'A wonderful title',
    'message': 'Message confirmation',
    'validText': 'It\'s OK!',
    'cancelText': 'Hm... No.'
});

Sixth step: the event methods

Our buttons needs to make some actions when we click on them!

To be as useful as possible, our plugin can propose this list of events:

  • onclick

    • This event will be triggered when the user clicks on element which creates the confirm window, before this last becomes visible.

  • onopen

    • This event will be triggered when the window becomes visible.

  • onclose

    • This event will be triggered when the window is closed.

  • onconfirm

    • This event will be triggered when the user clicks on the OK button.

  • oncancel

    • This event will be triggered when the user clicks on the Cancel button.

All these events will run a function which contains one parameter: the jQuery object which have create the confirm window.

First of all, we add these events as default values:

//[...]
var defaults=
{
    'validText': 'OK',
    'cancelText': 'Cancel',
    'title': 'Are you sure?',
    'message': 'Do you really want to do that?',
    'onconfirm': null,
    'oncancel': null,
    'onclick': null,
    'onopen': null,
    'onclose': null
};
//[...]

Let's start with the easiest: onopen. It has to be triggered when the window is opened:

//[...]
$confirmWindow.fadeIn('slow',function()
{
    if(parameters.onopen)
    {
        parameters.onopen($link);
    }
});
//[...]

onclick must be triggered just before this code. We can add a functionality to it: if it returns false, the confirm window will not be displayed.

//[...]
if(parameters.onclick)
{
    if(parameters.onclick($link)===false)
    {
        $confirmWindow.remove();
        return false;
    }
}
//[...]

onconfirm will be triggered by the OK button whereas oncancel will be by the Cancel button. After clicking on one of these buttons, we have to call the corresponding event and close the window. In our previous step, we simply called the remove() method:

//[...]
var $validButton=$('<input/>');
$validButton.attr('type','button').attr('value',parameters.validText)
.addClass('jConfirmValidButton').click(function()
{
    //We close the window
    $confirmWindow.remove();
}).appendTo($buttonsContainer);
//[...]

Now, instead of calling this remove() method, we'll call another function. This function takes one argument, the triggered event, and calls its attached function. Then, it closes the window.

Below is this function:

//Let's center the confirm Window
//[...]
//Function called when the confirm window is closed
function jConfirmWindowClosed(callbackFunction)
{
    //User can't click on buttons anymore
    $confirmWindow.find('input').attr('disabled','true');
    if(callbackFunction)
    {
        callbackFunction($link);
    }

    $confirmWindow.fadeOut('slow',function()
    {
        if(parameters.onclose)
        {
            parameters.onclose(link);
        }
        $(this).remove();
    });
}
//Buttons container
//[...]

Note You can see that we call the onclose event in this function!

And here is how we call it:

//[...]
var $validButton=$('<input/>');
$validButton.attr('type','button').attr('value',parameters.validText)
.addClass('jConfirmValidButton').click(function()
{
    jConfirmWindowClosed(parameters.onconfirm);
}).appendTo($buttonsContainer);

//Adding the Cancel button
var $cancelButton=$('<input/>');
$cancelButton.attr('type','button').attr('value',parameters.cancelText)
.addClass('jConfirmCancelButton').click(function()
{
    jConfirmWindowClosed(parameters.oncancel);
}).appendTo($buttonsContainer);
//[...]

Now that our events are defined, we can use them to make what we want! For example, below is a way to call our plugin:

$('#myID').jConfirm(
{
    'title': 'A wonderful title',
    'message': 'Message confirmation',
    'validText': 'It\'s OK!',
    'cancelText': 'Hm... No.',
    'onclick': function()
    {
        alert('Click event!');
    },
    'onopen': function()
    {
        alert('Window is displayed!');
    },
    'oncancel': function()
    {
        alert('You cancel the action!');
    },
    'onconfirm': function()
    {
        alert('You confirm the action!');
    },
    'onclose': function()
    {
        alert('Window is closed!');
    }
});

Seventh step: a splash screen

If a confirm box is displayed, we generally want the user to answer the question before doing anything else. For now, with our plugin, the user can ignore it by clicking other links in the page… So, it might be wise to add a splash screen between the confirm window and the web page.

We can also leave it up to the developer: if he doesn't want to display a splash screen, the plugin has to allow deactivating it!

//[...]
var defaults=
{
    'validText': 'OK',
    'cancelText': 'Cancel',
    'title': 'Are you sure?',
    'message': 'Do you really want to do that?',
    'splash': true,
    'onconfirm': null,
    'oncancel': null,
    'onclick': null,
    'onopen': null,
    'onclose': null
};
//[...]

Then, we create this splash screen: it's useless to have several splash screens, so we can create it before the return this.each(function(){[…]});!

//[...]
var parameters=$.extend(defaults, options);

if(parameters.splash)
{
    //If the splash screen is not created, we add it
    var $splash=$('#jConfirmSplash');
    if($splash.length==0)
    {
        $splash=$('<div id="jConfirmSplash">');
        $splash.css(
        {
            'position': 'fixed',
            'width': '100%',
            'height': '100%',
            'top': '0px',
            'left': '0px',
            'opacity': 0.7,
            'z-index': 999999
        }).hide().appendTo($('body'));
    }
}

return this.each(function()
{
//[...]

Note The CSS style applied on the splash screen is very simple, you should be able to understand it. However, please note that we don't set background-color property: since we want the plugin to be as customizable as possible, we'll let the user choose the color in their CSS file. In the next examples, we'll set this background-color in our checking code.

The splash screen is created, but it's not displayed: don't forget to show it before the confirm window!

//[...]
if(parameters.splash)
{
    $splash.fadeIn('slow');
}
//[...]

Finally, we have to hide it in jConfirmWindowClosed():

//[...]
if(parameters.splash)
{
    $splash.fadeOut('slow');
}
//[...]

Eighth step: some bonus

As such, our plugin is ready for use. However, I propose adding two small bonuses.

Set a default button

The first one is very easy to implement: we can set a default button. When the confirm window opens, the plugin will focus on one of the buttons.

//[...]
var defaults=
{
    'validText': 'OK',
    'cancelText': 'Cancel',
    'title': 'Are you sure?',
    'message': 'Do you really want to do that?',
    'splash': true,
    'defaultButton': 'valid',
    'onconfirm': null,
    'oncancel': null,
    'onclick': null,
    'onopen': null,
    'onclose': null
};
//[...]

If the parameter defaultButton is set to valid, the OK button will be focused on. If set to cancel, it will be the Cancel button. Otherwise, no button will be focused on!

To do that, we just have to call the focus() method just after the window is displayed:

//[...]
$confirmWindow.fadeIn('slow',function()
{
    if(parameters.defaultButton=='valid')
    {
        $validButton.focus();
    }
    else if(parameters.defaultButton=='cancel')
    {
        $cancelButton.focus();
    }

    if(parameters.onopen)
    {
        parameters.onopen(link);
    }
});
//[...]
//[...]
$('#myID').jConfirm(
{
    'title': 'A wonderful title',
    'message': 'Message confirmation',
    'validText': 'It\'s OK!',
    'cancelText': 'Hm... No.',
    'defaultButton': 'cancel',
    'oncancel': function()
    {
        alert('Action canceled!');
    }
});
//[...]

A small form in the window

When we want to delete an article, it's better to leave a comment to explain the reason. It could be wonderful if our plugin allows the possibility to add this feature!

Here is how it will work:

//[...]
$('#myID').jConfirm(
{
    'message': 'An input : <input type="text" name="myInput" />',
    'onconfirm': function(link,data)
    {
        //data.myInput contains the input value
    }
});
//[...]

To do that, we have to get all the inputs values just before the call of the event methods. Then, we can send the data to these methods!

//[...]
//Function called when the confirm window is closed
function jConfirmWindowClosed(callbackFunction)
{
    //We use a JSON: it's easier!
    var data={};
    $confirmWindow.find('*[name]').each(function()
    {
        //We get the name and the value of each inputs/select boxes
        data[$(this).attr('name')]=$(this).val();
    });

    $confirmWindow.find('input').attr('disabled','true');
    if(callbackFunction)
    {
        //We send the datas to the callback function
        callbackFunction($link,data);
    }

    if(parameters.splash)
    {
        $splash.fadeOut('slow');
    }
    $confirmWindow.fadeOut('slow',function()
    {
        if(parameters.onclose)
        {
            //We send also the datas to the onclose method
            parameters.onclose($link,data);
        }
        $(this).remove();
    });
}
//[...]

You can see below an example using this new feature:

//[...]
$('#myID').jConfirm(
{
    'title': 'Change the text',
    'message': 'Please enter a new text for this link : <input id="myInput" type="text" name="newText" />',
    'validText': 'Let\'s go!',
    'cancelText': 'Keep it.',
    'defaultButton': 'none',
    'onopen': function(link)
    {
        $('#myInput').val(link.text());
    },
    'onconfirm': function(link,data)
    {
        if($.trim(data.newText).length>0)
        {
            link.text(data.newText);
        }
    }
});
//[...]

Ninth step: it's more beautiful with CSS!

Our plugin is ready! It's now time to remove our checking code:

//[...]
//Only for checking
$confirmWindow.css(
{
    'width': '300px',
    'height': '300px',
    'background-color': '#000',
    'color': '#fff'
});
$splash.css('background-color','#000');
//End of checking code
//[...]

We'll stylize henceforth in a CSS file. Thanks to the classes we've added to the elements of our windows, it will be very easy!

Please find below an empty CSS file for our plugin:

/*This style is not finished yet!*/

/*Splash screen*/
#jConfirmSplash
{

}

/*The whole window*/
.jConfirmWindow
{

}

/*Window title*/
.jConfirmTitle
{

}


/*DIV containing the message*/
.jConfirmMessage
{

}

/*Paragraph containing the buttons*/
.jConfirmButtonsContainer
{

}

/*Buttons*/
.jConfirmButtonsContainer input
{

}

/*Cancel button*/
.jConfirmCancelButton
{

}

/*Valid button*/
.jConfirmValidButton
{

}

Now, it's just simple CSS, the only limit is your imagination!

By clicking the link below, you can see some examples of designs.

Download the resources

You can download all the resources of this tutorial.


Comments

Posted on Jul 31, 2012
Photo Inbal Taizi
Covertix
Member since Jul 31, 2012
Hi Adrien,
Thank you very much for your post.

Is it possible to change the code such that the call won't be depend on a click event?
I tried changing it, but it didn't work.

Thanks,
Inbal.
Posted on Jul 31, 2012
Photo Adrien Gueret
Software Engineer
Marakana, Inc.
Member since Jul 22, 2011
Location: London
Hi Inbal, and thanks for your feedbacks!

What do you mean by "won't be depend on a click event" ? Do you want to open the confirm box after the page loading?

If so, you just have to trigger the "click" event after calling the plugin:

$('#myLink').jConfirm(/* Blabla... */).trigger('click');

If you want to do another thing, you can add an option to the plugin which will be a string containing the name of the event you want to listen to.
Posted on Aug 1, 2012
Photo Inbal Taizi
Covertix
Member since Jul 31, 2012
Hi Adrien,

Thanks for your quick reply.

That's exactly what I wanted to do, just to open a confirm box without any event trigger.
I want to change it a bit, and to use this code for my Loading animation (without buttons), and what I need is just to display the box on the screen without any client event.

I tried your suggestion:

I added an anchor to my page: <a id="testLink" href="#"></a>
and in the script I added:

$(document).ready(
function() {

$('#testLink').jConfirm
({
'title': 'A wonderful title',
'message': 'Message confirmation',
'validText': 'It\'s OK!',
'cancelText': 'Hm... No.',
'oncancel': function() {
alert('You cancel the action!');
},
'onconfirm': function() {
alert('You confirm the action!');
}
}).trigger('click');
}
);

but I get jquery exception: "type property can't be changed".
Do you have any idea why?

Thanks!
Posted on Aug 1, 2012
Photo Adrien Gueret
Software Engineer
Marakana, Inc.
Member since Jul 22, 2011
Location: London
I don't have this issue: do you use the source code from this tutorial or did you change it a bit?
Or maybe it comes from the browser you use?

Anyway, the error you have is thrown when we try to change the "type" attribute of an input element.
We change it at the lines 110 and 118 in jquery-jConfirm.js, but it shouldn't cause this issue...

You can try to remove the call of the methods attr('type','button') and, on the above lines, replace $('<input/>') with $('<input type="button" />').

I hope it will solve your problem. :)
Posted on Aug 1, 2012
Photo Inbal Taizi
Covertix
Member since Jul 31, 2012
Solved :)
Thank you very very much for your help!
Posted on Sep 3, 2012
Photo Ajay Dhama
Asst. Programmer
NIC
Member since Sep 3, 2012
Hi Adrien,

First of all, Thanks for this wonderful plugin.
This plugin works perfectly fine when i write the jConfirm function within html <head> tag
but problem occurs when i write the jConfirm function in PHP script in <body> tag,
Although it works as expected but only issue is jConfirm window does not closes on clicking any of the given button. I am not able to figure out what's going wrong.
Hope, u have any idea.
Posted on Sep 7, 2012
Photo Adrien Gueret
Software Engineer
Marakana, Inc.
Member since Jul 22, 2011
Location: London
Hi Ajay Dhama,

First, sorry for the late reply!

Concerning your issue, it's very strange: do you have any error message in the console log?
If so, which one?
If not, is it possible to see your code?

Furthermore, I think it's not a very good idea to use PHP in order to generate JavaScript code, we should separate client side from server side!

Thanks.
Posted on Sep 7, 2012
Photo Marty W.
Consultant
Member since Sep 7, 2012
Location: OH
This plugin is pretty great so far! I've got a dynamic list of items that I'm trying to attach a delete confirm to. Here is what my links look like:

<a href="index.cfm?id=#id#&del=y&rank=#rank#" class="delink">X</a>

I can get the dialog box, however, I'm having trouble getting the values of my querystring passed through. I've tried $(this).attr("href"), but just keep getting "undefined" for the value. Any ideas? Thanks very much for this!

M.
Posted on Sep 7, 2012
Photo Adrien Gueret
Software Engineer
Marakana, Inc.
Member since Jul 22, 2011
Location: London
Hi Marty W.!

Do you put $(this).attr("href") inside the callback method?
Its context is not the link, but we provide it as parameter inside the plug-in:

callbackFunction(link,data);


So, you should try this:

Code:
$('a').jConfirm({
/* Other options... */
'onconfirm': function($link, data) {
alert($link.attr('href'));
}
});
Posted on Sep 7, 2012
Photo Marty W.
Consultant
Member since Sep 7, 2012
Location: OH
Excellent Adrien! Worked like a charm! Thank you very much!

Marty
Posted on Feb 18, 2013
Photo Azhar Mansuri
developer
DIGICORP
Member since Feb 18, 2013
Hello,

I have implemented this plugin. It works fine if I click 2 times on a button. Here is my code.[function GetLoginResult(data) {
if (data != null) {

$('#Login1_btnLogin').jConfirm(
{
'title': 'My GulfCar',
'message': data
});
}

$('#spinner').fadeOut();
}
]

This code is working fine if I will click 2 times on a button.

can you please suggest me how to do it in 1 click?
Posted on Feb 18, 2013
Photo Adrien Gueret
Software Engineer
Marakana, Inc.
Member since Jul 22, 2011
Location: London
Hm, you didn't provide enough code to permit me to help you.

When is this function GetLoginResult called?

You have to call jConfirm plugin before clicking on the element, maybe the issue is here.