JAVASCRIPT   21
FooTable Editable Plugin
Guest on 17th September 2023 06:13:02 AM


  1. /*!
  2.  * FooTable Editable Plugin - Awesome Responsive FooTables That Are Editable
  3.  * Version : 0.1
  4.  * Author: Jake Drew - http://www.jakemdrew.com
  5.  *
  6.  * Requires jQuery - http://jquery.com/
  7.  * Requires FooTable http://themergency.com/footable
  8.  *
  9.  * FooTable Editable Copyright Jake Drew
  10.  *
  11.  * Released under the MIT license
  12.  * You are free to use FooTable Editable in commercial projects as long as this copyright header is left intact.
  13.  *
  14.  * Date: 2 Jul 2013
  15.  */
  16.  
  17. (function ($, w, undefined) {
  18.     if (w.footable == undefined || w.footable == null)
  19.         throw new Error('Please check and make sure footable.js is included in the page and is loaded prior to this script.');
  20.  
  21.     var defaults = {
  22.         serverTableName: undefined,
  23.         dataHandlerURL: "demo",
  24.                 autoLoad: false,
  25.         createDetail:
  26.             function (element, data) {
  27.                 var groups = { '_none': { 'name': null, 'data': [] } };
  28.                 for (var i = 0; i < data.length; i++) {
  29.                     var groupid = data[i].group;
  30.                     if (groupid != null) {
  31.                         if (!(groupid in groups))
  32.                             groups[groupid] = { 'name': data[i].groupName, 'data': [] };
  33.  
  34.                         groups[groupid].data.push(data[i]);
  35.                     } else {
  36.                         groups._none.data.push(data[i]);
  37.                     }
  38.                 }
  39.  
  40.                 var table = $(element).closest('table');
  41.  
  42.                 for (var group in groups) {
  43.                     if (groups[group].data.length == 0) continue;
  44.                     if (group != '_none') element.append('<h4>' + groups[group].name + '</h4>');
  45.  
  46.                     for (var j = 0; j < groups[group].data.length; j++) {
  47.                         var separator = (groups[group].data[j].name) ? ':' : '';
  48.  
  49.                         //check for html input tags or img tags
  50.                                                 var tagTest = '<td>' + groups[group].data[j].display + '</td>';
  51.                                                 //if (groups[group].data[j].display.substring(0, 6) == "<input" ||
  52.                                                 //    groups[group].data[j].display.substring(0, 4) == "<img") {
  53.                                                 if($(tagTest).children().length > 0) {
  54.                             element.append('<div><strong>' + groups[group].data[j].name + '</strong>' + separator + ' ' + groups[group].data[j].display + '</div>');
  55.                         }
  56.                         else {
  57.                             if ($.data(w.footable, $(table).attr('id') + '_fooEditableCols').indexOf(groups[group].data[j].name) >= 0) {
  58.                                 element.append('<div><strong>' + groups[group].data[j].name + '</strong>' + separator + ' <input type="text" value="' + groups[group].data[j].display + '"/></div>');
  59.                             }
  60.                             else {
  61.                                 element.append('<div><strong>' + groups[group].data[j].name + '</strong>' + separator + ' <input type="text" readonly value="' + groups[group].data[j].display + '"/></div>');
  62.                             }
  63.                         }
  64.                     }
  65.                 }
  66.                 if ($(element).text() == "") {
  67.                     $(element).closest('tr').prev().removeClass('footable-detail-show');
  68.                     $(element).closest('tr').remove();
  69.                 }
  70.             },
  71.  
  72.             parsers: {
  73.                 numeric: function (cell) {
  74.                     var val = $(cell).data('value') || $(cell).text().replace(/[^0-9.-]/g, '');
  75.                     val = parseFloat(val);
  76.                     if (isNaN(val)) val = 0;
  77.                     return val;
  78.                 },
  79.                 JSONDate: function (cell) {
  80.                     if (String(cell).substring(0, 6) == '/Date(') {
  81.                         dt = new Date(parseInt(String(cell).substring(6)));
  82.                                                 d = dt.getDate(); m =  dt.getMonth() + 1; yy = dt.getFullYear();
  83.                                                 cell = m + '/' + d + '/' +  yy;
  84.                     }
  85.                     return cell;
  86.                 },
  87.                                 prettyDate: function (cell) {
  88.                                         var dt = Date.parse(cell);
  89.                     if (isNaN(dt)==false) {
  90.                                                 dt = new Date(dt);
  91.                                                 d = dt.getDate(); m =  dt.getMonth(); yy = dt.getFullYear();
  92.                                                 cell = m + '/' + d + '/' +  yy;
  93.                     }
  94.                     return cell;
  95.                 }
  96.             }
  97.     };
  98.  
  99.     function makeColsFooEditable(table) {
  100.         $(table).find('th').each(function (index) {
  101.             if ($(this).hasClass("fooEditable")) {
  102.                 index += 1;
  103.                 $('td:nth-child(' + index + ')').attr('contentEditable', true);
  104.             }
  105.         });
  106.     }
  107.  
  108.     function getButtonIndexes(table) {
  109.         //finds all fields defined data-ft-buttons= Add or Delete or both
  110.         //only creates the collection one time.
  111.         var buttonIndexes = $.data(w.footable, $(table).attr('id') + '_buttonIndexes');
  112.  
  113.         if (buttonIndexes === undefined) {
  114.  
  115.             buttonIndexes = {};
  116.             buttonIndexes.addCols = new Array();
  117.             buttonIndexes.deleteCols = new Array();
  118.             buttonIndexes.buttonCols = new Array();
  119.             buttonIndexes.buttonColCt = 0;
  120.  
  121.             $(table).find('th').each(function (index) {
  122.                 var buttons = $(this).attr('data-ft-buttons');
  123.                 if (buttons != undefined) {
  124.                     buttonIndexes.buttonCols.push(index);
  125.                     if (buttons.indexOf('Add') >= 0) {
  126.                         buttonIndexes.addCols.push(index);
  127.                     }
  128.                     if (buttons.indexOf('Delete') >= 0) {
  129.                         buttonIndexes.deleteCols.push(index);
  130.                     }
  131.                     buttonIndexes.buttonColCt++;
  132.                 }
  133.             });
  134.  
  135.             $.data(w.footable, $(table).attr('id') + '_buttonIndexes', buttonIndexes);
  136.         }
  137.         return buttonIndexes;
  138.     }
  139.  
  140.     function addFooRowButtons(table) {
  141.         //This function does NOT add buttons to the footable-row-detail rows
  142.         //(see fooNewRecord-Populated bind below)
  143.         var buttons = getButtonIndexes(table);
  144.         if (buttons != undefined && $(this).is(":visible")) {
  145.             $(table).find('tr').not(':first, .footable-row-detail').each(function () {
  146.                 addButtonsToRow(this, buttons);
  147.             });
  148.         }
  149.  
  150.     }
  151.  
  152.     function addButtonsToRow(row, buttons) {
  153.         if ($(row).hasClass('fooNewRecord')) {
  154.             $(buttons.addCols).each(function (i) {
  155.                 if ($(row).find('td').eq(buttons.addCols[i]).length > 0) {
  156.                     $(row).find('td').eq(buttons.addCols[i]).each(function () {
  157.                         if ($(this).find('input[type="button"][value="Add"]').length <= 0) {
  158.                             $(this).append('<input class="footableButton" type="button" value="Add" />');
  159.                         }
  160.                     });
  161.                 }
  162.                 else {
  163.                     $(row).append('<td><input class="footableButton" type="button" value="Add" /></td>');
  164.                 }
  165.             });
  166.         }
  167.         else {
  168.             $(buttons.deleteCols).each(function (i) {
  169.                 if ($(row).find('td').eq(buttons.deleteCols[i]).length > 0) {
  170.                     $(row).find('td').eq(buttons.deleteCols[i]).each(function () {
  171.                         if ($(this).find('input[type="button"][value="Delete"]').length <= 0) {
  172.                             $(this).append('<input class="footableButton" type="button" value="Delete" />');
  173.                         }
  174.                     });
  175.                 }
  176.                 else {
  177.                     $(row).append('<td><input class="footableButton" type="button" value="Delete" /></td>');
  178.                 }
  179.             });
  180.         }
  181.     }
  182.  
  183.     function addButtonsToDetailRow(detailRow, buttons) {
  184.         var row = $(detailRow).prev();
  185.         var detailDiv = $(detailRow).find('.footable-row-detail-inner');
  186.         var addButtonColVisible = $(row).find('input[type="button"][value="Add"].footableButton').is(":visible");
  187.         var deleteButtonColVisible = $(row).find('input[type="button"][value="Delete"].footableButton').is(":visible");
  188.         var newRecordRow = $(row).hasClass('fooNewRecord');
  189.  
  190.         if (row.hasClass('fooNewRecord')) {
  191.             if (!addButtonColVisible && buttons.addCols.length >= 0) {
  192.                 if ($(detailDiv).find('input[type="button"][value="Add"]').length <= 0) {
  193.                     $(detailDiv).append('<input class="footableButton" type="button" value="Add" />');
  194.                     $(detailDiv).find('input[type="button"][value="Delete"].footableButton').remove();
  195.                 }
  196.             }
  197.         }
  198.         else {
  199.             if (!newRecordRow && !deleteButtonColVisible && buttons.deleteCols.length >= 0) {
  200.                 if ($(detailDiv).find('input[type="button"][value="Delete"]').length <= 0) {
  201.                     $(detailDiv).append('<input class="footableButton" type="button" value="Delete" />');
  202.                     $(detailDiv).find('input[type="button"][value="Add"].footableButton').remove();
  203.                 }
  204.             }
  205.         }
  206.     }
  207.  
  208.     function processCommand(target, command) {
  209.         var tId = $(target).closest('table').attr('id');
  210.  
  211.         var curRow = getCurrentRow(target);
  212.  
  213.         //Do not process update transactions on a new record
  214.         if ($(curRow).hasClass('fooNewRecord') && $(target).attr('type') != 'button') return;
  215.  
  216.         var updateRecord = {};
  217.         updateRecord.command = command;
  218.         updateRecord.table = $.data(w.footable, tId + '_serverTableName');
  219.  
  220.         if (command == "Load") {
  221.             //send the updateRecord to the server via AJAX
  222.             transportData(target,updateRecord);
  223.             return;
  224.         }
  225.                
  226.         /*All fields are sent for command=add, only id fields for command=delete.*/
  227.         $(curRow).find('td').each(function () {
  228.             var fieldName = $.data(w.footable, tId + '_colNames')[$(this).index()];
  229.             var fieldIsVisible = $(this).is(":visible");
  230.             var fieldIsControl = $.data(w.footable, tId + '_colControlType')[$(this).index()];
  231.                         var fieldIsIdCol = $.data(w.footable, tId + '_idColIndexes').indexOf($(this).index()) >= 0;
  232.                        
  233.             if (command == 'Add' || fieldIsIdCol) {
  234.                 //input vals are always populated in corresponding td.
  235.                 if (fieldIsControl === undefined) updateRecord[fieldName] = $(this).text().trim();
  236.                 else {
  237.                     var ctlVal = $(this).find('input').val().trim();
  238.                     if (ctlVal != "true") ctlVal = "false";
  239.                     updateRecord[fieldName] = ctlVal;
  240.                 }
  241.             }
  242.  
  243.         });
  244.  
  245.         if (command == 'Update') {
  246.                        
  247.             var updatedFieldName = $.data(w.footable, tId + '_colNames')[$(target).index()];
  248.             var updatedFieldValue;
  249.                         var updatedFieldOldValue = $.data(target, 'oldValue');
  250.                        
  251.             if ($(target).is("input[type='text']")) {
  252.                 updatedFieldName = $(target).closest('div').text().trim().slice(0, -1);
  253.                 updatedFieldValue = $(target).val();
  254.             }
  255.                         else if($.data(w.footable, tId + '_colControlType')[$(target).index()] !== undefined) {
  256.                                 var ctl = $(target).find('input')
  257.                                 var ctlVal = ctl.val();
  258.                 if (ctlVal != "true") ctlVal = "false";
  259.                 updatedFieldValue = ctlVal;
  260.                                 updatedFieldOldValue = !ctlVal;
  261.                         }
  262.             else {
  263.                 updatedFieldValue = $(target).text();
  264.             }
  265.  
  266.             updateRecord.updatedFieldName = updatedFieldName;
  267.             updateRecord.updatedFieldValue = updatedFieldValue;
  268.             updateRecord.updatedFieldOldValue = updatedFieldOldValue;
  269.         }
  270.  
  271.         //send the updateRecord to the server via AJAX
  272.         transportData(target,updateRecord);
  273.     }
  274.  
  275.     function transportData(target, updateRecord) {  
  276.         var tId = $(target).closest('table').attr('id');
  277.                 var dataHandlerURL = $.data(w.footable, tId + '_dataHandlerURL')
  278.                
  279.                 //Do nothing mode...
  280.                 if (dataHandlerURL == '') return;
  281.                
  282.                 //Do not make ajax call for demo mode...
  283.         if (dataHandlerURL == 'demo' || updateRecord === undefined) {
  284.                         alert("Demo Mode:\r\nThe following JSON data would be sent to the server: \r\n" + JSON.stringify(updateRecord));
  285.                         //mimic server response
  286.                         var response = {};
  287.                             response.response = "Success";
  288.                                 response.message = "Your message here";
  289.                                 response.data = undefined;
  290.                         alert("Demo Mode:\r\nThe server responded: \r\n" + JSON.stringify(response));
  291.                         processServerResponse(target, JSON.stringify(response), updateRecord);
  292.             return;
  293.         }
  294.        
  295.         //Send the updateRecord to the server via AJAX for valid command.
  296.         $.ajax({
  297.             type: "POST",
  298.             url: $.data(w.footable, tId + '_dataHandlerURL'),
  299.             contentType: "application/json; charset=uft-8",
  300.             data: JSON.stringify(updateRecord)
  301.         })
  302.         .done(function (data) { processServerResponse(target, data, updateRecord); })
  303.         .fail(function (msg) { alert("error: " + JSON.stringify(msg.responseText)); });
  304.         //.always(function (msg) { alert("complete" + JSON.stringify(msg)); });
  305.     }
  306.        
  307.         function tryJSONParse(data){
  308.                 try {
  309.             p = JSON.parse(data);
  310.             data = p;
  311.         } catch (e) {
  312.             // data was not valid json
  313.         }
  314.                 finally{
  315.                         return data;
  316.                 }
  317.         }
  318.        
  319.     function processServerResponse(target, data, updateRecord) {
  320.                 //the data response variable can be json or a valid javascript object...
  321.         data = tryJSONParse(data);
  322.                 data.responseData = tryJSONParse(data.responseData);
  323.                
  324.         var table = $(target).closest('table');
  325.         var curRow = getCurrentRow(target);
  326.         var nextRow = $(curRow).next();
  327.  
  328.         //handle processing for fooButtons
  329.         if ($(target).hasClass('footableButton') && data.response != "Error") {
  330.             if (updateRecord.command == "Add") {
  331.                 //convert new record to normal record.
  332.                 $(curRow).removeClass('fooNewRecord');
  333.                 $(curRow).find('input[type="button"][value="Add"].footableButton').remove();
  334.                 addButtonsToRow(curRow, getButtonIndexes(table));
  335.                 if ($(nextRow).hasClass('footable-row-detail')) addButtonsToDetailRow(nextRow, getButtonIndexes(this));
  336.  
  337.                 //Hide the curRow detail row, if showing
  338.                 if ($(curRow).hasClass('footable-detail-show')) {
  339.                     $(curRow).removeClass('footable-detail-show');
  340.                     $(nextRow).hide();
  341.                 }
  342.  
  343.             }
  344.             if (updateRecord.command == "Delete" && data.response == "Success") {
  345.                 deleteRow(curRow);
  346.             }
  347.         }
  348.  
  349.         //Handle processing AJAX server responses.
  350.         if (data.response == "Success") {
  351.             //Do nothing!
  352.         }
  353.         else if (data.response == "Load") {
  354.             deleteAllRows(table);
  355.             addRows(table, data.responseData);
  356.         }
  357.         else if (data.response == "Append") {
  358.             addRows(table, data.responseData);
  359.         }
  360.         else if (data.response == "Update") {
  361.             updateRow(curRow, data.responseData);
  362.         }
  363.         else if (data.response == "Delete") {
  364.             deleteRow(curRow);
  365.         }
  366.         else if (data.response == "DeleteAll") {
  367.             deleteAllRows(table);
  368.         }
  369.         else if (data.response == "Error") {
  370.             alert("The update was not successful\r\n" + data.message);
  371.  
  372.             if (updateRecord.command == 'Update') {
  373.                 //if a cell update fails, revert back to the previous value.
  374.                 var updateIndex = $.data(w.footable, $(ft.table).attr('id') + '_colNames').indexOf(updateRecord.updatedFieldName);
  375.                 $(target).closest('tr').find('td').eq(updateIndex)
  376.                     .text(updateRecord.updatedFieldOldValue);
  377.             }
  378.         }
  379.         else {
  380.             alert('Invalid server response! Response recieved: ' + data.response);
  381.         }
  382.  
  383.         checkNewEmptyRecord(table);
  384.     }
  385.  
  386.     function getCurrentRow(target) {
  387.         var curRow = $(target).closest('tr');
  388.         if ($(curRow).hasClass('footable-row-detail')) curRow = $(curRow).prev();
  389.         return curRow;
  390.     }
  391.  
  392.     function updateRow(row, rowData) {
  393.         var table = $(row).closest('table');
  394.         var rowTd = $(row).find('td');
  395.         $.each(rowData, function (name, value) {
  396.             var colIndex = $.data(w.footable, $(table).attr('id') + '_colNames').indexOf(name);
  397.             if (colIndex != -1) $(rowTd).eq(colIndex).text(value);
  398.         });
  399.     }
  400.  
  401.     function deleteRow(row) {
  402.         if ($(row).next().hasClass('footable-row-detail')) {
  403.             $(row).next().remove();
  404.         }
  405.         if ($(row).prev().hasClass('footable-detail-show')) {
  406.             $(row).prev().remove();
  407.         }
  408.         $(row).remove();
  409.     }
  410.  
  411.     function deleteAllRows(table) {
  412.         $(table).find('tbody > tr').not('.fooNewRecord').remove();
  413.     }
  414.  
  415.     function checkNewEmptyRecord(table) {
  416.         //Don't add multiple empty records to a table.
  417.         if ($(table).find('.fooNewRecord').length > 0) return;
  418.         if ($.data(w.footable, $(table).attr('id') + '_fooNewRecord').length <= 0) return;
  419.         //make a copy of the default new record and hide fields that should be hidden.
  420.         var newRec = $.data(w.footable, $(table).attr('id') + '_fooNewRecord').clone(true, true);
  421.         var headRowTd = $(table).find('th');
  422.         $(newRec).find('td').each(function (index) {
  423.             if (!$(headRowTd[index]).is(":visible")) {
  424.                 $(this).hide();
  425.             }
  426.         });
  427.         $(table).find('tbody').append(newRec);
  428.     }
  429.  
  430.     function addRows(table, tableRows) {
  431.         //exit if there are no rows to process.
  432.         if (tableRows === undefined) return;
  433.         //Assume tableRows is a JSON string and try to parse, if it is not already and object
  434.  
  435.         var tableTh = $(table).find('th');
  436.         var rows = "";
  437.         var fooButtonIndexes = getButtonIndexes(table);
  438.  
  439.         var ft = $(table).data('ft');
  440.  
  441.         $(tableRows).each(function () {
  442.             var tr = '<tr>';
  443.             var i = 0;
  444.             //Build valid tr's for row in tableRows
  445.             $.each(this, function (name, value) {
  446.                 //use any custom return parsers to parse the value for each new row's cell
  447.                 var retParser = tableTh.eq(i).attr('data-return-type');
  448.                 if (retParser != undefined) {
  449.                     var parser = ft.options.parsers[retParser];
  450.                     value = parser(value);
  451.                 }
  452.  
  453.                 var fieldIsControl = $.data(w.footable, $(table).attr('id') + '_colControlType')[i];
  454.                 if (fieldIsControl != undefined) {
  455.                     if (value == "true" || value ==true) value = '<input type="checkbox" checked="checked" />';
  456.                     else value = '<input type="checkbox" />';
  457.                 }
  458.                 //capture and add fooTable data-class values.
  459.                 var classes = "";
  460.                 var dataClass = $(tableTh).eq(i).attr('data-class');
  461.                 if (dataClass !== undefined) classes = ' class="' + dataClass + '" ';
  462.                 //handle hidden fields    
  463.                 var style = "";
  464.                 if (!$(tableTh).eq(i).is(":visible")) style = ' style="display:none;" ';
  465.                
  466.                 tr += '<td' + classes + style + '>' + value + '</td>';
  467.                 i++
  468.             });
  469.  
  470.             //add 1 empty td for each button column
  471.             $(fooButtonIndexes.buttonColCt).each(function () {
  472.                 tr += '<td></td>';
  473.             });
  474.             tr += '</tr>';
  475.             rows += tr;
  476.         });
  477.  
  478.         $(table).find('tbody').prepend(rows);
  479.         addFooRowButtons(table);
  480.         makeColsFooEditable(table);
  481.  
  482.         $(table).data('ft').bindToggleSelectors();
  483.         $(table).data('ft').resize();  //makes new rows display correct when fields are hidden.
  484.     }
  485.  
  486.         $.fn.ftEditable = function (target) {
  487.                 var e = {};
  488.                 e.processCommand = processCommand;
  489.                 e.transportData = transportData;
  490.                 e.processServerResponse  = processServerResponse;
  491.                 e.updateRow = updateRow;
  492.                 e.deleteRow = deleteRow;
  493.                 e.deleteAllRows = deleteAllRows;
  494.                 e.checkNewEmptyRecord = checkNewEmptyRecord;
  495.                 e.addRows = addRows;
  496.                 return e;
  497.         }
  498.        
  499.     function Editable() {
  500.                
  501.                 //Expose plugin features to w.footable
  502.                
  503.         var p = this;
  504.         p.name = 'Footable Editable';
  505.         p.init = function (ft) {
  506.                        
  507.             //save a reference to ft.
  508.             $(ft.table).data('ft', ft);
  509.                        
  510.             //capture any default over-rides by user
  511.             var tId = $(ft.table).attr('id');
  512.                        
  513.                         $.data(w.footable, tId + '_dataHandlerURL', ft.options.dataHandlerURL);
  514.             $.data(w.footable, tId + '_serverTableName', ft.options.serverTableName);
  515.                         $.data(w.footable, tId + '_autoLoad', ft.options.autoLoad);
  516.                        
  517.             $(ft.table).bind({
  518.                 'footable_initialized': function (e) {
  519.  
  520.                     //Get array of all the column names, indexes with class='id' and footableButtons
  521.                     var idColIndexes = new Array();
  522.                     var colNames = new Array();
  523.                     var fooEditableCols = new Array();
  524.                     //var expandCols = new Array;
  525.                     var colControlType = new Array();
  526.  
  527.                     $(ft.table).find('th').each(function (index) {
  528.                         var fieldName = $(this).text().trim();
  529.                         colNames.push(fieldName);
  530.  
  531.                         if ($(this).hasClass('fooEditable')) {
  532.                             fooEditableCols.push(fieldName);
  533.                         }
  534.  
  535.                         if ($(this).hasClass('fooId')) {
  536.                             idColIndexes.push(index);
  537.                         }
  538.  
  539.                         colControlType.push($(this).attr('data-ft-control'));
  540.  
  541.                     });
  542.                     //set global table specific variables
  543.                     $.data(w.footable, tId + '_colNames', colNames);
  544.                     $.data(w.footable, tId + '_idColIndexes', idColIndexes);
  545.                     $.data(w.footable, tId + '_fooEditableCols', fooEditableCols);
  546.                     $.data(w.footable, tId + '_fooNewRecord', $(ft.table).find('.fooNewRecord').clone(true, true));
  547.                     $.data(w.footable, tId + '_colControlType', colControlType);
  548.  
  549.                     //Populate the value property of checkboxes in the footable to true or false
  550.                     $(ft.table).on('change', 'input[type="checkbox"]', function (e) {
  551.                         var val = $(this).is(':checked');
  552.                                                 $(this).val(val);
  553.                                                 if(val) this.setAttribute("checked", "checked");
  554.                                                 else this.removeAttribute("checked");
  555.                                                 $(this).parent().trigger('td-cell-changed');
  556.                     });
  557.  
  558.                     //track each footable cell's old value to determine when a cell value changes.
  559.                     $(ft.table).on('focus', 'td', function () {
  560.                         $.data(this, 'oldValue', $(this).text());
  561.                     });
  562.  
  563.                     //fire custom event each time a footable cell value changes
  564.                     $(ft.table).on('blur', 'td', function (e) {
  565.                         if ($(this).text() != $.data(this, 'oldValue')) {
  566.                             $(this).trigger('td-cell-changed');
  567.                         }
  568.                     });
  569.  
  570.                     //if a footable cell value changes, create an update object to send to the server.
  571.                     $(ft.table).bind('td-cell-changed', function (e) {
  572.                         var buttons = getButtonIndexes(this);
  573.                                                 //Do not process update on data-ft-buttons columns
  574.                         if (buttons.buttonCols.indexOf($(e.target).index()) < 0) {
  575.                             processCommand(e.target, 'Update');
  576.                         }
  577.                     });
  578.  
  579.                     //must use on() function since input tags are dynamically created.
  580.                     $(ft.table).on('focus', 'input', function (e) {
  581.                         $.data(this, 'oldValue', $(this).val());
  582.                     });
  583.  
  584.                     //must use on() function since input tags are dynamically created.
  585.                     $(ft.table).on('change', 'input', function (e) {
  586.                         if ($(e.target).closest('tr').hasClass('footable-row-detail')) {
  587.                             //Always pass changes made to an input detail textbox to it's corr parent td
  588.                             var FieldName = $(e.target).closest('div').text().trim().slice(0, -1);
  589.                             var tdFieldIndex = $.data(w.footable, $(ft.table).attr('id') + '_colNames').indexOf(FieldName);
  590.  
  591.                             $(e.target).closest('tr').prev().find('td').eq(tdFieldIndex)
  592.                                 .text($.data(e.target, 'oldValue'))
  593.                                 .text($(e.target).val());
  594.  
  595.                             processCommand(e.target, 'Update');
  596.                         }
  597.                     });
  598.  
  599.                     $(ft.table).on('click', 'input[type="button"][value="Add"].footableButton', function (e) {
  600.                         processCommand(e.target, 'Add');
  601.                     });
  602.  
  603.                     $(ft.table).on('click', 'input[type="button"][value="Delete"].footableButton', function (e) {
  604.                         processCommand(e.target, 'Delete');
  605.                     });
  606.                 } //footable_initialized
  607.             }); //ft.table bind
  608.  
  609.             makeColsFooEditable(ft.table);
  610.             addFooRowButtons(ft.table);
  611.                        
  612.             //AutoLoad sends a load command each time a Footable is created.
  613.                         if($.data(w.footable, $(ft.table).attr('id') + '_autoLoad')) {
  614.                                 processCommand(ft.table, 'Load');
  615.                         }
  616.  
  617.             //Create event that fires after footable-row-detail-inner div has been populated.
  618.             $(ft.table).on('click', 'tr', function () {
  619.                 if (!$(this).hasClass('footable-row-detail')) {
  620.                     $(this).trigger('fooDetail-Populated');
  621.                 }
  622.             });
  623.  
  624.             //Add any footableButton's to a row's footable-row-detail-inner div
  625.             $(ft.table).bind('fooDetail-Populated', function (e) {
  626.                 addButtonsToDetailRow($(e.target).next(), getButtonIndexes(this));
  627.             });
  628.  
  629.  
  630.         } //p.init
  631.  
  632.     } // Editable()
  633.  
  634.     w.footable.plugins.register(new Editable(), defaults);
  635.  
  636. })(jQuery, window);

Raw Paste

Login or Register to edit or fork this paste. It's free.