jQuery UI—The Dialog: Part 1

Exclusive offer: get 50% off this eBook here
jQuery UI 1.6: The User Interface Library for jQuery

jQuery UI 1.6: The User Interface Library for jQuery — Save 50%

Build highly interactive web applications with ready-to-use widgets of the jQuery user interface library

$26.99    $13.50
by Dan Wellman | February 2009 | Content Management Open Source PHP

Traditionally, the way to display a brief message or ask a visitor a question would be to use one of JavaScript's native dialog boxes, such as alert or confirm, or to open a new web page with a predefined size, styled to look like a dialog box. Unfortunately, neither of these methods is particularly flexible or engaging. For each problem they solve, several new problems are usually introduced.

Thankfully, the days of resorting to either of the aforementioned techniques are over. We can now make use of the advanced functionality and rich features of the jQuery UI dialog widget. The dialog widget lets us display a message, supplemental content (like images or text), or even interactive content (like forms). It's also very easy to add buttons, such as simple ok and cancel buttons, to the dialog and define callback functions for them in order to react to their being clicked.

In this first part of the article by Dan Wellman, we will complete the following tasks:

  • Create a basic dialog
  • Create a custom dialog skin
  • Work with dialog's properties
  • Enable modality and see an overlay
  • Add buttons to the dialog
  • Work with dialog's callbacks.

The following screenshot shows a dialog widget and the different elements that it is made of:

jQuery UI 1.6: The User Interface Library for jQuery

A basic dialog

A dialog has a lot of default behavior built-in, but few methods are needed to control it programmatically, making this a very easy widget to use that is also highly configurable.

Generating it on the page is very simple and requires a minimal underlying mark-up structure. The following page contains the minimum mark-up that's required to implement the dialog widget:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="jqueryui1.6rc2/themes/flora/flora.dialog.css">
<link rel="stylesheet" type="text/css" href="jqueryui1.6rc2/themes/flora/flora.resizable.css">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>jQuery UI Dialog Example 1</title>
</head>
<body>
<div id="myDialog" class="flora" title="This is the title">Lorem
ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
sollicitudin. Sed interdum pulvinar justo. Nam iaculis volutpat
ligula. Integer vitae felis quis diam laoreet ullamcorper. Etiam
tincidunt est vitae est. Ut posuere, mauris at sodales rutrum,
turpis tellus fermentum metus, ut bibendum velit enim eu lectus.
Suspendisse potenti. Donec at dolor ac metus pharetra aliquam.
Suspendisse purus. Fusce tempor ultrices libero. Sed quis nunc.
Pellentesque tincidunt viverra felis. Integer elit mauris,
egestas ultricies, gravida vitae, feugiat a, tellus.</div>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="jqueryui1.6rc2/jquery-1.2.6.js"></script>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="jqueryui1.6rc2/ui/ui.core.js"></script>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="jqueryui1.6rc2/ui/ui.dialog.js"></script>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="jqueryui1.6rc2/ui/ui.resizable.js"></script>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="jqueryui1.6rc2/ui/ui.draggable.js"></script>
<script type="text/javascript">
//define function to be executed on document ready
$(function(){
//create the dialog
$("#myDialog").dialog();
});
</script>
</body>
</html>

Dialog properties

An options object can be used in a dialog's constructor method to configure various dialog properties. Let's look at the available properties:

Save this as dialog1.html in the jqueryui folder. A few more source files are required, specifically the ui.resizable.js and ui.draggable.js files and the flora.resizable.css stylesheet.

The JavaScript files are low-level interaction helpers and are only required if the dialog is going to be resizable and draggable. The widget will still function without them. The dialog flora theme file is a mandatory requirement for this component, although the resizable one isn't.

Other than that, the widget is initialized in the same way as other widgets. When you run this page in your browser, you should see the default dialog widget shown in the previous screenshot, complete with draggable and resizable behaviors.

One more feature that I think deserves mentioning here is modality. The dialog comes with modality built-in, although it is disabled by default. When modality is enabled, a modal overlay element, which covers the underlying page, will be applied. The dialog will sit above the overlay while the rest of the page will be below it.

The benefit of this feature is that it ensures the dialog is closed before the underlying page becomes interactive again, and gives a clear visual indicator that the dialog must be closed before the visitor can proceed.

