3.1. Using JavaScript on the Client

The JavaScript language can be used independently of the browser. There are JavaScript interpreters for managing operating system components, interacting with COM objects, and automating server administration tasks. To use JavaScript in the browser, you should be aware of a few considerations.

First, you need to manage getting the script to the browser for a page effectively. As the amount of JavaScript you use grows, you will want to make use of the browser's ability to cache scripts for performance reasons. You also need to be aware of how the user's interaction with a page while background operations are performed affects the user's perception of the page's performance. In some conditions, you want your users to know that they are waiting for an action to be performed so they don't become frustrated, and in other cases, you want to ensure that the page is responsive while something happens transparently in the background. In addition, JavaScript resources can be embedded directly in a DLL and do not have to be deployed as text files on disk, as you might be accustomed to doing.

3.1.1. Getting JavaScript to the Browser

Before diving into the fundamentals of the language, you should understand how JavaScript code gets to the browser as part of a Web application. The HTML script tag is used to separate the script code from the markup, so the browser will be able to distinguish the difference. Listing 3-1 shows the two possible methods for including JavaScript in a page.

In the first example, the script code is included directly in the page within an HTML script element. The second example (the last line) defines the script code in a separate file and uses the src attribute of the script element in the page to provide the URL that the browser should use to retrieve the code.

Example 3-1. Two methods for getting JavaScript in your ASP.NET page
<script type="text/javascript">
   alert("Hello World");
</script>

<script type="text/javascript" src="scripts/code.js" ></script>

It used to be common to include language="javascript" in the script tag as well, but the language attribute has been deprecated in the latest HTML standards, although it is still accepted by most browsers at the present time. Multiple script tags can be included in the HTML source, so you can have many different sections of script code in a single page. Any code that is not defined within a JavaScript function is executed immediately when the page loads. The W3C standard includes the defer attribute to instruct the browser that it need not delay rendering of the HTML while the script is downloaded or parsed. This can be useful when you know that a particular piece of script code will not need to run until after the page has been completely rendered. Be aware, however, that users will start interacting with the page as soon as it is rendered. Users do not like waiting for page loads, and they certainly are not watching the animated browser icon to see if the browser is still busy loading part of the page that they cannot see. Therefore, the defer attribute is not commonly used.

If you use defer and the user performs actions in a partially rendered page, the code that tries to execute something from a deferred script before it is has finished loading will generate errors for the user. This is baffling to users, and the only recovery action is to load the page again. The error message they get is usually something vague about a function or variable being undefined. They do not have any way to know that the undefined something may not have loaded yet, so they may even repeat the same process and get the same error. The safest approach is to include script references earlier in the page whenever possible and avoid using deferred loading. This will make it more likely that the browser has your script code when the user starts interacting with the page. Of course, even this is not a guarantee.

To protect yourself from errors caused by early user interaction with a page, you can include a top-level piece of code to disable elements that might depend on load order. This way, you can avoid triggering the use of code that is still being fetched. For example, you can disable a Submit button in an HTML form to prevent the user from clicking it and needing some associated validation scripts before they are available.

3.1.2. Using .NET to Include Your Client-Side Scripts

ASP.NET uses the Page.ClientScript property to register and place JavaScript functions on your ASP.NET pages. Three of these methods are reviewed here. More methods and properties than just these three are available through the ClientScript object (which references an instance of System.Web.UI.ClientScriptManager), but these are the more useful ones. You can find the rest in the SDK documentation.

The Page.RegisterStartupScript and the Page.RegisterClientScriptBlock methods from the .NET Framework 1.0/1.1 are now considered obsolete. Both of these possibilities for registering scripts required a key/script set of parameters. Because two separate methods were involved, there was an extreme possibility that some key name collisions would occur. The Page.ClientScript property is meant to bring all the script registrations under one umbrella, making your code less error prone.

3.1.2.1. Using Page.ClientScript.RegisterClientScriptBlock

The RegisterClientScriptBlock method allows you to place a JavaScript function at the top of the page. This means that the script is in place for the startup of the page in the browser. Its use is illustrated in Listing 3-2.

Example 3-2. Using the RegisterClientScriptBlock method
<%@ Page Language="C#" %>

<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {
      string myScript = @"function AlertHello() { alert('Hello ASP.NET'), }";
      Page.ClientScript.RegisterClientScriptBlock(this.GetType(),
         "MyScript", myScript, true);
    }
</script>

