Home | Projects | Tutorials | Articles | live chat | Submit Project | Big Vote
 
Ajax Projects
.NET Frameworks
Java Frameworks
PHP Frameworks
Ruby Frameworks
Other Frameworks
Cool AJAX sites
Ajax Resources
Ajax Tools
JavaScript frameworks
Partners

 Home /  Tutorials / Create a Popup Calendar Helper

Create a Popup Calendar Helper





This is great news for ASP.NET MVC developers. It means that we can easily take advantage of the client-side AJAX behaviors contained in the AJAX Control Toolkit in our MVC views.

Read The Full Tutorial.
































This is great news for ASP.NET MVC developers. It means that we can easily take advantage of the client-side AJAX behaviors contained in the AJAX Control Toolkit in our MVC views. For example, we can create auto-complete input fields, modal dialog boxes, and rich animations. In this tip, I demonstrate how you can add a popup calendar to an HTML form input field which you can use as a fancy date picker (see Figure 1).

Figure 1 – Using the AJAX Calendar Behavior

I am a big fan of the AJAX Calendar behavior. It supports fancy animations. For example, when you click on the name of the month, a menu of months scrolls into view.

In this tip, I explore two methods of using the AJAX Calendar behavior. First, I explain how you can use the Calendar behavior by including a set of JavaScript, CSS, and image files in your view. Next, I explain how you can create a HTML Helper that adds all of the required files automatically.
Adding the Calendar Behavior to a View by Hand

Adding any of the behaviors from the AJAX Control Toolkit to a view by hand takes some work. The problem is that you must include several JavaScript libraries, in the right order, to use the behavior. In this section, I walk through the process of adding the Calendar behavior to a view. In the next section, I demonstrate how you can avoid this work.

Step 1 – Add the AJAX Control Toolkit Folder to Your Application

Download the client file only version of the AJAX Control Toolkit from the following location:

    http://www.codeplex.com/AjaxControlToolkit/Release/ProjectReleases.aspx?ReleaseId488

After you unzip the download, copy the AjaxControlToolkit folder into the Content folder in your ASP.NET MVC application.

There are a lot of files in the AjaxControlToolkit folder (the folder is a little over a megabyte in size). However, you’ll need to reference several files in the folder to use the Calendar behavior. Because, most likely, you’ll end up using several AJAX behaviors, I recommend just dumping the whole folder into your MVC application.

After you add the folder, your Solution Explorer window should resemble Figure 2.

Figure 2 – ASP.NET MVC Application with AJAX Control Toolkit files

Step 2 – Include the Required Files in Your View

This is the most time-consuming step. You must add all of the JavaScript and CSS files required by the Calendar behavior to the view in which you want to use the behavior (alternatively, you can include these files in a master page).

In order to use the Calendar behavior, you need to include all of the JavaScript files, and the single CSS file, in Listing 1.

