')
- .addClass('dt-button-collection')
- .addClass(options.collectionLayout)
- .css('display', 'none');
-
- content = $(content)
- .addClass(options.contentClassName)
- .attr('role', 'menu')
- .appendTo(display);
-
- hostNode.attr( 'aria-expanded', 'true' );
-
- if ( hostNode.parents('body')[0] !== document.body ) {
- hostNode = document.body.lastChild;
- }
-
- if ( options.collectionTitle ) {
- display.prepend(''+options.collectionTitle+'
');
- }
-
- _fadeIn( display.insertAfter( hostNode ), options.fade );
-
- var tableContainer = $( hostButton.table().container() );
- var position = display.css( 'position' );
-
- if ( options.align === 'dt-container' ) {
- hostNode = hostNode.parent();
- display.css('width', tableContainer.width());
- }
-
- // Align the popover relative to the DataTables container
- // Useful for wide popovers such as SearchPanes
- if (
- position === 'absolute' &&
- (
- display.hasClass( options.rightAlignClassName ) ||
- display.hasClass( options.leftAlignClassName ) ||
- options.align === 'dt-container'
- )
- ) {
-
- var hostPosition = hostNode.position();
-
- display.css( {
- top: hostPosition.top + hostNode.outerHeight(),
- left: hostPosition.left
- } );
-
- // calculate overflow when positioned beneath
- var collectionHeight = display.outerHeight();
- var tableBottom = tableContainer.offset().top + tableContainer.height();
- var listBottom = hostPosition.top + hostNode.outerHeight() + collectionHeight;
- var bottomOverflow = listBottom - tableBottom;
-
- // calculate overflow when positioned above
- var listTop = hostPosition.top - collectionHeight;
- var tableTop = tableContainer.offset().top;
- var topOverflow = tableTop - listTop;
-
- // if bottom overflow is larger, move to the top because it fits better, or if dropup is requested
- var moveTop = hostPosition.top - collectionHeight - 5;
- if ( (bottomOverflow > topOverflow || options.dropup) && -moveTop < tableTop ) {
- display.css( 'top', moveTop);
- }
-
- // Get the size of the container (left and width - and thus also right)
- var tableLeft = tableContainer.offset().left;
- var tableWidth = tableContainer.width();
- var tableRight = tableLeft + tableWidth;
-
- // Get the size of the popover (left and width - and ...)
- var popoverLeft = display.offset().left;
- var popoverWidth = display.width();
- var popoverRight = popoverLeft + popoverWidth;
-
- // Get the size of the host buttons (left and width - and ...)
- var buttonsLeft = hostNode.offset().left;
- var buttonsWidth = hostNode.outerWidth()
- var buttonsRight = buttonsLeft + buttonsWidth;
-
- // You've then got all the numbers you need to do some calculations and if statements,
- // so we can do some quick JS maths and apply it only once
- // If it has the right align class OR the buttons are right aligned OR the button container is floated right,
- // then calculate left position for the popover to align the popover to the right hand
- // side of the button - check to see if the left of the popover is inside the table container.
- // If not, move the popover so it is, but not more than it means that the popover is to the right of the table container
- var popoverShuffle = 0;
- if ( display.hasClass( options.rightAlignClassName )) {
- popoverShuffle = buttonsRight - popoverRight;
- if(tableLeft > (popoverLeft + popoverShuffle)){
- var leftGap = tableLeft - (popoverLeft + popoverShuffle);
- var rightGap = tableRight - (popoverRight + popoverShuffle);
-
- if(leftGap > rightGap){
- popoverShuffle += rightGap;
- }
- else {
- popoverShuffle += leftGap;
- }
- }
- }
- // else attempt to left align the popover to the button. Similar to above, if the popover's right goes past the table container's right,
- // then move it back, but not so much that it goes past the left of the table container
- else {
- popoverShuffle = tableLeft - popoverLeft;
-
- if(tableRight < (popoverRight + popoverShuffle)){
- var leftGap = tableLeft - (popoverLeft + popoverShuffle);
- var rightGap = tableRight - (popoverRight + popoverShuffle);
-
- if(leftGap > rightGap ){
- popoverShuffle += rightGap;
- }
- else {
- popoverShuffle += leftGap;
- }
-
- }
- }
-
- display.css('left', display.position().left + popoverShuffle);
-
- }
- else if (position === 'absolute') {
- // Align relative to the host button
- var hostPosition = hostNode.position();
-
- display.css( {
- top: hostPosition.top + hostNode.outerHeight(),
- left: hostPosition.left
- } );
-
- // calculate overflow when positioned beneath
- var collectionHeight = display.outerHeight();
- var top = hostNode.offset().top
- var popoverShuffle = 0;
-
- // Get the size of the host buttons (left and width - and ...)
- var buttonsLeft = hostNode.offset().left;
- var buttonsWidth = hostNode.outerWidth()
- var buttonsRight = buttonsLeft + buttonsWidth;
-
- // Get the size of the popover (left and width - and ...)
- var popoverLeft = display.offset().left;
- var popoverWidth = content.width();
- var popoverRight = popoverLeft + popoverWidth;
-
- var moveTop = hostPosition.top - collectionHeight - 5;
- var tableBottom = tableContainer.offset().top + tableContainer.height();
- var listBottom = hostPosition.top + hostNode.outerHeight() + collectionHeight;
- var bottomOverflow = listBottom - tableBottom;
-
- // calculate overflow when positioned above
- var listTop = hostPosition.top - collectionHeight;
- var tableTop = tableContainer.offset().top;
- var topOverflow = tableTop - listTop;
-
- if ( (bottomOverflow > topOverflow || options.dropup) && -moveTop < tableTop ) {
- display.css( 'top', moveTop);
- }
-
- popoverShuffle = options.align === 'button-right'
- ? buttonsRight - popoverRight
- : buttonsLeft - popoverLeft;
-
- display.css('left', display.position().left + popoverShuffle);
- }
- else {
- // Fix position - centre on screen
- var top = display.height() / 2;
- if ( top > $(window).height() / 2 ) {
- top = $(window).height() / 2;
- }
-
- display.css( 'marginTop', top*-1 );
- }
-
- if ( options.background ) {
- Buttons.background( true, options.backgroundClassName, options.fade, hostNode );
- }
-
- // This is bonkers, but if we don't have a click listener on the
- // background element, iOS Safari will ignore the body click
- // listener below. An empty function here is all that is
- // required to make it work...
- $('div.dt-button-background').on( 'click.dtb-collection', function () {} );
-
- $('body')
- .on( 'click.dtb-collection', function (e) {
- // andSelf is deprecated in jQ1.8, but we want 1.7 compat
- var back = $.fn.addBack ? 'addBack' : 'andSelf';
- var parent = $(e.target).parent()[0];
-
- if (( ! $(e.target).parents()[back]().filter( content ).length && !$(parent).hasClass('dt-buttons')) || $(e.target).hasClass('dt-button-background')) {
- close();
- }
- } )
- .on( 'keyup.dtb-collection', function (e) {
- if ( e.keyCode === 27 ) {
- close();
- }
- } );
-
- if ( options.autoClose ) {
- setTimeout( function () {
- dt.on( 'buttons-action.b-internal', function (e, btn, dt, node) {
- if ( node[0] === hostNode[0] ) {
- return;
- }
- close();
- } );
- }, 0);
- }
-
- $(display).trigger('buttons-popover.dt');
- }
-} );
-
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Statics
- */
-
-/**
- * Show / hide a background layer behind a collection
- * @param {boolean} Flag to indicate if the background should be shown or
- * hidden
- * @param {string} Class to assign to the background
- * @static
- */
-Buttons.background = function ( show, className, fade, insertPoint ) {
- if ( fade === undefined ) {
- fade = 400;
- }
- if ( ! insertPoint ) {
- insertPoint = document.body;
- }
-
- if ( show ) {
- _fadeIn(
- $('')
- .addClass( className )
- .css( 'display', 'none' )
- .insertAfter( insertPoint ),
- fade
- );
- }
- else {
- _fadeOut(
- $('div.'+className),
- fade,
- function () {
- $(this)
- .removeClass( className )
- .remove();
- }
- );
- }
-};
-
-/**
- * Instance selector - select Buttons instances based on an instance selector
- * value from the buttons assigned to a DataTable. This is only useful if
- * multiple instances are attached to a DataTable.
- * @param {string|int|array} Instance selector - see `instance-selector`
- * documentation on the DataTables site
- * @param {array} Button instance array that was attached to the DataTables
- * settings object
- * @return {array} Buttons instances
- * @static
- */
-Buttons.instanceSelector = function ( group, buttons )
-{
- if ( group === undefined || group === null ) {
- return $.map( buttons, function ( v ) {
- return v.inst;
- } );
- }
-
- var ret = [];
- var names = $.map( buttons, function ( v ) {
- return v.name;
- } );
-
- // Flatten the group selector into an array of single options
- var process = function ( input ) {
- if ( Array.isArray( input ) ) {
- for ( var i=0, ien=input.length ; i` in IE - it has to be ``
- tag: 'ActiveXObject' in window ?
- 'a' :
- 'button',
- className: 'dt-button',
- active: 'active',
- disabled: 'disabled'
- },
- buttonLiner: {
- tag: 'span',
- className: ''
- }
- }
-};
-
-/**
- * Version information
- * @type {string}
- * @static
- */
-Buttons.version = '1.6.5';
-
-
-$.extend( _dtButtons, {
- collection: {
- text: function ( dt ) {
- return dt.i18n( 'buttons.collection', 'Collection' );
- },
- className: 'buttons-collection',
- init: function ( dt, button, config ) {
- button.attr( 'aria-expanded', false );
- },
- action: function ( e, dt, button, config ) {
- e.stopPropagation();
-
- if ( config._collection.parents('body').length ) {
- this.popover(false, config);
- }
- else {
- this.popover(config._collection, config);
- }
- },
- attr: {
- 'aria-haspopup': true
- }
- // Also the popover options, defined in Buttons.popover
- },
- copy: function ( dt, conf ) {
- if ( _dtButtons.copyHtml5 ) {
- return 'copyHtml5';
- }
- if ( _dtButtons.copyFlash && _dtButtons.copyFlash.available( dt, conf ) ) {
- return 'copyFlash';
- }
- },
- csv: function ( dt, conf ) {
- // Common option that will use the HTML5 or Flash export buttons
- if ( _dtButtons.csvHtml5 && _dtButtons.csvHtml5.available( dt, conf ) ) {
- return 'csvHtml5';
- }
- if ( _dtButtons.csvFlash && _dtButtons.csvFlash.available( dt, conf ) ) {
- return 'csvFlash';
- }
- },
- excel: function ( dt, conf ) {
- // Common option that will use the HTML5 or Flash export buttons
- if ( _dtButtons.excelHtml5 && _dtButtons.excelHtml5.available( dt, conf ) ) {
- return 'excelHtml5';
- }
- if ( _dtButtons.excelFlash && _dtButtons.excelFlash.available( dt, conf ) ) {
- return 'excelFlash';
- }
- },
- pdf: function ( dt, conf ) {
- // Common option that will use the HTML5 or Flash export buttons
- if ( _dtButtons.pdfHtml5 && _dtButtons.pdfHtml5.available( dt, conf ) ) {
- return 'pdfHtml5';
- }
- if ( _dtButtons.pdfFlash && _dtButtons.pdfFlash.available( dt, conf ) ) {
- return 'pdfFlash';
- }
- },
- pageLength: function ( dt ) {
- var lengthMenu = dt.settings()[0].aLengthMenu;
- var vals = Array.isArray( lengthMenu[0] ) ? lengthMenu[0] : lengthMenu;
- var lang = Array.isArray( lengthMenu[0] ) ? lengthMenu[1] : lengthMenu;
- var text = function ( dt ) {
- return dt.i18n( 'buttons.pageLength', {
- "-1": 'Show all rows',
- _: 'Show %d rows'
- }, dt.page.len() );
- };
-
- return {
- extend: 'collection',
- text: text,
- className: 'buttons-page-length',
- autoClose: true,
- buttons: $.map( vals, function ( val, i ) {
- return {
- text: lang[i],
- className: 'button-page-length',
- action: function ( e, dt ) {
- dt.page.len( val ).draw();
- },
- init: function ( dt, node, conf ) {
- var that = this;
- var fn = function () {
- that.active( dt.page.len() === val );
- };
-
- dt.on( 'length.dt'+conf.namespace, fn );
- fn();
- },
- destroy: function ( dt, node, conf ) {
- dt.off( 'length.dt'+conf.namespace );
- }
- };
- } ),
- init: function ( dt, node, conf ) {
- var that = this;
- dt.on( 'length.dt'+conf.namespace, function () {
- that.text( conf.text );
- } );
- },
- destroy: function ( dt, node, conf ) {
- dt.off( 'length.dt'+conf.namespace );
- }
- };
- }
-} );
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * DataTables API
- *
- * For complete documentation, please refer to the docs/api directory or the
- * DataTables site
- */
-
-// Buttons group and individual button selector
-DataTable.Api.register( 'buttons()', function ( group, selector ) {
- // Argument shifting
- if ( selector === undefined ) {
- selector = group;
- group = undefined;
- }
-
- this.selector.buttonGroup = group;
-
- var res = this.iterator( true, 'table', function ( ctx ) {
- if ( ctx._buttons ) {
- return Buttons.buttonSelector(
- Buttons.instanceSelector( group, ctx._buttons ),
- selector
- );
- }
- }, true );
-
- res._groupSelector = group;
- return res;
-} );
-
-// Individual button selector
-DataTable.Api.register( 'button()', function ( group, selector ) {
- // just run buttons() and truncate
- var buttons = this.buttons( group, selector );
-
- if ( buttons.length > 1 ) {
- buttons.splice( 1, buttons.length );
- }
-
- return buttons;
-} );
-
-// Active buttons
-DataTable.Api.registerPlural( 'buttons().active()', 'button().active()', function ( flag ) {
- if ( flag === undefined ) {
- return this.map( function ( set ) {
- return set.inst.active( set.node );
- } );
- }
-
- return this.each( function ( set ) {
- set.inst.active( set.node, flag );
- } );
-} );
-
-// Get / set button action
-DataTable.Api.registerPlural( 'buttons().action()', 'button().action()', function ( action ) {
- if ( action === undefined ) {
- return this.map( function ( set ) {
- return set.inst.action( set.node );
- } );
- }
-
- return this.each( function ( set ) {
- set.inst.action( set.node, action );
- } );
-} );
-
-// Enable / disable buttons
-DataTable.Api.register( ['buttons().enable()', 'button().enable()'], function ( flag ) {
- return this.each( function ( set ) {
- set.inst.enable( set.node, flag );
- } );
-} );
-
-// Disable buttons
-DataTable.Api.register( ['buttons().disable()', 'button().disable()'], function () {
- return this.each( function ( set ) {
- set.inst.disable( set.node );
- } );
-} );
-
-// Get button nodes
-DataTable.Api.registerPlural( 'buttons().nodes()', 'button().node()', function () {
- var jq = $();
-
- // jQuery will automatically reduce duplicates to a single entry
- $( this.each( function ( set ) {
- jq = jq.add( set.inst.node( set.node ) );
- } ) );
-
- return jq;
-} );
-
-// Get / set button processing state
-DataTable.Api.registerPlural( 'buttons().processing()', 'button().processing()', function ( flag ) {
- if ( flag === undefined ) {
- return this.map( function ( set ) {
- return set.inst.processing( set.node );
- } );
- }
-
- return this.each( function ( set ) {
- set.inst.processing( set.node, flag );
- } );
-} );
-
-// Get / set button text (i.e. the button labels)
-DataTable.Api.registerPlural( 'buttons().text()', 'button().text()', function ( label ) {
- if ( label === undefined ) {
- return this.map( function ( set ) {
- return set.inst.text( set.node );
- } );
- }
-
- return this.each( function ( set ) {
- set.inst.text( set.node, label );
- } );
-} );
-
-// Trigger a button's action
-DataTable.Api.registerPlural( 'buttons().trigger()', 'button().trigger()', function () {
- return this.each( function ( set ) {
- set.inst.node( set.node ).trigger( 'click' );
- } );
-} );
-
-// Button resolver to the popover
-DataTable.Api.register( 'button().popover()', function (content, options) {
- return this.map( function ( set ) {
- return set.inst._popover( content, this.button(this[0].node), options );
- } );
-} );
-
-// Get the container elements
-DataTable.Api.register( 'buttons().containers()', function () {
- var jq = $();
- var groupSelector = this._groupSelector;
-
- // We need to use the group selector directly, since if there are no buttons
- // the result set will be empty
- this.iterator( true, 'table', function ( ctx ) {
- if ( ctx._buttons ) {
- var insts = Buttons.instanceSelector( groupSelector, ctx._buttons );
-
- for ( var i=0, ien=insts.length ; i'+title+'' : '';
-
- _fadeIn(
- $('')
- .html( title )
- .append( $('')[ typeof message === 'string' ? 'html' : 'append' ]( message ) )
- .css( 'display', 'none' )
- .appendTo( 'body' )
- );
-
- if ( time !== undefined && time !== 0 ) {
- _infoTimer = setTimeout( function () {
- that.buttons.info( false );
- }, time );
- }
-
- this.on('destroy.btn-info', function () {
- that.buttons.info(false);
- });
-
- return this;
-} );
-
-// Get data from the table for export - this is common to a number of plug-in
-// buttons so it is included in the Buttons core library
-DataTable.Api.register( 'buttons.exportData()', function ( options ) {
- if ( this.context.length ) {
- return _exportData( new DataTable.Api( this.context[0] ), options );
- }
-} );
-
-// Get information about the export that is common to many of the export data
-// types (DRY)
-DataTable.Api.register( 'buttons.exportInfo()', function ( conf ) {
- if ( ! conf ) {
- conf = {};
- }
-
- return {
- filename: _filename( conf ),
- title: _title( conf ),
- messageTop: _message(this, conf.message || conf.messageTop, 'top'),
- messageBottom: _message(this, conf.messageBottom, 'bottom')
- };
-} );
-
-
-
-/**
- * Get the file name for an exported file.
- *
- * @param {object} config Button configuration
- * @param {boolean} incExtension Include the file name extension
- */
-var _filename = function ( config )
-{
- // Backwards compatibility
- var filename = config.filename === '*' && config.title !== '*' && config.title !== undefined && config.title !== null && config.title !== '' ?
- config.title :
- config.filename;
-
- if ( typeof filename === 'function' ) {
- filename = filename();
- }
-
- if ( filename === undefined || filename === null ) {
- return null;
- }
-
- if ( filename.indexOf( '*' ) !== -1 ) {
- filename = filename.replace( '*', $('head > title').text() ).trim();
- }
-
- // Strip characters which the OS will object to
- filename = filename.replace(/[^a-zA-Z0-9_\u00A1-\uFFFF\.,\-_ !\(\)]/g, "");
-
- var extension = _stringOrFunction( config.extension );
- if ( ! extension ) {
- extension = '';
- }
-
- return filename + extension;
-};
-
-/**
- * Simply utility method to allow parameters to be given as a function
- *
- * @param {undefined|string|function} option Option
- * @return {null|string} Resolved value
- */
-var _stringOrFunction = function ( option )
-{
- if ( option === null || option === undefined ) {
- return null;
- }
- else if ( typeof option === 'function' ) {
- return option();
- }
- return option;
-};
-
-/**
- * Get the title for an exported file.
- *
- * @param {object} config Button configuration
- */
-var _title = function ( config )
-{
- var title = _stringOrFunction( config.title );
-
- return title === null ?
- null : title.indexOf( '*' ) !== -1 ?
- title.replace( '*', $('head > title').text() || 'Exported data' ) :
- title;
-};
-
-var _message = function ( dt, option, position )
-{
- var message = _stringOrFunction( option );
- if ( message === null ) {
- return null;
- }
-
- var caption = $('caption', dt.table().container()).eq(0);
- if ( message === '*' ) {
- var side = caption.css( 'caption-side' );
- if ( side !== position ) {
- return null;
- }
-
- return caption.length ?
- caption.text() :
- '';
- }
-
- return message;
-};
-
-
-
-
-
-
-
-var _exportTextarea = $('')[0];
-var _exportData = function ( dt, inOpts )
-{
- var config = $.extend( true, {}, {
- rows: null,
- columns: '',
- modifier: {
- search: 'applied',
- order: 'applied'
- },
- orthogonal: 'display',
- stripHtml: true,
- stripNewlines: true,
- decodeEntities: true,
- trim: true,
- format: {
- header: function ( d ) {
- return strip( d );
- },
- footer: function ( d ) {
- return strip( d );
- },
- body: function ( d ) {
- return strip( d );
- }
- },
- customizeData: null
- }, inOpts );
-
- var strip = function ( str ) {
- if ( typeof str !== 'string' ) {
- return str;
- }
-
- // Always remove script tags
- str = str.replace( /
-
@stack('scripts')