GridView jQuery Plugin Row MouseOver And Click Styles

by mosessaur| 30 March 2008| 1 Comments

Last year on October, Matt Berseth wrote few posts about improving styles of GridView, these posts are the following:

Last month, I posted a revised version of his work using Script#. And in this post I'm going to show that same features can be applied using jQuery. And I was really amazed by the simplicty and less of code that I had to write to get the same feature on hand.

I've implemented this using jQuery plugins. So I had to author a plugin and I can call it very simple one as the idea was already done and I had it on my head. I'm not going to explore how jQuery plugins can be authored, but you can return to the following links:

You can view demos here [demo 1] & [demo 2]. I will start from the end, on how to use the plugin. Actually it is very simple, all you need to do is to add this JavaScript line to your code when the page, or as a startup script. I did that using onLoad event of the ASP.NET AJAX Application as I have ScriptManager installed on the page:

$(selector).gridviewex(options);

For example:

<script type="text/javascript">
function pageLoad(s,e)
{
    $('#gvProducts').gridviewex({hasPageRow:true,dataRowClass:'row',altDataRowClass:'altrow',
                                rowHoverClass:'rowhover', rowSelectClass:'rowselect',
                                cellHoverClass:'cellhover',cellSelectClass:'cellselect',
                                columnHoverClass:'columnhover'});
}
</script>
This will initialize the GridView with the style needed. It worth to mention that you can use this plugin with any Table based HTML.

gridviewjqueryplugin00 gridviewjqueryplugin01

