Show/hide details of only one row
Show/hide details of only one row
Using the example here http://datatables.net/examples/api/row_details.html I've got very nice details shown for each of my rows, but I'd like only ONE details row to be shown at a time (and all closed rows should have their icons reflect their state). Also, the user should be able to close the open details row, reverting the table back to its initial state (this other example keeps the last detail row shown http://datatables.net/forums/comments.php?DiscussionID=1610)
[code]
$("td", oTable.fnGetNodes()).delegate("img", "click", function () {
var nTr = this.parentNode.parentNode;
if (this.src.match('icon-close')) {
/* This row is already open - close it */
this.src = "/images/icon-add.png";
oTable.fnClose(nTr);
var temp1 = oTable.fnGetData(nTr);
/* only update cell if data has changed */
if (schoolsList != temp1[4]) {
oTable.fnUpdate(schoolsList, nTr, 4, true);
$("td:nth-child(4)", nTr).effect("pulsate", { times: 3 }, "slow");
}
}
else {
/* Open this row */
this.src = "/images/icon-close.png";
oTable.fnOpen(nTr, fnFormatDetails(nTr), 'details');
var temp2 = oTable.fnGetData(nTr);
schoolsList = temp2[4];
}
});
[/code]
[code]
$("td", oTable.fnGetNodes()).delegate("img", "click", function () {
var nTr = this.parentNode.parentNode;
if (this.src.match('icon-close')) {
/* This row is already open - close it */
this.src = "/images/icon-add.png";
oTable.fnClose(nTr);
var temp1 = oTable.fnGetData(nTr);
/* only update cell if data has changed */
if (schoolsList != temp1[4]) {
oTable.fnUpdate(schoolsList, nTr, 4, true);
$("td:nth-child(4)", nTr).effect("pulsate", { times: 3 }, "slow");
}
}
else {
/* Open this row */
this.src = "/images/icon-close.png";
oTable.fnOpen(nTr, fnFormatDetails(nTr), 'details');
var temp2 = oTable.fnGetData(nTr);
schoolsList = temp2[4];
}
});
[/code]
This discussion has been closed.
Replies
[code]
/* Close any rows which are already open */
$("td img", oTable.fnGetNodes()).each( function () {
if ( this.src.match('icon-close') ) {
oTable.fnClose( this.parentNode.parentNode );
}
});
[/code]
It will look for any open rows and close them. You might want to add in some of the logic that you use in the closing part of your code - I'm not sure what you would want the functionality to be :-)
Regards,
Allan
[code]
/* Close any rows which are already open */
$("td img", oTable.fnGetNodes()).each(function () {
if (this.src.match('icon-close')) {
this.src = "/images/icon-add.png";
oTable.fnClose(this.parentNode.parentNode);
}
});
[/code]
[code]
$("td", oTable.fnGetNodes()).delegate("img", "click", function () {
//whatever
});
[/code]
instead of your example
[code]
$('td img', oTable.fnGetNodes()).each(function () {
$(this).click(function () {
//whatever
});
});
[/code]
For some reason I chose to use .delegate() but it adds about 10% to execution time... so I'll go back to your example. :) Thanks again.
Regards,
Allan
"Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements."
Meaning that it is live. The cool thing about it is that it creates one handler, which is fired from any element scoped by the *immediately* preceding selector. In comparison, live or bind create one handler for every element, clunky for many rows. This makes delegate an extremely useful tool for DataTables!
Here's an example from what I've just been working on. The handlers work great, but for some reason the event does not get stopped as one would imagine. Any thoughts on the issue would be most helpful!
[code] $dt_<%= table_name %>.delegate('tr.data_row a', 'click', function(e){ // ruby
alert('a click!');
e.stopImmediatePropagation();
});
$dt_<%= table_name %>.delegate('tr.data_row', 'click', function(e){ // ruby
alert('row click!');
});
[/code]
The anchor alert shows first, followed by the row alert. Gah.
PS: This is my first post. DataTables is the bomb! wooooo!
Edit: Had a friend look at the code. As far as I can tell, it looks like a JQ bug, which seems hard to believe, but might be true.. Here's my workaround, which is perhaps even better:
[code] $dt_<%= table_name %>.delegate('tr.data_row', 'click', function(e){
if ( !$(event.target).is("a") ){
console.log(e); //do stuff etc
}
});[/code]
I'm the first to admit that I'm a JQ noob, but, have you tried e.stopPropagation(); instead of e.stopImmediatePropagation(); ?
Just a thought.
http://api.jquery.com/event.stopImmediatePropagation/
"In addition to keeping any additional handlers on an element from being executed, this method also stops the bubbling by implicitly calling event.stopPropagation()."
Step 2: Check the source:
http://www.bit.ly/jqsource
[code]stopImmediatePropagation: function() {
this.isImmediatePropagationStopped = returnTrue;
this.stopPropagation();
},[/code]
Being a noob is fine. The important part is knowing how to learn well.
We are all learning on the forum (me more that most I'm sure :-) ), so let's keep it courteous. I'll leave this conversation open for now in the hope that we will return to talking about the merits of jQuery delegates, live and so on. It will be closed if it deviates...
Regards,
Allan
Thanks for your kind words about DataTables in your earlier post btw :-)
Going back to delegates - they do look like they have a lot of advantages over other methods when tying an event handler to many elements (not uncommon in a DataTable). Just a thought, but have you tried returning boolean false from the first event handler? jQuery tends to follow something like the MSIE (old) pattern of dealing with bubbling and basing it on the return of the event handler function.
Regards,
Allan
[code] var ret = handleObj.handler.apply( this, arguments );
if ( ret !== undefined ) {
event.result = ret;
if ( ret === false ) {
event.preventDefault();
event.stopPropagation();
}
}
if ( event.isImmediatePropagationStopped() ) {
break;
}[/code]
In short, returning false does the same as returning false in the onclick attr, which in this case prevents the link from being clicked on at all. I suppose the real challenge now would be figuring why stopPropagation doesn't have the desired effect on delegate, but for now I'm happy leaving it for another day ;-)
*http://paulirish.com/2009/perf/
[code]
$('#example tbody').delegate('tr td', 'click', function(e){
alert('click 1');
return false;
});
$('#example tbody').delegate('tr td', 'click', function(e){
alert('click 2');
});
$('#example').dataTable();
[/code]
I've been keeping a copy of jQuery.js on my desktop to look things up when things go funny. I like their method of dealing with isImmediatePropagationStopped(). Smooth.
Regards,
Allan
you already read this discussion, for help..
Krl