Wednesday, July 1, 2009

jQuery Plugins with ASP.NET Controls

After years of frustration with JavaScript and cross browser compatibility, a friend of mine introduced me to the wonderful world of jQuery. Then, after also discovering an endless amount of free plugin libraries for jQuery, I immediately went to work to develop reusable user controls for our internal development library. In this example, I will be using the qtip plugin:

1. First create an .ascx file with a placeholder.
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Tootip.ascx.cs" Inherits="JQueryInterfaceTests.Controls.Tootip" %>

" style="max-height:<%= this.MaxHeight.ToString() %>px; overflow:auto;">




2. Next, you will need to take advantage of registering your .js files in page's ClientScript. This is important because if you drop more than one instance of your control on the page, then you only want to include your .js file once.

public class QTipControl : UserControl, INamingContainer
{
protected override void OnLoad(EventArgs e)
{
string jqPath = this.Page.ResolveClientUrl("~/Javascripts/jquery-1.3.2.js");

if (!this.Page.ClientScript.IsClientScriptIncludeRegistered(jqPath))
this.Page.ClientScript.RegisterClientScriptInclude(jqPath, jqPath);
}

// More Code Here
}


3. Also, you will need to set all attributes that will be abstracted to the properties of the user control for ease of use.

#region Events
protected override void CreateChildControls()
{
//base.CreateChildControls();
}
#endregion

#region Properties
public string MouseOverClientID
{
get;
set;
}

public int MaxHeight
{
get;
set;
}

public Position TargetPosition
{
get;
set;
}

public Position TooltipPosition
{
get;
set;
}

public Position ArrowPosition
{
get;
set;
}

public Color BorderColor
{
get;
set;
}

public Color BackgroundColor
{
get;
set;
}

///
/// If false, then tooltip hides when user unfocuses from the MouseOverClientID element.
/// If true, then tooltip remains and can be interacted with until focus on to another element on the page occurs.
///

public bool IsSticky
{
get;
set;
}
#endregion


4. Finally, you will need to write any initialization for each client instance. Also, you will need to put the content into your placeholder (notice the INamingContainer). Now here is how your OnLoad ought to look now.

[ParseChildren(true)]
public abstract class MyWrapperControl : UserControl, INamingContainer
{
protected override void OnLoad(EventArgs e)
{
string jqPath = this.Page.ResolveClientUrl("~/Javascripts/jquery-1.3.2.js");
string qtipPath = this.Page.ResolveClientUrl(ResourcePaths.JQueryQtipTootipPath);

if (!this.Page.ClientScript.IsClientScriptIncludeRegistered(jqPath))
this.Page.ClientScript.RegisterClientScriptInclude(jqPath, jqPath);

if (!this.Page.ClientScript.IsClientScriptIncludeRegistered(qtipPath))
this.Page.ClientScript.RegisterClientScriptInclude(qtipPath, qtipPath);

// Write to placeholder
using (System.IO.StringWriter sw = new System.IO.StringWriter(sb))
{
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
if (this.Content != null)
this.Content.InstantiateIn(this.phPlaceHolder);

base.CreateChildControls();
base.Render(htw);
}
}

if (!this.Page.ClientScript.IsClientScriptBlockRegistered(this.ClientID))
this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(),
this.ClientID,
"$(document).ready(function(){" +

// Qtip Init
"$(\"#" + this.MouseOverClientID + "\").qtip({" +
"content: {text:'" + sb.ToString().Replace("'", "\\'").Replace(System.Environment.NewLine, string.Empty) + "'}" +
",position:{corner:{target:'" + this.TargetPosition + "',tooltip:'" + this.TooltipPosition + "'}}" +
",style:{tip:'" + this.ArrowPosition + "',name:'cream',background:'" + this.GetRGB(this.BackgroundColor) + "',color:'black',border:{radius:3,color:'" + this.GetRGB(this.BorderColor) + "'}}" +
(this.IsSticky ? ",hide:'unfocus'" : string.Empty) +
",show:{solo:true,effect:{type:'none',length:100}}" +
",hide:{effect:{type:'none',length:100}}" +
"});" +

"});",
true);
}
// More Code Here //
[TemplateContainer(typeof(JQueryUserControl))]
[PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate Content
{
get;
set;
}
}

That's it, enjoy!