Introduction
ASP.NET provides an elegant way to inject script from code-behind. With its facilities, we can have our own custom web controls (buttons etc.). Optionally, these custom web controls (.ascx or its associated code-behind) can have embedded JavaScript within them. Here we describe some gains and limitations that we may experience in the use of WebControls with JavaScript functions embedded in them.
The Scenario
Assume that we need a custom Reset button, which should not only just reset the form but optionally toggle some Label controls also. Optionally we would like to have different types of interfaces like button look-and-feel or hyperlink look-and-feel. Our natural choice is to give a UserControl with both Button and LinkButton, with optional properties to toggle visibility of one and hide the other. To prevent unnecessary roundtrips in the server, we may like to have this function embedded as a JavaScript. Now wherever we want to make use of this control, we use the syntax:
<%@ Register TagPrefix="STP" TagName="STP" SRC="./includes/rb.ascx" %>
Now we would be including this button like this:
<STP:STP Id="Stp1" runat="server"/>
This solves the problem, right? But what happens if I want two buttons of this type in the same page.
<STP:STP Id="Stp1" runat="server"/>
<STP:STP Id="Stp2" runat="server"/>
Now the embedded JavaScript function in the .ascx that is Register TagPrefixed is duplicated twice in the rendered HTML page.
The Solution
In the .ascx page, enclose the embedded JavaScript within runat=SERVER DIVs. Your code should look like this:
<DIV runat="server" id="divScript">
<Script Language="'JavaScript'">
function thisFunctionInUserControl()
{
}
</Script>
</DIV>
Now in the code-behind of the UserControl, declare the DIV as:
protected HtmlGenericControl divScript;
In the PageLoad method, just do the following:
string resetBtnScriptCb = divScript.InnerText;
divScript.Visible = false;
if (!Page.IsClientScriptBlockRegistered("resetbtnControlScript"))
{
Page.RegisterClientScriptBlock ("resetbtnControlScript",resetBtnScriptCb);
}
Conclusion
This should ensure that only copy of the embedded function in the UserControl gets rendered onto the client browser. Of course, I admit that you can use StringBuilder to build the JavaScript in code-behind itself. Then there comes the problem of escaping single quotes/double quotes, adding newlines etc. Perhaps this method just involves toggling with a runat=SERVER DIV.