Listing 1 – \Views\Home\Index.aspx

   1. <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="Tip36.Views.Home.Index" %> 
   2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
   3. <html xmlns="http://www.w3.org/1999/xhtml" > 
   4. <head runat="server"> 
   5.     <title>Index</title> 
   6.      
   7.     <link href="../../Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/AjaxControlToolkit.Calendar.Calendar.css" 
   8.         rel="stylesheet" type="text/css" /> 
   9.     <script src="../../Content/MicrosoftAjax.debug.js" type="text/javascript"></script> 
  10.  
  11.     <script src="../../Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/AjaxControlToolkit.ExtenderBase.BaseScripts.js" 
  12.         type="text/javascript"></script> 
  13.     <script src="../../Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/AjaxControlToolkit.Common.Common.js" 
  14.         type="text/javascript"></script> 
  15.     <script src="../../Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/AjaxControlToolkit.Common.DateTime.js" 
  16.         type="text/javascript"></script> 
  17.     <script src="../../Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/AjaxControlToolkit.Animation.Animations.js" 
  18.         type="text/javascript"></script> 
  19.     <script src="../../Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/AjaxControlToolkit.PopupExtender.PopupBehavior.js" 
  20.         type="text/javascript"></script> 
  21.     <script src="../../Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/AjaxControlToolkit.Animation.AnimationBehavior.js" 
  22.         type="text/javascript"></script> 
  23.     <script src="../../Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/AjaxControlToolkit.Common.Threading.js" 
  24.         type="text/javascript"></script> 
  25.     <script src="../../Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/AjaxControlToolkit.Compat.Timer.Timer.js" 
  26.         type="text/javascript"></script> 
  27.     <script src="../../Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/AjaxControlToolkit.Calendar.CalendarBehavior.js" 
  28.         type="text/javascript"></script>     
  29.     <script type="text/javascript"> 
  30.  
  31.         Sys.Application.add_init(appInit); 
  32.  
  33.         function appInit()  
  34.         { 
  35.             $create(AjaxControlToolkit.CalendarBehavior, null, null, null, $get('birthDate')); 
  36.         }    
  37.      
  38.     </script>     
  39. </head> 
  40. <body> 
  41.     <div> 
  42.      
  43.     <form method="post" action="/Home/Insert"> 
  44.      
  45.     <label for="birthDate">Birth Date:</label> 
  46.     <br /> 
  47.     <input id="birthDate" name="birthDate" /> 
  48.      
  49.     <br /><br /> 
  50.      
  51.     <input type="submit" value="Add" /> 
  52.      
  53.     </form> 
  54.     </div> 
  55. </body> 
  56. </html> 

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="Tip36.Views.Home.Index" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Index</title>
   
    <link href="../../Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/AjaxControlToolkit.Calendar.Calendar.css"
        rel="stylesheet" type="text/css" />
    <script src="../../Content/MicrosoftAjax.debug.js" type="text/javascript"></script>

    <script src="../../Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/AjaxControlToolkit.ExtenderBase.BaseScripts.js"
        type="text/javascript"></script>
    <script src="../../Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/AjaxControlToolkit.Common.Common.js"
        type="text/javascript"></script>
    <script src="../../Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/AjaxControlToolkit.Common.DateTime.js"
        type="text/javascript"></script>
    <script src="../../Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/AjaxControlToolkit.Animation.Animations.js"
        type="text/javascript"></script>
    <script src="../../Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/AjaxControlToolkit.PopupExtender.PopupBehavior.js"
        type="text/javascript"></script>
    <script src="../../Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/AjaxControlToolkit.Animation.AnimationBehavior.js"
        type="text/javascript"></script>
    <script src="../../Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/AjaxControlToolkit.Common.Threading.js"
        type="text/javascript"></script>
    <script src="../../Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/AjaxControlToolkit.Compat.Timer.Timer.js"
        type="text/javascript"></script>
    <script src="../../Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/AjaxControlToolkit.Calendar.CalendarBehavior.js"
        type="text/javascript"></script>   
    <script type="text/javascript">

        Sys.Application.add_init(appInit);

        function appInit()
        {
            $create(AjaxControlToolkit.CalendarBehavior, null, null, null, $get('birthDate'));
        }  
   
    </script>   
</head>
<body>
    <div>
   
    <form method="post" action="/Home/Insert">
   
    <label for="birthDate">Birth Date:</label>
    <br />
    <input id="birthDate" name="birthDate" />
   
    <br /><br />
   
    <input type="submit" value="Add" />
   
    </form>
    </div>
</body>
</html>

You must add the JavaScript files in the right order. One JavaScript file might depend on functionality defined in another JavaScript file.

Step 3 – Create the Behavior

The final step is to create the Calendar behavior and associate it with an input field. Notice that the view in Listing 1 contains the following script:

   1. <script type="text/javascript"> 
   2.  
   3.     Sys.Application.add_init(appInit); 
   4.  
   5.     function appInit()  
   6.     { 
   7.         $create(AjaxControlToolkit.CalendarBehavior, null, null, null, $get('birthDate')); 
   8.     }    
   9.  
  10. </script>     

    <script type="text/javascript">

        Sys.Application.add_init(appInit);

        function appInit()
        {
            $create(AjaxControlToolkit.CalendarBehavior, null, null, null, $get('birthDate'));
        }  
   
    </script>   

You create client-side AJAX controls and behaviors during the client-side Application init event. This script registers an event handler for this event that calls the $create() method to create the Calendar behavior.

