dataTables.colVis.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107
  1. /*! ColVis 1.1.1
  2. * ©2010-2014 SpryMedia Ltd - datatables.net/license
  3. */
  4. /**
  5. * @summary ColVis
  6. * @description Controls for column visibility in DataTables
  7. * @version 1.1.1
  8. * @file dataTables.colReorder.js
  9. * @author SpryMedia Ltd (www.sprymedia.co.uk)
  10. * @contact www.sprymedia.co.uk/contact
  11. * @copyright Copyright 2010-2014 SpryMedia Ltd.
  12. *
  13. * This source file is free software, available under the following license:
  14. * MIT license - http://datatables.net/license/mit
  15. *
  16. * This source file is distributed in the hope that it will be useful, but
  17. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  18. * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
  19. *
  20. * For details please refer to: http://www.datatables.net
  21. */
  22. (function(window, document, undefined) {
  23. var factory = function( $, DataTable ) {
  24. "use strict";
  25. /**
  26. * ColVis provides column visibility control for DataTables
  27. *
  28. * @class ColVis
  29. * @constructor
  30. * @param {object} DataTables settings object. With DataTables 1.10 this can
  31. * also be and API instance, table node, jQuery collection or jQuery selector.
  32. * @param {object} ColVis configuration options
  33. */
  34. var ColVis = function( oDTSettings, oInit )
  35. {
  36. /* Santiy check that we are a new instance */
  37. if ( !this.CLASS || this.CLASS != "ColVis" )
  38. {
  39. alert( "Warning: ColVis must be initialised with the keyword 'new'" );
  40. }
  41. if ( typeof oInit == 'undefined' )
  42. {
  43. oInit = {};
  44. }
  45. if ( $.fn.dataTable.camelToHungarian ) {
  46. $.fn.dataTable.camelToHungarian( ColVis.defaults, oInit );
  47. }
  48. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  49. * Public class variables
  50. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  51. /**
  52. * @namespace Settings object which contains customisable information for
  53. * ColVis instance. Augmented by ColVis.defaults
  54. */
  55. this.s = {
  56. /**
  57. * DataTables settings object
  58. * @property dt
  59. * @type Object
  60. * @default null
  61. */
  62. "dt": null,
  63. /**
  64. * Customisation object
  65. * @property oInit
  66. * @type Object
  67. * @default passed in
  68. */
  69. "oInit": oInit,
  70. /**
  71. * Flag to say if the collection is hidden
  72. * @property hidden
  73. * @type boolean
  74. * @default true
  75. */
  76. "hidden": true,
  77. /**
  78. * Store the original visibility settings so they could be restored
  79. * @property abOriginal
  80. * @type Array
  81. * @default []
  82. */
  83. "abOriginal": []
  84. };
  85. /**
  86. * @namespace Common and useful DOM elements for the class instance
  87. */
  88. this.dom = {
  89. /**
  90. * Wrapper for the button - given back to DataTables as the node to insert
  91. * @property wrapper
  92. * @type Node
  93. * @default null
  94. */
  95. "wrapper": null,
  96. /**
  97. * Activation button
  98. * @property button
  99. * @type Node
  100. * @default null
  101. */
  102. "button": null,
  103. /**
  104. * Collection list node
  105. * @property collection
  106. * @type Node
  107. * @default null
  108. */
  109. "collection": null,
  110. /**
  111. * Background node used for shading the display and event capturing
  112. * @property background
  113. * @type Node
  114. * @default null
  115. */
  116. "background": null,
  117. /**
  118. * Element to position over the activation button to catch mouse events when using mouseover
  119. * @property catcher
  120. * @type Node
  121. * @default null
  122. */
  123. "catcher": null,
  124. /**
  125. * List of button elements
  126. * @property buttons
  127. * @type Array
  128. * @default []
  129. */
  130. "buttons": [],
  131. /**
  132. * List of group button elements
  133. * @property groupButtons
  134. * @type Array
  135. * @default []
  136. */
  137. "groupButtons": [],
  138. /**
  139. * Restore button
  140. * @property restore
  141. * @type Node
  142. * @default null
  143. */
  144. "restore": null
  145. };
  146. /* Store global reference */
  147. ColVis.aInstances.push( this );
  148. /* Constructor logic */
  149. this.s.dt = $.fn.dataTable.Api ?
  150. new $.fn.dataTable.Api( oDTSettings ).settings()[0] :
  151. oDTSettings;
  152. this._fnConstruct( oInit );
  153. return this;
  154. };
  155. ColVis.prototype = {
  156. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  157. * Public methods
  158. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  159. /**
  160. * Get the ColVis instance's control button so it can be injected into the
  161. * DOM
  162. * @method button
  163. * @returns {node} ColVis button
  164. */
  165. button: function ()
  166. {
  167. return this.dom.wrapper;
  168. },
  169. /**
  170. * Alias of `rebuild` for backwards compatibility
  171. * @method fnRebuild
  172. */
  173. "fnRebuild": function ()
  174. {
  175. this.rebuild();
  176. },
  177. /**
  178. * Rebuild the list of buttons for this instance (i.e. if there is a column
  179. * header update)
  180. * @method fnRebuild
  181. */
  182. rebuild: function ()
  183. {
  184. /* Remove the old buttons */
  185. for ( var i=this.dom.buttons.length-1 ; i>=0 ; i-- ) {
  186. this.dom.collection.removeChild( this.dom.buttons[i] );
  187. }
  188. this.dom.buttons.splice( 0, this.dom.buttons.length );
  189. if ( this.dom.restore ) {
  190. this.dom.restore.parentNode( this.dom.restore );
  191. }
  192. /* Re-add them (this is not the optimal way of doing this, it is fast and effective) */
  193. this._fnAddGroups();
  194. this._fnAddButtons();
  195. /* Update the checkboxes */
  196. this._fnDrawCallback();
  197. },
  198. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  199. * Private methods (they are of course public in JS, but recommended as private)
  200. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  201. /**
  202. * Constructor logic
  203. * @method _fnConstruct
  204. * @returns void
  205. * @private
  206. */
  207. "_fnConstruct": function ( init )
  208. {
  209. this._fnApplyCustomisation( init );
  210. var that = this;
  211. var i, iLen;
  212. this.dom.wrapper = document.createElement('div');
  213. this.dom.wrapper.className = "ColVis";
  214. this.dom.button = $( '<button />', {
  215. 'class': !this.s.dt.bJUI ?
  216. "ColVis_Button ColVis_MasterButton" :
  217. "ColVis_Button ColVis_MasterButton ui-button ui-state-default"
  218. } )
  219. .append( '<span>'+this.s.buttonText+'</span>' )
  220. .bind( this.s.activate=="mouseover" ? "mouseover" : "click", function (e) {
  221. e.preventDefault();
  222. that._fnCollectionShow();
  223. } )
  224. .appendTo( this.dom.wrapper )[0];
  225. this.dom.catcher = this._fnDomCatcher();
  226. this.dom.collection = this._fnDomCollection();
  227. this.dom.background = this._fnDomBackground();
  228. this._fnAddGroups();
  229. this._fnAddButtons();
  230. /* Store the original visibility information */
  231. for ( i=0, iLen=this.s.dt.aoColumns.length ; i<iLen ; i++ )
  232. {
  233. this.s.abOriginal.push( this.s.dt.aoColumns[i].bVisible );
  234. }
  235. /* Update on each draw */
  236. this.s.dt.aoDrawCallback.push( {
  237. "fn": function () {
  238. that._fnDrawCallback.call( that );
  239. },
  240. "sName": "ColVis"
  241. } );
  242. /* If columns are reordered, then we need to update our exclude list and
  243. * rebuild the displayed list
  244. */
  245. $(this.s.dt.oInstance).bind( 'column-reorder', function ( e, oSettings, oReorder ) {
  246. for ( i=0, iLen=that.s.aiExclude.length ; i<iLen ; i++ ) {
  247. that.s.aiExclude[i] = oReorder.aiInvertMapping[ that.s.aiExclude[i] ];
  248. }
  249. var mStore = that.s.abOriginal.splice( oReorder.iFrom, 1 )[0];
  250. that.s.abOriginal.splice( oReorder.iTo, 0, mStore );
  251. that.fnRebuild();
  252. } );
  253. // Set the initial state
  254. this._fnDrawCallback();
  255. },
  256. /**
  257. * Apply any customisation to the settings from the DataTables initialisation
  258. * @method _fnApplyCustomisation
  259. * @returns void
  260. * @private
  261. */
  262. "_fnApplyCustomisation": function ( init )
  263. {
  264. $.extend( true, this.s, ColVis.defaults, init );
  265. // Slightly messy overlap for the camelCase notation
  266. if ( ! this.s.showAll && this.s.bShowAll ) {
  267. this.s.showAll = this.s.sShowAll;
  268. }
  269. if ( ! this.s.restore && this.s.bRestore ) {
  270. this.s.restore = this.s.sRestore;
  271. }
  272. // CamelCase to Hungarian for the column groups
  273. var groups = this.s.groups;
  274. var hungarianGroups = this.s.aoGroups;
  275. if ( groups ) {
  276. for ( var i=0, ien=groups.length ; i<ien ; i++ ) {
  277. if ( groups[i].title ) {
  278. hungarianGroups[i].sTitle = groups[i].title;
  279. }
  280. if ( groups[i].columns ) {
  281. hungarianGroups[i].aiColumns = groups[i].columns;
  282. }
  283. }
  284. }
  285. },
  286. /**
  287. * On each table draw, check the visibility checkboxes as needed. This allows any process to
  288. * update the table's column visibility and ColVis will still be accurate.
  289. * @method _fnDrawCallback
  290. * @returns void
  291. * @private
  292. */
  293. "_fnDrawCallback": function ()
  294. {
  295. var columns = this.s.dt.aoColumns;
  296. var buttons = this.dom.buttons;
  297. var groups = this.s.aoGroups;
  298. var button;
  299. for ( var i=0, ien=buttons.length ; i<ien ; i++ ) {
  300. button = buttons[i];
  301. if ( button.__columnIdx !== undefined ) {
  302. $('input', button).prop( 'checked', columns[ button.__columnIdx ].bVisible );
  303. }
  304. }
  305. var allVisible = function ( columnIndeces ) {
  306. for ( var k=0, kLen=columnIndeces.length ; k<kLen ; k++ )
  307. {
  308. if ( columns[columnIndeces[k]].bVisible === false ) { return false; }
  309. }
  310. return true;
  311. };
  312. var allHidden = function ( columnIndeces ) {
  313. for ( var m=0 , mLen=columnIndeces.length ; m<mLen ; m++ )
  314. {
  315. if ( columns[columnIndeces[m]].bVisible === true ) { return false; }
  316. }
  317. return true;
  318. };
  319. for ( var j=0, jLen=groups.length ; j<jLen ; j++ )
  320. {
  321. if ( allVisible(groups[j].aiColumns) )
  322. {
  323. $('input', this.dom.groupButtons[j]).prop('checked', true);
  324. $('input', this.dom.groupButtons[j]).prop('indeterminate', false);
  325. }
  326. else if ( allHidden(groups[j].aiColumns) )
  327. {
  328. $('input', this.dom.groupButtons[j]).prop('checked', false);
  329. $('input', this.dom.groupButtons[j]).prop('indeterminate', false);
  330. }
  331. else
  332. {
  333. $('input', this.dom.groupButtons[j]).prop('indeterminate', true);
  334. }
  335. }
  336. },
  337. /**
  338. * Loop through the groups (provided in the settings) and create a button for each.
  339. * @method _fnAddgroups
  340. * @returns void
  341. * @private
  342. */
  343. "_fnAddGroups": function ()
  344. {
  345. var nButton;
  346. if ( typeof this.s.aoGroups != 'undefined' )
  347. {
  348. for ( var i=0, iLen=this.s.aoGroups.length ; i<iLen ; i++ )
  349. {
  350. nButton = this._fnDomGroupButton( i );
  351. this.dom.groupButtons.push( nButton );
  352. this.dom.buttons.push( nButton );
  353. this.dom.collection.appendChild( nButton );
  354. }
  355. }
  356. },
  357. /**
  358. * Loop through the columns in the table and as a new button for each one.
  359. * @method _fnAddButtons
  360. * @returns void
  361. * @private
  362. */
  363. "_fnAddButtons": function ()
  364. {
  365. var
  366. nButton,
  367. columns = this.s.dt.aoColumns;
  368. if ( $.inArray( 'all', this.s.aiExclude ) === -1 ) {
  369. for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
  370. {
  371. if ( $.inArray( i, this.s.aiExclude ) === -1 )
  372. {
  373. nButton = this._fnDomColumnButton( i );
  374. nButton.__columnIdx = i;
  375. this.dom.buttons.push( nButton );
  376. }
  377. }
  378. }
  379. if ( this.s.order === 'alpha' ) {
  380. this.dom.buttons.sort( function ( a, b ) {
  381. var titleA = columns[ a.__columnIdx ].sTitle;
  382. var titleB = columns[ b.__columnIdx ].sTitle;
  383. return titleA === titleB ?
  384. 0 :
  385. titleA < titleB ?
  386. -1 :
  387. 1;
  388. } );
  389. }
  390. if ( this.s.restore )
  391. {
  392. nButton = this._fnDomRestoreButton();
  393. nButton.className += " ColVis_Restore";
  394. this.dom.buttons.push( nButton );
  395. }
  396. if ( this.s.showAll )
  397. {
  398. nButton = this._fnDomShowXButton( this.s.showAll, true );
  399. nButton.className += " ColVis_ShowAll";
  400. this.dom.buttons.push( nButton );
  401. }
  402. if ( this.s.showNone )
  403. {
  404. nButton = this._fnDomShowXButton( this.s.showNone, false );
  405. nButton.className += " ColVis_ShowNone";
  406. this.dom.buttons.push( nButton );
  407. }
  408. $(this.dom.collection).append( this.dom.buttons );
  409. },
  410. /**
  411. * Create a button which allows a "restore" action
  412. * @method _fnDomRestoreButton
  413. * @returns {Node} Created button
  414. * @private
  415. */
  416. "_fnDomRestoreButton": function ()
  417. {
  418. var
  419. that = this,
  420. dt = this.s.dt;
  421. return $(
  422. '<li class="ColVis_Special '+(dt.bJUI ? 'ui-button ui-state-default' : '')+'">'+
  423. this.s.restore+
  424. '</li>'
  425. )
  426. .click( function (e) {
  427. for ( var i=0, iLen=that.s.abOriginal.length ; i<iLen ; i++ )
  428. {
  429. that.s.dt.oInstance.fnSetColumnVis( i, that.s.abOriginal[i], false );
  430. }
  431. that._fnAdjustOpenRows();
  432. that.s.dt.oInstance.fnAdjustColumnSizing( false );
  433. that.s.dt.oInstance.fnDraw( false );
  434. } )[0];
  435. },
  436. /**
  437. * Create a button which allows show all and show node actions
  438. * @method _fnDomShowXButton
  439. * @returns {Node} Created button
  440. * @private
  441. */
  442. "_fnDomShowXButton": function ( str, action )
  443. {
  444. var
  445. that = this,
  446. dt = this.s.dt;
  447. return $(
  448. '<li class="ColVis_Special '+(dt.bJUI ? 'ui-button ui-state-default' : '')+'">'+
  449. str+
  450. '</li>'
  451. )
  452. .click( function (e) {
  453. for ( var i=0, iLen=that.s.abOriginal.length ; i<iLen ; i++ )
  454. {
  455. if (that.s.aiExclude.indexOf(i) === -1)
  456. {
  457. that.s.dt.oInstance.fnSetColumnVis( i, action, false );
  458. }
  459. }
  460. that._fnAdjustOpenRows();
  461. that.s.dt.oInstance.fnAdjustColumnSizing( false );
  462. that.s.dt.oInstance.fnDraw( false );
  463. } )[0];
  464. },
  465. /**
  466. * Create the DOM for a show / hide group button
  467. * @method _fnDomGroupButton
  468. * @param {int} i Group in question, order based on that provided in settings
  469. * @returns {Node} Created button
  470. * @private
  471. */
  472. "_fnDomGroupButton": function ( i )
  473. {
  474. var
  475. that = this,
  476. dt = this.s.dt,
  477. oGroup = this.s.aoGroups[i];
  478. return $(
  479. '<li class="ColVis_Special '+(dt.bJUI ? 'ui-button ui-state-default' : '')+'">'+
  480. '<label>'+
  481. '<input type="checkbox" />'+
  482. '<span>'+oGroup.sTitle+'</span>'+
  483. '</label>'+
  484. '</li>'
  485. )
  486. .click( function (e) {
  487. var showHide = !$('input', this).is(":checked");
  488. if ( e.target.nodeName.toLowerCase() !== "li" )
  489. {
  490. showHide = ! showHide;
  491. }
  492. for ( var j=0 ; j < oGroup.aiColumns.length ; j++ )
  493. {
  494. that.s.dt.oInstance.fnSetColumnVis( oGroup.aiColumns[j], showHide );
  495. }
  496. } )[0];
  497. },
  498. /**
  499. * Create the DOM for a show / hide button
  500. * @method _fnDomColumnButton
  501. * @param {int} i Column in question
  502. * @returns {Node} Created button
  503. * @private
  504. */
  505. "_fnDomColumnButton": function ( i )
  506. {
  507. var
  508. that = this,
  509. column = this.s.dt.aoColumns[i],
  510. dt = this.s.dt;
  511. var title = this.s.fnLabel===null ?
  512. column.sTitle :
  513. this.s.fnLabel( i, column.sTitle, column.nTh );
  514. return $(
  515. '<li '+(dt.bJUI ? 'class="ui-button ui-state-default"' : '')+'>'+
  516. '<label>'+
  517. '<input type="checkbox" />'+
  518. '<span>'+title+'</span>'+
  519. '</label>'+
  520. '</li>'
  521. )
  522. .click( function (e) {
  523. var showHide = !$('input', this).is(":checked");
  524. if ( e.target.nodeName.toLowerCase() !== "li" )
  525. {
  526. showHide = ! showHide;
  527. }
  528. /* Need to consider the case where the initialiser created more than one table - change the
  529. * API index that DataTables is using
  530. */
  531. var oldIndex = $.fn.dataTableExt.iApiIndex;
  532. $.fn.dataTableExt.iApiIndex = that._fnDataTablesApiIndex.call(that);
  533. // Optimisation for server-side processing when scrolling - don't do a full redraw
  534. if ( dt.oFeatures.bServerSide )
  535. {
  536. that.s.dt.oInstance.fnSetColumnVis( i, showHide, false );
  537. that.s.dt.oInstance.fnAdjustColumnSizing( false );
  538. if (dt.oScroll.sX !== "" || dt.oScroll.sY !== "" )
  539. {
  540. that.s.dt.oInstance.oApi._fnScrollDraw( that.s.dt );
  541. }
  542. that._fnDrawCallback();
  543. }
  544. else
  545. {
  546. that.s.dt.oInstance.fnSetColumnVis( i, showHide );
  547. }
  548. $.fn.dataTableExt.iApiIndex = oldIndex; /* Restore */
  549. if ( e.target.nodeName.toLowerCase() === 'input' && that.s.fnStateChange !== null )
  550. {
  551. that.s.fnStateChange.call( that, i, showHide );
  552. }
  553. } )[0];
  554. },
  555. /**
  556. * Get the position in the DataTables instance array of the table for this
  557. * instance of ColVis
  558. * @method _fnDataTablesApiIndex
  559. * @returns {int} Index
  560. * @private
  561. */
  562. "_fnDataTablesApiIndex": function ()
  563. {
  564. for ( var i=0, iLen=this.s.dt.oInstance.length ; i<iLen ; i++ )
  565. {
  566. if ( this.s.dt.oInstance[i] == this.s.dt.nTable )
  567. {
  568. return i;
  569. }
  570. }
  571. return 0;
  572. },
  573. /**
  574. * Create the element used to contain list the columns (it is shown and
  575. * hidden as needed)
  576. * @method _fnDomCollection
  577. * @returns {Node} div container for the collection
  578. * @private
  579. */
  580. "_fnDomCollection": function ()
  581. {
  582. return $('<ul />', {
  583. 'class': !this.s.dt.bJUI ?
  584. "ColVis_collection" :
  585. "ColVis_collection ui-buttonset ui-buttonset-multi"
  586. } )
  587. .css( {
  588. 'display': 'none',
  589. 'opacity': 0,
  590. 'position': ! this.s.bCssPosition ?
  591. 'absolute' :
  592. ''
  593. } )[0];
  594. },
  595. /**
  596. * An element to be placed on top of the activate button to catch events
  597. * @method _fnDomCatcher
  598. * @returns {Node} div container for the collection
  599. * @private
  600. */
  601. "_fnDomCatcher": function ()
  602. {
  603. var
  604. that = this,
  605. nCatcher = document.createElement('div');
  606. nCatcher.className = "ColVis_catcher";
  607. $(nCatcher).click( function () {
  608. that._fnCollectionHide.call( that, null, null );
  609. } );
  610. return nCatcher;
  611. },
  612. /**
  613. * Create the element used to shade the background, and capture hide events (it is shown and
  614. * hidden as needed)
  615. * @method _fnDomBackground
  616. * @returns {Node} div container for the background
  617. * @private
  618. */
  619. "_fnDomBackground": function ()
  620. {
  621. var that = this;
  622. var background = $('<div></div>')
  623. .addClass( 'ColVis_collectionBackground' )
  624. .css( 'opacity', 0 )
  625. .click( function () {
  626. that._fnCollectionHide.call( that, null, null );
  627. } );
  628. /* When considering a mouse over action for the activation, we also consider a mouse out
  629. * which is the same as a mouse over the background - without all the messing around of
  630. * bubbling events. Use the catcher element to avoid messing around with bubbling
  631. */
  632. if ( this.s.activate == "mouseover" )
  633. {
  634. background.mouseover( function () {
  635. that.s.overcollection = false;
  636. that._fnCollectionHide.call( that, null, null );
  637. } );
  638. }
  639. return background[0];
  640. },
  641. /**
  642. * Show the show / hide list and the background
  643. * @method _fnCollectionShow
  644. * @returns void
  645. * @private
  646. */
  647. "_fnCollectionShow": function ()
  648. {
  649. var that = this, i, iLen, iLeft;
  650. var oPos = $(this.dom.button).offset();
  651. var nHidden = this.dom.collection;
  652. var nBackground = this.dom.background;
  653. var iDivX = parseInt(oPos.left, 10);
  654. var iDivY = parseInt(oPos.top + $(this.dom.button).outerHeight(), 10);
  655. if ( ! this.s.bCssPosition )
  656. {
  657. nHidden.style.top = iDivY+"px";
  658. nHidden.style.left = iDivX+"px";
  659. }
  660. $(nHidden).css( {
  661. 'display': 'block',
  662. 'opacity': 0
  663. } );
  664. nBackground.style.bottom ='0px';
  665. nBackground.style.right = '0px';
  666. var oStyle = this.dom.catcher.style;
  667. oStyle.height = $(this.dom.button).outerHeight()+"px";
  668. oStyle.width = $(this.dom.button).outerWidth()+"px";
  669. oStyle.top = oPos.top+"px";
  670. oStyle.left = iDivX+"px";
  671. document.body.appendChild( nBackground );
  672. document.body.appendChild( nHidden );
  673. document.body.appendChild( this.dom.catcher );
  674. /* This results in a very small delay for the end user but it allows the animation to be
  675. * much smoother. If you don't want the animation, then the setTimeout can be removed
  676. */
  677. $(nHidden).animate({"opacity": 1}, that.s.iOverlayFade);
  678. $(nBackground).animate({"opacity": 0.1}, that.s.iOverlayFade, 'linear', function () {
  679. /* In IE6 if you set the checked attribute of a hidden checkbox, then this is not visually
  680. * reflected. As such, we need to do it here, once it is visible. Unbelievable.
  681. */
  682. if ( $.browser && $.browser.msie && $.browser.version == "6.0" )
  683. {
  684. that._fnDrawCallback();
  685. }
  686. });
  687. /* Visual corrections to try and keep the collection visible */
  688. if ( !this.s.bCssPosition )
  689. {
  690. iLeft = ( this.s.sAlign=="left" ) ?
  691. iDivX :
  692. iDivX - $(nHidden).outerWidth() + $(this.dom.button).outerWidth();
  693. nHidden.style.left = iLeft+"px";
  694. var iDivWidth = $(nHidden).outerWidth();
  695. var iDivHeight = $(nHidden).outerHeight();
  696. var iDocWidth = $(document).width();
  697. if ( iLeft + iDivWidth > iDocWidth )
  698. {
  699. nHidden.style.left = (iDocWidth-iDivWidth)+"px";
  700. }
  701. }
  702. this.s.hidden = false;
  703. },
  704. /**
  705. * Hide the show / hide list and the background
  706. * @method _fnCollectionHide
  707. * @returns void
  708. * @private
  709. */
  710. "_fnCollectionHide": function ( )
  711. {
  712. var that = this;
  713. if ( !this.s.hidden && this.dom.collection !== null )
  714. {
  715. this.s.hidden = true;
  716. $(this.dom.collection).animate({"opacity": 0}, that.s.iOverlayFade, function (e) {
  717. this.style.display = "none";
  718. } );
  719. $(this.dom.background).animate({"opacity": 0}, that.s.iOverlayFade, function (e) {
  720. document.body.removeChild( that.dom.background );
  721. document.body.removeChild( that.dom.catcher );
  722. } );
  723. }
  724. },
  725. /**
  726. * Alter the colspan on any fnOpen rows
  727. */
  728. "_fnAdjustOpenRows": function ()
  729. {
  730. var aoOpen = this.s.dt.aoOpenRows;
  731. var iVisible = this.s.dt.oApi._fnVisbleColumns( this.s.dt );
  732. for ( var i=0, iLen=aoOpen.length ; i<iLen ; i++ ) {
  733. aoOpen[i].nTr.getElementsByTagName('td')[0].colSpan = iVisible;
  734. }
  735. }
  736. };
  737. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  738. * Static object methods
  739. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  740. /**
  741. * Rebuild the collection for a given table, or all tables if no parameter given
  742. * @method ColVis.fnRebuild
  743. * @static
  744. * @param object oTable DataTable instance to consider - optional
  745. * @returns void
  746. */
  747. ColVis.fnRebuild = function ( oTable )
  748. {
  749. var nTable = null;
  750. if ( typeof oTable != 'undefined' )
  751. {
  752. nTable = oTable.fnSettings().nTable;
  753. }
  754. for ( var i=0, iLen=ColVis.aInstances.length ; i<iLen ; i++ )
  755. {
  756. if ( typeof oTable == 'undefined' || nTable == ColVis.aInstances[i].s.dt.nTable )
  757. {
  758. ColVis.aInstances[i].fnRebuild();
  759. }
  760. }
  761. };
  762. ColVis.defaults = {
  763. /**
  764. * Mode of activation. Can be 'click' or 'mouseover'
  765. * @property activate
  766. * @type string
  767. * @default click
  768. */
  769. active: 'click',
  770. /**
  771. * Text used for the button
  772. * @property buttonText
  773. * @type string
  774. * @default Show / hide columns
  775. */
  776. buttonText: 'Show / hide columns',
  777. /**
  778. * List of columns (integers) which should be excluded from the list
  779. * @property aiExclude
  780. * @type array
  781. * @default []
  782. */
  783. aiExclude: [],
  784. /**
  785. * Show restore button
  786. * @property bRestore
  787. * @type boolean
  788. * @default false
  789. */
  790. bRestore: false,
  791. /**
  792. * Restore button text
  793. * @property sRestore
  794. * @type string
  795. * @default Restore original
  796. */
  797. sRestore: 'Restore original',
  798. /**
  799. * Show Show-All button
  800. * @property bShowAll
  801. * @type boolean
  802. * @default false
  803. */
  804. bShowAll: false,
  805. /**
  806. * Show All button text
  807. * @property sShowAll
  808. * @type string
  809. * @default Restore original
  810. */
  811. sShowAll: 'Show All',
  812. /**
  813. * Position of the collection menu when shown - align "left" or "right"
  814. * @property sAlign
  815. * @type string
  816. * @default left
  817. */
  818. sAlign: 'left',
  819. /**
  820. * Callback function to tell the user when the state has changed
  821. * @property fnStateChange
  822. * @type function
  823. * @default null
  824. */
  825. fnStateChange: null,
  826. /**
  827. * Overlay animation duration in mS
  828. * @property iOverlayFade
  829. * @type integer|false
  830. * @default 500
  831. */
  832. iOverlayFade: 500,
  833. /**
  834. * Label callback for column names. Takes three parameters: 1. the
  835. * column index, 2. the column title detected by DataTables and 3. the
  836. * TH node for the column
  837. * @property fnLabel
  838. * @type function
  839. * @default null
  840. */
  841. fnLabel: null,
  842. /**
  843. * Indicate if the column list should be positioned by Javascript,
  844. * visually below the button or allow CSS to do the positioning
  845. * @property bCssPosition
  846. * @type boolean
  847. * @default false
  848. */
  849. bCssPosition: false,
  850. /**
  851. * Group buttons
  852. * @property aoGroups
  853. * @type array
  854. * @default []
  855. */
  856. aoGroups: [],
  857. /**
  858. * Button ordering - 'alpha' (alphabetical) or 'column' (table column
  859. * order)
  860. * @property order
  861. * @type string
  862. * @default column
  863. */
  864. order: 'column'
  865. };
  866. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  867. * Static object properties
  868. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  869. /**
  870. * Collection of all ColVis instances
  871. * @property ColVis.aInstances
  872. * @static
  873. * @type Array
  874. * @default []
  875. */
  876. ColVis.aInstances = [];
  877. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  878. * Constants
  879. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  880. /**
  881. * Name of this class
  882. * @constant CLASS
  883. * @type String
  884. * @default ColVis
  885. */
  886. ColVis.prototype.CLASS = "ColVis";
  887. /**
  888. * ColVis version
  889. * @constant VERSION
  890. * @type String
  891. * @default See code
  892. */
  893. ColVis.VERSION = "1.1.1";
  894. ColVis.prototype.VERSION = ColVis.VERSION;
  895. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  896. * Initialisation
  897. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  898. /*
  899. * Register a new feature with DataTables
  900. */
  901. if ( typeof $.fn.dataTable == "function" &&
  902. typeof $.fn.dataTableExt.fnVersionCheck == "function" &&
  903. $.fn.dataTableExt.fnVersionCheck('1.7.0') )
  904. {
  905. $.fn.dataTableExt.aoFeatures.push( {
  906. "fnInit": function( oDTSettings ) {
  907. var init = oDTSettings.oInit;
  908. var colvis = new ColVis( oDTSettings, init.colVis || init.oColVis || {} );
  909. return colvis.button();
  910. },
  911. "cFeature": "C",
  912. "sFeature": "ColVis"
  913. } );
  914. }
  915. else
  916. {
  917. alert( "Warning: ColVis requires DataTables 1.7 or greater - www.datatables.net/download");
  918. }
  919. // Make ColVis accessible from the DataTables instance
  920. $.fn.dataTable.ColVis = ColVis;
  921. $.fn.DataTable.ColVis = ColVis;
  922. return ColVis;
  923. }; // /factory
  924. // Define as an AMD module if possible
  925. if ( typeof define === 'function' && define.amd ) {
  926. define( ['jquery', 'datatables'], factory );
  927. }
  928. else if ( typeof exports === 'object' ) {
  929. // Node/CommonJS
  930. factory( require('jquery'), require('datatables') );
  931. }
  932. else if ( jQuery && !jQuery.fn.dataTable.ColVis ) {
  933. // Otherwise simply initialise as normal, stopping multiple evaluation
  934. factory( jQuery, jQuery.fn.dataTable );
  935. }
  936. })(window, document);