Click here to Skip to main content
Click here to Skip to main content
Articles » Web Development » Ajax » General » Downloads
 
Add your own
alternative version

Magic AJAX: Applying AJAX to your existing Web Pages

, 28 May 2007
How to apply AJAX technologies to your web pages without replacing ASP.NET controls and/or writing JavaScript code.
magicajax-030-net11.zip
magicajax
Examples
ExampleSite (.NET 2.0 only)
Web.sitemap
webparts
images
first.GIF
last.GIF
next.gif
pow_by_aspnet2.0.gif
prev.GIF
examples
App_Data
App_Code
Docs
Core
script
bin
MagicAjax.dll
magicajax-030-net20.zip
MagicAjax.dll
Web.sitemap
first.GIF
last.GIF
next.gif
pow_by_aspnet2.0.gif
prev.GIF
magicajax-030-source.zip
Web.sitemap
CVS
Root
Repository
Entries.Old
Entries
Entries.Extra.Old
Entries.Extra
first.GIF
last.GIF
next.gif
pow_by_aspnet2.0.gif
prev.GIF
CVS
Root
Repository
Entries.Old
Entries
Entries.Extra.Old
Entries.Extra
CVS
Root
Repository
Entries.Old
Entries
Entries.Extra.Old
Entries.Extra
CVS
Root
Repository
Entries.Old
Entries
Entries.Extra.Old
Entries.Extra
CVS
Root
Repository
Entries.Old
Entries
Entries.Extra.Old
Entries.Extra
CVS
Root
Repository
Entries
Entries.Extra
Entries.Old
Entries.Extra.Old
CVS
Root
Repository
Entries.Old
Entries.Extra.Old
Entries
Entries.Extra
CVS
Root
Repository
Entries
Entries.Extra
Entries.Old
Entries.Extra.Old
MagicAjax.snk
CVS
Root
Repository
Entries.Old
Entries.Extra.Old
Entries
Entries.Extra
UI
Design
CVS
Root
Repository
Entries.Old
Entries.Extra.Old
Entries
Entries.Extra
Controls
ClientEventControls
CVS
Root
Repository
Entries.Old
Entries
Entries.Extra.Old
Entries.Extra
CVS
Root
Repository
Entries.Extra
Entries.Old
Entries
Entries.Extra.Old
CVS
Root
Repository
Entries.Old
Entries.Extra.Old
Entries
Entries.Extra
Interfaces
CVS
Root
Repository
Entries.Old
Entries.Extra.Old
Entries
Entries.Extra
Configuration
CVS
Root
Repository
Entries.Old
Entries.Extra.Old
Entries
Entries.Extra
CVS
Root
Repository
Entries
Entries.Extra
Entries.Old
Entries.Extra.Old
CVS
Root
Repository
Entries.Old
Entries.Extra.Old
Entries
Entries.Extra
magicajax.zip
AJAXTest
AJAXTest.csproj.webinfo
Global.asax
Ajax
Ajax.csproj.user
Controls
Design
script
#region Copyright
/*
Copyright (C) 2005 Argiris Kirtzidis
This script is supplied "as is" without any form of warranty. I shall not be liable for
any loss or damage to person or property as a result of using this script. Use this script
at your own risk! You are licensed to use this script free of charge for commercial or
non-commercial use providing you do not remove the copyright notice or disclaimer.
*/
#endregion

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;

namespace Ajax.Controls
{
	#region Public Class RenderStartEventArgs
	/// <summary>
	/// It contains the HtmlTextWriter writer event argument to be used during a
	/// RenderStart event.
	/// </summary>
	public class RenderStartEventArgs : EventArgs
	{
		private bool abortRendering = false;
		private HtmlTextWriter writer;

		public bool AbortRendering
		{
			get { return abortRendering; }
			set { abortRendering = value; }
		}

		public HtmlTextWriter Writer
		{
			get { return writer; }
		}

		public RenderStartEventArgs(HtmlTextWriter writer)
		{
			this.writer = writer;
		}
	}
	#endregion

	/// <summary>
	/// The event handler for a RenderStart event.
	/// </summary>
	public delegate void RenderStartEventHandler(object sender, RenderStartEventArgs e);