The $create() method accepts the following parameters:

    · type – The type of client-side component, control, or behavior to create

    · properties – A JavaScript object literal that represents a set of property names and values

    · events – A JavaScript object literal that represents a set of event names and handlers

    · references – A JavaScript object literal that represents a set of property names and references to other components

    · element – The DOM element to which the client-side component, control, or behavior is attached

In Listing 1, the Calendar behavior is attached to the birthDate input field contained in the HTML form located in the body of the view.

After you complete this step, the Calendar behavior works in the view. When you click in the birth date field (or tab to the field) the calendar appears.
Adding the Calendar Behavior to a View with an HTML Helper

In the previous section, we added the Calendar behavior to a view by hand. The hardest part of the process was adding all of the files required by the Calendar. In this section, we create an HTML Helper that adds all of the required files automatically.

We will need to create a couple of helper classes before we can create our Calendar class. The first class that we need to make is something called the ResourceTracker class. This class is contained in Listing 2.

Listing 2 – ResourceTracker.cs

   1. using System; 
   2. using System.Collections.Generic; 
   3. using System.Linq; 
   4. using System.Text; 
   5. using System.Web; 
   6.  
   7. namespace AjaxControlToolkitMvc 
   8. { 
   9.     public class ResourceTracker 
  10.     { 
  11.         const string resourceKey = "__resources"; 
  12.  
  13.         private List<string> _resources; 
  14.  
  15.         public ResourceTracker(HttpContextBase context) 
  16.         { 
  17.             _resources = (List<string>)context.Items[resourceKey]; 
  18.             if (_resources == null) 
  19.             { 
  20.                 _resources = new List<string>(); 
  21.                 context.Items[resourceKey] = _resources; 
  22.             } 
  23.         } 
  24.  
  25.         public void Add(string url) 
  26.         { 
  27.             url = url.ToLower(); 
  28.             _resources.Add(url); 
  29.         } 
  30.  
  31.         public bool Contains(string url) 
  32.         { 
  33.             url = url.ToLower(); 
  34.             return _resources.Contains(url); 
  35.         } 
  36.      
  37.     } 
  38. } 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;

namespace AjaxControlToolkitMvc
{
    public class ResourceTracker
    {
        const string resourceKey = "__resources";

        private List<string> _resources;

        public ResourceTracker(HttpContextBase context)
        {
            _resources = (List<string>)context.Items[resourceKey];
            if (_resources == null)
            {
                _resources = new List<string>();
                context.Items[resourceKey] = _resources;
            }
        }

        public void Add(string url)
        {
            url = url.ToLower();
            _resources.Add(url);
        }

        public bool Contains(string url)
        {
            url = url.ToLower();
            return _resources.Contains(url);
        }
   
    }
}

The reason that we need the ResourceTracker class is to prevent us from adding the same script or CSS file to a page more than once. Imagine that you need two Calendar input fields (for example, a start and end date). In that case, you do not want to add all of the necessary JavaScript files twice because adding all of these files would slow down your page. The ResourceTracker verifies whether or not a resource with a certain URL has already been added.

The ResourceTracker uses the HttpContext.Items collection. This collection survives a single browser request. This is what we want. We don’t want to include a JavaScript file more than once within a single browser request for a single user.

The class in Listing 3 adds a single utility method for adding JavaScript file includes.

Listing 3 – ScriptExtensions.cs

   1. using System.Text; 
   2. using System.Web.Mvc; 
   3.  
   4. namespace AjaxControlToolkitMvc 
   5. { 
   6.     public static class ScriptExtensions 
   7.     { 
   8.         public static string ScriptInclude(this AjaxHelper helper, params string[] url) 
   9.         { 
  10.             var tracker = new ResourceTracker(helper.ViewContext.HttpContext); 
  11.  
  12.             var sb = new StringBuilder(); 
  13.             foreach (var item in url) 
  14.             { 
  15.                 if (!tracker.Contains(item)) 
  16.                 { 
  17.                     tracker.Add(item); 
  18.                     sb.AppendFormat("<script type='text/javascript' src='{0}'></script>", item); 
  19.                     sb.AppendLine(); 
  20.                 } 
  21.             } 
  22.             return sb.ToString(); 
  23.         } 
  24.  
  25.     } 
  26. } 

