jQuery - Beginning Visual Basic (2012)

Beginning Visual Basic(2012)

Chapter 11

jQuery

What You Will Learn in This Chapter:

· What jQuery is

· What NuGet is and how to use it

· How to use jQuery to enhance your pages, including adding rich visual effects and animations

· How to leverage jQuery to enhance the ASP.NET validation framework

Wrox.com Code Downloads for this Chapter

You can find the wrox.com code downloads for this chapter on the Download Code tab at www.wrox.com/remtitle.cgi?isbn=1118311809. The code is in the Chapter 11 download.

In previous chapters you were introduced to JavaScript, the de facto language for client-side scripting and interacting with elements in your web pages at the client. Though the examples shown were relatively straightforward, JavaScript can do much more and is quite a powerful programming language. But powerful as it may be, it has a few shortcomings. One of the problems with JavaScript is that not all browsers interpret it the same way. A lot of the JavaScript code you'll write will work in all major browsers, but subtle differences in code and behavior exist that make it difficult to write code that behaves exactly the same in all major browsers. Also, JavaScript lacks some useful features that would come in handy in your day-to-day JavaScript coding. For example, it has built-in methods to find a specific element on a page (using getElementById as you saw in Chapters 9 and 10) and to find all elements of a specific HTML tag (using getElementsByTagName), but it lacks features like getElementsByClassName to get a list of elements with a specific class applied to them.

Fortunately, the Internet developer community has been very active developing frameworks that use JavaScript under the hood and that extend its power, while offering a very rich feature set that helps you create interactive client-side web pages. Over the years, many JavaScript libraries have been developed—most of which are free—including:

