/MVC/Scripts/DataTables/dataTables.rowGroup.js

https://bitbucket.org/lrods/mvc · JavaScript · 386 lines · 208 code · 70 blank · 108 comment · 35 complexity · d946540cff1008cc6f8f947923500cd0 MD5 · raw file

  1. /*! RowGroup 1.0.0
  2. * ©2017 SpryMedia Ltd - datatables.net/license
  3. */
  4. /**
  5. * @summary RowGroup
  6. * @description RowGrouping for DataTables
  7. * @version 1.0.0
  8. * @file dataTables.rowGroup.js
  9. * @author SpryMedia Ltd (www.sprymedia.co.uk)
  10. * @contact datatables.net
  11. * @copyright Copyright 2017 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( factory ){
  23. if ( typeof define === 'function' && define.amd ) {
  24. // AMD
  25. define( ['jquery', 'datatables.net'], function ( $ ) {
  26. return factory( $, window, document );
  27. } );
  28. }
  29. else if ( typeof exports === 'object' ) {
  30. // CommonJS
  31. module.exports = function (root, $) {
  32. if ( ! root ) {
  33. root = window;
  34. }
  35. if ( ! $ || ! $.fn.dataTable ) {
  36. $ = require('datatables.net')(root, $).$;
  37. }
  38. return factory( $, root, root.document );
  39. };
  40. }
  41. else {
  42. // Browser
  43. factory( jQuery, window, document );
  44. }
  45. }(function( $, window, document, undefined ) {
  46. 'use strict';
  47. var DataTable = $.fn.dataTable;
  48. var RowGroup = function ( dt, opts ) {
  49. // Sanity check that we are using DataTables 1.10 or newer
  50. if ( ! DataTable.versionCheck || ! DataTable.versionCheck( '1.10.8' ) ) {
  51. throw 'RowGroup requires DataTables 1.10.8 or newer';
  52. }
  53. // User and defaults configuration object
  54. this.c = $.extend( true, {},
  55. DataTable.defaults.rowGroup,
  56. RowGroup.defaults,
  57. opts
  58. );
  59. // Internal settings
  60. this.s = {
  61. dt: new DataTable.Api( dt ),
  62. dataFn: DataTable.ext.oApi._fnGetObjectDataFn( this.c.dataSrc ),
  63. };
  64. // DOM items
  65. this.dom = {
  66. };
  67. // Check if row grouping has already been initialised on this table
  68. var settings = this.s.dt.settings()[0];
  69. var existing = settings.rowGroup;
  70. if ( existing ) {
  71. return existing;
  72. }
  73. settings.rowGroup = this;
  74. this._constructor();
  75. };
  76. $.extend( RowGroup.prototype, {
  77. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  78. * API methods for DataTables API interface
  79. */
  80. /**
  81. * Get/set the grouping data source - need to call draw after this is
  82. * executed as a setter
  83. * @returns string~RowGroup
  84. */
  85. dataSrc: function ( val )
  86. {
  87. if ( val === undefined ) {
  88. return this.c.dataSrc;
  89. }
  90. var dt = this.s.dt;
  91. this.c.dataSrc = val;
  92. this.s.dataFn = DataTable.ext.oApi._fnGetObjectDataFn( this.c.dataSrc );
  93. $(dt.table().node()).triggerHandler( 'rowgroup-datasrc.dt', [ dt, val ] );
  94. return this;
  95. },
  96. /**
  97. * Disable - need to call draw after this is executed
  98. * @returns RowGroup
  99. */
  100. disable: function ()
  101. {
  102. this.c.enable = false;
  103. return this;
  104. },
  105. /**
  106. * Enable - need to call draw after this is executed
  107. * @returns RowGroup
  108. */
  109. enable: function ( flag )
  110. {
  111. if ( flag === false ) {
  112. return this.disable();
  113. }
  114. this.c.enable = true;
  115. return this;
  116. },
  117. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  118. * Constructor
  119. */
  120. _constructor: function ()
  121. {
  122. var that = this;
  123. var dt = this.s.dt;
  124. dt.on( 'draw.dtrg', function () {
  125. if ( that.c.enable ) {
  126. that._draw();
  127. }
  128. } );
  129. dt.on( 'column-visibility.dtrg', function () {
  130. that._adjustColspan();
  131. } );
  132. dt.on( 'destroy', function () {
  133. dt.off( '.dtrg' );
  134. } );
  135. },
  136. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  137. * Private methods
  138. */
  139. /**
  140. * Adjust column span when column visibility changes
  141. * @private
  142. */
  143. _adjustColspan: function ()
  144. {
  145. $( 'tr.'+this.c.className, this.s.dt.table().body() )
  146. .attr( 'colspan', this._colspan() );
  147. },
  148. /**
  149. * Get the number of columns that a grouping row should span
  150. * @private
  151. */
  152. _colspan: function ()
  153. {
  154. return $( this.s.dt.columns().header() ).filter(':visible').length;
  155. },
  156. /**
  157. * Update function that is called whenever we need to draw the grouping rows
  158. * @private
  159. */
  160. _draw: function ()
  161. {
  162. var that = this;
  163. var dt = this.s.dt;
  164. var rows = dt.rows( { page: 'current' } );
  165. var groupedRows = [];
  166. var last, display;
  167. rows.every( function () {
  168. var d = this.data();
  169. var group = that.s.dataFn( d );
  170. if ( last === undefined || group !== last ) {
  171. groupedRows.push( [] );
  172. last = group;
  173. }
  174. groupedRows[ groupedRows.length - 1 ].push( this.index() );
  175. } );
  176. for ( var i=0, ien=groupedRows.length ; i<ien ; i++ ) {
  177. var group = groupedRows[i];
  178. var firstRow = dt.row(group[0]);
  179. var groupName = this.s.dataFn( firstRow.data() );
  180. if ( this.c.startRender ) {
  181. display = this.c.startRender.call( this, dt.rows(group), groupName );
  182. this
  183. ._rowWrap( display, this.c.startClassName )
  184. .insertBefore( firstRow.node() );
  185. }
  186. if ( this.c.endRender ) {
  187. display = this.c.endRender.call( this, dt.rows(group), groupName );
  188. this
  189. ._rowWrap( display, this.c.endClassName )
  190. .insertAfter( dt.row( group[ group.length-1 ] ).node() );
  191. }
  192. }
  193. },
  194. /**
  195. * Take a rendered value from an end user and make it suitable for display
  196. * as a row, by wrapping it in a row, or detecting that it is a row.
  197. * @param [node|jQuery|string] display Display value
  198. * @param [string] className Class to add to the row
  199. * @private
  200. */
  201. _rowWrap: function ( display, className )
  202. {
  203. var row;
  204. if ( typeof display === 'object' && display.nodeName && display.nodeName.toLowerCase() === 'tr') {
  205. row = $(display);
  206. }
  207. else if (display instanceof $ && display.length && display[0].nodeName.toLowerCase() === 'tr') {
  208. row = display;
  209. }
  210. else {
  211. row = $('<tr/>')
  212. .append(
  213. $('<td/>')
  214. .attr( 'colspan', this._colspan() )
  215. .append( display )
  216. );
  217. }
  218. return row
  219. .addClass( this.c.className )
  220. .addClass( className );
  221. }
  222. } );
  223. /**
  224. * RowGroup default settings for initialisation
  225. *
  226. * @namespace
  227. * @name RowGroup.defaults
  228. * @static
  229. */
  230. RowGroup.defaults = {
  231. /**
  232. * Class to apply to grouping rows - applied to both the start and
  233. * end grouping rows.
  234. * @type string
  235. */
  236. className: 'group',
  237. /**
  238. * Data property from which to read the grouping information
  239. * @type string|integer
  240. */
  241. dataSrc: 0,
  242. /**
  243. * Initial enablement state
  244. * @boolean
  245. */
  246. enable: true,
  247. /**
  248. * Class name to give to the end grouping row
  249. * @type string
  250. */
  251. endClassName: 'group-end',
  252. /**
  253. * End grouping label function
  254. * @function
  255. */
  256. endRender: null,
  257. /**
  258. * Class name to give to the start grouping row
  259. * @type string
  260. */
  261. startClassName: 'group-start',
  262. /**
  263. * Start grouping label function
  264. * @function
  265. */
  266. startRender: function ( rows, group ) {
  267. return group;
  268. }
  269. };
  270. RowGroup.version = "1.0.0";
  271. $.fn.dataTable.RowGroup = RowGroup;
  272. $.fn.DataTable.RowGroup = RowGroup;
  273. DataTable.Api.register( 'rowGroup()', function () {
  274. return this;
  275. } );
  276. DataTable.Api.register( 'rowGroup().disable()', function () {
  277. return this.iterator( 'table', function (ctx) {
  278. if ( ctx.rowGroup ) {
  279. ctx.rowGroup.enable( false );
  280. }
  281. } );
  282. } );
  283. DataTable.Api.register( 'rowGroup().enable()', function ( opts ) {
  284. return this.iterator( 'table', function (ctx) {
  285. if ( ctx.rowGroup ) {
  286. ctx.rowGroup.enable( opts === undefined ? true : opts );
  287. }
  288. } );
  289. } );
  290. DataTable.Api.register( 'rowGroup().dataSrc()', function ( val ) {
  291. if ( val === undefined ) {
  292. return this.context[0].rowGroup.dataSrc();
  293. }
  294. return this.iterator( 'table', function (ctx) {
  295. if ( ctx.rowGroup ) {
  296. ctx.rowGroup.dataSrc( val );
  297. }
  298. } );
  299. } );
  300. // Attach a listener to the document which listens for DataTables initialisation
  301. // events so we can automatically initialise
  302. $(document).on( 'preInit.dt.dtrg', function (e, settings, json) {
  303. if ( e.namespace !== 'dt' ) {
  304. return;
  305. }
  306. var init = settings.oInit.rowGroup;
  307. var defaults = DataTable.defaults.rowGroup;
  308. if ( init || defaults ) {
  309. var opts = $.extend( {}, defaults, init );
  310. if ( init !== false ) {
  311. new RowGroup( settings, opts );
  312. }
  313. }
  314. } );
  315. return RowGroup;
  316. }));