Click here to Skip to main content
15,881,281 members
Articles / Web Development / XHTML

Write jQuery Plugin WebControl for ASP.NET Just in Few Minutes!

Rate me:
Please Sign up or sign in to vote.
4.50/5 (27 votes)
9 Jun 2009GPL33 min read 219.8K   2.6K   115  
Write jQuery plugin WebControl for ASP.NET just in few miniutes!

///  Copyright (c) 2009 Ray Liang (http://www.dotnetage.com)
///  Dual licensed under the MIT and GPL licenses:
///  http://www.opensource.org/licenses/mit-license.php
///  http://www.gnu.org/licenses/gpl.html
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Reflection;
using System.Web.Script.Serialization;
using System.Web.UI.HtmlControls;
using System.IO;

namespace DNA.UI
{
    public sealed class ScriptBuilder
    {
        public static string AddComfirScript(string confirmText, string script)
        {
            if (!string.IsNullOrEmpty(confirmText))
                return "if (!confirm('" + confirmText + "')) {self.event.returnValue=false;void(0);} else {" + script + "}";
            else
                return script;
        }

        public static Control CreateStyleLink(string href)
        {
            HtmlLink link = new HtmlLink();
            link.Attributes.Add("rel", "Stylesheet");
            link.Attributes.Add("type", "text/css");
            link.Attributes.Add("href", href);
            return link;
        }

        public static string GetControlResourceWebUrl(Control control,string scriptResource)
        {
            return control.Page.ClientScript.GetWebResourceUrl(control.GetType(), scriptResource);
        }

        public static void AddScriptReference(Control control,string scriptResource)
        {
            AddRefToContext(GetControlResourceWebUrl(control,scriptResource));
        }

        static void AddRefToContext(string refUrl)
        {
            string key = "JQuery-Javascripts";
            if (HttpContext.Current.Items[key] == null)
                HttpContext.Current.Items[key] = new System.Collections.Specialized.StringCollection();

            System.Collections.Specialized.StringCollection refs = (HttpContext.Current.Items[key] as System.Collections.Specialized.StringCollection);
            if (!refs.Contains(refUrl))
                refs.Add(refUrl);
        }

        public static void RegisterJQuery(Control ctrl)
        {
            if (HttpContext.Current.Items["AddJQueryRegistedHandler"] == null)
            {
                ctrl.Page.PreRenderComplete += new EventHandler(RegisterScriptsOnPagePreRenderComplete);
                HttpContext.Current.Items["AddJQueryRegistedHandler"] = true;
                string jqueryWebUrl = ctrl.Page.ClientScript.GetWebResourceUrl(typeof(jQuery.Res), "jQuery.core.js");
                AddRefToContext(jqueryWebUrl);
                //AddScriptReference(ctrl, "DNA.UI.ClientScripts.JQuery.jquery-1.3.2.min.js");
            }
        }

        static void RegisterScriptsOnPagePreRenderComplete(object sender, EventArgs e)
        {
            Page page = sender as Page;
            string key = "JQuery-Javascripts";
            if (HttpContext.Current.Items[key] == null)
                HttpContext.Current.Items[key] = new System.Collections.Specialized.StringCollection();
            System.Collections.Specialized.StringCollection refs = (HttpContext.Current.Items[key] as System.Collections.Specialized.StringCollection);
            foreach (string url in refs)
                page.Header.Controls.Add(new LiteralControl("<script type='text/javascript' src='" + url + "'></script>"));
        }

        /// <summary>
        /// 向Ajax客户端注册加载时执行的Java脚本
        /// </summary>
        public static void RegisterClientApplicationLoadScript(Control control, string script)
        {
            RegisterClientApplicationLoadScript(control, control.ClientID + "_LoadScript", script);
        }

        public static void RegisterClientApplicationLoadScript(Control control, string key, string script)
        {
            //if (NeedRegisterToPageManager(control))
            //{
            //    RegisterClientScriptToPageManager(control, key, script);
            //    return;
            //}

            StringBuilder scripts = new StringBuilder();
            scripts.Append("<script type='text/javascript'>");
            scripts.Append("Sys.Application.add_load(function(){");
            scripts.Append(script);
            scripts.Append("});");
            scripts.Append("</script>");
            control.Page.ClientScript.RegisterStartupScript(control.GetType(), key, scripts.ToString());
        }

        public static void RegisterClientScriptToPageManager(Control control,string key,string script)
        {
            StringBuilder scripts = new StringBuilder();
            //scripts.Append("<script type='text/javascript'>");
            scripts.Append("Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(function(sender, args){");
            //string formattedScript = FormatFunctionString(script);
            scripts.Append(script);
            scripts.Append(");");
            //scripts.Append("</script>");
            control.Page.ClientScript.RegisterStartupScript(control.GetType(), key, script,true);
        }

        public static bool NeedRegisterToPageManager(Control control)
        {
            if (control.Page.IsPostBack)
            {
                ScriptManager sm = ScriptManager.GetCurrent(control.Page);
                if (sm != null)
                    if (sm.EnablePartialRendering)
                        return true;
            }
            return false;
        }

        public static void RegisterClientApplicationInitScript(Control contorl, string script)
        {
            RegisterClientApplicationInitScript(contorl, contorl.ClientID + "_InitScript", script);
        }

        public static void RegisterClientApplicationInitScript(Control control, string key, string script)
        {
            //if (NeedRegisterToPageManager(control))
            //{
            //    RegisterClientScriptToPageManager(control, key, script);
            //    return;
            //}

            StringBuilder scripts = new StringBuilder();
            scripts.Append("<script type='text/javascript'>");
            scripts.Append("Sys.Application.add_init(function(){");
            scripts.Append(script);
            scripts.Append("});");
            scripts.Append("</script>");
            control.Page.ClientScript.RegisterStartupScript(control.GetType(),key, scripts.ToString());
        }

        public static void RegisterDocumentReadyScript(Control control, string script)
        {
            StringBuilder scripts = new StringBuilder();
            scripts.Append("<script type='text/javascript'>");
            scripts.Append("$().ready(function() {");
            scripts.Append(script);
            scripts.Append("});");
            scripts.Append("</script>");
            control.Page.ClientScript.RegisterStartupScript(control.GetType(), control.ClientID + "_ReadyScript", scripts.ToString());
        }

        public static string ExecuteCallBackMethod(Control control, string eventArgument)
        {
            if (string.IsNullOrEmpty(eventArgument))
                return "";

            JavaScriptSerializer ser = new JavaScriptSerializer();
            Dictionary<string, object> objArgs = (Dictionary<string, object>)ser.DeserializeObject(eventArgument);
           
            if (!objArgs.ContainsKey("method"))
                return "";

            string methodName = (string)objArgs["method"];

            if (string.IsNullOrEmpty(methodName))
                return "";

            //string paramsString = "";
            //if (objArgs.ContainsKey("params"))
            //    paramsString = objArgs["params"].ToString();

            string returnValue = "";
            Type cattr = typeof(CallBackMethodAttribute);
            //Refaction
            MethodInfo mi = (from MethodInfo m in control.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)
                             where (Attribute.GetCustomAttribute(m, cattr, true) == null) ? false :
                             ((m.Name == methodName) ||
                             (((CallBackMethodAttribute)Attribute.GetCustomAttribute(m, cattr, true)).FriendlyName == methodName))
                             select m).SingleOrDefault();

            if (mi != null)
            {
                //bool hasCallBackResult = ((CallBackMethodAttribute)Attribute.GetCustomAttribute(mi, cattr)).HasCallbackResult;
                object[] paramsObjs = null;
                if (objArgs["params"]!=null)
                {
                    //Dictionary<string, object> paramdic = (Dictionary<string, object>)ser.DeserializeObject(paramsString);
                    //paramsObjs = paramdic.Values.ToArray<object>();
                    paramsObjs = objArgs["params"] as object[];
                }

                if (mi.ReturnType!=null)
                {
                    object returnObject =mi.Invoke(control, paramsObjs);
                    if (mi.ReturnType==typeof(string))
                         returnValue=returnObject as string;
                    if (mi.ReturnType == typeof(bool))
                        returnValue = returnObject == null ? "false" : returnObject.ToString().ToLower();
                    if ((mi.ReturnType == typeof(int)) ||
                        (mi.ReturnType == typeof(float)) ||
                        (mi.ReturnType == typeof(decimal)))
                        returnValue = returnObject.ToString();
                    returnValue = ser.Serialize(returnObject);
                }
                else
                    mi.Invoke(control, paramsObjs);
            }
            else
                throw new MissingMethodException();

            if (control.EnableViewState)
            {
                //Update viewstates
                MethodInfo pmi = typeof(System.Web.UI.Page).GetMethod("SaveAllState", BindingFlags.Instance | BindingFlags.NonPublic);
                pmi.Invoke(control.Page, null);
                PropertyInfo statePro = control.Page.GetType().GetProperty("ClientState", BindingFlags.Instance | BindingFlags.NonPublic);
                string state = statePro.GetValue(control.Page, null).ToString();
                return state + ";" + returnValue;
            }
            else
                return returnValue;

        }

        public static ScriptDescriptor GetControlDescriptors(Control control, string controlType)
        {
            ScriptControlDescriptor descriptor = new ScriptControlDescriptor(controlType, control.ClientID);

            Type TAttr = typeof(ClientPropertyAttribute);
            var properties = from PropertyInfo p in control.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)
                             where (Attribute.GetCustomAttribute(p, TAttr, true) != null)
                             select p;
            foreach (PropertyInfo property in properties)
            {
                ClientPropertyAttribute cpt = Attribute.GetCustomAttribute(property, TAttr, true) as ClientPropertyAttribute;
                object propertyValue = property.GetValue(control, null);
                if (propertyValue == null)
                {
                    if (cpt.DefaultValue != null)
                        propertyValue = cpt.DefaultValue;
                    else
                        if (!cpt.RegistNullValue)
                            continue;
                }
                switch (cpt.Type)
                {
                    case ClientPropertyTypes.ElementProperty:
                        descriptor.AddElementProperty(cpt.Name, control.ClientID);
                        break;
                    case ClientPropertyTypes.Event:
                        if (propertyValue != null)
                            descriptor.AddEvent(cpt.Name, propertyValue.ToString());
                        break;
                    case ClientPropertyTypes.ScriptProperty:
                        if (propertyValue != null)
                            descriptor.AddScriptProperty(cpt.Name, propertyValue.ToString());
                        break;
                    case ClientPropertyTypes.ComponentProperty:
                        descriptor.AddComponentProperty(cpt.Name, control.ClientID);
                        break;
                    default:
                        if (property.PropertyType == typeof(string))
                        {
                            string relativeUrl = propertyValue as string;
                            if (cpt.IsUrl)
                            {
                                //if (control.EnableTheming)
                                //{
                                //    if (!string.IsNullOrEmpty(relativeUrl))
                                //    {
                                //        if (VirtualPathUtility.IsAppRelative(relativeUrl))
                                //        {
                                //            if (!relativeUrl.ToLower().StartsWith("~/app_themes"))
                                //                relativeUrl = relativeUrl.Replace("~/", "~/app_themes/" + control.Page.Theme + "/");
                                //        }
                                //    }
                                //}
                                propertyValue = control.ResolveUrl(relativeUrl);
                            }
                        }
                        descriptor.AddProperty(cpt.Name, propertyValue);
                        break;
                }
            }
            return descriptor;
        }

        public static IEnumerable<ScriptReference> GetControlScriptReferences(Control control)
        {
            //List<ScriptReference> scriptRefs = new List<ScriptReference>();
            SortedList<int, ScriptReference> scriptRefs = new SortedList<int, ScriptReference>();

            object[] attrs = control.GetType().GetCustomAttributes(typeof(ScriptReferenceAttribute), true);
            if (attrs != null)
            {
                if (attrs.Length > 0)
                {
                    foreach (ScriptReferenceAttribute srefAttr in attrs)
                    {
                        int order = srefAttr.LoadOrder;

                        while (scriptRefs.Keys.Contains(order))
                            order++;
                        string assembly=srefAttr.Assembly;
                        if (string.IsNullOrEmpty(srefAttr.Assembly))
                            assembly=control.GetType().Assembly.FullName;
                        scriptRefs.Add(order, new ScriptReference(srefAttr.Name, assembly));
                    }
                }
            }
            return scriptRefs.Values.ToArray<ScriptReference>();
        }

        public static void RegisterJQueryControl(Control control)
        {
            RegisterJQueryControl(control, null);
        }

        public static void RegisterJQueryControl(Control control, Dictionary<string, string> options)
        {
            ScriptManager sm = ScriptManager.GetCurrent(control.Page);
            if (sm == null)
                throw new Exception("You need place the ScriptManager in WebForm");

            RegisterJQuery(control);

            //JQuery.RegisterJQuery(control.Page);
            Type controlType = control.GetType();
            object[] attrs = controlType.GetCustomAttributes(typeof(JQueryAttribute), true);

            if (attrs != null)
            {
                foreach (JQueryAttribute jqueryAttr in attrs)
                {
                    string name = jqueryAttr.Name;
                    StringBuilder scripts = new StringBuilder();
                    scripts.Append("$('#" + control.ClientID + "')." + name + "(");

                    RegisterJQueryScriptReferences(control, sm, jqueryAttr);

                    var properties = from PropertyInfo p in controlType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
                                     where (Attribute.GetCustomAttribute(p, typeof(JQueryOptionAttribute), true) != null)
                                     select p;

                    System.Collections.ArrayList optionArray = new System.Collections.ArrayList();

                    if (options != null)
                    {
                        foreach (string key in options.Keys)
                            optionArray.Add(key + ":" + options[key]);
                    }

                    foreach (PropertyInfo pi in properties)
                    {
                        JQueryOptionAttribute option = (JQueryOptionAttribute)(Attribute.GetCustomAttribute(pi, typeof(JQueryOptionAttribute)));
                        if (!string.IsNullOrEmpty(option.Target))
                        {
                            if (option.Target != jqueryAttr.Name)
                                continue;
                        }

                        object pValue = pi.GetValue(control, null);
                        if (pValue == null)
                        {
                            if (option.DefaultValue != null)
                                pValue = option.DefaultValue;
                            if (pValue == null)
                            {
                                if (!option.RegistNullValue)
                                    continue;
                            }
                        }

                        if (IsIgnoreValue(option.IgnoreValue,pValue,pi.PropertyType))
                            continue;

                        string value = "";
                        value = option.Name + ":";
                        switch (option.Type)
                        {
                            case JQueryOptionTypes.Value:
                                string fv = pValue.ToString();
                                if (pi.PropertyType == typeof(string))
                                    fv = "'" + fv + "'";
                                if (pi.PropertyType == typeof(bool))
                                    fv = fv.ToLower();

                                if ((pi.PropertyType == typeof(JQueryEffects?)) || (pi.PropertyType == typeof(JQueryEffects)))
                                {
                                    if (fv.ToLower() == "none")
                                        continue;
                                    fv = "'" + fv.ToLower() + "'";
                                }
                                else
                                {
                                    if (pi.PropertyType.IsEnum)
                                        fv = "'" + fv.ToLower() + "'";
                                }
                                //if ((pi.PropertyType == typeof(Orientation)))
                                //    fv = "'" + fv.ToLower() + "'";
                                value += fv;
                                break;
                            case JQueryOptionTypes.JSONObject:
                                if (pi.PropertyType == typeof(string))
                                    value += pValue;
                                else
                                value += (new JavaScriptSerializer()).Serialize(pValue);
                                break;
                            case JQueryOptionTypes.Function:
                                string fV = pValue.ToString();
                                if (!fV.StartsWith("function"))
                                {
                                    if (option.FunctionParams != null)
                                    {
                                        fV = "function(" + String.Join(",", option.FunctionParams) + "){" + fV + "}";
                                    }
                                    else
                                        fV = "function(){" + fV + "}";
                                }
                                value += fV;
                                break;
                            default:
                                value += pValue.ToString();
                                break;
                        }
                        optionArray.Add(value);
                    }

                    if (optionArray.Count > 0)
                    {
                        scripts.Append("{");
                        scripts.Append(String.Join(",", (string[])optionArray.ToArray(typeof(string)))); scripts.Append("}");
                    }

                    scripts.Append(");");
                    switch (jqueryAttr.StartEvent)
                    {
                        case ClientRegisterEvents.ApplicaitonInit:
                            RegisterClientApplicationInitScript(control,scripts.ToString());
                            break;
                        case ClientRegisterEvents.ApplicationLoad:
                            RegisterClientApplicationLoadScript(control,scripts.ToString());
                            break;
                        case ClientRegisterEvents.DocumentReady:
                            RegisterDocumentReadyScript(control, scripts.ToString());
                            break;
                    }
                }
            }
        }

        private static bool IsIgnoreValue(object compareValue, object value, Type valueType)
        {
            //Ignore value
            if (compareValue != null)
            {
                if (valueType== typeof(bool))
                {
                    if ((bool)compareValue == (bool)value)
                        return true;
                }

                if (valueType == typeof(int))
                {
                    if ((int)compareValue == (int)value)
                        return true;
                }

                if (valueType == typeof(float))
                {
                    if ((float)compareValue == (float)value)
                        return true;
                }

                if (valueType == typeof(string))
                {
                    if (compareValue.ToString() ==valueType.ToString())
                        return true;
                }


                if (compareValue == value)
                    return true;
            }

            return false;
        }

        private static void RegisterJQueryScriptReferences(Control control, ScriptManager sm, JQueryAttribute jqueryAttr)
        {
            if (jqueryAttr.ScriptResources != null)
            {
                string assembly = control.GetType().Assembly.FullName;
                if (!string.IsNullOrEmpty(jqueryAttr.Assembly))
                    assembly = jqueryAttr.Assembly;

                foreach (string scriptRef in jqueryAttr.ScriptResources)
                {
                    string script = scriptRef;
                    if (!string.IsNullOrEmpty(jqueryAttr.ScriptResourceBaseName))
                        script = jqueryAttr.ScriptResourceBaseName + scriptRef;
                    sm.Scripts.Add(new ScriptReference(script, assembly));
                }
            }
        }

        public static Control FindControl(Control container, string id)
        {
            for (int i = 0; i < container.Controls.Count;i++ )
            {
                Control ctrl = container.Controls[i];
                if (ctrl.ID == id)
                    return ctrl;
                if (ctrl.Controls.Count > 0)
                    return FindControl(ctrl, id);
            }
                return null;
        }

        public static string GetControlClientID(Page page, string id)
        {
            string realID = id;
            if (!string.IsNullOrEmpty(id))
            {
                Control ctrl = FindControl(page.Form, id);
                if (ctrl != null)
                    realID = ctrl.ClientID;
            }
            return realID;
        }

        public static string RenderControlToHTML(Control control)
        {
            using (MemoryStream memory = new MemoryStream())
            {
                StreamWriter writer = new StreamWriter(memory);
                HtmlTextWriter htmlWriter = new Html32TextWriter(writer);
                control.Visible = true;
                control.RenderControl(htmlWriter);
                htmlWriter.Flush();
                memory.Position = 0;
                StreamReader reader = new StreamReader(memory);
                string html = reader.ReadToEnd();
                memory.Close();
                return html;
            }
        }

        public static string FormatFunctionString(string value)
        {
            return FormatFunctionString(value, null);
        }

        public static string FormatFunctionString(string value,string[] _params)
        {
            string formatted = value;
            if (!value.StartsWith("function"))
            {
                if (_params != null)
                {
                    formatted = "function(" + String.Join(",", _params) + "){" + value + "}";
                }
                else
                    formatted = "function(){" + formatted + "}";
            }
            return formatted;
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Architect DotNetAge
China China
In 1999, I started programming using Delphi, VB, VJ.From 2002 I started with .NET using C#.Since 2005 when i had became an EIP product manager I was focus on EIP and CMS technique. In 2008 i established dotnetage.com and started to shared my ideas and projects online. I believe "No shared no grow"

www.dotnetage.com

Comments and Discussions