Custom dialog skins

The dialog's appearance is easy to change from the flora theme used in the first example. Like some of the other widgets, certain aspects of the default or flora themes are required to make the widget function correctly. Therefore, when overriding styles, we need to be careful to just override the rules related to the dialog's display.

When creating a new skin for the default implementation, including resizable behavior, we have a lot of new files that will need to be created. Apart from new images for the different components of the dialog, we also have to create new images for the resizing handles. The following files need to be replaced when skinning a dialog:

  • dialog-e.gif
  • dialog-n.gif
  • dialog-ne.gif
  • dialog-nw.gif
  • dialog-s.gif
  • dialog-se.gif
  • dialog-sw.gif
  • dialog-title.gif
  • dialog-titlebar-close.png
  • dialog-titlebar-close.png

To make it easier to remember which image corresponds to which part of the dialog, these images are named after the compass points at which they appear. The following image illustrates this:

jQuery UI 1.6: The User Interface Library for jQuery

Note that these are file names as opposed to class names. The class names given to each of the different elements that make up the dialog, including resizable elements, are similar, but are prefixed with ui- as we'll see in the next example code.

Let's replace these images with some of our own. In a new file in your text editor, create the following stylesheet:

.flora .ui-dialog, .flora.ui-dialog {
background-color:#99ccff;
}
.flora .ui-dialog .ui-dialog-titlebar, .flora.ui-dialog
.ui-dialog-titlebar {
background:url(../img/dialog/my-title.gif) repeat-x;
background-color:#003399;
}
.flora .ui-dialog .ui-dialog-titlebar-close, .flora.ui-dialog
.ui-dialog-titlebar-close {
background:url(../img/dialog/my-title-close.gif) no-repeat; }
.flora .ui-dialog .ui-dialog-titlebar-close-hover, .flora.ui-dialog
.ui-dialog-titlebar-close-hover {
background:url(../img/dialog/my-title-close-hover.gif) norepeat;
}
.flora .ui-dialog .ui-resizable-n, .flora.ui-dialog .ui-resizable-n {
background:url(../img/dialog/my-n.gif) repeat center top;
}
.flora .ui-dialog .ui-resizable-s, .flora.ui-dialog .ui-resizable-s {
background:url(../img/dialog/my-s.gif) repeat center top;
}
.flora .ui-dialog .ui-resizable-e, .flora.ui-dialog .ui-resizable-e {
background:url(../img/dialog/my-e.gif) repeat right center; }
.flora .ui-dialog .ui-resizable-w, .flora.ui-dialog .ui-resizable-w {
background:url(../img/dialog/my-w.gif) repeat left center;
}
.flora .ui-dialog .ui-resizable-ne, .flora.ui-dialog .ui-resizable-ne
{
background:url(../img/dialog/my-ne.gif) repeat;
}
.flora .ui-dialog .ui-resizable-se, .flora.ui-dialog .ui-resizable-se
{
background:url(../img/dialog/my-se.gif) repeat;
}
.flora .ui-dialog .ui-resizable-sw, .flora.ui-dialog .ui-resizable-sw
{
background:url(../img/dialog/my-sw.gif) repeat;
}
.flora .ui-dialog .ui-resizable-nw, .flora.ui-dialog .ui-resizable-nw
{
background:url(../img/dialog/my-nw.gif) repeat;
}

Save this as dialogTheme.css in the styles folder. We should also create a new folder within our img folder called dialog. This folder will be used to store all of our dialog-specific images.

All we need to do is specify new images to replace the existing ones used by flora. All other rules can stay the same. In dialog1.html, link to the new file with the following code, which should appear directly after the link to the resizable stylesheet:

<link rel="stylesheet" type="text/css" href="styles/dialogTheme.css">

Save the change as dialog2.html. These changes will result in a dialog that should appear similar to the following screenshot:

jQuery UI 1.6: The User Interface Library for jQuery

So you can see that skinning the dialog to make it fit in with your existing content is very easy. The existing image files used by the default theme give you something to start with, and it's really just a case of playing around with colors in an image editor until you get the desired effect.

Dialog properties

An options object can be used in a dialog's constructor method to configure various dialog properties. Let's look at the available properties:

Property

Default Value

Usage

autoOpen

true

Shows the dialog as soon as the dialog method is called

bgiframe

true

Creates an <iframe> shim to prevent <select> elements showing through the dialog in IE6 - at present, the bgiframe plugin is required, although this may not be the case in future versions of this widget

buttons

 

{}

Supplies an object containing buttons to be used with the dialog

dialogClass

ui-dialog

Sets additional class names on the dialog for theming purposes

draggable

true

Makes the dialog draggable (use ui.draggable.js)

height

200(px)

Sets the starting height of the dialog

hide

none

Sets an effect to be used when the dialog is closed

maxHeight

none

Sets a maximum height for the dialog

maxWidth

none

Sets a maximum width for the dialog

minHeight

100(px)

Sets a minimum height for the dialog

minWidth

150(px)

Sets a minimum width for the dialog

modal

false

Enables modality while the dialog is open

overlay

{}

Object with CSS properties for the modal overlay

position

center

Sets the starting position of the dialog in the viewport

resizable

true

Makes the dialog resizable (also requires ui.resizable.js)

show

none

Sets an effect to be used when the dialog is opened

stack

true

Causes the focused dialog to move to the front when several dialogs are open

title

none

Alternative to specifying title on source element

width

300(px)

Sets the original width of the dialog

jQuery UI 1.6: The User Interface Library for jQuery Build highly interactive web applications with ready-to-use widgets of the jQuery user interface library
Published: February 2009
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

As you can see, we have a range of configurable properties to work with in our dialog implementations. Many of these properties are boolean or numerical, and string-based, making them extremely easy to set and work with.

In our examples so far, the dialog has opened as soon as the page has loaded, or as soon as the dialog constructor method is called, which is as soon as the page is ready in this case. We can change this so that the dialog is opened when something else occurs. For example, a <button> being clicked, say, by adjusting the autoOpen property. We'll come back to this property when we look at the open method a little later on.

The position property controls where the dialog is rendered in the viewport when it is opened and accepts either a string or an array value. The strings may be one of the following values:

  • bottom
  • center
  • left
  • right
  • top

An array is used when you want to specify the exact coordinates of the top-left corner where the dialog should appear. The coordinates are specified as an offset from the top-left corner of the viewport.

The previous table shows a title property. Although the title for the dialog can be set using the title attribute of the underlying HTML element, using the title property is preferred. This will stop the dialog from displaying the title when the body of the dialog widget is hovered over.

One of the dialog's greatest assets is modality. This feature creates an overlay when the widget is opened that sits above the page content but below the dialog. The overlay is removed as soon as the dialog is closed. But while the dialog is open, none of the underlying page content can be interacted with in any way.

When using the modal feature of the dialog widget, we also need to configure the overlay property too. Change dialog2.html to this:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="jqueryui1.6rc2/themes/flora/flora.dialog.css">
<link rel="stylesheet" type="text/css" href="jqueryui1.6rc2/themes/flora/flora.resizable.css">
<link rel="stylesheet" type="text/css" href="styles/dialogTheme.css">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>jQuery UI Dialog Example 3</title>
</head>
<body>
<div id="myDialog" class="flora" title="This is the title">Lorem
ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
sollicitudin. Sed interdum pulvinar justo. Nam iaculis volutpat
ligula. Integer vitae felis quis diam laoreet ullamcorper. Etiam
tincidunt est vitae est. Ut posuere, mauris at sodales rutrum, turpis
tellus fermentum metus, ut bibendum velit enim eu lectus. Suspendisse
potenti. Donec at dolor ac metus pharetra aliquam. Suspendisse purus.
Fusce tempor ultrices libero. Sed quis nunc. Pellentesque tincidunt
viverra felis. Integer elit mauris, egestas ultricies, gravida vitae,
feugiat a, tellus.</div>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="jqueryui1.6rc2/jquery-1.2.6.js"></script>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="jqueryui1.6rc2/ui/ui.core.js"></script>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="jqueryui1.6rc2/ui/ui.dialog.js"></script>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="jqueryui1.6rc2/ui/ui.resizable.js"></script>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="jqueryui1.6rc2/ui/ui.draggable.js"></script>
<script type="text/javascript">
//define function to be executed on document ready
$(function(){
//define config object
var dialogOpts = {
modal: true,
overlay: {
background: "url(img/modal.png) repeat"
}
};
//create the dialog
$("#myDialog").dialog(dialogOpts);
});
</script>
</body>
</html>

