/src/webapp/script/jqueryplugins/dataTables/extras/TableTools/media/js/TableTools.js

http://github.com/bogeblad/infoglue · JavaScript · 530 lines · 303 code · 78 blank · 149 comment · 39 complexity · 4ebc1d4abdbf9b33f6194a00ec163649 MD5 · raw file

  1. /*
  2. * File: TableTools.js
  3. * Version: 1.0.3
  4. * CVS: $Id: TableTools.js,v 1.1 2009/10/08 21:47:40 mattias Exp $
  5. * Description: Copy, save and print functions for DataTables
  6. * Author: Allan Jardine (www.sprymedia.co.uk)
  7. * Created: Wed 1 Apr 2009 08:41:58 BST
  8. * Modified: $Date: 2009/10/08 21:47:40 $ by $Author: mattias $
  9. * Language: Javascript
  10. * License: LGPL
  11. * Project: Just a little bit of fun :-)
  12. * Contact: www.sprymedia.co.uk/contact
  13. *
  14. * Copyright 2009 Allan Jardine, all rights reserved.
  15. *
  16. */
  17. /*
  18. * Variable: TableToolsInit
  19. * Purpose: Parameters for TableTools customisation
  20. * Scope: global
  21. */
  22. var TableToolsInit = {
  23. "oFeatures": {
  24. "bCsv": true,
  25. "bXls": true,
  26. "bCopy": true,
  27. "bPrint": true
  28. },
  29. "sPrintMessage": "",
  30. "sTitle": "",
  31. "sSwfPath": "media/swf/ZeroClipboard.swf",
  32. "iButtonHeight": 30,
  33. "iButtonWidth": 30,
  34. "_iNextId": 1 /* Internal useage - but needs to be global */
  35. };
  36. (function($) {
  37. /*
  38. * Function: TableTools
  39. * Purpose: TableTools "class"
  40. * Returns: same as _fnInit
  41. * Inputs: same as _fnInit
  42. */
  43. function TableTools ( oInit )
  44. {
  45. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  46. * Private parameters
  47. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  48. var _oSettings;
  49. var nTools = null;
  50. var _nTableWrapper;
  51. var _aoPrintHidden = [];
  52. var _iPrintScroll = 0;
  53. var _nPrintMessage = null;
  54. var _DTSettings;
  55. var _sLastData;
  56. var _iId;
  57. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  58. * Initialisation
  59. */
  60. /*
  61. * Function: _fnInit
  62. * Purpose: Initialise the table tools
  63. * Returns: node: - The created node for the table tools wrapping
  64. * Inputs: object:oInit - object with:
  65. * oDTSettings - DataTables settings
  66. */
  67. function _fnInit( oInit )
  68. {
  69. _nTools = document.createElement('div');
  70. _nTools.className = "TableTools";
  71. _iId = TableToolsInit._iNextId++;
  72. /* Copy the init object */
  73. _oSettings = $.extend( true, {}, TableToolsInit );
  74. _DTSettings = oInit.oDTSettings;
  75. _nTableWrapper = fnFindParentClass( _DTSettings.nTable, "dataTables_wrapper" );
  76. ZeroClipboard.moviePath = _oSettings.sSwfPath;
  77. if ( _oSettings.oFeatures.bCopy ) {
  78. fnFeatureClipboard();
  79. }
  80. if ( _oSettings.oFeatures.bCsv ) {
  81. fnFeatureSaveCSV();
  82. }
  83. if ( _oSettings.oFeatures.bXls ) {
  84. fnFeatureSaveXLS();
  85. }
  86. if ( _oSettings.oFeatures.bPrint ) {
  87. fnFeaturePrint();
  88. }
  89. return _nTools;
  90. }
  91. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  92. * Feature buttons
  93. */
  94. /*
  95. * Function: fnFeatureSaveCSV
  96. * Purpose: Add a button for saving a CSV file
  97. * Returns: -
  98. * Inputs: -
  99. */
  100. function fnFeatureSaveCSV ()
  101. {
  102. var sBaseClass = "TableTools_button TableTools_csv";
  103. var nButton = document.createElement( 'div' );
  104. nButton.id = "ToolTables_CSV_"+_iId;
  105. nButton.style.height = _oSettings.iButtonHeight+'px';
  106. nButton.style.width = _oSettings.iButtonWidth+'px';
  107. nButton.className = sBaseClass;
  108. _nTools.appendChild( nButton );
  109. var clip = new ZeroClipboard.Client();
  110. clip.setHandCursor( true );
  111. clip.setAction( 'save' );
  112. clip.setFileName( fnGetTitle()+'.csv' );
  113. clip.addEventListener('mouseOver', function(client) {
  114. nButton.className = sBaseClass+'_hover';
  115. } );
  116. clip.addEventListener('mouseOut', function(client) {
  117. nButton.className = sBaseClass;
  118. } );
  119. clip.addEventListener('mouseDown', function(client) {
  120. clip.setText( fnGetDataTablesData(",") );
  121. } );
  122. fnGlue( clip, nButton, "ToolTables_CSV_"+_iId, "Save as CSV" );
  123. }
  124. /*
  125. * Function: fnFeatureSaveXLS
  126. * Purpose: Add a button for saving an XLS file
  127. * Returns: -
  128. * Inputs: -
  129. */
  130. function fnFeatureSaveXLS ()
  131. {
  132. var sBaseClass = "TableTools_button TableTools_xls";
  133. var nButton = document.createElement( 'div' );
  134. nButton.id = "ToolTables_XLS_"+_iId;
  135. nButton.style.height = _oSettings.iButtonHeight+'px';
  136. nButton.style.width = _oSettings.iButtonWidth+'px';
  137. nButton.className = sBaseClass;
  138. _nTools.appendChild( nButton );
  139. var clip = new ZeroClipboard.Client();
  140. clip.setHandCursor( true );
  141. clip.setAction( 'save' );
  142. clip.setFileName( fnGetTitle()+'.xls' );
  143. clip.addEventListener('mouseOver', function(client) {
  144. nButton.className = sBaseClass+'_hover';
  145. } );
  146. clip.addEventListener('mouseOut', function(client) {
  147. nButton.className = sBaseClass;
  148. } );
  149. clip.addEventListener('mouseDown', function(client) {
  150. clip.setText( fnGetDataTablesData("\t") );
  151. } );
  152. fnGlue( clip, nButton, "ToolTables_XLS_"+_iId, "Save for Excel" );
  153. }
  154. /*
  155. * Function: fnFeatureClipboard
  156. * Purpose: Add a button for copying data to clipboard
  157. * Returns: -
  158. * Inputs: -
  159. */
  160. function fnFeatureClipboard ()
  161. {
  162. var sBaseClass = "TableTools_button TableTools_clipboard";
  163. var nButton = document.createElement( 'div' );
  164. nButton.id = "ToolTables_Copy_"+_iId;
  165. nButton.style.height = _oSettings.iButtonHeight+'px';
  166. nButton.style.width = _oSettings.iButtonWidth+'px';
  167. nButton.className = sBaseClass;
  168. _nTools.appendChild( nButton );
  169. var clip = new ZeroClipboard.Client();
  170. clip.setHandCursor( true );
  171. clip.setAction( 'copy' );
  172. clip.addEventListener('mouseOver', function(client) {
  173. nButton.className = sBaseClass+'_hover';
  174. } );
  175. clip.addEventListener('mouseOut', function(client) {
  176. nButton.className = sBaseClass;
  177. } );
  178. clip.addEventListener('mouseDown', function(client) {
  179. clip.setText( fnGetDataTablesData("\t") );
  180. } );
  181. clip.addEventListener('complete', function (client, text) {
  182. var aData = _sLastData.split('\n');
  183. alert( 'Copied '+(aData.length-2)+' rows to the clipboard' );
  184. } );
  185. fnGlue( clip, nButton, "ToolTables_Copy_"+_iId, "Copy to clipboard" );
  186. }
  187. /*
  188. * Function: fnFeaturePrint
  189. * Purpose: Add a button for printing data
  190. * Returns: -
  191. * Inputs: -
  192. * Notes: Fun one this function. In order to print the table, we want the table to retain
  193. * it's position in the DOM, so all styles still apply, but we don't want to print all the
  194. * other nonesense. So we hide that nonesese and add an event handler for 'esc' which will
  195. * restore a normal view.
  196. */
  197. function fnFeaturePrint ()
  198. {
  199. var sBaseClass = "TableTools_button TableTools_print";
  200. var nButton = document.createElement( 'div' );
  201. nButton.style.height = _oSettings.iButtonHeight+'px';
  202. nButton.style.width = _oSettings.iButtonWidth+'px';
  203. nButton.className = sBaseClass;
  204. nButton.title = "Print table";
  205. _nTools.appendChild( nButton );
  206. /* Could do this in CSS - but might as well be consistent with the flash buttons */
  207. $(nButton).hover( function(client) {
  208. nButton.className = sBaseClass+'_hover';
  209. }, function(client) {
  210. nButton.className = sBaseClass;
  211. } );
  212. $(nButton).click( function() {
  213. /* Parse through the DOM hiding everything that isn't needed for the table */
  214. fnPrintHideNodes( _DTSettings.nTable );
  215. /* Show the whole table */
  216. _iPrintSaveLength = _DTSettings._iDisplayLength;
  217. _DTSettings._iDisplayLength = -1;
  218. _DTSettings.oApi._fnCalculateEnd( _DTSettings );
  219. _DTSettings.oApi._fnDraw( _DTSettings );
  220. /* Remove the other DataTables feature nodes - but leave the table! and info div */
  221. var anFeature = _DTSettings.anFeatures;
  222. for ( var cFeature in anFeature )
  223. {
  224. if ( cFeature != 'i' && cFeature != 't' )
  225. {
  226. _aoPrintHidden.push( {
  227. "node": anFeature[cFeature],
  228. "display": "block"
  229. } );
  230. anFeature[cFeature].style.display = "none";
  231. }
  232. }
  233. /* Add a node telling the user what is going on */
  234. var nInfo = document.createElement( "div" );
  235. nInfo.className = "TableTools_PrintInfo";
  236. nInfo.innerHTML = "<h6>Print view</h6><p>Please use your browser's print function to "+
  237. "print this table. Press escape when finished.";
  238. document.body.appendChild( nInfo );
  239. /* Add a message at the top of the page */
  240. if ( _oSettings.sPrintMessage != "" )
  241. {
  242. _nPrintMessage = document.createElement( "p" );
  243. _nPrintMessage.className = "TableTools_PrintMessage";
  244. _nPrintMessage.innerHTML = _oSettings.sPrintMessage;
  245. document.body.insertBefore( _nPrintMessage, document.body.childNodes[0] );
  246. }
  247. /* Cache the scrolling and the jump to the top of the t=page */
  248. _iPrintScroll = $(window).scrollTop();
  249. window.scrollTo( 0, 0 );
  250. $(document).bind( "keydown", null, fnPrintEnd );
  251. setTimeout( function() {
  252. $(nInfo).fadeOut( "normal", function() {
  253. document.body.removeChild( nInfo );
  254. } );
  255. }, 2000 );
  256. } );
  257. }
  258. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  259. * Printing functions
  260. */
  261. /*
  262. * Function: fnPrintEnd
  263. * Purpose: Printing is finished, resume normal display
  264. * Returns: -
  265. * Inputs: event
  266. */
  267. function fnPrintEnd ( e )
  268. {
  269. /* Only interested in the escape key */
  270. if ( e.keyCode == 27 )
  271. {
  272. /* Show all hidden nodes */
  273. fnPrintShowNodes();
  274. /* Restore the scroll */
  275. window.scrollTo( 0, _iPrintScroll );
  276. /* Drop the print message */
  277. if ( _nPrintMessage )
  278. {
  279. document.body.removeChild( _nPrintMessage );
  280. _nPrintMessage = null;
  281. }
  282. /* Restore the table length */
  283. _DTSettings._iDisplayLength = _iPrintSaveLength;
  284. _DTSettings.oApi._fnCalculateEnd( _DTSettings );
  285. _DTSettings.oApi._fnDraw( _DTSettings );
  286. $(document).unbind( "keypress", fnPrintEnd );
  287. }
  288. }
  289. /*
  290. * Function: fnPrintShowNodes
  291. * Purpose: Resume the display of all TableTools hidden nodes
  292. * Returns: -
  293. * Inputs: -
  294. */
  295. function fnPrintShowNodes( )
  296. {
  297. for ( var i=0, iLen=_aoPrintHidden.length ; i<iLen ; i++ )
  298. {
  299. _aoPrintHidden[i].node.style.display = _aoPrintHidden[i].display;
  300. }
  301. _aoPrintHidden.splice( 0, _aoPrintHidden.length );
  302. }
  303. /*
  304. * Function: fnPrintHideNodes
  305. * Purpose: Hide nodes which are not needed in order to display the table
  306. * Returns: -
  307. * Inputs: node:nNode - the table node - we parse back up
  308. * Notes: Recursive
  309. */
  310. function fnPrintHideNodes( nNode )
  311. {
  312. var nParent = nNode.parentNode;
  313. var nChildren = nParent.childNodes;
  314. for ( var i=0, iLen=nChildren.length ; i<iLen ; i++ )
  315. {
  316. if ( nChildren[i] != nNode && nChildren[i].nodeType == 1 )
  317. {
  318. /* If our node is shown (don't want to show nodes which were previously hidden) */
  319. var sDisplay = $(nChildren[i]).css("display");
  320. if ( sDisplay != "none" )
  321. {
  322. /* Cache the node and it's previous state so we can restore it */
  323. _aoPrintHidden.push( {
  324. "node": nChildren[i],
  325. "display": sDisplay
  326. } );
  327. nChildren[i].style.display = "none";
  328. }
  329. }
  330. }
  331. if ( nParent.nodeName != "BODY" )
  332. {
  333. fnPrintHideNodes( nParent );
  334. }
  335. }
  336. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  337. * Support functions
  338. */
  339. /*
  340. * Function: fnGlue
  341. * Purpose: Wait until the id is in the DOM before we "glue" the swf
  342. * Returns: -
  343. * Inputs: object:clip - Zero clipboard object
  344. * node:node - node to glue swf to
  345. * string:id - id of the element to look for
  346. * string:text - title of the flash movie
  347. * Notes: Recursive (setTimeout)
  348. */
  349. function fnGlue ( clip, node, id, text )
  350. {
  351. if ( document.getElementById(id) )
  352. {
  353. clip.glue( node, text );
  354. }
  355. else
  356. {
  357. setTimeout( function () {
  358. fnGlue( clip, node, id, text );
  359. }, 100 );
  360. }
  361. }
  362. /*
  363. * Function: fnGetTitle
  364. * Purpose: Get the title of the page (from DOM or user set) for file saving
  365. * Returns:
  366. * Inputs:
  367. */
  368. function fnGetTitle( )
  369. {
  370. if ( _oSettings.sTitle != "" )
  371. return _oSettings.sTitle;
  372. else
  373. return document.getElementsByTagName('title')[0].innerHTML;
  374. }
  375. /*
  376. * Function: fnFindParentClass
  377. * Purpose: Parse back up the DOM to a node with a particular node
  378. * Returns: node: - found node
  379. * Inputs: node:n - Node to test
  380. * string:sClass - class to find
  381. * Notes: Recursive
  382. */
  383. function fnFindParentClass ( n, sClass )
  384. {
  385. if ( n.className.match(sClass) || n.nodeName == "BODY" )
  386. return n;
  387. else
  388. return fnFindParentClass( n.parentNode, sClass );
  389. }
  390. /*
  391. * Function: fnGetDataTablesData
  392. * Purpose: Get data from DataTables' internals and format it for output
  393. * Returns:
  394. * Inputs:
  395. */
  396. function fnGetDataTablesData( sSeperator )
  397. {
  398. var i, iLen;
  399. var j, jLen;
  400. var sData = '';
  401. var sNewline = navigator.userAgent.match(/Windows/) ? "\r\n" : "\n";
  402. /* Titles */
  403. for ( i=0, iLen=_DTSettings.aoColumns.length ; i<iLen ; i++ )
  404. {
  405. if ( _DTSettings.aoColumns[i].bVisible )
  406. {
  407. sData += _DTSettings.aoColumns[i].sTitle.replace(/\n/g," ").replace( /<.*?>/g, "" ) +sSeperator;
  408. }
  409. }
  410. sData = sData.slice( 0, sSeperator.length*-1 );
  411. sData += sNewline;
  412. /* Rows */
  413. for ( j=0, jLen=_DTSettings.aiDisplay.length ; j<jLen ; j++ )
  414. {
  415. /* Columns */
  416. for ( i=0, iLen=_DTSettings.aoColumns.length ; i<iLen ; i++ )
  417. {
  418. if ( _DTSettings.aoColumns[i].bVisible )
  419. {
  420. sData += _DTSettings.aoData[ _DTSettings.aiDisplay[j] ]._aData[ i ].replace(/\n/g," ").replace( /<.*?>/g, "" ) +sSeperator;
  421. }
  422. }
  423. sData = sData.slice( 0, sSeperator.length*-1 );
  424. sData += sNewline;
  425. }
  426. /* Remove the last new line */
  427. sData.slice( 0, -1 );
  428. _sLastData = sData;
  429. return sData;
  430. }
  431. /* Initialise our new object */
  432. return _fnInit( oInit );
  433. }
  434. /*
  435. * Register a new feature with DataTables
  436. */
  437. if ( typeof $.fn.dataTable == "function" && typeof $.fn.dataTableExt.sVersion != "undefined" )
  438. {
  439. $.fn.dataTableExt.aoFeatures.push( {
  440. "fnInit": function( oSettings ) {
  441. return new TableTools( { "oDTSettings": oSettings } );
  442. },
  443. "cFeature": "T",
  444. "sFeature": "TableTools"
  445. } );
  446. }
  447. else
  448. {
  449. alert( "Warning: TableTools requires DataTables 1.5 beta 9 or greater - "+
  450. "www.datatables.net/download");
  451. }
  452. })(jQuery);