How can you enhance jQuery UI Dialog to work with WebForms? Find out…

Using jQuery UI Dialog with WebForms

Since the beginning of my current project, I knew that the day would come when the legacy AjaxControlToolkit modals would no longer suffice and we would have to implement something with more control, speed, and scalability. I have been partial to jQuery UI, so I thought that the dialog option it offered was worth a go.

For anyone who has tried this with a form-based solution, I’m sure the first thing you noticed was that the content of the dialog was not being posted to the form. After some scouring, I found some ad hoc solutions, but for a page with many modals with varied purposes, this just wouldn’t work. So, into the jQuery UI code I went…

After beautifying and digging in a bit, I noticed a few things. First, the dialog is appended to the body upon initialization:


_init: function () {
            this.originalTitle = this.element.attr("title");
            var l = this,
                m = this.options,
                j = m.title || this.originalTitle || " ",
                e = c.ui.dialog.getTitleId(this.element),
                k = (this.uiDialog = c("<div/>")).appendTo(document.body).hide()...
}

Here’s the first spot (and the most important for this specific topic) where the dialog is being placed within the context of the body, rather than a submittable form. Before we just go and change this to hit the form in question, it’s a good idea to make it a bit more configurable for later use. Back into the code we go. A little further down, you’ll find the dialog object being extended with some default properties:


 c.extend(c.ui.dialog, {
        version: "1.7.2",
        defaults: {
            autoOpen: true,
            bgiframe: false,
            buttons: {},
            closeOnEscape: true,
            closeText: "close",
            appendToForm: false,
            dialogClass: "",
            draggable: true,
            hide: null,
            height: "auto",
            maxHeight: false,
            maxWidth: false,
            minHeight: 150,
            minWidth: 150,
            modal: false,
            position: "center",
            resizable: true,
            show: null,
            stack: true,
            title: "",
            width: 300,
            zIndex: 1000
        }

I went ahead and kept the default as false, because it’s quite often that I use these dialogs for quick, dynamic informational popups and I don’t need to be worried about setting a lot of properties.

So, back to the initialization – I added a line above the declaration of k, that grabs the element that you want to append the dialog to as to not disturb the flow of the subsequent code.


var z = this.options.appendToForm ? $('form:first') : document.body;

We’ll call this z, because the other variables are named in alphabetical order and I’d bet they won’t hit z anytime soon. Then, right below we appendTo the selected element.


k = (this.uiDialog = c("<div/>")).appendTo(z).hide()...

All right, we’re almost done. Be more patient. The last spot is in the open, where it’s a little trickier. I am not entirely sure of the intent of the following code, but we’ll talk through it and I’ll show you the changes I made.


open: function () {
	if (this._isOpen) {
		return
	}
	var e = this.options,
	d = this.uiDialog;
	this.overlay = e.modal ? new c.ui.dialog.overlay(this) : null;
	(d.next().length && d.appendTo("body"));

Ok, this is confusing to me. The first portion of the highlighted section utilizes the jQuery.next() function, which provides you access to the next sibling in the list. So, what this says is that if a sibling exists (length isn’t 0), append the dialog to the body. In my opinion, the question you want to ask is “is this already appended to the body?” If the answer is no, then go ahead and append it.

Note: In case you aren’t comfortable with this particular nuance of JavaScript, the logical and (&&) is evaluated one side at a time. If the first side is false, the engine will not evaluate the second section. This is a compact way to perform if logic that is completely compatible with minification.

So, I changed the code to read the following:


var z = e.appendToForm ? "form:first" : "body";
(d.parent().length === 0 && d.appendTo(z));

In other words, if the dialog has no parent (it isn’t registered in the DOM at all), then append it to the container of your choice. It seems like this situation will never arise, since the initialization includes the DOM registration code. However, I decided to keep this around because in a future enhancement I will be removing the initialization code and push the content to the form on-demand. Being constrained by the basic principles of WebForms, I want to keep my form as lightweight as possible, so on some of the more complex pages it makes sense to only push data around as it is required when posting back.

Just create and consume the dialog as normal and include { appendToForm: true } to your options and you are off and posting in no time. For your convenience, I’ve attached a modified version of jQueryUI that already has the code in it. Note that this is without warranty and you’re using these enhancements at your own risk.

Note: If anyone cares to add some context to the d.next() situation, please post to the comments.

Attachment: jquery-ui-1.7.2.formdialog.min.js

kick it on DotNetKicks.com


.NET Property Emulation in JavaScript

One of my favorite things about Javascript is the ability to dynamically extend any object. It makes me tingle all over. A technique I’ve grown fond of is to build a pseudo-emulation of a simple C# style property (i.e., a getter and setter in one) using this dynamic extension to handle basic default values (empty


Life, the Universe, and Everything

It’s me time.