Showing posts with label jquery. Show all posts
Showing posts with label jquery. Show all posts

Thursday, September 2, 2010

jQuery: Simple Ajax Loading Screen

So another thing jQuery made easy for me this week was a loading screen. What I wanted was a loading screen to be displayed for all Ajax calls. I started preparing for this by thinking of the states I'd need to watch and then the search and replace that wouldn't work quite right to ensure all of my Ajax would kick off the loading screen, and then turn it off again when the call was successful.

Well, it seems in jQuery this is pretty easy. Check the code below, as it is all it took.

busyDialog = {
 
 init: function () {
  var el = $(document.createElement('div')).attr('id', 'busyDialog')
   .css({
    'width': '100%',
    'height': '100%',
    'background-image': 'url(lib/images/ajax-loader.gif)',
    'background-position': 'center',
    'background-repeat': 'no-repeat',
    'position': 'fixed',
    'z-index': '9999',
    'display': 'none',
    'cursor': 'progress'
   });
  
  $(el).ajaxStart(function(){
      $(this).show();
   });
  $(el).ajaxStop(function(){
      $(this).hide();
   });
  $('body').prepend(el);
 }
}

Personally, I have this thing loaded into a widget class.  When the app instantiates I call the init method and I'm set.  This would be sickeningly easy to prototype into jQuery as a plugin.

What happens in the code above is that we create a new div and place a loading animated gif in the center of it.  You can get an animated gif over at AjaxLoad.  The div is created at 100% width and height so that the use cannot interact with the screen while the loading dialog is active.  The loading div is initially invisible.  Two event handlers (ajaxStart and ajaxStop) are employed, which is where the real helpfulness of jQuery comes in.  jQuery allows us to specify global handlers (here showing and hiding the loading div) for all Ajax requests.  We are still able to have our custom success handlers for each individual Ajax call.  Wicked.

The final step is to throw the div into the DOM.  We do this as the first child of 'body'.

Friday, August 27, 2010

jQuery Validate and Checkboxes

As I start this post, a quick aside.. I've had some discussions with a few devs lately on the use of the id attribute versus the name attribute on HTML input elements.  IMO, id is a unique identifier, whereas name is used to tie fields such as checkboxes together, which today's post deals with.  The result looks like this:


For what it's worth, I never use the name attribute on input elements except when it is of type checkbox, but I digress... ;)

I had the need to require two or more checkboxes to be checked on a form recently.  I am using jQuery Validate for the form validation logic.  This is the first time I've had to roll my own validator since starting with jQuery Validate as it's defaults are pretty inclusive.  Creating a custom validator is simple.  The code looks like this:
$.validator.addMethod(
 'multiplecheckboxchecked',
 function (value, element) {
  var aChecked = $('input[name='+$(element).attr('name')+']:checked');
  return ( aChecked.length > 1 ) ? true : false;
 }
);
Breaking it down,  use the addMethod() function to define a new rule in the form addMethod(name, callback, message).  In my validation logic I change the color of the container div so I do not need the message attribute.  The name attribute specifies the rule name when we assign it to an element when creating the validator.  The callback is the function we will use to validate the form field.  The callback method gets two parameters by default: value and element.  Value is the value of the form field being validated.  In the case of a checkbox this is a bit weird.  We get only one element passed through which has the name value we specify in our rules definition.  The element is the actual form element, and for a checkbox we can use this to our advantage by grabbing the name attribute to get all of the checkboxes bound by the same name.  Line 4 shows our selector: 'input[name='+$(element).attr('name')+']:checked'.  This tells jQuery to get all input controls with a name matching our checkbox group name that are also checked.  This selector returns an array of elements, and we use the length of that array to tell how many boxes have been checked.  In my case I needed at least two, so I return true if two or more are checked, false if one or less are checked.

Using the rule then looks like this:
rules: {
 frictiontypeid: 'required',
 checkboxgroupname: 'multiplecheckboxchecked'
}
I also had to use a custom highlighter which is simple to override for checkboxes:
highlight: function(element, errorClass, validclass) {
 // if the element is a checkbox, highlight the entire group
 if ( element.type == 'checkbox' ) {
     $(element).parents('.ctrlHolder').addClass('error');
 } else {
  $(element).parent().addClass('error');
 }
},