DataTables and Jeditable with Tabbing (inline editing)

September 16, 2011 by Mike Henke    13 Comments
Posted under: jquery

The last couple weeks (off and on) I have been working on editing DataTables with jEditable. If you haven't seen Datatables, you should check it out. The examples are great and implementing is easy. Datatables makes changing any table layout into a dynamic sort and filter a breeze. You'll look like a Rockstar. With that said, we wanted to allow editing the cells in the table. The DataTables editing example was great but it forced the user to click a cell, change, press return to save, then repeat. We wanted to tab to for saving and going to the next cell. I kinda got it working using Tab key with JEditable fields but 1) on last column doesn't go to the next row, first cell AND 2) when after tab saves and goes to the next cell, it would be nice if all the text was highlighted. With that said, here is the sample code.

<script type="text/javascript"><!--
$(document).ready(function() {
   /* Init DataTables */
   var oTable = $('#example').dataTable();
   
   /* Apply the jEditable handlers to the table */
   $('td', oTable.fnGetNodes()).editable( '/index.cfm/futurepremiums/update', {
      "callback": function( sValue, y ) {
         var aPos = oTable.fnGetPosition( this );
         oTable.fnUpdate( sValue, aPos[0], aPos[1] );
      },
      "submitdata": function ( value, settings ) {
         return {
            "row_id": this.parentNode.getAttribute('id'),
            "column": oTable.fnGetPosition( this )[2]
         };
      },
      "height": "14px"
   });
   
   $('td.editbox').bind('keydown', function(event) {
if(event.keyCode==9) {
$(this).find("input").submit();
if ($(this).is(".lasteditbox")) {
$("td.editbox:first").click();
} else {
   $(this).next("td.editbox").click();
}
return false;
      }
   });
});
// -->
</script>

Then in the td tags for each cell, I added the class="editbox"

