Tabs/jeditable - not quite desired results

Tabs/jeditable - not quite desired results

SDCSDC Posts: 8Questions: 0Answers: 0
edited August 2009 in General
Hi all,

I really like the DataTables plugin, it gives you an awful lot out of the box, however I have hit a wall.

I want to use jEditable but have the ability to tab to the next field (and have it post the new val back to the server).

However, it will either advance properly but show the OLD value in the cell after advancing, or will set and show the value, but then advance and immediately UNSELECT the next cell.

Some code w/out dumping the whole thing on you:

I'm using these options:
[code]
oTable = $('#example').dataTable( {
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": "/cds/",
[/code]

The usual jEditable piece:

[code]
$('#example tbody td').editable( '/editor/', {
\
"callback": function( sValue, y ) {
/* Redraw the table from the new data on the server */
oTable.fnDraw();
var aPos = oTable.fnGetPosition( this );
oTable.fnUpdate( sValue, aPos[0], aPos[1] );
var row = oTable.fnGetData(aPos[0]);
$.post('/update/', { cdid: row[0], asin:row[1], artist:row[2], title:row[3], upc:row[4] });
},
"height": "14px"
} );
[/code]

Something to catch the tab:

[code]
$('#example tbody td').bind('keydown', function(evt) {
if(evt.keyCode==9) {
var vally = $(this).find('input').val(); // < - gets new val
var nextBox;
idx = $("#example tbody td").index(this);
nextBox = $("#example tbody td:eq(" +(idx+1)+")");
$(this).find("input").blur();
sendTheEdit(this, vally);
$(nextBox).click(); //Go to assigned next box
return false; //Suppress normal tab
}
});
[/code]

The send the edit bit....

[code]
function sendTheEdit(item, sValue)
{ /* Redraw the table from the new data on the server */
var aPos = oTable.fnGetPosition( item );
oTable.fnUpdate( sValue, aPos[0], aPos[1], false ); //- 'false' should help (no redraw)
// UPDATE sends first call...after this the get happens again...
// note, there are TWO calls to grab data following tha edit
var row = oTable.fnGetData(aPos[0]);
row[aPos[1]] = sValue;
$.post('/update/', { cdid: row[0], asin:row[1], artist:row[2], title:row[3], upc:row[4] });
}
[/code]

Sorry for all that verbiage. If I'm totally on the wrong track please let me know, or if a better approach is preferred. Google didn't quite get me there, any assistance is appreciated.

Replies

  • allanallan Posts: 63,516Questions: 1Answers: 10,472 Site admin
    Hi,

    Very nice idea. With the deselect issue that you are seeing, I very much suspect that it's due to the fnUpdate call in the jEditable callback. The tab moves on to the next cell and then the table is redrawn using the server data, thus resulting in the appearance of the cell being editable for a short time only.

    What might be needed is to move the 'making the next cell editable' into fnDrawCallback(), and use a flag to indicate which cell should be made editable once the draw has completed - what do you think? The other option is to not redraw the table at all during the update, and try to keep the server and client-side stuff separate at that point.

    Regards,
    Allan
  • SDCSDC Posts: 8Questions: 0Answers: 0
    Hi Allan,

    Thanks for the idea. I did try the 'click the cell in fnDrawCallback()', unfortunately it doesn't click the cell...

    if (indexUpdate >= 0) {
    nextBox = $("#example tbody td:eq(" +(indexUpdate)+")");
    $(nextBox).click();
    indexUpdate = -1;
    }

    The index is passed around nice enough, and the $(nextBox).click() worked nice enough in another attempt. But here it doesn't seem to be taking effect. I also tried forcing update of the text (for the previous cell). This lasted a split second. I probably am just missing something in the callbacks/events/etc in the mix. I had a similar idea to just make the whole row editable on click and submit the update on an Enter keypress, maybe I'll go that route.
  • allanallan Posts: 63,516Questions: 1Answers: 10,472 Site admin
    Hi,

    Have you reapplied the jEditable event handlers before your call .click()? What happens when DataTables is using server-side processing is that it recreates the DOM elements on each draw, so any events attached to the old table are lost, and need to be replaced.

    Allan
  • SDCSDC Posts: 8Questions: 0Answers: 0
    Thanks. I did try that, but it is still doing the show the new value for a second and then flash back to the previous val. It's odd...
  • SDCSDC Posts: 8Questions: 0Answers: 0
    D'oh!

    Scratch that. I misinterpreted what you said.

    Works fine now. Thanks for the help (and patience)!
  • nreddignreddig Posts: 1Questions: 0Answers: 0
    edited February 2011
    This thread was excellent. I've been able to implement the tab feature in the jeditable Data Tables so it can behave like excel in a way. However I am at the same place SDC was in Aug 2009. You hit tab. It updates the cell and moves to the next cell. However the old cell then switches back to the older value. If I refresh from the server the data actually went in but the user is not aware unless they refresh the page.

    SDC seems to understand what you mean, Allan, by "reapplied the jEditable event handlers before your call .click()?"

    However that solution is not clear to me.

    What goes between lines 8 and 9 in SDC's "Catch the tab" code?

    Here's my code which is nearly identical. I just don't understand what you mean by reapplied the JEditable event handlers.

    [code]

    $(document).ready(function() {

    /* Init DataTables */

    var oTable = $('#example').dataTable( {

    "fnDrawCallback": function() {
    $('.edit').editable( 'js/editable_ajax.php', {

    "submitdata": function ( value, settings ) {
    return {
    "row_id": this.parentNode.getAttribute('id'),
    "col_id": this.getAttribute('id'),
    "column": oTable.fnGetPosition( this )[2]
    };
    },
    "height": "20px"
    } );

    $('.edit').bind('keydown', function(evt) {
    if(evt.keyCode==9) {
    var vally = $(this).find('input').val(); // < - gets new val
    var nextBox;
    idx = $("#example tbody td").index(this);
    arow_id=this.parentNode.getAttribute('id');
    acol_id=this.getAttribute('id');
    acolumn=oTable.fnGetPosition( this )[2];
    oldBox = $("#example tbody td:eq(" +(idx)+")");
    nextBox = $("#example tbody td:eq(" +(idx+1)+")");
    $(this).find("input").blur();
    sendTheEdit(this, vally,arow_id,acol_id,acolumn);
    //What goes here????
    $(nextBox).click(); //Go to assigned next box

    return false; //Suppress normal tab
    }
    });
    [/code]
  • allanallan Posts: 63,516Questions: 1Answers: 10,472 Site admin
    Hi nreddig,

    The good news is that I think we can simplify the code a bit. I also think we can improve it a bit as well (tabbing the the next line for example). The bad news - well hopefully there is none... :-). This code seems to work okay for me in my test setup:

    [code]
    $(document).ready(function() {
    var oTable;

    $('.edit').editable( 'js/editable_ajax.php', {
    "onblur" : "submit",
    "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'),
    "col_id": this.getAttribute('id'),
    "column": oTable.fnGetPosition( this )[2]
    };
    },
    "height": "14px"
    } );

    $('.edit').bind('keydown', function(evt) {
    if(evt.keyCode==9) {
    /* Submit the current element */
    $('input', this)[0].blur();

    /* Activate the next element */
    if ( $(this).next('.edit').length == 1 )
    {
    $(this).next('.edit').click();
    }
    else if ( $('.edit', $(this.parentNode).next()).length > 0 )
    {
    $('.edit:eq(0)', $(this.parentNode).next()).click();
    }
    return false;
    }
    } );

    oTable = $('#example').dataTable();
    });
    [/code]
    Let me know how you get on!

    Regards,
    Allan
This discussion has been closed.