text: /*! Responsive 1.0.3
   * 2014 SpryMedia Ltd - datatables.net/license
   */
  
  /**
   * @summary     Responsive
   * @description Responsive tables plug-in for DataTables
   * @version     1.0.3
   * @file        dataTables.responsive.js
   * @author      SpryMedia Ltd (www.sprymedia.co.uk)
   * @contact     www.sprymedia.co.uk/contact
   * @copyright   Copyright 2014 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 (window, document, undefined) {
  
  
  	var factory = function ($, DataTable) {
  		"use strict";
  
  		/**
  		 * 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.1+
  		 *
  		 *  @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.1')) {
  				throw 'DataTables Responsive requires DataTables 1.10.1 or newer';
  			}
  
  			this.s = {
  				dt: new DataTable.Api(settings),
  				columns: []
  			};
  
  			// 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();
  		};
  
  		Responsive.prototype = {
  			/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  			 * Constructor
  			 */
  
  			/**
  			 * Initialise the Responsive instance
  			 *
  			 * @private
  			 */
  			_constructor: function () {
  				var that = this;
  				var dt = this.s.dt;
  
  				dt.settings()[0]._responsive = this;
  
  				// Use DataTables' private throttle function to avoid processor thrashing
  				$(window).on('resize.dtr orientationchange.dtr', dt.settings()[0].oApi._fnThrottle(function () {
  					that._resize();
  				}));
  
  				// Destroy event handler
  				dt.on('destroy.dtr', function () {
  					$(window).off('resize.dtr orientationchange.dtr draw.dtr');
  				});
  
  				// 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;
  				});
  
  				// Determine which columns are already hidden, and should therefore
  				// remain hidden. TODO - should this be done? See thread 22677
  				//
  				// this.s.alwaysHidden = dt.columns(':hidden').indexes();
  
  				this._classLogic();
  				this._resizeAuto();
  
  				// First pass - draw the table for the current viewport size
  				this._resize();
  
  				// Details handler
  				var details = this.c.details;
  				if (details.type) {
  					that._detailsInit();
  					this._detailsVis();
  
  					dt.on('column-visibility.dtr', function () {
  						that._detailsVis();
  					});
  
  					// Redraw the details box on each draw. This is used until
  					// DataTables implements a native `updated` event for rows
  					dt.on('draw.dtr', function () {
  						dt.rows().iterator('row', function (settings, idx) {
  							var row = dt.row(idx);
  
  							if (row.child.isShown()) {
  								var info = that.c.details.renderer(dt, idx);
  								row.child(info, 'child').show();
  							}
  						});
  					});
  
  					$(dt.table().node()).addClass('dtr-' + details.type);
  				}
  			},
  
  
  			/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  			 * 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;
  
  				// 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 < ien; i++) {
  					if (display[i] === true) {
  						requiredWidth += columns[i].minWidth;
  					}
  				}
  
  				// Second pass, use up any remaining width for other columns
  				var widthAvailable = dt.table().container().offsetWidth;
  				var usedWidth = widthAvailable - requiredWidth;
  
  				// Control column needs to always be included. This makes it sub-
  				// optimal in terms of using the available with, but to stop layout
  				// thrashing or overflow. Also we need to account for the control column
  				// width first so we know how much width is available for the other
  				// columns, since the control column might not be the first one shown
  				for (i = 0, ien = display.length; i < ien; i++) {
  					if (columns[i].control) {
  						usedWidth -= columns[i].minWidth;
  					}
  				}
  
  				// Allow columns to be shown (counting from the left) until we run out
  				// of room
  				for (i = 0, ien = display.length; i < ien; i++) {
  					if (display[i] === '-' && !columns[i].control) {
  						display[i] = usedWidth - columns[i].minWidth < 0 ?
  							false :
  							true;
  
  						usedWidth -= columns[i].minWidth;
  					}
  				}
  
  				// Determine if the 'control' column should be shown (if there is one).
  				// This is the case when there is a hidden column (that is not the
  				// control column). The two loops look inefficient here, but they are
  				// trivial and will fly through. We need to know the outcome from the
  				// first , before the action in the second can be taken
  				var showControl = false;
  
  				for (i = 0, ien = columns.length; i < ien; i++) {
  					if (!columns[i].control && !columns[i].never && !display[i]) {
  						showControl = true;
  						break;
  					}
  				}
  
  				for (i = 0, ien = columns.length; i < ien; i++) {
  					if (columns[i].control) {
  						display[i] = showControl;
  					}
  				}
  
  				// Finally we need to make sure that there is at least one column that
  				// is visible
  				if ($.inArray(true, display) === -1) {
  					display[0] = true;
  				}
  
  				return display;
  			},
  
  
  			/**
  			 * Create the internal `columns` array with information about the columns
  			 * for the table. This includes determining which breakpoints the column
  			 * will appear in, based upon class names in the column, which makes up the
  			 * vast majority of this method.
  			 *
  			 * @private
  			 */
  			_classLogic: function () {
  				var that = this;
  				var calc = {};
  				var breakpoints = this.c.breakpoints;
  				var columns = this.s.dt.columns().eq(0).map(function (i) {
  					var className = this.column(i).header().className;
  
  					return {
  						className: className,
  						includeIn: [],
  						auto: false,
  						control: false,
  						never: className.match(/\bnever\b/) ? true : false
  					};
  				});
  
  				// Simply add a breakpoint to `includeIn` array, ensuring that there are
  				// no duplicates
  				var add = function (colIdx, name) {
  					var includeIn = columns[colIdx].includeIn;
  
  					if ($.inArray(name, includeIn) === -1) {
  						includeIn.push(name);
  					}
  				};
  
  				var column = function (colIdx, name, operator, matched) {
  					var size, i, ien;
  
  					if (!operator) {
  						columns[colIdx].includeIn.push(name);
  					}
  					else if (operator === 'max-') {
  						// Add this breakpoint and all smaller
  						size = that._find(name).width;
  
  						for (i = 0, ien = breakpoints.length; i < ien; i++) {
  							if (breakpoints[i].width <= size) {
  								add(colIdx, breakpoints[i].name);
  							}
  						}
  					}
  					else if (operator === 'min-') {
  						// Add this breakpoint and all larger
  						size = that._find(name).width;
  
  						for (i = 0, ien = breakpoints.length; i < ien; i++) {
  							if (breakpoints[i].width >= size) {
  								add(colIdx, breakpoints[i].name);
  							}
  						}
  					}
  					else if (operator === 'not-') {
  						// Add all but this breakpoint (xxx need extra information)
  
  						for (i = 0, ien = breakpoints.length; i < ien; i++) {
  							if (breakpoints[i].name.indexOf(matched) === -1) {
  								add(colIdx, breakpoints[i].name);
  							}
  						}
  					}
  				};
  
  				// Loop over each column and determine if it has a responsive control
  				// class
  				columns.each(function (col, i) {
  					var classNames = col.className.split(' ');
  					var hasClass = false;
  
  					// Split the class name up so multiple rules can be applied if needed
  					for (var k = 0, ken = classNames.length; k < ken; k++) {
  						var className = $.trim(classNames[k]);
  
  						if (className === 'all') {
  							// Include in all
  							hasClass = true;
  							col.includeIn = $.map(breakpoints, function (a) {
  								return a.name;
  							});
  							return;
  						}
  						else if (className === 'none' || className === 'never') {
  							// Include in none (default) and no auto
  							hasClass = true;
  							return;
  						}
  						else if (className === 'control') {
  							// Special column that is only visible, when one of the other
  							// columns is hidden. This is used for the details control
  							hasClass = true;
  							col.control = true;
  							return;
  						}
  
  						$.each(breakpoints, function (j, breakpoint) {
  							// Does this column have a class that matches this breakpoint?
  							var brokenPoint = breakpoint.name.split('-');
  							var re = new RegExp('(min\\-|max\\-|not\\-)?(' + brokenPoint[0] + ')(\\-[_a-zA-Z0-9])?');
  							var match = className.match(re);
  
  							if (match) {
  								hasClass = true;
  
  								if (match[2] === brokenPoint[0] && match[3] === '-' + brokenPoint[1]) {
  									// Class name matches breakpoint name fully
  									column(i, breakpoint.name, match[1], match[2] + match[3]);
  								}
  								else if (match[2] === brokenPoint[0] && !match[3]) {
  									// Class name matched primary breakpoint name with no qualifier
  									column(i, breakpoint.name, match[1], match[2]);
  								}
  							}
  						});
  					}
  
  					// If there was no control class, then automatic sizing is used
  					if (!hasClass) {
  						col.auto = true;
  					}
  				});
  
  				this.s.columns = columns;
  			},
  
  
  			/**
  			 * Initialisation for the details handler
  			 *
  			 * @private
  			 */
  			_detailsInit: function () {
  				var that = this;
  				var dt = this.s.dt;
  				var details = this.c.details;
  
  				// The inline type always uses the first child as the target
  				if (details.type === 'inline') {
  					details.target = 'td:first-child';
  				}
  
  				// type.target can be a string jQuery selector or a column index
  				var target = details.target;
  				var selector = typeof target === 'string' ? target : 'td';
  
  				// Click handler to show / hide the details rows when they are available
  				$(dt.table().body()).on('click', selector, function (e) {
  					// If the table is not collapsed (i.e. there is no hidden columns)
  					// then take no action
  					if (!$(dt.table().node()).hasClass('collapsed')) {
  						return;
  					}
  
  					// Check that the row is actually a DataTable's controlled node
  					if (!dt.row($(this).closest('tr')).length) {
  						return;
  					}
  
  					// For column index, we determine if we should act or not in the
  					// handler - otherwise it is already okay
  					if (typeof target === 'number') {
  						var targetIdx = target < 0 ?
  						dt.columns().eq(0).length + target :
  							target;
  
  						if (dt.cell(this).index().column !== targetIdx) {
  							return;
  						}
  					}
  
  					// $().closest() includes itself in its check
  					var row = dt.row($(this).closest('tr'));
  
  					if (row.child.isShown()) {
  						row.child(false);
  						$(row.node()).removeClass('parent');
  					}
  					else {
  						var info = that.c.details.renderer(dt, row[0]);
  						row.child(info, 'child').show();
  						$(row.node()).addClass('parent');
  					}
  				});
  			},
  
  
  			/**
  			 * Update the child rows in the table whenever the column visibility changes
  			 *
  			 * @private
  			 */
  			_detailsVis: function () {
  				var that = this;
  				var dt = this.s.dt;
  
  				// Find how many columns are hidden
  				var hiddenColumns = dt.columns().indexes().filter(function (idx) {
  					var col = dt.column(idx);
  
  					if (col.visible()) {
  						return null;
  					}
  
  					// Only counts as hidden if it doesn't have the `never` class
  					return $(col.header()).hasClass('never') ? null : idx;
  				});
  				var haveHidden = true;
  
  				if (hiddenColumns.length === 0 || ( hiddenColumns.length === 1 && this.s.columns[hiddenColumns[0]].control )) {
  					haveHidden = false;
  				}
  
  				if (haveHidden) {
  					// Got hidden columns
  					$(dt.table().node()).addClass('collapsed');
  
  					// Show all existing child rows
  					dt.rows().eq(0).each(function (idx) {
  						var row = dt.row(idx);
  
  						if (row.child()) {
  							var info = that.c.details.renderer(dt, row[0]);
  
  							// The renderer can return false to have no child row
  							if (info === false) {
  								row.child.hide();
  							}
  							else {
  								row.child(info, 'child').show();
  							}
  						}
  					});
  				}
  				else {
  					// No hidden columns
  					$(dt.table().node()).removeClass('collapsed');
  
  					// Hide all existing child rows
  					dt.rows().eq(0).each(function (idx) {
  						dt.row(idx).child.hide();
  					});
  				}
  			},
  
  
  			/**
  			 * Find a breakpoint object from a name
  			 * @param  {string} name Breakpoint name to find
  			 * @return {object}      Breakpoint description object
  			 */
  			_find: function (name) {
  				var breakpoints = this.c.breakpoints;
  
  				for (var i = 0, ien = breakpoints.length; i < ien; i++) {
  					if (breakpoints[i].name === name) {
  						return breakpoints[i];
  					}
  				}
  			},
  
  
  			/**
  			 * Alter the table display for a resized viewport. This involves first
  			 * determining what breakpoint the window currently is in, getting the
  			 * column visibilities to apply and then setting them.
  			 *
  			 * @private
  			 */
  			_resize: function () {
  				var dt = this.s.dt;
  				var width = $(window).width();
  				var breakpoints = this.c.breakpoints;
  				var breakpoint = breakpoints[0].name;
  
  				// Determine what breakpoint we are currently at
  				for (var i = breakpoints.length - 1; i >= 0; i--) {
  					if (width <= breakpoints[i].width) {
  						breakpoint = breakpoints[i].name;
  						break;
  					}
  				}
  
  				// Show the columns for that break point
  				var columns = this._columnsVisiblity(breakpoint);
  
  				dt.columns().eq(0).each(function (colIdx, i) {
  					dt.column(colIdx).visible(columns[i]);
  				});
  			},
  
  
  			/**
  			 * Determine the width of each column in the table so the auto column hiding
  			 * has that information to work with. This method is never going to be 100%
  			 * perfect since column widths can change slightly per page, but without
  			 * seriously compromising performance this is quite effective.
  			 *
  			 * @private
  			 */
  			_resizeAuto: function () {
  				var dt = this.s.dt;
  				var columns = this.s.columns;
  
  				// Are we allowed to do auto sizing?
  				if (!this.c.auto) {
  					return;
  				}
  
  				// Are there any columns that actually need auto-sizing, or do they all
  				// have classes defined
  				if ($.inArray(true, $.map(columns, function (c) {
  						return c.auto;
  					})) === -1) {
  					return;
  				}
  
  				// Clone the table with the current data in it
  				var tableWidth = dt.table().node().offsetWidth;
  				var columnWidths = dt.columns;
  				var clonedTable = dt.table().node().cloneNode(false);
  				var clonedHeader = $(dt.table().header().cloneNode(false)).appendTo(clonedTable);
  				var clonedBody = $(dt.table().body().cloneNode(false)).appendTo(clonedTable);
  
  				// This is a bit slow, but we need to get a clone of each row that
  				// includes all columns. As such, try to do this as little as possible.
  				dt.rows({page: 'current'}).indexes().flatten().each(function (idx) {
  					var clone = dt.row(idx).node().cloneNode(true);
  
  					if (dt.columns(':hidden').flatten().length) {
  						$(clone).append(dt.cells(idx, ':hidden').nodes().to$().clone());
  					}
  
  					$(clone).appendTo(clonedBody);
  				});
  
  				var cells = dt.columns().header().to$().clone(false).wrapAll('tr').appendTo(clonedHeader);
  				var inserted = $('<div/>')
  					.css({
  						width: 1,
  						height: 1,
  						overflow: 'hidden'
  					})
  					.append(clonedTable)
  					.insertBefore(dt.table().node());
  
  				// The cloned header now contains the smallest that each column can be
  				dt.columns().eq(0).each(function (idx) {
  					columns[idx].minWidth = cells[idx].offsetWidth || 0;
  				});
  
  				inserted.remove();
  			}
  		};
  
  
  		/**
  		 * 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}
  		];
  
  
  		/**
  		 * 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:
  			 *
  			 * * `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: {
  				renderer: function (api, rowIdx) {
  					var data = api.cells(rowIdx, ':hidden').eq(0).map(function (cell) {
  						var header = $(api.column(cell.column).header());
  						var idx = api.cell(cell).index();
  
  						if (header.hasClass('control') || header.hasClass('never')) {
  							return '';
  						}
  
  						// Use a non-public DT API method to render the data for display
  						// This needs to be updated when DT adds a suitable method for
  						// this type of data retrieval
  						var dtPrivate = api.settings()[0];
  						var cellData = dtPrivate.oApi._fnGetCellData(
  							dtPrivate, idx.row, idx.column, 'display'
  						);
  
  						return '<li data-dtr-index="' + idx.column + '">' +
  						'<span class="dtr-title">' +
  						header.text() + ':' +
  						'</span> ' +
  						'<span class="dtr-data">' +
  						cellData +
  						'</span>' +
  						'</li>';
  					}).toArray().join('');
  
  					return data ?
  						$('<ul data-dtr-index="' + rowIdx + '"/>').append(data) :
  						false;
  				},
  
  				target: 0,
  
  				type: 'inline'
  			}
  		};
  
  
  		/*
  		 * 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.recalc()', function () {
  			this.iterator('table', function (ctx) {
  				if (ctx._responsive) {
  					ctx._responsive._resizeAuto();
  					ctx._responsive._resize();
  				}
  			});
  		});
  
  		Api.register('responsive.index()', function (li) {
  			li = $(li);
  
  			return {
  				column: li.data('dtr-index'),
  				row: li.parent().data('dtr-index')
  			};
  		});
  
  
  		/**
  		 * Version information
  		 *
  		 * @name Responsive.version
  		 * @static
  		 */
  		Responsive.version = '1.0.3';
  
  
  		$.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 ($(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;
  	}; // /factory
  
  
  // Define as an AMD module if possible
  	if (typeof define === 'function' && define.amd) {
  		define(['jquery', 'datatables'], factory);
  	}
  	else if (typeof exports === 'object') {
  		// Node/CommonJS
  		factory(require('jquery'), require('datatables'));
  	}
  	else if (jQuery && !jQuery.fn.dataTable.Responsive) {
  		// Otherwise simply initialise as normal, stopping multiple evaluation
  		factory(jQuery, jQuery.fn.dataTable);
  	}
  
  
  })(window, document);
  
  