A Javascript Confirm/Alert Replacement jQuery Plugin
Monday, 6th August 2012, 23:06
No messing, straight to the point! The built in Javascript functions alert() and confirm() are useful, but ugly. So I decided to knock up a quick almost-drop-in-replacement jQuery plugin that does the same job. And then extend it a bit to add some more useful features, like configuring the title, number of buttons, etc.
Since this is really basic stuff, I'll just post the code and a quick guide on how to use it afterwards. If you want a DEMO, yes I put that in caps to attract the wandering eye, put any old thing in the Username box in the comments section and no password, it will pop up the dialog for you to see without having to submit anything.
First up, this is the jQuery plugin itself:
// Custom modal dialog box jQuery plugin
(function( $ ){
var ModalDialog = function(args)
{
var self = this;
if (args.template == "ok")
{
this.title = "Information";
this.message = "Click the Okay button to continue";
this.buttons = [ { text: "Okay", value: true, class: "default" } ];
}
else
{
this.title = "Are you sure?";
this.message = "Do you really want to do this?";
this.buttons = [ { text: "Okay", value: true }, { text: "Cancel", value: false, class: "default" } ];
}
this.modalclass = "modaldialog";
this.blackoutclass = "blackout";
this.buttonclass = "buttons";
this.body = $("body");
this.window = $(window);
this.fadespeed = 300;
this.inoffsetx = -200;
this.inoffsety = 0;
this.outoffsetx = 200;
this.outoffsety = 0;
this.opacity = 0.7;
for (key in args)
this[key] = args[key];
this.createModal();
this.showModal();
};
ModalDialog.prototype.createModal = function()
{
this.hdTitle = $("<h4>" + this.title + "</h4>");
this.paMesage = $("<p>" + this.message + "</p>");
this.dvButtons = $("<div></div>");
this.arrButtons = new Array();
for (var u = 0; u < this.buttons.length; u++)
{
var btButton = $("<button value=\"" + this.buttons[u].value + "\" type=\"button\">" + this.buttons[u].text + "</button>");
if (this.buttons[u].class)
btButton.addClass(this.buttons[u].class);
this.arrButtons.push(btButton);
if (u > 0)
this.dvButtons.append(" ");
this.dvButtons.append(btButton);
}
this.dvModal = $("<div></div>");
this.dvModal.append(this.hdTitle, this.paMesage, this.dvButtons);
this.dvBlackout = $("<div></div>");
if (this.buttonclass)
this.dvButtons.addClass(this.buttonclass);
if (this.modalclass)
this.dvModal.addClass(this.modalclass);
if (this.blackoutclass)
this.dvBlackout.addClass(this.blackoutclass);
this.body.append(this.dvBlackout);
this.body.append(this.dvModal);
if (this.height)
this.dvModal.height(this.height);
if (this.width)
this.dvModal.width(this.width);
};
ModalDialog.prototype.showModal = function()
{
var self = this;
this.dvBlackout.fadeTo(this.fadespeed, this.opacity);
this.dvModal.fadeTo(this.fadespeed, 1);
this.centerModal();
// Better than using offset() because that doesn't account for padding/borders/etc
var top = parseInt(this.dvModal.css("top"), 10);
var left = parseInt(this.dvModal.css("left"), 10);
this.dvModal.css("top", (top + this.inoffsety) + "px");
this.dvModal.css("left", (left + this.inoffsetx) + "px");
this.dvModal.stop();
this.dvModal.animate({ opacity: 1, top: top, left: left }, this.fadespeed, function() {
for (var u = 0; u < self.arrButtons.length; u++)
self.arrButtons[u].click(function() {
var value = $(this).val();
switch (value.toLowerCase())
{
case "true":
value = true;
break;
case "false":
value = false;
break;
}
if (self.callback)
self.callback(value);
self.hideModal();
});
});
this.window.scroll(function() {
self.centerModal();
});
this.window.resize(function() {
self.centerModal();
});
};
ModalDialog.prototype.centerModal = function()
{
var offset = { left: 0, top: this.window.scrollTop() };
this.dvBlackout.offset(offset);
this.dvBlackout.width(this.window.outerWidth());
this.dvBlackout.height(this.window.outerHeight());
offset.left += Math.floor((this.window.width() - parseInt(this.body.css("marginLeft"), 10) - parseInt(this.body.css("marginRight"), 10)- this.dvModal.outerWidth()) / 2);
offset.top = Math.floor((this.window.height() - parseInt(this.body.css("marginTop"), 10) - parseInt(this.body.css("marginBottom"), 10) - this.dvModal.outerHeight()) / 2) + this.window.scrollTop();
this.dvModal.offset(offset);
};
ModalDialog.prototype.hideModal = function()
{
var self = this;
this.dvBlackout.fadeOut(this.fadespeed, function() {
self.dvBlackout.remove();
});
var top = parseInt(this.dvModal.css("top"), 10) + this.outoffsety;
var left = parseInt(this.dvModal.css("left"), 10) + this.outoffsetx;
this.dvModal.animate({ opacity: 0, top: top, left: left }, this.fadespeed, function() {
self.dvModal.remove();
delete self;
});
};
$.modaldialog = function(args) {
new ModalDialog(args);
};
})( jQuery );
You'll need to make yourself some CSS to go with it. This is in LESS format, and obviously is entirely based on a predefined variable @colour-background. You should be able to work out what needs changing even if you don't know how LESS works:
div.modaldialog
{
position: absolute;
top: 50px;
left: 50px;
width: 295px;
overflow: auto;
z-index: 1000;
display: none;
text-align: left;
padding: 10px;
background-color: @colour-background;
color: @colour-body;
border: 2px solid lighten(@colour-background, 20%);
.border-radius(7px);
div.buttons
{
text-align: center;
}
button
{
border-top: 2px solid lighten(@colour-background, 40%);
border-left: 2px solid lighten(@colour-background, 40%);
border-right: 2px solid lighten(@colour-background, 10%);
border-bottom: 2px solid lighten(@colour-background, 10%);
&.default
{
border-top: 2px solid lighten(@colour-background, 50%);
border-left: 2px solid lighten(@colour-background, 50%);
border-right: 2px solid lighten(@colour-background, 30%);
border-bottom: 2px solid lighten(@colour-background, 30%);
}
.border-radius(5px);
padding: 2px 5px;
background-color: lighten(@colour-background, 20%);
color: white;
text-shadow: 2px 2px black;
font-family: @font-body;
font-size: 1em;
cursor: pointer;
&:active
{
border-right: 2px solid lighten(@colour-background, 20%);
border-bottom: 2px solid lighten(@colour-background, 20%);
border-top: 2px solid lighten(@colour-background, 10%);
border-left: 2px solid lighten(@colour-background, 10%);
}
&:hover
{
text-decoration: underline;
}
}
p
{
margin-top: 5px;
}
h4
{
text-align: center;
margin-bottom: 10px;
font-weight: bold;
}
}
And finally, you use it as follows:
// Format of the jQuery plugin command is as follows
// $.modaldialog(object, function);
//
// Where object contains optional arguments, and function is an optional callback function for a resulting button click
// As a replacement for alert():
$.modaldialog({ template: "ok", message: "This is just to alert you of something!" });
// As a replacement for confirm():
$.modaldialog({ message: "Can I do something?", callback: function(result) {
if (result)
console.log("I'm doing something, look!");
} });
A few notes on what you can pass as arguments...
title
string: er, well, um, the title of the modal dialog! defaults to "Information" or "Are You Sure?" depending on the template
message
string: the message that appears in the modal dialog. defaults to two silly things that really you don't want. If you set nothing at all, at least make sure you set this other wise it is all a bit pointless!
template
string: sets defaults based on a template, of which there is only really two. One if you specify "ok" as the template, which is pretty much like alert(), not specifying anything results in defaults for a confirm() style dialog
buttons
array of objects: specify like the following: { text: "Cancel", value: false, class: "default" } , where text is the words you want to appear on the button, value is the result you wish the dialog to return to your callback function upon clicking, and class is the optional class you wish the button to have. Note that value is returned as a text string, unless it is "true" or "false" in which case it returns the boolean values.
modalclass
string: class given to the modal dialog DIV itself, defaults to "modaldialog"
blackoutclass
string: class given to the background DIV that appears behind the modal dialog, defaults to "blackout"
buttonclass
string: class given to the DIV that contains the row of buttons, defaults to "buttons"
fadespeed
integer: speed in milliseconds of fade in/out animations, defaults to 300
inoffsetx
integer: animation offset on the X axis of the dialog when fading in, defaults to -200 (appear 200 pixels from the left)
inoffsety
integer: animation offset on the Y axis of the dialog when fading in, defaults to 0
outoffsetx
integer: animation offset on the X axis of the dialog when fading out, defaults to 200 (disappear 200 pixels to the right)
outoffsety
integer: animation offset on the Y axis of the dialog when fading out, defaults to 0
opacity
float: opacity between 0 and 1 for the background DIV, defaults to 0.7
Enjoy! And please post a nice comment if you use it, and report any bugs...