From this example, you can see that you create the JavaScript function AlertHello() as a string called myScript. Then using the Page.ClientScript.RegisterClientScriptBlock method, you program the script to be placed on the page. The two possible constructions of the RegisterClientScriptBlock method are the following:

  • RegisterClientScriptBlock (type, key, script)

  • RegisterClientScriptBlock (type, key, script, script tag specification)

In the example from Listing 3-2, you are specifying the type as this.GetType(), the key, the script to include, and then a Boolean value setting of true so that .NET places the script on the ASP.NET page with <script> tags automatically. When running the page, you can view the source code for the page to see the results:

<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>
    Adding JavaScript
</title></head>
<body>
    <form method="post" action="JavaScriptPage.aspx" id="form1">
<div>
<input type="hidden" name="__VIEWSTATE"
 value="/wEPDwUKMTY3NzE5MjIyMGRkiyYSRMg+bcXi9DiawYlbxndiTDo=" />
</div>


<script type="text/javascript">
<! --
function AlertHello() { alert('Hello ASP.NET'), }//  -- >
</script>

    <div>
        <input type="submit" name="Button1" value="Button" onclick="AlertHello();"
         id="Button1" />
    </div>
    </form>
</body>
</html>

This code shows that the script specified was indeed included on the ASP.NET page before the page code. Not only were the <script> tags included, the proper comment tags were added around the script (so older browsers will not break).

3.1.2.2. Using Page.ClientScript.RegisterStartupScript

The RegisterStartupScript method is not too much different from the RegisterClientScriptBlock method. The big difference is that the RegisterStartupScript places the script at the bottom of the ASP.NET page instead of at the top. In fact, the RegisterStartupScript method even takes the same constructors as the RegisterClientScriptBlock method:

  • RegisterStartupScript (type, key, script)

  • RegisterStartupScript (type, key, script, script tag specification)

So what difference does it make where the script is registered on the page? A lot, actually!

If you have a bit of JavaScript that is working with one of the controls on your page, in most cases you want to use the RegisterStartupScript method instead of RegisterClientScriptBlock. For example, you'd use the following code to create a page that includes a simple <asp:TextBox> control that contains a default value of Hello ASP.NET:

<asp:TextBox ID="TextBox1" Runat="server">Hello ASP.NET</asp:TextBox>

Then use the RegisterClientScriptBlock method to place a script on the page that utilizes the value in the TextBox1 control, as illustrated in Listing 3-3.

Example 3-3. Improperly using the RegisterClientScriptBlock method
protescted void Page_Load(object sender, EventArgs e)
{
   string myScript = @"alert(document.forms[0]['TextBox1'].value);";
   Page.ClientScript.RegisterClientScriptBlock(this.GetType(),
      "MyScript", myScript, true);
}

Running this page (depending on which version of IE you are using for this example) gives you a JavaScript error, as shown in Figure 3-1.

Figure 3-1. Figure 3-1

This error occurs because the JavaScript function fired before the text box was even placed on the screen. Therefore, the JavaScript function did not find TextBox1, and that caused an error to be thrown by the page. Now try the RegisterStartupScript method shown in Listing 3-4.

Example 3-4. Using the RegisterStartupScript method
protected void Page_Load(object sender, EventArgs e)
{
   string myScript = @"alert(document.forms[0]['TextBox1'].value);";
   Page.ClientScript.RegisterStartupScript(this.GetType(),
      "MyScript", myScript, true);
}

This approach puts the JavaScript function at the bottom of the ASP.NET page, so when the JavaScript actually starts, it finds the TextBox1 element and works as planned. The result is shown in Figure 3-2.

Figure 3-2. Figure 3-2

3.1.2.3. Using Page.ClientScript.RegisterClientScriptInclude

The final method is RegisterClientScriptInclude. Many developers place their JavaScript inside a .js file, which is considered a best practice because it makes it very easy to make global JavaScript changes to the application. You can register the script files on your ASP.NET pages by using the RegisterClientScriptInclude method illustrated in Listing 3-5.

Example 3-5. Using the RegisterClientScriptInclude method
string myScript = "myJavaScriptCode.js";
Page.ClientScript.RegisterClientScriptInclude("myKey", myScript);

This creates the following construction on the ASP.NET page:

<script src="myJavaScriptCode.js" type="text/javascript"></script>

3.1.3. Perceived Performance

If you allow users to interact with a page before all the script code has been downloaded, the page appears to them to be ready to use. By temporarily disabling the page postback, you can ensure safety and allow users to enter their data on the page while the scripts continue loading in the background.

