HTML Table Filter Generator: editable AJAX table

This demo shows how to implement an advanced editable table by using the AJAX capabilities of the jQuery library. The filters are refreshed everytime the table content is loaded.

To make the table cells editable, you need to install the ezEditTable extension, enable the editable property and configure the ezEditTable configuration object (ezEditTable_config).

Instructions: Double-click on a cell on or press Enter key to open the cell editor.

Loading data...
Id Name Email Start Date Salary Active
Loading...
 
Imported javascript files:
  1. <script type="text/javascript" language="javascript" src="TableFilter/tablefilter_all.js"></script>  
  2. <script type="text/javascript" language="javascript" src="includes/jquery-1.7.2.min.js"></script>  
Configuration object and AJAX logic:
  1.   // filters configuration  
  2.   var config = {  
  3.     grid_layout: true,  
  4.     grid_width: '840px',  
  5.     sort: true,  
  6.     alternate_rows: true,  
  7.     rows_counter: true,  
  8.     mark_active_columns: true,  
  9.     loader: true,  
  10.     loader_html: '<img src="TableFilter/TF_Themes/SkyBlue/images/img_loading.gif" alt="">',  
  11.     loader_css_class: 'myLoader',  
  12.     btn_reset: true,  
  13.     status_bar: true,  
  14.     col_1: 'select',  
  15.     col_2: 'select',  
  16.     col_5: 'select',  
  17.     remember_grid_values: true,  
  18.     remember_page_number: true,  
  19.     col_width: ['50px''270px''210px''80px''80px''60px'],  
  20.     paging: true,  
  21.     paging_length: 15,  
  22.     on_filters_loaded: function(o){  
  23.       if(o.paging){ tf_Id('paging').checked = true; }  
  24.     },  
  25.   
  26.     /* Custom data delegate for Active column checkbox */  
  27.     custom_cell_data_cols: [5],  
  28.         custom_cell_data: function(o, c, i){  
  29.             if(i === 5){  
  30.                 var chk = c.getElementsByTagName('input')[0];  
  31.                 if(chk.checked) return 'yes';  
  32.                 else return 'no';  
  33.             }  
  34.         },  
  35.   
  36.         /* Sky Blue theme */  
  37.     themes: {  
  38.         name:['SkyBlueTheme'],  
  39.         src:['TableFilter/TF_Themes/SkyBlue/TF_SkyBlue.css'],  
  40.         description:['SkyBlue stylesheet']  
  41.     },  
  42.   
  43.         //Column resize feature  
  44.         extensions: {  
  45.             name:['ColumnsResizer'],  
  46.             src:['TableFilter/TFExt_ColsResizer/TFExt_ColsResizer.js'],  
  47.             description:['Columns Resizing'],  
  48.             initialize:[function(o){o.SetColsResizer();}]  
  49.         },  
  50.         col_resizer_all_cells: true,  
  51.   
  52.     // selection and edition require ezEditTable extension  
  53.         selectable: true,  
  54.         editable: true,  
  55.   
  56.         // ezEditTable extension configuration  
  57.         ezEditTable_config: {  
  58.         loadStylesheet: true,  
  59.             default_selection: 'both',  
  60.             editor_model: 'cell',  
  61.             cell_editors: [  
  62.                 { type: 'none' },  
  63.                 { type: 'input', attributes: [['title''First name and last name']] },  
  64.                 { type: 'input', attributes: [['title''email address']] },  
  65.                 { type: 'none' },  
  66.                 { type: 'input', attributes: [['maxLength', 10], ['title''10 digits max.\n numbers with 2 decimal places only']], css: 'alignRight' },  
  67.                 { type: 'boolean' }  
  68.             ],  
  69.             actions: {  
  70.                 'update': {  
  71.                     uri: 'php/employeeUpdate.php', submit_method: 'form', form_method: 'POST',  
  72.                     param_names: ['id''name''email''startdate''salary''active'],  
  73.                     on_after_submit: function (o) {  
  74.                         ajax.isRefreshed = false;  
  75.                         // selected row index is stored  
  76.                         ajax.activeRowIndex = o.Selection.GetActiveRow().rowIndex;  
  77.                     // rows are loaded  
  78.                     ajax.loadContent();  
  79.                     }  
  80.                 },  
  81.                 'insert': {  
  82.                     uri: 'php/employeeInsert.php', submit_method: 'form', form_method: 'POST',  
  83.                     param_names: ['id''name''email''startdate''salary''active'],  
  84.                     default_record: ['''Employee name...''employee@email.com''2011-01-01''0.00''<input type="checkbox" checked="">'],  
  85.                     on_after_submit: function (o) {  
  86.                         ajax.isRefreshed = false;  
  87.                         // selected row index is stored  
  88.                         ajax.activeRowIndex = o.Selection.GetActiveRow().rowIndex;  
  89.                     // rows are loaded  
  90.                     ajax.loadContent();  
  91.                     }  
  92.                 },  
  93.                 'delete': {  
  94.                     uri: 'php/script.deleteEmployee.php', submit_method: 'script', bulk_delete: false,  
  95.                     param_names: ['id'],  
  96.                     on_after_submit: function (o) {  
  97.                         ajax.isRefreshed = false;  
  98.                     // rows are loaded  
  99.                     ajax.loadContent();  
  100.                     }  
  101.                 }  
  102.             },  
  103.   
  104.         //Callback triggered when a new row element is added  
  105.             on_added_dom_row: function (o) {  
  106.                 //TF total rows nb needs to be re-calculated  
  107.                 tf.nbRows = tf.GetRowsNb();  
  108.             },  
  109.   
  110.             //Data validation delegate, the ezEditTable script does not provide data validation tools  
  111.             validate_modified_value: function (o, colIndex, oldVal, newVal, cell, editor) {  
  112.                 if (colIndex == 2 && oldVal != newVal) {  
  113.                     if (!et_ValidateEmail(newVal)) {  
  114.                         alert('Please insert a valid email!');  
  115.                         return false;  
  116.                     } else return true;  
  117.                 }  
  118.                 else if (colIndex == 4 && oldVal != newVal) {  
  119.                     if (!et_IsNumber(newVal)) {  
  120.                         alert('Please insert a valid number with 2 decimal places!');  
  121.                         return false;  
  122.                     } else return true;  
  123.                 }  
  124.                 else return true;  
  125.             }  
  126.         }  
  127.   
  128.   
  129. //jQuery AJAX  
  130. var ajax = {  
  131.     isRefreshed: false,  
  132.     loadContent: function () {  
  133.         if (this.isRefreshed) { return; }  
  134.         // loading message  
  135.         $('#loadLabel').html('Loading data...');  
  136.         // AJAX call  
  137.         this.load('php/getEmployees.php');  
  138.     },  
  139.     load: function(uri){  
  140.         var xhr = $.ajax({  
  141.             url: uri + '?r='new Date().getTime(),  
  142.             context: $('#demo tbody'),  
  143.             type: 'GET',  
  144.             dataType: 'html'  
  145.          })  
  146.         .done(function (data) {  
  147.             // inject html table rows  
  148.             this.html(data);  
  149.             // loading message is cleared  
  150.             $('#loadLabel').html('');  
  151.   
  152.             // filters need to be refreshed after  
  153.             // table content is loaded  
  154.             if (tf) {  
  155.                 // temp hack to make the refresh filters feature  
  156.                 // work correctly when paging is on. This will be  
  157.                 // fixed in next release  
  158.                 if(tf.paging){ tf.paging = false; }  
  159.                 // total rows number is recalculated  
  160.                 tf.nbRows = tf.GetRowsNb();  
  161.                 // filters are refreshed  
  162.                 tf.RefreshFiltersGrid();  
  163.                 // paging is reset if on  
  164.                 if(!tf.paging && tf_Id('paging').checked){  
  165.                   tf.RemovePaging();  
  166.                   tf.paging = true;  
  167.                   tf.SetPaging();  
  168.                 }  
  169.                 // reapply alternating backgrounds  
  170.                 tf.SetAlternateRows();  
  171.   
  172.                 // ezEditTable created, modified, deleted rows arrays are reset  
  173.                 tf.ezEditTable.Editable.modifiedRows = [];  
  174.                 tf.ezEditTable.Editable.addedRows = [];  
  175.                 tf.ezEditTable.Editable.deletedRows = [];  
  176.                 //Selection is reapplied if any  
  177.                 if(ajax.activeRowIndex){  
  178.                   tf.ezEditTable.Selection.SelectRowByIndex(ajax.activeRowIndex);  
  179.                 }  
  180.                 //Page is also reselected  
  181.                 if(tf.paging && tf.currentPageNb > 0){  
  182.                   tf.SetPage(tf.currentPageNb);  
  183.                 }  
  184.                 ajax.isRefreshed = true;  
  185.             } else {  
  186.                 // first time rows are loaded filters are instantiated  
  187.                 tf = new TF('demo', config);  
  188.                 tf.Init();  
  189.             }  
  190.         })  
  191.         .fail(function(jqXHR, textStatus){  
  192.             $('#loadLabel').html(textStatus);  
  193.             this.html('Ouups an error occured! Data could not be loaded!');  
  194.         });  
  195.     }  
  196.   };  
  197.   
  198.   //Validation functions for cell editors  
  199.   function et_ValidateEmail(email) {  
  200.       var reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;  
  201.       return reg.test(email);  
  202.   }  
  203.   
  204.   function et_IsNumber(val) {  
  205.       var isNumber = /^\d+\.\d{2}$/;  
  206.       return isNumber.test(val);  
  207.   }  
  208.   
  209.   var tf; //global TF instance  
  210.   
  211.   $(function(){  
  212.     // table rows are loaded when page is ready  
  213.     ajax.loadContent();  
  214.   });  
PHP page serving the HTML table rows:
  1. connect_db();  
  2. $query = mysql_query("SELECT ID, NAME, EMAIL, STARTDATE, SALARY, ACTIVE".  
  3.     " FROM ".TBL_DEMO_EMPLOYEE." WHERE DELETED = 0".  
  4.     " ORDER BY ID DESC LIMIT 0, 30");  
  5.   
  6. while($row = mysql_fetch_row($query)){  
  7.     $id =  $row[0];  
  8.     $name = $row[1];  
  9.     $email = $row[2];  
  10.     $startdate = $row[3];  
  11.     $salary =  $row[4];  
  12.     $active =  $row[5];  
  13.     $checked = "";  
  14.     if($active == 1) $checked = "checked=\"checked\"";  
  15.   
  16.     echo("\n\t");  
  17.     echo("".$id."\n\t");  
  18.     echo("".$name."\n\t");  
  19.     echo("".$email."\n\t");  
  20.     echo("".$startdate."\n\t");  
  21.     echo("".$salary."\n\t");  
  22.     echo("<input type="\"checkbox\"" ".$checked."="">\n");  
  23.     echo("\n\t" );  
  24. }  
  25.   
  26. close_db();  
  27.    
Insert, update and delete operations are served by the same server-side pages detailed in this demo: editable-grid.php