jquery-datatables 1.10.19.1 → 1.10.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +1 -0
  3. data/README.md +28 -1
  4. data/app/assets/javascripts/datatables/dataTables.uikit.js +2 -2
  5. data/app/assets/javascripts/datatables/extensions/AutoFill/dataTables.autoFill.js +42 -29
  6. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.bootstrap.js +1 -1
  7. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.bootstrap4.js +8 -2
  8. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.colVis.js +6 -3
  9. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.foundation.js +5 -4
  10. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.html5.js +58 -6
  11. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.print.js +16 -5
  12. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.semanticui.js +1 -1
  13. data/app/assets/javascripts/datatables/extensions/Buttons/dataTables.buttons.js +267 -152
  14. data/app/assets/javascripts/datatables/extensions/ColReorder/colReorder.foundation.js +1 -1
  15. data/app/assets/javascripts/datatables/extensions/ColReorder/dataTables.colReorder.js +121 -52
  16. data/app/assets/javascripts/datatables/extensions/FixedColumns/dataTables.fixedColumns.js +32 -5
  17. data/app/assets/javascripts/datatables/extensions/KeyTable/dataTables.keyTable.js +166 -63
  18. data/app/assets/javascripts/datatables/extensions/KeyTable/keyTable.foundation.js +1 -1
  19. data/app/assets/javascripts/datatables/extensions/RowGroup/dataTables.rowGroup.js +105 -53
  20. data/app/assets/javascripts/datatables/extensions/RowGroup/rowGroup.foundation.js +1 -1
  21. data/app/assets/javascripts/datatables/extensions/RowGroup/{rowGroup.semanicui.js → rowGroup.semanticui.js} +0 -0
  22. data/app/assets/javascripts/datatables/extensions/RowReorder/dataTables.rowReorder.js +10 -9
  23. data/app/assets/javascripts/datatables/extensions/RowReorder/rowReorder.foundation.js +1 -1
  24. data/app/assets/javascripts/datatables/extensions/Scroller/dataTables.scroller.js +519 -636
  25. data/app/assets/javascripts/datatables/extensions/Scroller/scroller.foundation.js +1 -1
  26. data/app/assets/javascripts/datatables/extensions/Select/dataTables.select.js +49 -18
  27. data/app/assets/javascripts/datatables/extensions/Select/select.foundation.js +1 -1
  28. data/app/assets/javascripts/datatables/jquery.dataTables.js +97 -60
  29. data/app/assets/javascripts/datatables/plugins/api/average.js +7 -6
  30. data/app/assets/javascripts/datatables/plugins/api/sum.js +7 -6
  31. data/app/assets/javascripts/datatables/plugins/pagination/ellipses.js +160 -0
  32. data/app/assets/javascripts/datatables/plugins/pagination/extjs.js +137 -0
  33. data/app/assets/javascripts/datatables/plugins/pagination/four_button.js +110 -0
  34. data/app/assets/javascripts/datatables/plugins/pagination/full_numbers_no_ellipses.js +59 -0
  35. data/app/assets/javascripts/datatables/plugins/pagination/input.js +22 -19
  36. data/app/assets/javascripts/datatables/plugins/pagination/scrolling.js +130 -0
  37. data/app/assets/javascripts/datatables/plugins/pagination/select.js +97 -0
  38. data/app/assets/javascripts/datatables/plugins/pagination/simple_incremental_bootstrap.js +154 -0
  39. data/app/assets/javascripts/datatables/plugins/pagination/simple_numbers_no_ellipses.js +59 -0
  40. data/app/assets/javascripts/datatables/plugins/search/dataTables.alphabetSearch.js +440 -399
  41. data/app/assets/javascripts/datatables/plugins/sorting/enum.js +51 -0
  42. data/app/assets/javascripts/datatables/plugins/type-detection/date-dd-MMM-yyyy.js +63 -0
  43. data/app/assets/javascripts/datatables/plugins/type-detection/date-de.js +125 -0
  44. data/app/assets/javascripts/datatables/plugins/type-detection/date-eu.js +64 -0
  45. data/app/assets/javascripts/datatables/plugins/type-detection/date-euro.js +48 -0
  46. data/app/assets/javascripts/datatables/plugins/type-detection/date-uk.js +35 -12
  47. data/app/assets/javascripts/datatables/plugins/type-detection/datetime-moment.js +74 -0
  48. data/app/assets/javascripts/datatables/plugins/type-detection/datetime-us.js +86 -0
  49. data/app/assets/javascripts/datatables/plugins/type-detection/file-size.js +37 -13
  50. data/app/assets/javascripts/datatables/plugins/type-detection/ip-address.js +113 -11
  51. data/app/assets/javascripts/datatables/plugins/type-detection/numString.js +63 -0
  52. data/app/assets/javascripts/datatables/plugins/type-detection/percent.js +34 -0
  53. data/app/assets/javascripts/datatables/plugins/type-detection/time-elapsed-dhms.js +42 -0
  54. data/app/assets/javascripts/datatables/plugins/type-detection/time.js +56 -0
  55. data/app/assets/javascripts/datatables/plugins/type-detection/title-numeric.js +40 -0
  56. data/app/assets/javascripts/datatables/plugins/type-detection/title-string.js +36 -0
  57. data/app/assets/stylesheets/datatables/extensions/AutoFill/autoFill.dataTables.scss +10 -3
  58. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.bootstrap.scss +12 -3
  59. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.bootstrap4.scss +13 -6
  60. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.dataTables.scss +2 -0
  61. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.foundation.scss +5 -1
  62. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.jqueryui.scss +1 -0
  63. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.semanticui.scss +2 -1
  64. data/app/assets/stylesheets/datatables/extensions/Buttons/common.scss +10 -0
  65. data/app/assets/stylesheets/datatables/extensions/Buttons/mixins.scss +42 -30
  66. data/app/assets/stylesheets/datatables/extensions/FixedColumns/fixedColumns.bootstrap.scss +11 -7
  67. data/app/assets/stylesheets/datatables/extensions/FixedColumns/fixedColumns.foundation.scss +1 -0
  68. data/app/assets/stylesheets/datatables/extensions/KeyTable/keyTable.dataTables.scss +13 -5
  69. data/app/assets/stylesheets/datatables/extensions/RowGroup/rowGroup.dataTables.scss +20 -2
  70. data/app/assets/stylesheets/datatables/extensions/Scroller/scroller.dataTables.scss +15 -2
  71. data/lib/jquery-datatables/version.rb +1 -1
  72. metadata +26 -12
  73. data/app/assets/javascripts/datatables/dataTables.bootstrap2.js +0 -162
  74. data/app/assets/javascripts/datatables/extensions/ColReorder/colReorder.semanicui.js +0 -38
  75. data/app/assets/javascripts/datatables/extensions/FixedColumns/fixedColumns.semanicui.js +0 -38
  76. data/app/assets/javascripts/datatables/extensions/FixedHeader/fixedHeader.semanicui.js +0 -38
  77. data/app/assets/javascripts/datatables/extensions/KeyTable/keyTable.semanicui.js +0 -38
  78. data/app/assets/javascripts/datatables/extensions/RowReorder/rowReorder.semanicui.js +0 -38
  79. data/app/assets/stylesheets/datatables/dataTables.bootstrap2.scss +0 -178
