Fancybox on Web Forms

My “lightbox” of choice for web development is the jQuery plugin Fancybox. It is simple, lightweight and completely customizable. Future tutorials will go more in depth with using and customizing Fancybox. One of the issues is fancybox on web forms does not work when showing server controls inline. This tutorial will walk through the steps to get Fancybox working properly.

Here’s the scenario. Say you have an form on a page with a GridView showing a list of names (say, from the Northwind sample database). Above the gridview you would like to provide a link or button to add a new name. You’ve created a Panel on the page that holds the controls to add a new name.

To get started, create a new WebForm. I called my Default.aspx. In order for this example to work  we’ll need to download jQuery and Fancybox and reference them in the <head> section of our new page.

You may notice I put Fancybox in a js/fancybox folder. I like to keep things organized. Where you put them it totally up to you. You may also notice, I’m reference jQuery from another location (http://res.alychidesigns). I’ll explain in a future post, but in short, I’m tired of copying js files to each project so I’ve created a repository of JavaScript and CSS files on my site.

We also need to initialize our fancybox. I prefer to add JavaScript at the bottom of the page (just above the closing </body> tag). You can put the script in the head if you prefer. Here’s the fancybox initialization code:

This code basically calls all items that have the class “fancybox” and adds the fancybox event to each.

Continue on with this post to get Fancybox playing nice with your form.

Before we begin, I want to note that the below fix only applies to opening “inline” elements on forms (elements such as Panels that are on the same page). Fancybox is also capable of opening external pages (including web forms) inside an iframe. Using iframes is my preferred method, but sometimes it would be nice just to do stuff all on one page. That’s where the following solution comes in handy.

The ID issue

You would like this panel to open in a “lightbox”. On the Fancybox How To page it tells you that to open an element on the same page in a Fancybox you set it’s href to “#itemid” (there are ways to open a Fancybox without having to use a hyperlink but that is for future posts.) like this:

Ok, so that’s pretty easy, right? You can just set the NavigateUrl property of the HyperLink hlNew to be “#pnlAddForm.” Right? Not so fast. In this simple example this will work but in the real world you will will more than likely be using a MasterPage. And while master pages can be life savers, they do a number on page controls and their ids. In our example, if the panel pnlAddForm was in a ContentPlaceHolder then the id, although would stay the same when working with before runtime (when you’re not viewing the page in a browser), at runtime (when you are viewing the page in a browser) the id of the panel becomes something like “MainContent_pnlAddForm.” So if you set the href of the hyperlink #pnlAddForm Fancybox will not be able to find any elements with this ID so it will not work.

There are two ways to fix this, the correct way and the incorrect way (actually there are several incorrect ways to do it but since I’m going to show you the correct one you won’t have to worry about those). The incorrect way would be to hard-code the href on the page. Rather href=”#pnlAddForm” it would be href=”#MainContent_pnlAddForm.” The problem with this approach is, 1) If the ID of the ContentPlaceHolder on the MasterPage changes the id will no longer be that, and 2) it’s just not right, so don’t do it.

The correct way to do this is to use the ClientID property. This property provides what the ID will be when rendered to the browser, not what it is during development. Best way to do this is in the code-behind during the Page_Load event.

It’s that simple. Now, if for some strange reason the ID doesn’t end up being “MainContent_pnlAddForm” then it doesn’t matter because the href will be set to the correct ID.

This will not fix everything though. If you view the page in a browser and click on the hyperlink to add a name, nothing will happen. Fixing the ID issue is just the first step. There are more.

The Visible property vs. the CSS display property issue

In the code we started with the Panel (pnlAddForm) Visible property is set to False. This makes sense. You only want the form to display when the user clicks the “Add” link so it should initially be hidden when the page loads.

If you want to work with this panel with Fancybox, jQuery or any other JavaScript it will not work. Why, you ask. Well, it won’t work because the panel doesn’t exist on the page. If you view the source from your browser you and search for a div with the id of pnlAddForm (or MainContent_pnlAddForm) it will not be there. Setting Visible=”False” for any web control (or any control with runat=”server” for that matter) will not show up in the source code. It will not exist until you set Visible=”True”.

So, to use Fancybox with this panel, we cannot set it’s visibility to false.

Your next thought may be, “Ok, how about setting the style of the panel to display: none?”

Ok, you’re on to something now. Well almost.

Setting the style=”display: none” in the panel is a good idea. (note: you may notice if you’re working with Visual Studio that IntelliSense does not provide a Style property for a Panel. “Faget about et” **said in a fake NJ accent**. I won’t throw an error, the development team must have just forgot to put it in there. You won’t receive any errors or anything.)

Here’s the updated code with style set to display: none:

What happens when you click on the “Add Name” link a Fancybox will appear, which is splendid. The not-so-splendid part is the Fancybox is empty.

Read Also:  How to Clear Facebook Cache URL

There are a couple ways to fix this. No real wrong way necessarily. Although one way is much more involved than the other. When initializing our Fancybox script $(‘.fancybox’).fancybox({…}); we could set a function to the onStart event.

I’d prefer not to do this because there is a lot of coding involved and it’s not full-proof. Not only would you have to add a function for onStart you would also have to do one to re-hide it in the onClosed event. I especially don’t prefer this method because there is one far more simple and works great.

Figured it out yet? All we have to do is add any Panels or other elements we want to open in a Fancybox inside a div that is hidden. (I normally create a .hidden class in my style sheet for this purpose. I rarely ever use in-line styles.)

View the page in your browser after this change and, wallah, our add form is in a Fancybox!

Now we need to add some code-behind to show a message when the add button is clicked. Let’s also add another panel with a message to display (I’ve set Visible=”False” for this panel since it will not be used with any client-side scripting). Make sure you “hook up” the con

Also need to “hook up” the OnClick property to the new method in the code-behind.

Let’s test it again. View the page in a browser, click on the “Add Name” link to open the form in a Fancybox, enter a name and click the Save button.

Does it work?

No? Are you sure?

All this time on this tutorial and it doesn’t work? Well son of a motherless goat!

It’s ok. Don’t toss your monitor on the floor or put a hammer through it just yet. There’s one more thing we need to do to get this working.

Fixing Fancybox

Read me now, believe me later when I say this took me forever to figure out. The triumphant joy I was feeling after getting the form just to display in Fancybox turned to bitter anguish the more and more I fought with this. I just could not figure out why my page wasn’t doing anything when I click on that blasted button. After a while I figured out it wasn’t the button. Nothing within that Fancybox would cause a post-back to the server, and for the life of I didn’t get why.

I was definitely getting to the point of looking for the hammer when I decided to take a look at the code-behind of the page. I am convinced the moment I finally figured out why this was happening (or wasn’t happening) was comparable to when Newton had that apple fall on his head.

Fancybox itself was the problem!

Fancybox, actually removes the targeted element from the DOM (fancy word for the tree of the web page HTML code) and adds it inside some divs created by Fancybox at the bottom of the page (just before the closing </body> tag). The reason form buttons or other controls won’t do a post-back to the server is because Fancybox removed the controls from the form. These controls must be in the form to work.

The Fix

It is actually quite simple to fix this but it requires us to actually change the code inside the Fancybox JavaScript file. Just remember if you upgrade to a newer version of Fancybox you remember what you did.

There are two different Fancybox files, a “source code” version (currently jquery.fancybox-1.3.4.js) for development and a “packed” or “minified” version for production (currently jquery.fancybox-1.3.4.pack.js).

Updating the “Source Code” version

Open the file in notepad, Visual Studio or whatever your text editor of choice is and search for “$(‘body’).append(“. It should be in toward the bottom of the file in a function called $.fancybox.init. Change that line to the following:

Updating the “packed” version

This is a bit trickier since all the JavaScript basically is on one line. Lucky for you I’m going to tell you exactly how to do it. It would probably be a good idea to make a backup copy of this file just in case it gets royally messed up. Again, open the file up (jquery.fancybox-1.3.4.pack.js) in your handy, dandy text editor. This time search for “b(“body”).append(” and change it to:

To make sure this only happens on pages I added a class=”serverform” to the form. This class will need added to any form you want to use Fancybox with.

Now we’re ready to test it again.

It works!!

This fix only affects inline fancybox elements. Fancybox works great pulling pages with iframes. But more on that in future posts!

If you have any questions or problems getting this code to work, make sure to leave a comment below and I’ll try to help out any way that I can.

Leave a Reply

Your email address will not be published. Required fields are marked *