Posts Tagged how-to

jQuery UI Selectable With ASP.NET

While playing with jQuery UI library I have found great way to utilize jQuery UI Selectable plugin with ASP.NET. It can be used as a replacement for long series of checkboxes. For instance, in my scenario, I had to give authors (it’s a CMS system) ability to create a news and additionally give them an option to select countries relevant for the news. Logic behind it is that later we can easily filter news by country. The most obvious approach is to give authors list of checkboxes or multiselect list. In my opinion both options are not very pleasant to use. Therefore I was looking for some alternative. And here is what I was able to achieve with jQuery Selectable plugin:

 

jQuery Selectable Plugin

Selectable list of countries implemented with jQuery Selectable

Authors have an option to select countries in a few different ways:

The jQuery UI Selectable plugin allows for elements to be selected by dragging a box (sometimes called a lasso) with the mouse over the elements. Also, elements can be selected by click or drag while holding the Ctrl/Meta key, allowing for multiple (non-contiguous) selections.

On top of that it’s very easy to add functional buttons like ‘Select All’ and ‘Deselect All’.

I think that’s it in terms of introduction, now I will show you how to get jQuery UI Selectable plugin integrated with ASP.NET. Also I will show you how to pre-select some elements and how to add select all (and deselect all) functionality.

How to integrate jQuery UI Selectable plugin with ASP.NET

Step 1 – download jQuery UI on your machine. I was using version 1.8.14.

Step 2 – Make sure that your page has all the required JS and CSS files included. jQuery Selectable plugin has a few dependencies. Here is everything you need:

<link href="Styles/ui-lightness/jquery-ui-1.8.14.custom.css" rel="stylesheet" type="text/css" />
<script src="/Scripts/jquery-1.5.1.min.js" type="text/javascript"></script>
<script src="Scripts/ui/jquery.ui.core.js" type="text/javascript"></script>
<script src="Scripts/ui/jquery.ui.widget.js" type="text/javascript"></script>
<script src="Scripts/ui/jquery.ui.mouse.js" type="text/javascript"></script>
<script src="Scripts/ui/jquery.ui.selectable.js" type="text/javascript"></script>

Step 3 – HTML

Our goal is to get HTML like this:

<h3>This is Selectable plugin demo!</h3>
<div>
    <ol id="selectable">
		<li class="ui-widget-content">Argentina</li>
		<li class="ui-widget-content">Australia</li>
		<li class="ui-widget-content">Austria</li>
		<li class="ui-widget-content">Belgium</li>
	</ol>
</div>

But it’s not a good idea to hardcode countries in HTML, ASP.NET should generate the list. So on server side we will replace the HTML list with ASP.NET Repeater control:

<h3>This is Selectable plugin demo!</h3>
<div>
    <asp:Repeater ID="rptCountries" runat="server">
        <HeaderTemplate><ol id="selectable"></HeaderTemplate>
        <ItemTemplate>
            <li class="ui-widget-content">
                    <%# ((Country)Container.DataItem).Name %>
            </li>
        </ItemTemplate>
        <FooterTemplate></ol></FooterTemplate>
    </asp:Repeater>
</div>

You can see that on server side there is a class Country which has all the country related data. So let’s jump to server side where you will find the details.

Step 4 – ASP.NET code

At the moment, server side code looks like this:

public class Country
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public partial class SelectableDemo : System.Web.UI.Page
{
    // list of countries can be much longer
    private IList<Country> countries = new List<Country>() {
                new Country () { Id = 1, Name = "Argentina" },
                new Country () { Id = 2, Name = "Australia" },
                new Country () { Id = 3, Name = "Austria" }
            };

    protected void Page_Load(object sender, EventArgs e)
    {
        rptCountries.DataSource = countries;
        rptCountries.DataBind();
    }
}

One thing worth noticing is that Country class has an Id property which is set for all countries from my example but it’s not used anywhere. It will be required in further steps when we will get the point of saving selected countries.

Step 5 – jQuery code

The final step is to enable jQuery Selectable plugin on our list. This is as simple as this:

$(document).ready(function () {
    $("#selectable").selectable();
});

To find our countries list I’m using jQuery selector $(“#selectable”) which will find all tags with ID selectable.

After completing this step you should get list of countries generated by ASP.NET and jQuery Selectable plugin enabled for the list. So in fact you should be able to already select countries which you like.

But the job is not really finished yet! How are you going to save selected countries? How are you going to pre-select countries saved earlier? How to implement select all or deselect all functionality? This is exactly where the fun begins…

Step 1 – Let’s start with changes in HTML generated by ASP.NET, we need to add a few elements there:

  • button to save selected countries,
  • button to select all countries
  • button to deselect all countries
  • text box where jQuery will list selected countries – this way it will be easy to get it on server side,
  • and a literal to display a message after saving the list – it is not really needed, but it will handy to prove that everything works ;)
  • HTML list has to change as well – there will be a new attribute countryid which is not displayed anywhere but it’s a way to give jQuery information about ID of selected country

Here are the changes:

<h3>This is Selectable plugin demo!</h3>
<div>
    <asp:Repeater ID="rptCountries" runat="server">
        <HeaderTemplate><ol id="selectable"></HeaderTemplate>
        <ItemTemplate>
            <li
                countryid="<%# ((Country)Container.DataItem).Id %>"
                class="ui-widget-content">
                    <%# ((Country)Container.DataItem).Name %>
            </li>
        </ItemTemplate>
        <FooterTemplate></ol></FooterTemplate>
    </asp:Repeater>
<br />
<button id="selectall">Select All</button>
<button id="deselectall">Deselect All</button> <br />
<asp:Button ID="btnSaveChanges" runat="server" Text="Save Changes" onclick="btnSave_Click" /> <br />
<asp:Literal ID="litMessage" runat="server" />
<asp:TextBox ID="txbSelectedCountries" runat="server" CssClass="selectedCountries" />
</div>

