Your partner in IT success

A specialized company in providing high quality consultancy on analysis, architecture and development projects

 
22
Apr

A contribution to SquishIt

I’m using SquishIt, a friendly ASP.NET JavaScript and CSS squisher, on different projects (on this web site too). I love the library: it’s so easy to use, thanks to the fluent API, and the results are great. CSS and JavaScript files are combined and minified in one file at runtime.

The only drawbacks I could mention is that SquishIt is not perfectly integrated with ASP.NET MVC. I recently decided to contribute to the library and to publish a NuGet package to propose a better integration with MVC projects.

To use it, it’s quite simple, just install SquishIt.Contrib.Mvc with the package manager or by adding a library package reference inside Visual Studio. Then, edit the web.config file located under the Views directory. Locate the system.web.webPages.razor section and modify the pageBaseType attribute to SquishIt.Contrib.Mvc.SquishItBasePage.

Now, inside the layout and the views, you have access to a new helper: SquishIt. Use it to add the CSS and the JavaScript you’ll like to include in your web site. See this example:

_Layout.cshtml

@{
    SquishIt.Css.Add("~/Content/Site.css");
    SquishIt.JavaScript.Add("~/Scripts/jquery-1.4.4.min.js");
}
<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
 
    @SquishIt.Css.Render("~/Content/Site.min.css")
</head>
 
<body>
    @RenderBody()
 
    @SquishIt.JavaScript.Render("~/Scripts/Site.min.js")
</body>
</html>

Index.cshtml

@{
    SquishIt.Css.Add("~/Content/Home.css");
    SquishIt.JavaScript.Add("~/Scripts/jquery-ui.js");
    
    ViewBag.Title = "Index";
}
 
<h2>Index</h2>

And voila, a nice integration of SquishIt with ASP.NET MVC!

Don’t wait a minute, and give a try to SquishIt.Contrib.Mvc. I’ll read your comment with pleasure!

Posted by Fabian Vilers, Consulting Principal
19
Apr
.NET / Ajax / ASP.NET / C# / Web

How to submit a form when the user hits enter in a TextBox?

I’ve been recently confronted to this functionality to be implemented. On our web site, we have a search panel with a text box and a button that triggers the search action. It was boring for our users to have to type in keywords, then grab the mouse and then click on the search button.

This functionality can be implemented in various way. One of them is to have a small JavaScript snippet that listen for the onkeypress event on the text box and simulate the click on the button when the enter key is pressed. It’s a nice trick, but far from being reusable in this form. We could embed this JavaScript “logic” inside a CustomTextBox derived from the TextBox class but I don’t like this solution. We are adding a custom behavior to a control which responsibility is to handle text, and not to submit forms.

As we are using the AjaxControlToolkit, we’ll build an extender. This control will be reusable across project and is fully supported by the framework. This extender will add dynamically the aforementioned JavaScript snippet to the controls for which it is binded.

The extender is built with three files: the extender class, the extender designer, and the extender behavior. Let’s have a look to the extender. It is quite simple and exposes a single property: the target button on which the click should be simulated. The smart use of attributes restricts the use of the extender only on button objects.

using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using AjaxControlToolkit;
 
[assembly: System.Web.UI.WebResource("DevOne.Framework.Web.Controls.AjaxControlToolkit.TextBoxSubmitBehavior.js", "text/javascript")]
 
namespace DevOne.Framework.Web.Controls.AjaxControlToolkit
{
    [Designer(typeof(TextBoxSubmitDesigner))]
    [ClientScriptResource("DevOne.Framework.Web.Controls.AjaxControlToolkit.TextBoxSubmitBehavior", "DevOne.Framework.Web.Controls.AjaxControlToolkit.TextBoxSubmitBehavior.js")]
    [TargetControlType(typeof(TextBox))]
    public class TextBoxSubmitExtender : ExtenderControlBase
    {
        [ExtenderControlProperty]
        [DefaultValue("")]
        [IDReferenceProperty(typeof(Button))]
        public string TargetButtonID
        {
            get
            {
                return GetPropertyValue("TargetButtonID", "");
            }
            set
            {
                SetPropertyValue("TargetButtonID", value);
            }
        }
    }
}

In order to have the extender correctly displayed in the Visual Studio designer, you have to provide a designer class. Again, we’ll take advantage of the AjaxControlToolkit base class that will does all the work of us.

using AjaxControlToolkit.Design;
 
namespace DevOne.Framework.Web.Controls.AjaxControlToolkit
{
    internal class TextBoxSubmitDesigner : ExtenderControlBaseDesigner<TextBoxSubmitExtender>
    {
    }
}

And the most important file, the behavior, is coded in JavaScript. The code complies totally with the Microsoft Ajax Framework. The interesting part is the _onkeypress method, where we read the pressed key, and simulate the click if it is the enter key.

Type.registerNamespace('DevOne.Framework.Web.Controls.AjaxControlToolkit');
 
DevOne.Framework.Web.Controls.AjaxControlToolkit.TextBoxSubmitBehavior = function (element) {
    DevOne.Framework.Web.Controls.AjaxControlToolkit.TextBoxSubmitBehavior.initializeBase(this, [element]);
    this._targetButtonIDValue = null;
}
 
DevOne.Framework.Web.Controls.AjaxControlToolkit.TextBoxSubmitBehavior.prototype = {
    initialize: function () {
        DevOne.Framework.Web.Controls.AjaxControlToolkit.TextBoxSubmitBehavior.callBaseMethod(this, 'initialize');
 
        $addHandler(this.get_element(), 'keypress', Function.createDelegate(this, this._onkeypress));
    },
 
    dispose: function () {
        DevOne.Framework.Web.Controls.AjaxControlToolkit.TextBoxSubmitBehavior.callBaseMethod(this, 'dispose');
    },
 
    get_TargetButtonID: function () {
        return this._targetButtonIDValue;
    },
 
    set_TargetButtonID: function (value) {
        this._targetButtonIDValue = value;
    },
 
    _onkeypress: function (event) {
        var key = event.keyCode ? event.keyCode : event.rawEvent.keyCode;
 
        if (key === Sys.UI.Key.enter) {
            var button = $get(this._targetButtonIDValue);
 
            if (button.click) {
                button.click();
            }
            else if (document.createEvent) {
                var evt = document.createEvent("MouseEvents");
                evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
                var wasCanceled = !button.dispatchEvent(evt);
            }
        }
    }
}
 
DevOne.Framework.Web.Controls.AjaxControlToolkit.TextBoxSubmitBehavior.registerClass('DevOne.Framework.Web.Controls.AjaxControlToolkit.TextBoxSubmitBehavior', Sys.Extended.UI.BehaviorBase);

Okay, so we have our text box extender. Let’s build the project, reference it and update the web.config’s control section.

<pages>
  <controls>
    <add tagPrefix="ajaxToolkit" assembly="AjaxControlToolkit" namespace="AjaxControlToolkit" />
    <add tagPrefix="devone" assembly="DevOne.Framework.Web" namespace="DevOne.Framework.Web.Controls.AjaxControlToolkit" />
  </controls>
</pages>

You’re now ready to use the extender! Here’s a example:

<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
 
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" />
 
<devone:TextBoxSubmitExtender ID="TextBoxSubmitExtender1" runat="server" TargetControlID="TextBox1" TargetButtonID="Button1"></devone:TextBoxSubmitExtender>

Enjoy!

Posted by Fabian Vilers, Consulting Principal