	/// <summary>
	///	This control manages its appearance on the page using javascript that sends
	///	to the client during a CallBack.
	/// </summary>
	/// <remarks>
	/// It provides the basic functionality for controls like AjaxPanel. It manages
	/// its tag attributes using javascript.
	/// </remarks>
	public class RenderedByScriptControl : AjaxControl, IPreRenderByScriptEventHandler, IRenderedByScript
	{
		private bool isRenderedOnPage = false;
		private bool monitorVisibilityState = true;
		private string currentTagHtml = null;
		private string tagOnPageHtml = null;
		private bool isHtmlRendered = false;

		public event RenderStartEventHandler RenderStart;
		public event EventHandler RenderEnd;
		public event EventHandler PreRenderByScript;

		// Disable EnableViewState so that the properties it sustains doesn't interfere with
		// the funtionality provided by RenderedByScriptControl.
		[Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public override bool EnableViewState
		{
			get	{ return false; }
			set	{ }
		}

		public override bool Visible
		{
			get
			{
				return base.Visible;
			}
			set
			{
				if ( CallBackHelper.IsCallBack
					&& IsRenderedOnPage
					&& MonitorVisibilityState
					&& value != base.Visible )
					CallBackHelper.WriteSetVisibilityOfElementScript (ClientID, value);

				base.Visible = value;
			}
		}

		/// <summary>
		/// Determines whether the RenderedByScriptControl control has been rendered
		/// on the page, either by normal rendering or by script.
		/// </summary>
		/// <remarks>
		/// IsRenderedOnPage is set to true during a normal rendering or a rendering
		/// by script. It is set to false only during a CallBackStartup.
		/// </remarks>
		[Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public bool IsRenderedOnPage
		{
			get { return isRenderedOnPage; }
		}

		/// <summary>
		/// Gets or sets whether every time "Visible" property is changed
		/// CallBackHelper.WriteSetVisibilityOfElementScript method should be called.
		/// Default is true.
		/// </summary>
		/// <remarks>
		/// If this property is true, every time you change the "Visible" property during a
		/// CallBack, the display attribute of the style of the control on the page will
		/// be set to "" or "none" by calling the CallBackHelper.WriteSetVisibilityOfElementScript
		/// method.
		/// </remarks>
		[Bindable(false), Category("Behavior"), DefaultValue(true)] 
		public bool MonitorVisibilityState
		{
			get { return monitorVisibilityState; }
			set { monitorVisibilityState = value; }
		}

		/// <summary>
		/// Returns the tag name of the control.
		/// </summary>
		/// <returns></returns>
		public string GetTagName()
		{
			return TagKey.ToString();
		}

		public RenderedByScriptControl()
		{
			base.EnableViewState = false;
			this.ID = "";
		}
		public RenderedByScriptControl(HtmlTextWriterTag tag) : base(tag)
		{
			base.EnableViewState = false;
			this.ID = "";
		}

		/// <summary>
		/// It defines whether the RenderedByScriptControl was already rendered during
		/// a normal rendering.
		/// </summary>
		/// <remarks>
		/// The RenderedByScriptControl can be normally rendered by the Render method
		/// even during a CallBack (i.e when all the controls of an AjaxPanel is new
		/// and the AjaxPanel renders all of them in a single html rendering).
		/// In this case it's not necessary to send any javascript to the client.
		/// </remarks>
		protected bool IsHtmlRendered
		{
			get { return isHtmlRendered; }
		}

		protected override void OnCallBack(EventArgs e)
		{
			isHtmlRendered = false;

			if ( CallBackHelper.IsCallBackStartup )
			{
				isRenderedOnPage = false;
				currentTagHtml = tagOnPageHtml;
			}

			base.OnCallBack(e);
		}

		protected override void OnPreRender(EventArgs e)
		{
			CallBackHelper.RegisterCallBackStartupScript();
			base.OnPreRender (e);
		}

		/// <summary>
		/// Normal rendering.
		/// </summary>
		/// <remarks>
		/// It raises the RenderStart and RenderEnd events. If the rendering is not
		/// aborted during the RenderStart event, it renders the control and sets
		/// the isHtmlRendered variable to true.
		/// </remarks>
		/// <param name="writer"></param>
		protected override void Render(HtmlTextWriter writer)
		{
			RenderStartEventArgs eventArgs = new RenderStartEventArgs(writer);
			OnRenderStart(eventArgs);

			if (!eventArgs.AbortRendering)
			{
				base.Render (writer);
				isHtmlRendered = true;
				isRenderedOnPage = true;
			}

			OnRenderEnd(EventArgs.Empty);
		}

		/// <summary>
		/// It stores the tag html for later checking.
		/// </summary>
		/// <param name="writer"></param>
		public override void RenderBeginTag(HtmlTextWriter writer)
		{
			System.Text.StringBuilder sb = new System.Text.StringBuilder();
			HtmlTextWriter strwriter = new HtmlTextWriter(new System.IO.StringWriter(sb));
			base.RenderBeginTag (strwriter);
			tagOnPageHtml = currentTagHtml = sb.ToString();

			base.RenderBeginTag (writer);
		}

		/// <summary>
		/// Called by AjaxHttpModule
		/// </summary>
		public virtual void RaisePreRenderByScriptEvent()
		{
			OnPreRenderByScript (EventArgs.Empty);
		}

		/// <summary>
		/// If the tag html of the control is changed, send the attributes using javascript.
		/// </summary>
		/// <returns>True if rendering by script was needed, False if it was not</returns>
		public virtual bool RenderByScript()
		{
			// If there was a normal rendering, javascript is not needed
			if (IsHtmlRendered)
				return false;

			if ( ! IsRenderedOnPage )
			{
				Control con = FindNextVisibleSibling();
				CallBackHelper.WriteAddElementScript (Parent.ClientID, this.GetTagName(), this.ClientID, "", (con == null) ? null : con.ClientID);
			}

			System.Text.StringBuilder sb = new System.Text.StringBuilder();
			HtmlTextWriter strwriter = new HtmlTextWriter(new System.IO.StringWriter(sb));

			// Take care of the tag of the control

			base.RenderBeginTag (strwriter);
			string html = sb.ToString();
			sb.Length = 0;

			if(currentTagHtml != html)
			{
				CallBackHelper.WriteSetAttributesOfControl (ClientID, FormatAttributes(html));
				currentTagHtml = html;
			}

			isRenderedOnPage = true;

			return true;
		}

		protected virtual void OnRenderStart(RenderStartEventArgs eventArgs)
		{
			if (RenderStart != null)
				RenderStart(this, eventArgs);
		}
		
		protected virtual void OnRenderEnd(EventArgs e)
		{
			if (RenderEnd != null)
				RenderEnd(this, e);
		}
		
		protected virtual void OnPreRenderByScript(EventArgs e)
		{
			if (PreRenderByScript != null)
				PreRenderByScript(this, e);
		}

		/// <summary>
		/// Finds the next visible control of the control collection of this
		/// control's parent that has its ID attribute set.
		/// </summary>
		/// <returns></returns>
		private Control FindNextVisibleSibling()
		{
			for (int i=Parent.Controls.IndexOf(this) + 1; i < Parent.Controls.Count; i++)
			{
				Control con = Parent.Controls[i];

				if (con.Visible && con.ID != null)
					return con;
			}

			return null;
		}							

		/// <summary>
		/// It finds the attributes from the html of the control's tag, and formats them
		/// so that they are send by CallBackHelper.WriteSetAttributesOfControl method.
		/// </summary>
		/// <param name="html">The html tag of the control</param>
		/// <returns></returns>
		private string FormatAttributes(string html)
		{
			System.Text.StringBuilder sb = new System.Text.StringBuilder(html);
			System.Text.StringBuilder attribs = new System.Text.StringBuilder();
			int mode = 0;

			for (int i=0; i < sb.Length; i++)
			{
				char ch = sb[i];
				if (ch == '>') break;

				switch (mode)
				{
					case 0:
						if (ch == ' ')	mode++;
						break;
					case 1:
					switch (ch)
					{
						case '\"':
							mode++;
							break;
						case ' ':
							attribs.Append ('|');
							break;
						default:
							attribs.Append (ch);
							break;
					}
						break;
					case 2:
						if (ch == '\"')
							mode--;
						else
							attribs.Append (ch);
						break;
				}
			}

			return attribs.ToString();
		}
	}
}

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 MIT License

About the Author

Argiris Kirtzidis
Web Developer
Greece Greece
No Biography provided

| Advertise | Privacy | Mobile
Web02 | 2.8.140721.1 | Last Updated 28 May 2007
Article Copyright 2005 by Argiris Kirtzidis
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid