Friday, June 11, 2010

Telerik RadWindow Client-Side Content Container

Telerik RadControls for ASP.NET AJAX is a powerful set of .NET controls for Web Forms (they also have control sets for MVC, Silverlight, Windows Forms, WPF, and other productivity tools).  We use 'RadControls' all the time.  RadControls provide near Windows Forms-based controls functionality.  The RAD ability of RadControls is untouchable.

The caveat with RadControls is that if you want to go out-of-box Telerik box and extend the functionality or use it in a way that different for the Telerik way of developing Web interface, you're often let down after hours of 'trying' to make the controls work 'your' way.  Case in-point: RadWindow.

RadWindow is your basic inline popup that provide an IFRAME for rendering external content.  Until last year, displaying inline content (Telerik describes it at 'internal content') where the RadWindow's source is not an external page was close to impossible.  Rendering inline content in a RadWindow still isn't documented all that well.

I'll save you the details on the Telerik recommended solution to providing inline content (you can read about it here and somewhere in here).  Well, you've probably realized that this did not meet my requirements.  I wanted to have client-side RadWindow support to render dialogs with content retrieved from Web services, inline hidden elements, JavaScript, etc...  So, I created a small library that I can include as a reference in my pages to give me my desired functionality.

Before I post my solution, I need to give you a quick background on my design and code structure for Web Forms.  I tend to have a Master Page that includes common libraries (jQuery, Telerik Core, project specific, etc...).  When I use RadWindows I add a RadWindowsManager to my Master Page.  This provides all the Telerik RadWindow client-side libararies that I need.  My Master Pages also implement an Interface that contain references to .NET controls on the Master Page.  This gives Page controls type-safe access to the Master Page and the controls contained with in the Master Page.

So, here's the code.  It's fully documented, so you shouldn't have a problem using it.

/*
* File Name: telerik.radwindow.extensions.js
* Requirements:
* - Telerik.Web.UI.RadWindowManager client-side library
*   - adding a RadWindowManager control to the top of the page will add all the necessary libraries, include Telerik Core and jQuery.
*/

// namespace this libarary to avoid namespace clashes.
var radWindowExtensions = (radWindowExtensions || {});

radWindowExtensions.openDialog = function(options) { /* @options: extend the 'defaults' object map of the function. */
   // get the rad window manager - throw exception if RadWindowManager client-side library is not loaded.
   var rwm = null; try { rwm = GetRadWindowManager(); } catch (e) { throw new Error('Telerik.Web.UI.RadWindowManager client-side library is not loaded.'); }
   var defaults = {
      width: 500, /* outer width of rad window */
      height: 500, /* outer height of rad window */
      modal: true, /* is modal? */
      center: true, /* center rad window? */
      resizable: true, /* is rad window resizable? */
      title: '', /* rad window title */
      content: '', /* rad window content */
      xBorderSize: 16, /* the size of the horizontal borders */
      yBorderSize: 61, /* the size of the vertical borders */
      xPos: Number.NaN, /* x-position of the rad window */
      yPos: Number.NaN, /* y-position of the rad window */
      // event handler 'this' reference is to the current RadWindow.  @content parameter is a reference to the jQuery wrapped content
      onOpen: function(content) { }, /* onOpen event handler */
      onClosing: function(content) { }, /* onClosing event handler */
      onClosed: function(content) { } /* onClosed event handler */
   };
   // merge @options with default settings
   options = $telerik.$.extend({}, defaults, (options) ? options : {});

   // parse the x and y positions
   options.xPos = parseInt(options.xPos); options.yPos = parseInt(options.yPos);

   // create a rad new window (and open - this is required)
   var win = rwm.open(null, null);

   // remove the iframe from the default rad window
   $(win._iframe).remove();

   // render the window as modal
   if (options.modal) { win.set_modal(options.modal); }

   // set the window width
   win.set_width(options.width);

   // set the window height
   win.set_height(options.height);

   // set the window xy coordinates or center the window or use default positioning
   if ((!isNaN(options.xPos)) && (!isNaN(options.yPos))) win.moveTo(options.xPos, options.yPos);
   else if (!!options.center) win.center();

   // set the window title
   win.set_title(options.title);

   // create the content and wrap in a parent div
   var $content = $telerik.$('<div></div>').width(options.width - options.xBorderSize).height(options.height - options.yBorderSize).css('overflow', 'auto').append(options.content);
// destroy on close
   win.set_destroyOnClose(true);

   // add onClosing and onClosed event handlers
   win.add_beforeClose(function() { options.onClosing.call(win, $content); });
   win.add_close(function() { options.onClosed.call(win, $content); });

   // set the window behaviors (Move and Close)
   win.set_behaviors(Telerik.Web.UI.WindowBehaviors.Move + Telerik.Web.UI.WindowBehaviors.Close + ((!!options.resizable) ? Telerik.Web.UI.WindowBehaviors.Resize : 0));

   // add the wrapped content to the rad window - use the set_contentElement(content) function
   setTimeout(function() {
      win.set_contentElement($content.get(0));
      // fire the onOpen event handler
      if (options.onOpen) options.onOpen.call(win, $content);
   }, 0);
};

When using this library, I use a minimized version of the file.  To minimize JavaScript and CSS files, I use Yahoo! UI Compressor Library: YUI Compressor for .NET located on CodePlex or I use the Online YUI Compressor located here.

EDIT:  the formatting for the JavaScript above is parsed incorrectly and displaying two code blocks.  If you are copying and pasting the code, copy both blocks and create a single code file.  Sorry about that...

Thanks for reading...

No comments: