/trunk/src/AjaxSnippets/Snippet.cs
C# | 253 lines | 165 code | 34 blank | 54 comment | 16 complexity | 977ff67e05d3d69e69a9b64a287cb8ea MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Web.UI;
- using System.Text;
- using System.Reflection;
- using System.Web.UI.HtmlControls;
- using System.IO;
- using System.Text.RegularExpressions;
-
- namespace AjaxSnippets
- {
- /// <summary>
- /// Base class for snippets
- /// </summary>
- public abstract class Snippet : UserControl
- {
- /// <summary>
- /// TODO: this does not work currently, need to somehow flip this to true if
- /// there are child controls of SnippetCallback
- /// </summary>
- private bool _ContainsCallbacks = false;
- private ScriptManager GetScriptManager()
- {
- return (ScriptManager)Parent.FindControl("ScriptManager");
- }
-
- protected override void Render(HtmlTextWriter writer)
- {
- // Render the contents in <snippet> tag that we can use as a marker
- // to strip out the noise that ASP.NET creates which we will not be
- // making any use of
- if (IsOnSnippetPage) writer.Write("<snippet>");
-
-
- // Wrap up the snippet in a div with the ClientID of this control
- writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
- writer.RenderBeginTag(HtmlTextWriterTag.Div);
-
- base.Render(writer);
-
- if (IsOnSnippetPage)
- {
- RenderCssIncludes(writer);
-
-
- // HACK: Use reflection to get at ScriptRegistration from ScriptManager
- // this holds all the script includes and script blocks ready
- // to be pumped out to the browser
- ScriptManager sm = GetScriptManager();
- List<RegisteredScript> scriptBlocks = null;
- List<RegisteredScript> scriptStartupBlocks = null;
- if (sm != null)
- {
- object scriptRegistrations = sm.GetType().GetProperty("ScriptRegistration", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(sm, null);
- scriptBlocks = (List<RegisteredScript>)scriptRegistrations.GetType().GetProperty("ScriptBlocks").GetValue(scriptRegistrations, null);
- scriptStartupBlocks = (List<RegisteredScript>)scriptRegistrations.GetType().GetProperty("ScriptStartupBlocks").GetValue(scriptRegistrations, null);
- }
-
- RenderScriptIncludes(writer, scriptBlocks);
-
- //Make sure we have SnippetManager script registered
- RenderSnippetManagerCheckScript(writer);
-
- if (scriptStartupBlocks != null)
- {
- // Try to remove this component if its already been created in a previous request
- RenderComponentRemovalScripts(writer, scriptStartupBlocks);
-
- #region TODO: May have to enumerate descriptors and manually set them up
- //foreach (RegisteredScript startupScript in scriptStartupBlocks)
- //{
- // if (startupScript.Control is IScriptControl)
- // {
- // IScriptControl scriptControl = (IScriptControl)startupScript.Control;
-
- // IEnumerable<ScriptDescriptor> descriptors = scriptControl.GetScriptDescriptors();
-
- // IEnumerator<ScriptDescriptor> descEnumerator = descriptors.GetEnumerator();
- // while (descEnumerator.MoveNext())
- // {
- // ScriptDescriptor descriptor = descEnumerator.Current;
- // }
- // }
- //}
- #endregion
-
- foreach (RegisteredScript startupScript in scriptStartupBlocks)
- {
- writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/javascript");
- writer.AddAttribute("language", "javascript");
- writer.RenderBeginTag(HtmlTextWriterTag.Script);
- // HACK: Lets replace this and have snippet manager deal with it
- writer.Write(startupScript.Script.Replace("Sys.Application.add_init", "AjaxSnippets.SnippetManager.stackFunction"));
- writer.RenderEndTag();
- }
- }
- }
-
- if (IsOnSnippetPage) RenderInvokeSnippetRenderedScript(writer);
-
- writer.RenderEndTag();
-
- if (IsOnSnippetPage) writer.Write("</snippet>");
- }
-
- /// <summary>
- /// TODO: Refactor this to RenderHtmlLinks, attributes for rel and type can be pulled from HtmlLink
- /// </summary>
- /// <param name="writer"></param>
- private void RenderCssIncludes(HtmlTextWriter writer)
- {
- if (this.Page.Header != null)
- {
- foreach (Control control in this.Page.Header.Controls)
- {
- // we expect AJAX Framework scripts to be already rendered since SnippetManager needs it in the hosting page
- if (control is HtmlLink)
- {
- HtmlLink link = (HtmlLink)control;
- writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/javascript");
- writer.AddAttribute("language", "javascript");
- writer.RenderBeginTag(HtmlTextWriterTag.Script);
- writer.Write("AjaxSnippets.SnippetManager.loadCss('" + link.Href + "');");
- writer.RenderEndTag();
- }
- }
- }
- }
-
-
- private void RenderScriptIncludes(HtmlTextWriter writer, List<RegisteredScript> includes)
- {
- if (includes != null)
- {
- foreach (RegisteredScript include in includes)
- {
- // we expect AJAX Framework scripts to be already rendered since SnippetManager needs it in the hosting page
- if (!(include.Control is ScriptManager))
- {
- writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/javascript");
- writer.AddAttribute("language", "javascript");
- writer.RenderBeginTag(HtmlTextWriterTag.Script);
- writer.Write("AjaxSnippets.SnippetManager.loadScript('" + include.Url + "');");
- writer.RenderEndTag();
- }
- }
- }
- }
-
- private void RenderComponentRemovalScripts(HtmlTextWriter writer, List<RegisteredScript> scriptStartupBlocks)
- {
- foreach (RegisteredScript startupScript in scriptStartupBlocks)
- {
- writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/javascript");
- writer.AddAttribute("language", "javascript");
- writer.RenderBeginTag(HtmlTextWriterTag.Script);
- writer.Write("AjaxSnippets.SnippetManager.removeComponent('" + startupScript.Control.ClientID + "');");
- writer.RenderEndTag();
- }
- }
-
- /// <summary>
- /// Renders a script that alerts the user that they need to add the SnippetManager
- /// </summary>
- /// <param name="writer"></param>
- private void RenderSnippetManagerCheckScript(HtmlTextWriter writer)
- {
- if (_ContainsCallbacks)
- {
- writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/javascript");
- writer.AddAttribute("language", "javascript");
- writer.RenderBeginTag(HtmlTextWriterTag.Script);
- writer.Write("if($find('SnippetManager') === null) { alert('The SnippetManager control must be added to the page'); }\n");
- writer.RenderEndTag();
- }
- }
-
- /// <summary>
- /// Renders a client script block that invokes a client snippetRendered() function if it exists
- ///
- /// TODO: Might remove this feature, evaluate if this is actually needed
- /// </summary>
- private void RenderInvokeSnippetRenderedScript(HtmlTextWriter writer)
- {
- // Invoke the client-side snippetRendered method if any
- writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/javascript");
- writer.AddAttribute("language", "javascript");
- writer.RenderBeginTag(HtmlTextWriterTag.Script);
- writer.Write("if(typeof(snippetRendered) !== 'undefined') { snippetRendered('" + this.ID + "') }\n");
- writer.RenderEndTag();
- }
-
- public bool IsOnSnippetPage
- {
- get
- {
- return (this.Page is SnippetPage);
- }
- }
- public override string ToString()
- {
- if (!IsOnSnippetPage)
- return base.ToString();
-
- string result = null;
-
- try
- {
- StringWriter writer = new StringWriter();
- HttpContext.Current.Server.Execute(Page, writer, false);
- Regex regEx = new Regex(@"(?<=<snippet>)(.*)(?=</snippet>)", RegexOptions.Singleline);
- result = regEx.Match(writer.ToString()).Value;
- }
- catch (Exception ex)
- {
- throw ex.GetBaseException();
- }
-
-
- return result;
- }
-
- /// <summary>
- /// Create a snippet of the given type from the given file
- /// </summary>
- /// <typeparam name="SnippetType">The Type of the snippet</typeparam>
- /// <param name="snippetId">a naming container</param>
- /// <param name="virtualPath">The virtual path to the ascx file of this snippet</param>
- /// <returns></returns>
- public static SnippetType Create<SnippetType>(string snippetId, string virtualPath) where SnippetType : Snippet
- {
- SnippetPage holder = new SnippetPage();
- // HACK: Add a HtmlHead, AjaxControlToolkit controls use this to register CSS
- holder.GetType().BaseType.GetField("_header", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).SetValue(holder, new HtmlHead());
-
- HtmlForm form = new HtmlForm();
- holder.Controls.Add(form);
-
- ScriptManager scriptManager = new ScriptManager();
- scriptManager.ID = "ScriptManager";
- form.Controls.Add(scriptManager);
-
- Snippet snippetControl = (Snippet)holder.LoadControl(virtualPath);
- snippetControl.ID = snippetId;
- form.Controls.Add(snippetControl);
- return (SnippetType)snippetControl;
- }
-
- public class SnippetPage : Page{}
- }
- }