All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.wicketstuff.datatables.res.js.dataTables.responsive.js Maven / Gradle / Ivy

There is a newer version: 10.3.0
Show newest version
/*! Responsive 2.0.0
 * 2014-2015 SpryMedia Ltd - datatables.net/license
 */

/**
 * @summary     Responsive
 * @description Responsive tables plug-in for DataTables
 * @version     2.0.0
 * @file        dataTables.responsive.js
 * @author      SpryMedia Ltd (www.sprymedia.co.uk)
 * @contact     www.sprymedia.co.uk/contact
 * @copyright   Copyright 2014-2015 SpryMedia Ltd.
 *
 * This source file is free software, available under the following license:
 *   MIT license - http://datatables.net/license/mit
 *
 * This source file is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
 *
 * For details please refer to: http://www.datatables.net
 */
(function( factory ){
	if ( typeof define === 'function' && define.amd ) {
		// AMD
		define( ['jquery', 'datatables.net'], function ( $ ) {
			return factory( $, window, document );
		} );
	}
	else if ( typeof exports === 'object' ) {
		// CommonJS
		module.exports = function (root, $) {
			if ( ! root ) {
				root = window;
			}

			if ( ! $ || ! $.fn.dataTable ) {
				$ = require('datatables.net')(root, $).$;
			}

			return factory( $, root, root.document );
		};
	}
	else {
		// Browser
		factory( jQuery, window, document );
	}
}(function( $, window, document, undefined ) {
'use strict';
var DataTable = $.fn.dataTable;


/**
 * Responsive is a plug-in for the DataTables library that makes use of
 * DataTables' ability to change the visibility of columns, changing the
 * visibility of columns so the displayed columns fit into the table container.
 * The end result is that complex tables will be dynamically adjusted to fit
 * into the viewport, be it on a desktop, tablet or mobile browser.
 *
 * Responsive for DataTables has two modes of operation, which can used
 * individually or combined:
 *
 * * Class name based control - columns assigned class names that match the
 *   breakpoint logic can be shown / hidden as required for each breakpoint.
 * * Automatic control - columns are automatically hidden when there is no
 *   room left to display them. Columns removed from the right.
 *
 * In additional to column visibility control, Responsive also has built into
 * options to use DataTables' child row display to show / hide the information
 * from the table that has been hidden. There are also two modes of operation
 * for this child row display:
 *
 * * Inline - when the control element that the user can use to show / hide
 *   child rows is displayed inside the first column of the table.
 * * Column - where a whole column is dedicated to be the show / hide control.
 *
 * Initialisation of Responsive is performed by:
 *
 * * Adding the class `responsive` or `dt-responsive` to the table. In this case
 *   Responsive will automatically be initialised with the default configuration
 *   options when the DataTable is created.
 * * Using the `responsive` option in the DataTables configuration options. This
 *   can also be used to specify the configuration options, or simply set to
 *   `true` to use the defaults.
 *
 *  @class
 *  @param {object} settings DataTables settings object for the host table
 *  @param {object} [opts] Configuration options
 *  @requires jQuery 1.7+
 *  @requires DataTables 1.10.3+
 *
 *  @example
 *      $('#example').DataTable( {
 *        responsive: true
 *      } );
 *    } );
 */
var Responsive = function ( settings, opts ) {
	// Sanity check that we are using DataTables 1.10 or newer
	if ( ! DataTable.versionCheck || ! DataTable.versionCheck( '1.10.3' ) ) {
		throw 'DataTables Responsive requires DataTables 1.10.3 or newer';
	}

	this.s = {
		dt: new DataTable.Api( settings ),
		columns: [],
		current: []
	};

	// Check if responsive has already been initialised on this table
	if ( this.s.dt.settings()[0].responsive ) {
		return;
	}

	// details is an object, but for simplicity the user can give it as a string
	if ( opts && typeof opts.details === 'string' ) {
		opts.details = { type: opts.details };
	}

	this.c = $.extend( true, {}, Responsive.defaults, DataTable.defaults.responsive, opts );
	settings.responsive = this;
	this._constructor();
};

$.extend( Responsive.prototype, {
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
	 * Constructor
	 */

	/**
	 * Initialise the Responsive instance
	 *
	 * @private
	 */
	_constructor: function ()
	{
		var that = this;
		var dt = this.s.dt;
		var dtPrivateSettings = dt.settings()[0];

		dt.settings()[0]._responsive = this;

		// Use DataTables' throttle function to avoid processor thrashing on
		// resize
		$(window).on( 'resize.dtr orientationchange.dtr', DataTable.util.throttle( function () {
			that._resize();
		} ) );

		// DataTables doesn't currently trigger an event when a row is added, so
		// we need to hook into its private API to enforce the hidden rows when
		// new data is added
		dtPrivateSettings.oApi._fnCallbackReg( dtPrivateSettings, 'aoRowCreatedCallback', function (tr, data, idx) {
			if ( $.inArray( false, that.s.current ) !== -1 ) {
				$('td, th', tr).each( function ( i ) {
					var idx = dt.column.index( 'toData', i );

					if ( that.s.current[idx] === false ) {
						$(this).css('display', 'none');
					}
				} );
			}
		} );

		// Destroy event handler
		dt.on( 'destroy.dtr', function () {
			dt.off( '.dtr' );
			$( dt.table().body() ).off( '.dtr' );
			$(window).off( 'resize.dtr orientationchange.dtr' );

			// Restore the columns that we've hidden
			$.each( that.s.current, function ( i, val ) {
				if ( val === false ) {
					that._setColumnVis( i, true );
				}
			} );
		} );

		// Reorder the breakpoints array here in case they have been added out
		// of order
		this.c.breakpoints.sort( function (a, b) {
			return a.width < b.width ? 1 :
				a.width > b.width ? -1 : 0;
		} );

		this._classLogic();
		this._resizeAuto();

		// Details handler
		var details = this.c.details;
		if ( details.type !== false ) {
			that._detailsInit();

			// DataTables will trigger this event on every column it shows and
			// hides individually
			dt.on( 'column-visibility.dtr', function (e, ctx, col, vis) {
				that._classLogic();
				that._resizeAuto();
				that._resize();
			} );

			// Redraw the details box on each draw which will happen if the data
			// has changed. This is used until DataTables implements a native
			// `updated` event for rows
			dt.on( 'draw.dtr', function () {
				that._redrawChildren();
			} );

			$(dt.table().node()).addClass( 'dtr-'+details.type );
		}

		dt.on( 'column-reorder.dtr', function (e, settings, details) {
			// This requires ColReorder 1.2.1 or newer
			if ( details.drop ) {
				that._classLogic();
				that._resizeAuto();
				that._resize();
			}
		} );

		// First pass - draw the table for the current viewport size
		this._resize();
	},


	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
	 * Private methods
	 */

	/**
	 * Calculate the visibility for the columns in a table for a given
	 * breakpoint. The result is pre-determined based on the class logic if
	 * class names are used to control all columns, but the width of the table
	 * is also used if there are columns which are to be automatically shown
	 * and hidden.
	 *
	 * @param  {string} breakpoint Breakpoint name to use for the calculation
	 * @return {array} Array of boolean values initiating the visibility of each
	 *   column.
	 *  @private
	 */
	_columnsVisiblity: function ( breakpoint )
	{
		var dt = this.s.dt;
		var columns = this.s.columns;
		var i, ien;

		// Create an array that defines the column ordering based first on the
		// column's priority, and secondly the column index. This allows the
		// columns to be removed from the right if the priority matches
		var order = columns
			.map( function ( col, idx ) {
				return {
					columnIdx: idx,
					priority: col.priority
				};
			} )
			.sort( function ( a, b ) {
				if ( a.priority !== b.priority ) {
					return a.priority - b.priority;
				}
				return a.columnIdx - b.columnIdx;
			} );


		// Class logic - determine which columns are in this breakpoint based
		// on the classes. If no class control (i.e. `auto`) then `-` is used
		// to indicate this to the rest of the function
		var display = $.map( columns, function ( col ) {
			return col.auto && col.minWidth === null ?
				false :
				col.auto === true ?
					'-' :
					$.inArray( breakpoint, col.includeIn ) !== -1;
		} );

		// Auto column control - first pass: how much width is taken by the
		// ones that must be included from the non-auto columns
		var requiredWidth = 0;
		for ( i=0, ien=display.length ; i
') .css( { width: 1, height: 1, overflow: 'hidden' } ) .append( clonedTable ); inserted.insertBefore( dt.table().node() ); // The cloned header now contains the smallest that each column can be headerCells.each( function (i) { var idx = dt.column.index( 'fromVisible', i ); columns[ idx ].minWidth = this.offsetWidth || 0; } ); inserted.remove(); }, /** * Set a column's visibility. * * We don't use DataTables' column visibility controls in order to ensure * that column visibility can Responsive can no-exist. Since only IE8+ is * supported (and all evergreen browsers of course) the control of the * display attribute works well. * * @param {integer} col Column index * @param {boolean} showHide Show or hide (true or false) * @private */ _setColumnVis: function ( col, showHide ) { var dt = this.s.dt; var display = showHide ? '' : 'none'; // empty string will remove the attr $( dt.column( col ).header() ).css( 'display', display ); $( dt.column( col ).footer() ).css( 'display', display ); dt.column( col ).nodes().to$().css( 'display', display ); }, /** * Update the cell tab indexes for keyboard accessibility. This is called on * every table draw - that is potentially inefficient, but also the least * complex option given that column visibility can change on the fly. Its a * shame user-focus was removed from CSS 3 UI, as it would have solved this * issue with a single CSS statement. * * @private */ _tabIndexes: function () { var dt = this.s.dt; var cells = dt.cells( { page: 'current' } ).nodes().to$(); var ctx = dt.settings()[0]; var target = this.c.details.target; cells.filter( '[data-dtr-keyboard]' ).removeData( '[data-dtr-keyboard]' ); var selector = typeof target === 'number' ? ':eq('+target+')' : target; $( selector, dt.rows( { page: 'current' } ).nodes() ) .attr( 'tabIndex', ctx.iTabIndex ) .data( 'dtr-keyboard', 1 ); } } ); /** * List of default breakpoints. Each item in the array is an object with two * properties: * * * `name` - the breakpoint name. * * `width` - the breakpoint width * * @name Responsive.breakpoints * @static */ Responsive.breakpoints = [ { name: 'desktop', width: Infinity }, { name: 'tablet-l', width: 1024 }, { name: 'tablet-p', width: 768 }, { name: 'mobile-l', width: 480 }, { name: 'mobile-p', width: 320 } ]; /** * Display methods - functions which define how the hidden data should be shown * in the table. * * @namespace * @name Responsive.defaults * @static */ Responsive.display = { childRow: function ( row, update, render ) { if ( update ) { if ( $(row.node()).hasClass('parent') ) { row.child( render(), 'child' ).show(); return true; } } else { if ( ! row.child.isShown() ) { row.child( render(), 'child' ).show(); $( row.node() ).addClass( 'parent' ); return true; } else { row.child( false ); $( row.node() ).removeClass( 'parent' ); return false; } } }, childRowImmediate: function ( row, update, render ) { if ( (! update && row.child.isShown()) || ! row.responsive.hasHidden() ) { // User interaction and the row is show, or nothing to show row.child( false ); $( row.node() ).removeClass( 'parent' ); return false; } else { // Display row.child( render(), 'child' ).show(); $( row.node() ).addClass( 'parent' ); return true; } }, // This is a wrapper so the modal options for Bootstrap and jQuery UI can // have options passed into them. This specific one doesn't need to be a // function but it is for consistency in the `modal` name modal: function ( options ) { return function ( row, update, render ) { if ( ! update ) { // Show a modal var close = function () { modal.remove(); // will tidy events for us $(document).off( 'keypress.dtr' ); }; var modal = $('
') .append( $('
') .append( $('
') .append( render() ) ) .append( $('
×
' ) .click( function () { close(); } ) ) ) .append( $('
') .click( function () { close(); } ) ) .appendTo( 'body' ); if ( options && options.header ) { modal.find( 'div.dtr-modal-content' ).prepend( '

'+options.header( row )+'

' ); } $(document).on( 'keyup.dtr', function (e) { if ( e.keyCode === 27 ) { e.stopPropagation(); close(); } } ); } else { $('div.dtr-modal-content') .empty() .append( render() ); } }; } }; /** * Responsive default settings for initialisation * * @namespace * @name Responsive.defaults * @static */ Responsive.defaults = { /** * List of breakpoints for the instance. Note that this means that each * instance can have its own breakpoints. Additionally, the breakpoints * cannot be changed once an instance has been creased. * * @type {Array} * @default Takes the value of `Responsive.breakpoints` */ breakpoints: Responsive.breakpoints, /** * Enable / disable auto hiding calculations. It can help to increase * performance slightly if you disable this option, but all columns would * need to have breakpoint classes assigned to them * * @type {Boolean} * @default `true` */ auto: true, /** * Details control. If given as a string value, the `type` property of the * default object is set to that value, and the defaults used for the rest * of the object - this is for ease of implementation. * * The object consists of the following properties: * * * `display` - A function that is used to show and hide the hidden details * * `renderer` - function that is called for display of the child row data. * The default function will show the data from the hidden columns * * `target` - Used as the selector for what objects to attach the child * open / close to * * `type` - `false` to disable the details display, `inline` or `column` * for the two control types * * @type {Object|string} */ details: { display: Responsive.display.childRow, renderer: function ( api, rowIdx, columns ) { var data = $.map( columns, function ( col, i ) { return col.hidden ? '
  • '+ ''+ col.title+ ' '+ ''+ col.data+ ''+ '
  • ' : ''; } ).join(''); return data ? $('
      ').append( data ) : false; }, target: 0, type: 'inline' }, /** * Orthogonal data request option. This is used to define the data type * requested when Responsive gets the data to show in the child row. * * @type {String} */ orthogonal: 'display' }; /* * API */ var Api = $.fn.dataTable.Api; // Doesn't do anything - work around for a bug in DT... Not documented Api.register( 'responsive()', function () { return this; } ); Api.register( 'responsive.index()', function ( li ) { li = $(li); return { column: li.data('dtr-index'), row: li.parent().data('dtr-index') }; } ); Api.register( 'responsive.rebuild()', function () { return this.iterator( 'table', function ( ctx ) { if ( ctx._responsive ) { ctx._responsive._classLogic(); } } ); } ); Api.register( 'responsive.recalc()', function () { return this.iterator( 'table', function ( ctx ) { if ( ctx._responsive ) { ctx._responsive._resizeAuto(); ctx._responsive._resize(); } } ); } ); Api.register( 'responsive.hasHidden()', function () { var ctx = this.context[0]; return ctx._responsive ? $.inArray( false, ctx._responsive.s.current ) !== -1 : false; } ); /** * Version information * * @name Responsive.version * @static */ Responsive.version = '2.0.0'; $.fn.dataTable.Responsive = Responsive; $.fn.DataTable.Responsive = Responsive; // Attach a listener to the document which listens for DataTables initialisation // events so we can automatically initialise $(document).on( 'init.dt.dtr', function (e, settings, json) { if ( e.namespace !== 'dt' ) { return; } if ( $(settings.nTable).hasClass( 'responsive' ) || $(settings.nTable).hasClass( 'dt-responsive' ) || settings.oInit.responsive || DataTable.defaults.responsive ) { var init = settings.oInit.responsive; if ( init !== false ) { new Responsive( settings, $.isPlainObject( init ) ? init : {} ); } } } ); return Responsive; }));




    © 2015 - 2025 Weber Informatics LLC | Privacy Policy