13 Comments + Add Comment

  • Mike Henke

    Now we want to use arrow keys to navigate forward, down, up, and backward so once I get that working I'll update this post.

  • John Madhavan-Reese

    You'll want an easy way to turn arrow-key navigation on and off, since most people expect arrow keys to move within the editable field, not necessarily to jump to new editable cells. But when you want to use arrow keys to navigate, it's certainly useful to have if you can enable/disable it easily.

    Also, you'll need to allow configurable tab direction (down or right). Shift-tab should move in the opposite direction. Enter should move in the same direction as tab.

  • Mike Henke

    Hi John, Yeah, after thinking about the navigation with arrows keys, we decided up/down would be nice but left/right might be unintuitive like you mentioned. Tab-shift is a great idea for backwards! Thanks

  • Tom Noel

    Mike this is great stuff! I am new to this approach and have two issues that are stumping me. I have taken what you have shown and plugged it in changing the table names to match mine. The edit portion is working on all columns including the checkbox columns which I don't want. I initially used the class="editbox" in the TDs, then discovered when I leave them out it made no difference. The saving function totally stumps me. I have no clue what to do with '/index.cfm/futurepremiums/update'. I am presuming that the index.cfm is what this page is built on. Can you provide a little more detail concerning the update? Thanks!


        /* Apply the jEditable handlers to the table */
        $('td', oBitTable.fnGetNodes()).editable( '/index.cfm/futurepremiums/update', {
        "callback": function( sValue, y ) {
        var aPos = oBitTable.fnGetPosition( this );
        oBitTable.fnUpdate( sValue, aPos[0], aPos[1] );
        },
        "submitdata": function ( value, settings ) {
        return {
        "row_id": this.parentNode.getAttribute('id'),
        "column": oBitTable.fnGetPosition( this )[2]
        };
        },
        "height": "12px"
        });
       
        $('td.editbox').bind('keydown', function(event) {
             if(event.keyCode==9) {
                $(this).find("input").submit();
                if ($(this).is(".lasteditbox")){
                   $("td.editbox:first").click();
                }
                else{
                    $(this).next("td.editbox").click();
                }
                return false;
           }
          });

  • Mike Henke

    Hi Tom,

    The /index.cfm/futurepremiums/update is the ajax call for the editted field to happen. Here is a dummy example that just returns the updated value with (server updated).

       <cffunction name="update">
          <cfsetting showDebugOutput="No">
          <cfset local.echo = params.value & " (server updated)" />
          <cfset renderText(local.echo)>
       </cffunction>

    Interesting about the editbox class. We did this a proof of concept, then proceeded with a different approach.

  • Ron Ventura

    Hi. I'm trying to implement something similar, but can't figure out what to do in the cfm page called on update. Currently, we have a text box for each field in the relevant table, with a single Add/Update button. When the button is clicked, a Javascript function is called which sets up a bunch of hidden form fields, and then resubmits the current page, which then determines what to do when it's reloaded. Ultimately it calls a Java method which executes a stored procedure which either adds the record, or updates it if a matching record is found in the database.

    Can I get Datatables to call the Javascript function on update? Do I put the update code into the "submitdata" function in the jQuery initialisation?

    Thanks.

  • Tom Noel

    This what I used. It makes each field editable and you press enter after changing the text to save. I haven't tried to setup the tab saving yet.

    <cfajaxproxy cfc="/cfc/com/validation" jsclassname="codesDAO"> Before the script tags.

          codesproxy = new codesDAO();
          var oBitTable = $('#table4').dataTable({
             "aoColumns": bColumns,
             "bStateSave": true,
             "bAutoWidth": false,
             "sDom": '<"top"f>rt<"bottom"l>',
             "iCookieDuration":minutes*60
             }).makeEditable({
             sUpdateURL: function ( value, settings ){
                         var cellname = $(this).attr('id');
                         var bitid = $(this).siblings("td:nth-child(2)").attr('id');
                         var labid = $(this).siblings("td:nth-child(1)").attr('id');
                         var seq = $(this).siblings("td:nth-child(2)").text();
                         var wuc = $(this).siblings("td:nth-child(3)").text();
                         var bitname = $(this).siblings("td:nth-child(4)").text();
                         var partno = $(this).siblings("td:nth-child(5)").text();
                         var qty = $(this).siblings("td:nth-child(6)").text();
                         var fsc = $(this).siblings("td:nth-child(8)").text();
                         var sentimds = $(this).siblings("td:nth-child(9)").text();
                         var user = $("#skin_username").text();
                         var hmVal = $(this).siblings("td:nth-child(7)").text();
                         var hm = codesproxy.getCodeId(
                            codeType = 'HOW_MAL',
                            codeValue = hmVal
                         );
                         var result = 0;
                         switch(cellname){
                            case('bitwuc'):
                               wuc = value;
                            break;
                            case('bitname'):
                               bitname = value;
                            break;
                            case('bitpartno'):
                               partno = value;
                            break;
                            case('bitqty'):
                               qty = value;
                            break;
                            case('howmal'):
                               var hmId = codesproxy.getCodeId(
                                  codeType = 'HOW_MAL',
                                  codeValue = value
                               );
                               hm = hmId;
                            break;
                            case('fsc'):
                               fsc = value;
                            break;
                            case('sentimds'):
                               sentimds = value;
                            break;
                         }
                         $.ajax({
                            url: 'cfc/com/ddrDAO.cfc',
                            data: {method:'updateDDRBitPiece',
                                     laborbitId:bitid,
                                     bitseq:seq,
                                     bitwuc:wuc,
                                     bitPartno:partno,
                                     fsc:fsc,
                                     bitname:bitname,
                                     sentimds:sentimds,
                                     howmal:hm,
                                     bitQty:qty,
                                     chgby:user,
                                     returnFormat:'json'
                                  },
                            dataType: 'json',
                            success: function(data){
                               alert('Saved!');
                            },
                       error: function(data) {
                               alert('Error');
                       },
                       complete: function(data) {
                       }
                         });
                    return (value);
                      }
          });

  • Mike Henke

    Ron - Tom is the man! I didn't get very far with this post since we changed gears.

  • Ravindra Ghatage

    Hi, I am Java programmar, dont know about php. And if i want to use this plugin , then what do i need to use instead of php call for .editable( '/index.cfm/futurepremiums/update').

  • Mike Henke

    You might have better luck asking the question on datatables forums. I would call your jsp page or the web service that would do the update.

  • Ravindra Ghatage

    @Mike, Solved the issue. Thanks.

  • Santosh

    Can i get a working example of this. I'm really bad in need of this. Thanks

  • Tom

    In order to have a working example you need a database table to hit against. If you have questions about specific pieces I can help some.

  • Got anything to say? Go ahead and leave a comment!