I have a DataTables table, which has checkboxes and popups in some of the header columns. (Plus I use FixedColumn and ColReorder plugins too). A mock-up of what I have in a jsfiddle is at the bottom
My problem is that if a user tries to check the checkboxes or push the popups, the sorting event takes over everything. The jsfiddle page is not functioning fully, because in my app I receive the events for the checkbox click, but it's too late at that time, the sorting also happens. The sort icon is just a background CSS for the header cells, and the sorting event is registered for the whole header cell by DataTables.
Plans to solve this problem:
- Register handlers and try to prevent the running of Datatables's own handlers. As of now, if I also register an event handler for the header cells, I'll get the event only after DataTable's handler, the events are delivered in registration order. I also registered handlers for the checkbox and the popup itself, but those are also delivered only after DataTables's handlers (bubbling up). This could only work if I could somehow register my handler before DataTables's own handler, but I haven't found an entry point to do that. The table DOM should be already generated, when the event is registered. Right now I see too late occasions, I can only register.
- Finding an API call point where I could cancel DataTables's sorting. The order event (http://datatables.net/reference/event/order) seems to be after the fact, I don't see a way for cancellation.
- At some point I restructured the non-fixed column headers to contain two rows: the top row was for sorting and the bottom contained my checbox and popup controls. That seemed to work except that it turned out that it doesn't work with the ColReorder plugin. I need that plugin, and it only reordered the top row of the header, the bottom stayed there. If I could fix that, it would be a solution also.
http://jsfiddle.net/csabatoth/pgue1sf5/8/
var initPage = function () {
var columnsArray = [
{ "title": "index", "class": "dt-center" },
{ "title": "lastname", "class": "dt-head-center dt-body-left" },
{ "title": "firstname", "class": "dt-head-center dt-body-left" },
{ "title": '<div>foo1</div><input type="checkbox" class="filterchk" checked="checked"> <select class="paramsel"><option value="1" selected="selected"/><option value="2"/><option value="3"/></select>', "class": "dt-head-center dt-body-left" },
{ "title": '<div>foo2</div><input type="checkbox" class="filterchk" checked="checked"> <select class="paramsel"><option value="1" selected="selected"/><option value="2"/><option value="3"/></select>', "class": "dt-center rulecolumn" },
{ "title": '<div>foo3</div><input type="checkbox" class="filterchk" checked="checked"> <select class="paramsel"><option value="1" selected="selected"/><option value="2"/><option value="3"/></select>', "class": "dt-center rulecolumn" },
{ "title": '<div>foo4</div><input type="checkbox" class="filterchk" checked="checked"> <select class="paramsel"><option value="1" selected="selected"/><option value="2"/><option value="3"/></select>', "class": "dt-center rulecolumn" },
{ "title": '<div>bar1</div><input type="checkbox" class="filterchk" checked="checked"> <select class="paramsel"><option value="1" selected="selected"/><option value="2"/><option value="3"/></select>', "class": "dt-center rulecolumn" },
{ "title": '<div>bar2</div><input type="checkbox" class="filterchk" checked="checked"> <select class="paramsel"><option value="1" selected="selected"/><option value="2"/><option value="3"/></select>', "class": "dt-center rulecolumn" },
{ "title": '<div>bar3</div><input type="checkbox" class="filterchk" checked="checked"> <select class="paramsel"><option value="1" selected="selected"/><option value="2"/><option value="3"/></select>', "class": "dt-center rulecolumn" }
];
var dataArray = [
[ 1, "aaa", "rrr", "x", "x", "x", "x", "x", "x", "x" ],
[ 2, "bbb", "qqq", "x", "x", "x", "x", "x", "x", "x" ],
[ 3, "ccc", "ppp", "x", "x", "x", "x", "x", "x", "x" ],
[ 4, "ddd", "ooo", "x", "x", "x", "x", "x", "x", "x" ],
[ 5, "eee", "nnn", "x", "x", "x", "x", "x", "x", "x" ],
[ 6, "fff", "mmm", "x", "x", "x", "x", "x", "x", "x" ],
[ 7, "ggg", "lll", "x", "x", "x", "x", "x", "x", "x" ],
[ 8, "hhh", "kkk", "x", "x", "x", "x", "x", "x", "x" ],
[ 9, "iii", "jjj", "x", "x", "x", "x", "x", "x", "x" ]
];
viewModel.table = $('#MyTable').DataTable({
dom: "Rrtip",
autoWidth: false,
deferRender: true,
info: true,
lengthChange: false,
ordering: true,
orderMulti: true,
orderFixed: {
pre: [0, 'asc'],
post: [1, 'asc']
},
paging: true,
pagingType: "full_numbers",
renderer: "bootstrap",
processing: true,
scrollX: true,
scrollY: false,
searching: false,
columns: columnsArray,
data: dataArray,
initComplete: function (settings, json) {
viewModel.attachTableEventHandlers();
},
displayLength: 5,
colReorder: {
fixedColumnsLeft: 3,
fixedColumnsRight: 0
}
});
new $.fn.dataTable.FixedColumns(viewModel.table, {
leftColumns: 3
});
To reiterate my attempts:
So the only method I could think of is to take a deep breath and hack DataTables itself:
So I added that return statement to the beginning of the function body. This will prevent the attachment of the listener. I left the unaccessable code below the return to cause as less modification as possible. Problems with this modification:
function Ka(a,b,c,d){return;var e=a.aoColumns[c];Ta(b ...
Now that the click doesn't work, I need attach my own listeners, and call the sorting programatically, if the click was not on an input element.
What you see here is a combination of yacdf filters or popups ("option") or edit boxes marked with "paramsel" class by me or check boxes marked by "paramchk" class by will receive the click event, and I don't sort. But otherwise I need to programatically sort. The following code even tries to support multiple column sorting if shift key is pressed.
One more needed piece is the decorating the header cells with the column index:
This is all so complicated in the end, that please don't hesitate to tell me if it can be made simpler, or you know any kind of elegant or other solution.
I have read only the title of the question and the first 3 lines of it (so I hope it helps), but if all that you need is to stop the propagation of the click even of the clicked checkbox that is located inside the table header you should add
onclick="event.stopPropagation()"
to that checkbox, or even better a function that will work on IE (old) and other browsersand in your checkbox add
onclick="stopPropagation(event)"
for your select you should also add
onmousedown="..."
so it look like this:Here is a working jsfiddle, I only fixed the first checkbox/select
not sure if this would help, but I was in a similar situation - my header contains a dropdown button, which opens a .dropdown-pane pane element with a slider. Every slider move would have caused column sorting. I was desperate and wrote nearly 100 lines trying to unbind and override this behavior. At the end I would either disable both sorting and slider with preventDefault() (obviously, not a solution), or nothing would work at all. Surprisingly, after few hours of mistakes and trials, I found that this works: