jquery-datatables 1.10.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +27 -0
  5. data/README.md +118 -0
  6. data/Rakefile +166 -0
  7. data/app/assets/images/datatables/sort_asc.png +0 -0
  8. data/app/assets/images/datatables/sort_asc_disabled.png +0 -0
  9. data/app/assets/images/datatables/sort_both.png +0 -0
  10. data/app/assets/images/datatables/sort_desc.png +0 -0
  11. data/app/assets/images/datatables/sort_desc_disabled.png +0 -0
  12. data/app/assets/javascripts/datatables/dataTables.bootstrap.js +182 -0
  13. data/app/assets/javascripts/datatables/dataTables.bootstrap4.js +184 -0
  14. data/app/assets/javascripts/datatables/dataTables.foundation.js +174 -0
  15. data/app/assets/javascripts/datatables/dataTables.jqueryui.js +164 -0
  16. data/app/assets/javascripts/datatables/dataTables.material.js +191 -0
  17. data/app/assets/javascripts/datatables/dataTables.semanticui.js +208 -0
  18. data/app/assets/javascripts/datatables/dataTables.uikit.js +176 -0
  19. data/app/assets/javascripts/datatables/extensions/AutoFill/autoFill.bootstrap.js +43 -0
  20. data/app/assets/javascripts/datatables/extensions/AutoFill/autoFill.bootstrap4.js +43 -0
  21. data/app/assets/javascripts/datatables/extensions/AutoFill/autoFill.foundation.js +43 -0
  22. data/app/assets/javascripts/datatables/extensions/AutoFill/autoFill.jqueryui.js +43 -0
  23. data/app/assets/javascripts/datatables/extensions/AutoFill/autoFill.semanticui.js +43 -0
  24. data/app/assets/javascripts/datatables/extensions/AutoFill/dataTables.autoFill.js +1036 -0
  25. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.bootstrap.js +68 -0
  26. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.bootstrap4.js +60 -0
  27. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.colVis.js +199 -0
  28. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.flash.js +1325 -0
  29. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.foundation.js +85 -0
  30. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.html5.js +1322 -0
  31. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.jqueryui.js +62 -0
  32. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.print.js +172 -0
  33. data/app/assets/javascripts/datatables/extensions/Buttons/buttons.semanticui.js +57 -0
  34. data/app/assets/javascripts/datatables/extensions/Buttons/dataTables.buttons.js +1634 -0
  35. data/app/assets/javascripts/datatables/extensions/ColReorder/dataTables.colReorder.js +1335 -0
  36. data/app/assets/javascripts/datatables/extensions/FixedColumns/dataTables.fixedColumns.js +1623 -0
  37. data/app/assets/javascripts/datatables/extensions/FixedHeader/dataTables.fixedHeader.js +672 -0
  38. data/app/assets/javascripts/datatables/extensions/KeyTable/dataTables.keyTable.js +883 -0
  39. data/app/assets/javascripts/datatables/extensions/Responsive/dataTables.responsive.js +1232 -0
  40. data/app/assets/javascripts/datatables/extensions/Responsive/responsive.bootstrap.js +81 -0
  41. data/app/assets/javascripts/datatables/extensions/Responsive/responsive.bootstrap4.js +81 -0
  42. data/app/assets/javascripts/datatables/extensions/Responsive/responsive.foundation.js +62 -0
  43. data/app/assets/javascripts/datatables/extensions/Responsive/responsive.jqueryui.js +63 -0
  44. data/app/assets/javascripts/datatables/extensions/Responsive/responsive.semanticui.js +77 -0
  45. data/app/assets/javascripts/datatables/extensions/RowReorder/dataTables.rowReorder.js +709 -0
  46. data/app/assets/javascripts/datatables/extensions/Scroller/dataTables.scroller.js +1349 -0
  47. data/app/assets/javascripts/datatables/extensions/Select/dataTables.select.js +1109 -0
  48. data/app/assets/javascripts/datatables/jquery.dataTables.js +15278 -0
  49. data/app/assets/media/swf/flashExport.swf +0 -0
  50. data/app/assets/stylesheets/datatables/dataTables.bootstrap.css +185 -0
  51. data/app/assets/stylesheets/datatables/dataTables.bootstrap4.css +193 -0
  52. data/app/assets/stylesheets/datatables/dataTables.foundation.css +116 -0
  53. data/app/assets/stylesheets/datatables/dataTables.jqueryui.css +481 -0
  54. data/app/assets/stylesheets/datatables/dataTables.material.css +87 -0
  55. data/app/assets/stylesheets/datatables/dataTables.semanticui.css +103 -0
  56. data/app/assets/stylesheets/datatables/dataTables.uikit.css +146 -0
  57. data/app/assets/stylesheets/datatables/extensions/AutoFill/autoFill.bootstrap.css +81 -0
  58. data/app/assets/stylesheets/datatables/extensions/AutoFill/autoFill.bootstrap4.css +81 -0
  59. data/app/assets/stylesheets/datatables/extensions/AutoFill/autoFill.dataTables.css +92 -0
  60. data/app/assets/stylesheets/datatables/extensions/AutoFill/autoFill.foundation.css +85 -0
  61. data/app/assets/stylesheets/datatables/extensions/AutoFill/autoFill.jqueryui.css +85 -0
  62. data/app/assets/stylesheets/datatables/extensions/AutoFill/autoFill.semanticui.css +81 -0
  63. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.bootstrap.css +102 -0
  64. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.bootstrap4.css +163 -0
  65. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.dataTables.css +298 -0
  66. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.foundation.css +129 -0
  67. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.jqueryui.css +162 -0
  68. data/app/assets/stylesheets/datatables/extensions/Buttons/buttons.semanticui.css +114 -0
  69. data/app/assets/stylesheets/datatables/extensions/Buttons/common.scss +27 -0
  70. data/app/assets/stylesheets/datatables/extensions/Buttons/mixins.scss +89 -0
  71. data/app/assets/stylesheets/datatables/extensions/ColReorder/colReorder.bootstrap.css +11 -0
  72. data/app/assets/stylesheets/datatables/extensions/ColReorder/colReorder.bootstrap4.css +11 -0
  73. data/app/assets/stylesheets/datatables/extensions/ColReorder/colReorder.dataTables.css +11 -0
  74. data/app/assets/stylesheets/datatables/extensions/ColReorder/colReorder.foundation.css +11 -0
  75. data/app/assets/stylesheets/datatables/extensions/ColReorder/colReorder.jqueryui.css +11 -0
  76. data/app/assets/stylesheets/datatables/extensions/ColReorder/colReorder.semanticui.css +11 -0
  77. data/app/assets/stylesheets/datatables/extensions/FixedColumns/fixedColumns.bootstrap.css +44 -0
  78. data/app/assets/stylesheets/datatables/extensions/FixedColumns/fixedColumns.bootstrap4.css +44 -0
  79. data/app/assets/stylesheets/datatables/extensions/FixedColumns/fixedColumns.dataTables.css +18 -0
  80. data/app/assets/stylesheets/datatables/extensions/FixedColumns/fixedColumns.foundation.css +27 -0
  81. data/app/assets/stylesheets/datatables/extensions/FixedColumns/fixedColumns.jqueryui.css +8 -0
  82. data/app/assets/stylesheets/datatables/extensions/FixedColumns/fixedColumns.semanticui.css +16 -0
  83. data/app/assets/stylesheets/datatables/extensions/FixedHeader/fixedHeader.bootstrap.css +20 -0
  84. data/app/assets/stylesheets/datatables/extensions/FixedHeader/fixedHeader.bootstrap4.css +20 -0
  85. data/app/assets/stylesheets/datatables/extensions/FixedHeader/fixedHeader.dataTables.css +19 -0
  86. data/app/assets/stylesheets/datatables/extensions/FixedHeader/fixedHeader.foundation.css +20 -0
  87. data/app/assets/stylesheets/datatables/extensions/FixedHeader/fixedHeader.jqueryui.css +15 -0
  88. data/app/assets/stylesheets/datatables/extensions/FixedHeader/fixedHeader.semanticui.css +14 -0
  89. data/app/assets/stylesheets/datatables/extensions/KeyTable/keyTable.bootstrap.css +5 -0
  90. data/app/assets/stylesheets/datatables/extensions/KeyTable/keyTable.bootstrap4.css +5 -0
  91. data/app/assets/stylesheets/datatables/extensions/KeyTable/keyTable.dataTables.css +5 -0
  92. data/app/assets/stylesheets/datatables/extensions/KeyTable/keyTable.foundation.css +5 -0
  93. data/app/assets/stylesheets/datatables/extensions/KeyTable/keyTable.jqueryui.css +5 -0
  94. data/app/assets/stylesheets/datatables/extensions/KeyTable/keyTable.semanticui.css +5 -0
  95. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.bootstrap.css +181 -0
  96. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.bootstrap4.css +181 -0
  97. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.dataTables.css +178 -0
  98. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.foundation.css +181 -0
  99. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.jqueryui.css +178 -0
  100. data/app/assets/stylesheets/datatables/extensions/Responsive/responsive.semanticui.css +181 -0
  101. data/app/assets/stylesheets/datatables/extensions/RowReorder/rowReorder.bootstrap.css +22 -0
  102. data/app/assets/stylesheets/datatables/extensions/RowReorder/rowReorder.bootstrap4.css +22 -0
  103. data/app/assets/stylesheets/datatables/extensions/RowReorder/rowReorder.dataTables.css +22 -0
  104. data/app/assets/stylesheets/datatables/extensions/RowReorder/rowReorder.foundation.css +22 -0
  105. data/app/assets/stylesheets/datatables/extensions/RowReorder/rowReorder.jqueryui.css +22 -0
  106. data/app/assets/stylesheets/datatables/extensions/RowReorder/rowReorder.semanticui.css +22 -0
  107. data/app/assets/stylesheets/datatables/extensions/RowReorder/semanticui.scss +5 -0
  108. data/app/assets/stylesheets/datatables/extensions/Scroller/scroller.bootstrap.css +24 -0
  109. data/app/assets/stylesheets/datatables/extensions/Scroller/scroller.bootstrap4.css +24 -0
  110. data/app/assets/stylesheets/datatables/extensions/Scroller/scroller.dataTables.css +20 -0
  111. data/app/assets/stylesheets/datatables/extensions/Scroller/scroller.foundation.css +17 -0
  112. data/app/assets/stylesheets/datatables/extensions/Scroller/scroller.jqueryui.css +20 -0
  113. data/app/assets/stylesheets/datatables/extensions/Scroller/scroller.semanticui.css +20 -0
  114. data/app/assets/stylesheets/datatables/extensions/Select/select.bootstrap.css +110 -0
  115. data/app/assets/stylesheets/datatables/extensions/Select/select.bootstrap4.css +110 -0
  116. data/app/assets/stylesheets/datatables/extensions/Select/select.dataTables.css +100 -0
  117. data/app/assets/stylesheets/datatables/extensions/Select/select.foundation.css +112 -0
  118. data/app/assets/stylesheets/datatables/extensions/Select/select.jqueryui.css +100 -0
  119. data/app/assets/stylesheets/datatables/extensions/Select/select.semanticui.css +105 -0
  120. data/app/assets/stylesheets/datatables/jquery.dataTables.css +452 -0
  121. data/app/assets/stylesheets/datatables/jquery.dataTables_themeroller.css +416 -0
  122. data/jquery-datatables.gemspec +27 -0
  123. data/lib/generators/jquery/datatables/install_generator.rb +63 -0
  124. data/lib/generators/jquery/datatables/templates/bootstrap.css.tt +15 -0
  125. data/lib/generators/jquery/datatables/templates/bootstrap.js.tt +22 -0
  126. data/lib/generators/jquery/datatables/templates/bootstrap4.css.tt +15 -0
  127. data/lib/generators/jquery/datatables/templates/bootstrap4.js.tt +22 -0
  128. data/lib/generators/jquery/datatables/templates/foundation.css.tt +15 -0
  129. data/lib/generators/jquery/datatables/templates/foundation.js.tt +24 -0
  130. data/lib/generators/jquery/datatables/templates/jqueryui.css.tt +15 -0
  131. data/lib/generators/jquery/datatables/templates/jqueryui.js.tt +18 -0
  132. data/lib/generators/jquery/datatables/templates/material.css.tt +15 -0
  133. data/lib/generators/jquery/datatables/templates/material.js.tt +19 -0
  134. data/lib/generators/jquery/datatables/templates/regular.css.tt +15 -0
  135. data/lib/generators/jquery/datatables/templates/regular.js.tt +18 -0
  136. data/lib/generators/jquery/datatables/templates/semanticui.css.tt +16 -0
  137. data/lib/generators/jquery/datatables/templates/semanticui.js.tt +22 -0
  138. data/lib/generators/jquery/datatables/templates/uikit.css.tt +15 -0
  139. data/lib/generators/jquery/datatables/templates/uikit.js.tt +19 -0
  140. data/lib/jquery-datatables.rb +26 -0
  141. data/lib/jquery-datatables/engine.rb +11 -0
  142. data/lib/jquery-datatables/version.rb +6 -0
  143. metadata +269 -0
