Accessible Custom AJAX and .NET

Add to FacebookAdd to DiggAdd to Del.icio.usAdd to StumbleuponAdd to RedditAdd to BlinklistAdd to TwitterAdd to TechnoratiAdd to Yahoo BuzzAdd to Newsvine

One general rule in making an accessible web application is that you shouldn’t change content of the page with javascript. This is because screen readers have a tough time monitoring the page and notifying the user of dynamic changes. Usually, the reason you would use Ajax is exactly that – do something on the server, and then update some small part of the page without causing the whole page to refresh. That means if you have an “ajaxy” page and you care about accessibility, you have to provide a non-ajax interface as a fallback for screen readers.

Ajax.NET, Microsoft’s library for Ajax, makes this fallback easy to implement. Microsoft has you define your AJAX properties in an abstraction layer – the page XAML – which means that the framework can decide to not render the AJAX code to certain browsers (and screen readers) that will not support it, and instead use the standard postback method.

The problem with Ajax.NET is that the communication can be bloated (mostly because of the abstraction layer, it sends more post values than you might need – like the encrypted viewstate value), which negates many of the benefits of an Ajax solution. I really wanted to roll my own ajax communications to make them as lightweight as possible.

My solution was to write the page in a standard .NET postback manner, and then use a user-defined property that would allow javascript to replace the postback in javascript/jQuery with an Ajax call.

Here’s my code:

$(function() {
            if (serverVars.uiVersion != "accessible") { // use js/ajax for checking/unchecking where possible
                var $todos = $("#chkToDo");
               $todos.removeAttr("onclick"); // remove postback
                    function() {
                        //some stuff altering the document, and an ajax call to report the change to the db

This works great, although you need to be careful about your server-side events. In my case, I had an OnCheckChanged event to handle the postback/accessible mode. Even though checking/unchecking the box no longer fired an autopostback – ASP.NET will still fire the checkchanged event if you postback later for some other reason (e.g. – a linkbutton elsewhere on the page) after the checked status had changed. So, if a user had changed the state of a checkbox, then clicked another link button on the page – instead of sending the user to the intended page,my app just refreshed the whole page(because my CheckChanged event redirected to reload the page – which caused it to skip the ‘click’ event of the linkbutton). Once I realized this was happening, it was easy enough to fix – I just needed to only run the event logic if the user was in accessibility mode. I spent a little time running in circles on that one though, at first I thought my client side document changes were causing a ViewState validation error on the server.


Extending jQuery to Select ASP Controls

Add to FacebookAdd to DiggAdd to Del.icio.usAdd to StumbleuponAdd to RedditAdd to BlinklistAdd to TwitterAdd to TechnoratiAdd to Yahoo BuzzAdd to Newsvine

If you have worked with JavaScript in an ASP.NET Web Forms environment, you almost certainly have been frustrated that this markup:

	<asp:TextBox runat="server" ID="txtPhoneNumber" />

renders out as something like:

	<input type="text" id="ctl00_ctl00_ctl00_main_Content_txtPhoneNumber"
		name="ctl00$ctl00$ctl00$main$Content$txtPhoneNumber" />

The fastest and easiest way to get a reference to a DOM element in JavaScript is using the ID attribute and document.getElementById(). Unfortunately, the ID attribute generated by the server is unpredictable and based on the server naming containers. There are a couple ways of that I have previously dealt with that problem, but both have problems.

Old Solutions

  1. Accessing the ClientID of the server control

    If you use inline code inside <% %> tags, you can access the ClientID directly from the .aspx page.

    	var goodID = '<% txtPhoneNumber.ClientID %>';  // = 'ctl00_ctl00_ctl00_main_HeaderTabs_txtPhoneNumber'
    	var badID = 'txtPhoneNumber'; // The text box does not have this ID, it will not work
    	var uglyID = 'ctl00_ctl00_ctl00_main_Content_txtPhoneNumber'; // DO NOT hardcode the generated ID into your code!

    This is not ideal because you cannot reference the ClientID from outside of the page, so you cannot keep your JavaScript in external files.

  2. Setting attributes on control and accessing with jQuery selectors

    jQuery has an excellent selector API that can easily grab an element if you know attributes on it. So, if there were a couple controls defined as:

    	<asp:TextBox runat="server" ID="txtPhoneNumber" CssClass="txtPhoneNumber" />
    	<asp:TextBox runat="server" ID="txtAddress" ClientID="txtAddress" />

    You could access them with jQuery:

    	$(".txtPhoneNumber").keyup(...);   // This works
    	$("[ClientID='txtAddress']").keyup(...);   // This works
    	$("#txtPhoneNumber").keyup(...);   // This still DOESN'T work
    	$("#txtAddress").keyup(...);   // This still DOESN'T work

    This is not ideal because it requires adding extra attributes onto any server control that you want to access with JavaScript.

Original jQuery Solution

I first happened upon a solution to the same problem over on John Sheehan’s blog. This looked promising, but did not work the current latest release of jQuery (1.3). Another contributer to this blog, Tim Banks, updated the code in to work with the newer version.

However, I found an error in Internet Explorer and a more reliable way to get the ClientID would be to use the jQuery attribute selector and match based on an “id” attribute that ends with the Server ID. So, I wrote a JavaScript function called $asp that returned a jQuery collection. This function worked well and was implemented in the latest Foliotek release.

	function $asp(serverID) {
		return $("[id$='" + serverID+ "']");

	// Once this function is included, you can call it and get back a jQuery collection

Updated jQuery and Sizzle Solution

It seemed like it would be better if the solution actually extended the selector engine rather than using a function to select objects. This would fit better into a jQuery development paradigm, allow more complex selectors, and also allow the selector to be used in other library functions, like “filter” or “find”. Also, it would be nice to be able to use the tag name in the selector to give a performance improvement, since getElementsByTagName is a fast operation that will narrow the element collection.

So, I returned to the selector, fixed the IE bug and made sure it worked with the now latest version of jQuery (1.3.2). This short function extends the Sizzle selector engine to return an element that has an ID that ends with the ID that is passed in the parenthesis after the “:asp()” selector.

	// Include this function before you use any selectors that rely on it
	jQuery.expr[':'].asp = function(elem, i, match) {
		return ( &&[3] + "$"));

	// Now all of these are valid selectors
	// They show why this method has more functionality than the previous $asp() function.
	$(":asp(txtPhoneNumber), :asp(txtAddress)")
	$("ul:asp(listTodos) li")

This function allows access to server controls without adding additional markup and without the JavaScript existing on the .aspx page.

Note, there is a potential limitation if you had one control with the ID=”txtPhoneNumber” and another with ID=”mytxtPhoneNumber”. Both elements end with “txtPhoneNumber” and the selector would not necessarily return the correct value. This solution is not perfect in that sense, but the benefits it provides over other methods (cleaner markup and ability to use external JavaScript files) make it a good alternative.

Finding real body height using jQuery

Add to FacebookAdd to DiggAdd to Del.icio.usAdd to StumbleuponAdd to RedditAdd to BlinklistAdd to TwitterAdd to TechnoratiAdd to Yahoo BuzzAdd to Newsvine

Sometimes, you need to know the full content of a document’s height. In our case, we needed to set an iframe to be the full height of its content.  There are several ways to attempt this:


I’ve found that all of these require significant tweaking to get accurate results across all browsers. Each property means something different in each browser. That sucks for coding and maintenance. Enter jQuery:


Unfortunately, even that doesn’t seem to work very well in IE.

Here’s a workaround that should always work, though. Basically, you create a temporary div that contains everything from the body, insert it off screen, and measure it:

function getDocumentHeight()
       var $temp = $("<div>")

        var h = $temp.height();
        return h;
    return $("body").height();

It seems like it would be really inefficient, but it actually performs fairly well.

jQuery Extension: radioClass() method

Add to FacebookAdd to DiggAdd to Del.icio.usAdd to StumbleuponAdd to RedditAdd to BlinklistAdd to TwitterAdd to TechnoratiAdd to Yahoo BuzzAdd to Newsvine

I recently ran into a method in the Ext javascript library called radioClass.  This method will add one or more CSS classes to an element and remove the class(es) from the siblings of the element.  I found that this would be helpful in jQuery since I find myself doing something similar often:


I wrote the following extension method in jQuery to reduce the amount of code.


     radioClass: function(c) {
     return $(this).addClass(c).siblings().removeClass(c).end();



View Demo