Step 2 – Changes in ASP.NET, code behind file:

  • Country class will have an additional property – Selected,
  • Page_Load method has to not only set DataSource for the Repeater, it has to also check which countries are selected and put this information to the text box txbSelectedCountries. jQuery will later parse it and select appropriate countries.
  • method btnSave_Click has to be added – within this method, after clicking on ‘Save Changes’ button, we will get list of all selected countries (from text box txbSelectedCountries) and display relevant information in the literal component (litMessage). It also has to update internal list of countries and mark selected countries as selected.

Here are the changes:

public class Country
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool Selected { get; set; }
}

public partial class SelectableDemo : System.Web.UI.Page
{
    private IList<Country> countries = new List<Country>() {
            new Country () { Id = 1, Name = "Argentina", Selected = true },
            new Country () { Id = 2, Name = "Australia", Selected = false },
            new Country () { Id = 3, Name = "Austria", Selected = false }
        };

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            rptCountries.DataSource = countries;
            rptCountries.DataBind();

            // add selected countries to a textbox
            StringBuilder selectedCountries = new StringBuilder();
            foreach (var country in countries)
            {
                if (country.Selected) selectedCountries.Append(country.Id + ",");
            }

            txbSelectedCountries.Text = selectedCountries.ToString();
        }
    }

    protected void btnSave_Click(object sender, EventArgs e)
    {
        // mark all in-memory countries as Selected = false
        foreach (var country in countries)
        {
            country.Selected = false;
        }

        // selected countries are in format: 1,2,5,6,
        string[] selectedIds = txbSelectedCountries.Text
                        .Substring(0, txbSelectedCountries.Text.Length-1).Split(',');
        StringBuilder output = new StringBuilder();

        foreach (string id in selectedIds)
        {
            var country = (from c in countries where c.Id.ToString().Equals(id) select c)
                        .First<Country>();
            country.Selected = true;
            output.Append(country.Name + "<br/>");
        }

        litMessage.Text = "Saved Countries: <br/>" + output.ToString();
    }
}

IDs of selected countries are stored as a single string, IDs are comma separated, for instance: 1,56,42,2,
Please note that after last ID there is an additional comma.

Step 3 – Changes in jQuery code

This part is the most complex, firstly you need to bind custom function to “selectablestop” event. Custom function will figure out which countries are selected and will update the txbSelectedCountries text box with the IDs:

$(document).ready(function () {
    $("#selectable").selectable();

    $("#selectable").bind("selectablestop", function (event) {
        var result = "";
        $(".ui-selected", this).each(function () {
            result += this.getAttribute("countryid") + ",";
        });
        $("input.selectedCountries").val(result);
    });

    //update selected countries based on value in selectedCountries input (textbox)
    var ids = $("input.selectedCountries").val().split(',');
    for (var i = 0; i < ids.length - 1; i++) {
        $("#selectable li[countryid=" + ids[i] + "]").addClass("ui-selected");
    }
});

Additionally, in last lines, jQuery has to parse data from selectedCountries input and select those countries which IDs are there. This way countries selected earlier and saved will appear on page load as selected. Those lines will be executed only once, it’s a way to keep data synchronised between ASP.NET on server side and jQuery on client side.

Next thing to do is to add ‘select all’ and ‘deselect all’ functionality. Here is how to get it done:

$(document).ready(function () {
    $("button, input:submit").button();

    $("button#selectall").click(function (event) {
        $("#selectable li").addClass("ui-selected");
        $("#selectable").trigger("selectablestop");
        event.preventDefault();
    });

    $("button#deselectall").click(function (event) {
        $("#selectable li").removeClass("ui-selected");
        $("#selectable").trigger("selectablestop");
        event.preventDefault();
    });
});

Three things are important here:

  • First line is an example of jQuery UI button plugin used. The only reason why it’s here is make buttons look nice. If you want to use it, it’s not a problem, but you need to add reference to the jquery.ui.button.js file
  • Next function is responsible for ‘select all’ functionality. You will find there basic usage of jQuery selectors (“#selectable li”) to find all list items and add “ui-selected” class. In the next line we are manually triggering “selectablestop” event to tell jQuery that selection has been made. As a result our function bound to that event will be executed and IDs of selected countries will end up in text box. And finally event.preventDefault() function prevents button from submitting the form.
  • And the last function is responsible for ‘deselect all’ functionality. The only difference is that instead of adding “ui-selected” class we are removing this class to make sure that all countries are not selected.

And this is the final effect after saving the countries:

jQuery Selectable Plugin with ASP.NET

View after saving the countries

Is that all? 

Well, almost – this is all in terms of functionality. You still need to play with CSS a bit to get the final effect like the one on attached screen. It’s not difficult, you can download the code and check modifications which I made, there are very few. Also you can download the project just to play with it and see how it all works together.

You can as well check how to integrate other jQuery UI widgets with ASP.NET like:

You may also need to check other events and options which you use with jQuery UI Selectable plugin.

VN:F [1.9.14_1148]
Rating: 9.6/10 (5 votes cast)

No Comments

jQuery UI Datepicker With ASP.NET

jQuery UI Datepicker is another great widget, extremely useful on forms, which can be easily integrated with ASP.NET. There are tones of different datepickers available almost everywhere so big question is why this one is better than other ones?

jQuery UI DatePicker

jQuery UI DatePicker Themes

Here are a few reasons:

  • jQuery UI is very well tested
  • jQuery UI is based on jQuery framework and very well integrated
  • there are 20+ themes available, ready to use, which you can take and make the datepicker to look consistent with your site
  • even if available themes are no good for you, you can easily customize it
  • it’s easy to integrate with ASP.NET
  • it’s flexible, you can configure it to serve you in many scenarios

On top of that, it’s my subjective opinion, but I really can recommend this plugin. I think it should cover 95% of typical scenarios which you can encounter on websites.

Okey, so let’s get started …

How to integrate jQuery UI Datepicker with ASP.NET

Step 1 – download jQuery UI on your machine. I was using version 1.8.14.

Step 2 – Make sure that your page has all the required JS and CSS files included. Datapicker has a few dependencies. Here is everything you need:

<script src="/Scripts/jquery-1.5.1.min.js" type="text/javascript"></script>
<link href="/Styles/ui-lightness/jquery-ui-1.8.14.custom.css" rel="stylesheet" type="text/css" />
<script src="/Scripts/ui/jquery.ui.core.js" type="text/javascript"></script>
<script src="/Scripts/ui/jquery.ui.widget.js" type="text/javascript"></script>
<script src="/Scripts/ui/jquery.ui.datepicker.js" type="text/javascript"></script>

Step 3 – HTML Code

This part is very simplified of course just to illustrate basic concepts.

<div id="DatepickerDiv" class="demo">
Event start date: <asp:TextBox ID="txtEventStartDate" runat="server" CssClass="DatepickerInput" /><br />
<asp:Button ID="btnSave" runat="server" Text="Save" onclick="btnSave_Click" /><br />
<asp:Literal ID="litMessage" runat="server" />
</div>

Basically minimalistic version contains textbox where user will enter a date. Datepicker widget will be attached to exactly this textbox. There is also button which will submit the form and literal to display messages from server.

Step 4 – jQuery Code

$(document).ready(function () {
    $(".DatepickerInput").datepicker({ dateFormat: 'dd/mm/yy' });
});

As you can see this is not very complex. In fact specifying date format is optional but I don’t like to leave date formats not specified. I have too many bad experiences from working with multilingual sites. Date format is different even between UK and US so this is one thing which I don’t want to leave for jQuery to figure out.

In this example jQuery finds textbox based on CSS class – this part is responsible for it: $(“.DatepickerInput”). Here you can read more about how to use basic jQuery filters. Datepicker is attached by calling function datepicker(). All parameters are optional, even dateFormat which I used here.

After this step you should be able to get this effect after clicking on txtEventStartDate textbox:

 

jQuery UI DatePicker Demo

jQuery UI DatePicker Demo Page

Step 5 – ASP.NET Code

On server side the only missing thing is implementation of btnSave_Click() method:

protected void btnSave_Click(object sender, EventArgs e)
{
    DateTime date;

    if (DateTime.TryParseExact( txtEventStartDate.Text,
                                "dd/MM/yyyy", // example: 31/01/2011
                                CultureInfo.InvariantCulture,
                                DateTimeStyles.None,
                                out date))
    {
        litMessage.Text = "Parsed event start date: " + date.ToShortDateString();
    }
    else
    {
        litMessage.Text = "Error: we were unable to parse the start date: " + txtEventStartDate.Text;
    }
}

The most important thing to remember is to use the same date format as it was in jQuery script. You can see that there are differences in Java Script and ASP.NET data format notation.  This can be confusing and is something that should be well commented! It is also a good practice to use TryParseExact() method over simply ParseExact(). And the rest I think is self-explanatory :)

Conclusion

jQuery UI Datepicker can be easily integrated with ASP.NET and I think should be considered as a default datepicker option for majority of websites. Example in this post shows that you need only a few lines on jQuery code to get everything working. Can you see any reason to not follow this approach?

Next steps? Two actually …

  1. You can also check how to integrate Autocomplete jQuery UI widget with ASP.NET
  2. And you can read more about configuration options which Datepicker offers.
And here you can download ASP.NET project with code from this post.
VN:F [1.9.14_1148]
Rating: 9.6/10 (7 votes cast)

No Comments

Button Click Event via Ajax With jQuery

In this post you will see how easy you can simulate button click event via ajax and this way call some ASP.NET server side method. There are number of scenarios in which this trick can be useful but for me the most appealing one are asynchronous autosaves. You have seen it in number of places for sure – basically whenever you give user an option to enter long piece of content, it’s a good practice to implement autosave, just in case, to prevent user’s content from disappearing because of browser crash or session timeout.

Okey, so here is an example how to get asynchronous autosaves working.

Step 1 – Get HTML ready

HTML is very straightforward, all you need is a textarea and a button. Of course you don’t need any button to have autosaves working, button will be used to save final version.

<h3>This is AutoSave demo!</h3>
<div>
<textarea id="ContentTextarea" cols="50" rows="10"><%=HttpContext.Current.Session["UserContent"]%></textarea>
<br />
<button id="SaveContentButton">Save</button> <span id="autosaveUpdates"></span>
</div>

There are two additional elements:

  1. span autosaveUpdates – this is where I will show updates to a user, it’s nice to inform that everything went fine and autosave actually works
  2. server side call to HTTP Session – I’m going to keep autosaved content in HTTP session, this is definitely not a production viable option, but for this example it will work

Step 2 – ASP.NET method which saves data

There are two things which you need to do to make your ASP.NET method available for jQuery and Ajax calls:

  • method has to be public and static,
  • and you need to add [WebMethod] attribute

Here is an example with very basic code which stores content in HTTP Session:

[WebMethod]
public static void SaveContent(string content, bool autosave)
{
    if (autosave) {
        HttpContext.Current.Session["UserContent"] = content;
    }
    else {
        // TODO save data to a database
        HttpContext.Current.Session["UserContent"] = String.Empty;
    }
}

Step 3 – Button Click Event via Ajax

Before going to autosave functionality, I will show you how to call button click even via ajax with jQuery. So firstly, this is the function which will call ASP.NET method (from step 2):

function SaveDataViaAjax(autosaveMode) {
    $("#autosaveUpdates").html("Saving ... ");

    methodURL = "/AutoSave.aspx/SaveContent";
    parameters = "{'content':'" + $("#ContentTextarea").val() + "', 'autosave':'" + autosaveMode + "'}";

    $.ajax({
        type: "POST",
        contentType: "application/json; charset=utf-8",
        url: methodURL,
        data: parameters,
        dataType: "json",
        async: true,
        success: function (data) {
            if (autosaveMode) {
                $("#autosaveUpdates").html("Autosave at " + Date().toLocaleString());
            }
            else {
                $("#autosaveUpdates").html("Data have been saved at " + Date().toLocaleString());
            }
        },
        error: function (result) {
            alert("Due to unexpected errors we were unable to load data");
        }
    });
};

