Tabs/jeditable - not quite desired results
Tabs/jeditable - not quite desired results
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.
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.
This discussion has been closed.
Replies
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
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.
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
Scratch that. I misinterpreted what you said.
Works fine now. Thanks for the help (and patience)!
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]
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