Flash PDF button not working in DataTables TableTools in multiple jQuery tabs

4.1k Views Asked by At

I am using DataTables, TableTools display 2 tables. I am using Easy Tabs jQuery plug-in for my menu and I am displaying 2 tables on different tabs. Since the buttons' element is display: none and thus has no height / width, the Flash buttons can't be correctly sized, and you can't click on a 0x0 element.

I need to use the TableTools fnResizeButtons() method for resizing the buttons when the tab is made visible.

The tabs (divs) are made hidden through CSS:

#tabcontent2, #tabcontent3, #tabcontent4,{ 
    display: none;}

Here is my script for fnResizeButtons and to initialize DataTables & TableTools:

/**Begin script to resize buttons when div made visible *******************/ 
$("#tabcontent1, #tabcontent2").tabs( {
"show": function(event, ui) {
   var jqTable = $('table.display', ui.panel);
   if ( jqTable.length > 0 ) {
       var oTableTools = TableTools.fnGetInstance( jqTable[0] );
       if ( oTableTools != null && oTableTools.fnResizeRequired() ){
           /* A resize of TableTools' buttons and DataTables' 
                        * columns is only required on the
            * first visible draw of the table
            */
           jqTable.dataTable().fnAdjustColumnSizing();
           oTableTools.fnResizeButtons();
       } //end if
   } //end 
} //end "show": function(event, ui) {
} ); //end $("#tabcontent1, #tabcontent2").tabs( {
} ); //end $(document).ready(function()

/**Begin Initialisation oTable**************/
var oTable = {};               
$(document).ready( function () {
oTable = $('#claims').dataTable( {
"oLanguage": {
    "sSearch": "Search all columns:"
}, //end <a href="/ref#oLanguage">oLanguage</a>                 
"sPaginationType": "full_numbers",

// initialize Table Tools
"sDom": 'T<"clear">lfrtip',
"oTableTools": {
    // setting SWF path
    "sSwfPath": ["swf/copy_csv_xls_pdf.swf"],
    // buttons
    "aButtons": [                                             
                    {   "sExtends":    "copy",
                         "bFooter": false
                    }, // end sExtends
                    {   "sExtends":    "print",
                         "bFooter": false
                    }, // end sExtends
                    {   "sExtends":    "csv",
                         "bFooter": false
                    }, // end sExtends
                    {   "sExtends":    "xls",
                         "bFooter": false
                    }, // end sExtends
                    {   "sExtends":    "pdf",
                         "bFooter": false,
                         "sPdfOrientation": "landscape"
                    } // end sExtends
    ] //end aButtons                                      
} //end oTableTools
} ); //end #example .dataTable
} ); //end $(document).ready(function()


/**Begin Initialisation froi table****************************/            
var froiTable = {};
$(document).ready( function () {
froiTable = $('#froi').dataTable( {
"bPaginate": false,
"bFilter": false,
"bSort": false,             

// initialize Table Tools
"sDom": 'T<"clear">lfrtip',
"oTableTools": {
    // setting SWF path
    "sSwfPath": ["swf/copy_csv_xls_pdf.swf"],
    // buttons
    "aButtons": [                                             
                        "print",
                        "pdf"
    ] //end aButtons                                      
} //end oTableTools                                  
} ); //end #froi .dataTable
} ); //end $(document).ready(function() 

Here is my code for the menu and divs:

    <div id="tabs" class="menu"> <!--Start menu -->
<ul>
<li><a href="#" onmouseover="easytabs('1', '1');"   onfocus="easytabs('1', '1');"   onclick="return false;"  title="" id="tablink1" >Tabcontent 1</a></li>
<li><a href="#" onmouseover="easytabs('1', '2');"   onfocus="easytabs('1', '2');"   onclick="return false;"  title="" id="tablink2" >Tabcontent 2</a></li>
<li><a href="#" onmouseover="easytabs('1', '3');"   onfocus="easytabs('1', '3');"   onclick="return false;"  title="" id="tablink3">Tabcontent 3</a></li>
<li><a href="#" onmouseover="easytabs('1', '4');"   onfocus="easytabs('1', '4');"   onclick="return false;"  title="" id="tablink4" >Tabcontent 4</a></li>         
</ul>
</div> <!--End menu -->


<div id="tabcontent1">

            <!--Code for Table goes here -->

</div> <!--End Tabcontent 1-->


<div id="tabcontent2">

            <!--Code for Table goes here -->

</div><!--End Tabcontent 2 -->


<div id="tabcontent3">

</div><!--End Tabcontent 3-->


<div id="tabcontent4">

</div><!--End Tabcontent 4-->

I believe that my problem is in the script to resize buttons when div made visible (fnResizeButtons script).

What am I missing?

4

There are 4 best solutions below

0
On

lots of complicated solutions here, what is important for this to work ( i.e. not having height:0px and width:0px ) is for the containing element to not be hidden at the moment of time datatables tries to bind to the element. If you want to hide something you have to do it AFTER datatables it is bound ( initiated )

0
On

I just debugged this and found an easy answer that doesn't require hacking ZeroClipboard at all.

The problem was with this snippet of code var jqTable = $('table.display', ui.panel);

The function is looking for a <table> with a class of display which I didn't have. Once I changed this to the classes I was using, it began working with the code as provided.

Here's the entirety of my solution, no hacking of ZeroClipboard required:

$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) { // This is the tab show code for Twitter Bootstrap
    var jqTable = $('table.table', $(e.target).attr("href"));
        if ( jqTable.length > 0 ) {
        var oTableTools = TableTools.fnGetInstance( jqTable[0] );
        if ( oTableTools != null && oTableTools.fnResizeRequired() ){
            jqTable.dataTable().fnAdjustColumnSizing();
            oTableTools.fnResizeButtons();
        } //end if
    }
});
0
On

This is what worked for me:

$(document).ready(function() {

$('a[data-toggle="tab"]').on( 'shown.bs.tab', function (e) {
    $.fn.dataTable.tables( {visible: true, api: true} ).columns.adjust();
    $.fn.dataTable.tables( {visible: true, api: true} ).columns.adjust().draw();
} );



$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {         
    var tableInstances = TableTools.fnGetMasters(), instances = tableInstances.length;
    while (instances--)
    {
        var dataTable = tableInstances[instances];
        if (dataTable.fnResizeRequired())
        {
            dataTable.fnResizeButtons();
        }
    }
});
});
0
On

SOLVED!!!!! The problem is in getDOMObjectPosition of ZeroClipoard.js. This tries to determine position & dimension of the element the Flash-Movie is attached to. The problem is the used .width & .offsetWidth do not work on invisible Elements. Alter the function to check for visibility. If non-visibility clone the element into a temp div 200px outside window where visible, then do dimension-retrieval on clone & afterwards destroy both temp div & cloned element. Solution here: on DataTables forum.

getDOMObjectPosition: function(obj) {

   var info = Object();

   // get absolute coordinates for dom element
   if ($(obj).is(":visible")){ //obj.widht and obj.offsetWidth only work on visible elements
       info = {
           left: 0,
           top: 0,
           width: obj.width ? obj.width : obj.offsetWidth,
           height: obj.height ? obj.height : obj.offsetHeight
       };
   } else {
       //clone the object into a div outside of the window
       var tempDiv = $('<div id="__ZeroClipBoard_Object_Temp" style=\"position:absolute; left:-2000px\"></div>');
       var objClone = $(obj).clone();
       objClone.appendTo(tempDiv).appendTo($('body'));
       //get the info needed
       info = {
           left: 0,
           top: 0,
           width: objClone.width ? objClone.width : objClone.offsetWidth,
           height: objClone.height ? objClone.height : objClone.offsetHeight
       };
       //destroy the temporary objects
       objClone.remove();
       tempDiv.remove();

   }

   if ( obj.style.width != "" )
       info.width = obj.style.width.replace("px","");

   if ( obj.style.height != "" )
       info.height = obj.style.height.replace("px","");

   while (obj) {
       info.left += obj.offsetLeft;
       info.top += obj.offsetTop;
       obj = obj.offsetParent;
   }
   return info; 
   };

This solves the problem, I am not convinced that this is the correct way to fix it, but it works...