This function will be used to save data after manually clicking on the button and also to autosave content. A few words of explanation:

  • URL to the ASPX page and method is: ‘/AutoSave.aspx/SaveContent’
  • I need to pass two parameters as this is exactly what is expected by SaveContent() method – content and autosave
  • $(“ContentTextarea”).val() returns value of textarea.
  • $.ajax() method is responsible for all the ajax calls mechanics.
  • please note that ajax() function is configured to make a asynchronous call, hence user interface won’t be blocked even in case when server will need a few seconds to respond.
  • success function will be invoked when entire ajax call went fine and error in other case.
  • I use simple jQuery selectors to find relevant tags.

I hope that the rest is self-explanatory. If not – let me know!

Now, we need to set this function to be called after clicking on the button, this code will do it:

$(document).ready(function () {
    $("#SaveContentButton").click(function (event) {
        SaveDataViaAjax(false)
        event.preventDefault();
    });
});

Step 4 – Autosaves with jQuery

And final step where I just need to do 2 things :)

  1. Define AutoSave function
  2. Tell Java Script to call the AutoSave function every 5 seconds

And here is code which will do all of that:

$(document).ready(function () {
    window.setInterval(Autosave, 5000)
});

function Autosave() {
    SaveDataViaAjax(true);
}

And this is it, it all together should work like a charm :) Essential here is usage of setInterval() function which takes as a parameter name of the function which should be invoked and interval of time how often give function should be invoked. If you like ajax updates then I recommend you reading about  about modules and ajax updates every X seconds, you will find more details there.

Conclusions

After reading this post you should know how to:

  • simulate button click event via ajax and jQuery
  • call ASP.NET method via Ajax after clicking on a button – ajax() jQuery function
  • call server-side method periodically with setInterval() function
  • create methods in ASP.NET pages which can be invoked by jQuery

And here is the final effect:

Button Click Event via Ajax, jQuery And ASP.NET Autosave
VN:F [1.9.14_1148]
Rating: 8.6/10 (5 votes cast)

1 Comment

jQuery UI Autocomplete With ASP.NET

In this post I want to show you how to integrate ASP.NET with jQuery UI Autocomplete widget. For those of you which don’t know what jQuery UI is here is a bit of introduction:

jQuery UI provides a comprehensive set of core interaction plugins, UI widgets and visual effects that use a jQuery-style, event-driven architecture and a focus on web standards, accessiblity, flexible styling, and user-friendly design.

From practitioner point of view – jQuery UI provides a few very nice and very useful widgets which you can really easily integrate with your application. Great example is Autocomplete widget which I will use in this post. I have found this widget very useful while implementing search functionality for my project. Of course to implement “just” search functionality where user can enter a keyword and click “search” button you don’t need much. And for sure you don’t need any fancy jQuery widgets. In my case additional requirement was to implement predictive search functionalty. That was a massive change for ASP.NET developer because out of the sudden I had to invoke search after each letter entered by a user and present it in a nice way.

Here is a great example how Google did the predictive search:

Google Predictive Search

And here is another example, something like this I will show how to build in this post:

Predictive Search

There is no component like that in Visual Studio! So the solution was to use jQuery UI Autocomplete widget.

How to integrate jQuery UI Autocomplete widget with ASP.NET

Step 1 – go to jqueryui.com and download jQuery UI. I was using version 1.8.14

Step 2 – include following JS scripts in your master page

<link href="/Styles/ui-lightness/jquery-ui-1.8.14.custom.css" rel="stylesheet" type="text/css" />
<script src="/Scripts/jquery-1.5.1.min.js" type="text/javascript"></script>
<script src="/Scripts/ui/jquery-ui-1.8.14.js" type="text/javascript"></scrpt>
<script src="/Scripts/ui/jquery.ui.core.js" type="text/javascript"></script>
<script src="/Scripts/ui/jquery.ui.widget.js" type="text/javascript"></script>
<script src="/Scripts/ui/jquery.ui.position.js" type="text/javascript"></script>
<script src="/Scripts/ui/jquery.ui.autocomplete.js" type="text/javascript"></script>

On the list above are all jQuery, jQuery UI Autocomplete widget and dependencies. Please note that there is also CSS style on the list – this is required to make Autocomplete widget looks nice :)

Step 3 – Create a Web Service which will return predictive search results

[System.Web.Script.Services.ScriptService]
public class PredictiveSearch : System.Web.Services.WebService
{

    [WebMethod]
    public IList<string> GetAllPredictions(string keywordStartsWith)
    {
        //TODO: implement real search here!

        // dummy implementation
        IList<string> output = new List<string>();
        output.Add(keywordStartsWith + "1");
        output.Add(keywordStartsWith + "2");
        output.Add(keywordStartsWith + "3");
        output.Add(keywordStartsWith + "4");
        return output;
    }
}

This is an example of web service which returns dummy data. Your job is to take is further and integrate with your system. Good thing is that from this point it’s all .Net so something you should be comfortable with.

Step 4 – HTML Code

<div class="ui-widget">
    <asp:Label ID="lblSearch" Text="Search" AssociatedControlID="txbSearchKeyword" runat="server"></asp:Label>
    <asp:TextBox ID="txbSearchKeyword" runat="server" CssClass="searchinput"></asp:TextBox>
    <asp:Button Text="Go!" runat="server" onclick="Search_Click" />
</div>

<asp:Literal ID="litStatus" runat="server"></asp:Literal>

As you can see HTML code is fairly straightforward. Only standard ASP.NET controls are here. Textbox txbSearchKeyword is the place where users will be entering keywords. So this is also the place where we need to add jQuery Autocomplete functionality. And that will happen in next step …

Step 5 – jQuery code

Firstly, let me show you the simplest possible implementation. It’s very simple so also a bit limited ;)
Limitation in this case is that search results are static (there are no ajax calls to server for search results). This can work well in scenario where set of all possible options is very limited – for instance you can use it to tag content. Assumption is that set of tags is fairly constant and in total there are below 100 tags in the system.

$(document).ready(function () {
    $(".searchinput").autocomplete({
        source: ["test", "asp.net", "jQuery"],
        minLength: 2
    });
});

And here is an example which actually uses Web Service from step 3.

