Introduction
One of the things that drove me nuts while writing web applications was the battle to modularise your code while still keeping generated HTML neat. In particular, having individual code modules within a page render their own javascript often resulted in pages containing many different and unrelated pieces of script scattered in no particular order. It's nice to have javascript appear within the HEAD
tags of a page, where appropriate, but ASP 3.0 didn't provide an easy solution.
ASP.NET does provide a solution, of sorts, in the form of the RegisterClientScriptBlock
method in the Page
class. This allows you to register blocks of client-side script that will, at page render time, be output in one neat chunk to the page. I say it's a solution "of sorts" because while it's a neat idea, it doesn't actually do what you would always hope.
The issues, at least for me, of the RegisterClientScriptBlock
method were that the script is output after the opening Form
tag of an ASP.NET page. What if you don't have such a tag in your page? What if you want the script output in the HEAD section instead? The method also required you to include the <script>
tags. To me just meant lots of repeated boiler plate code and potential for mistakes. I wanted something that would make it easy to include script from many different points within the page creation logic and from within controls contained by a page. I also wanted a method that would fill in the boiler plate code for me whereever possible.
A new base class for your webpages.
With ASP.NET providing the ability to derive your pages from whatever System.Web.UI.Page
derived class you wish, there will no doubt be a plethora of web page base classes available. I could have chosen to encapsulate the functionality I needed in a separate utility class which would then be instantiated and called from your own System.Web.UI.Page
derived class, but I'm lazy and so that particular exercise has been left to the reader.
I instead created a simple class, ScriptPage
, derived from System.Web.UI.Page
from which subsequent pages can be derived. The methods available are:
RegisterClientScriptBlock
Registers a client side javascript block. The block is automatically surrounded by <script> tags
void RegisterClientScriptBlock(string key, string script)
void RegisterClientScriptBlock(string key, string script, string language)
void RegisterClientScriptBlock(string key, string script, string language,
bool defer)
Parameters
key - Script key. If a script file is already registered using this key then the previous script is replaced
script - The javascript to include.
language - The script's language. Default is "Javascript"
defer - Whether or not the script should be run after the page has fully loaded. Default is false
RegisterClientScriptFile
Registers a client side javascript file include
void RegisterClientScriptFile(string key, string file)
void RegisterClientScriptFile(string key, string file, string language)
void RegisterClientScriptFile(string key, string file, string language,
bool defer)
Parameters
key - Script key. If a script file is already registered using this key then the previous script is replaced
file - The javascript include file to reference
language - The script's language. Default is "Javascript"
defer - Whether or not the script should be run after the page has fully loaded. Default is false
RegisterClientScriptEvent
void RegisterClientScriptEvent(string key, string eventName, string ctrlName,
string script)
void RegisterClientScriptEvent(string key, string eventName, string ctrlName,
string script, string language)
Registers a client side javascript event handler. Will be rendered only for IE 4.0 and above.
Parameters
key - Script key. If a script file is already registered using this key then the previous script is replaced
eventName - The event to handle
ctrlName - The name of the HTML element(s) to apply this handler to
script - The script to run
language - The script's language. Default is "Javascript"
IsClientScriptRegistered
Returns true if the script block is registered; otherwise, false.
public bool IsClientScriptRegistered(string key)
Parameters
key - Script key to check.
Using the class
Using the class is simple.
- Include the ScriptPage.cs file in your project
- Derive your page from
CodeProject.ScriptPage
instead of System.Web.UI.Page
. namespace CodeProject
{
public class WebForm1 : CodeProject.ScriptPage
{
...
- Include an ASP.NET Literal control named
_clientScript
at the place within your page where you want the script to be rendered. This can be anywhere on the page, but within the <HEAD>
section is recommended. <HTML>
<HEAD>
<title>WebForm1</title>
<asp:literal id="_clientScript" runat="server"></asp:literal>
</HEAD>
<body>
<form id=Form1 ...
Important: If you don't include this control then the javascript will not be rendered.
Note: The designer in Visual Studio .NET will, if you edit your page in design mode, add the following line your code-behind class:
protected System.Web.UI.WebControls.Literal _clientScript;
If this occurs you will need to manually remove this line from your code-behind file.
- To register some javascript from within a page simply call the base class' methods:
private void Page_Load(object sender, System.EventArgs e)
{
RegisterClientScriptBlock("Script1", "alert(\"Script1 called\");");
RegisterClientScriptFile("Script2", "MyScripts.js", "Javascript 1.2");
RegisterClientScriptEvent("Script3", "onclick", "MyButton",
"alert(\"Script3 called\");");
}
- To register some javascript from within a user or custom control simply cast the parent page to the base class and again call the base class' methods:
CodeProject.ScriptPage basePage = Page as CodeProject.ScriptPage;
if (basePage != null)
basePage.RegisterClientScriptBlock("Script4",
"document.getElementById(\"MyTable\").style.backgroundColor='#ff9900';",
"Javascript", true);
Results
Consider the page below which contains a simple form and a simple User Control. Both the form and the user control will register some javascript as described above.
<%@ Page language="c#" Codebehind="WebForm1.aspx.cs"
AutoEventWireup="false" Inherits="CodeProject.WebForm1"
enableViewState="False" Trace="False"%>
<%@ Register TagPrefix="CP" TagName="WebUserControl1"
Src="WebUserControl1.ascx" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>WebForm1</title>
<asp:literal id="_clientScript" runat="server"></asp:literal>
</HEAD>
<body>
<form id=Form1 method=post runat="server">
<p>This is a very simple webpage. Click 'View Source' to
see the Javascript embedded within this page.
<P><input type=button id=MyButton name=MyButton value="Click me"></P>
<CP:WebUserControl1 id=WebUserControl11 runat="server"></CP:WebUserControl1>
</form>
</body>
</HTML>
The output, when rendered, is as follows:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>WebForm1</title>
<script type="text/javascript" language="Javascript 1.2"
src="MyScripts.js">
</script>
<script type="text/javascript" language="Javascript"><!--
alert("Script1 called");
--></script>
<script type="text/javascript" language="Javascript" defer="true"><!--
document.getElementById("MyTable").style.backgroundColor = '#ff9900';
--></script>
<script type="text/javascript" language="Javascript" for="MyButton"
event="onclick" defer="true"><!--
alert("Script3 called");
</HEAD>
<body>
<form name="Form1" method="post" action="WebForm1.aspx" id="Form1">
<p>This is a very simple webpage. Click 'View Source' to
see the Javascript embedded within this page.
<P><input type=button id=MyButton name=MyButton value="Click me"></P>
<table id=MyTable name=MyTable border=1 width=200 height=60
bgcolor=grey>
<tr><td align=center valign=middle><font size=2 face=verdana>This
is a User Control</font></td></tr>
</table>
</form>
</body>
</HTML>