In my previous post Fun with canvas and MooTools: a Rectangle class, I explained that I wanted to make a modal window for a project at my workplace. I was interested in using MochaUI, but felt it was a bit heavy for my needs. I started playing with the canvas
element (using excanvas.js for Internet Explorer support), and wound up making a useful Rectangle
class that can quickly draw shapes in canvas using JavaScript.
Shortly afterward I built a simple modal window class named Modal
using MooTools. This class combines a dynamic canvas drawing API (the Rectangle
class) with dynamic DOM element generation to create on-demand modal windows using no external images. My goal was to make this about as easy to use as a normal JavaScript alert
, prompt
or confirm
window.
I’ve been playing with it over the last week or so, and while it’s nowhere near perfect (esp. the ‘close’ button), I think it’s good enough for my project at work. I figured I’d post it here in case anyone wants to have a look. Feel free to use it if you like, but remember it comes as-is with no warranties! View Modal.js here.
Note: The code in Modal.js is subject to change!
I’m completely open to suggestions for code improvements (my code still feels ‘hacky’ to me), but I’m not really interested in adding new features at the moment. If you really want a full-featured, well-crafted window system, you should use Greg Houston’s MochaUI.
Modal
Examples:
- Default settings
- Simple no-frills
- Prompt-style (using HTML for the buttons)
- Multiple windows (they get queued and show up in the order they were invoked)
The default
The simplest way to invoke the window is:
var modal = new Modal({ title: "My title", html: "<p>My html code goes here</p>" });
Code language: JavaScript (javascript)
Simple no-frills
You have the option of not using a window titlebar or ‘close’ button:
var html = "<p>This is a modal window without any title bar.</p>";
var modal = new Modal({
html: html,
width: 300,
height: 200,
edgeMargin: 1,
windowRadius: 9,
opacity: 0.80,
colors: {
modalBackground: "#CCC",
windowBackground: "#999",
contentBackground: "#EFEFEF"
},
showTitleBar: false
});
Code language: JavaScript (javascript)
Public Methods
close()
This closes the modal window. Once the window is closed, the elements are destroyed and garbage collected using MooTools’ element.destroy
method.
var mymodal = new Modal({
title: "My title",
html: "<p><a href='#' onclick='return goAway()'>Close me</a></p>"
});
function goAway(){
mymodal.close();
return false;
}
Code language: JavaScript (javascript)
Options
The options available in the Modal class are:
Text
title
(String) Text content for titlebar. String format, loads into anh1
element.html
(String) Text content for the main window content. Loads into adiv
.padding
(Number, default is 12) Indicates how much padding the contentdiv
gets, in pixels.font
(String, default is “Verdana, Geneva”) Sets CSS style for the title and window content. Can be overridden by inline styles.fontSize
(String, default is “small”) Sets CSS style for the window content div. Can be overridden by inline styles.
Size/shape
width
(Number, default is 350) Width of window before the drop shadow gets added, in pixels.height
(Number, default is 200) Width of window before the drop shadow gets added, in pixels.shadowSize
(Number, default is 6) Size of drop shadow, in pixels (note: not 100% pixel perfect measurements).titlebarHeight
(Number, default is 28) Size of titlebar, in pixels.edgeMargin
(Number, default is 1) Size of window chrome between shadow and content area, in pixels.windowRadius
(object OR number) Size of window corner radius, in pixels. If a number is specified, all four corners get the same radius. If an object is used, each corner gets the number specified (see below).windowRadius.topLeft
(Number, default is 9)windowRadius.topRight
(Number, default is 9)windowRadius.bottomLeft
(Number, default is 3)windowRadius.bottomRight
(Number, default is 3)
Behavior
animate
(Boolean, default istrue
) Indicates whether or not to fade out the modal background when dismissing the window.backgroundClickDismissesModal
(Boolean, default istrue
) Indicates whether or not clicking the background will dismiss the modal window.closeButton
(Boolean, default istrue
) Indicates whether or not to include a close button. Only works when showTitleBar is also set totrue
.showTitleBar
(Boolean, default istrue
) Indicates whether or not the title bar should be rendered.
Colors
opacity
(Number, default is 0.66) Indicates the opacity level of the background modaldiv
. Number must be between 0 and 1.colors
(object) Child properties are used to specify colors for window elements. All color parameters accept standard CSS color conventions, including hex and RGB.colors.modalBackground
(Default is #000) Background modaldiv
.colors.windowBackground
(Default is #AAA) Window chrome color.colors.windowTitleBar
(object) Used to create a gradient background for the window’s title bar. Accepts two properties: top and bottom.colors.windowTitleBar.top
(Default is “#F5F5F5”)colors.windowTitleBar.bottom
(Default is “#AAA”)
colors.contentBackground
. (Default is “#F8F8F8”) Color of the canvas element behind the contentdiv
.colors.closeButton
(object) Used to create a the background and stroke for the closeButton.colors.closeButton.fill
(object) Used to create a gradient background for the closeButton.colors.closeButton.fill.top
(Default is “#F5F5F5”)colors.closeButton.fill.bottom
(Default is “#F36”)
colors.closeButton.stroke
(object) Used to create a gradient stroke for the closeButton (does not work in Internet Explorer).colors.closeButton.stroke.top
(Default is “#FFF”)colors.closeButton.stroke.bottom
(Default is “#F00”)
Drawbacks
A system like this is bound to have drawbacks, and the biggest one is probably accessibility. Users with a screen reader or similar device may find the custom modal completely unusable. This is the same problem most RIAs face due to dynamically generated content. I’m considering implementing a check that uses a traditional JavaScript alert
, prompt
or confirm
window in lieu of the custom modal if the user is using a screen reader. The check may or may not be based on whether WAI-ARIA mode is activated, but I have a long way to go before I’m ready for that! (Side note: To see WAI-ARIA in action, check out Google Reader.)
Another drawback is the mingling of my CSS with my JavaScript; in most cases I don’t like using JavaScript to set styles, except to set a classname. However, in this case I want the modal window to be as simple as possible and look nice out-of-the-box without requiring adding CSS files and all that jazz.
Lastly, I’d like to point out that the window doesn’t auto-size to fit the content. However, if the the HTML content doesn’t fit, the main content div will sprout scrollbars, ensuring you still have access to all of the content.
Anyway, this has been a fun experiment for me. It’s taught me a lot about what goes into creating feature-rich and flexible JavaScript widgets. I have nothing but respect for people who make JavaScript-based UI components like the folks behind MochaUI, Dojo, and YUI. It’s a TON of work.