using System.Text;
using System.Web.Mvc;

namespace AjaxControlToolkitMvc
{
    public static class ScriptExtensions
    {
        public static string ScriptInclude(this AjaxHelper helper, params string[] url)
        {
            var tracker = new ResourceTracker(helper.ViewContext.HttpContext);

            var sb = new StringBuilder();
            foreach (var item in url)
            {
                if (!tracker.Contains(item))
                {
                    tracker.Add(item);
                    sb.AppendFormat("<script type='text/javascript' src='{0}'></script>", item);
                    sb.AppendLine();
                }
            }
            return sb.ToString();
        }

    }
}

Notice that the class in Listing 3 takes advantage of the ResourceTracker class. Imagine that you call the ScriptInclude() helper method multiple times in a page like this:

    <%= Ajax.ScriptInclude(“/scripts/myLibrary.js”) %>

    <%= Ajax.ScriptInclude(“/scripts/myLibrary.js”) %>

    <%= Ajax.ScriptInclude(“/scripts/myLibrary.js”) %>

In that case, the myLibrary.js file will be included in the page only once. The ResourceTracker prevents the script from being included multiple times.

Next, we need to create a utility class for generating URLs to the Microsoft Ajax Library and the Ajax Control Toolkit files. This class is contained in Listing 4.

Listing 4 – AjaxExtensions.cs

   1. using System; 
   2. using System.Text; 
   3. using System.Web.Mvc; 
   4.  
   5. namespace AjaxControlToolkitMvc 
   6. { 
   7.     public static class AjaxExtensions 
   8.     { 
   9.         private static string _microsoftAjaxLibraryUrl = "/Content/MicrosoftAjax.js"; 
  10.         private static string _toolkitFolderUrl = "/Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/"; 
  11.  
  12.         public static void SetMicrosoftAjaxLibraryUrl(this AjaxHelper helper, string url) 
  13.         { 
  14.             _microsoftAjaxLibraryUrl = url; 
  15.         } 
  16.  
  17.         public static string GetMicrosoftAjaxLibraryUrl(this AjaxHelper helper) 
  18.         { 
  19.             return _microsoftAjaxLibraryUrl; 
  20.         } 
  21.  
  22.  
  23.         public static void SetToolkitFolderUrl(this AjaxHelper helper, string url) 
  24.         { 
  25.             _toolkitFolderUrl = url; 
  26.         } 
  27.  
  28.         public static string GetToolkitFolderUrl(this AjaxHelper helper) 
  29.         { 
  30.             return _toolkitFolderUrl; 
  31.         } 
  32.  
  33.         public static string MicrosoftAjaxLibraryInclude(this AjaxHelper helper) 
  34.         { 
  35.             return ScriptExtensions.ScriptInclude(helper, _microsoftAjaxLibraryUrl); 
  36.         } 
  37.  
  38.         public static string ToolkitInclude(this AjaxHelper helper, params string[] fileName) 
  39.         { 
  40.             var sb = new StringBuilder(); 
  41.             foreach (string item in fileName) 
  42.             { 
  43.                 var fullUrl = _toolkitFolderUrl + item; 
  44.                 sb.AppendLine( ScriptExtensions.ScriptInclude(helper, fullUrl)); 
  45.             } 
  46.             return sb.ToString(); 
  47.         } 
  48.  
  49.  
  50.         public static string DynamicToolkitCssInclude(this AjaxHelper helper, string fileName) 
  51.         { 
  52.             var fullUrl = _toolkitFolderUrl + fileName; 
  53.             return helper.DynamicCssInclude(fullUrl); 
  54.         } 
  55.              
  56.         public static string DynamicCssInclude(this AjaxHelper helper, string url) 
  57.         { 
  58.             var tracker = new ResourceTracker(helper.ViewContext.HttpContext); 
  59.             if (tracker.Contains(url)) 
  60.                 return String.Empty; 
  61.  
  62.             var sb = new StringBuilder(); 
  63.             sb.AppendLine("<script type='text/javascript'>"); 
  64.             sb.AppendLine("var link=document.createElement('link')"); 
  65.             sb.AppendLine("link.setAttribute('rel', 'stylesheet');"); 
  66.             sb.AppendLine("link.setAttribute('type', 'text/css');"); 
  67.             sb.AppendFormat("link.setAttribute('href', '{0}');", url); 
  68.             sb.AppendLine(); 
  69.             sb.AppendLine("var head = document.getElementsByTagName('head')[0];"); 
  70.             sb.AppendLine("head.appendChild(link);"); 
  71.             sb.AppendLine("</script>"); 
  72.             return sb.ToString(); 
  73.         } 
  74.  
  75.  
  76.         public static string Create(this AjaxHelper helper, string clientType, string elementId) 
  77.         { 
  78.             var sb = new StringBuilder(); 
  79.             sb.AppendLine("<script type='text/javascript'>"); 
  80.             sb.AppendLine("Sys.Application.add_init(function(){"); 
  81.             sb.AppendFormat("$create({0},null,null,null,$get('{1}'))", clientType, elementId); 
  82.             sb.AppendLine("});"); 
  83.             sb.AppendLine("</script>"); 
  84.             return sb.ToString(); 
  85.         } 
  86.  
  87.     } 
  88. } 