· Prototype (http://prototypejs.org)

· Scriptaculous, an add-on to Prototype (http://script.aculo.us)

· Ext JS (http://extjs.com)

· Dojo (http://dojotoolkit.org)

One framework that has received a lot of attention is jQuery. Initially developed and released by John Resig in January 2006, jQuery has grown to be a very popular client-side framework. It also caught the attention of Microsoft, which decided to start shipping jQuery with Microsoft products. Initially, jQuery shipped with the Microsoft ASP.NET MVC Framework, but it's now also included in Visual Studio 2012.

An Introduction to jQuery

The main focus of the jQuery library has always been to simplify the way you access the elements in your web pages, provide help in working with client-side events, enable visual effects like animations, and make it easier to use Ajax in your applications. In January 2006, John Resig announced the first version of jQuery, which was followed by an official release of jQuery 1.0 in August 2006. Many more versions would follow, with version 1.7.2 as the latest, stable release at the time of writing.

Note

jQuery is under active development, and, as such, there's a fair chance that by the time you read this book, a new version of jQuery will have been released. Although the code presented in this chapter is expected to be compatible with future versions, backward-compatibility issues may arise with later versions. If you find that some of your code doesn't work with the jQuery version you are using, consider using the files that come with this chapter's download to rule out any problems with the new version.

You have a few ways to acquire the jQuery library and add it to your website. First of all, you can download the latest version of jQuery from the official website at http://jquery.com. Not only will you find the downloadable files there, but you'll also find the documentation, FAQs, tutorials, and much more information you can use to make the most out of jQuery.

The second way is to use the ASP.NET Web Forms Site template to create a new site, because it already contains a Scripts folder with the necessary jQuery files. However, back in Chapter 2 you based the Planet Wrox website on the ASP.NET Empty Web Site template, which doesn't include these files.

The third solution to add jQuery to your site is by using a Content Delivery Network (CDN) as you'll see later.

The final way is to use NuGet, the Library Package Manager that ships with Visual Studio (including the Express editions). NuGet is discussed next.

Introducing NuGet

NuGet is an open source Library Package Manager that comes as a Visual Studio extension and that makes it very easy to add, remove, and update external libraries in your Visual Studio projects and websites. It was initially developed by Microsoft but has now been turned into an Open Source project that accepts contributions from the developer community. Although you'll see NuGet used in the context of a website in VS, NuGet is certainly not for ASP.NET only. You can use it for all types of applications you can build with Visual Studio.

To understand what problems NuGet solves, imagine you want to add an open source library such as jQuery to your ASP.NET website. Although the specifics differ from library to library, you usually need to go through the following steps:

1. Find the website of the library.

2. Find a link to the download of the latest stable version of the library and download it.

3. Unblock the downloaded file using Windows Explorer, unzip it, and add it to your project, optionally creating a specific folder for it.

4. Optionally, add a reference to the library in your project.

5. Optionally, configure the library through the Web.config file or other code files.

Using NuGet, you can greatly minimize the steps needed to add libraries to your project. For example, you can add the jQuery library with just five mouse clicks. In addition to adding packages, NuGet also enables you to easily update libraries to their latest versions after you've added them to your website, and it enables you to remove packages again without leaving a trace.

Besides the extension for Visual Studio, NuGet also has its own website at http://nuget.org. Here you can browse the catalog of packages, find commands for installing packages (more on that in the next section), read detailed documentation, and more.

To manage libraries with NuGet, you have two options: you can use the Manage NuGet Packages dialog box or use the Package Manager Console.

Using the Manage NuGet Packages Dialog Box

The Manage NuGet Packages dialog box enables you to search for packages online, as well as manage packages you already installed. You access this dialog box by right-clicking your website in the Solution Explorer and choosing Manage NuGet Packages. Alternatively, choose Tools ⇒ Library Package Manager ⇒ Manage NuGet Packages for Solution. Figure 11.1 shows the dialog box in action.

Figure 11.1

11.1

On the left of the dialog box you can choose from four different types of lists with packages:

· Installed packages—This item shows a list of packages that have been installed into your website. You can use this option to find out which version of a package you have installed, uninstall packages, or install the same package into another website or project that is part of the same solution.

· Online—This item enables you to search for packages online using the official NuGet package source, or on any additional feeds you may have added (which you can do using Tools ⇒Options ⇒ Package Manager ⇒ Package Sources). By default, the list shows the most popular packages first (measured by the number of downloads), but you can change the ordering using the drop-down list at the top. To the left of the Sort by drop-down you have the option to display only stable packages, or also include prelease versions of packages. In the upper-right corner you can search for packages by entering (part of) their name. Once you find the package you want to add to your website, select it, click the Install button and the NuGet Package Manager takes care of the installation process. You see more of this in a later exercise.

· Updates—This item shows a list of packages for which new versions have been released since you installed the package into your website. Because updates could potentially break an existing website, they are not installed automatically and you need to manually select the packages you want to update.

· Recent packages—This item gives you a list of packages you used before. This serves as a shortcut to packages you use often so you don't have to search for them online each time you want to install them in your website.

You can find the full documentation on the Manage NuGet Packages dialog box in the documentation section of the NuGet website at http://bit.ly/q2PiyM.

Besides using this dialog box, you can also manage packages using the Package Manager Console.

Using the Package Manager Console

The Package Manager Console enables you to manage your packages from a command-line interface. This is not as user-friendly as using the dialog box, but once you get the hang of using NuGet you'll find that the console can be really useful. Using the console you can access the same features as with the dialog box and more. Figure 11.2 shows the Package Manager Console, which you can access from the main menu by choosing Tools ⇒ Library Package Manager ⇒ Package Manager Console.

Figure 11.2

11.2

Note

NuGet is updated quite often (you'll be notified by Visual Studio when a new release is available) so your version number may be slightly different. That doesn't matter for the functionality described in this book.

This command-line window supports a number of commands that help you manage packages. To get a list of the available main commands, type Get-Help NuGet and press Enter. You'll see a list of commands appear that you can execute at the console. The console has IntelliSense as well to help you complete the commands by pressing the Tab key. In the example of the Help command, simply type Get followed by the Tab key to get a list with all commands that start with Get. You can then select the command from the list and complete it by pressing Tab again or by pressing Enter. Because many commands start with Get, in this case it's probably quicker to type Get-H and then press Tab, or to type the complete command yourself. However, for longer and more unique command names, using the Tab key can be a great time saver.

Probably the most popular commands are Get-Package and Install-Package. Using Get-Package you can list the packages that are currently installed in your site. To see the list, just type the command and hit Enter. If you try this now, your list will be empty because you haven't installed any packages yet. By using Get-Package -ListAvailable you can see a complete list of all available packages. Because thousands of them exist (and the list is growing), you want to filter the list using -Filter, like this:

Get-Package -ListAvailable -Filter jQuery

This lists all the packages that have jQuery in their name. Note that filtering isn't case sensitive. To find prerelease versions of packages that haven't been officially released yet, you use the -PreRelease option, like this:

Get-Package -ListAvailable -Filter jQuery -PreRelease

Once you find the package you want to install, use the Install-Package command. As an argument, you need to supply it the name of the package. For example, to install jQuery into your website you execute the following command:

Install-Package jQuery

After you hit Enter, the Package Manager Console downloads the package and installs it in your website exactly the same as using the Manage NuGet Packages dialog box does.

For a complete overview of all the available commands, look at the official NuGet documentation at http://docs.nuget.org. You can find the command-line reference here: http://bit.ly/q0N57L.

In the next exercise, you use the Manage NuGet Packages dialog box to install the jQuery library into your website.

Try It Out: Using NuGet to Install Packages

In this exercise you see how to find and install the latest jQuery package using the Manage NuGet Packages dialog box. Using the dialog box is the most intuitive and easiest way, so it's a good place to get started with NuGet. In later parts of this book you also use the Console window to install packages.

1. Start by opening the Manage NuGet Packages dialog box. You can do that by right-clicking your site in the Solution Explorer and choosing Manage NuGet Packages. Alternatively, you can choose Tools ⇒ Library Package Manager ⇒ Manage NuGet Packages for Solution. The dialog box shown in Figure 11.1 appears.

2. If it's not already selected, click the Online item in the list on the left.

3. Because jQuery is so popular, it should appear in the list with packages that are shown by default. If it's not, or if you want to install another package, use the search box at the top-right corner of the dialog box.

4. Click the jQuery library package in the list. Make sure you choose just the jQuery library, and not the jQuery UI (Combined Library) or jQuery Validation package, because these serve a different purpose.

5. Click the Install button. A dialog box pops up that lists the actions that are executed to install the package. Once that dialog box has disappeared, click the Close button to dismiss the Manage NuGet Packages dialog box.

That's it. You just installed jQuery using NuGet.

How It Works

To see how it works, take a look at the Scripts folder in your Solution Explorer. You should see an item called jquery-1.7.2.js, shown in Figure 11.3. Remember, a new version may have been released since this book was written so your version numbers may be different. During installation, NuGet added three jQuery-related JavaScript files to your Scripts folder (which it would have created if it didn't exist.) In addition, it kept track of the installed packages in a file called packages.config that has been placed in the root of your website and created a packagesfolder to store a local copy of the downloaded packages. Depending on your settings, this location could differ, but most likely it's located in a folder named after your site in Documents\Visual Studio 2012\Projects.

Figure 11.3

11.3

These three .js files all serve a different purpose. The file jquery-1.7.2.js contains the core jQuery code in an uncompressed format. This means you can read its code and use it for debugging purposes in cases where you need to see what code the library executes. The file jquery-1.7.2.intellisense.js contains the documentation for the code in the jQuery library that is used in the IntelliSense lists and documentation pop-ups. You see how this works later in this chapter. Finally, the file jquery-1.7.2.min.js is the core jQuery library in a compressed format. This is the file you'll use in your website because it has the smallest size and is thus the quickest to download.

Now that the jQuery library has been added to the website, the next step is determining where to use it. Because the jQuery library adds to the size of your web pages, it should be a deliberate choice whether or not you include it in your site.

Choosing the Location for Your jQuery Reference

To include jQuery in your website, you have a couple of options:

· Add a reference to the jQuery library in just the web pages or user controls that require it.

· Add a reference to the jQuery library in the master page of your site so it's available in all pages.

Both methods have their own advantages and disadvantages. Adding a reference to the jQuery library in just the pages that need it helps keep the size of your pages down a bit. When your users browse only to pages without jQuery, they'll never have to download the library file, saving them some bandwidth. Note that once they've visited a page that does reference the library, the browser will cache a copy of it, removing the need to download it again on subsequent visits to pages.

Adding the reference to jQuery in the master page of your site is quite convenient, because all pages based on this master page automatically get access to the jQuery functionality. However, this results in a small performance hit on the first page of your site because the library needs to be downloaded from the server. This is the option used in the Planet Wrox website.

In addition to the location where you add your jQuery file, you also have a few options with regard to the way you include the file.

Different Ways to Include the jQuery Library

Because the jQuery library consists of a single file with JavaScript code, you can embed a reference to the library in a page, user control, or master page using the standard <script> syntax:

<script src="FileName.ext" type="text/javascript"></script>

It's important to use a separate closing </script> tag because some browsers will choke if you use a self-closing tag.

By default, the NuGet package manager uses (and optionally) creates a Scripts folder in the root of the site for JavaScript files such as jQuery, so a reference to the jQuery library (called jquery-1.7.2.min.js) will end up like this:

<script src="/Scripts/jquery-1.7.2.min.js" type="text/javascript"></script>

You can also embed the reference inside the ScriptManager control that you added to the master page in the previous chapter. The ScriptManager control has a <Scripts> child element that lets you register JavaScript files that will be added to the final page in the browser. In its simplest form, a JavaScript file registered in the ScriptManager looks like this:

<asp:ScriptManager ID="ScriptManager1" runat="server">
  <Scripts>
    <asp:ScriptReference Path="∼/Scripts/jquery-1.7.2.min.js" />
  </Scripts>
</asp:ScriptManager>

Another alternative is to refer to an online version of the library with Microsoft's Content Delivery Network (CDN) or Google Code. For more information on this, visit Microsoft's CDN site at www.asp.net/ajax/cdn or Google's API site at http://code.google.com/apis/ajaxlibs/.

The advantages of using online versions of external libraries are improved performance and lowered bandwidth for your servers. Because it is likely that visitors to your site already have downloaded the shared scripts when visiting another site, they don't have to download them again when visiting yours.

In the following exercise, you add the jQuery library to the master page of the Planet Wrox website. With the library set up, the remainder of this chapter teaches you how jQuery works and how to use it in the Planet Wrox website.

Note

By the time you read this book, a new version of jQuery may have been released. This means that the version number in your jQuery file may be different from what I am showing here. Be sure to update the filenames to match your library files.

Try It Out: Your First jQuery Page

In this exercise, you add the jQuery library to the master page so it's available to all pages in your site.

1. 1 . Open the Frontend.master file from the MasterPages folder and switch it to Markup View if necessary. Locate the ScriptManager control and add the following bolded markup to it:

<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true">
  <Scripts>
    <asp:ScriptReference Path="∼/Scripts/jquery-1.7.2.min.js" />
  </Scripts>
</asp:ScriptManager>

If your ScriptManager didn't have a separate closing tag yet, you should add one now (and remove the slash (/) from the opening tag) or the code won't be added correctly.

2. Save and close the master page because you're done with it for now.

3. To try out the jQuery library, create a brand new Web Form in the Demos folder based on your custom template. Call the page jQuery.aspx, and set its Title to jQuery Demo.

4. With the new page open in Markup View, add the following code to the Content block for cpMainContent:

<asp:Content ID="Content2" ContentPlaceHolderID="cpMainContent" runat="Server">
  <input id="Button1" type="button" value="button" />
  <script type="text/javascript">
    $(document).ready(function() {
      $('#MainContent').css('background-color', ‘green')
 
      $('#Button1').click(function() {
        $('#MainContent').css('background-color', ‘red')
                      .animate({ width: ‘100px', height: ‘800px' })
      });
    });
  </script>
</asp:Content>

Just like many other programming languages, JavaScript (and thus jQuery) is case sensitive and quite sensitive to missing quotes, brackets, and parentheses, so make sure you type this code exactly as shown here. Alternatively, you can copy and paste the code from the jQuery.aspx page that is part of the full source code that comes with this book.

Note that while typing, IntelliSense pops up, helping you complete the code and giving you information about various methods and parameters in a tooltip. If it doesn't pop up, make sure you added the right <Scripts> element to the master page. Also, try saving and closing all open documents and then reopen jQuery.aspx.

5. Save the changes to the page and then press Ctrl+F5 to open it up in the browser. Notice how the background color of the MainContent element has turned to green. Click the button and notice how the background color changes to red and how the MainContent element changes size, ending up with a width of 100 pixels and a height of 800 pixels.

Note

If you get an error, or you don't see the animation, make sure the link to the jQuery library is added to the master page correctly. Also, check your code for any typos you may have made.

How It Works

Although the effects shown in this exercise aren't that fancy, a lot is going on under the hood to make this example work. To understand how it works, first look back at the master page where you added a reference to the jQuery library:

<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true">
  <Scripts>
    <asp:ScriptReference Path="∼/Scripts/jquery-1.7.2.min.js" />
  </Scripts>
</asp:ScriptManager>

This tells the script manager to include a script element pointing to the jQuery library. If you look in the HTML source for the page in the browser, you should see the following script element:

<script src="../Scripts/jquery-1.7.2.min.js" type="text/javascript"></script>

This in turn tells the browser to download the jquery-1.7.2.min.js file from the Scripts folder, giving your page access to all functionality included in the jQuery library.

The next thing to look at is the code in the jQuery demo page. First, you added a standard <script> block that can contain JavaScript. Inside this block, you added some jQuery code that is fired as soon as the browser is done loading the page. Everything between the opening ({) and closing (}) curly braces is executed when the page is ready:

<script type="text/javascript">
  $(document).ready(function() {
    // Remainder of the code skipped
  });
</script>

Because the jQuery code interacts with the elements on the page, you often have to wait until the entire page has loaded so the elements you're programming against are available. Adding jQuery code like this is a standard practice to delay execution of the code until the entire page is ready. You see more of this, including a handy shortcut to the “document ready function" $(document).ready later in this chapter.

The code that is executed when the page is ready consists of two parts. The first line of code sets the background color of the MainContent <section> to green:

$('#MainContent').css('background-color', ‘green')

This code gets a reference to the MainContent element and then calls the css method to change the background color to green. Remember document.getElementById from the previous chapter that gets a reference to an element in the page by its id? In this example, $('#MainContent') is jQuery's equivalent, but as you see later, it's much more powerful.

The second part sets up a click handler for the HTML button you added to the page, similar to how you used onclick in Chapter 10. Inside the click handler you see some code that changes the background color of the MainContent <section> element to red, and changes the height and the width of it using a fluid animation:

$('#Button1').click(function() {
        $('#MainContent').css('background-color', ‘red')
                   .animate({ width: ‘100px', height: ‘800px' })
      });

Again, you learn more about how jQuery is able to find the button and the <section> element and how the css and animate methods work later in this chapter, so don't worry too much if none of this is making a lot of sense right now.

When you click the button in the browser, the MainContent's background color is changed to red, and then its width and height are changed to 100 and 800 pixels, respectively.

When you typed the jQuery code you may have noticed you got help from IntelliSense. As soon as you typed $( you got a tooltip explaining the information you can pass to this function. Likewise, IntelliSense helps you find and complete the css method and the various arguments you need to pass to it, as shown in Figure 11.4.

Figure 11.4

11.4

IntelliSense for jQuery works through the extra file—jquery-1.7.2.intellisense.js—you added to the site with NuGet. VS scans the library's folder for files ending in intellisense.js, parses them, and then uses the documentation it finds in them to build up the IntelliSense list.

The reason for the separate documentation file is to keep the size of the original jQuery library down. Without the documentation, the library is only 93 KB; with the documentation the file size would be much bigger.

You should never include a link to the IntelliSense version of the library in your pages because it doesn't add any value in the browser.

Now that you've seen some jQuery at work, it's time to get a better understanding of its possibilities and syntax.

jQuery Syntax

To understand and use jQuery, you need to know a few important basics. First, you need to know more about jQuery's core functionality, including the $ function you've seen before, and its ready method that enables you to execute code when the page is done loading in the browser. Next, you need to learn more about jQuery's selector and filter syntax, which enable you to find elements in a page by criteria that you specify. Once you have a reference to one or more elements in a page, you can apply various methods to them, like the css method you saw earlier. You also need to know a little about jQuery events that enable you to attach behavior to the events that your HTML elements might fire, like click, mouseover, and so on. In the next couple of sections, you see all of these main jQuery topics at work.

jQuery Core

Most of the jQuery code you write will be executed when the browser is done loading the page. It's important to wait with executing your code until the page is done loading the DOM. The DOM—the document object model—is a hierarchical representation of your web page and contains a tree-like structure of all your HTML elements, script files, CSS, images, and so on. The DOM is always in sync with the page you see in the browser, so if you make a programmatic change to the DOM (for example, with jQuery code), the change is reflected in the page in the browser. If you execute your jQuery code too early (for example, at the very top of the page), the DOM may not have loaded the elements you're referring to in your script, and you may get errors. Fortunately, it's easy to postpone the execution of your code until the DOM is ready using the ready function in jQuery. You've already seen the ready function at work in the previous Try It Out, but it's shown here again now that you better understand what it's used for:

$(document).ready(function() {
  // Code added here is executed when the DOM is ready.
});

Any code you add between the opening and closing curly braces is executed when the page is ready for DOM manipulation. jQuery also comes with a shortcut for the ready function to make it easier to write code that fires when the DOM is ready. The following snippet is equivalent to the preceding example:

$(function() {
  // Code added here is executed when the DOM is ready.
});

Note

It's important that any code referencing the jQuery library is not run before the jQuery library itself is loaded. Because the link to the jQuery library is added after the <body> tag by the ScriptManager, you need to find a location later in the page. A good place for this is near the closing</body> tag defined in the master page.

Because jQuery code is often specific to a page, it makes sense to add the code to the end of just the pages that require it. To make this a little easier, you can add a ContentPlaceHolder in your master page especially for this purpose. The pages that use this master page then have an easy location to write jQuery code. You see how to do this in the next exercise.

In the previous jQuery example you saw some code that selected the MainContent <section> element and the button in your page. However, jQuery comes with a lot more options to select specific elements in your pages. These options are discussed next.

Selecting Items Using jQuery

In jQuery you use the dollar sign ($) as a shortcut to find elements in your page. The elements that are found and returned are referred to as a matched set. The basic syntax for the $ method is this:

$('Selector Here')

Between the quotes (you can use single or double quotes, as long as you use the same type on each end) you enter one or more selectors, which are discussed later. The $ method returns zero or more elements that you can then influence using one of the many jQuery methods. For example, to apply some CSS to all h2 elements, you use the css method:

$('h2').css('padding-bottom', ‘10px');

This applies a padding of ten pixels at the bottom of all headings at level two in the page. The cool thing about many of the jQuery methods is that, besides applying some design or behavior, they return the matched set again. This enables you to call another method on the same matched set so both are applied. This concept is called chaining or fluent programming where you use the result of one method as the input of another, enabling you to create a chain of effects. For example, the following code first changes the font size of all level-two headings in the page, and then fades them out until they are invisible in five seconds:

$('h2').css('font-size', ‘40px').fadeOut(5000); // timeout is in milliseconds

As you learned in earlier chapters, you should try to avoid using inline CSS properties like this. Instead, you should define CSS classes and assign them to the HTML elements. You see how to do this later in this chapter. You learn more about the different visual effects like animate and fadeOutafter you've seen how selectors and filters work.

Basic Selectors

jQuery selectors enable you to find one or more elements in your page's document object model so you can apply all sorts of jQuery methods to these elements. The great thing about jQuery selectors is that you already know how they work. Rather than inventing a new technique to find page elements, the designers of jQuery decided to use an existing selector-based syntax that you are already familiar with: CSS. Remember the CSS selectors from Chapter 3? You can use the exact same ones in jQuery.

The Universal Selector

Just as its CSS counterpart, the Universal selector matches all elements in your page. To set the font-family property of the style for each element in your page to Arial, you use this code:

$('*').css('font-family', ‘Arial');

The Element Selector

This selector returns a reference to zero or more elements that match a specific tag name. For example, this code turns the text color of all headings at level two to blue:

$('h2').css('color', ‘blue');

The ID Selector

This selector finds and retrieves an element by its id, the same as you would do in CSS. For example, to set the CSS class for a button called Button1, you use this code:

$('#Button1').addClass('NewClassName');

When this code sets the CSS class (using the addClass method), the standard CSS rules apply. That means that for this code to work and change the appearance of the button, the NewClassName class needs to be available to the page, either through an external CSS file or by an embedded style sheet. Refer to Chapter 3 if you need a refresher on the different cascading style sheet types. However, you'll also see examples where a CSS class is added that doesn't exist in a CSS file. This is convenient to “tag" elements so you can select them again later using a Class selector.

The Class Selector

The Class selector returns a reference to zero or more elements that match a specific class name. Consider this HTML fragment:

<h1 class="Highlight">Heading 1</h1>
<h2>Heading 2</h2>
<p class="Highlight">First paragraph</p>
<p>Second paragraph</p>

Notice how two of the four elements have a CSS class called Highlight. The following jQuery code changes the background color of the first heading and the first paragraph to red, leaving the other elements unmodified:

$('.Highlight').css('background-color', ‘red');

Grouped and Combined Selectors

Just as with CSS, you can group and combine selectors. The following Grouped selector changes the text color of all h1 and h2 elements in your page:

$('h1, h2').css('color', ‘orange');

With a Combined selector, you can find specific elements that fall within some others. For example, the following jQuery touches just the paragraphs that fall within the MainContent element, leaving all other paragraphs alone:

$('#MainContent p').css('border', ‘1px solid red');

To get a feel for the selectors in jQuery and the effects you can apply to the matched set, the next exercise shows you how to use some of the selectors and apply some animations to the matched sets. In later sections of this chapter, you get a more detailed explanation of the different animations; for now, just focus on the selector part of the jQuery code.

Try It Out: Using Basic Selectors

In this exercise, you first add an additional ContentPlaceHolder control to the main master page so it's easier to add client-side jQuery code to your pages. You then write some jQuery to try out the various selectors.

1. Open up the Frontend.master file from the MasterPages folder and make sure it's in Markup View.

2. Near the bottom of the page, right before the closing </form> tag, drag a ContentPlaceHolder from the Toolbox. Set its ID to cpClientScript. Your code should end up like this:

    <footer>Footer Goes Here</footer>
  </div>
  <asp:ContentPlaceHolder ID="cpClientScript" runat="server">
  </asp:ContentPlaceHolder>
</form>

3. Save and close the master page because you're done with it for now.

4. Create a new demo page called BasicSelectors.aspx in the Demos folder. Once again, base it on your own template and give it a meaningful title. Switch the page to Design View, locate the cpClientScript placeholder at the bottom, open its Smart Tasks panel, and choose Create Custom Content.

5. Switch to Markup View and add the following HTML to the cpMainContent placeholder (don't accidentally add it to the placeholder you just added):

<h1>Basic Selectors</h1>
<div class="SampleClass">I am a div.</div>

6. Add the following jQuery code demonstrating all six basic selectors to the cpClientScript placeholder you created in step 4:

<asp:Content ID="Content3" runat="server" ContentPlaceHolderID="cpClientScript">
<script type="text/javascript">
  $(function()
  {
    $('*').css('color', ‘Green');                                 // Universal
    $('#Sidebar').css('border-bottom', ‘2px solid red');          // ID
    $('h1').bind('click', function () { alert('Hello World') });  // Element
    $('.SampleClass').addClass('PleaseWait').hide(5000);          // Class
    $('footer, header').slideUp('slow').slideDown('slow');        // Grouped
    $('#Sidebar img').fadeTo(5000, 0.1);                          // Combined
  });
</script>
</asp:Content>

7. Save all your changes and request the page in the browser. All text is now green, the sidebar has an extra bottom border, you see the Please Wait animated icon and text appear and then disappear, the header and footer disappear and then reappear, and finally, during a five-second period, the banner in the sidebar becomes almost transparent. If you click the Basic Selectors heading you get a pop-up saying Hello World.

How It Works

Phew, lots of animation fun. I typically don't recommend adding all these features to your pages at once or you'll be sure to scare away most of your users. However, for this demo it works really well because you can see some of the power of jQuery. You've seen all of the six selectors, but the code that is being executed against their matched sets is probably new to you.

The first selector selects all elements in your page and then applies the css method to turn their font color to green. The ID selector then gets a single element and calls the same css method to apply a border. The third example uses the Element selector to find the h1 element and then dynamically binds a click handler so that when you click the heading, the code between the curly braces is executed.

Selector four demonstrates the Class selector and shows you how to find elements by their class name. Notice that the CSS class being searched for doesn't have to be an existing CSS class defined in your style sheet. Once the elements are found, the addClass method then adds a new class to them, PleaseWait in this example, which applies the spinner image as the background to the <div> element. The hide method then hides the elements again during a five-second timeframe.

Line number five uses the Grouped selector to find both the footer and the header elements. The slideUp method then slowly decreases the height of these elements until they have completely disappeared. In doing so, it remembers the initial size, so when you call slideDown again it knows to what size to restore the elements.

The final example uses a Combined selector to find the banner image in the right-hand sidebar. Once it has found the image, it slowly dissolves it (in five seconds) by setting its opacity to 0.1 (10%) so it gets almost invisible.

In a later section in this chapter you see more of the various styling and animation methods that jQuery offers. For now, it's just important that you understand the selector syntax to refer to the elements in your page.

Quite often, simply selecting items in your page is not enough. For instance, when selecting rows in a table you may not want to select all rows at once, but only the odd or even rows, so you can apply a “zebra stripe" effect to the table where odd and even rows have different colors. That's where filters come into play.

Basic Filters

In jQuery you can use filters to further filter the result set from a selector. This opens a lot of possibilities because it enables you to get at elements like the first, last, all even or odd ones, all headings, or items at a specific location. The table after the next exercise lists the most-used basic filters and gives an example of how to use them. To follow along with these examples and many that follow, carry out this exercise, which sets up a test page for most of the jQuery examples.

Try It Out: Setting up a jQuery Demo Page

In this exercise, you create a brand new demo page you can use to try out many of the examples in this chapter, simply by replacing a single line of code.

1. Create a new page based on your custom template and call it jQueryDemos.aspx. Give the page a title and then in the cpMainContent placeholder add the following HTML:

<h1 title="First Header">First Header</h1>
<table id="DemoTable">
  <tr><td>Row 1 Cell 1</td><td>Row 1 Cell 2</td></tr>
  <tr><td>Row 2 Cell 1</td><td>Row 2 Cell 2</td></tr>
  <tr><td>Row 3 Cell 1</td><td>Row 3 Cell 2</td></tr>
  <tr><td>Row 4 Cell 1</td><td>Row 4 Cell 2</td></tr>
  <tr><td>Row 5 Cell 1</td><td>Row 5 Cell 2</td></tr>
</table>
<h2>Second <span style="font-style: italic; font-weight: bold;">
               Header</span></h2>
<input id="Button1" type="button" value="button" />
<input id="Text1" type="text" />
<input id="Checkbox1" type="checkbox" />
<input id="Checkbox2" type="checkbox" />

You don't have to type all this code yourself. Instead, you can use VS to write most of it for you. Make good use of the Table menu and the HTML category of the Toolbox.

2. Add a Content block for the cpClientScript below cpMainContent and enter the following code:

</asp:Content>
<asp:Content ID="Content3" runat="server" ContentPlaceHolderID="cpClientScript">
<script type="text/javascript">
  $(function()
  {
    // Examples go here
  });
</script>
</asp:Content>

3. Replace the line // Examples go here with the following code to test out your setup:

$('#DemoTable').css('background-color', ‘green');

4. Save your changes and press Ctrl+F5 to open the page in your browser. If all went well, the background color of the cells in the table turned green.

5. Close your browser and go back to VS. Press Ctrl+Z to undo your last changes until you see the // Examples go here line again, and save the page.

How It Works

In this exercise you created a simple Content block that can hold your jQuery code. You then defined a code block that fires as soon as the browser is done loading the DOM. Inside this block you wrote a simple selector that selects the table with an id of DemoTable and then used jQuery'scss method to change its background color.

In the following table you see a list of jQuery's basic filters. Remember, you can try out each example by replacing the //Examples go here line with the code examples given. Then save the page and load it in your browser to see the code at work.

Filter

Purpose

:first
:last

Enables you to select the first or last item in a matched set. The following example changes the background color of the first or last row of the table to red:

$('#DemoTable tr:first').css('background-color', ‘red'); 
$('#DemoTable tr:last').css('background-color', ‘red');


First, the table is found using #DemoTable. Then all its rows are found using tr. Finally, the first or last row is found using the :first and :last filters.

:odd
:even

Enables you to select the odd or even items in a matched set. The following example changes the background color of the odd rows of the table to red. Because the numbering is zero-based, you actually see the second and fourth rows change color (because they have an index of 1 and 3, respectively).

$('#DemoTable tr:odd').css('background-color', ‘red');

:eq(index)
:lt(index)
:gt(index)

Matches elements by their index. :eq (equals) returns a single element by its index, and :lt (less than) and :gt (greater than) return items smaller or greater than the given index, respectively. Examples:

// Changes the color in the first row (with an index of 0)
$('#DemoTable tr:eq(0)').css('color', ‘green');
 
// Changes only the last two rows. The first three 
// with an index of 0, 1 and 2 respectively, are skipped.
$('#DemoTable tr:gt(2)').css('color', ‘green');
 
// Changes the text color of the first two rows to green.
$('#DemoTable tr:lt(2)').css('color', ‘green');

:header

Finds all headers (from h1 to h6) in the page. Example:

$(':header').css('color', ‘green');

For a complete list of all basic filters, check out the jQuery documentation at http://api.jquery .com/category/selectors/.

Advanced Filters

Besides the basic filters you just saw, jQuery supports a lot more filters that enable you to get items based on the text they contain, whether or not they are visible, and also on any attributes they may have. Additionally, you can find filters to get at form elements (like buttons, check boxes, radio buttons, and so on) and a number of selectors that enable you to select children, parents, siblings, and descendants. The following table lists the ones you'll use most. The online jQuery documentation gives you access to the complete list, with full working examples showing how they work.

Filter

Purpose

:contains(text)

Matches an element by the text it contains. Example:

$('td:contains("Row 3")').css('color', ‘green');


If you leave out the td, the entire table will be green. This is because the table itself is matched as well (one of its children contains the text Row 3) so the color is applied to the table, which in turn changes the text in each cell to green. Note how I am using double quotes for the text string to avoid closing the single quote from the selector too soon.

:has(element)

Matches elements that contain at least one of the given elements. Example:

$(':header:has("span")').css('color', ‘green');


This matches only the h2 because it's a header (:header) and contains a <span> element (has("span")).

[attribute]

Matches an element based on the given attribute. Example:

// Matches the button and the text box as both 
// have a type attribute but would also
// match other elements with a type attribute
$('[type]').css('color', ‘green');


To select only input controls with a type attribute you can use this:

$('input[type]').css('color', ‘green');


You need to type some text in the text box to see the green font color.

[attribute=value]

Matches an element based on an attribute and that attribute's value. Example:

// Matches just the text box
$('[type=text]').css('color', ‘green');

:input
:text
:password
:radio
:checkbox
:submit
:image
:reset
:button
:hidden
:file

These selectors enable you to match specific client HTML form elements. For example, the code snippet that finds the button and the text box can be rewritten using a Grouped selector as follows:

$(':button, :text').css('color', ‘green');
You can use these filters to do some fancy stuff. For example, to write some functionality that checks all check boxes in a form, you can use:$(':checkbox').attr('checked', true);


In order to uncheck all check boxes, you pass false as the second argument to the attr method.

Powerful as these selectors and filters are, they are pretty useless without a way to act upon their results. Changing the looks and behavior of the items in the matched set is the topic of the next section.

Modifying the DOM with jQuery

Once you have a matched set, you want to do something with it. For example, you may want to apply a CSS class or style to the items in it. Or you may want to append some behavior to them, like adding a click handler that fires some code when the items get clicked. You've already seen some examples of this using the css and bind methods, but jQuery has a lot more to offer. In the next two sections, you see how to work with the various CSS methods and learn how to set up event handlers.

CSS Methods

CSS is supported in jQuery in a few different ways. First, there's the css method that enables you to retrieve a specific CSS value (like the color of an item), and to set one or more CSS properties on a set of elements. Secondly, methods like addClass, removeClass, toggleClass, and hasClassenable you to alter or inspect the CSS classes that are applied to elements. Furthermore, a couple of methods enable you to work with the dimensions and position of an element. I discuss only the most common ones, but you can look up the entire list at the jQuery website. The examples once again use the same HTML fragment you saw before, so it's easy to follow along if you want to try them out in your browser.

css(name, value)

This method enables you to set a specific CSS property on a matched element. The name argument refers to a CSS property (such as border, color, and so on) and the value defines the style you want to apply. The following example changes the background color of the h1 element:

$('h1').css('background-color', ‘green');

css(name)

This method retrieves a specific CSS value based on the property you pass to it. The following example alerts ‘italic’ because that's the font-style of the <span> element in the heading level 2:

alert($('h2 span').css('font-style'));

You can use this value in your jQuery scripts; for example, you can use it to toggle the font-style between italic and normal or to set multiple elements to the same style.

css(properties)

This is quite a powerful method because it enables you to set multiple properties on the matched elements in one fell swoop. The following example changes the color of all cells in the table to red, changes the font to Verdana and sets their padding to 10px. You pass the data in what is called ananonymous object where you wrap the entire set of properties in a pair of curly braces ({}), separate each property and value by a colon (:) and each pair by a comma:

$('#DemoTable td').css({'color' : ‘red', ‘font-family' : ‘Verdana', 
           ‘padding' : ‘10px'});

addClass, removeClass, and toggleClass

The addClass and removeClass methods enable you to add and remove classes from elements, respectively. Just as with plain CSS, you're better off using these methods than assigning inline CSS with the css(properties) method. This way, it's easier to define CSS classes at a central place, which makes them easier to maintain and reuse. The next example shows how to assign a class to the h2 element:

$('h2').addClass('PleaseWait');

If you want to remove the class again, you call removeClass like this:

$('h2').removeClass('PleaseWait');

The toggleClass method assigns the class if it's not present yet and removes it otherwise.

All three methods enable you to pass multiple classes by separating them with a space.

attr(attributeName)

The attr method enables you to read and set the values of attributes on HTML elements. This version, which accepts a single argument, is used to read an existing value. For the attributeName you pass the name of the attribute as a string. The following example alerts First Header, the titleattribute of the h1 header:

alert($('h1').attr('title'));

attr(attributeName, value)

The second version of attr, which accepts two arguments, is used to change the value of an attribute. Besides the name of the attribute you want to change, you also need to send the new value for the attribute. The following example checks all check boxes in the demo page:

$(':checkbox').attr('checked', true);

Together, these CSS methods give you great power to change the look and feel of elements in your page. You can take this one step further by using the rich event system in jQuery that enables you to assign and remove all kinds of handlers to your elements through code.

Handling Events

Events are a very common technique in many programming languages. You've seen .NET events at work in previous chapters where you used them to handle a Button control's Click event or a Page's Load event. JavaScript and the DOM are no exception and events are available in many places. For example, many HTML elements (such as a button defined with input type="button") have a click event that fires when you click it. Likewise, they have mouseover and mouseout events that fire when you move your mouse over or away from them. Normally, when you define the events directly in markup, they look like this:

<input type="button" onclick="alert('Hello');" value="Click Me" />

Rather than writing the code they trigger inline (the alert function in this example), you can also point them to JavaScript functions you can write yourself. The following example calls a fictitious SayYourName function:

<input type="button" onclick="SayYourName();" value="Click Me" />

jQuery goes one step further, and enables you to hook up events not only to a single element, but to a whole matched set at once. This is extremely powerful because it enables you to bind handlers to a large number of elements with only a few lines of code. Consider, for example, a table with many rows. To make the table a little more visually attractive, you could apply a technique that is called “active item tracking," where the item your mouse is over changes color. Without jQuery you would write onmouseover and onmouseout handlers on each and every row in the table. This clearly leads to a lot of excessive bloat in the final HTML of the page. With jQuery, all you need is this code, again using the HTML code samples you used before:

$(function()
{
  $('#DemoTable tr')
      .bind('mouseover', function() { $(this).css('background-color', ‘yellow') });
});

This code finds all the table rows within the #DemoTable element and then dynamically assigns a function that is called when you hover your mouse over each row. If you hover your mouse over them, the background changes color. But if you move your mouse away, the new color remains. To fix this problem, you can use jQuery's chaining concept, where the result of a jQuery method returns the matched set so you can apply another function to it. To bind the mouseout to a new function, simply call bind again on the return value of the first call to bind:

$('#DemoTable tr')
    .bind('mouseover', function() { $(this).css('background-color', ‘yellow') })
    .bind('mouseout', function() { $(this).css('background-color', ‘') });

Notice how the semicolon that closed off the line in the previous example has been moved to the final line. Then the second bind is simply chained to the previous call to bind. It's a bit difficult to see because the code is spread out over multiple lines to accommodate the width of this book, but this code actually comes down to this:

$('#DemoTable tr').bind('mouseover', ...). bind('mouseout', ...);

This code does three things: first it uses $('#DemoTable tr') to find all rows in the table. On the matched set that is returned it calls bind to dynamically hook up some behavior that fires when you move your mouse over a row. Then bind is called again on the matched set returned by the first call to bind to reset the background color when you move your mouse away from the table row. Notice how I am setting the color to an empty string ('') to remove the CSS background property so you can see the original background again.

There's one more important thing to look at in this example and that's the way the background color is set:

$(this).css('background-color', ‘yellow')

The this keyword in this example refers to the element to which the item is applied: the table row in this case. Using $(this) then gives you a jQuery matched set (containing a single element) to which you can apply regular jQuery methods such as css. Instead of using jQuery you can also execute standard JavaScript against the this element.

this.style.backgroundColor = ‘yellow'

The table row (and many other HTML elements) has a style property that lets you change CSS styles programmatically. Maybe you expected to use style.background-color to change the color, but that's not how it works in JavaScript. In that language, the dash (-) is not a valid identifier so in JavaScript all dashes are removed from the property names. Furthermore, each letter following the original dash is written in uppercase. So, background-color in CSS becomes backgroundColor in JavaScript, font-family becomes fontFamily, and so forth. Keep these naming rules in mind when you try to set CSS information dynamically through JavaScript and jQuery.

Miscellaneous jQuery Functionality

Before you move on to the next topic of effects with jQuery, you need to understand a few important functions in jQuery. First of all, there's each.

The each method iterates (or loops) over a collection. This is great if you want to apply some behavior to items in your matched set that you cannot set with a single jQuery function. As an argument to each you supply a function that is executed for each item. The following each example alerts the contents of each table cell by looping over the items in the matched set and then calling alert. Again, you can try this out with your jQueryDemos.aspx page.

$('#DemoTable td').each(function()
  {
    alert(this.innerHTML);
  });

Two other important methods include parent and prev. These methods are used in DOM traversing, where you can “walk" up and down the document tree finding elements that are either below or above an item, or at the same level.

The prev method selects a matched element's direct sibling. To see how this works, take a look at this:

alert($('#DemoTable td:contains("Row 1 Cell 2") ‘).prev()[0].innerHTML);

What do you think this alerts? If you guessed “Row 1 Cell 1,” you're right. The $ selector first selects the table cell in the second column of the first row by the text it contains. The prev method then returns its first sibling: the cell to the left of it. Because a matched set is a collection even if it contains only a single item, you still need to use an indexer (with [0]) to refer to that first item. The table cell then exposes an .innerHTML property that returns the content of the cell.

Finally, take a look at parent:

alert($('#DemoTable td:contains("Row 1 Cell 2") ‘).parent()[0].innerHTML);

If you run this code in the demo page, you get the result shown in Figure 11.5.

Figure 11.5

11.5

If you're not seeing this exact same HTML, make sure that the line that begins with alert is the only one inside your document ready function, because the other examples may influence the HTML for the table.

The selector is the same as in the previous example. The parent function then points to the <tr> around the matched table cell. Alerting the innerHTML then returns the HTML for the two cells that this row contains.

Common Mistakes When Working with jQuery

Depending on the complexity of the jQuery functionality you're using, writing the code can be quite challenging. You need to take care of the proper capitalization, parentheses, brackets, commas, and more. When you find your jQuery code doesn't run or has unexpected behavior, check to see if your code is suffering from the following problems.

Your ID Selectors Don't Work

It's likely you forgot to include the # symbol in front of it. $('DemoTable') does not select the table with an id of DemoTable, whereas $('#DemoTable') does select it. Another situation where your ID selector might not work is when you've got the casing wrong. ID selectors are case sensitive, so$('#DemoTable') is not the same as $('#demotable').

Your ID Selectors Don't Work, Even with a Hash Symbol

In this case, it's likely that the client element doesn't have the id you expect. Maybe the ASP.NET run time changed the client id by prefixing it with the id of its parent? In that case, try setting the ClientIDMode on the relevant control to Static so the id ends up more predictable. Also make sure your code executes inside the document ready function because the elements you're targeting may not be available yet.

None of Your Code Seems to Run

Check your parentheses, curly braces, and quotes. Each pair needs to be balanced, with an equal number of opening and closing items.

So far the code you've seen revolves mostly around finding elements in your page and changing their appearance through CSS or to execute JavaScript. However, jQuery comes with a bag of tricks to animate elements in your page as well. In the next section you see these so-called effects, followed by a Try It Out exercise that shows them in action.

Effects with jQuery

In an earlier example in this chapter you saw how to use slideUp and slideDown to slowly hide and show elements. But these are only two of the many effect and animation methods that jQuery has available. The following table lists the most common ones you can use. Once again, you're advised to try out all examples using the jQueryDemos.aspx page.

Method Name

Purpose

show()
hide()

Hides or shows the matched elements by decreasing the height, width, and opacity (making them transparent). Both methods enable you to define a fixed speed (slow, normal, and fast) or a number defining the animation time in milliseconds. Examples:

$('h1').hide(1000);  //Hide the heading in 1 second
$('h1').show(1000);  //Make it reappear in 1 second

toggle()

The toggle method uses show and hide internally and changes the display of the matched elements. That is, visible items are hidden, and vice versa. Example:

$('h1').toggle(2000); // hide or show the h1 in 2 seconds

slideDown()
slideUp()
slideToggle()

Just like hide and show, these methods make matched elements appear or disappear. However, they do this by adjusting the height from its current size to zero or vice versa, causing the element to “slide up” or “slide down.” The slideToggle method slides down hidden elements and slides up visible elements, which makes it easy to show and hide elements repeatedly with a single action. Examples:

$('h1').slideUp(1000);
$('h1').slideDown(1000);
$('h1').slideToggle(1000);

fadeIn()
fadeOut()
fadeTo()

These methods make the matched elements visible or invisible by changing their opacity. fadeOut sets the opacity to 0, making the item completely transparent, and then sets the CSS display property to none, hiding the item completely. fadeTo lets you specify an opacity (a number between 0 and 1) to determine the transparency level of the elements and fadeIn makes the item visible again and sets the opacity to 1. All three methods enable you to define a fixed speed (slow, normal, and fast) or a number defining the duration of the animation in milliseconds. Examples:

$('h1').fadeOut(1000);     // dissolve the h1 in 1 second
$('h1').fadeIn(1000);      // h1 reappears in 1 second
$('h1').fadeTo(1000, 0.5); // fade to semi-transparent

animate()

Internally, animate is used for many of the animation methods like show and hide. However, it's also externally available to give you great flexibility in animating your matched elements. With the animate method you can specify a bunch of properties to animate. Consider this example:

$('h1').animate({ 
        opacity: 0.4,
        marginLeft: ‘50px',
        fontSize: ‘50px'
      }, 1500 );


In one smooth animation with a duration of 1.5 seconds, this code takes the h1 element and increases its font size to 50 pixels, sets the opacity to 0.4 to make the element semi-transparent, and changes the left margin to 50 pixels. The first argument of the animate method is an object holding one or more properties you want to animate, each one separated by a comma. Notice how you need to use JavaScript's marginLeft and fontSize, rather than the CSS margin-left and font-size properties. You can only animate properties that take numeric values. That is, you can use properties like margin, fontSize, opacity, and so on, but not properties like color or fontFamily.

Now that you've seen the most important jQuery concepts, from simple selectors to advanced animation options, you can use this knowledge to make the contact form of the Planet Wrox site a little more attractive.

Try It Out: Animating the Contact Form

In this exercise you apply two main animations: one is triggered when the user submits the contact form and slowly slides it up until it disappears. The other animation is used to show and hide the Message Sent label, attracting more attention until it completely disappears.

1. 1 . Start by adding an additional text paragraph below the Message Sent label in the ContactForm .ascx user control in Markup View. This paragraph will be visible after the form has been submitted, and remains visible, even after the Message Sent text has been hidden. Within the paragraph tags add some text that thanks the user for his response. Add id and runat="server" attributes to the paragraph (so you can program against it in Code Behind) and set its Visible property to False. Finally, set the CssClass attribute of the Label control placed before the paragraph to Attention. You should end up with this code:

<asp:Label ID="Message" runat="server" CssClass="Attention" 
               Text="Message Sent" Visible="False" />
<p runat="server" id="MessageSentPara" visible="False">Thank you for your message. 
           We'll get in touch with you if necessary.</p>

2. Wrap the entire table that holds the form controls in a <div> and set its id to TableWrapper. Tables can't be easily resized using slideUp and slideDown, but by wrapping the table in a <div> you can resize that element instead:

<div id="TableWrapper">
<table class="auto-style1" runat="server" id="FormTable">
...
</table>
</div>

3. In previous versions of VS, you would not see IntelliSense for jQuery and other script libraries in user controls. That's because VS doesn't know in which pages or master page the control will be used. Because the script references are added to these pages, the user control doesn't know of their existence. You could work around that by adding a reference to the library in the control and hide it in a server-side comment, or remove the reference when you deploy your site. However, VS 2012 introduces a much cleaner solution. By adding a JavaScript file with the special name of _references.js to your site, VS gives you IntelliSense for all script file references it finds in that file. To set this up, first add a JavaScript file called _references.js to the Scripts folder (right-click the folder and choose Add ⇒ JavaScript file.) Then from the Scriptsfolder in the Solution Explorer, drag jquery-1.7.2.js into the open JavaScript file. VS adds the following code for you:

/// <reference path="jquery-1.7.2.js" />

Save and close the file. From now on, you'll see IntelliSense appear for the jQuery library, no matter where you're adding your jQuery code. Visual Studio looks at the file reference you added to this file and looks for matching files with an intellisense.js extension, which it uses to build up IntelliSense and the documentation tool tips. You can add other references to _references.js as well to light up IntelliSense for other JavaScript libraries. I really like this feature because it gives you IntelliSense everywhere without messy hacks or double script references. You never have to include a reference to this special file in the pages or controls in your site; it serves purely as a development-time feature.

4. Back in the user control ContactForm.ascx, scroll down to the end of the control's markup, and add a <script> element and the following jQuery code that fires when the form is about to be submitted:

<script type="text/javascript">
  $(function() {    
    $('form').bind('submit', function()
    {
      if (Page_IsValid)
      {
        $('#TableWrapper').slideUp(3000);
      }
    }); 
  });
  // Code from step 5 goes here
</script>

5. Right before the closing </script> tag and after the closing curly brace, parenthesis, and semicolon of the jQuery document ready function, add the following bold piece of JavaScript:

  });
  function pageLoad()
  {
    $('.Attention').animate({ width: ‘600px' }, 3000).
               animate({ width: ‘100px' }, 3000).fadeOut('slow');
  }
</script>

The pageLoad method (which is part of the client-side JavaScript made available by ASP.NET AJAX) serves the same purpose as jQuery's document ready, with one exception: it also fires after a partial page update, which is what takes place after you submit the form because of theUpdatePanel in the user control.

6. Switch to Code Behind and add the following line of code to the SendButton_Click method. This code makes the text paragraph visible when the form is submitted and the e-mail message is sent:

VB.NET

 Message.Visible = True
 MessageSentPara.Visible = True
 FormTable.Visible = False
 

C#

 Message.Visible = true;
 MessageSentPara.Visible = true;
 FormTable.Visible = false;

7. Save all your changes and close the user control because you're done with it.

8. Open the Monochrome.css file from its theme folder and add the following CSS declaration to the bottom of the file:

.Attention
{
  border: 4px solid red;
  padding: 10px 0;
  width: 100px;
  margin: auto;
  display: block;
  text-align: center;
}

9. Copy the same declaration to the DarkGrey theme's CSS file.

10. Save your changes and then request the Planet Wrox site in your browser. Choose the Contact Us item (under About) from the Menu or TreeView control, fill in the form, and click Send. Notice how shortly after clicking the button the form slides up slowly until it completely disappears. Figure 11.6 shows the form halfway during the slideUp operation.

11. Once the page is done loading, the Message Sent label and the thank you text appear. Notice how the label first grows in size to span the full content width, then shrinks again and finally disappears completely. Figure 11.7 shows the message while it's being resized. If you don't see this animation appear, press Ctrl+F5 or Ctrl+R to get a fresh copy of the CSS file from the server and then fill in the contact form again.

Figure 11.6

11.6

6

Figure 11.7

11.7

How It Works

A lot of the steps involved in this exercise deal with things you've already seen: adding <div> elements, classes, and CSS declarations. However, there's some jQuery and some Ajax code in this example that's worth examining. First, take a look at the code you added in the jQuery document ready function:

$('form').bind('submit', function()
{
  if (Page_IsValid)
  {
    $('#TableWrapper').slideUp(3000);
  }
});

The first line dynamically binds some code to the form's submit event. This way, the remainder of the code fires when the user clicks the Send button. The check for Page_IsValid is necessary to prevent the form from sliding up if the user made a mistake somewhere. Imagine that a user leaves both phone numbers empty and clicks the Send button. This button then tries to submit the form, causing the form's submit event to fire. The ASP.NET client framework intercepts this event and validates the form, causing an alert box with an error message to appear. But even though the form is invalid, it continues to handle other submit event handlers, including the one your code set up. If you didn't take precautions, the form would slide up, regardless of whether it was valid. This makes it impossible for the user to complete the form. Fortunately, you can check Page_IsValid, which is set to false when the form contains invalid data. Only when Page_IsValid returns true will the slideUp method hide the form. During a three-second period (3,000 milliseconds) the form smoothly slides up until it's no longer visible.

Then the server code runs and sends out the message as you've seen in previous chapters. Once the e-mail is sent, the server code sends back the Message Sent label and the paragraph. The message is then animated through this code, which uses a combination of ASP.NET AJAX and jQuery:

function pageLoad()
{
  $('.Attention').animate({ width: ‘600px' }, 3000).
           animate({ width: ‘100px' }, 3000).fadeOut('slow');
}

Rather than using jQuery's $(function() to fire code when the page loads, this example uses ASP .NET AJAX's pageLoad, and for a very specific reason: this event is fired by the Ajax framework when the page loads the first time, and after every postback, partial or not! This is important, because the Message Sent text is only available after the partial postback caused by the button. Notice that pageLoad also fires on the initial request of Contact.aspx. However, in that case, the Label with the Attention class is not present in the page (because its Visible property has been set to False which results in the control's code not being not sent to the browser) so $('.Attention') results in an empty matched set and no animation takes place.

The code that executes here is relatively straightforward. First, using animate({ width: ‘600px’ }, 3000) the message is animated to have a width of 600 pixels. The animation takes three seconds to complete. Once the three seconds are over, another chained method animates the message back to 100 pixels. Finally, the fadeOut method is used to dissolve the message, after which it completely disappears.

Although some of the code looks quite complex, I hope you agree that with jQuery it's relatively easy to apply some fancy design makeover to your pages. Not every page or form should be abused for these techniques, but when used sparingly, jQuery animations can really add some flavor to your website.

As you saw in the previous sections, jQuery is really powerful. You can use it to find elements in your page, manipulate them through code, change the appearance of elements and create animations. However, jQuery can be used for more than that. The remaining section of this chapter deals with the topic of using jQuery for validation.

jQuery and Validation

Remember the validation controls you used in Chapter 9 to validate the contact form? The validation controls work by generating JavaScript that is added to the page. The downside of that approach is that your page becomes unnecessarily large because a lot of repetitive code is added to each page that uses these controls. The developers of ASP.NET have thought of this too and decided to leverage the power of jQuery to improve client-side validation. They have done this through a concept known as unobtrusive JavaScript, where the functionality (the code that gets executed) has been separated from the structure and content of the page. Rather than embedding large chunks of JavaScript code in the page, they have written a small JavaScript library that uses jQuery under the hood to perform the validation. This leads to cleaner code and reduces the size of the page. For the Contact Us page, enabling unobtrusive JavaScript validation decreased the size of the final HTML from 20.7 KB to 14.9 KB, a reduction of more than 25 percent.

Configuring the validation framework to use unobtrusive validation with jQuery instead of the built-in code that is generated is a two-step activity:

1. Enable unobtrusive validation in the Web.config file.

2. Register the jQuery library with the ScriptManager in the Global.asax file.

The Global.asax file is a special ASP.NET file that you add to the root of the site. Inside this file you can write code that responds to global events that happen within your application. These events work the same as other events you've seen so far, such as the Button's Click event. The biggest difference is that these events fire for the entire application (your website) and not for a single control or page. For example, when your ASP.NET application starts up, the Application_Start event is fired, enabling you to execute your own code. Other events that fire include BeginRequest, which fires for each request to the site and Application_Error, which fires when an unhandled exception in your site occurs. You make use of this last event in Chapter 18, which deals with debugging and exception handling.

In the next exercise you see how to add the Global.asax file to your site and then enable unobtrusive JavaScript validation.

Try It Out: Enabling Unobtrusive JavaScript Validation

In this exercise you revisit the current Contact Us page to look at the code that the controls generate. You'll then add a Global.asax file and enable unobtrusive JavaScript validation so you can see the effect this has on the code that is generated.

1. Start by opening the Contact.aspx file from the About folder and then press Ctrl+F5 to view that page in your browser.

2. View the HTML for the page in the browser by right-clicking the page and choosing View Source or View Page Source.

3. Locate the input field for the user's name and then look at the code for the validator that is placed directly below it. You should see something like this:

<span id="cpMainContent_ContactForm_RequiredFieldValidator1" 
           class="ErrorMessage" style="visibility:hidden;">*</span>

4. Scroll down to the end of the code until you see the large chunk of JavaScript code that is responsible for the validation. For the Name field, you'll see something like this:

var cpMainContent_ContactForm_RequiredFieldValidator1 = document.all ? 
   document.all["cpMainContent_ContactForm_RequiredFieldValidator1"] : 
   document.getElementById(
    "cpMainContent_ContactForm_RequiredFieldValidator1");
cpMainContent_ContactForm_RequiredFieldValidator1.controltovalidate 
    = "cpMainContent_ContactForm_Name";
cpMainContent_ContactForm_RequiredFieldValidator1.errormessage 
    = "Enter your name";
cpMainContent_ContactForm_RequiredFieldValidator1.evaluationfunction 
    = "RequiredFieldValidatorEvaluateIsValid";
cpMainContent_ContactForm_RequiredFieldValidator1.initialvalue = "";

For each of the validation controls you see similar code, all adding to the size of the page.

5. Go back to VS, right-click the website in the Solution Explorer, and choose Add ⇒ Add New Item. Locate the Global Application Class item. You don't have to enter a name because the default of Global.asax is the only allowed name for this file.

6. Add the following code to the Application_Start method that is already part of the code template of the Global.asax file:

VB
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
  ScriptManager.ScriptResourceMapping.AddDefinition("jquery",
      New ScriptResourceDefinition With
        { .Path = "∼/Scripts/jquery-1.7.2.min.js" })
End Sub
 

C#

void Application_Start(object sender, EventArgs e) 
{
  ScriptManager.ScriptResourceMapping.AddDefinition("jquery",
      new ScriptResourceDefinition
      {
        Path = "∼/Scripts/jquery-1.7.2.min.js"
      }
  );
}

The spelling of the word jquery (all lowercase) is case sensitive, so make sure you type it exactly as shown here. If you have a newer version of the jQuery library, don't forget to update the version number.

7. Save your changes and close the file.

8. Next, open up the Web.config file and modify the following line of code in the <appSettings> element. You added that line in Chapter 9. If you don't have this line of code, add it between the <appSettings> tags. Either way, you should end up with this code:

<appSettings>
  ...
  <add key="ValidationSettings:UnobtrusiveValidationMode" value="WebForms" />
</appSettings>

9. Open up the master page and change the reference to the jQuery library so it points to the ScriptResourceDefinition you created in the Global.asax file like this:

<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true">
  <Scripts>
    <asp:ScriptReference Name="jquery" />
  </Scripts>
</asp:ScriptManager>

10. If you didn't make this change, jQuery would be included twice on pages that use the validation controls; once from the code in Global.asax, and once from the reference in the ScriptManager control. By having the ScriptReference point to the ScriptResourceDefinition defined inGlobal.asax, ASP.NET sees that it's pointing to the same JavaScript library and includes the reference only once.

Save your changes and then request Contact.aspx in your browser. Click the Send button and notice that validation still works. Open up the HTML for the page and locate the input field for the name again. Below that field you should see the following code for the validator:

<span data-val-controltovalidate="cpMainContent_ContactForm_Name" 
    data-val-errormessage="Enter your name" 
    id="cpMainContent_ContactForm_RequiredFieldValidator1" 
    class="ErrorMessage" data-val="true" 
    data-val-evaluationfunction="RequiredFieldValidatorEvaluateIsValid" 
    data-val-initialvalue="" style="visibility:hidden;">*</span>

11. Scroll down to the end of the code. Notice all the JavaScript you saw previously has now gone. Instead, at the top of the file you now find a <script> element that points to a JavaScript file (one of the links that start with /ScriptResource.axd) that contains validation code that uses the jQuery library.

How It Works

By enabling unobtrusive JavaScript validation, the validation controls generate different code. Rather than emitting JavaScript code that carries out the validation, the controls now emit HTML5 data attributes on the validation <span>. The HTML5 specification enables you to make up your own attributes on elements as long as you prefix them with data-. The unobtrusive validation framework makes use of this feature by adding attributes for things like the error message (in data-val-error-message), and the JavaScript function that needs to be executed to validate the input control (in data-val-evaluationfunction). When you click the submit button, the validation framework kicks in, finds all controls that need to be validated, and then uses the data- attributes to determine what needs to be validated and how. Note that other than the validation controls and the JavaScript they generated previously, not much has changed. Your page still contains the same input controls and submit button. But the way validation takes place has changed radically, and now uses the jQuery library and the data-attributes added to the HTML elements.

To enable unobtrusive validation you have to enable a key in Web.config that you previously disabled. This key signals the validation framework to switch modes and emit unobtrusive JavaScript code instead. Because the validation relies on jQuery, you also need to register the jQuery library with the ScriptManager. Unfortunately, you cannot register the library with the ScriptManager control; you have to do this in the Global.asax with this code:

VB

Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
  ScriptManager.ScriptResourceMapping.AddDefinition("jquery",
      New ScriptResourceDefinition With
      { .Path = "∼/scripts/jquery-1.7.2.min.js" })
End Sub

C#

void Application_Start(object sender, EventArgs e) 
{
  ScriptManager.ScriptResourceMapping.AddDefinition("jquery", 
    new ScriptResourceDefinition 
    {
      Path = "∼/scripts/jquery-1.7.2.min.js"      
    }
  );
}

This code uses an object initializer to create a new instance of the ScriptResourceDefinition class. It sets its Path property to the path of the jQuery library. This instance is then added to the ScriptManager's ScriptResourceMapping using the AddDefinition method. Finally, by pointing theScriptManager control in the master page to this ScriptResourceDefinition, jQuery is included on all pages in your site. Although this looks a bit funky, the outcome is pretty straightforward: a link to the referenced jQuery library is added to the output of the page so the validation framework can use it.

Once you've set this up, you never have to worry about it; you can add validation controls to your page as you did before and jQuery and the validation framework of ASP.NET will handle all validation for you. Note that this change does not impact server-side validation at all; that will continue to function as before.

If by now you think that jQuery really rocks, I completely agree. Although it may be a bit difficult to get used to jQuery in the beginning, once you get the hang of it you'll wonder how you ever did without it. And what's even cooler is that you're not limited to what the jQuery library supports out of the box. jQuery has a pluggable architecture, which means you can write plug-ins for it that extend or enhance jQuery's functionality. At the time of writing, the official jQuery plug-in site was taken offline while they were working on a new site. However, searching the web for “jQuery plug-ins” should bring up many useful plug-ins for all kinds of purposes, ranging from image galleries, validation frameworks, visual tooltips, dialog boxes, and more. You're also encouraged to look at jQuery UI, a collection of widgets such as tabs, dialog boxes, calendars, draggable content, and more. You can find the jQuery UI project at http://jQueryUI.com. If you like jQuery UI, you should also check out Juice UI (at http://juiceui.com). Juice UI is an open source collection of ASP.NET controls that render jQuery UI elements in the browser. This way, you get the best of both worlds: a rich and programmable framework at the server and lean and clean client-side HTML that leverages jQuery and jQuery UI.

Up until now, you've been working on fairly static web pages. Although jQuery enables you to create dynamically changing pages at the client, the content that's available on the website is still static. To fix that, you can use a database, the topic of the next four chapters. In the next chapter you get a thorough introduction to databases, and the chapters that follow give you in-depth information on working with data in an ASP.NET environment.

Practical Tips on jQuery

To get the most out of jQuery, follow these short tips:

· Experiment and experiment. At first, jQuery is a bit of an odd technique to master, mostly because of all its curly braces and parentheses. However, by practicing a lot you can become a jQuery master in no time.

· Visit the jQuery.com website. Besides very good documentation with many examples showing off jQuery's capabilities, you also find a wealth of articles and links on using jQuery, including links to sites that feature video content.

· Invest some time in browsing the jQuery UI and Juice UI websites. You may not need what they offer right now, or you may feel you're not ready to take that next step yet, but it's good to know what these products have to offer when you're building your next website with a rich client interface.

Summary

In this chapter you were introduced to jQuery, a very popular, open source, client-side JavaScript framework for interacting with the document object model.

The chapter started off by showing you where to get jQuery and how to add it to your site. You then got a quick example of jQuery, which was followed by an introduction to jQuery selectors and filters that enable you to find relevant elements in your page.

The second part of this chapter was devoted to the numerous methods that jQuery supports to apply effects and animations to your matched sets. You saw how to use methods like css to manipulate CSS settings, parent and prev to navigate through the items in your set, and how to work with events to fire code in response to some action like the click of a button or when a form is submitted.

Near the end of the chapter you learned how to use the many animation methods in jQuery to give your page a more compelling and interactive appearance, and you saw how to leverage the power of jQuery in the ASP.NET validation framework.

Exercises

1. Imagine that you want to offer your users the possibility of hiding a certain region of a page. For example, you could offer them a link to hide or show the large banner in the Sidebar element with the click of a button. What jQuery does this require? Bonus points if you can find a way to change the text that triggers the code from Hide to Show and vice versa.

2. What's the difference between slideUp and slideDown? What important argument do both methods accept?

3. What's the difference between jQuery's document ready function, defined with $(function()...), and the ASP.NET AJAX pageLoad method? How can you make good use of this difference?

4. What's the purpose of the _references.js file in the Scripts folder?

You can find answers to these exercises in Appendix A.

What You Learned in this Chapter

_references.js

The special JavaScript file in the Scripts folder that triggers IntelliSense for all JavaScript files it references

Chaining

The concept where the result of one method is used as the input of another to create a chain of effects

Filters

Enable you to further refine your jQuery matched set of elements

Global.asax

A central file that is used to handle various application-scoped events such as Application_Start, Application_Error, and more

jQuery

A popular client-side JavaScript framework that simplifies working with the DOM, visual effects, event handling, and Ajax functionality

Matched set

The set of elements that are returned by a jQuery selector

NuGet

The Library Package Manager for Visual Studio to help you manage third-party libraries in your .NET websites and projects

Selectors

A CSS-like syntax to find elements in your page using jQuery