8 (
function($, window, document) {
25 TableTools =
function( oDT, oOpts )
28 if ( !
this instanceof TableTools )
30 alert(
"Warning: TableTools must be initialised with the keyword 'new'" );
35 var dtSettings = $.fn.dataTable.Api ?
36 new $.fn.dataTable.Api( oDT ).settings()[0] :
98 "funcEnd":
function () {}
136 "preRowSelect": null,
144 "postSelected": null,
152 "postDeselected": null,
279 this.classes = $.extend(
true, {}, TableTools.classes );
280 if ( this.s.dt.bJUI )
282 $.extend(
true, this.classes, TableTools.classes_themeroller );
295 this.fnSettings =
function () {
301 if ( typeof oOpts ==
'undefined' )
307 TableTools._aInstances.push(
this );
308 this._fnConstruct( oOpts );
315 TableTools.prototype = {
328 "fnGetSelected":
function ( filtered )
332 data = this.s.dt.aoData,
333 displayed = this.s.dt.aiDisplay,
339 for ( i=0, iLen=displayed.length ; i<iLen ; i++ )
341 if ( data[ displayed[i] ]._DTTT_selected )
343 out.push( data[ displayed[i] ].nTr );
350 for ( i=0, iLen=data.length ; i<iLen ; i++ )
352 if ( data[i]._DTTT_selected )
354 out.push( data[i].nTr );
368 "fnGetSelectedData":
function ()
371 var data=this.s.dt.aoData;
374 for ( i=0, iLen=data.length ; i<iLen ; i++ )
376 if ( data[i]._DTTT_selected )
378 out.push( this.s.dt.oInstance.fnGetData(i) );
394 "fnGetSelectedIndexes":
function ( filtered )
398 data = this.s.dt.aoData,
399 displayed = this.s.dt.aiDisplay,
405 for ( i=0, iLen=displayed.length ; i<iLen ; i++ )
407 if ( data[ displayed[i] ]._DTTT_selected )
409 out.push( displayed[i] );
416 for ( i=0, iLen=data.length ; i<iLen ; i++ )
418 if ( data[i]._DTTT_selected )
434 "fnIsSelected":
function ( n )
436 var pos = this.s.dt.oInstance.fnGetPosition( n );
437 return (this.s.dt.aoData[pos]._DTTT_selected===
true) ?
true :
false;
447 "fnSelectAll":
function ( filtered )
449 this._fnRowSelect( filtered ?
450 this.s.dt.aiDisplay :
462 "fnSelectNone":
function ( filtered )
464 this._fnRowDeselect( this.fnGetSelectedIndexes(filtered) );
473 "fnSelect":
function ( n )
475 if ( this.s.select.type ==
"single" )
478 this._fnRowSelect( n );
482 this._fnRowSelect( n );
492 "fnDeselect":
function ( n )
494 this._fnRowDeselect( n );
504 "fnGetTitle":
function( oConfig )
507 if ( typeof oConfig.sTitle !=
'undefined' && oConfig.sTitle !==
"" ) {
508 sTitle = oConfig.sTitle;
510 var anTitle = document.getElementsByTagName(
'title');
511 if ( anTitle.length > 0 )
513 sTitle = anTitle[0].innerHTML;
520 if (
"\u00A1".toString().length < 4 ) {
521 return sTitle.replace(/[^a-zA-Z0-9_\u00A1-\uFFFF\.,\-_ !\(\)]/g,
"");
523 return sTitle.replace(/[^a-zA-Z0-9_\.,\-_ !\(\)]/g,
"");
535 "fnCalcColRatios":
function ( oConfig )
538 aoCols = this.s.dt.aoColumns,
539 aColumnsInc = this._fnColumnTargets( oConfig.mColumns ),
541 iWidth = 0, iTotal = 0, i, iLen;
543 for ( i=0, iLen=aColumnsInc.length ; i<iLen ; i++ )
545 if ( aColumnsInc[i] )
547 iWidth = aoCols[i].nTh.offsetWidth;
549 aColWidths.push( iWidth );
554 for ( i=0, iLen=aColWidths.length ; i<iLen ; i++ )
556 aColWidths[i] = aColWidths[i] / iTotal;
559 return aColWidths.join(
'\t');
568 "fnGetTableData":
function ( oConfig )
573 return this._fnGetDataTablesData( oConfig );
583 "fnSetText":
function ( clip, text )
585 this._fnFlashSetText( clip, text );
594 "fnResizeButtons":
function ()
596 for ( var cli in ZeroClipboard_TableTools.clients )
600 var client = ZeroClipboard_TableTools.clients[cli];
601 if ( typeof client.domElement !=
'undefined' &&
602 client.domElement.parentNode )
604 client.positionElement();
614 "fnResizeRequired":
function ()
616 for ( var cli in ZeroClipboard_TableTools.clients )
620 var client = ZeroClipboard_TableTools.clients[cli];
621 if ( typeof client.domElement !=
'undefined' &&
622 client.domElement.parentNode ==
this.dom.container &&
623 client.sized ===
false )
644 "fnPrint":
function ( bView, oConfig )
646 if ( oConfig === undefined )
651 if ( bView === undefined || bView )
653 this._fnPrintStart( oConfig );
667 "fnInfo":
function ( message, time ) {
668 var info = $(
'<div/>')
669 .addClass( this.classes.print.info )
673 setTimeout(
function() {
674 info.fadeOut(
"normal",
function() {
686 "fnContainer":
function () {
687 return this.dom.container;
703 "_fnConstruct":
function ( oOpts )
707 this._fnCustomiseSettings( oOpts );
710 this.dom.container = document.createElement( this.s.tags.container );
711 this.dom.container.className = this.classes.container;
714 if ( this.s.select.type !=
'none' )
716 this._fnRowSelectConfig();
720 this._fnButtonDefinations( this.s.buttonSet,
this.dom.container );
723 this.s.dt.aoDestroyCallback.push( {
724 "sName":
"TableTools",
727 .off(
'click.DTTT_Select', that.s.custom.sRowSelector )
728 .off(
'mousedown.DTTT_Select',
'tr' )
729 .off(
'mouseup.DTTT_Select',
'tr' );
731 $.each( ZeroClipboard_TableTools.clients, function (
id, client ) {
732 if ( $(client.domElement).parents( that.dom.container ).length ) {
733 delete ZeroClipboard_TableTools.clients[ id ];
737 $(that.dom.container).empty();
740 var idx = $.inArray( that, TableTools._aInstances );
742 TableTools._aInstances.splice( idx, 1 );
756 "_fnCustomiseSettings":
function ( oOpts )
759 if ( typeof this.s.dt._TableToolsInit ==
'undefined' )
761 this.s.master =
true;
762 this.s.dt._TableToolsInit =
true;
766 this.dom.table = this.s.dt.nTable;
769 this.s.custom = $.extend( {}, TableTools.DEFAULTS, oOpts );
772 this.s.swfPath = this.s.custom.sSwfPath;
773 if ( typeof ZeroClipboard_TableTools !=
'undefined' )
775 ZeroClipboard_TableTools.moviePath = this.s.swfPath;
779 this.s.select.type = this.s.custom.sRowSelect;
780 this.s.select.preRowSelect = this.s.custom.fnPreRowSelect;
781 this.s.select.postSelected = this.s.custom.fnRowSelected;
782 this.s.select.postDeselected = this.s.custom.fnRowDeselected;
785 if ( this.s.custom.sSelectedClass )
787 this.classes.select.row = this.s.custom.sSelectedClass;
790 this.s.tags = this.s.custom.oTags;
793 this.s.buttonSet = this.s.custom.aButtons;
806 "_fnButtonDefinations":
function ( buttonSet, wrapper )
810 for ( var i=0, iLen=buttonSet.length ; i<iLen ; i++ )
812 if ( typeof buttonSet[i] ==
"string" )
814 if ( typeof TableTools.BUTTONS[ buttonSet[i] ] ==
'undefined' )
816 alert(
"TableTools: Warning - unknown button type: "+buttonSet[i] );
819 buttonDef = $.extend( {}, TableTools.BUTTONS[ buttonSet[i] ], true );
823 if ( typeof TableTools.BUTTONS[ buttonSet[i].sExtends ] ==
'undefined' )
825 alert(
"TableTools: Warning - unknown button type: "+buttonSet[i].sExtends );
828 var o = $.extend( {}, TableTools.BUTTONS[ buttonSet[i].sExtends ], true );
829 buttonDef = $.extend( o, buttonSet[i],
true );
832 var button = this._fnCreateButton(
834 $(wrapper).hasClass(this.classes.collection.container)
838 wrapper.appendChild( button );
851 "_fnCreateButton":
function ( oConfig, bCollectionButton )
853 var nButton = this._fnButtonBase( oConfig, bCollectionButton );
855 if ( oConfig.sAction.match(/flash/) )
857 if ( ! this._fnHasFlash() ) {
861 this._fnFlashConfig( nButton, oConfig );
863 else if ( oConfig.sAction ==
"text" )
865 this._fnTextConfig( nButton, oConfig );
867 else if ( oConfig.sAction ==
"div" )
869 this._fnTextConfig( nButton, oConfig );
871 else if ( oConfig.sAction ==
"collection" )
873 this._fnTextConfig( nButton, oConfig );
874 this._fnCollectionConfig( nButton, oConfig );
877 if ( this.s.dt.iTabIndex !== -1 ) {
879 .attr(
'tabindex', this.s.dt.iTabIndex )
880 .attr(
'aria-controls', this.s.dt.sTableId )
881 .on(
'keyup.DTTT',
function (e) {
885 if ( e.keyCode === 13 ) {
888 $(
this).trigger(
'click' );
891 .on(
'mousedown.DTTT',
function (e) {
898 if ( ! oConfig.sAction.match(/flash/) ) {
915 "_fnButtonBase":
function ( o, bCollectionButton )
917 var sTag, sLiner, sClass;
919 if ( bCollectionButton )
921 sTag = o.sTag && o.sTag !==
"default" ? o.sTag : this.s.tags.collection.button;
922 sLiner = o.sLinerTag && o.sLinerTag !==
"default" ? o.sLiner : this.s.tags.collection.liner;
923 sClass = this.classes.collection.buttons.normal;
927 sTag = o.sTag && o.sTag !==
"default" ? o.sTag : this.s.tags.button;
928 sLiner = o.sLinerTag && o.sLinerTag !==
"default" ? o.sLiner : this.s.tags.liner;
929 sClass = this.classes.buttons.normal;
933 nButton = document.createElement( sTag ),
934 nSpan = document.createElement( sLiner ),
935 masterS = this._fnGetMasterSettings();
937 nButton.className = sClass+
" "+o.sButtonClass;
938 nButton.setAttribute(
'id',
"ToolTables_"+this.s.dt.sInstance+
"_"+masterS.buttonCounter );
939 nButton.appendChild( nSpan );
940 nSpan.innerHTML = o.sButtonText;
942 masterS.buttonCounter++;
956 "_fnGetMasterSettings":
function ()
965 var instances = TableTools._aInstances;
966 for ( var i=0, iLen=instances.length ; i<iLen ; i++ )
968 if ( this.dom.table == instances[i].s.dt.nTable )
970 return instances[i].s;
989 "_fnCollectionConfig":
function ( nButton, oConfig )
991 var nHidden = document.createElement( this.s.tags.collection.container );
992 nHidden.style.display =
"none";
993 nHidden.className = this.classes.collection.container;
994 oConfig._collection = nHidden;
995 document.body.appendChild( nHidden );
997 this._fnButtonDefinations( oConfig.aButtons, nHidden );
1008 "_fnCollectionShow":
function ( nButton, oConfig )
1012 oPos = $(nButton).offset(),
1013 nHidden = oConfig._collection,
1015 iDivY = oPos.top + $(nButton).outerHeight(),
1016 iWinHeight = $(window).height(), iDocHeight = $(document).height(),
1017 iWinWidth = $(window).width(), iDocWidth = $(document).width();
1019 nHidden.style.position =
"absolute";
1020 nHidden.style.left = iDivX+
"px";
1021 nHidden.style.top = iDivY+
"px";
1022 nHidden.style.display =
"block";
1023 $(nHidden).
css(
'opacity',0);
1025 var nBackground = document.createElement(
'div');
1026 nBackground.style.position =
"absolute";
1027 nBackground.style.left =
"0px";
1028 nBackground.style.top =
"0px";
1029 nBackground.style.height = ((iWinHeight>iDocHeight)? iWinHeight : iDocHeight) +
"px";
1030 nBackground.style.width = ((iWinWidth>iDocWidth)? iWinWidth : iDocWidth) +
"px";
1031 nBackground.className = this.classes.collection.background;
1032 $(nBackground).
css(
'opacity',0);
1034 document.body.appendChild( nBackground );
1035 document.body.appendChild( nHidden );
1038 var iDivWidth = $(nHidden).outerWidth();
1039 var iDivHeight = $(nHidden).outerHeight();
1041 if ( iDivX + iDivWidth > iDocWidth )
1043 nHidden.style.left = (iDocWidth-iDivWidth)+
"px";
1046 if ( iDivY + iDivHeight > iDocHeight )
1048 nHidden.style.top = (iDivY-iDivHeight-$(nButton).outerHeight())+
"px";
1051 this.dom.collection.collection = nHidden;
1052 this.dom.collection.background = nBackground;
1057 setTimeout(
function () {
1058 $(nHidden).animate({
"opacity": 1}, 500);
1059 $(nBackground).animate({
"opacity": 0.25}, 500);
1063 this.fnResizeButtons();
1066 $(nBackground).click(
function () {
1067 that._fnCollectionHide.call( that, null, null );
1079 "_fnCollectionHide":
function ( nButton, oConfig )
1081 if ( oConfig !== null && oConfig.sExtends ==
'collection' )
1086 if ( this.dom.collection.collection !== null )
1088 $(this.dom.collection.collection).animate({
"opacity": 0}, 500,
function (e) {
1089 this.style.display =
"none";
1092 $(this.dom.collection.background).animate({
"opacity": 0}, 500,
function (e) {
1093 this.parentNode.removeChild(
this );
1096 this.dom.collection.collection = null;
1097 this.dom.collection.background = null;
1113 "_fnRowSelectConfig":
function ()
1115 if ( this.s.master )
1121 aoOpenRows = this.s.dt.aoOpenRows;
1123 $(dt.nTable).addClass( this.classes.select.table );
1128 if ( this.s.select.type ===
'os' ) {
1129 $(dt.nTBody).on(
'mousedown.DTTT_Select',
'tr',
function(e) {
1133 .
css(
'-moz-user-select',
'none' )
1134 .one(
'selectstart.DTTT_Select',
'tr',
function () {
1140 $(dt.nTBody).on(
'mouseup.DTTT_Select',
'tr',
function(e) {
1141 $(dt.nTBody).
css(
'-moz-user-select',
'' );
1146 $(dt.nTBody).on(
'click.DTTT_Select', this.s.custom.sRowSelector,
function(e) {
1147 var row = this.nodeName.toLowerCase() ===
'tr' ?
1149 $(
this).parents(
'tr')[0];
1151 var select = that.s.select;
1152 var pos = that.s.dt.oInstance.fnGetPosition( row );
1155 if ( row.parentNode != dt.nTBody ) {
1160 if ( dt.oInstance.fnGetData(row) === null ) {
1166 if ( select.type ==
'os' ) {
1167 if ( e.ctrlKey || e.metaKey ) {
1169 if ( that.fnIsSelected( row ) ) {
1170 that._fnRowDeselect( row, e );
1173 that._fnRowSelect( row, e );
1176 else if ( e.shiftKey ) {
1179 var rowIdxs = that.s.dt.aiDisplay.slice();
1180 var idx1 = $.inArray( select.lastRow, rowIdxs );
1181 var idx2 = $.inArray( pos, rowIdxs );
1183 if ( that.fnGetSelected().length === 0 || idx1 === -1 ) {
1186 rowIdxs.splice( $.inArray( pos, rowIdxs )+1, rowIdxs.length );
1190 if ( idx1 > idx2 ) {
1196 rowIdxs.splice( idx2+1, rowIdxs.length );
1197 rowIdxs.splice( 0, idx1 );
1200 if ( ! that.fnIsSelected( row ) ) {
1202 that._fnRowSelect( rowIdxs, e );
1206 rowIdxs.splice( $.inArray( pos, rowIdxs ), 1 );
1207 that._fnRowDeselect( rowIdxs, e );
1213 if ( that.fnIsSelected( row ) && that.fnGetSelected().length === 1 ) {
1214 that._fnRowDeselect( row, e );
1217 that.fnSelectNone();
1218 that._fnRowSelect( row, e );
1222 else if ( that.fnIsSelected( row ) ) {
1223 that._fnRowDeselect( row, e );
1225 else if ( select.type ==
"single" ) {
1226 that.fnSelectNone();
1227 that._fnRowSelect( row, e );
1229 else if ( select.type ==
"multi" ) {
1230 that._fnRowSelect( row, e );
1233 select.lastRow = pos;
1239 dt.oApi._fnCallbackReg( dt,
'aoRowCreatedCallback',
function (tr, data, index) {
1240 if ( dt.aoData[index]._DTTT_selected ) {
1241 $(tr).addClass( that.classes.select.row );
1243 },
'TableTools-SelectAll' );
1252 "_fnRowSelect":
function ( src, e )
1256 data = this._fnSelectData( src ),
1257 firstTr = data.length===0 ? null : data[0].nTr,
1262 for ( i=0, len=data.length ; i<len ; i++ )
1266 anSelected.push( data[i].nTr );
1271 if ( this.s.select.preRowSelect !== null && !
this.s.select.preRowSelect.call(
this, e, anSelected,
true) )
1277 for ( i=0, len=data.length ; i<len ; i++ )
1279 data[i]._DTTT_selected =
true;
1283 $(data[i].nTr).addClass( that.classes.select.row );
1288 if ( this.s.select.postSelected !== null )
1290 this.s.select.postSelected.call(
this, anSelected );
1293 TableTools._fnEventDispatch(
this,
'select', anSelected,
true );
1301 "_fnRowDeselect":
function ( src, e )
1305 data = this._fnSelectData( src ),
1306 firstTr = data.length===0 ? null : data[0].nTr,
1307 anDeselectedTrs = [],
1311 for ( i=0, len=data.length ; i<len ; i++ )
1315 anDeselectedTrs.push( data[i].nTr );
1320 if ( this.s.select.preRowSelect !== null && !
this.s.select.preRowSelect.call(
this, e, anDeselectedTrs,
false) )
1326 for ( i=0, len=data.length ; i<len ; i++ )
1328 data[i]._DTTT_selected =
false;
1332 $(data[i].nTr).removeClass( that.classes.select.row );
1337 if ( this.s.select.postDeselected !== null )
1339 this.s.select.postDeselected.call(
this, anDeselectedTrs );
1342 TableTools._fnEventDispatch(
this,
'select', anDeselectedTrs,
false );
1352 "_fnSelectData":
function ( src )
1354 var out = [], pos, i, iLen;
1359 pos = this.s.dt.oInstance.fnGetPosition( src );
1360 out.push( this.s.dt.aoData[pos] );
1362 else if ( typeof src.length !==
'undefined' )
1365 for ( i=0, iLen=src.length ; i<iLen ; i++ )
1367 if ( src[i].nodeName )
1369 pos = this.s.dt.oInstance.fnGetPosition( src[i] );
1370 out.push( this.s.dt.aoData[pos] );
1372 else if ( typeof src[i] ===
'number' )
1374 out.push( this.s.dt.aoData[ src[i] ] );
1384 else if ( typeof src ===
'number' )
1386 out.push(this.s.dt.aoData[src]);
1410 "_fnTextConfig":
function ( nButton, oConfig )
1414 if ( oConfig.fnInit !== null )
1416 oConfig.fnInit.call(
this, nButton, oConfig );
1419 if ( oConfig.sToolTip !==
"" )
1421 nButton.title = oConfig.sToolTip;
1424 $(nButton).hover(
function () {
1425 if ( oConfig.fnMouseover !== null )
1427 oConfig.fnMouseover.call(
this, nButton, oConfig, null );
1430 if ( oConfig.fnMouseout !== null )
1432 oConfig.fnMouseout.call(
this, nButton, oConfig, null );
1436 if ( oConfig.fnSelect !== null )
1438 TableTools._fnEventListen(
this,
'select',
function (n) {
1439 oConfig.fnSelect.call( that, nButton, oConfig, n );
1443 $(nButton).click(
function (e) {
1446 if ( oConfig.fnClick !== null )
1448 oConfig.fnClick.call( that, nButton, oConfig, null, e );
1452 if ( oConfig.fnComplete !== null )
1454 oConfig.fnComplete.call( that, nButton, oConfig, null, null );
1457 that._fnCollectionHide( nButton, oConfig );
1473 "_fnHasFlash":
function ()
1476 var fo =
new ActiveXObject(
'ShockwaveFlash.ShockwaveFlash');
1483 navigator.mimeTypes &&
1484 navigator.mimeTypes[
'application/x-shockwave-flash'] !== undefined &&
1485 navigator.mimeTypes[
'application/x-shockwave-flash'].enabledPlugin
1503 "_fnFlashConfig":
function ( nButton, oConfig )
1506 var flash =
new ZeroClipboard_TableTools.Client();
1508 if ( oConfig.fnInit !== null )
1510 oConfig.fnInit.call(
this, nButton, oConfig );
1513 flash.setHandCursor(
true );
1515 if ( oConfig.sAction ==
"flash_save" )
1517 flash.setAction(
'save' );
1518 flash.setCharSet( (oConfig.sCharSet==
"utf16le") ?
'UTF16LE' :
'UTF8' );
1519 flash.setBomInc( oConfig.bBomInc );
1520 flash.setFileName( oConfig.sFileName.replace(
'*',
this.fnGetTitle(oConfig)) );
1522 else if ( oConfig.sAction ==
"flash_pdf" )
1524 flash.setAction(
'pdf' );
1525 flash.setFileName( oConfig.sFileName.replace(
'*',
this.fnGetTitle(oConfig)) );
1529 flash.setAction(
'copy' );
1532 flash.addEventListener(
'mouseOver',
function(client) {
1533 if ( oConfig.fnMouseover !== null )
1535 oConfig.fnMouseover.call( that, nButton, oConfig, flash );
1539 flash.addEventListener(
'mouseOut',
function(client) {
1540 if ( oConfig.fnMouseout !== null )
1542 oConfig.fnMouseout.call( that, nButton, oConfig, flash );
1546 flash.addEventListener(
'mouseDown',
function(client) {
1547 if ( oConfig.fnClick !== null )
1549 oConfig.fnClick.call( that, nButton, oConfig, flash );
1553 flash.addEventListener(
'complete',
function (client, text) {
1554 if ( oConfig.fnComplete !== null )
1556 oConfig.fnComplete.call( that, nButton, oConfig, flash, text );
1558 that._fnCollectionHide( nButton, oConfig );
1561 if ( oConfig.fnSelect !== null )
1563 TableTools._fnEventListen(
this,
'select',
function (n) {
1564 oConfig.fnSelect.call( that, nButton, oConfig, n );
1568 this._fnFlashGlue( flash, nButton, oConfig.sToolTip );
1582 "_fnFlashGlue":
function ( flash, node, text )
1585 var
id = node.getAttribute(
'id');
1587 if ( document.getElementById(
id) )
1589 flash.glue( node, text );
1593 setTimeout(
function () {
1594 that._fnFlashGlue( flash, node, text );
1614 "_fnFlashSetText":
function ( clip, sData )
1616 var asData = this._fnChunkData( sData, 8192 );
1619 for ( var i=0, iLen=asData.length ; i<iLen ; i++ )
1621 clip.appendText( asData[i] );
1642 "_fnColumnTargets":
function ( mColumns )
1647 var columns = dt.aoColumns;
1648 var columnCount = columns.length;
1650 if ( typeof mColumns ==
"function" )
1652 var a = mColumns.call(
this, dt );
1654 for ( i=0, iLen=columnCount ; i<iLen ; i++ )
1656 aColumns.push( $.inArray( i, a ) !== -1 ?
true :
false );
1659 else if ( typeof mColumns ==
"object" )
1661 for ( i=0, iLen=columnCount ; i<iLen ; i++ )
1663 aColumns.push(
false );
1666 for ( i=0, iLen=mColumns.length ; i<iLen ; i++ )
1668 aColumns[ mColumns[i] ] =
true;
1671 else if ( mColumns ==
"visible" )
1673 for ( i=0, iLen=columnCount ; i<iLen ; i++ )
1675 aColumns.push( columns[i].bVisible ?
true :
false );
1678 else if ( mColumns ==
"hidden" )
1680 for ( i=0, iLen=columnCount ; i<iLen ; i++ )
1682 aColumns.push( columns[i].bVisible ?
false :
true );
1685 else if ( mColumns ==
"sortable" )
1687 for ( i=0, iLen=columnCount ; i<iLen ; i++ )
1689 aColumns.push( columns[i].bSortable ?
true :
false );
1694 for ( i=0, iLen=columnCount ; i<iLen ; i++ )
1696 aColumns.push(
true );
1710 "_fnNewline":
function ( oConfig )
1712 if ( oConfig.sNewLine ==
"auto" )
1714 return navigator.userAgent.match(/Windows/) ?
"\r\n" :
"\n";
1718 return oConfig.sNewLine;
1737 "_fnGetDataTablesData":
function ( oConfig )
1739 var i, iLen, j, jLen;
1740 var aRow, aData=[], sLoopData=
'', arr;
1741 var dt = this.s.dt, tr, child;
1742 var regex =
new RegExp(oConfig.sFieldBoundary,
"g");
1743 var aColumnsInc = this._fnColumnTargets( oConfig.mColumns );
1744 var bSelectedOnly = (typeof oConfig.bSelectedOnly !=
'undefined') ? oConfig.bSelectedOnly :
false;
1749 if ( oConfig.bHeader )
1753 for ( i=0, iLen=dt.aoColumns.length ; i<iLen ; i++ )
1755 if ( aColumnsInc[i] )
1757 sLoopData = dt.aoColumns[i].sTitle.replace(/\n/g,
" ").replace( /<.*?>/g,
"" ).replace(/^\s+|\s+$/g,
"");
1758 sLoopData = this._fnHtmlDecode( sLoopData );
1760 aRow.push( this._fnBoundData( sLoopData, oConfig.sFieldBoundary, regex ) );
1764 aData.push( aRow.join(oConfig.sFieldSeperator) );
1767 bSelectedOnly =
true;
1773 var aSelected = this.fnGetSelectedIndexes();
1774 bSelectedOnly = this.s.select.type !==
"none" && bSelectedOnly && aSelected.length !== 0;
1776 if ( bSelectedOnly ) {
1778 aDataIndex = aSelected;
1780 else if ( DataTable.Api ) {
1782 aDataIndex =
new DataTable.Api( dt )
1783 .rows( oConfig.oSelectorOpts )
1790 aDataIndex = dt.oInstance
1791 .$(
'tr', oConfig.oSelectorOpts)
1792 .map(
function (
id, row) {
1793 return dt.oInstance.fnGetPosition( row );
1798 for ( j=0, jLen=aDataIndex.length ; j<jLen ; j++ )
1800 tr = dt.aoData[ aDataIndex[j] ].nTr;
1804 for ( i=0, iLen=dt.aoColumns.length ; i<iLen ; i++ )
1806 if ( aColumnsInc[i] )
1809 var mTypeData = dt.oApi._fnGetCellData( dt, aDataIndex[j], i,
'display' );
1810 if ( oConfig.fnCellRender )
1812 sLoopData = oConfig.fnCellRender( mTypeData, i, tr, aDataIndex[j] )+
"";
1814 else if ( typeof mTypeData ==
"string" )
1817 sLoopData = mTypeData.replace(/\n/g,
" ");
1819 sLoopData.replace(/<img.*?\s+alt\s*=\s*(?:
"([^"]+)
"|'([^']+)'|([^\s>]+)).*?>/gi,
1821 sLoopData = sLoopData.replace( /<.*?>/g, "" );
1825 sLoopData = mTypeData+"";
1828 /* Trim and clean the data */
1829 sLoopData = sLoopData.replace(/^\s+/, '').replace(/\s+$/, '');
1830 sLoopData = this._fnHtmlDecode( sLoopData );
1832 /* Bound it and add it to the total data */
1833 aRow.push( this._fnBoundData( sLoopData, oConfig.sFieldBoundary, regex ) );
1837 aData.push( aRow.join(oConfig.sFieldSeperator) );
1839 /* Details rows from fnOpen */
1840 if ( oConfig.bOpenRows )
1842 arr = $.grep(dt.aoOpenRows, function(o) { return o.nParent === tr; });
1844 if ( arr.length === 1 )
1846 sLoopData = this._fnBoundData( $('td', arr[0].nTr).html(), oConfig.sFieldBoundary, regex );
1847 aData.push( sLoopData );
1855 if ( oConfig.bFooter && dt.nTFoot !== null )
1859 for ( i=0, iLen=dt.aoColumns.length ; i<iLen ; i++ )
1861 if ( aColumnsInc[i] && dt.aoColumns[i].nTf !== null )
1863 sLoopData = dt.aoColumns[i].nTf.innerHTML.replace(/\n/g," ").replace( /<.*?>/g, "" );
1864 sLoopData = this._fnHtmlDecode( sLoopData );
1866 aRow.push( this._fnBoundData( sLoopData, oConfig.sFieldBoundary, regex ) );
1870 aData.push( aRow.join(oConfig.sFieldSeperator) );
1873 var _sLastData = aData.join( this._fnNewline(oConfig) );
1888 "_fnBoundData
": function ( sData, sBoundary, regex )
1890 if ( sBoundary === "" )
1896 return sBoundary + sData.replace(regex, sBoundary+sBoundary) + sBoundary;
1909 "_fnChunkData
": function ( sData, iSize )
1912 var iStrlen = sData.length;
1914 for ( var i=0 ; i<iStrlen ; i+=iSize )
1916 if ( i+iSize < iStrlen )
1918 asReturn.push( sData.substring( i, i+iSize ) );
1922 asReturn.push( sData.substring( i, iStrlen ) );
1937 "_fnHtmlDecode
": function ( sData )
1939 if ( sData.indexOf('&') === -1 )
1944 var n = document.createElement('div');
1946 return sData.replace( /&([^\s]*?);/g, function( match, match2 ) {
1947 if ( match.substr(1, 1) === '#' )
1949 return String.fromCharCode( Number(match2.substr(1)) );
1953 n.innerHTML = match;
1954 return n.childNodes[0].nodeValue;
1961 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1962 * Printing functions
1973 "_fnPrintStart
": function ( oConfig )
1976 var oSetDT = this.s.dt;
1978 /* Parse through the DOM hiding everything that isn't needed for the table */
1979 this._fnPrintHideNodes( oSetDT.nTable );
1981 /* Show the whole table */
1982 this.s.print.saveStart = oSetDT._iDisplayStart;
1983 this.s.print.saveLength = oSetDT._iDisplayLength;
1985 if ( oConfig.bShowAll )
1987 oSetDT._iDisplayStart = 0;
1988 oSetDT._iDisplayLength = -1;
1989 if ( oSetDT.oApi._fnCalculateEnd ) {
1990 oSetDT.oApi._fnCalculateEnd( oSetDT );
1992 oSetDT.oApi._fnDraw( oSetDT );
1995 /* Adjust the display for scrolling which might be done by DataTables */
1996 if ( oSetDT.oScroll.sX !== "" || oSetDT.oScroll.sY !== "" )
1998 this._fnPrintScrollStart( oSetDT );
2000 // If the table redraws while in print view, the DataTables scrolling
2001 // setup would hide the header, so we need to readd it on draw
2002 $(this.s.dt.nTable).bind('draw.DTTT_Print', function () {
2003 that._fnPrintScrollStart( oSetDT );
2007 /* Remove the other DataTables feature nodes - but leave the table! and info div */
2008 var anFeature = oSetDT.aanFeatures;
2009 for ( var cFeature in anFeature )
2011 if ( cFeature != 'i' && cFeature != 't' && cFeature.length == 1 )
2013 for ( var i=0, iLen=anFeature[cFeature].length ; i<iLen ; i++ )
2015 this.dom.print.hidden.push( {
2016 "node
": anFeature[cFeature][i],
2019 anFeature[cFeature][i].style.display = "none
";
2024 /* Print class can be used for styling */
2025 $(document.body).addClass( this.classes.print.body );
2027 /* Show information message to let the user know what is happening */
2028 if ( oConfig.sInfo !== "" )
2030 this.fnInfo( oConfig.sInfo, 3000 );
2033 /* Add a message at the top of the page */
2034 if ( oConfig.sMessage )
2037 .addClass( this.classes.print.message )
2038 .html( oConfig.sMessage )
2039 .prependTo( 'body' );
2042 /* Cache the scrolling and the jump to the top of the page */
2043 this.s.print.saveScroll = $(window).scrollTop();
2044 window.scrollTo( 0, 0 );
2046 /* Bind a key event listener to the document for the escape key -
2047 * it is removed in the callback
2049 $(document).bind( "keydown.DTTT
", function(e) {
2050 /* Only interested in the escape key */
2051 if ( e.keyCode == 27 )
2054 that._fnPrintEnd.call( that, e );
2067 "_fnPrintEnd
": function ( e )
2070 var oSetDT = this.s.dt;
2071 var oSetPrint = this.s.print;
2072 var oDomPrint = this.dom.print;
2074 /* Show all hidden nodes */
2075 this._fnPrintShowNodes();
2077 /* Restore DataTables' scrolling */
2078 if ( oSetDT.oScroll.sX !== "" || oSetDT.oScroll.sY !== "" )
2080 $(this.s.dt.nTable).unbind('draw.DTTT_Print');
2082 this._fnPrintScrollEnd();
2085 /* Restore the scroll */
2086 window.scrollTo( 0, oSetPrint.saveScroll );
2088 /* Drop the print message */
2089 $('div.'+this.classes.print.message).remove();
2092 $(document.body).removeClass( this.classes.print.body );
2094 /* Restore the table length */
2095 oSetDT._iDisplayStart = oSetPrint.saveStart;
2096 oSetDT._iDisplayLength = oSetPrint.saveLength;
2097 if ( oSetDT.oApi._fnCalculateEnd ) {
2098 oSetDT.oApi._fnCalculateEnd( oSetDT );
2100 oSetDT.oApi._fnDraw( oSetDT );
2102 $(document).unbind( "keydown.DTTT
" );
2111 "_fnPrintScrollStart
": function ()
2115 nScrollHeadInner = oSetDT.nScrollHead.getElementsByTagName('div')[0],
2116 nScrollHeadTable = nScrollHeadInner.getElementsByTagName('table')[0],
2117 nScrollBody = oSetDT.nTable.parentNode,
2118 nTheadSize, nTfootSize;
2120 /* Copy the header in the thead in the body table, this way we show one single table when
2121 * in print view. Note that this section of code is more or less verbatim from DT 1.7.0
2123 nTheadSize = oSetDT.nTable.getElementsByTagName('thead');
2124 if ( nTheadSize.length > 0 )
2126 oSetDT.nTable.removeChild( nTheadSize[0] );
2129 if ( oSetDT.nTFoot !== null )
2131 nTfootSize = oSetDT.nTable.getElementsByTagName('tfoot');
2132 if ( nTfootSize.length > 0 )
2134 oSetDT.nTable.removeChild( nTfootSize[0] );
2138 nTheadSize = oSetDT.nTHead.cloneNode(true);
2139 oSetDT.nTable.insertBefore( nTheadSize, oSetDT.nTable.childNodes[0] );
2141 if ( oSetDT.nTFoot !== null )
2143 nTfootSize = oSetDT.nTFoot.cloneNode(true);
2144 oSetDT.nTable.insertBefore( nTfootSize, oSetDT.nTable.childNodes[1] );
2147 /* Now adjust the table's viewport so we can actually see it */
2148 if ( oSetDT.oScroll.sX !== "" )
2150 oSetDT.nTable.style.width = $(oSetDT.nTable).outerWidth()+"px
";
2151 nScrollBody.style.width = $(oSetDT.nTable).outerWidth()+"px
";
2152 nScrollBody.style.overflow = "visible
";
2155 if ( oSetDT.oScroll.sY !== "" )
2157 nScrollBody.style.height = $(oSetDT.nTable).outerHeight()+"px
";
2158 nScrollBody.style.overflow = "visible
";
2169 "_fnPrintScrollEnd
": function ()
2173 nScrollBody = oSetDT.nTable.parentNode;
2175 if ( oSetDT.oScroll.sX !== "" )
2177 nScrollBody.style.width = oSetDT.oApi._fnStringToCss( oSetDT.oScroll.sX );
2178 nScrollBody.style.overflow = "auto";
2181 if ( oSetDT.oScroll.sY !== "" )
2183 nScrollBody.style.height = oSetDT.oApi._fnStringToCss( oSetDT.oScroll.sY );
2184 nScrollBody.style.overflow = "auto";
2195 "_fnPrintShowNodes
": function ( )
2197 var anHidden = this.dom.print.hidden;
2199 for ( var i=0, iLen=anHidden.length ; i<iLen ; i++ )
2201 anHidden[i].node.style.display = anHidden[i].display;
2203 anHidden.splice( 0, anHidden.length );
2215 "_fnPrintHideNodes
": function ( nNode )
2217 var anHidden = this.dom.print.hidden;
2219 var nParent = nNode.parentNode;
2220 var nChildren = nParent.childNodes;
2221 for ( var i=0, iLen=nChildren.length ; i<iLen ; i++ )
2223 if ( nChildren[i] != nNode && nChildren[i].nodeType == 1 )
2225 /* If our node is shown (don't want to show nodes which were previously hidden) */
2226 var sDisplay = $(nChildren[i]).css("display
");
2227 if ( sDisplay != "none
" )
2229 /* Cache the node and it's previous state so we can restore it */
2231 "node
": nChildren[i],
2234 nChildren[i].style.display = "none
";
2239 if ( nParent.nodeName.toUpperCase() != "BODY
" )
2241 this._fnPrintHideNodes( nParent );
2248 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2250 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2260 TableTools._aInstances = [];
2269 TableTools._aListeners = [];
2273 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2275 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2283 TableTools.fnGetMasters = function ()
2286 for ( var i=0, iLen=TableTools._aInstances.length ; i<iLen ; i++ )
2288 if ( TableTools._aInstances[i].s.master )
2290 a.push( TableTools._aInstances[i] );
2302 TableTools.fnGetInstance = function ( node )
2304 if ( typeof node != 'object' )
2306 node = document.getElementById(node);
2309 for ( var i=0, iLen=TableTools._aInstances.length ; i<iLen ; i++ )
2311 if ( TableTools._aInstances[i].s.master && TableTools._aInstances[i].dom.table == node )
2313 return TableTools._aInstances[i];
2330 TableTools._fnEventListen = function ( that, type, fn )
2332 TableTools._aListeners.push( {
2352 TableTools._fnEventDispatch = function ( that, type, node, selected )
2354 var listeners = TableTools._aListeners;
2355 for ( var i=0, iLen=listeners.length ; i<iLen ; i++ )
2357 if ( that.dom.table == listeners[i].that.dom.table && listeners[i].type == type )
2359 listeners[i].fn( node, selected );
2369 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2371 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2375 TableTools.buttonBase = {
2379 "sLinerTag
": "default",
2380 "sButtonClass
": "DTTT_button_text
",
2381 "sButtonText
": "Button text
",
2385 // Common button specific options
2388 "sFileName
": "*.csv
",
2389 "sFieldBoundary
": "",
2390 "sFieldSeperator
": "\t
",
2392 "mColumns
": "all
", /* "all
", "visible
", "hidden
" or array of column integers */
2396 "bSelectedOnly
": false,
2397 "oSelectorOpts
": undefined, // See http://datatables.net/docs/DataTables/1.9.4/#$ for full options
2400 "fnMouseover
": null,
2406 "fnCellRender
": null
2413 TableTools.BUTTONS = {
2414 "csv
": $.extend( {}, TableTools.buttonBase, {
2415 "sAction
": "flash_save
",
2416 "sButtonClass
": "DTTT_button_csv
",
2417 "sButtonText
": "CSV
",
2418 "sFieldBoundary
": '"',
2419 "sFieldSeperator": ",",
2420 "fnClick": function( nButton, oConfig, flash ) {
2421 this.fnSetText( flash, this.fnGetTableData(oConfig) );
2425 "xls": $.extend( {}, TableTools.buttonBase, {
2426 "sAction": "flash_save",
2427 "sCharSet": "utf16le",
2429 "sButtonClass": "DTTT_button_xls",
2430 "sButtonText": "Excel",
2431 "fnClick": function( nButton, oConfig, flash ) {
2432 this.fnSetText( flash, this.fnGetTableData(oConfig) );
2436 "copy": $.extend( {}, TableTools.buttonBase, {
2437 "sAction": "flash_copy",
2438 "sButtonClass": "DTTT_button_copy",
2439 "sButtonText": "Copy",
2440 "fnClick": function( nButton, oConfig, flash ) {
2441 this.fnSetText( flash, this.fnGetTableData(oConfig) );
2443 "fnComplete": function(nButton, oConfig, flash, text) {
2444 var lines = text.split('\n
').length;
2445 if (oConfig.bHeader) lines--;
2446 if (this.s.dt.nTFoot !== null && oConfig.bFooter) lines--;
2447 var plural = (lines==1) ? "" : "s";
2448 this.fnInfo( '<h6>Table copied</h6>
'+
2449 '<p>Copied
'+lines+' row
'+plural+' to the clipboard.</p>
',
2455 "pdf": $.extend( {}, TableTools.buttonBase, {
2456 "sAction": "flash_pdf",
2458 "sFileName": "*.pdf",
2459 "sButtonClass": "DTTT_button_pdf",
2460 "sButtonText": "PDF",
2461 "sPdfOrientation": "portrait",
2464 "fnClick": function( nButton, oConfig, flash ) {
2465 this.fnSetText( flash,
2466 "title:"+ this.fnGetTitle(oConfig) +"\n"+
2467 "message:"+ oConfig.sPdfMessage +"\n"+
2468 "colWidth:"+ this.fnCalcColRatios(oConfig) +"\n"+
2469 "orientation:"+ oConfig.sPdfOrientation +"\n"+
2470 "size:"+ oConfig.sPdfSize +"\n"+
2471 "--/TableToolsOpts--\n" +
2472 this.fnGetTableData(oConfig)
2477 "print": $.extend( {}, TableTools.buttonBase, {
2478 "sInfo": "<h6>Print view</h6><p>Please use your browser's print
function to
"+
2479 "print
this table. Press escape when finished.</p>
",
2482 "sToolTip
": "View print view
",
2483 "sButtonClass
": "DTTT_button_print
",
2484 "sButtonText
": "Print
",
2485 "fnClick
": function ( nButton, oConfig ) {
2486 this.fnPrint( true, oConfig );
2490 "text
": $.extend( {}, TableTools.buttonBase ),
2492 "select
": $.extend( {}, TableTools.buttonBase, {
2493 "sButtonText
": "Select button
",
2494 "fnSelect
": function( nButton, oConfig ) {
2495 if ( this.fnGetSelected().length !== 0 ) {
2496 $(nButton).removeClass( this.classes.buttons.disabled );
2498 $(nButton).addClass( this.classes.buttons.disabled );
2501 "fnInit
": function( nButton, oConfig ) {
2502 $(nButton).addClass( this.classes.buttons.disabled );
2506 "select_single
": $.extend( {}, TableTools.buttonBase, {
2507 "sButtonText
": "Select button
",
2508 "fnSelect
": function( nButton, oConfig ) {
2509 var iSelected = this.fnGetSelected().length;
2510 if ( iSelected == 1 ) {
2511 $(nButton).removeClass( this.classes.buttons.disabled );
2513 $(nButton).addClass( this.classes.buttons.disabled );
2516 "fnInit
": function( nButton, oConfig ) {
2517 $(nButton).addClass( this.classes.buttons.disabled );
2521 "select_all
": $.extend( {}, TableTools.buttonBase, {
2522 "sButtonText
": "Select all
",
2523 "fnClick
": function( nButton, oConfig ) {
2526 "fnSelect
": function( nButton, oConfig ) {
2527 if ( this.fnGetSelected().length == this.s.dt.fnRecordsDisplay() ) {
2528 $(nButton).addClass( this.classes.buttons.disabled );
2530 $(nButton).removeClass( this.classes.buttons.disabled );
2535 "select_none
": $.extend( {}, TableTools.buttonBase, {
2536 "sButtonText
": "Deselect all
",
2537 "fnClick
": function( nButton, oConfig ) {
2538 this.fnSelectNone();
2540 "fnSelect
": function( nButton, oConfig ) {
2541 if ( this.fnGetSelected().length !== 0 ) {
2542 $(nButton).removeClass( this.classes.buttons.disabled );
2544 $(nButton).addClass( this.classes.buttons.disabled );
2547 "fnInit
": function( nButton, oConfig ) {
2548 $(nButton).addClass( this.classes.buttons.disabled );
2552 "ajax
": $.extend( {}, TableTools.buttonBase, {
2553 "sAjaxUrl
": "/xhr.php
",
2554 "sButtonText
": "Ajax button
",
2555 "fnClick
": function( nButton, oConfig ) {
2556 var sData = this.fnGetTableData(oConfig);
2558 "url": oConfig.sAjaxUrl,
2560 { "name
": "tableData
", "value
": sData }
2562 "success
": oConfig.fnAjaxComplete,
2566 "error
": function () {
2567 alert( "Error detected when sending table data to server
" );
2571 "fnAjaxComplete
": function( json ) {
2572 alert( 'Ajax complete' );
2576 "div
": $.extend( {}, TableTools.buttonBase, {
2579 "sButtonClass
": "DTTT_nonbutton
",
2580 "sButtonText
": "Text button
"
2583 "collection
": $.extend( {}, TableTools.buttonBase, {
2584 "sAction
": "collection
",
2585 "sButtonClass
": "DTTT_button_collection
",
2586 "sButtonText
": "Collection
",
2587 "fnClick
": function( nButton, oConfig ) {
2588 this._fnCollectionShow(nButton, oConfig);
2593 * on* callback parameters:
2594 * 1. node - button element
2595 * 2. object - configuration object for this button
2596 * 3. object - ZeroClipboard reference (flash button only)
2597 * 4. string - Returned string from Flash (flash button only - and only on 'complete')
2600 // Alias to match the other plug-ins styling
2601 TableTools.buttons = TableTools.BUTTONS;
2609 TableTools.classes = {
2610 "container
": "DTTT_container
",
2612 "normal
": "DTTT_button
",
2613 "disabled
": "DTTT_disabled
"
2616 "container
": "DTTT_collection
",
2617 "background
": "DTTT_collection_background
",
2619 "normal
": "DTTT_button
",
2620 "disabled
": "DTTT_disabled
"
2624 "table
": "DTTT_selectable
",
2625 "row
": "DTTT_selected selected
"
2628 "body
": "DTTT_Print
",
2629 "info
": "DTTT_print_info
",
2630 "message
": "DTTT_PrintMessage
"
2639 TableTools.classes_themeroller = {
2640 "container
": "DTTT_container ui-buttonset ui-buttonset-multi
",
2642 "normal
": "DTTT_button ui-button ui-state-
default"
2645 "container
": "DTTT_collection ui-buttonset ui-buttonset-multi
"
2653 TableTools.DEFAULTS = {
2654 "sSwfPath
": "../swf/copy_csv_xls_pdf.swf
",
2655 "sRowSelect
": "none
",
2656 "sRowSelector
": "tr
",
2657 "sSelectedClass
": null,
2658 "fnPreRowSelect
": null,
2659 "fnRowSelected
": null,
2660 "fnRowDeselected
": null,
2661 "aButtons
": [ "copy
", "csv
", "xls
", "pdf
", "print
" ],
2664 "button
": "a
", // We really want to use buttons here, but Firefox and IE ignore the
2665 // click on the Flash element in the button (but not mouse[in|out]).
2675 // Alias to match the other plug-ins
2676 TableTools.defaults = TableTools.DEFAULTS;
2685 TableTools.prototype.CLASS = "TableTools
";
2694 TableTools.version = "2.2.4
";
2698 // DataTables 1.10 API
2700 // This will be extended in a big way in in TableTools 3 to provide API methods
2701 // such as rows().select() and rows.selected() etc, but for the moment the
2702 // tabletools() method simply returns the instance.
2704 if ( $.fn.dataTable.Api ) {
2705 $.fn.dataTable.Api.register( 'tabletools()', function () {
2708 if ( this.context.length > 0 ) {
2709 tt = TableTools.fnGetInstance( this.context[0].nTable );
2719 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2721 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2724 * Register a new feature with DataTables
2726 if ( typeof $.fn.dataTable == "function" &&
2727 typeof $.fn.dataTableExt.fnVersionCheck == "function" &&
2728 $.fn.dataTableExt.fnVersionCheck('1.9.0') )
2730 $.fn.dataTableExt.aoFeatures.push( {
2731 "fnInit
": function( oDTSettings ) {
2732 var init = oDTSettings.oInit;
2734 init.tableTools || init.oTableTools || {} :
2737 return new TableTools( oDTSettings.oInstance, opts ).dom.container;
2740 "sFeature
": "TableTools
"
2745 alert( "Warning: TableTools requires DataTables 1.9.0 or newer - www.datatables.net/download
");
2748 $.fn.DataTable.TableTools = TableTools;
2750 })(jQuery, window, document);