@@ -0,0 +1,62 @@
1
+ /*! jQuery UI integration for DataTables' Buttons
2
+ * ©2016 SpryMedia Ltd - datatables.net/license
3
+ */
4
+
5
+ (function( factory ){
6
+ if ( typeof define === 'function' && define.amd ) {
7
+ // AMD
8
+ define( ['jquery', 'datatables.net-jqui', 'datatables.net-buttons'], function ( $ ) {
9
+ return factory( $, window, document );
10
+ } );
11
+ }
12
+ else if ( typeof exports === 'object' ) {
13
+ // CommonJS
14
+ module.exports = function (root, $) {
15
+ if ( ! root ) {
16
+ root = window;
17
+ }
18
+
19
+ if ( ! $ || ! $.fn.dataTable ) {
20
+ $ = require('datatables.net-jqui')(root, $).$;
21
+ }
22
+
23
+ if ( ! $.fn.dataTable.Buttons ) {
24
+ require('datatables.net-buttons')(root, $);
25
+ }
26
+
27
+ return factory( $, root, root.document );
28
+ };
29
+ }
30
+ else {
31
+ // Browser
32
+ factory( jQuery, window, document );
33
+ }
34
+ }(function( $, window, document, undefined ) {
35
+ 'use strict';
36
+ var DataTable = $.fn.dataTable;
37
+
38
+
39
+ $.extend( true, DataTable.Buttons.defaults, {
40
+ dom: {
41
+ container: {
42
+ className: 'dt-buttons ui-buttonset'
43
+ },
44
+ button: {
45
+ className: 'dt-button ui-button ui-state-default ui-button-text-only',
46
+ disabled: 'ui-state-disabled',
47
+ active: 'ui-state-active'
48
+ },
49
+ buttonLiner: {
50
+ tag: 'span',
51
+ className: 'ui-button-text'
52
+ }
53
+ }
54
+ } );
55
+
56
+ DataTable.ext.buttons.collection.text = function ( dt ) {
57
+ return dt.i18n('buttons.collection', 'Collection <span class="ui-button-icon-primary ui-icon ui-icon-triangle-1-s"/>');
58
+ };
59
+
60
+
61
+ return DataTable.Buttons;
62
+ }));
@@ -0,0 +1,172 @@
1
+ /*!
2
+ * Print button for Buttons and DataTables.
3
+ * 2016 SpryMedia Ltd - datatables.net/license
4
+ */
5
+
6
+ (function( factory ){
7
+ if ( typeof define === 'function' && define.amd ) {
8
+ // AMD
9
+ define( ['jquery', 'datatables.net', 'datatables.net-buttons'], function ( $ ) {
10
+ return factory( $, window, document );
11
+ } );
12
+ }
13
+ else if ( typeof exports === 'object' ) {
14
+ // CommonJS
15
+ module.exports = function (root, $) {
16
+ if ( ! root ) {
17
+ root = window;
18
+ }
19
+
20
+ if ( ! $ || ! $.fn.dataTable ) {
21
+ $ = require('datatables.net')(root, $).$;
22
+ }
23
+
24
+ if ( ! $.fn.dataTable.Buttons ) {
25
+ require('datatables.net-buttons')(root, $);
26
+ }
27
+
28
+ return factory( $, root, root.document );
29
+ };
30
+ }
31
+ else {
32
+ // Browser
33
+ factory( jQuery, window, document );
34
+ }
35
+ }(function( $, window, document, undefined ) {
36
+ 'use strict';
37
+ var DataTable = $.fn.dataTable;
38
+
39
+
40
+ var _link = document.createElement( 'a' );
41
+
42
+ /**
43
+ * Convert a `link` tag's URL from a relative to an absolute address so it will
44
+ * work correctly in the popup window which has no base URL.
45
+ *
46
+ * @param {node} el Element to convert
47
+ */
48
+ var _relToAbs = function( el ) {
49
+ var url;
50
+ var clone = $(el).clone()[0];
51
+ var linkHost;
52
+
53
+ if ( clone.nodeName.toLowerCase() === 'link' ) {
54
+ _link.href = clone.href;
55
+ linkHost = _link.host;
56
+
57
+ // IE doesn't have a trailing slash on the host
58
+ // Chrome has it on the pathname
59
+ if ( linkHost.indexOf('/') === -1 && _link.pathname.indexOf('/') !== 0) {
60
+ linkHost += '/';
61
+ }
62
+
63
+ clone.href = _link.protocol+"//"+linkHost+_link.pathname+_link.search;
64
+ }
65
+
66
+ return clone.outerHTML;
67
+ };
68
+
69
+
70
+ DataTable.ext.buttons.print = {
71
+ className: 'buttons-print',
72
+
73
+ text: function ( dt ) {
74
+ return dt.i18n( 'buttons.print', 'Print' );
75
+ },
76
+
77
+ action: function ( e, dt, button, config ) {
78
+ var data = dt.buttons.exportData( config.exportOptions );
79
+ var addRow = function ( d, tag ) {
80
+ var str = '<tr>';
81
+
82
+ for ( var i=0, ien=d.length ; i<ien ; i++ ) {
83
+ str += '<'+tag+'>'+d[i]+'</'+tag+'>';
84
+ }
85
+
86
+ return str + '</tr>';
87
+ };
88
+
89
+ // Construct a table for printing
90
+ var html = '<table class="'+dt.table().node().className+'">';
91
+
92
+ if ( config.header ) {
93
+ html += '<thead>'+ addRow( data.header, 'th' ) +'</thead>';
94
+ }
95
+
96
+ html += '<tbody>';
97
+ for ( var i=0, ien=data.body.length ; i<ien ; i++ ) {
98
+ html += addRow( data.body[i], 'td' );
99
+ }
100
+ html += '</tbody>';
101
+
102
+ if ( config.footer && data.footer ) {
103
+ html += '<tfoot>'+ addRow( data.footer, 'th' ) +'</tfoot>';
104
+ }
105
+
106
+ // Open a new window for the printable table
107
+ var win = window.open( '', '' );
108
+ var title = config.title;
109
+
110
+ if ( typeof title === 'function' ) {
111
+ title = title();
112
+ }
113
+
114
+ if ( title.indexOf( '*' ) !== -1 ) {
115
+ title= title.replace( '*', $('title').text() );
116
+ }
117
+
118
+ win.document.close();
119
+
120
+ // Inject the title and also a copy of the style and link tags from this
121
+ // document so the table can retain its base styling. Note that we have
122
+ // to use string manipulation as IE won't allow elements to be created
123
+ // in the host document and then appended to the new window.
124
+ var head = '<title>'+title+'</title>';
125
+ $('style, link').each( function () {
126
+ head += _relToAbs( this );
127
+ } );
128
+
129
+ //$(win.document.head).html( head );
130
+ win.document.head.innerHTML = head; // Work around for Edge
131
+
132
+ // Inject the table and other surrounding information
133
+ win.document.body.innerHTML =
134
+ '<h1>'+title+'</h1>'+
135
+ '<div>'+config.message+'</div>'+
136
+ html;
137
+ // $(win.document.body).html(
138
+ // '<h1>'+title+'</h1>'+
139
+ // '<div>'+config.message+'</div>'+
140
+ // html
141
+ // );
142
+
143
+ if ( config.customize ) {
144
+ config.customize( win );
145
+ }
146
+
147
+ setTimeout( function () {
148
+ if ( config.autoPrint ) {
149
+ win.print(); // blocking - so close will not
150
+ win.close(); // execute until this is done
151
+ }
152
+ }, 250 );
153
+ },
154
+
155
+ title: '*',
156
+
157
+ message: '',
158
+
159
+ exportOptions: {},
160
+
161
+ header: true,
162
+
163
+ footer: false,
164
+
165
+ autoPrint: true,
166
+
167
+ customize: null
168
+ };
169
+
170
+
171
+ return DataTable.Buttons;
172
+ }));
@@ -0,0 +1,57 @@
1
+ /*! Bootstrap integration for DataTables' Buttons
2
+ * ©2016 SpryMedia Ltd - datatables.net/license
3
+ */
4
+
5
+ (function( factory ){
6
+ if ( typeof define === 'function' && define.amd ) {
7
+ // AMD
8
+ define( ['jquery', 'datatables.net-se', 'datatables.net-buttons'], function ( $ ) {
9
+ return factory( $, window, document );
10
+ } );
11
+ }
12
+ else if ( typeof exports === 'object' ) {
13
+ // CommonJS
14
+ module.exports = function (root, $) {
15
+ if ( ! root ) {
16
+ root = window;
17
+ }
18
+
19
+ if ( ! $ || ! $.fn.dataTable ) {
20
+ $ = require('datatables.net-se')(root, $).$;
21
+ }
22
+
23
+ if ( ! $.fn.dataTable.Buttons ) {
24
+ require('datatables.net-buttons')(root, $);
25
+ }
26
+
27
+ return factory( $, root, root.document );
28
+ };
29
+ }
30
+ else {
31
+ // Browser
32
+ factory( jQuery, window, document );
33
+ }
34
+ }(function( $, window, document, undefined ) {
35
+ 'use strict';
36
+ var DataTable = $.fn.dataTable;
37
+
38
+
39
+ $.extend( true, DataTable.Buttons.defaults, {
40
+ dom: {
41
+ container: {
42
+ className: 'dt-buttons ui basic buttons'
43
+ },
44
+ button: {
45
+ tag: 'button',
46
+ className: 'ui button'
47
+ },
48
+ collection: {
49
+ tag: 'div',
50
+ className: 'dt-button-collection ui basic vertical buttons'
51
+ }
52
+ }
53
+ } );
54
+
55
+
56
+ return DataTable.Buttons;
57
+ }));
@@ -0,0 +1,1634 @@
1
+ /*! Buttons for DataTables 1.2.0
2
+ * ©2016 SpryMedia Ltd - datatables.net/license
3
+ */
4
+
5
+ (function( factory ){
6
+ if ( typeof define === 'function' && define.amd ) {
7
+ // AMD
8
+ define( ['jquery', 'datatables.net'], function ( $ ) {
9
+ return factory( $, window, document );
10
+ } );
11
+ }
12
+ else if ( typeof exports === 'object' ) {
13
+ // CommonJS
14
+ module.exports = function (root, $) {
15
+ if ( ! root ) {
16
+ root = window;
17
+ }
18
+
19
+ if ( ! $ || ! $.fn.dataTable ) {
20
+ $ = require('datatables.net')(root, $).$;
21
+ }
22
+
23
+ return factory( $, root, root.document );
24
+ };
25
+ }
26
+ else {
27
+ // Browser
28
+ factory( jQuery, window, document );
29
+ }
30
+ }(function( $, window, document, undefined ) {
31
+ 'use strict';
32
+ var DataTable = $.fn.dataTable;
33
+
34
+
35
+ // Used for namespacing events added to the document by each instance, so they
36
+ // can be removed on destroy
37
+ var _instCounter = 0;
38
+
39
+ // Button namespacing counter for namespacing events on individual buttons
40
+ var _buttonCounter = 0;
41
+
42
+ var _dtButtons = DataTable.ext.buttons;
43
+
44
+ /**
45
+ * [Buttons description]
46
+ * @param {[type]}
47
+ * @param {[type]}
48
+ */
49
+ var Buttons = function( dt, config )
50
+ {
51
+ // Allow a boolean true for defaults
52
+ if ( config === true ) {
53
+ config = {};
54
+ }
55
+
56
+ // For easy configuration of buttons an array can be given
57
+ if ( $.isArray( config ) ) {
58
+ config = { buttons: config };
59
+ }
60
+
61
+ this.c = $.extend( true, {}, Buttons.defaults, config );
62
+
63
+ // Don't want a deep copy for the buttons
64
+ if ( config.buttons ) {
65
+ this.c.buttons = config.buttons;
66
+ }
67
+
68
+ this.s = {
69
+ dt: new DataTable.Api( dt ),
70
+ buttons: [],
71
+ listenKeys: '',
72
+ namespace: 'dtb'+(_instCounter++)
73
+ };
74
+
75
+ this.dom = {
76
+ container: $('<'+this.c.dom.container.tag+'/>')
77
+ .addClass( this.c.dom.container.className )
78
+ };
79
+
80
+ this._constructor();
81
+ };
82
+
83
+
84
+ $.extend( Buttons.prototype, {
85
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
86
+ * Public methods
87
+ */
88
+
89
+ /**
90
+ * Get the action of a button
91
+ * @param {int|string} Button index
92
+ * @return {function}
93
+ *//**
94
+ * Set the action of a button
95
+ * @param {node} node Button element
96
+ * @param {function} action Function to set
97
+ * @return {Buttons} Self for chaining
98
+ */
99
+ action: function ( node, action )
100
+ {
101
+ var button = this._nodeToButton( node );
102
+
103
+ if ( action === undefined ) {
104
+ return button.conf.action;
105
+ }
106
+
107
+ button.conf.action = action;
108
+
109
+ return this;
110
+ },
111
+
112
+ /**
113
+ * Add an active class to the button to make to look active or get current
114
+ * active state.
115
+ * @param {node} node Button element
116
+ * @param {boolean} [flag] Enable / disable flag
117
+ * @return {Buttons} Self for chaining or boolean for getter
118
+ */
119
+ active: function ( node, flag ) {
120
+ var button = this._nodeToButton( node );
121
+ var klass = this.c.dom.button.active;
122
+ var jqNode = $(button.node);
123
+
124
+ if ( flag === undefined ) {
125
+ return jqNode.hasClass( klass );
126
+ }
127
+
128
+ jqNode.toggleClass( klass, flag === undefined ? true : flag );
129
+
130
+ return this;
131
+ },
132
+
133
+ /**
134
+ * Add a new button
135
+ * @param {object} config Button configuration object, base string name or function
136
+ * @param {int|string} [idx] Button index for where to insert the button
137
+ * @return {Buttons} Self for chaining
138
+ */
139
+ add: function ( config, idx )
140
+ {
141
+ var buttons = this.s.buttons;
142
+
143
+ if ( typeof idx === 'string' ) {
144
+ var split = idx.split('-');
145
+ var base = this.s;
146
+
147
+ for ( var i=0, ien=split.length-1 ; i<ien ; i++ ) {
148
+ base = base.buttons[ split[i]*1 ];
149
+ }
150
+
151
+ buttons = base.buttons;
152
+ idx = split[ split.length-1 ]*1;
153
+ }
154
+
155
+ this._expandButton( buttons, config, false, idx );
156
+ this._draw();
157
+
158
+ return this;
159
+ },
160
+
161
+ /**
162
+ * Get the container node for the buttons
163
+ * @return {jQuery} Buttons node
164
+ */
165
+ container: function ()
166
+ {
167
+ return this.dom.container;
168
+ },
169
+
170
+ /**
171
+ * Disable a button
172
+ * @param {node} node Button node
173
+ * @return {Buttons} Self for chaining
174
+ */
175
+ disable: function ( node ) {
176
+ var button = this._nodeToButton( node );
177
+
178
+ $(button.node).addClass( this.c.dom.button.disabled );
179
+
180
+ return this;
181
+ },
182
+
183
+ /**
184
+ * Destroy the instance, cleaning up event handlers and removing DOM
185
+ * elements
186
+ * @return {Buttons} Self for chaining
187
+ */
188
+ destroy: function ()
189
+ {
190
+ // Key event listener
191
+ $('body').off( 'keyup.'+this.s.namespace );
192
+
193
+ // Individual button destroy (so they can remove their own events if
194
+ // needed
195
+ var buttons = this.s.buttons;
196
+ var i, ien;
197
+
198
+ for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
199
+ this.remove( buttons[i].node );
200
+ }
201
+
202
+ // Container
203
+ this.dom.container.remove();
204
+
205
+ // Remove from the settings object collection
206
+ var buttonInsts = this.s.dt.settings()[0];
207
+
208
+ for ( i=0, ien=buttonInsts.length ; i<ien ; i++ ) {
209
+ if ( buttonInsts.inst === this ) {
210
+ buttonInsts.splice( i, 1 );
211
+ break;
212
+ }
213
+ }
214
+
215
+ return this;
216
+ },
217
+
218
+ /**
219
+ * Enable / disable a button
220
+ * @param {node} node Button node
221
+ * @param {boolean} [flag=true] Enable / disable flag
222
+ * @return {Buttons} Self for chaining
223
+ */
224
+ enable: function ( node, flag )
225
+ {
226
+ if ( flag === false ) {
227
+ return this.disable( node );
228
+ }
229
+
230
+ var button = this._nodeToButton( node );
231
+ $(button.node).removeClass( this.c.dom.button.disabled );
232
+
233
+ return this;
234
+ },
235
+
236
+ /**
237
+ * Get the instance name for the button set selector
238
+ * @return {string} Instance name
239
+ */
240
+ name: function ()
241
+ {
242
+ return this.c.name;
243
+ },
244
+
245
+ /**
246
+ * Get a button's node
247
+ * @param {node} node Button node
248
+ * @return {jQuery} Button element
249
+ */
250
+ node: function ( node )
251
+ {
252
+ var button = this._nodeToButton( node );
253
+ return $(button.node);
254
+ },
255
+
256
+ /**
257
+ * Remove a button.
258
+ * @param {node} node Button node
259
+ * @return {Buttons} Self for chaining
260
+ */
261
+ remove: function ( node )
262
+ {
263
+ var button = this._nodeToButton( node );
264
+ var host = this._nodeToHost( node );
265
+ var dt = this.s.dt;
266
+
267
+ // Remove any child buttons first
268
+ if ( button.buttons.length ) {
269
+ for ( var i=button.buttons.length-1 ; i>=0 ; i-- ) {
270
+ this.remove( button.buttons[i].node );
271
+ }
272
+ }
273
+
274
+ // Allow the button to remove event handlers, etc
275
+ if ( button.conf.destroy ) {
276
+ button.conf.destroy.call( dt.button(node), dt, $(node), button.conf );
277
+ }
278
+
279
+ this._removeKey( button.conf );
280
+
281
+ $(button.node).remove();
282
+
283
+ var idx = $.inArray( button, host );
284
+ host.splice( idx, 1 );
285
+
286
+ return this;
287
+ },
288
+
289
+ /**
290
+ * Get the text for a button
291
+ * @param {int|string} node Button index
292
+ * @return {string} Button text
293
+ *//**
294
+ * Set the text for a button
295
+ * @param {int|string|function} node Button index
296
+ * @param {string} label Text
297
+ * @return {Buttons} Self for chaining
298
+ */
299
+ text: function ( node, label )
300
+ {
301
+ var button = this._nodeToButton( node );
302
+ var buttonLiner = this.c.dom.collection.buttonLiner;
303
+ var linerTag = button.inCollection && buttonLiner && buttonLiner.tag ?
304
+ buttonLiner.tag :
305
+ this.c.dom.buttonLiner.tag;
306
+ var dt = this.s.dt;
307
+ var jqNode = $(button.node);
308
+ var text = function ( opt ) {
309
+ return typeof opt === 'function' ?
310
+ opt( dt, jqNode, button.conf ) :
311
+ opt;
312
+ };
313
+
314
+ if ( label === undefined ) {
315
+ return text( button.conf.text );
316
+ }
317
+
318
+ button.conf.text = label;
319
+
320
+ if ( linerTag ) {
321
+ jqNode.children( linerTag ).html( text(label) );
322
+ }
323
+ else {
324
+ jqNode.html( text(label) );
325
+ }
326
+
327
+ return this;
328
+ },
329
+
330
+
331
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
332
+ * Constructor
333
+ */
334
+
335
+ /**
336
+ * Buttons constructor
337
+ * @private
338
+ */
339
+ _constructor: function ()
340
+ {
341
+ var that = this;
342
+ var dt = this.s.dt;
343
+ var dtSettings = dt.settings()[0];
344
+ var buttons = this.c.buttons;
345
+
346
+ if ( ! dtSettings._buttons ) {
347
+ dtSettings._buttons = [];
348
+ }
349
+
350
+ dtSettings._buttons.push( {
351
+ inst: this,
352
+ name: this.c.name
353
+ } );
354
+
355
+ for ( var i=0, ien=buttons.length ; i<ien ; i++ ) {
356
+ this.add( buttons[i] );
357
+ }
358
+
359
+ dt.on( 'destroy', function () {
360
+ that.destroy();
361
+ } );
362
+
363
+ // Global key event binding to listen for button keys
364
+ $('body').on( 'keyup.'+this.s.namespace, function ( e ) {
365
+ if ( ! document.activeElement || document.activeElement === document.body ) {
366
+ // SUse a string of characters for fast lookup of if we need to
367
+ // handle this
368
+ var character = String.fromCharCode(e.keyCode).toLowerCase();
369
+
370
+ if ( that.s.listenKeys.toLowerCase().indexOf( character ) !== -1 ) {
371
+ that._keypress( character, e );
372
+ }
373
+ }
374
+ } );
375
+ },
376
+
377
+
378
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
379
+ * Private methods
380
+ */
381
+
382
+ /**
383
+ * Add a new button to the key press listener
384
+ * @param {object} conf Resolved button configuration object
385
+ * @private
386
+ */
387
+ _addKey: function ( conf )
388
+ {
389
+ if ( conf.key ) {
390
+ this.s.listenKeys += $.isPlainObject( conf.key ) ?
391
+ conf.key.key :
392
+ conf.key;
393
+ }
394
+ },
395
+
396
+ /**
397
+ * Insert the buttons into the container. Call without parameters!
398
+ * @param {node} [container] Recursive only - Insert point
399
+ * @param {array} [buttons] Recursive only - Buttons array
400
+ * @private
401
+ */
402
+ _draw: function ( container, buttons )
403
+ {
404
+ if ( ! container ) {
405
+ container = this.dom.container;
406
+ buttons = this.s.buttons;
407
+ }
408
+
409
+ container.children().detach();
410
+
411
+ for ( var i=0, ien=buttons.length ; i<ien ; i++ ) {
412
+ container.append( buttons[i].inserter );
413
+
414
+ if ( buttons[i].buttons && buttons[i].buttons.length ) {
415
+ this._draw( buttons[i].collection, buttons[i].buttons );
416
+ }
417
+ }
418
+ },
419
+
420
+ /**
421
+ * Create buttons from an array of buttons
422
+ * @param {array} attachTo Buttons array to attach to
423
+ * @param {object} button Button definition
424
+ * @param {boolean} inCollection true if the button is in a collection
425
+ * @private
426
+ */
427
+ _expandButton: function ( attachTo, button, inCollection, attachPoint )
428
+ {
429
+ var dt = this.s.dt;
430
+ var buttonCounter = 0;
431
+ var buttons = ! $.isArray( button ) ?
432
+ [ button ] :
433
+ button;
434
+
435
+ for ( var i=0, ien=buttons.length ; i<ien ; i++ ) {
436
+ var conf = this._resolveExtends( buttons[i] );
437
+
438
+ if ( ! conf ) {
439
+ continue;
440
+ }
441
+
442
+ // If the configuration is an array, then expand the buttons at this
443
+ // point
444
+ if ( $.isArray( conf ) ) {
445
+ this._expandButton( attachTo, conf, inCollection, attachPoint );
446
+ continue;
447
+ }
448
+
449
+ var built = this._buildButton( conf, inCollection );
450
+ if ( ! built ) {
451
+ continue;
452
+ }
453
+
454
+ if ( attachPoint !== undefined ) {
455
+ attachTo.splice( attachPoint, 0, built );
456
+ attachPoint++;
457
+ }
458
+ else {
459
+ attachTo.push( built );
460
+ }
461
+
462
+ if ( built.conf.buttons ) {
463
+ var collectionDom = this.c.dom.collection;
464
+ built.collection = $('<'+collectionDom.tag+'/>')
465
+ .addClass( collectionDom.className );
466
+ built.conf._collection = built.collection;
467
+
468
+ this._expandButton( built.buttons, built.conf.buttons, true, attachPoint );
469
+ }
470
+
471
+ // init call is made here, rather than buildButton as it needs to
472
+ // be selectable, and for that it needs to be in the buttons array
473
+ if ( conf.init ) {
474
+ conf.init.call( dt.button( built.node ), dt, $(built.node), conf );
475
+ }
476
+
477
+ buttonCounter++;
478
+ }
479
+ },
480
+
481
+ /**
482
+ * Create an individual button
483
+ * @param {object} config Resolved button configuration
484
+ * @param {boolean} inCollection `true` if a collection button
485
+ * @return {jQuery} Created button node (jQuery)
486
+ * @private
487
+ */
488
+ _buildButton: function ( config, inCollection )
489
+ {
490
+ var buttonDom = this.c.dom.button;
491
+ var linerDom = this.c.dom.buttonLiner;
492
+ var collectionDom = this.c.dom.collection;
493
+ var dt = this.s.dt;
494
+ var text = function ( opt ) {
495
+ return typeof opt === 'function' ?
496
+ opt( dt, button, config ) :
497
+ opt;
498
+ };
499
+
500
+ if ( inCollection && collectionDom.button ) {
501
+ buttonDom = collectionDom.button;
502
+ }
503
+
504
+ if ( inCollection && collectionDom.buttonLiner ) {
505
+ linerDom = collectionDom.buttonLiner;
506
+ }
507
+
508
+ // Make sure that the button is available based on whatever requirements
509
+ // it has. For example, Flash buttons require Flash
510
+ if ( config.available && ! config.available( dt, config ) ) {
511
+ return false;
512
+ }
513
+
514
+ var action = function ( e, dt, button, config ) {
515
+ config.action.call( dt.button( button ), e, dt, button, config );
516
+
517
+ $(dt.table().node()).triggerHandler( 'buttons-action.dt', [
518
+ dt.button( button ), dt, button, config
519
+ ] );
520
+ };
521
+
522
+ var button = $('<'+buttonDom.tag+'/>')
523
+ .addClass( buttonDom.className )
524
+ .attr( 'tabindex', this.s.dt.settings()[0].iTabIndex )
525
+ .attr( 'aria-controls', this.s.dt.table().node().id )
526
+ .on( 'click.dtb', function (e) {
527
+ e.preventDefault();
528
+
529
+ if ( ! button.hasClass( buttonDom.disabled ) && config.action ) {
530
+ action( e, dt, button, config );
531
+ }
532
+
533
+ button.blur();
534
+ } )
535
+ .on( 'keyup.dtb', function (e) {
536
+ if ( e.keyCode === 13 ) {
537
+ if ( ! button.hasClass( buttonDom.disabled ) && config.action ) {
538
+ action( e, dt, button, config );
539
+ }
540
+ }
541
+ } );
542
+
543
+ // Make `a` tags act like a link
544
+ if ( buttonDom.tag.toLowerCase() === 'a' ) {
545
+ button.attr( 'href', '#' );
546
+ }
547
+
548
+ if ( linerDom.tag ) {
549
+ var liner = $('<'+linerDom.tag+'/>')
550
+ .html( text( config.text ) )
551
+ .addClass( linerDom.className );
552
+
553
+ if ( linerDom.tag.toLowerCase() === 'a' ) {
554
+ liner.attr( 'href', '#' );
555
+ }
556
+
557
+ button.append( liner );
558
+ }
559
+ else {
560
+ button.html( text( config.text ) );
561
+ }
562
+
563
+ if ( config.enabled === false ) {
564
+ button.addClass( buttonDom.disabled );
565
+ }
566
+
567
+ if ( config.className ) {
568
+ button.addClass( config.className );
569
+ }
570
+
571
+ if ( config.titleAttr ) {
572
+ button.attr( 'title', config.titleAttr );
573
+ }
574
+
575
+ if ( ! config.namespace ) {
576
+ config.namespace = '.dt-button-'+(_buttonCounter++);
577
+ }
578
+
579
+ var buttonContainer = this.c.dom.buttonContainer;
580
+ var inserter;
581
+ if ( buttonContainer && buttonContainer.tag ) {
582
+ inserter = $('<'+buttonContainer.tag+'/>')
583
+ .addClass( buttonContainer.className )
584
+ .append( button );
585
+ }
586
+ else {
587
+ inserter = button;
588
+ }
589
+
590
+ this._addKey( config );
591
+
592
+ return {
593
+ conf: config,
594
+ node: button.get(0),
595
+ inserter: inserter,
596
+ buttons: [],
597
+ inCollection: inCollection,
598
+ collection: null
599
+ };
600
+ },
601
+
602
+ /**
603
+ * Get the button object from a node (recursive)
604
+ * @param {node} node Button node
605
+ * @param {array} [buttons] Button array, uses base if not defined
606
+ * @return {object} Button object
607
+ * @private
608
+ */
609
+ _nodeToButton: function ( node, buttons )
610
+ {
611
+ if ( ! buttons ) {
612
+ buttons = this.s.buttons;
613
+ }
614
+
615
+ for ( var i=0, ien=buttons.length ; i<ien ; i++ ) {
616
+ if ( buttons[i].node === node ) {
617
+ return buttons[i];
618
+ }
619
+
620
+ if ( buttons[i].buttons.length ) {
621
+ var ret = this._nodeToButton( node, buttons[i].buttons );
622
+
623
+ if ( ret ) {
624
+ return ret;
625
+ }
626
+ }
627
+ }
628
+ },
629
+
630
+ /**
631
+ * Get container array for a button from a button node (recursive)
632
+ * @param {node} node Button node
633
+ * @param {array} [buttons] Button array, uses base if not defined
634
+ * @return {array} Button's host array
635
+ * @private
636
+ */
637
+ _nodeToHost: function ( node, buttons )
638
+ {
639
+ if ( ! buttons ) {
640
+ buttons = this.s.buttons;
641
+ }
642
+
643
+ for ( var i=0, ien=buttons.length ; i<ien ; i++ ) {
644
+ if ( buttons[i].node === node ) {
645
+ return buttons;
646
+ }
647
+
648
+ if ( buttons[i].buttons.length ) {
649
+ var ret = this._nodeToHost( node, buttons[i].buttons );
650
+
651
+ if ( ret ) {
652
+ return ret;
653
+ }
654
+ }
655
+ }
656
+ },
657
+
658
+ /**
659
+ * Handle a key press - determine if any button's key configured matches
660
+ * what was typed and trigger the action if so.
661
+ * @param {string} character The character pressed
662
+ * @param {object} e Key event that triggered this call
663
+ * @private
664
+ */
665
+ _keypress: function ( character, e )
666
+ {
667
+ var run = function ( conf, node ) {
668
+ if ( ! conf.key ) {
669
+ return;
670
+ }
671
+
672
+ if ( conf.key === character ) {
673
+ $(node).click();
674
+ }
675
+ else if ( $.isPlainObject( conf.key ) ) {
676
+ if ( conf.key.key !== character ) {
677
+ return;
678
+ }
679
+
680
+ if ( conf.key.shiftKey && ! e.shiftKey ) {
681
+ return;
682
+ }
683
+
684
+ if ( conf.key.altKey && ! e.altKey ) {
685
+ return;
686
+ }
687
+
688
+ if ( conf.key.ctrlKey && ! e.ctrlKey ) {
689
+ return;
690
+ }
691
+
692
+ if ( conf.key.metaKey && ! e.metaKey ) {
693
+ return;
694
+ }
695
+
696
+ // Made it this far - it is good
697
+ $(node).click();
698
+ }
699
+ };
700
+
701
+ var recurse = function ( a ) {
702
+ for ( var i=0, ien=a.length ; i<ien ; i++ ) {
703
+ run( a[i].conf, a[i].node );
704
+
705
+ if ( a[i].buttons.length ) {
706
+ recurse( a[i].buttons );
707
+ }
708
+ }
709
+ };
710
+
711
+ recurse( this.s.buttons );
712
+ },
713
+
714
+ /**
715
+ * Remove a key from the key listener for this instance (to be used when a
716
+ * button is removed)
717
+ * @param {object} conf Button configuration
718
+ * @private
719
+ */
720
+ _removeKey: function ( conf )
721
+ {
722
+ if ( conf.key ) {
723
+ var character = $.isPlainObject( conf.key ) ?
724
+ conf.key.key :
725
+ conf.key;
726
+
727
+ // Remove only one character, as multiple buttons could have the
728
+ // same listening key
729
+ var a = this.s.listenKeys.split('');
730
+ var idx = $.inArray( character, a );
731
+ a.splice( idx, 1 );
732
+ this.s.listenKeys = a.join('');
733
+ }
734
+ },
735
+
736
+ /**
737
+ * Resolve a button configuration
738
+ * @param {string|function|object} conf Button config to resolve
739
+ * @return {object} Button configuration
740
+ * @private
741
+ */
742
+ _resolveExtends: function ( conf )
743
+ {
744
+ var dt = this.s.dt;
745
+ var i, ien;
746
+ var toConfObject = function ( base ) {
747
+ var loop = 0;
748
+
749
+ // Loop until we have resolved to a button configuration, or an
750
+ // array of button configurations (which will be iterated
751
+ // separately)
752
+ while ( ! $.isPlainObject(base) && ! $.isArray(base) ) {
753
+ if ( base === undefined ) {
754
+ return;
755
+ }
756
+
757
+ if ( typeof base === 'function' ) {
758
+ base = base( dt, conf );
759
+
760
+ if ( ! base ) {
761
+ return false;
762
+ }
763
+ }
764
+ else if ( typeof base === 'string' ) {
765
+ if ( ! _dtButtons[ base ] ) {
766
+ throw 'Unknown button type: '+base;
767
+ }
768
+
769
+ base = _dtButtons[ base ];
770
+ }
771
+
772
+ loop++;
773
+ if ( loop > 30 ) {
774
+ // Protect against misconfiguration killing the browser
775
+ throw 'Buttons: Too many iterations';
776
+ }
777
+ }
778
+
779
+ return $.isArray( base ) ?
780
+ base :
781
+ $.extend( {}, base );
782
+ };
783
+
784
+ conf = toConfObject( conf );
785
+
786
+ while ( conf && conf.extend ) {
787
+ // Use `toConfObject` in case the button definition being extended
788
+ // is itself a string or a function
789
+ if ( ! _dtButtons[ conf.extend ] ) {
790
+ throw 'Cannot extend unknown button type: '+conf.extend;
791
+ }
792
+
793
+ var objArray = toConfObject( _dtButtons[ conf.extend ] );
794
+ if ( $.isArray( objArray ) ) {
795
+ return objArray;
796
+ }
797
+ else if ( ! objArray ) {
798
+ // This is a little brutal as it might be possible to have a
799
+ // valid button without the extend, but if there is no extend
800
+ // then the host button would be acting in an undefined state
801
+ return false;
802
+ }
803
+
804
+ // Stash the current class name
805
+ var originalClassName = objArray.className;
806
+
807
+ conf = $.extend( {}, objArray, conf );
808
+
809
+ // The extend will have overwritten the original class name if the
810
+ // `conf` object also assigned a class, but we want to concatenate
811
+ // them so they are list that is combined from all extended buttons
812
+ if ( originalClassName && conf.className !== originalClassName ) {
813
+ conf.className = originalClassName+' '+conf.className;
814
+ }
815
+
816
+ // Buttons to be added to a collection -gives the ability to define
817
+ // if buttons should be added to the start or end of a collection
818
+ var postfixButtons = conf.postfixButtons;
819
+ if ( postfixButtons ) {
820
+ if ( ! conf.buttons ) {
821
+ conf.buttons = [];
822
+ }
823
+
824
+ for ( i=0, ien=postfixButtons.length ; i<ien ; i++ ) {
825
+ conf.buttons.push( postfixButtons[i] );
826
+ }
827
+
828
+ conf.postfixButtons = null;
829
+ }
830
+
831
+ var prefixButtons = conf.prefixButtons;
832
+ if ( prefixButtons ) {
833
+ if ( ! conf.buttons ) {
834
+ conf.buttons = [];
835
+ }
836
+
837
+ for ( i=0, ien=prefixButtons.length ; i<ien ; i++ ) {
838
+ conf.buttons.splice( i, 0, prefixButtons[i] );
839
+ }
840
+
841
+ conf.prefixButtons = null;
842
+ }
843
+
844
+ // Although we want the `conf` object to overwrite almost all of
845
+ // the properties of the object being extended, the `extend`
846
+ // property should come from the object being extended
847
+ conf.extend = objArray.extend;
848
+ }
849
+
850
+ return conf;
851
+ }
852
+ } );
853
+
854
+
855
+
856
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
857
+ * Statics
858
+ */
859
+
860
+ /**
861
+ * Show / hide a background layer behind a collection
862
+ * @param {boolean} Flag to indicate if the background should be shown or
863
+ * hidden
864
+ * @param {string} Class to assign to the background
865
+ * @static
866
+ */
867
+ Buttons.background = function ( show, className, fade ) {
868
+ if ( fade === undefined ) {
869
+ fade = 400;
870
+ }
871
+
872
+ if ( show ) {
873
+ $('<div/>')
874
+ .addClass( className )
875
+ .css( 'display', 'none' )
876
+ .appendTo( 'body' )
877
+ .fadeIn( fade );
878
+ }
879
+ else {
880
+ $('body > div.'+className)
881
+ .fadeOut( fade, function () {
882
+ $(this).remove();
883
+ } );
884
+ }
885
+ };
886
+
887
+ /**
888
+ * Instance selector - select Buttons instances based on an instance selector
889
+ * value from the buttons assigned to a DataTable. This is only useful if
890
+ * multiple instances are attached to a DataTable.
891
+ * @param {string|int|array} Instance selector - see `instance-selector`
892
+ * documentation on the DataTables site
893
+ * @param {array} Button instance array that was attached to the DataTables
894
+ * settings object
895
+ * @return {array} Buttons instances
896
+ * @static
897
+ */
898
+ Buttons.instanceSelector = function ( group, buttons )
899
+ {
900
+ if ( ! group ) {
901
+ return $.map( buttons, function ( v ) {
902
+ return v.inst;
903
+ } );
904
+ }
905
+
906
+ var ret = [];
907
+ var names = $.map( buttons, function ( v ) {
908
+ return v.name;
909
+ } );
910
+
911
+ // Flatten the group selector into an array of single options
912
+ var process = function ( input ) {
913
+ if ( $.isArray( input ) ) {
914
+ for ( var i=0, ien=input.length ; i<ien ; i++ ) {
915
+ process( input[i] );
916
+ }
917
+ return;
918
+ }
919
+
920
+ if ( typeof input === 'string' ) {
921
+ if ( input.indexOf( ',' ) !== -1 ) {
922
+ // String selector, list of names
923
+ process( input.split(',') );
924
+ }
925
+ else {
926
+ // String selector individual name
927
+ var idx = $.inArray( $.trim(input), names );
928
+
929
+ if ( idx !== -1 ) {
930
+ ret.push( buttons[ idx ].inst );
931
+ }
932
+ }
933
+ }
934
+ else if ( typeof input === 'number' ) {
935
+ // Index selector
936
+ ret.push( buttons[ input ].inst );
937
+ }
938
+ };
939
+
940
+ process( group );
941
+
942
+ return ret;
943
+ };
944
+
945
+ /**
946
+ * Button selector - select one or more buttons from a selector input so some
947
+ * operation can be performed on them.
948
+ * @param {array} Button instances array that the selector should operate on
949
+ * @param {string|int|node|jQuery|array} Button selector - see
950
+ * `button-selector` documentation on the DataTables site
951
+ * @return {array} Array of objects containing `inst` and `idx` properties of
952
+ * the selected buttons so you know which instance each button belongs to.
953
+ * @static
954
+ */
955
+ Buttons.buttonSelector = function ( insts, selector )
956
+ {
957
+ var ret = [];
958
+ var nodeBuilder = function ( a, buttons, baseIdx ) {
959
+ var button;
960
+ var idx;
961
+
962
+ for ( var i=0, ien=buttons.length ; i<ien ; i++ ) {
963
+ button = buttons[i];
964
+
965
+ if ( button ) {
966
+ idx = baseIdx !== undefined ?
967
+ baseIdx+i :
968
+ i+'';
969
+
970
+ a.push( {
971
+ node: button.node,
972
+ name: button.conf.name,
973
+ idx: idx
974
+ } );
975
+
976
+ if ( button.buttons ) {
977
+ nodeBuilder( a, button.buttons, idx+'-' );
978
+ }
979
+ }
980
+ }
981
+ };
982
+
983
+ var run = function ( selector, inst ) {
984
+ var i, ien;
985
+ var buttons = [];
986
+ nodeBuilder( buttons, inst.s.buttons );
987
+
988
+ var nodes = $.map( buttons, function (v) {
989
+ return v.node;
990
+ } );
991
+
992
+ if ( $.isArray( selector ) || selector instanceof $ ) {
993
+ for ( i=0, ien=selector.length ; i<ien ; i++ ) {
994
+ run( selector[i], inst );
995
+ }
996
+ return;
997
+ }
998
+
999
+ if ( selector === null || selector === undefined || selector === '*' ) {
1000
+ // Select all
1001
+ for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
1002
+ ret.push( {
1003
+ inst: inst,
1004
+ node: buttons[i].node
1005
+ } );
1006
+ }
1007
+ }
1008
+ else if ( typeof selector === 'number' ) {
1009
+ // Main button index selector
1010
+ ret.push( {
1011
+ inst: inst,
1012
+ node: inst.s.buttons[ selector ].node
1013
+ } );
1014
+ }
1015
+ else if ( typeof selector === 'string' ) {
1016
+ if ( selector.indexOf( ',' ) !== -1 ) {
1017
+ // Split
1018
+ var a = selector.split(',');
1019
+
1020
+ for ( i=0, ien=a.length ; i<ien ; i++ ) {
1021
+ run( $.trim(a[i]), inst );
1022
+ }
1023
+ }
1024
+ else if ( selector.match( /^\d+(\-\d+)*$/ ) ) {
1025
+ // Sub-button index selector
1026
+ var indexes = $.map( buttons, function (v) {
1027
+ return v.idx;
1028
+ } );
1029
+
1030
+ ret.push( {
1031
+ inst: inst,
1032
+ node: buttons[ $.inArray( selector, indexes ) ].node
1033
+ } );
1034
+ }
1035
+ else if ( selector.indexOf( ':name' ) !== -1 ) {
1036
+ // Button name selector
1037
+ var name = selector.replace( ':name', '' );
1038
+
1039
+ for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
1040
+ if ( buttons[i].name === name ) {
1041
+ ret.push( {
1042
+ inst: inst,
1043
+ node: buttons[i].node
1044
+ } );
1045
+ }
1046
+ }
1047
+ }
1048
+ else {
1049
+ // jQuery selector on the nodes
1050
+ $( nodes ).filter( selector ).each( function () {
1051
+ ret.push( {
1052
+ inst: inst,
1053
+ node: this
1054
+ } );
1055
+ } );
1056
+ }
1057
+ }
1058
+ else if ( typeof selector === 'object' && selector.nodeName ) {
1059
+ // Node selector
1060
+ var idx = $.inArray( selector, nodes );
1061
+
1062
+ if ( idx !== -1 ) {
1063
+ ret.push( {
1064
+ inst: inst,
1065
+ node: nodes[ idx ]
1066
+ } );
1067
+ }
1068
+ }
1069
+ };
1070
+
1071
+
1072
+ for ( var i=0, ien=insts.length ; i<ien ; i++ ) {
1073
+ var inst = insts[i];
1074
+
1075
+ run( selector, inst );
1076
+ }
1077
+
1078
+ return ret;
1079
+ };
1080
+
1081
+
1082
+ /**
1083
+ * Buttons defaults. For full documentation, please refer to the docs/option
1084
+ * directory or the DataTables site.
1085
+ * @type {Object}
1086
+ * @static
1087
+ */
1088
+ Buttons.defaults = {
1089
+ buttons: [ 'copy', 'excel', 'csv', 'pdf', 'print' ],
1090
+ name: 'main',
1091
+ tabIndex: 0,
1092
+ dom: {
1093
+ container: {
1094
+ tag: 'div',
1095
+ className: 'dt-buttons'
1096
+ },
1097
+ collection: {
1098
+ tag: 'div',
1099
+ className: 'dt-button-collection'
1100
+ },
1101
+ button: {
1102
+ tag: 'a',
1103
+ className: 'dt-button',
1104
+ active: 'active',
1105
+ disabled: 'disabled'
1106
+ },
1107
+ buttonLiner: {
1108
+ tag: 'span',
1109
+ className: ''
1110
+ }
1111
+ }
1112
+ };
1113
+
1114
+ /**
1115
+ * Version information
1116
+ * @type {string}
1117
+ * @static
1118
+ */
1119
+ Buttons.version = '1.2.0';
1120
+
1121
+
1122
+ $.extend( _dtButtons, {
1123
+ collection: {
1124
+ text: function ( dt ) {
1125
+ return dt.i18n( 'buttons.collection', 'Collection' );
1126
+ },
1127
+ className: 'buttons-collection',
1128
+ action: function ( e, dt, button, config ) {
1129
+ var host = button;
1130
+ var hostOffset = host.offset();
1131
+ var tableContainer = $( dt.table().container() );
1132
+ var multiLevel = false;
1133
+
1134
+ // Remove any old collection
1135
+ if ( $('div.dt-button-background').length ) {
1136
+ multiLevel = $('div.dt-button-collection').offset();
1137
+ $('body').trigger( 'click.dtb-collection' );
1138
+ }
1139
+
1140
+ config._collection
1141
+ .addClass( config.collectionLayout )
1142
+ .css( 'display', 'none' )
1143
+ .appendTo( 'body' )
1144
+ .fadeIn( config.fade );
1145
+
1146
+ var position = config._collection.css( 'position' );
1147
+
1148
+ if ( multiLevel && position === 'absolute' ) {
1149
+ config._collection.css( {
1150
+ top: multiLevel.top + 5, // magic numbers for a little offset
1151
+ left: multiLevel.left + 5
1152
+ } );
1153
+ }
1154
+ else if ( position === 'absolute' ) {
1155
+ config._collection.css( {
1156
+ top: hostOffset.top + host.outerHeight(),
1157
+ left: hostOffset.left
1158
+ } );
1159
+
1160
+ var listRight = hostOffset.left + config._collection.outerWidth();
1161
+ var tableRight = tableContainer.offset().left + tableContainer.width();
1162
+ if ( listRight > tableRight ) {
1163
+ config._collection.css( 'left', hostOffset.left - ( listRight - tableRight ) );
1164
+ }
1165
+ }
1166
+ else {
1167
+ // Fix position - centre on screen
1168
+ var top = config._collection.height() / 2;
1169
+ if ( top > $(window).height() / 2 ) {
1170
+ top = $(window).height() / 2;
1171
+ }
1172
+
1173
+ config._collection.css( 'marginTop', top*-1 );
1174
+ }
1175
+
1176
+ if ( config.background ) {
1177
+ Buttons.background( true, config.backgroundClassName, config.fade );
1178
+ }
1179
+
1180
+ // Need to break the 'thread' for the collection button being
1181
+ // activated by a click - it would also trigger this event
1182
+ setTimeout( function () {
1183
+ // This is bonkers, but if we don't have a click listener on the
1184
+ // background element, iOS Safari will ignore the body click
1185
+ // listener below. An empty function here is all that is
1186
+ // required to make it work...
1187
+ $('div.dt-button-background').on( 'click.dtb-collection', function () {} );
1188
+
1189
+ $('body').on( 'click.dtb-collection', function (e) {
1190
+ if ( ! $(e.target).parents().andSelf().filter( config._collection ).length ) {
1191
+ config._collection
1192
+ .fadeOut( config.fade, function () {
1193
+ config._collection.detach();
1194
+ } );
1195
+
1196
+ $('div.dt-button-background').off( 'click.dtb-collection' );
1197
+ Buttons.background( false, config.backgroundClassName, config.fade );
1198
+
1199
+ $('body').off( 'click.dtb-collection' );
1200
+ dt.off( 'buttons-action.b-internal' );
1201
+ }
1202
+ } );
1203
+ }, 10 );
1204
+
1205
+ if ( config.autoClose ) {
1206
+ dt.on( 'buttons-action.b-internal', function () {
1207
+ $('div.dt-button-background').click();
1208
+ } );
1209
+ }
1210
+ },
1211
+ background: true,
1212
+ collectionLayout: '',
1213
+ backgroundClassName: 'dt-button-background',
1214
+ autoClose: false,
1215
+ fade: 400
1216
+ },
1217
+ copy: function ( dt, conf ) {
1218
+ if ( _dtButtons.copyHtml5 ) {
1219
+ return 'copyHtml5';
1220
+ }
1221
+ if ( _dtButtons.copyFlash && _dtButtons.copyFlash.available( dt, conf ) ) {
1222
+ return 'copyFlash';
1223
+ }
1224
+ },
1225
+ csv: function ( dt, conf ) {
1226
+ // Common option that will use the HTML5 or Flash export buttons
1227
+ if ( _dtButtons.csvHtml5 && _dtButtons.csvHtml5.available( dt, conf ) ) {
1228
+ return 'csvHtml5';
1229
+ }
1230
+ if ( _dtButtons.csvFlash && _dtButtons.csvFlash.available( dt, conf ) ) {
1231
+ return 'csvFlash';
1232
+ }
1233
+ },
1234
+ excel: function ( dt, conf ) {
1235
+ // Common option that will use the HTML5 or Flash export buttons
1236
+ if ( _dtButtons.excelHtml5 && _dtButtons.excelHtml5.available( dt, conf ) ) {
1237
+ return 'excelHtml5';
1238
+ }
1239
+ if ( _dtButtons.excelFlash && _dtButtons.excelFlash.available( dt, conf ) ) {
1240
+ return 'excelFlash';
1241
+ }
1242
+ },
1243
+ pdf: function ( dt, conf ) {
1244
+ // Common option that will use the HTML5 or Flash export buttons
1245
+ if ( _dtButtons.pdfHtml5 && _dtButtons.pdfHtml5.available( dt, conf ) ) {
1246
+ return 'pdfHtml5';
1247
+ }
1248
+ if ( _dtButtons.pdfFlash && _dtButtons.pdfFlash.available( dt, conf ) ) {
1249
+ return 'pdfFlash';
1250
+ }
1251
+ },
1252
+ pageLength: function ( dt ) {
1253
+ var lengthMenu = dt.settings()[0].aLengthMenu;
1254
+ var vals = $.isArray( lengthMenu[0] ) ? lengthMenu[0] : lengthMenu;
1255
+ var lang = $.isArray( lengthMenu[0] ) ? lengthMenu[1] : lengthMenu;
1256
+ var text = function ( dt ) {
1257
+ return dt.i18n( 'buttons.pageLength', {
1258
+ "-1": 'Show all rows',
1259
+ _: 'Show %d rows'
1260
+ }, dt.page.len() );
1261
+ };
1262
+
1263
+ return {
1264
+ extend: 'collection',
1265
+ text: text,
1266
+ className: 'buttons-page-length',
1267
+ autoClose: true,
1268
+ buttons: $.map( vals, function ( val, i ) {
1269
+ return {
1270
+ text: lang[i],
1271
+ action: function ( e, dt ) {
1272
+ dt.page.len( val ).draw();
1273
+ },
1274
+ init: function ( dt, node, conf ) {
1275
+ var that = this;
1276
+ var fn = function () {
1277
+ that.active( dt.page.len() === val );
1278
+ };
1279
+
1280
+ dt.on( 'length.dt'+conf.namespace, fn );
1281
+ fn();
1282
+ },
1283
+ destroy: function ( dt, node, conf ) {
1284
+ dt.off( 'length.dt'+conf.namespace );
1285
+ }
1286
+ };
1287
+ } ),
1288
+ init: function ( dt, node, conf ) {
1289
+ var that = this;
1290
+ dt.on( 'length.dt'+conf.namespace, function () {
1291
+ that.text( text( dt ) );
1292
+ } );
1293
+ },
1294
+ destroy: function ( dt, node, conf ) {
1295
+ dt.off( 'length.dt'+conf.namespace );
1296
+ }
1297
+ };
1298
+ }
1299
+ } );
1300
+
1301
+
1302
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1303
+ * DataTables API
1304
+ *
1305
+ * For complete documentation, please refer to the docs/api directory or the
1306
+ * DataTables site
1307
+ */
1308
+
1309
+ // Buttons group and individual button selector
1310
+ DataTable.Api.register( 'buttons()', function ( group, selector ) {
1311
+ // Argument shifting
1312
+ if ( selector === undefined ) {
1313
+ selector = group;
1314
+ group = undefined;
1315
+ }
1316
+
1317
+ return this.iterator( true, 'table', function ( ctx ) {
1318
+ if ( ctx._buttons ) {
1319
+ return Buttons.buttonSelector(
1320
+ Buttons.instanceSelector( group, ctx._buttons ),
1321
+ selector
1322
+ );
1323
+ }
1324
+ }, true );
1325
+ } );
1326
+
1327
+ // Individual button selector
1328
+ DataTable.Api.register( 'button()', function ( group, selector ) {
1329
+ // just run buttons() and truncate
1330
+ var buttons = this.buttons( group, selector );
1331
+
1332
+ if ( buttons.length > 1 ) {
1333
+ buttons.splice( 1, buttons.length );
1334
+ }
1335
+
1336
+ return buttons;
1337
+ } );
1338
+
1339
+ // Active buttons
1340
+ DataTable.Api.registerPlural( 'buttons().active()', 'button().active()', function ( flag ) {
1341
+ if ( flag === undefined ) {
1342
+ return this.map( function ( set ) {
1343
+ return set.inst.active( set.node );
1344
+ } );
1345
+ }
1346
+
1347
+ return this.each( function ( set ) {
1348
+ set.inst.active( set.node, flag );
1349
+ } );
1350
+ } );
1351
+
1352
+ // Get / set button action
1353
+ DataTable.Api.registerPlural( 'buttons().action()', 'button().action()', function ( action ) {
1354
+ if ( action === undefined ) {
1355
+ return this.map( function ( set ) {
1356
+ return set.inst.action( set.node );
1357
+ } );
1358
+ }
1359
+
1360
+ return this.each( function ( set ) {
1361
+ set.inst.action( set.node, action );
1362
+ } );
1363
+ } );
1364
+
1365
+ // Enable / disable buttons
1366
+ DataTable.Api.register( ['buttons().enable()', 'button().enable()'], function ( flag ) {
1367
+ return this.each( function ( set ) {
1368
+ set.inst.enable( set.node, flag );
1369
+ } );
1370
+ } );
1371
+
1372
+ // Disable buttons
1373
+ DataTable.Api.register( ['buttons().disable()', 'button().disable()'], function () {
1374
+ return this.each( function ( set ) {
1375
+ set.inst.disable( set.node );
1376
+ } );
1377
+ } );
1378
+
1379
+ // Get button nodes
1380
+ DataTable.Api.registerPlural( 'buttons().nodes()', 'button().node()', function () {
1381
+ var jq = $();
1382
+
1383
+ // jQuery will automatically reduce duplicates to a single entry
1384
+ $( this.each( function ( set ) {
1385
+ jq = jq.add( set.inst.node( set.node ) );
1386
+ } ) );
1387
+
1388
+ return jq;
1389
+ } );
1390
+
1391
+ // Get / set button text (i.e. the button labels)
1392
+ DataTable.Api.registerPlural( 'buttons().text()', 'button().text()', function ( label ) {
1393
+ if ( label === undefined ) {
1394
+ return this.map( function ( set ) {
1395
+ return set.inst.text( set.node );
1396
+ } );
1397
+ }
1398
+
1399
+ return this.each( function ( set ) {
1400
+ set.inst.text( set.node, label );
1401
+ } );
1402
+ } );
1403
+
1404
+ // Trigger a button's action
1405
+ DataTable.Api.registerPlural( 'buttons().trigger()', 'button().trigger()', function () {
1406
+ return this.each( function ( set ) {
1407
+ set.inst.node( set.node ).trigger( 'click' );
1408
+ } );
1409
+ } );
1410
+
1411
+ // Get the container elements for the button sets selected
1412
+ DataTable.Api.registerPlural( 'buttons().containers()', 'buttons().container()', function () {
1413
+ var jq = $();
1414
+
1415
+ // jQuery will automatically reduce duplicates to a single entry
1416
+ $( this.each( function ( set ) {
1417
+ jq = jq.add( set.inst.container() );
1418
+ } ) );
1419
+
1420
+ return jq;
1421
+ } );
1422
+
1423
+ // Add a new button
1424
+ DataTable.Api.register( 'button().add()', function ( idx, conf ) {
1425
+ if ( this.length === 1 ) {
1426
+ this[0].inst.add( conf, idx );
1427
+ }
1428
+
1429
+ return this.button( idx );
1430
+ } );
1431
+
1432
+ // Destroy the button sets selected
1433
+ DataTable.Api.register( 'buttons().destroy()', function () {
1434
+ this.pluck( 'inst' ).unique().each( function ( inst ) {
1435
+ inst.destroy();
1436
+ } );
1437
+
1438
+ return this;
1439
+ } );
1440
+
1441
+ // Remove a button
1442
+ DataTable.Api.registerPlural( 'buttons().remove()', 'buttons().remove()', function () {
1443
+ this.each( function ( set ) {
1444
+ set.inst.remove( set.node );
1445
+ } );
1446
+
1447
+ return this;
1448
+ } );
1449
+
1450
+ // Information box that can be used by buttons
1451
+ var _infoTimer;
1452
+ DataTable.Api.register( 'buttons.info()', function ( title, message, time ) {
1453
+ var that = this;
1454
+
1455
+ if ( title === false ) {
1456
+ $('#datatables_buttons_info').fadeOut( function () {
1457
+ $(this).remove();
1458
+ } );
1459
+ clearTimeout( _infoTimer );
1460
+ _infoTimer = null;
1461
+
1462
+ return this;
1463
+ }
1464
+
1465
+ if ( _infoTimer ) {
1466
+ clearTimeout( _infoTimer );
1467
+ }
1468
+
1469
+ if ( $('#datatables_buttons_info').length ) {
1470
+ $('#datatables_buttons_info').remove();
1471
+ }
1472
+
1473
+ title = title ? '<h2>'+title+'</h2>' : '';
1474
+
1475
+ $('<div id="datatables_buttons_info" class="dt-button-info"/>')
1476
+ .html( title )
1477
+ .append( $('<div/>')[ typeof message === 'string' ? 'html' : 'append' ]( message ) )
1478
+ .css( 'display', 'none' )
1479
+ .appendTo( 'body' )
1480
+ .fadeIn();
1481
+
1482
+ if ( time !== undefined && time !== 0 ) {
1483
+ _infoTimer = setTimeout( function () {
1484
+ that.buttons.info( false );
1485
+ }, time );
1486
+ }
1487
+
1488
+ return this;
1489
+ } );
1490
+
1491
+ // Get data from the table for export - this is common to a number of plug-in
1492
+ // buttons so it is included in the Buttons core library
1493
+ DataTable.Api.register( 'buttons.exportData()', function ( options ) {
1494
+ if ( this.context.length ) {
1495
+ return _exportData( new DataTable.Api( this.context[0] ), options );
1496
+ }
1497
+ } );
1498
+
1499
+
1500
+ var _exportTextarea = $('<textarea/>')[0];
1501
+ var _exportData = function ( dt, inOpts )
1502
+ {
1503
+ var config = $.extend( true, {}, {
1504
+ rows: null,
1505
+ columns: '',
1506
+ modifier: {
1507
+ search: 'applied',
1508
+ order: 'applied'
1509
+ },
1510
+ orthogonal: 'display',
1511
+ stripHtml: true,
1512
+ stripNewlines: true,
1513
+ decodeEntities: true,
1514
+ trim: true,
1515
+ format: {
1516
+ header: function ( d ) {
1517
+ return strip( d );
1518
+ },
1519
+ footer: function ( d ) {
1520
+ return strip( d );
1521
+ },
1522
+ body: function ( d ) {
1523
+ return strip( d );
1524
+ }
1525
+ }
1526
+ }, inOpts );
1527
+
1528
+ var strip = function ( str ) {
1529
+ if ( typeof str !== 'string' ) {
1530
+ return str;
1531
+ }
1532
+
1533
+ if ( config.stripHtml ) {
1534
+ str = str.replace( /<[^>]*>/g, '' );
1535
+ }
1536
+
1537
+ if ( config.trim ) {
1538
+ str = str.replace( /^\s+|\s+$/g, '' );
1539
+ }
1540
+
1541
+ if ( config.stripNewlines ) {
1542
+ str = str.replace( /\n/g, ' ' );
1543
+ }
1544
+
1545
+ if ( config.decodeEntities ) {
1546
+ _exportTextarea.innerHTML = str;
1547
+ str = _exportTextarea.value;
1548
+ }
1549
+
1550
+ return str;
1551
+ };
1552
+
1553
+
1554
+ var header = dt.columns( config.columns ).indexes().map( function (idx) {
1555
+ return config.format.header( dt.column( idx ).header().innerHTML, idx );
1556
+ } ).toArray();
1557
+
1558
+ var footer = dt.table().footer() ?
1559
+ dt.columns( config.columns ).indexes().map( function (idx) {
1560
+ var el = dt.column( idx ).footer();
1561
+ return config.format.footer( el ? el.innerHTML : '', idx );
1562
+ } ).toArray() :
1563
+ null;
1564
+
1565
+ var rowIndexes = dt.rows( config.rows, config.modifier ).indexes().toArray();
1566
+ var cells = dt
1567
+ .cells( rowIndexes, config.columns )
1568
+ .render( config.orthogonal )
1569
+ .toArray();
1570
+ var columns = header.length;
1571
+ var rows = columns > 0 ? cells.length / columns : 0;
1572
+ var body = new Array( rows );
1573
+ var cellCounter = 0;
1574
+
1575
+ for ( var i=0, ien=rows ; i<ien ; i++ ) {
1576
+ var row = new Array( columns );
1577
+
1578
+ for ( var j=0 ; j<columns ; j++ ) {
1579
+ row[j] = config.format.body( cells[ cellCounter ], j, i );
1580
+ cellCounter++;
1581
+ }
1582
+
1583
+ body[i] = row;
1584
+ }
1585
+
1586
+ return {
1587
+ header: header,
1588
+ footer: footer,
1589
+ body: body
1590
+ };
1591
+ };
1592
+
1593
+
1594
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1595
+ * DataTables interface
1596
+ */
1597
+
1598
+ // Attach to DataTables objects for global access
1599
+ $.fn.dataTable.Buttons = Buttons;
1600
+ $.fn.DataTable.Buttons = Buttons;
1601
+
1602
+
1603
+
1604
+ // DataTables creation - check if the buttons have been defined for this table,
1605
+ // they will have been if the `B` option was used in `dom`, otherwise we should
1606
+ // create the buttons instance here so they can be inserted into the document
1607
+ // using the API. Listen for `init` for compatibility with pre 1.10.10, but to
1608
+ // be removed in future.
1609
+ $(document).on( 'init.dt plugin-init.dt', function (e, settings) {
1610
+ if ( e.namespace !== 'dt' ) {
1611
+ return;
1612
+ }
1613
+
1614
+ var opts = settings.oInit.buttons || DataTable.defaults.buttons;
1615
+
1616
+ if ( opts && ! settings._buttons ) {
1617
+ new Buttons( settings, opts ).container();
1618
+ }
1619
+ } );
1620
+
1621
+ // DataTables `dom` feature option
1622
+ DataTable.ext.feature.push( {
1623
+ fnInit: function( settings ) {
1624
+ var api = new DataTable.Api( settings );
1625
+ var opts = api.init().buttons || DataTable.defaults.buttons;
1626
+
1627
+ return new Buttons( api, opts ).container();
1628
+ },
1629
+ cFeature: "B"
1630
+ } );
1631
+
1632
+
1633
+ return Buttons;
1634
+ }));