@@ -91,9 +91,13 @@ DataTable.ext.buttons.print = {
91
91
  $.extend( {decodeEntities: false}, config.exportOptions ) // XSS protection
92
92
  );
93
93
  var exportInfo = dt.buttons.exportInfo( config );
94
- var columnClasses = $.map( dt.settings()[0].aoColumns, function (col, key) {
95
- return col.sClass;
96
- } );
94
+ var columnClasses = dt
95
+ .columns( config.exportOptions.columns )
96
+ .flatten()
97
+ .map( function (idx) {
98
+ return dt.settings()[0].aoColumns[dt.column(idx).index()].sClass;
99
+ } )
100
+ .toArray();
97
101
 
98
102
  var addRow = function ( d, tag ) {
99
103
  var str = '<tr>';
@@ -169,12 +173,19 @@ DataTable.ext.buttons.print = {
169
173
  }
170
174
 
171
175
  // Allow stylesheets time to load
172
- win.setTimeout( function () {
176
+ var autoPrint = function () {
173
177
  if ( config.autoPrint ) {
174
178
  win.print(); // blocking - so close will not
175
179
  win.close(); // execute until this is done
176
180
  }
177
- }, 1000 );
181
+ };
182
+
183
+ if ( navigator.userAgent.match(/Trident\/\d.\d/) ) { // IE needs to call this without a setTimeout
184
+ autoPrint();
185
+ }
186
+ else {
187
+ win.setTimeout( autoPrint, 1000 );
188
+ }
178
189
  },
179
190
 
180
191
  title: '*',
@@ -47,7 +47,7 @@ $.extend( true, DataTable.Buttons.defaults, {
47
47
  },
48
48
  collection: {
49
49
  tag: 'div',
50
- className: 'dt-button-collection ui basic vertical buttons'
50
+ className: 'ui basic vertical buttons'
51
51
  }
52
52
  }
53
53
  } );
@@ -1,5 +1,5 @@
1
- /*! Buttons for DataTables 1.5.2
2
- * ©2016-2018 SpryMedia Ltd - datatables.net/license
1
+ /*! Buttons for DataTables 1.6.1
2
+ * ©2016-2019 SpryMedia Ltd - datatables.net/license
3
3
  */
4
4
 
5
5
  (function( factory ){
@@ -48,6 +48,15 @@ var _dtButtons = DataTable.ext.buttons;
48
48
  */
49
49
  var Buttons = function( dt, config )
50
50
  {
51
+ // If not created with a `new` keyword then we return a wrapper function that
52
+ // will take the settings object for a DT. This allows easy use of new instances
53
+ // with the `layout` option - e.g. `topLeft: $.fn.dataTable.Buttons( ... )`.
54
+ if ( !(this instanceof Buttons) ) {
55
+ return function (settings) {
56
+ return new Buttons( settings, dt ).container();
57
+ };
58
+ }
59
+
51
60
  // If there is no config set it to an empty object
52
61
  if ( typeof( config ) === 'undefined' ) {
53
62
  config = {};
@@ -157,7 +166,7 @@ $.extend( Buttons.prototype, {
157
166
  idx = split[ split.length-1 ]*1;
158
167
  }
159
168
 
160
- this._expandButton( buttons, config, false, idx );
169
+ this._expandButton( buttons, config, base !== undefined, idx );
161
170
  this._draw();
162
171
 
163
172
  return this;
@@ -248,23 +257,29 @@ $.extend( Buttons.prototype, {
248
257
  },
249
258
 
250
259
  /**
251
- * Get a button's node
252
- * @param {node} node Button node
253
- * @return {jQuery} Button element
260
+ * Get a button's node of the buttons container if no button is given
261
+ * @param {node} [node] Button node
262
+ * @return {jQuery} Button element, or container
254
263
  */
255
264
  node: function ( node )
256
265
  {
266
+ if ( ! node ) {
267
+ return this.dom.container;
268
+ }
269
+
257
270
  var button = this._nodeToButton( node );
258
271
  return $(button.node);
259
272
  },
260
273
 
261
274
  /**
262
275
  * Set / get a processing class on the selected button
276
+ * @param {element} node Triggering button node
263
277
  * @param {boolean} flag true to add, false to remove, undefined to get
264
278
  * @return {boolean|Buttons} Getter value or this if a setter.
265
279
  */
266
280
  processing: function ( node, flag )
267
281
  {
282
+ var dt = this.s.dt;
268
283
  var button = this._nodeToButton( node );
269
284
 
270
285
  if ( flag === undefined ) {
@@ -273,6 +288,10 @@ $.extend( Buttons.prototype, {
273
288
 
274
289
  $(button.node).toggleClass( 'processing', flag );
275
290
 
291
+ $(dt.table().node()).triggerHandler( 'buttons-processing.dt', [
292
+ flag, dt.button( node ), dt, $(node), button.conf
293
+ ] );
294
+
276
295
  return this;
277
296
  },
278
297
 
@@ -486,10 +505,8 @@ $.extend( Buttons.prototype, {
486
505
  }
487
506
 
488
507
  if ( built.conf.buttons ) {
489
- var collectionDom = this.c.dom.collection;
490
- built.collection = $('<'+collectionDom.tag+'/>')
491
- .addClass( collectionDom.className )
492
- .attr( 'role', 'menu') ;
508
+ built.collection = $('<'+this.c.dom.collection.tag+'/>');
509
+
493
510
  built.conf._collection = built.collection;
494
511
 
495
512
  this._expandButton( built.buttons, built.conf.buttons, true, attachPoint );
@@ -547,6 +564,7 @@ $.extend( Buttons.prototype, {
547
564
  };
548
565
 
549
566
  var tag = config.tag || buttonDom.tag;
567
+ var clickBlurs = config.clickBlurs === undefined ? true : config.clickBlurs
550
568
  var button = $('<'+tag+'/>')
551
569
  .addClass( buttonDom.className )
552
570
  .attr( 'tabindex', this.s.dt.settings()[0].iTabIndex )
@@ -557,8 +575,9 @@ $.extend( Buttons.prototype, {
557
575
  if ( ! button.hasClass( buttonDom.disabled ) && config.action ) {
558
576
  action( e, dt, button, config );
559
577
  }
560
-
561
- button.blur();
578
+ if( clickBlurs ) {
579
+ button.blur();
580
+ }
562
581
  } )
563
582
  .on( 'keyup.dtb', function (e) {
564
583
  if ( e.keyCode === 13 ) {
@@ -626,6 +645,13 @@ $.extend( Buttons.prototype, {
626
645
 
627
646
  this._addKey( config );
628
647
 
648
+ // Style integration callback for DOM manipulation
649
+ // Note that this is _not_ documented. It is currently
650
+ // for style integration only
651
+ if( this.c.buttonCreated ) {
652
+ inserter = this.c.buttonCreated( config, inserter );
653
+ }
654
+
629
655
  return {
630
656
  conf: config,
631
657
  node: button.get(0),
@@ -892,6 +918,180 @@ $.extend( Buttons.prototype, {
892
918
  }
893
919
 
894
920
  return conf;
921
+ },
922
+
923
+ /**
924
+ * Display (and replace if there is an existing one) a popover attached to a button
925
+ * @param {string|node} content Content to show
926
+ * @param {DataTable.Api} hostButton DT API instance of the button
927
+ * @param {object} inOpts Options (see object below for all options)
928
+ */
929
+ _popover: function ( content, hostButton, inOpts ) {
930
+ var dt = hostButton;
931
+ var buttonsSettings = this.c;
932
+ var options = $.extend( {
933
+ align: 'button-left', // button-right, dt-container
934
+ autoClose: false,
935
+ background: true,
936
+ backgroundClassName: 'dt-button-background',
937
+ contentClassName: buttonsSettings.dom.collection.className,
938
+ collectionLayout: '',
939
+ collectionTitle: '',
940
+ dropup: false,
941
+ fade: 400,
942
+ rightAlignClassName: 'dt-button-right',
943
+ tag: buttonsSettings.dom.collection.tag
944
+ }, inOpts );
945
+ var hostNode = hostButton.node();
946
+
947
+ var close = function () {
948
+ $('.dt-button-collection').stop().fadeOut( options.fade, function () {
949
+ $(this).detach();
950
+ } );
951
+
952
+ $(dt.buttons( '[aria-haspopup="true"][aria-expanded="true"]' ).nodes())
953
+ .attr('aria-expanded', 'false');
954
+
955
+ $('div.dt-button-background').off( 'click.dtb-collection' );
956
+ Buttons.background( false, options.backgroundClassName, options.fade, hostNode );
957
+
958
+ $('body').off( '.dtb-collection' );
959
+ dt.off( 'buttons-action.b-internal' );
960
+ };
961
+
962
+ if (content === false) {
963
+ close();
964
+ }
965
+
966
+ var existingExpanded = $(dt.buttons( '[aria-haspopup="true"][aria-expanded="true"]' ).nodes());
967
+ if ( existingExpanded.length ) {
968
+ hostNode = existingExpanded.eq(0);
969
+
970
+ close();
971
+ }
972
+
973
+ var display = $('<div/>')
974
+ .addClass('dt-button-collection')
975
+ .addClass(options.collectionLayout)
976
+ .css('display', 'none');
977
+
978
+ content = $(content)
979
+ .addClass(options.contentClassName)
980
+ .attr('role', 'menu')
981
+ .appendTo(display);
982
+
983
+ hostNode.attr( 'aria-expanded', 'true' );
984
+
985
+ if ( hostNode.parents('body')[0] !== document.body ) {
986
+ hostNode = document.body.lastChild;
987
+ }
988
+
989
+ if ( options.collectionTitle ) {
990
+ display.prepend('<div class="dt-button-collection-title">'+options.collectionTitle+'</div>');
991
+ }
992
+
993
+ display
994
+ .insertAfter( hostNode )
995
+ .fadeIn( options.fade );
996
+
997
+ var tableContainer = $( hostButton.table().container() );
998
+ var position = display.css( 'position' );
999
+
1000
+ if ( options.align === 'dt-container' ) {
1001
+ hostNode = hostNode.parent();
1002
+ display.css('width', tableContainer.width());
1003
+ }
1004
+
1005
+ if ( position === 'absolute' ) {
1006
+ var hostPosition = hostNode.position();
1007
+
1008
+ display.css( {
1009
+ top: hostPosition.top + hostNode.outerHeight(),
1010
+ left: hostPosition.left
1011
+ } );
1012
+
1013
+ // calculate overflow when positioned beneath
1014
+ var collectionHeight = display.outerHeight();
1015
+ var collectionWidth = display.outerWidth();
1016
+ var tableBottom = tableContainer.offset().top + tableContainer.height();
1017
+ var listBottom = hostPosition.top + hostNode.outerHeight() + collectionHeight;
1018
+ var bottomOverflow = listBottom - tableBottom;
1019
+
1020
+ // calculate overflow when positioned above
1021
+ var listTop = hostPosition.top - collectionHeight;
1022
+ var tableTop = tableContainer.offset().top;
1023
+ var topOverflow = tableTop - listTop;
1024
+
1025
+ // if bottom overflow is larger, move to the top because it fits better, or if dropup is requested
1026
+ var moveTop = hostPosition.top - collectionHeight - 5;
1027
+ if ( (bottomOverflow > topOverflow || options.dropup) && -moveTop < tableTop ) {
1028
+ display.css( 'top', moveTop);
1029
+ }
1030
+
1031
+ // Right alignment is enabled on a class, e.g. bootstrap:
1032
+ // $.fn.dataTable.Buttons.defaults.dom.collection.className += " dropdown-menu-right";
1033
+ if ( display.hasClass( options.rightAlignClassName ) || options.align === 'button-right' ) {
1034
+ display.css( 'left', hostPosition.left + hostNode.outerWidth() - collectionWidth );
1035
+ }
1036
+
1037
+ // Right alignment in table container
1038
+ var listRight = hostPosition.left + collectionWidth;
1039
+ var tableRight = tableContainer.offset().left + tableContainer.width();
1040
+ if ( listRight > tableRight ) {
1041
+ display.css( 'left', hostPosition.left - ( listRight - tableRight ) );
1042
+ }
1043
+
1044
+ // Right alignment to window
1045
+ var listOffsetRight = hostNode.offset().left + collectionWidth;
1046
+ if ( listOffsetRight > $(window).width() ) {
1047
+ display.css( 'left', hostPosition.left - (listOffsetRight-$(window).width()) );
1048
+ }
1049
+ }
1050
+ else {
1051
+ // Fix position - centre on screen
1052
+ var top = display.height() / 2;
1053
+ if ( top > $(window).height() / 2 ) {
1054
+ top = $(window).height() / 2;
1055
+ }
1056
+
1057
+ display.css( 'marginTop', top*-1 );
1058
+ }
1059
+
1060
+ if ( options.background ) {
1061
+ Buttons.background( true, options.backgroundClassName, options.fade, hostNode );
1062
+ }
1063
+
1064
+ // This is bonkers, but if we don't have a click listener on the
1065
+ // background element, iOS Safari will ignore the body click
1066
+ // listener below. An empty function here is all that is
1067
+ // required to make it work...
1068
+ $('div.dt-button-background').on( 'click.dtb-collection', function () {} );
1069
+
1070
+ $('body')
1071
+ .on( 'click.dtb-collection', function (e) {
1072
+ // andSelf is deprecated in jQ1.8, but we want 1.7 compat
1073
+ var back = $.fn.addBack ? 'addBack' : 'andSelf';
1074
+
1075
+ if ( ! $(e.target).parents()[back]().filter( content ).length ) {
1076
+ close();
1077
+ }
1078
+ } )
1079
+ .on( 'keyup.dtb-collection', function (e) {
1080
+ if ( e.keyCode === 27 ) {
1081
+ close();
1082
+ }
1083
+ } );
1084
+
1085
+ if ( options.autoClose ) {
1086
+ setTimeout( function () {
1087
+ dt.on( 'buttons-action.b-internal', function (e, btn, dt, node) {
1088
+ if ( node[0] === hostNode[0] ) {
1089
+ return;
1090
+ }
1091
+ close();
1092
+ } );
1093
+ }, 0);
1094
+ }
895
1095
  }
896
1096
  } );
897
1097
 
@@ -908,20 +1108,25 @@ $.extend( Buttons.prototype, {
908
1108
  * @param {string} Class to assign to the background
909
1109
  * @static
910
1110
  */
911
- Buttons.background = function ( show, className, fade ) {
1111
+ Buttons.background = function ( show, className, fade, insertPoint ) {
912
1112
  if ( fade === undefined ) {
913
1113
  fade = 400;
914
1114
  }
1115
+ if ( ! insertPoint ) {
1116
+ insertPoint = document.body;
1117
+ }
915
1118
 
916
1119
  if ( show ) {
917
1120
  $('<div/>')
918
1121
  .addClass( className )
919
1122
  .css( 'display', 'none' )
920
- .appendTo( 'body' )
1123
+ .insertAfter( insertPoint )
1124
+ .stop()
921
1125
  .fadeIn( fade );
922
1126
  }
923
1127
  else {
924
- $('body > div.'+className)
1128
+ $('div.'+className)
1129
+ .stop()
925
1130
  .fadeOut( fade, function () {
926
1131
  $(this)
927
1132
  .removeClass( className )
@@ -943,7 +1148,7 @@ Buttons.background = function ( show, className, fade ) {
943
1148
  */
944
1149
  Buttons.instanceSelector = function ( group, buttons )
945
1150
  {
946
- if ( ! group ) {
1151
+ if ( group === undefined || group === null ) {
947
1152
  return $.map( buttons, function ( v ) {
948
1153
  return v.inst;
949
1154
  } );
@@ -1142,10 +1347,13 @@ Buttons.defaults = {
1142
1347
  },
1143
1348
  collection: {
1144
1349
  tag: 'div',
1145
- className: 'dt-button-collection'
1350
+ className: ''
1146
1351
  },
1147
1352
  button: {
1148
- tag: 'button',
1353
+ // Flash buttons will not work with `<button>` in IE - it has to be `<a>`
1354
+ tag: 'ActiveXObject' in window ?
1355
+ 'a' :
1356
+ 'button',
1149
1357
  className: 'dt-button',
1150
1358
  active: 'active',
1151
1359
  disabled: 'disabled'
@@ -1162,7 +1370,7 @@ Buttons.defaults = {
1162
1370
  * @type {string}
1163
1371
  * @static
1164
1372
  */
1165
- Buttons.version = '1.5.2';
1373
+ Buttons.version = '1.6.1';
1166
1374
 
1167
1375
 
1168
1376
  $.extend( _dtButtons, {
@@ -1171,140 +1379,23 @@ $.extend( _dtButtons, {
1171
1379
  return dt.i18n( 'buttons.collection', 'Collection' );
1172
1380
  },
1173
1381
  className: 'buttons-collection',
1382
+ init: function ( dt, button, config ) {
1383
+ button.attr( 'aria-expanded', false );
1384
+ },
1174
1385
  action: function ( e, dt, button, config ) {
1175
- var host = button;
1176
- var collectionParent = $(button).parents('div.dt-button-collection');
1177
- var hostPosition = host.position();
1178
- var tableContainer = $( dt.table().container() );
1179
- var multiLevel = false;
1180
- var insertPoint = host;
1181
-
1182
- // Remove any old collection
1183
- if ( collectionParent.length ) {
1184
- multiLevel = $('.dt-button-collection').position();
1185
- insertPoint = collectionParent;
1186
- $('body').trigger( 'click.dtb-collection' );
1187
- }
1188
-
1189
- if ( insertPoint.parents('body')[0] !== document.body ) {
1190
- insertPoint = document.body.lastChild;
1191
- }
1192
-
1193
- config._collection
1194
- .addClass( config.collectionLayout )
1195
- .css( 'display', 'none' )
1196
- .insertAfter( insertPoint )
1197
- .fadeIn( config.fade );
1198
-
1199
-
1200
- var position = config._collection.css( 'position' );
1386
+ e.stopPropagation();
1201
1387
 
1202
- if ( multiLevel && position === 'absolute' ) {
1203
- config._collection.css( {
1204
- top: multiLevel.top,
1205
- left: multiLevel.left
1206
- } );
1207
- }
1208
- else if ( position === 'absolute' ) {
1209
- config._collection.css( {
1210
- top: hostPosition.top + host.outerHeight(),
1211
- left: hostPosition.left
1212
- } );
1213
-
1214
- // calculate overflow when positioned beneath
1215
- var tableBottom = tableContainer.offset().top + tableContainer.height();
1216
- var listBottom = hostPosition.top + host.outerHeight() + config._collection.outerHeight();
1217
- var bottomOverflow = listBottom - tableBottom;
1218
-
1219
- // calculate overflow when positioned above
1220
- var listTop = hostPosition.top - config._collection.outerHeight();
1221
- var tableTop = tableContainer.offset().top;
1222
- var topOverflow = tableTop - listTop;
1223
-
1224
- // if bottom overflow is larger, move to the top because it fits better, or if dropup is requested
1225
- if (bottomOverflow > topOverflow || config.dropup) {
1226
- config._collection.css( 'top', hostPosition.top - config._collection.outerHeight() - 5);
1227
- }
1228
-
1229
- // Right alignment in table container
1230
- var listRight = hostPosition.left + config._collection.outerWidth();
1231
- var tableRight = tableContainer.offset().left + tableContainer.width();
1232
- if ( listRight > tableRight ) {
1233
- config._collection.css( 'left', hostPosition.left - ( listRight - tableRight ) );
1234
- }
1235
-
1236
- // Right alignment to window
1237
- var listOffsetRight = host.offset().left + config._collection.outerWidth();
1238
- if ( listOffsetRight > $(window).width() ) {
1239
- config._collection.css( 'left', hostPosition.left - (listOffsetRight-$(window).width()) );
1240
- }
1388
+ if ( config._collection.parents('body').length ) {
1389
+ this.popover(false, config);
1241
1390
  }
1242
1391
  else {
1243
- // Fix position - centre on screen
1244
- var top = config._collection.height() / 2;
1245
- if ( top > $(window).height() / 2 ) {
1246
- top = $(window).height() / 2;
1247
- }
1248
-
1249
- config._collection.css( 'marginTop', top*-1 );
1392
+ this.popover(config._collection, config);
1250
1393
  }
1251
-
1252
- if ( config.background ) {
1253
- Buttons.background( true, config.backgroundClassName, config.fade );
1254
- }
1255
-
1256
- var close = function () {
1257
- config._collection
1258
- .fadeOut( config.fade, function () {
1259
- config._collection.detach();
1260
- } );
1261
-
1262
- $('div.dt-button-background').off( 'click.dtb-collection' );
1263
- Buttons.background( false, config.backgroundClassName, config.fade );
1264
-
1265
- $('body').off( '.dtb-collection' );
1266
- dt.off( 'buttons-action.b-internal' );
1267
- };
1268
-
1269
- // Need to break the 'thread' for the collection button being
1270
- // activated by a click - it would also trigger this event
1271
- setTimeout( function () {
1272
- // This is bonkers, but if we don't have a click listener on the
1273
- // background element, iOS Safari will ignore the body click
1274
- // listener below. An empty function here is all that is
1275
- // required to make it work...
1276
- $('div.dt-button-background').on( 'click.dtb-collection', function () {} );
1277
-
1278
- $('body')
1279
- .on( 'click.dtb-collection', function (e) {
1280
- // andSelf is deprecated in jQ1.8, but we want 1.7 compat
1281
- var back = $.fn.addBack ? 'addBack' : 'andSelf';
1282
-
1283
- if ( ! $(e.target).parents()[back]().filter( config._collection ).length ) {
1284
- close();
1285
- }
1286
- } )
1287
- .on( 'keyup.dtb-collection', function (e) {
1288
- if ( e.keyCode === 27 ) {
1289
- close();
1290
- }
1291
- } );
1292
-
1293
- if ( config.autoClose ) {
1294
- dt.on( 'buttons-action.b-internal', function () {
1295
- close();
1296
- } );
1297
- }
1298
- }, 10 );
1299
1394
  },
1300
- background: true,
1301
- collectionLayout: '',
1302
- backgroundClassName: 'dt-button-background',
1303
- autoClose: false,
1304
- fade: 400,
1305
1395
  attr: {
1306
1396
  'aria-haspopup': true
1307
1397
  }
1398
+ // Also the popover options, defined in Buttons.popover
1308
1399
  },
1309
1400
  copy: function ( dt, conf ) {
1310
1401
  if ( _dtButtons.copyHtml5 ) {
@@ -1381,7 +1472,7 @@ $.extend( _dtButtons, {
1381
1472
  init: function ( dt, node, conf ) {
1382
1473
  var that = this;
1383
1474
  dt.on( 'length.dt'+conf.namespace, function () {
1384
- that.text( text( dt ) );
1475
+ that.text( conf.text );
1385
1476
  } );
1386
1477
  },
1387
1478
  destroy: function ( dt, node, conf ) {
@@ -1519,8 +1610,15 @@ DataTable.Api.registerPlural( 'buttons().trigger()', 'button().trigger()', funct
1519
1610
  } );
1520
1611
  } );
1521
1612
 
1613
+ // Button resolver to the popover
1614
+ DataTable.Api.register( 'button().popover()', function (content, options) {
1615
+ return this.map( function ( set ) {
1616
+ return set.inst._popover( content, this.button(this[0].node), options );
1617
+ } );
1618
+ } );
1619
+
1522
1620
  // Get the container elements
1523
- DataTable.Api.registerPlural( 'buttons().containers()', 'buttons().container()', function () {
1621
+ DataTable.Api.register( 'buttons().containers()', function () {
1524
1622
  var jq = $();
1525
1623
  var groupSelector = this._groupSelector;
1526
1624
 
@@ -1539,6 +1637,11 @@ DataTable.Api.registerPlural( 'buttons().containers()', 'buttons().container()',
1539
1637
  return jq;
1540
1638
  } );
1541
1639
 
1640
+ DataTable.Api.register( 'buttons().container()', function () {
1641
+ // API level of nesting is `buttons()` so we can zip into the containers method
1642
+ return this.containers().eq(0);
1643
+ } );
1644
+
1542
1645
  // Add a new button
1543
1646
  DataTable.Api.register( 'button().add()', function ( idx, conf ) {
1544
1647
  var ctx = this.context;
@@ -1579,6 +1682,7 @@ DataTable.Api.register( 'buttons.info()', function ( title, message, time ) {
1579
1682
  var that = this;
1580
1683
 
1581
1684
  if ( title === false ) {
1685
+ this.off('destroy.btn-info');
1582
1686
  $('#datatables_buttons_info').fadeOut( function () {
1583
1687
  $(this).remove();
1584
1688
  } );
@@ -1611,6 +1715,10 @@ DataTable.Api.register( 'buttons.info()', function ( title, message, time ) {
1611
1715
  }, time );
1612
1716
  }
1613
1717
 
1718
+ this.on('destroy.btn-info', function () {
1719
+ that.buttons.info(false);
1720
+ });
1721
+
1614
1722
  return this;
1615
1723
  } );
1616
1724
 
@@ -1884,17 +1992,24 @@ $(document).on( 'init.dt plugin-init.dt', function (e, settings) {
1884
1992
  }
1885
1993
  } );
1886
1994
 
1995
+ function _init ( settings ) {
1996
+ var api = new DataTable.Api( settings );
1997
+ var opts = api.init().buttons || DataTable.defaults.buttons;
1998
+
1999
+ return new Buttons( api, opts ).container();
2000
+ }
2001
+
1887
2002
  // DataTables `dom` feature option
1888
2003
  DataTable.ext.feature.push( {
1889
- fnInit: function( settings ) {
1890
- var api = new DataTable.Api( settings );
1891
- var opts = api.init().buttons || DataTable.defaults.buttons;
1892
-
1893
- return new Buttons( api, opts ).container();
1894
- },
2004
+ fnInit: _init,
1895
2005
  cFeature: "B"
1896
2006
  } );
1897
2007
 
2008
+ // DataTables 2 layout feature
2009
+ if ( DataTable.ext.features ) {
2010
+ DataTable.ext.features.register( 'buttons', _init );
2011
+ }
2012
+
1898
2013
 
1899
2014
  return Buttons;
1900
2015
  }));