This file can be saved as dialog3.html. When you view the page in a browser, you'll see the modal effect immediately.

We've used a repeated, semi-transparent PNG image for the overlay in this example for simplicity, but other CSS properties such as background colors and opacity are also acceptable. The path to the PNG is specified as the value of the overlay property, so you can see how this property and the modal property should be used together.

The PNG used in this example is a simple square one pixel high by one pixel wide. The image is made of the color #999999 set to approx 25% transparency.

Adding buttons

One of the properties we saw a moment ago was the button property. This property accepts a literal object and is used to specify the  <button> elements that should be present on the dialog. Let's add an ok! <button> to our dialog. Alter dialog3.html so that it appears like this:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="jqueryui1.6rc2/themes/flora/flora.dialog.css">
<link rel="stylesheet" type="text/css" href="jqueryui1.6rc2/themes/flora/flora.resizable.css">
<link rel="stylesheet" type="text/css" href="styles/dialogTheme.css">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>jQuery UI Dialog Example 4</title>
</head>
<body>
<div id="myDialog" class="flora" title="This is the title">Lorem
ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
sollicitudin. Sed interdum pulvinar justo. Nam iaculis volutpat
ligula. Integer vitae felis quis diam laoreet ullamcorper. Etiam
tincidunt est vitae est. Ut posuere, mauris at sodales rutrum, turpis
tellus fermentum metus, ut bibendum velit enim eu lectus.</div>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="jqueryui1.6rc2/jquery-1.2.6.js"></script>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="jqueryui1.6rc2/ui/ui.core.js"></script>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="jqueryui1.6rc2/ui/ui.dialog.js"></script>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="jqueryui1.6rc2/ui/ui.resizable.js"></script>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="jqueryui1.6rc2/ui/ui.draggable.js"></script>
<script type="text/javascript">
//define function to be executed on document ready
$(function(){
//define doOk function
var doOk = function() {
}
//define config object
var dialogOpts = {
modal: true,
overlay: {
background: "url(img/modal.png) repeat",
},
buttons: {
"Ok!": doOk
},
height: "250px"
};
//create the dialog
$("#myDialog").dialog(dialogOpts);
});
</script>
</body>
</html>

Save the file as dialog4.html. The key for each property in the buttons object is the text that will form the <button> label, and the value is the name of the callback function to execute when the <button> is clicked.

We've added the doOk function as the behavior for our new <button>. Although it won't do anything at this stage, the page won't work without it. We can come back to this function when we look at a dialog's methods.

We also configured the height property in this example. The buttons that we create are absolutely positioned at the bottom of the dialog. Therefore, we need to increase the height of the widget so that the <button> does not obscure the text.

We can also style the <button> itself by using the following selector. We need to do this in order to move the <button> up from the bottom edge of the widget slightly. Add the following code to dialogTheme.css:

.flora .ui-dialog .ui-dialog-buttonpane button, .flora.ui-dialog
.ui-dialog-buttonpane button { margin-bottom:10px; }

View the new file in your browser. It should appear something like the following screenshot:

jQuery UI 1.6: The User Interface Library for jQuery

Working with dialog's callbacks

The dialog widget gives us a wide range of callback properties that we can use to execute arbitrary code at different points in any dialog interaction. The following table lists the properties available to us:

Property

Fired When

close

The dialog is closed

 

drag

The dialog is being dragged

 

dragStart

The dialog starts being dragged

 

dragStop

The dialog stops being dragged

 

focus

The dialog receives focus

 

open

The dialog is opened

 

resize

The dialog is being resized

 

resizeStart

The dialog starts to be resized

 

resizeStop

The dialog stops being resized

Some of these callbacks are only available in certain situations, such as the drag and resize callbacks, while others such as the open, close, and focus callbacks, will be available in any implementation. Let's look at an example in which we can make use of some of these callback properties. In a new page in your text editor, add the following code:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="jqueryui1.6rc2/themes/flora/flora.dialog.css">
<link rel="stylesheet" type="text/css" href="jqueryui1.6rc2/themes/flora/flora.resizable.css">
<link rel="stylesheet" type="text/css" href="styles/dialogTheme.css">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>jQuery UI Dialog Example 5</title>
</head>
<body>
<div id="myDialog" class="flora" title="This is the title">Lorem
ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
sollicitudin. Sed interdum pulvinar justo. Nam iaculis volutpat
ligula. Integer vitae felis quis diam laoreet ullamcorper. Etiam
tincidunt est vitae est. Ut posuere, mauris at sodales rutrum, turpis
tellus fermentum metus, ut bibendum velit enim eu lectus. Suspendisse
potenti. Donec at dolor ac metus pharetra aliquam. Suspendisse purus.
Fusce tempor ultrices libero. Sed quis nunc. Pellentesque tincidunt
viverra felis. Integer elit mauris, egestas ultricies, gravida vitae,
feugiat a, tellus.</div>
<p id="status">The dialog is closed</p>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="jqueryui1.6rc2/jquery-1.2.6.js"></script>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="jqueryui1.6rc2/ui/ui.core.js"></script>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="jqueryui1.6rc2/ui/ui.dialog.js"></script>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="jqueryui1.6rc2/ui/ui.resizable.js"></script>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="jqueryui1.6rc2/ui/ui.draggable.js"></script>
<script type="text/javascript">
//define function to be executed on document ready
$(function(){
//define config object
var dialogOpts = {
open: function() {
//change status
$("#status").text("The dialog is open");
},
close: function() {
//change status
$("#status").text("The dialog is closed");
}
};
//create the dialog
$("#myDialog").dialog(dialogOpts);
});
</script>
</body>
</html>

Save this as dialog5.html. Our configuration object uses the open and close properties to specify simple callback functions. These change the text of the status message depending on the state of the dialog.

When the dialog is opened, the text will be changed to reflect this, and likewise, when it is closed, the text will be changed. It's a simple page, but it highlights the points at which the open and close events are fired and shows how easy these properties are to use.

Summary

The dialog widget is extremely specialized and is catered to the display of a message or question in a floating panel that sits above the page content. Advanced functionality, such as draggability and resizability, are directly built in, and features such as the excellent modality and overlay are easy to configure.

We started out by looking at the default implementation, which is as simple as it is with the other widgets we have looked at so far. However, there are several optional components that can also be used in conjunction with the dialog, such as the draggables and resizable components.

We then moved on to look at the different styling options available for use with the dialog, including the default or flora themes, and how easy it is to override some of these styles to create our own custom theme.

We also examined the range of configurable properties exposed by the dialog's API. We can easily make use of the properties to enable or disable built-in behavior such as modality, or set the dimensions of the widget, as well as giving us a wide range of callbacks that allow us to hook into custom events fired by the widget during an interaction.

In the next and final part of the article, we will learn how to enable animations for the dialog and control the dialog programmatically.

jQuery UI 1.6: The User Interface Library for jQuery Build highly interactive web applications with ready-to-use widgets of the jQuery user interface library
Published: February 2009
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

About the Author :


Dan Wellman

Dan Wellman is an author and frontend engineer living on the South Coast of the UK and working in London. By day he works for Skype and has a blast writing application-grade JavaScript. By night he writes books and tutorials focused mainly on frontend web development. He is also a staff writer for the Tuts+ arm of the Envato network, and occasionally writes for .Net magazine. He's the proud father of four amazing children, and the grateful husband of a wonderful wife.

Books From Packt

Learning jQuery : Better Interaction Design and Web Development with Simple JavaScript Techniques
Learning jQuery : Better Interaction Design and Web Development with Simple JavaScript Techniques

Learning Dojo
Learning Dojo

Magento Beginner's Guide
Magento Beginner's Guide

jQuery Reference Guide
jQuery Reference Guide

Learning Joomla! 1.5 Extension Development
Learning Joomla! 1.5 Extension Development

JBoss Portal Server Development
JBoss Portal Server Development

WordPress Plugin Development (Beginner's Guide)
WordPress Plugin Development (Beginner's Guide)

Practical Plone 3: A Beginner's Guide to Building Powerful Websites
Practical Plone 3: A Beginner's Guide to Building Powerful Websites

Your rating: None Average: 2.8 (4 votes)

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
K
d
m
L
f
V
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software