using System;
using System.Text;
using System.Web.Mvc;

namespace AjaxControlToolkitMvc
{
    public static class AjaxExtensions
    {
        private static string _microsoftAjaxLibraryUrl = "/Content/MicrosoftAjax.js";
        private static string _toolkitFolderUrl = "/Content/AjaxControlToolkit/3.0.20820.16598/3.0.20820.0/";

        public static void SetMicrosoftAjaxLibraryUrl(this AjaxHelper helper, string url)
        {
            _microsoftAjaxLibraryUrl = url;
        }

        public static string GetMicrosoftAjaxLibraryUrl(this AjaxHelper helper)
        {
            return _microsoftAjaxLibraryUrl;
        }


        public static void SetToolkitFolderUrl(this AjaxHelper helper, string url)
        {
            _toolkitFolderUrl = url;
        }

        public static string GetToolkitFolderUrl(this AjaxHelper helper)
        {
            return _toolkitFolderUrl;
        }

        public static string MicrosoftAjaxLibraryInclude(this AjaxHelper helper)
        {
            return ScriptExtensions.ScriptInclude(helper, _microsoftAjaxLibraryUrl);
        }

        public static string ToolkitInclude(this AjaxHelper helper, params string[] fileName)
        {
            var sb = new StringBuilder();
            foreach (string item in fileName)
            {
                var fullUrl = _toolkitFolderUrl + item;
                sb.AppendLine( ScriptExtensions.ScriptInclude(helper, fullUrl));
            }
            return sb.ToString();
        }


        public static string DynamicToolkitCssInclude(this AjaxHelper helper, string fileName)
        {
            var fullUrl = _toolkitFolderUrl + fileName;
            return helper.DynamicCssInclude(fullUrl);
        }
     %

Says:
Thu Apr 09, 2009 9:59 am
neon tabela Says:
Sun Nov 01, 2009 9:16 pm
Your site is very good. There are useful information and most importantly, for sharing great. Thank you ajax..
web tasarım Says:
Fri Dec 18, 2009 3:46 pm
thanks
Narsa Says:
Mon Dec 28, 2009 6:13 am
Hi,

Great example!

I have one problem though. When running my app in debug mode everything is working fine. After deploying my app I get a "Sys is not defined" error though.

Any ideas?

Leave Your Comment

Name (Required)
Mail (will not be published) (required)
Website
AddThis Social Bookmark Button
Top Projects
MSN Web Messenger
MessengerFX
ebuddy
e-messenger
ILoveIM
AJAX file upload
You Tube
KoolIM.com
Meebo
Ajax.NET Professional
Tutorials
AJAX Design Patterns
Very Dynamic Web Interfaces
CakePHP and Events with AJAX and MySQL (Part 1)
ASP.NET MVC and JSON
ASP.NET Ajax MVC Preview
File Upload with AJAX.NET Progress Bar
CSSHttpRequest: cross-domain Ajax using CSS for transport
jQuery AJAX Form Submit for Dummies
Improving jQuery’s JSON performance and security
Faking an AJAX upload script