fnAddData, jeditable and keytable
fnAddData, jeditable and keytable
Hi,
I wonder if it's possible in dataTables to dynamically add a new row with fnAddData et makes keytable and jeditable working on this new row.
When I add a new item in textbox (which is in div.scan) and press return key to following code call server-side data and add a new row. But I don't know how to add this row in keytable and jeditable at the same time. I want to be able to modify the new row with jeditable but using functionality of keytable.
[code]
$("div.scan input").live("keypress", function(e) {
if (e.keyCode == 13) {
var ein = $(this).val();
$.getJSON("templates/warehouse_test_decoders/ajax/ein_details.php", {searchedEin : ein}, function(data) {
oTable.fnAddData( ["",data.ein, data.ein_desc, data.tech_diag, data.tech_comments, data.date, data.tech_name, data.headquarter,"","",""] );
});
$(this).val("");
}
})
[/code]
Any Idea?
I wonder if it's possible in dataTables to dynamically add a new row with fnAddData et makes keytable and jeditable working on this new row.
When I add a new item in textbox (which is in div.scan) and press return key to following code call server-side data and add a new row. But I don't know how to add this row in keytable and jeditable at the same time. I want to be able to modify the new row with jeditable but using functionality of keytable.
[code]
$("div.scan input").live("keypress", function(e) {
if (e.keyCode == 13) {
var ein = $(this).val();
$.getJSON("templates/warehouse_test_decoders/ajax/ein_details.php", {searchedEin : ein}, function(data) {
oTable.fnAddData( ["",data.ein, data.ein_desc, data.tech_diag, data.tech_comments, data.date, data.tech_name, data.headquarter,"","",""] );
});
$(this).val("");
}
})
[/code]
Any Idea?
This discussion has been closed.
Replies
What I would suggest is doing the fnAddData and then taking the return from that and adding the jEditable initialiser to make the new cells editable (http://datatables.net/api#fnAddData - it returns an array index which you can look up and use the node as a jQuery selector for jEditable).
Allan
Here is how it can be done with the return from fnAddData:
[code]
$(document).ready(function() {
/* Init DataTables */
var oTable = $('#example').dataTable();
/* Apply the jEditable handlers to the table */
$('td', oTable.fnGetNodes()).editable( '../examples_support/editable_ajax.php', {...} );
var aiData = oTable.fnAddData( [1, 2, 3, 4, 5] );
var oSettings = oTable.fnSettings();
$('td', oSettings.aoData[ aiData[0] ].nTr).editable( '../examples_support/editable_ajax.php', {...} );
} );
[/code]
The array aiData contains pointers to where the new row is in the internal DataTables data store (aoData) - so you can get the TR node (.nTr) from that and then perform any operation you want on it - in this case adding jEditable event listeners.
Would be nice if jEditable provided a $.live() option, and there are a few posts around the web saying how to do that, if you wanted to go that route, but this one should do nicely :-)
Regards,
Allan
This code is working to apply jeditable on new row on all td's. How can I apply it only , by example, td #5 and td #6.
And I want this to work with keytable and trigger jeditable on return keypress is this possible? I can't find the way to apply keytable to row added with fnAddData.
Here's the code I use for now:
[code]
$("div.scan input").live("keypress", function(e) {
if (e.keyCode == 13) {
var ein = $(this).val();
$.getJSON("templates/warehouse_test_decoders/ajax/ein_details.php", {searchedEin : ein}, function(data) {
var aiData = oTable.fnAddData( ["",data.ein, data.ein_desc, data.tech_diag, data.tech_comments, data.date, data.tech_name, data.headquarter,"","",""] );
var oSettings = oTable.fnSettings();
$("td", oSettings.aoData[ aiData[0] ].nTr).editable( "templates/warehouse_test_decoders/ajax/ein_details.php");
});
$(this).val("");
}
})
[/code]
Note: I did not put jeditable option in code for this example.
Any Idea?
[code]
$("td:eq(5)", oSettings.aoData[ aiData[0] ].nTr).editable("templates/warehouse_test_decoders/ajax/ein_details.php");
[/code]
What code are you using for KeyTable? I just recently updated the example code for jEditable with KeyTable to take into account jEditable 1.7.1 - the change can be found here: https://github.com/DataTables/KeyTable/blob/master/editing.html . If you are using a KeyTable action like that, you shouldn't need to add the jEditable handler with the fnAddData.
Regards,
Allan
[code]
$("div.scan input").live("keypress", function(e) {
if (e.keyCode == 13) {
var ein = $(this).val();
$.getJSON("templates/warehouse_test_decoders/ajax/ein_details.php", {searchedEin : ein}, function(data) {
var aiData = oTable.fnAddData( ["",data.ein, data.ein_desc, data.tech_diag, data.tech_comments, data.date, data.tech_name, data.headquarter,"","",""] );
var oSettings = oTable.fnSettings();
$("td:eq(0)", oSettings.aoData[ aiData[0] ].nTr).html(\'\');
$("td:eq(9)", oSettings.aoData[ aiData[0] ].nTr).addClass("edit_comments");
var keys = new KeyTable( {
"table": document.getElementById("example")
} );
/* Apply a return key event to each cell in the table */
keys.event.action( null, null, function (nCell) {
/* Block KeyTable from performing any events while jEditable is in edit mode */
keys.block = true;
if($(nCell).hasClass("edit_comments") == true){
/* Initialise the Editable instance for this table */
$(nCell).editable( "templates/tech/ajax/edit_comments.php", {
callback: function(value, settings) {
keys.block = false;
$(this).editable("destroy");
},
submit : "OK",
cancel : "Cancel",
indicator : "Saving...",
placeholder: " ",
"onblur": "cancel",
"onreset": function(){
/* Unblock KeyTable, but only after this "esc" key event has finished.
* Otherwise it will "esc" KeyTable as well
*/
$(nCell).editable("destroy");
setTimeout( function () {keys.block = false;}, 0);
}
} );
/* Dispatch click event to go into edit mode - Saf 4 needs a timeout... */
setTimeout( function () { $(nCell).click(); }, 0 );
}else{
keys.block = false;
}
} );
});
$(this).val("");
}
});
[/code]
[code]
function fnEditable ( nCell )
{
/* Block KeyTable from performing any events while jEditable is in edit mode */
keys.block = true;
/* Initialise the Editable instance for this table */
$(nCell).editable( "templates/tech/ajax/edit_comments.php", {
callback: function(value, settings) {
keys.block = false;
$(this).editable("destroy");
},
submit : "OK",
cancel : "Cancel",
indicator : "Saving...",
placeholder: " ",
"onblur": "cancel",
"onreset": function(){
/* Unblock KeyTable, but only after this "esc" key event has finished.
* Otherwise it will "esc" KeyTable as well
*/
$(nCell).editable("destroy");
setTimeout( function () {keys.block = false;}, 0);
}
} );
/* Dispatch click event to go into edit mode - Saf 4 needs a timeout... */
setTimeout( function () { $(nCell).click(); }, 0 );
}
$(document).ready( function () {
var oTable = $('#example').dataTable( {
"aoColumnDefs": [
{
"fnRender": function (o) {
return '';
},
"aTargets": [ 0 ]
},
{
"sClass": "edit_comments",
"aTargets": [ 9 ]
}
]
/* and whatever else initialisation is needed */
} );
var keys = new KeyTable( {
"table": document.getElementById("example"),
"datatable": oTable
} );
keys.event.action( 5, null, fnEditable ); /* Providing editing on the 6th column */
keys.event.action( 6, null, fnEditable ); /* Providing editing on the 7th column */
$("div.scan input").live("keypress", function(e) {
if (e.keyCode == 13) {
var ein = $(this).val();
$.getJSON("templates/warehouse_test_decoders/ajax/ein_details.php", {searchedEin : ein}, function(data) {
oTable.fnAddData( ["",data.ein, data.ein_desc, data.tech_diag, data.tech_comments, data.date, data.tech_name, data.headquarter,"","",""] );
});
$(this).val("");
}
});
} );
[/code]
So you are right, the initialisation of 'keys' every time is inefficient, and will quickly consume RAM. So what can be done is to take advantage of the KeyTables events, which are effectively 'live' - you don't need to add a new instance of KeyTable for every new row - using 'null' as the event location for the column and/or row will allow it to always work on that column / row.
So in the example above I've got the editable function being called on the 6th and 7th columns, again using the KeyTable event options (not sure if these are the right columns for you, but easy to change!).
I've also made use of the aoColumnDefs option in DataTables to apply some of the formatting that you were using.
Regards,
Allan
Regards,
Allan
[code]
< script type = "text/javascript" charset = "utf-8" >
function fnEditable(nCell) {
/* Block KeyTable from performing any events while jEditable is in edit mode */
keys.block = true;
/* Initialise the Editable instance for this table */
$(nCell).editable("templates/tech/ajax/edit_comments.php", {
callback: function (value, settings) {
keys.block = false;
$(this).editable("destroy");
},
submit: "OK",
cancel: "Cancel",
indicator: "Saving...",
placeholder: " ",
"onblur": "cancel",
"onreset": function () {
/* Unblock KeyTable, but only after this "esc" key event has finished.
* Otherwise it will "esc" KeyTable as well
*/
$(nCell).editable("destroy");
setTimeout(function () {
keys.block = false;
}, 0);
}
});
/* Dispatch click event to go into edit mode - Saf 4 needs a timeout... */
setTimeout(function () {
$(nCell).click();
}, 0);
}
function fnFormatDetails(oTable, nTr) {
var aData = oTable.fnGetData(nTr);
var date = aData[3];
var workorder = aData[1];
var eqID = aData[2];
$.ajax({
type: "POST",
url: "templates/tech/ajax/workorder_details.php",
cache: false,
data: ({
search_term: date + "+" + workorder + "+" + eqID + "+supervisors"
}),
success: function (msg) {
oTable.fnOpen(nTr, msg, "details");
}
});
return "";
}
$(document).ready(function () {
TableToolsInit.sSwfPath = "javascript/DataTables/extras/TableTools/media/swf/ZeroClipboard.swf";
var oTable = $("#example").dataTable({
"bFilter": false,
"bJQueryUI": true,
"sDom": '<"H"l<"scan">r>t<"F"i"T"p>',
"aoColumnDefs": [{
"fnRender": function (o) {
return '';
},
"aTargets": [0]
},
{
"sClass": "edit_comments",
"aTargets": [9]
},
{
"bSortable": false,
"aTargets": [0]
}]
});
$("div.scan").html("Rechercher : ");
$("div.scan").css("float", "right");
var keys = new KeyTable({
"table": document.getElementById("example"),
"datatable": oTable
});
keys.event.action(9, null, fnEditable); /* Providing editing on the 9th column */
$("div.scan input").live("keypress", function (e) {
if (e.keyCode == 13) {
var ein = $(this).val();
$.getJSON("templates/warehouse_test_decoders/ajax/ein_details.php", {
searchedEin: ein
}, function (data) {
oTable.fnAddData(["", data.ein, data.ein_desc, data.tech_diag, data.tech_comments, data.date, data.tech_name, data.headquarter, "", "", ""]);
});
$(this).val("");
}
});
/* Add event listener for opening and closing details
* Note that the indicator for showing which row is open is not controlled by DataTables,
* rather it is done here
*/
$("#example tbody td img").live("click", function () {
var nTr = this.parentNode.parentNode;
if (this.src.match("details_close")) {
/* This row is already open - close it */
this.src = "javascript/DataTables/examples/examples_support/details_open.png";
oTable.fnClose(nTr);
} else {
/* Open this row */
this.src = "javascript/DataTables/examples/examples_support/details_close.png";
oTable.fnOpen(nTr, fnFormatDetails(oTable, nTr), "details");
}
});
});
< /script>
[/code]
Thanks,
Allan
1. Make keys global
2. Pass keys through an anon function
3. Move the function back into the document.ready one - since you are only using it once.
Here is how option 2 can be done:
[code]
< script type = "text/javascript" charset = "utf-8" >
function fnEditable(keys, nCell) {
/* Block KeyTable from performing any events while jEditable is in edit mode */
keys.block = true;
/* Initialise the Editable instance for this table */
$(nCell).editable("templates/tech/ajax/edit_comments.php", {
callback: function (value, settings) {
keys.block = false;
$(this).editable("destroy");
},
submit: "OK",
cancel: "Cancel",
indicator: "Saving...",
placeholder: " ",
"onblur": "cancel",
"onreset": function () {
/* Unblock KeyTable, but only after this "esc" key event has finished.
* Otherwise it will "esc" KeyTable as well
*/
$(nCell).editable("destroy");
setTimeout(function () {
keys.block = false;
}, 0);
}
});
/* Dispatch click event to go into edit mode - Saf 4 needs a timeout... */
setTimeout(function () {
$(nCell).click();
}, 0);
}
function fnFormatDetails(oTable, nTr) {
var aData = oTable.fnGetData(nTr);
var date = aData[3];
var workorder = aData[1];
var eqID = aData[2];
$.ajax({
type: "POST",
url: "templates/tech/ajax/workorder_details.php",
cache: false,
data: ({
search_term: date + "+" + workorder + "+" + eqID + "+supervisors"
}),
success: function (msg) {
oTable.fnOpen(nTr, msg, "details");
}
});
return "";
}
$(document).ready(function () {
TableToolsInit.sSwfPath = "javascript/DataTables/extras/TableTools/media/swf/ZeroClipboard.swf";
var oTable = $("#example").dataTable({
"bFilter": false,
"bJQueryUI": true,
"sDom": '<"H"l<"scan">r>t<"F"i"T"p>',
"aoColumnDefs": [{
"fnRender": function (o) {
return '';
},
"aTargets": [0]
},
{
"sClass": "edit_comments",
"aTargets": [9]
},
{
"bSortable": false,
"aTargets": [0]
}]
});
$("div.scan").html("Rechercher : ");
$("div.scan").css("float", "right");
var keys = new KeyTable({
"table": document.getElementById("example"),
"datatable": oTable
});
keys.event.action(9, null, function (node) {
fnEditable( keys, node );
} ); /* Providing editing on the 9th column */
$("div.scan input").live("keypress", function (e) {
if (e.keyCode == 13) {
var ein = $(this).val();
$.getJSON("templates/warehouse_test_decoders/ajax/ein_details.php", {
searchedEin: ein
}, function (data) {
oTable.fnAddData(["", data.ein, data.ein_desc, data.tech_diag, data.tech_comments, data.date, data.tech_name, data.headquarter, "", "", ""]);
});
$(this).val("");
}
});
/* Add event listener for opening and closing details
* Note that the indicator for showing which row is open is not controlled by DataTables,
* rather it is done here
*/
$("#example tbody td img").live("click", function () {
var nTr = this.parentNode.parentNode;
if (this.src.match("details_close")) {
/* This row is already open - close it */
this.src = "javascript/DataTables/examples/examples_support/details_open.png";
oTable.fnClose(nTr);
} else {
/* Open this row */
this.src = "javascript/DataTables/examples/examples_support/details_close.png";
oTable.fnOpen(nTr, fnFormatDetails(oTable, nTr), "details");
}
});
});
< /script>
[/code]
Regards,
Allan
Thanks for your support. It is really appreciated! :-)
Regards,
Allan
Thanks!
Regards,
Allan
Here's the code I use for that:
[code]
$("div.scan input").live("keypress", function(e) {
if (e.keyCode == 13) {
var ein = $(this).val();
$.get("templates/warehouse_test_decoders/ajax/ein_details.php", {searchedEin : ein}, function(data) {
var n = $(data).filter("tr").length;
for ( var i=0 ; i
So with this method, KeyTable thinks that the added row is a part of the table (since it is!) and thus will treat it as the same. It is probably possible to have KeyTable skip rows / cells with a certain class, but it's not something I've looked at before.
Regards,
Allan