The plugin starts with plugin definition as the following:

   1: $.fn.gridviewex = function(options) {
   2:     // build main options before element iteration
   3:     opts = $.extend({}, $.fn.gridviewex.defaults, options);
   4:     
   5:     // iterate and reformat each matched element
   6:     var i = 0;
   7:     return this.each(function() {
   8:       $this = $(this);
   9:       //Only table element allowed.
  10:       if(!$this.is('table')){
  11:         alert('Your selection must be element of type table');
  12:         return;
  13:       }

The only challenge was how to traverse table element and retrieve all rows with cells and identify header row from data rows. In GridView header rows are rendered with '<th>' while data rows are normal '<td>'. So, I used this as a rule:

   1: //Header row must contain th tag
   2: var $headerRow = $this.children('tbody').children('tr:has(th)');
   3:  
   4: //Data rows, should execlude header row.
   5: $dataRows = ($headerRow.length > 0) ? $this.children('tbody').children('tr:not(:has(th))') : $this.children('tbody').children('tr');
   6:  
   7: //If the table contains pager row, this flag should be set to true by developer
   8: if(!opts.hasPagerRow)
   9:     $dataRows = $dataRows.not(':last');

Next was to initialize row and alternative row style as well as bind event handler to mouseover, mouseout and click events on each cell:

   1: //Attache dataRowClass & altDataRowClass to rows
   2: $dataRows.each(function(){
   3:     if(rowIndex%2==0){
   4:         if(!$(this).hasClass(opts.dataRowClass))
   5:             $(this).addClass(opts.dataRowClass);}
   6:     else{
   7:         if(!$(this).hasClass(opts.altDataRowClass))
   8:             $(this).addClass(opts.altDataRowClass);}
   9:         
  10:     //Columns    
  11:     var $dataCells = $(this).children();
  12:     
  13:     var cellIndex = 0;
  14:     
  15:     //Bind mouseover, mouseout and click events handlers to column cells
  16:     $dataCells.each(function(){
  17:         //Extra data to be sent to event handler. Can be accessed like this e.data.propertyName.
  18:         var args = {rowIndex:rowIndex,cellIndex:cellIndex};
  19:         $(this).bind('mouseover', args, cellHover);
  20:         $(this).bind('mouseout', args, cellOut);
  21:         $(this).bind('click', args, cellClick);
  22:         cellIndex++;
  23:     });
  24:     rowIndex++;
  25:   });
  26: });

You'll notice 2 variables, rowIndex and cellIndex variables. These are used to be sent to each event handler. They are handy and useful. As in mousover and mouseout events when columnSelectClass and columnHoverClass are applied, it worth alot to know the cellIndex of the current hover cell.

You must know the each method is really a magic method. When I say $dataRow.each(fn), this will iterate through all elements within $dataRow one by one. And inside the callback function you can use $(this) to access current jQuery object which stores the element.
Using this method I was able to increment rowIndex and cellIndex variables. Also I used it to bind event handlers using bind method.

Now time to explore the event handlers. They are very simple, I just followed the pattern Matt's presented in his post:

   1: //mouseover event handler 
   2: function cellHover(e)
   3: {
   4:     //$(this) is the current hover cell jQuery Object.
   5:     //$dataRows is a private jGuery variable holding all data rows
   6:     //$column is a jQuery local variable holds all cells on the same column (having same cellIndex) as current cell
   7:     
   8:     //get all cells in the current row including current hovering cell.
   9:     var $cells = $(this).siblings().andSelf();
  10:     
  11:     //Accessing additional data sent to the event handler.
  12:     var index = e.data.cellIndex+1;
  13:     
  14:     //Equation to select cells of the same column.
  15:     var eq = ':nth-child('+index+')';
  16:     
  17:     //Column Cells
  18:     var $column =  $dataRows.children(eq);
  19:     
  20:     //Attache rowHoverClass to each cell.
  21:     $cells.each(function(){
  22:         if(notEmptyOrNull(opts.rowHoverClass) && !$(this).hasClass(opts.rowHoverClass))
  23:             $(this).addClass(opts.rowHoverClass);
  24:     });
  25:     
  26:     //Attache columnHoverClass to each cell on the column.   
  27:     $column.each(function(){
  28:         if(notEmptyOrNull(opts.columnHoverClass) && !$(this).hasClass(opts.columnHoverClass))
  29:             $(this).addClass(opts.columnHoverClass);
  30:     });
  31:     
  32:     //If cellHoverClass Applied, remove columnHoverClass from current hover cell.
  33:     if(notEmptyOrNull(opts.cellHoverClass) && !$(this).hasClass(opts.cellHoverClass)){
  34:         $(this).removeClass(opts.columnHoverClass);
  35:         $(this).addClass(opts.cellHoverClass);
  36:     }
  37: };
  38: //mouseout event handler 
  39: function cellOut(e)
  40: {
  41:     //$(this) is the current hover cell jQuery Object.
  42:     //$dataRows is a private jGuery variable holding all data rows
  43:     //$column is a jQuery local variable holds all cells on the same column (having same cellIndex) as current cell
  44:     
  45:     //get all cells in the current row including current hovering cell.
  46:     var $cells = $(this).siblings().andSelf();
  47:     
  48:     //Accessing additional data sent to the event handler.
  49:     var index = e.data.cellIndex+1;
  50:     
  51:     //Equation to select cells of the same column.
  52:     var eq = ':nth-child('+index+')';
  53:     
  54:     //Column Cells
  55:     var $column =  $dataRows.children(eq);
  56:     
  57:     //Remove rowHoverClass from each cell in the current row.
  58:     $cells.each(function(){
  59:         if(notEmptyOrNull(opts.rowHoverClass) && $(this).hasClass(opts.rowHoverClass))
  60:             $(this).removeClass(opts.rowHoverClass);
  61:     });
  62:     
  63:     //Remove columnHoverClass from each cell in the current column.
  64:     $column.each(function(){
  65:         if(notEmptyOrNull(opts.columnHoverClass) && $(this).hasClass(opts.columnHoverClass))
  66:             $(this).removeClass(opts.columnHoverClass);
  67:     });
  68:     
  69:     //Remove cellHoverClass current cell.
  70:     if(notEmptyOrNull(opts.cellHoverClass) && $(this).hasClass(opts.cellHoverClass))
  71:         $(this).removeClass(opts.cellHoverClass);
  72: };
  73: //click event handler 
  74: function cellClick(e)
  75: {
  76:     //$(this) is the current hover cell jQuery Object.
  77:     //$dataRows is a private jGuery variable holding all data rows
  78:     
  79:     //Remove all attached css classes to be ready to apply rowSelectClass
  80:     $dataRows.each(function(){
  81:         $dataRows.children().each(function(){
  82:             if(notEmptyOrNull(opts.rowSelectClass) && $(this).hasClass(opts.rowSelectClass))
  83:                 $(this).removeClass(opts.rowSelectClass);
  84:             
  85:             if(notEmptyOrNull(opts.cellHoverClass) && $(this).hasClass(opts.cellHoverClass))
  86:                 $(this).removeClass(opts.cellHoverClass);
  87:                 
  88:             if(notEmptyOrNull(opts.cellSelectClass) && $(this).hasClass(opts.cellSelectClass))
  89:                 $(this).removeClass(opts.cellSelectClass);
  90:         });
  91:     });
  92:         
  93:     var $cells = $(this).siblings().andSelf();
  94:     
  95:     //Attache rowSelectClass to current selected row.
  96:     $cells.each(function(){
  97:         if(notEmptyOrNull(opts.rowSelectClass) && !$(this).hasClass(opts.rowSelectClass))
  98:             $(this).addClass(opts.rowSelectClass);
  99:     });
 100:     
 101:     if(notEmptyOrNull(opts.cellSelectClass) && !$(this).hasClass(opts.cellSelectClass)){
 102:         $(this).removeClass(opts.rowSelectClass);
 103:         $(this).removeClass(opts.columnHoverClass);
 104:         $(this).removeClass(opts.columnSelectClass);
 105:         $(this).addClass(opts.cellSelectClass);
 106:     }
 107: };
 108:  
 109: function notEmptyOrNull(value){
 110:     return value != '' && value != null;
 111: };

jQuery provided simplicy to the code, and ease of use as well. Reaching to the element you want is no more issue. Really you can do more with less code.

You can download the code [56.61] , and view the demos [demo 1] & [demo 2]

kick it on DotNetKicks.com

Comments (1) -

satish
satish United States on 10/5/2008 3:53 PM hi moses ,
     i am trying to create the inline edit gridview (i am jus trying to play around with the gridview and jquery).wat i was trying to do in the key down or mouseover i am ejecting the textbox instead of label of watever control there.. but on the back i need to find the cell index or the rowID so tat i can save the value back to the dataset.. how can i do tat.. do u have any idea on it

Pingbacks and trackbacks (3)+

Comments are closed