$(document).ready(function () {
    $(".searchinput").autocomplete({
        source: function (request, response) {
            $.ajax({
                type: "POST",
                contentType: "application/json; charset=utf-8",
                url: "/Services/PredictiveSearch.asmx/GetAllPredictions",
                data: "{'keywordStartsWith':'" + request.term + "'}",
                dataType: "json",
                async: true,
                success: function (data){
                    response(data.d);
                },
                error: function (result) {
                    alert("Due to unexpected errors we were unable to load data");
                }
            });
        },
        minLength: 2
    });
});

In both examples searching for predictions will start not straight away after entering 1 letter! It will start after entering 2 letters, parameter minLength is responsible for that. You can see that behind the scene autocomplete functions calls our PredictiveSearch.asmx Web Service, in particular method GetAllPredictions(). In the next line we are passing entered letters as a parameter data.

It’s recommended to have your JS function in a separate file so that HTML code is separated from JS code.

Step 6 – Get Keyword on server side

On this stage, everything should be working now on client side. You should be able to see something this:

 Predictive Search

The only missing thing is implementation of onClick function called by “Go!” button. Implementation is again dummy, just to show you how to access all the relevant data:

protected void Search_Click(object sender, EventArgs e)
{
    litStatus.Text = "Search conducted for keyword: " + txbSearchKeyword.Text;
}

And as far as I’m concerned this all what you need to integrate jQuery UI Autocomplete with ASP.NET. However here you will find more advanced tutorial showing how to customize jQuery UI Autocomplete widget.

Questions? If yes then leave a comment!

You can download the full ASP.NET project here with the jQuery UI Autocomplete integrated - it should help you with experimenting.

VN:F [1.9.14_1148]
Rating: 8.0/10 (5 votes cast)

17 Comments

Easy Client Side Repeater with jTemplates Part 2

In the first part I have showed you how to use jTemplates plugin to build client side repeater. In this part I will show you how to make that work with data from ASP.NET WebService. That can be done in 3 steps:

Step 1 – Call WebService to Get Data

GetForthcomingEvents = function (successFunction) {
    $.ajax({
        type: "POST",
        contentType: "application/json; charset=utf-8",
        url: "/Services/EventsService.asmx/GetTheForthcomingEvents",
        dataType: "json",
        success: successFunction,
        error: function (result) {
            alert("Due to unexpected errors we were unable to load data");
        }
    });
}

This is standard example of $.ajax() function usage. URL of the WebService is /Services/EventsService.asmx and function’s name is GetForthcomingEvents().

GetForthcomingEvents() function expects another function as a parameter. That function will be invoked, assuming that call to WebService went fine (success: successFunction). In the next step you will see an exemplary implementation. It won’t be a surprise to you – it is the same function which was already presented in the first part.

Step 2 – Bind Data From WebService to jTemplates template

BindDataToEventsTemplate = function (result) {
    // check if jTemplates is loaded
    if (!jQuery.fn.processTemplate) {
        alert("jTemplates is not loaded");
        return;
    }

    // attach and process the template
    $("#Events").setTemplateElement("EventsTemplate");
    $("#Events").processTemplate(result);
}

Data returned from the WebService will be passed here. Next, data will be used to “process template” and this way data will be passed to client side repeater.

Step 3 – Get to all working on document ready

$(document).ready(function () {
    $("#Events").html("Loading events ....");
    GetForthcomingEvents(function (result) {
        if (result.d.length > 0) BindDataToEventsTemplate(result);
    });
});

This is of course not the simplest possible option. I have added one if statement (if (result.d.length > 0)) to check if there are actually some events returned. I didn’t want to “execute” repeater when there are no events to display. But it’s optional step and can be omitted.

jTemplates in action

Here I want just to remind you essential part of the template which will be used to process the data

{#foreach $T.d as record}
<tr>
  <td><a href="{$T.record.WebSite}">{$T.record.Name}</a></td>
  <td><a href="mailto:{$T.record.Organizer.Email}">{$T.record.Organizer.Name}</a></td>
        <td>{$T.record.Venue.Name}</td>
</tr>
{#/for}

For each record a row like that will be created. For more details please check first part of this post.

Bonus – The WebService

Here you can see my dummy code of the WebService

[System.Web.Script.Services.ScriptService]
public class EventsService : System.Web.Services.WebService
{

    [WebMethod]
    public Event[] GetTheForthcomingEvents()
    {
        return new Event[] { GetFirstEvent(), GetSecondEvent() };
    }

    private Event GetFirstEvent()
    {
        return new Event
        {
            StartDate = DateTime.Now,
            EndDate = DateTime.Now,
            Name = "MTS Conference",
            WebSite = "http://microsoft.com",
            Organizer = new Contact
            {
                Email = "john@ms.com",
                JobTitle = "CEO",
                Name = "John White"
            },
            Venue = new Venue
            {
                Address = "Alabama St. 45",
                City = "Washington DC",
                Name = "Medison Square Garden",
                PostCode = "45-233"
            }
        };
    }

    private Event GetSecondEvent()
    {
        return new Event
        {
            StartDate = DateTime.Now,
            EndDate = DateTime.Now,
            Name = "Microsoft TechEd North America",
            WebSite = http://www.microsoft.com/events/techednorthamerica/",
            Organizer = new Contact
            {
                Email = "john@ms.com",
                JobTitle = "CEO",
                Name = "Barry Green"
            },
            Venue = new Venue
            {
                Address = "Alabama St. 45",
                City = "Atlanta",
                Name = "Georgia World Congress Center",
                PostCode = "30303"
            }
        };
    }
}

public class Event
{
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public string Name { get; set; }
    public string WebSite { get; set; }
    public Contact Organizer { get; set; }
    public Venue Venue { get; set; }
}

public class Venue
{
    public string Name { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string PostCode { get; set; }
}

public class Contact
{
    public string Name {get; set; }
    public string JobTitle { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
}

Now you have all the pieces. Take it, use it, experiment with it and have fun!

I hope that it all makes sense to you … if not then please leave a comment and I will do my best to help you.

VN:F [1.9.14_1148]
Rating: 10.0/10 (2 votes cast)

, , ,

No Comments

Easy Client Side Repeater With jTemplates

In this post I would like to show you how easy you can implement client side repeater. There are a few jQuery plugins which you can use for it. However I recommend using jTemplates. With jTemplates you can easily define a client side templates, here is an example:

<p style="display:none"><textarea id="EventsTemplate" rows="0" cols="0"><!--
    <table>
        <thead>
            <tr>
                <th>Event</th>
                <th>Contact</th>
                <th>Venue</th>
            </tr>
        </thead>
        <tbody>
        {#foreach $T.d as record}
         <tr>
           <td><a href="{$T.record.WebSite}">{$T.record.Name}</a></td>
           <td>
                    <a href="mailto:{$T.record.Organizer.Email}">
                        {$T.record.Organizer.Name}
                    </a>
           </td>
           <td>{$T.record.Venue.Name}</td>
         </tr>
         {#/for}
        </tbody>
    </table>
--></textarea></p>

In the above example you can see that template itself is hidden for end users (display:none). Everything within HTML comments will be used. You can easily recognize elements corresponding to well known ASP.NET Repeater elements:

  • everything from the very top (<table>) to {#foreach … } represents HeaderTemplate
  • everything between {#foreach…} and {/#for} represents ItemTemplate
  • and everything under {/#for} is a FooterTemplate

How to Bind Data to Client Side Repeater?

JS code binding data to the jTemplates repeater looks like this:

BindDataToEventsTemplate = function (result) {
    // attach and process the template
    $("#Events").setTemplateElement("EventsTemplate");
    $("#Events").processTemplate(result);
}

Where $(“Events”) selects tag with id “Events” – this is where output will be placed. “EventsTemplate” is the name of our template – check the definition of template (first piece of code). So it’s that easy – firstly you need to set template which you want to use and secondly bind the data and ”process template”. End of story!

Just to make everything perfectly clear – here is an example of my “Events” tag where new events will be added using client side repeater:

<div id="Events"></div>

One additional tip – you can also check, just in case, if jTemplates has been correctly loaded by adding this piece of code:

// check if jTemplates is loaded
if (!jQuery.fn.processTemplate) {
    alert("jTemplates is not loaded");
    return;
}

In my case I have loaded data to the repeater from ASP.NET WebService. In the next post I will show you how to get it all working together – jTemplates with ASP.NET WebServices.

VN:F [1.9.14_1148]
Rating: 9.0/10 (4 votes cast)

, , ,

1 Comment

Modules and AJAX Updates Every X Seconds

In this post I want to show you how easy you can achieve AJAX asynchronous updates with jQuery. Typical scenarios where such functionality is handy are all sorts of modules which you would like to update without reloading entire page like:

  • The latest tweeter updates
  • The latest comments
  • Currently logged in users, or number of users online
  • and so on …

In my example I will show you how to create module showing currently logged in users which will be updated asynchronously every 10 seconds.

1. Create ASP.NET Web Form Page which outputs JUST the module’s HTML

Here is ASP.NET code for my module:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="CurrentlyLoggedInUsers.aspx.cs" Inherits="TestWebApp.Modules.CurrentlyLoggedInUsers" %>

<asp:Repeater ID="rptUsers" runat="server">
    <HeaderTemplate><div id="loggedInUsers"></HeaderTemplate>
    <ItemTemplate><a href="#"><%# Container.DataItem%></a>, </ItemTemplate>
    <FooterTemplate></div></FooterTemplate>
</asp:Repeater>

Generated at <%= DateTime.Now.ToLongTimeString() %>

And code behind code:

public partial class CurrentlyLoggedInUsers : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        // dummy list of users
        var list = new List<String> { "john", "mark", "james", "mike", "rodney" };

        rptUsers.DataSource = list;
        rptUsers.DataBind();

        // simulate real life scenario where it takes some time to generate the list
        Thread.Sleep(2000);
    }
}

As you can see it’s nothing sophisticated, very simple HTML, Repeater and dummy list of users. Good base to check how this solution works and to build on top of that later on…

2. Module and jQuery code

On other pages, where module is supposed to be located, it’s required to have only a div tag inside of which module will be loaded by jQuery:

<div id="LoggedInUsersModule"></div>
<div id="LoggedInUsersModuleUpdateStatus"></div>

Second div tag will be used to indicate that AJAX update is in progress and is loading new data. It’s not a part of core solution but I think it’s something which is nice to have. It improves user’s experience.

And now jQuery code:

$(document).ready(function () {
    updateLoggedInUsersModule();
    window.setInterval(updateLoggedInUsersModule, 10000)
});

function updateLoggedInUsersModule() {
    $('#LoggedInUsersModuleUpdateStatus').html('Loading ...').fadeIn('fast');
    $('#LoggedInUsersModule').load('/Modules/CurrentlyLoggedInUsers.aspx', function(response, status, xhr) {
        $('#LoggedInUsersModuleUpdateStatus').fadeOut('fast');
    });
}

Explanation:

  • First 4 lines a responsible for setup. In the second line I’m manually calling updateLoggedInUsersModule() function to load initial data. I don’t want to wait 10 seconds to show something on a page.
  • window.setInterval() function is a JavaScript’s built-in function which will call function passed as a first parameter (updateLoggedInUsersModule() in my case) every 10 seconds (second parameter)
  • In 7th line I’m updating status by setting new inner HTML and then jQuery function fadeIn() will display the element.
  • 8th line is the most important line, load() function will load data from server and place it into selected element. In our case that will be div with id LoggedInUsersModule.
  • Last parameter of load() function is a callback function which will be invoked after loading the data. I used this place to hide ‘Loading …’ text and this way show that operation has ended with success. Text will be hidden by fading them to transparent thanks to fadeOut() function.

What next?

  • Nice thing about load() function is that you don’t necessarily have to use entire HTML generated by server. You can use jQuery selectors on that HTML in a following way: $(‘#LoggedInUsersModule’).load(‘/Modules/CurrentlyLoggedInUsers.aspx #loggedInUsers‘)
  • Please remember that modules like this, with AJAX updates done every X seconds will be heavily used so it’s essential to make sure that performance is not a problem. Use a lot of caching on server-side if necessary.
VN:F [1.9.14_1148]
Rating: 8.7/10 (3 votes cast)

No Comments

Custom Validators and Asynchronous Calls to Web Service with jQuery

Custom ASP.NET Validators give developers easy way to create validator which is tailored exactly to their needs. Last week I have encountered a scenario in which custom validator was a great solution. I was working on yet another registration form and my job was to validate if username and email address are unique with javascript. I have used Custom Validators for that because I was already using ASP.NET validators so I wanted to stick to one approach for all fields of the registration form. Within client side function I have used jQuery to call web service which will do the validation for me. The trick was to bring it all together and make sure that this solution works with asynchronous calls. Let me show it to you step by step.

1. Create validation Web Service

There are really no tricks regarding the web service. All that you have to remember is to make sure that following lines are uncommented:

// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
[System.Web.Script.Services.ScriptService]

Then add methods which jQuery will call to validate if username and email are unique and therefore available:

[WebMethod]
public bool IsUsernameAvailable(string username)
{
    Thread.Sleep(1000); // for tests only
    return !username.StartsWith("a");
}

[WebMethod]
public bool IsEmailAvailable(string email)
{
    Thread.Sleep(1000); // for tests only
    return email.StartsWith("a");
}

This is of course dummy implementation but I’m sure you get my point here. One thing worth noticing is that Sleep() method on Thread has been used. That’s because in real life scenario validation like this will require a call to a database so inevitably it will be slow. Thanks to Sleep() method I wanted to make sure that response is not instant and this way simulate real life scenario.

2. Custom Validator

Basic ASP.NET code consists of a field where users will enter username and custom validator for it:

<asp:Label ID="lblUsername" runat="server" AssociatedControlID="txbUsername" Text="Username" />
<asp:TextBox ID="txbUsername" runat="server"/>

<asp:CustomValidator
    ID="cuvUsernameAvailable"
    runat="server"
    ControlToValidate="txbUsername"
    Display="Dynamic"
    ClientValidationFunction="ValidateUsername"
    ErrorMessage="Username is not available!"/>

As you can see custom validator requires javascript function ValidateUsername to validate username.

3. Client Side function

Within javascript function I have used jQuery to call web service and this way delegate validation there. jQuery part looks like this:

ValidateUsernameWithWebService = function (username, successFunction) {
    $.ajax({
        type: "POST",
        contentType: "application/json; charset=utf-8",
        url: "/Services/RegistrationDataValidationService.asmx/IsUsernameAvailable",
        data: "{'username':'" + username + "'}",
        dataType: "json",
        async: true,
        success: successFunction,
        error: function (result) {
            alert("Due to unexpected errors validation doesn't work");
        }
    });
}

A few words of explanation:

  • function expects two parameters – username (string) and callback function which will be called after web service invocation.
  • URL to the web service is /Services/RegistrationDataValidationService.asmx, and method which will be invoked is IsUsernameAvailable
  • async parameter is set to true so entire call will be done asynchronously

And finally the ValidateUsername function which will be called by the validator:

// variable to keep result of the last call to web service
var UsernameValidationResult;
// variable to keep information about username which was validated in the last call
var UsernameValidatorLastCheckValue;

ValidateUsername = function (source, args) {

    // detect validation triggered by form submission
    // prevent calls to web service in such scenario, return the previous result
    if (UsernameValidatorLastCheckValue == args.Value) {
        args.IsValid = UsernameValidationResult;
        return;
    }

    // async check with web service
    ValidateUsernameWithWebService(args.Value, function (result) {
        // following 2 lines are here to make sure
        // that on submit validator won't invoke call to webservice
        // it will reuse data from a call which was triggered by onChange event
        UsernameValidationResult = result.d;
        UsernameValidatorLastCheckValue = args.Value;

        // next three lines - inform validator about the result, update display
        source.isvalid = result.d;
        ValidatorUpdateDisplay(source);
        ValidatorUpdateIsValid();
    });
}

This part is a bit messy because you have to realize that validation and therefore this function will be called after entering username (onChange event) and when user click on submit button.

In the first case (onChange event) it’s fine to do the asynchronous call and get results after a second or two. However in case of form submission it’s not an option. It’s also worth noticing that in case of form submission username entered by the user hasn’t change, it was already validated. So it doesn’t make sense to validate it again. And that’s why in the above code I keep results of the last validation in the UsernameValidationResult and UsernameValidatorLastCheckValue variables.

I hope that it all make sense to you, if not then don’t hesitate to leave a comment. I will do my best to refine not clear areas. Also don’t hesitate to leave a comment even if everything is clear but you have a question or maybe something interesting to add. :)

VN:F [1.9.14_1148]
Rating: 10.0/10 (2 votes cast)

, ,

1 Comment

How To Empower ASP.NET Repeater With jQuery

As a ASP.NET developer I can imagine that you are using ASP.NET Repeater very often. It’s certainly true in my case. Repeater is probably the most useful control available in entire ASP.NET. It is great to output lists with custom template.

Here is a very simple example showing how to display list of strings as a HTML list. In code behind file I have to simply bind data to the repeater:

var list = new List() { "first point", "second point", "third point", "fourth point", "fifth point", "sixth point" };

rptList.DataSource = list;
rptList.DataBind();

And Repeater is defined in a following way:

<asp:Repeater ID="rptList" runat="server">
    <HeaderTemplate><ul></HeaderTemplate>
    <ItemTemplate>
        <li><%# Container.DataItem %></li>
    </ItemTemplate>
    <FooterTemplate></ul></FooterTemplate>
</asp:Repeater>

ASP.NET Repeater and dealing with CSS styles

To that point everything works great. However what was always problematic with Repeaters is manipulation with CSS styles. Quite typically there are requirements to set some custom class on a first and last element. Such requirements enforces changes in my clean code into something like this:

1. First let me update Repeater template:

<asp:Repeater ID="rptMagicList" runat="server">
    <HeaderTemplate><ul></HeaderTemplate>
    <ItemTemplate>
        <asp:Literal ID="litElement" runat="server" />
    </ItemTemplate>
    <FooterTemplate></ul></FooterTemplate>
</asp:Repeater>

2. Introduction of ASP.NET Literal means that binding will be done in code behind files:

private int elementsCount = 0;

protected void Page_Load(object sender, EventArgs e)
{
    var list = new List() { "first point", "second point", "third point", "fourth point", "fifth point", "sixth point" };

    // this is needed to figure out which element is the last one
    elementsCount = list.Count; 

    rptMagicList.ItemDataBound += rptMagicList_ItemDataBound;
    rptMagicList.DataSource = list;
    rptMagicList.DataBind();
}

void rptMagicList_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
    {
        var currentElement = e.Item.DataItem as String;
        var litElement = e.Item.FindControl("litElement") as Literal;

        var cssClassName = String.Empty;
        if (e.Item.ItemIndex == 0) cssClassName = "first";
        if (e.Item.ItemIndex == elementsCount - 1) cssClassName = "last";

        litElement.Text = string.Format("<li class='{0}'>{1}</li>",cssClassName, currentElement);
    }
}

Of course this approach works. It’s also true that from developer to developer solution for this task may vary slightly. But I think you will agree that by adding one simple requirement we had to add lots of lines of monkey code. Let’s face it … this is not a rocket science, this code is trivial and after updating a few repeaters like this … you are sick of it.

So is there a better approach? I think there is – use strong side of ASP.NET Repeater to output list and strong side of jQuery to deal with custom CSS styles!

How to empower ASP.NET Repeater with jQuery

If you use Repeater + jQuery approach then there is no need to change ASP.NET code from initial example. All you have to do is to add JavaScript file with jQuery code:

$(document).ready(function () {
    $("ul.magicList > li:first").addClass("first");
    $("ul.magicList > li:last").addClass("last");
});

If you are new to jQuery and not sure what this code is doing, check my older posts. Everything is explained there in a simple way:

So to sum up … what are the benefits of this approach:

  • Less code – code which you write is an absolute minimum, no monkey code
  • Flexibility – jQuery has a lot to offer, ASP.NET has also a lot to offer — use strong sides of both technologies to get thinks done
  • Lack of hardcoded CSS classes in code behind files – this is also important, this way you don’t need a developer to change some purely UI related issues.
  • Part of HTML transformation is moved from server-side to client-side — if your servers have less work with one request, they can handle more requests
  • Richer UI – there are tones of jQuery plugins which you can use to improve user experience.
What are the alternatives? You can also stop using ASP.NET Repeater and switch to client side version – check how to implement client side repeater with jTemplates.
VN:F [1.9.14_1148]
Rating: 10.0/10 (2 votes cast)

,

No Comments

How To Use Basic jQuery Filters With HTML List (part 2)

In my previous post I have given you a few examples of the most basic jQuery filters. In this post I will dig a bit deeper to show you what else is possible.

Just to recap quickly, so far I have mentioned about following selectors:

  • :first – selects first element
  • :last – selects last element
  • : odd – selects all odd elements
  • :even – selects all even elements

And now a few new ones, but before I will jump to that, here is an HTML code which I use to play with:

<h2>
    Here is my magic list
</h2>
<p>
    <ul>
        <li>first point</li>
        <li>second point with an image: <img src="Images/icon_smile.gif" /></li>
        <li>third point</li>
        <li>fourth point</li>
        <li>fifth point</li>
        <li>sixth point</li>
    </ul>
</p>

Task 1: Our first taks is to add custom colour to the third and fifth element only, here is jQuery code which you can use:

$(document).ready(function () {
    $("ul.magicList > li:eq(2), ul.magicList > li:eq(4)").css("color", "red");
});

And here is the result:

basic jQuery filters

A few words of explanation:

  • li:eq(2) – our job was to select third element so you may ask why there is ’2′ passed as a paramater? That’s because index is zero-based. So first element has index 0, for second element index is 1 etc.
  • ul.magicList > li:eq(2), ul.magicList > li:eq(4)” – comma in the middle means logical OR. So it can be translated into: find third element OR fifth element.

Task 2: Now our objective is to select all elements starting from the second one. In other words … all except of the first one. There are two options which will give exactly the same effect:

$(document).ready(function () {
    $("ul.magicList > li:gt(0)").css("color", "red");
});

and second option:

$(document).ready(function () {
    $("ul.magicList > li:not(:first)").css("color", "red");
});

And here are the results:

jQuery filters and selectors

Explanation:

  • selector :not() allows you to invert selection, so you can select all elements that do not match the given selector, in our case :first
  • selector :gt() requires parameter, zero-based index. GT stands for “greather than”. In out case we want all elements where index is greather than 0. Hint: there is also another similar selector – lower than :lt() which works in analogical way.

Task 3: this one is more interesting … add custom colour for all elements which contain an image. Even though it may sound like a much more complicated job, in fact you can do it really easily:

$(document).ready(function () {
    // set custom style for all elements containing image
    $("ul.magicList > li:has(img)").css("color", "blue");
});

Explanation:

  • selector li:has(img) will return all LI elements conatining IMG tag. Of course you can use this selector to find any tag.

Task 4: the hardest task … add custom colour for every third element. So 3rd, 6th, 9th … elements should get a custom colour. jQuery doesn’t have a predefined selector for it, so in this case we have to implement it on our own. Luckily, it not a rocket science:

$(document).ready(function () {
    // set color only for every third element
    $("ul.magicList > li")
        .filter(function (index) { return index % 3 == 2; })
        .css("color", "red");});

Final result:

jQuery filters and selectors

Explanation:

  • after selecting all LI elements (“ul.magicList > li”) you can filter results with your own function which has to be passed as a parameter: filter(function (index) { return index % 3 == 2; })
  • your custom function is expected to return true for all elements that you want to include and false for element which you want to reject
  • parameter for your functions ‘index‘ is zero-based which means that for third element index is 2. 2 modulo 3 is 2. For sixth element index is 5, 5 modulo 3 is 2. You see how it works now?

I hope it all make sense to you. If not, leave a comment I will try to help! :)

VN:F [1.9.14_1148]
Rating: 10.0/10 (2 votes cast)

, ,

3 Comments