In addition to the perceived performance advantage, some applications temporarily disable elements of the form that cause a postback in order to avoid a complication with a security feature of ASP.NET. Some controls can be registered for validation, and ASP.NET will round-trip the set of valid values set for that control. The possible values are hashed (a cryptographic signature is calculated on them and later validated after postback) and round-tripped along with the values so that the server can detect any attempt by malicious code to submit something other than the valid list of values. Because the set of authentic values has to be collected while the page is being rendered and may not be fully assembled until after the form has been fully rendered, the hashed data is included after the closing form element.

When a specific Web form is fairly large or complex, the set of validation values can also be large, so it is possible for the user to interact with the form and submit it before the browser receives the validation data. The browser would then be unable to submit the set of valid values back to the server, and the user will see an error when the page is posted back on the server and the validation values are missing. Therefore, to prevent this scenario, you can disable the postback until you are sure that the browser has received all of the validation values.

In Listing 3-6, the Submit button is disabled initially in the HTML markup. The script element contains a function to enable the Submit button along with a line of script for attaching the function to the window's onload event. Thus, the button will be disabled initially and then enabled after the whole page has been loaded.

Example 3-6. Disabling the Submit button until the entire page is loaded
<%@ Page Language="C#" %>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Example</title>
</head>
<body>
    <form id="form1" runat="server">

    <script type="text/javascript">
        function enableSubmit()
        {
            var elt = document.getElementById('submitButton'),
            alert("Enabling form now");
            elt.disabled = false;
         }

        window.onload = enableSubmit;
    </script>

    <div>
        <input type="submit" id="submitButton" value="Submit"
         disabled="disabled" />
    </div>
    </form>
</body>
</html>

When you run this example, you get the following results as illustrated here in Figure 3-3. This example is before the button is enabled again.

Notice that this example only disabled the Submit button. Your first inclination might be to disable the entire form and have everything in it disabled, but that would not be portable to all the browsers. In a real application with several elements that might cause a postback, you would have to disable all of them initially and then enable them during the onload() event.

Figure 3-3. Figure 3-3

There is not a limit to the number of script tags allowed on a page, but browsers typically open only one or two channels back to the server for scripts and images, so it appears as though the page is loading slowly. You can improve the perceived performance of page loading by using several script tags to contain your JavaScript code so that the browser can download multiple scripts simultaneously. Although this may not complete the overall load any faster, allowing the user to start interacting with the page earlier makes it seem to be loading faster to the user.

3.1.4. Script Resources

One of the longstanding difficulties with the deployment of Web applications to Web servers is ensuring that the right versions of all the miscellaneous files are deployed. Ever since ASP.NET 2.0, you have been able to include JavaScript code as a text resource embedded in the compiled DLL for an application. This allows you to create a Web server control that includes the script files internally and can be deployed with only configuration entries and a single DLL. This ensures that the correct script files will always be sent to the user and will not have to be maintained in a folder on the server. ASP.NET will then field requests for those script resources via its built-in Web Resource handler.

If you view the source for just about any .aspx page, you will see references to WebResource.axd followed by a set of querystring parameters used to retrieve the appropriate embedded resource. At first glance, it looks like a bunch of garbage, but if you extract one of those URL querystrings from a typical page's source and paste it into your browser's address window to request it separately, the proper resource is returned to you. An example of this is shown here:

http://www.mysite.com/WebResource.axd?d=3843647524 -- -
HJKAeoedaslathlmhueeuyr&amp;t=111205042031232968

The Web Resource handler is used for more than just JavaScript files; it can also be used for image files. Since the first version of ASP.NET did not have this functionality, some developers modified the standard ASP.NET JavaScript files themselves to obtain certain types of custom behaviors. To maintain functionality for those customizations when upgrading to the next release, ASP.NET checks for the existence of those external script files in an application and uses them instead of the ones provided by Microsoft in System.Web.dll. However, this WebResource.axd mechanism can still be used by your own Web controls, regardless of whether it is used for the standard ASP.NET scripts used by all pages.

NOTE

Switching back and forth between languages can be a challenge. Visual Basic is not case sensitive, but C# is. Like C#, JavaScript is also case sensitive. The .NET Framework Design Guidelines advocate variable and API naming conventions that are different from JavaScript's. The convention in .NET development is to use camel-casing for member variables, with leading underscores for privates. Pascal casing is used for public members.

Although, when writing JavaScript, camel-casing is employed for public members. Developers have come to rely on these conventions, so it pays to be attentive to these details although it can be confusing at first, especially if you are switching languages often.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset