Posts Tagged 'Ajax'

Managing Screen Updates When Loading UI Controls Using Ajax

I came across an interesting problem recently while working on www.cocktailsrus.com. I was adding a new rating system allowing members to rate cocktails on a scale of 1-5. I wanted to do something that was accessible, but also visually appealing and appropriate, so that this:

radio buttons

could easily and accessibly be converted into this:

rating plugin with images

The answer, of course, was to write a jQuery plugin that would be called on document.ready() and convert the default radio-buttons to active images – but only for users who have JavaScript enabled. I duly wrote the plugin, and it does everything I intended (e.g. you can customize the images, change the maximum number on the scale etc.). It’s free for anyone to use, and you can download it here.

However, during testing I came across a problem. The site makes extensive use of Ajax, and when the partial page downloads to the client the radio buttons are briefly visible before being replaced by the images. The problem is that the screen is being updated before document.ready() runs.

The obvious solution is to use a callback. I use two different Ajax methods – the built-in jQuery .load() method and .ajaxSubmit() (part of the jquery form plugin). Both have callbacks that run when the Ajax call returns, like this:

$(‘article’).load(url, function () {

$(‘#ScoreSection’).rate();

});

Unfortunately, while this looked like a promising solution, the problem remained: there is a perceptible delay between the DOM updating and the callback running. Once again, the user sees the radio-buttons briefly before they are replaced. So how to fix the problem?

The answer lies in an old animation technique – make the change off-screen and only make it visible after it has completed. In this case, that means:

  1. Use jQuery to create an empty div element and assign the result to a variable
  2. Assign the return from the Ajax call to the variable
  3. Run the plugin against the updated variable
  4. Update the DOM with the variable

With .load():

var $temp = $(‘<div />’);

$temp.load(url, function () {

   $(‘#ScoreSection’, $temp).rate();

   $(‘article’).html($temp);

});

With .ajaxSubmit():

var $temp = $(‘<div />’);

$form.ajaxSubmit({ target: $temp,

   success: function () {

     $(‘#ScoreSection’, $temp).rate();

     $(‘article’).html($temp);

}

});

Using this technique, the images replace the radio-buttons before they become visible, even when using Ajax. For an extra refinement, add a test inside document.ready() to make sure that the original method is only invoked if the Ajax callback has not already run. In this case, that’s a simple matter of testing the visibility of the radio-buttons, and only running the .rate() method if they’re visible.

Kevin Rattan

For other related information, check out these courses from Learning Tree:

jQuery: A Comprehensive Hands-On Introduction

Building Web Applications with ASP.NET and Ajax

Building Web Applications with ASP.NET MVC

Improved Device Detection with ASP.NET

This is a follow up to my last post where I did a quick-and-dirty hack to get around the limitations of ASP.NET’s built-in isMobileDevice property.

At the end of that post, I said I was going to wait and see if Microsoft did a better job next time around before I went to the trouble of improving my solution. Well, it didn’t work out that way. You see, even if I hadn’t disliked leaving a quick-and-dirty fix in place, it turned out that there was another complication that meant I really needed to provide a proper solution.

The app uses Ajax extensively (and explicitly) in the non-mobile version in order to give a better user experience. It also uses Ajax implicitly in the mobile solution, as jQuery mobile automatically converts links and forms into Ajax calls unless you tell it not to do so. What I hadn’t taken into account in my quick-and-dirty approach was that I wasn’t just detecting mobile devices inside the view engine – I also needed to detect them in order to provide partial pages to Ajax calls in the non-mobile Web version.

The app delivers three kinds of content:

  • Full Web Pages
  • Full Mobile Pages
  • Partial pages for non-mobile Ajax calls

Unfortunately, as jQuery mobile also makes Ajax calls, when mobiles were not detected by the built-in isMobileDevice property, I was returning the partial page when I should have been returning the full mobile page.

So back to the drawing board.

And since I was now going to have to do things properly, I decided to support all the major mobile platforms, not just Android.

I created a new static method isMobileDevice() which accepts an argument of type HttpContextBase and checks both the built-in isMobileDevice property and series of string constants. I then call this method from inside the ViewEngine Nuget and also from my controllers when detecting if the call is an Ajax call.

Here is the key method:

Sample code from method detecting mobile devices

And here is one of the calls to the method:

Sample code calling the new method

If you want the full code, I’ve placed it online as devicedetector.txt. I hope you find it useful.

Kevin Rattan

For other related information, check out these courses from Learning Tree:

Building Web Applications with ASP.NET MVC

Building Web Applications with ASP.NET and Ajax

Simplifying Dynamic Ajax Forms with jQuery Delegates

Recently I was working on an ASP.NET MVC application that made extensive use of Ajax. It’s a version of Chutes/Snakes and Ladders using HTML5 and JavaScript. I used jQuery for the Ajax, of course (what do you expect? I wrote the Learning Tree course jQuery: A Comprehensive Hands-On Introduction). As always, jQuery was a pleasure to work with, but even so it was a tough bit of code to write: until I turned to jQuery delegates.

The problem was complexity. I wasn’t just adding Ajax to existing page content – I also had to Ajax-enable an open-ended number of nested links and forms which were themselves dynamically downloaded.

The .load() method

The jQuery .load() method allows you to download fragments of HTML into the current page. I was using it to download multiple forms (and links), which then had to be set up to use Ajax. These new Ajax forms and links would then download further forms which would also need to be set up for Ajax. This led to some very messy coding and all sorts of recursion problems (such as event handlers being bound to the same object more than once). Switching to delegates not only solved the problems – it also made the code much simpler.

The application used two forms of Ajax: form submission using the Forms plugin, and links which which used the .load() method – which looks like this:

1st code sample

In the example, the .load() method retrieves the page at http://myHref and then looks for the section identified by the selector #selector. The resulting HTML is set as the HTML content of the element myID.

I needed to call .load() on every link inside the newly downloaded HTML, and then use the optional callback to add Ajax to any forms that had been downloaded. This screenshot shows the problem – a user can have n games, which can have n players, who can have n player statements – all of which need to be downloaded using Ajax and then set up to make their own Ajax calls.

2nd code sample

In my first pass, the callback was very large, with logic to ensure I was not setting up the same event handlers twice, and named elements given individual treatment:

3rd code sample

Switching to delegates made the code much simpler – and removed the problem of panels having to be processed multiple times:

4th code sample

So, what is a jQuery delegate, and what does it do for me?

The delegate method looks like this:

5th code sample

The key point is that rather than assigning the event handler directly on the element, you are assigning the handler to any and all matching elements (in this case, input:text) inside the matched set (in this case, the <body> element). This is powerful enough – but the real beauty is that the handlers are assigned, even if the matching child elements have not been added yet. That means the handler will automatically be applied to any child elements that are added dynamically using Ajax.

Now, instead of having to repeatedly set up each element as it is downloaded, I can set up the Ajax behavior I want on the parent element and it is automatically applied to all children – whether or not they have been downloaded yet. This means I can create a general function to set up the links:

6th code sample

And then call it with the appropriate arguments for the particular div/panel:

7th code sample

Now, as the new forms and links are downloaded and added to a container, any matching elements are automatically assigned Ajax behavior.

Without jQuery delegates, wiring up Ajax functionality on dynamically downloaded forms can be a nightmare of recursion. With jQuery delegates, the code becomes simpler, cleaner – and much more elegant.

If you’re interested in the complete code, I’ve put the ASP.NET MVC page including the JavaScript in a text file here.

If you want to learn about jQuery in depth, then you might want to spend 3 days attending jQuery: A Comprehensive Hands-On Introduction. If you’re interested in jQuery with ASP.NET MVC, then that is covered in Building Web Applications with ASP.NET MVC, and if you want to know how to integrate jQuery into ASP.NET Web forms – well, our course Building Web Applications with ASP.NET and Ajax covers that as well, and I just happen to be the author.

Kevin Rattan

For other related information, check out these courses from Learning Tree:

HTML5: Next Generation Web Development

JavaScript for Web Development


Learning Tree International

.NET & Visual Studio Courses

Learning Tree offers over 245 IT and Management courses, including a full curriculum of over 15 .NET training options.

Free White Papers

Questions on current IT or Management topics? Access our Complete Online Resource Library of over 65 White Papers, Articles and Podcasts

Enter your email address to subscribe to this blog and receive notifications of new posts by e-mail.

Join 9 other followers

Follow Learning Tree on Twitter

Archives

Do you need a customized .NET training solution delivered at your facility?

Last year Learning Tree held nearly 2,500 on-site training events worldwide. To find out more about hosting one at your location, click here for a free consultation.
Live, online training

Follow

Get every new post delivered to your Inbox.