Enhancement suggestion

Enhancement suggestion

adsoodadsood Posts: 10Questions: 0Answers: 0
edited August 2011 in General
Hello,

the problem:
we need to highlight the cells content based on the content of the table. lets say a hidden column contains a flag and based on the flag we highlight the other column in a predefined color.

the approach:
it seems that aoColumnsDefs -> fnRender function is the most continent for highlighting. in the function we would read the data in the hidden cells and generate cell content or apply appropriate styling for the cell being rendered.
however, this did not work well for us. the table cell itself (td element) has margins/paddings set and whatever colored markup we generate inside the cell, it always has some white border around. the best solution would be to apply styles to then td element that is being rendered, but the element is not available in the fnRender function.

the solution:
we solve the issue by adjusting the datatables code and adding the td element to the parameter object for fnRender function.
here are the snippets from modified jquery,datatables.js (Version: 1.7.6)
note: the inserts are wrapped in with "ADS" keyword

start at line: 1842
[code]
this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
{
...
if ( oSettings.aoColumns[iColumn].fnRender !== null )
{
//ADS: Expose TD node to fnRender
var iVisCol = _fnColumnIndexToVisible( oSettings, iColumn );
var tdNode;
if ( iVisCol !== null )
{
tdNode = oSettings.aoData[iRow].nTr.getElementsByTagName('td')[iVisCol];
}
else
{
tdNode = oSettings.aoData[iRow]._anHidden[iColumn];
}
//:ADS

sDisplay = oSettings.aoColumns[iColumn].fnRender( {
"iDataRow": iRow,
"iDataColumn": iColumn,
"aData": oSettings.aoData[iRow]._aData,
"oSettings": oSettings,
"nTd": tdNode
} );

[/code]

...

[code]
if ( oSettings.aoColumns[i].fnRender !== null )
{
//ADS: Expose TD node to fnRender
var iVisCol = _fnColumnIndexToVisible( oSettings, iColumn );
var tdNode;
if ( iVisCol !== null )
{
tdNode = oSettings.aoData[iRow].nTr.getElementsByTagName('td')[iVisCol];
}
else
{
tdNode = oSettings.aoData[iRow]._anHidden[i];
}
//:ADS

sDisplay = oSettings.aoColumns[i].fnRender( {
"iDataRow": iRow,
"iDataColumn": i,
"aData": oSettings.aoData[iRow]._aData,
"oSettings": oSettings,
"nTd": tdNode
} );

[/code]

...

[code]
if ( typeof oSettings.aoColumns[i].fnRender == 'function' )
{
var sRendered = oSettings.aoColumns[i].fnRender( {
"iDataRow": iThisIndex,
"iDataColumn": i,
"aData": aData,
"oSettings": oSettings,
//ADS: Expose TD node to fnRender
"nTd": nTd
//:ADS
} );
nTd.innerHTML = sRendered;
if ( oSettings.aoColumns[i].bUseRendered )

[/code]

...

[code]
/* Rendering */
if ( bRender )
{
sRendered = oSettings.aoColumns[iColumn].fnRender( {
"iDataRow": iRow,
"iDataColumn": iColumn,
"aData": oSettings.aoData[iRow]._aData,
"oSettings": oSettings,
//ADS: Expose TD node to fnRender
"nTd": nCell
//:ADS
} );
nCell.innerHTML = sRendered;
if ( oSettings.aoColumns[iColumn].bUseRendered )


[/code]

if you see a better way to access td element, your comments are appreciated.
if not, I hope to see this (or similar) fixes to be incorporated to the next releases.

Thanks,
Andrew.

Replies

  • fbasfbas Posts: 1,094Questions: 4Answers: 0
    I agree with you. Not having the DOM element available at the time of fnRender (and not available through oObj, which would be convenient) is a big annoyance.
  • allanallan Posts: 63,531Questions: 1Answers: 10,475 Site admin
    It is currently possible to get it like this:

    [code]
    oSettings[ iDataRow ].nTr
    [/code]

    however I also agree, it would be nice for this to be made more accessible. I'll add it in for the next version.

    Regards,
    Allan
  • allanallan Posts: 63,531Questions: 1Answers: 10,475 Site admin
    Hmmm... having said that... :-). I was just going to implement this, and then remembered that the TR element is not always available when fnRender is called. If you are using server-side processing, Ajax data or a JS data source (i.e. anything but DOM) then the TR element is created after fnRender in order to ensure that fnRender need only be called once.

    I think for the moment rather than putting in the changes that would be needed for this, fnRender should stay as it is - intended for string processing only, and fnRowCallback be used for DOM manipulation.

    Regards,
    Allan
  • fbasfbas Posts: 1,094Questions: 4Answers: 0
    edited August 2011
    fair enough. just as long as there are examples/documentation that highlight this. I think a lot of people (myself included) make the assumption that they can act on a DOM object during fnRender, and spend some time trying to make it work.
  • adsoodadsood Posts: 10Questions: 0Answers: 0
    Tried it out. Works for me.

    The only question I have is:
    if I have visible and non-visible columns in the table, how would this affect my selection criteria of the td element. Currently, it is very simple:
    [code]
    var $td = $(nRow).children('td').first();
    $td.css('background-color', aData[20] );
    [/code]
    However, if I need to highlight the data column 10 and I have set visible=false for columns 1 and 2 what my jQuery selection would be?
    I am assuming that the td index will be 8 rather then 10.
    Correct?
  • allanallan Posts: 63,531Questions: 1Answers: 10,475 Site admin
    Correct yes :-). Hidden columns are removed from the DOM so effect the visible index. DataTables has built in functions to do this calculation, which it might be an idea to expose via an API call.

    In fact - I've just put together the two plug-ins to do this:

    http://datatables.net/plug-ins/api#fnColumnIndexToVisible
    http://datatables.net/plug-ins/api#fnVisibleToColumnIndex

    Hopefully make it a little easier and more flexible to go between them.

    Regards,
    Allan
  • adsoodadsood Posts: 10Questions: 0Answers: 0
    Excellent,
    Thanks.
This discussion has been closed.