Friday, March 27, 2009

A Basic Example of JQuery's UI.Dialog Dynamically Loading an URL with an IFRAME

Given the momentum that JQuery has had lately with .Net, I wanted to try out loading a form into a "lightbox" as an alternative to writing a webpart for SharePoint. So a first step is just to get the "lightbox" approach working. I used the JQuery UI Build Your Download page to build a barebones download for version 1.7.1. This download gives a nice bundle with demo pages--however I didn't see any pages with an example of dynamically loading an URL using an IFRAME. Searching the web turned up lots of stuff, but between different versions of the toolkit, options for using other plugins, and different approaches--I didn't quite find a nice simple example. So here goes.

Upon unpacking the download archive, you'll get a folder structure. I put my sample html files along side the html files in \development-bundle\demos\dialog, so if you're following along, that's where you should put the samples below.

In this first sample, the IFRAME is placed inside a DIV. In the second sample, the IFRAME is dynamically generated into the DIV--so it doesn't have to appear in the DIV content intially. In either case, there is some boilerplate css and jquery files that are loaded (they are pretty small in size compared to some other javascript libraries fortunately). Both samples also show the $(document).ready() function used to specify settings for the dialog. Then a links onclick method invokes the showDialog method. When the IFRAME is statically part of the div tag, it's src attribute is simply set in shoeDialog using JQuery's attr method.
<!DOCTYPE html><html><head>

<link type="text/css" href="../../themes/base/ui.all.css" rel="stylesheet" />

<script type="text/javascript" src="../../jquery-1.3.2.js"></script>
<script type="text/javascript" src="../../ui/ui.core.js"></script>
<script type="text/javascript" src="../../ui/ui.dialog.js"></script>

<script type="text/javascript">
function showDialog(){
$("#divId").dialog("open");
$("#modalIframeId").attr("src","http://www.google.com");
return false;
}

$(document).ready(function() {
$("#divId").dialog({
autoOpen: false,
modal: true,
height: 500,
width: 500
});
});
</script>
</head>
<body >

<a href="" onclick="return showDialog()">Show the Dialog</a>

<div id="divId" title="Dialog Title">
<iframe id="modalIframeId" width="100%" height="100%"
marginWidth="0" marginHeight="0" frameBorder="0" scrolling="auto"
title="Dialog Title">Your browser does not suppr</iframe>
</div>

</body>
</html>


For the second sample, just a few lines are different--removing the IFRAME from the DIV, and instead creating it in the showDialog method.

<!DOCTYPE html><html><head>

<link type="text/css" href="../../themes/base/ui.all.css" rel="stylesheet" />

<script type="text/javascript" src="../../jquery-1.3.2.js"></script>
<script type="text/javascript" src="../../ui/ui.core.js"></script>
<script type="text/javascript" src="../../ui/ui.dialog.js"></script>

<script type="text/javascript">
function showDialog(){
$("#divId").html('<iframe id="modalIframeId" width="100%" height="100%"
marginWidth="0" marginHeight="0" frameBorder="0" scrolling="auto" />').dialog("open");
$("#modalIframeId").attr("src","http://www.google.com");
return false;
}

$(document).ready(function() {
$("#divId").dialog({
autoOpen: false,
modal: true,
height: 500,
width: 500
});
});
</script>
</head>
<body >

<a href="" onclick="return showDialog()">Show the Dialog</a>

<div id="divId" title="Dialog Title" />

</body>
</html>

In either case, you can specify attributes on the IFRAME to control standard IFRAME features, and you can also use different options for the ui.dialog, described here (the JQuery documentation is quite good). Currently, the samples only use scrolling when required.

Wednesday, March 11, 2009

No BackStage Pass for Nested Classes in C#

In java land, I used to use nested classes to simplify a class that was getting complicated. If a class grew a cluster of fields and logic related to a single concept, I would create an inner class to encapsulate all that thus making the outer class simpler to understand--basic OO modularity/cohesion principles. Yes, some folks don't like inner classes and in java the compiler actually opens up the access modifiers of the fields--but I found it useful. But in C#, the nested class doesn't share any special access into the outer/enclosing class (perhaps for security reasons?). The workaround seems to be to pass in an instance of the outer class. The problem with this is that without special access to the internals of the outer class (fields, etc), you have to start modifying the access modifiers of the outer class, or start pushing all the state into the nested class via constructors or methods/properties. But that defeats the purpose--the idea was to keep the API to the outer class the same and keep the change encapsulated between the outer and nested class. The workaround I'm using is to have a special method on the outer class that has all the business logic needed to construct the nested class. Not perfect, but it seems like a decent compromise.