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,883 @@
1
+ /*! KeyTable 2.1.2
2
+ * ©2009-2016 SpryMedia Ltd - datatables.net/license
3
+ */
4
+
5
+ /**
6
+ * @summary KeyTable
7
+ * @description Spreadsheet like keyboard navigation for DataTables
8
+ * @version 2.1.2
9
+ * @file dataTables.keyTable.js
10
+ * @author SpryMedia Ltd (www.sprymedia.co.uk)
11
+ * @contact www.sprymedia.co.uk/contact
12
+ * @copyright Copyright 2009-2016 SpryMedia Ltd.
13
+ *
14
+ * This source file is free software, available under the following license:
15
+ * MIT license - http://datatables.net/license/mit
16
+ *
17
+ * This source file is distributed in the hope that it will be useful, but
18
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
20
+ *
21
+ * For details please refer to: http://www.datatables.net
22
+ */
23
+
24
+ (function( factory ){
25
+ if ( typeof define === 'function' && define.amd ) {
26
+ // AMD
27
+ define( ['jquery', 'datatables.net'], function ( $ ) {
28
+ return factory( $, window, document );
29
+ } );
30
+ }
31
+ else if ( typeof exports === 'object' ) {
32
+ // CommonJS
33
+ module.exports = function (root, $) {
34
+ if ( ! root ) {
35
+ root = window;
36
+ }
37
+
38
+ if ( ! $ || ! $.fn.dataTable ) {
39
+ $ = require('datatables.net')(root, $).$;
40
+ }
41
+
42
+ return factory( $, root, root.document );
43
+ };
44
+ }
45
+ else {
46
+ // Browser
47
+ factory( jQuery, window, document );
48
+ }
49
+ }(function( $, window, document, undefined ) {
50
+ 'use strict';
51
+ var DataTable = $.fn.dataTable;
52
+
53
+
54
+ var KeyTable = function ( dt, opts ) {
55
+ // Sanity check that we are using DataTables 1.10 or newer
56
+ if ( ! DataTable.versionCheck || ! DataTable.versionCheck( '1.10.8' ) ) {
57
+ throw 'KeyTable requires DataTables 1.10.8 or newer';
58
+ }
59
+
60
+ // User and defaults configuration object
61
+ this.c = $.extend( true, {},
62
+ DataTable.defaults.keyTable,
63
+ KeyTable.defaults,
64
+ opts
65
+ );
66
+
67
+ // Internal settings
68
+ this.s = {
69
+ /** @type {DataTable.Api} DataTables' API instance */
70
+ dt: new DataTable.Api( dt ),
71
+
72
+ enable: true,
73
+
74
+ /** @type {bool} Flag for if a draw is triggered by focus */
75
+ focusDraw: false
76
+ };
77
+
78
+ // DOM items
79
+ this.dom = {
80
+
81
+ };
82
+
83
+ // Check if row reorder has already been initialised on this table
84
+ var settings = this.s.dt.settings()[0];
85
+ var exisiting = settings.keytable;
86
+ if ( exisiting ) {
87
+ return exisiting;
88
+ }
89
+
90
+ settings.keytable = this;
91
+ this._constructor();
92
+ };
93
+
94
+
95
+ $.extend( KeyTable.prototype, {
96
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
97
+ * API methods for DataTables API interface
98
+ */
99
+
100
+ /**
101
+ * Blur the table's cell focus
102
+ */
103
+ blur: function ()
104
+ {
105
+ this._blur();
106
+ },
107
+
108
+ /**
109
+ * Enable cell focus for the table
110
+ *
111
+ * @param {string} state Can be `true`, `false` or `-string navigation-only`
112
+ */
113
+ enable: function ( state )
114
+ {
115
+ this.s.enable = state;
116
+ },
117
+
118
+ /**
119
+ * Focus on a cell
120
+ * @param {integer} row Row index
121
+ * @param {integer} column Column index
122
+ */
123
+ focus: function ( row, column )
124
+ {
125
+ this._focus( this.s.dt.cell( row, column ) );
126
+ },
127
+
128
+ /**
129
+ * Is the cell focused
130
+ * @param {object} cell Cell index to check
131
+ * @returns {boolean} true if focused, false otherwise
132
+ */
133
+ focused: function ( cell )
134
+ {
135
+ var lastFocus = this.s.lastFocus;
136
+
137
+ if ( ! lastFocus ) {
138
+ return false;
139
+ }
140
+
141
+ var lastIdx = this.s.lastFocus.index();
142
+ return cell.row === lastIdx.row && cell.column === lastIdx.column;
143
+ },
144
+
145
+
146
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
147
+ * Constructor
148
+ */
149
+
150
+ /**
151
+ * Initialise the KeyTable instance
152
+ *
153
+ * @private
154
+ */
155
+ _constructor: function ()
156
+ {
157
+ this._tabInput();
158
+
159
+ var that = this;
160
+ var dt = this.s.dt;
161
+ var table = $( dt.table().node() );
162
+
163
+ // Need to be able to calculate the cell positions relative to the table
164
+ if ( table.css('position') === 'static' ) {
165
+ table.css( 'position', 'relative' );
166
+ }
167
+
168
+ // Click to focus
169
+ $( dt.table().body() ).on( 'click.keyTable', 'th, td', function () {
170
+ if ( that.s.enable === false ) {
171
+ return;
172
+ }
173
+
174
+ var cell = dt.cell( this );
175
+
176
+ if ( ! cell.any() ) {
177
+ return;
178
+ }
179
+
180
+ that._focus( cell, null, false );
181
+ } );
182
+
183
+ // Key events
184
+ $( document ).on( 'keydown.keyTable', function (e) {
185
+ that._key( e );
186
+ } );
187
+
188
+ // Click blur
189
+ if ( this.c.blurable ) {
190
+ $( document ).on( 'click.keyTable', function ( e ) {
191
+ // Click on the search input will blur focus
192
+ if ( $(e.target).parents( '.dataTables_filter' ).length ) {
193
+ that._blur();
194
+ }
195
+
196
+ // If the click was inside the DataTables container, don't blur
197
+ if ( $(e.target).parents().filter( dt.table().container() ).length ) {
198
+ return;
199
+ }
200
+
201
+ // Don't blur in Editor form
202
+ if ( $(e.target).parents('div.DTE').length ) {
203
+ return;
204
+ }
205
+
206
+ that._blur();
207
+ } );
208
+ }
209
+
210
+ if ( this.c.editor ) {
211
+ dt.on( 'key.keyTable', function ( e, dt, key, cell, orig ) {
212
+ that._editor( key, orig );
213
+ } );
214
+ }
215
+
216
+ // Stave saving
217
+ if ( dt.settings()[0].oFeatures.bStateSave ) {
218
+ dt.on( 'stateSaveParams.keyTable', function (e, s, d) {
219
+ d.keyTable = that.s.lastFocus ?
220
+ that.s.lastFocus.index() :
221
+ null;
222
+ } );
223
+ }
224
+
225
+ // Reload - re-focus on the currently selected item. In SSP mode this
226
+ // has the effect of keeping the focus in position when changing page as
227
+ // well (which is different from how client-side processing works).
228
+ dt.on( 'xhr.keyTable', function ( e ) {
229
+ if ( that.s.focusDraw ) {
230
+ // Triggered by server-side processing, and thus `_focus` will
231
+ // do the refocus on the next draw event
232
+ return;
233
+ }
234
+
235
+ var lastFocus = that.s.lastFocus;
236
+
237
+ if ( lastFocus ) {
238
+ that.s.lastFocus = null;
239
+
240
+ dt.one( 'draw', function () {
241
+ that._focus( lastFocus );
242
+ } );
243
+ }
244
+ } );
245
+
246
+ dt.on( 'destroy.keyTable', function () {
247
+ dt.off( '.keyTable' );
248
+ $( dt.table().body() ).off( 'click.keyTable', 'th, td' );
249
+ $( document.body )
250
+ .off( 'keydown.keyTable' )
251
+ .off( 'click.keyTable' );
252
+ } );
253
+
254
+ // Initial focus comes from state or options
255
+ var state = dt.state.loaded();
256
+
257
+ if ( state && state.keyTable ) {
258
+ // Wait until init is done
259
+ dt.one( 'init', function () {
260
+ var cell = dt.cell( state.keyTable );
261
+
262
+ // Ensure that the saved cell still exists
263
+ if ( cell.any() ) {
264
+ cell.focus();
265
+ }
266
+ } );
267
+ }
268
+ else if ( this.c.focus ) {
269
+ dt.cell( this.c.focus ).focus();
270
+ }
271
+ },
272
+
273
+
274
+
275
+
276
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
277
+ * Private methods
278
+ */
279
+
280
+ /**
281
+ * Blur the control
282
+ *
283
+ * @private
284
+ */
285
+ _blur: function ()
286
+ {
287
+ if ( ! this.s.enable || ! this.s.lastFocus ) {
288
+ return;
289
+ }
290
+
291
+ var cell = this.s.lastFocus;
292
+
293
+ $( cell.node() ).removeClass( this.c.className );
294
+ this.s.lastFocus = null;
295
+
296
+ this._emitEvent( 'key-blur', [ this.s.dt, cell ] );
297
+ },
298
+
299
+
300
+ /**
301
+ * Get an array of the column indexes that KeyTable can operate on. This
302
+ * is a merge of the user supplied columns and the visible columns.
303
+ *
304
+ * @private
305
+ */
306
+ _columns: function ()
307
+ {
308
+ var dt = this.s.dt;
309
+ var user = dt.columns( this.c.columns ).indexes();
310
+ var out = [];
311
+
312
+ dt.columns( ':visible' ).every( function (i) {
313
+ if ( user.indexOf( i ) !== -1 ) {
314
+ out.push( i );
315
+ }
316
+ } );
317
+
318
+ return out;
319
+ },
320
+
321
+
322
+ /**
323
+ * Perform excel like navigation for Editor by triggering an edit on key
324
+ * press
325
+ *
326
+ * @param {integer} key Key code for the pressed key
327
+ * @param {object} orig Original event
328
+ * @private
329
+ */
330
+ _editor: function ( key, orig )
331
+ {
332
+ var dt = this.s.dt;
333
+ var editor = this.c.editor;
334
+
335
+ orig.stopPropagation();
336
+
337
+ // Return key should do nothing - for textareas's it would empty the
338
+ // contents
339
+ if ( key === 13 ) {
340
+ orig.preventDefault();
341
+ }
342
+
343
+ editor.inline( this.s.lastFocus.index() );
344
+
345
+ // Excel style - select all text
346
+ var input = $('div.DTE input, div.DTE textarea');
347
+ if ( input.length ) {
348
+ input[0].select();
349
+ }
350
+
351
+ // Reduce the keys the Keys listens for
352
+ dt.keys.enable( 'navigation-only' );
353
+
354
+ // On blur of the navigation submit
355
+ dt.one( 'key-blur.editor', function () {
356
+ if ( editor.displayed() ) {
357
+ editor.submit();
358
+ }
359
+ } );
360
+
361
+ // Restore full key navigation on close
362
+ editor.one( 'close', function () {
363
+ dt.keys.enable( true );
364
+ dt.off( 'key-blur.editor' );
365
+ } );
366
+ },
367
+
368
+
369
+ /**
370
+ * Emit an event on the DataTable for listeners
371
+ *
372
+ * @param {string} name Event name
373
+ * @param {array} args Event arguments
374
+ * @private
375
+ */
376
+ _emitEvent: function ( name, args )
377
+ {
378
+ this.s.dt.iterator( 'table', function ( ctx, i ) {
379
+ $(ctx.nTable).triggerHandler( name, args );
380
+ } );
381
+ },
382
+
383
+
384
+ /**
385
+ * Focus on a particular cell, shifting the table's paging if required
386
+ *
387
+ * @param {DataTables.Api|integer} row Can be given as an API instance that
388
+ * contains the cell to focus or as an integer. As the latter it is the
389
+ * visible row index - NOT the data index
390
+ * @param {integer} [column] Not required if a cell is given as the first
391
+ * parameter. Otherwise this is the column data index for the cell to
392
+ * focus on
393
+ * @param {boolean} [shift=true] Should the viewport be moved to show cell
394
+ * @private
395
+ */
396
+ _focus: function ( row, column, shift )
397
+ {
398
+ var that = this;
399
+ var dt = this.s.dt;
400
+ var pageInfo = dt.page.info();
401
+ var lastFocus = this.s.lastFocus;
402
+
403
+ if ( ! this.s.enable ) {
404
+ return;
405
+ }
406
+
407
+ if ( typeof row !== 'number' ) {
408
+ // Convert the cell to a row and column
409
+ var index = row.index();
410
+ column = index.column;
411
+ row = dt
412
+ .rows( { filter: 'applied', order: 'applied' } )
413
+ .indexes()
414
+ .indexOf( index.row );
415
+
416
+ // For server-side processing normalise the row by adding the start
417
+ // point, since `rows().indexes()` includes only rows that are
418
+ // available at the client-side
419
+ if ( pageInfo.serverSide ) {
420
+ row += pageInfo.start;
421
+ }
422
+ }
423
+
424
+ // Is the row on the current page? If not, we need to redraw to show the
425
+ // page
426
+ if ( pageInfo.length !== -1 && (row < pageInfo.start || row >= pageInfo.start+pageInfo.length) ) {
427
+ this.s.focusDraw = true;
428
+
429
+ dt
430
+ .one( 'draw', function () {
431
+ that.s.focusDraw = false;
432
+ that._focus( row, column );
433
+ } )
434
+ .page( Math.floor( row / pageInfo.length ) )
435
+ .draw( false );
436
+
437
+ return;
438
+ }
439
+
440
+ // In the available columns?
441
+ if ( $.inArray( column, this._columns() ) === -1 ) {
442
+ return;
443
+ }
444
+
445
+ // De-normalise the server-side processing row, so we select the row
446
+ // in its displayed position
447
+ if ( pageInfo.serverSide ) {
448
+ row -= pageInfo.start;
449
+ }
450
+
451
+ var cell = dt.cell( ':eq('+row+')', column, {search: 'applied'} );
452
+
453
+ if ( lastFocus ) {
454
+ // Don't trigger a refocus on the same cell
455
+ if ( lastFocus.node() === cell.node() ) {
456
+ return;
457
+ }
458
+
459
+ // Otherwise blur the old focus
460
+ this._blur();
461
+ }
462
+
463
+ var node = $( cell.node() );
464
+ node.addClass( this.c.className );
465
+
466
+ // Shift viewpoint and page to make cell visible
467
+ if ( shift === undefined || shift === true ) {
468
+ this._scroll( $(window), $(document.body), node, 'offset' );
469
+
470
+ var bodyParent = dt.table().body().parentNode;
471
+ if ( bodyParent !== dt.table().header().parentNode ) {
472
+ var parent = $(bodyParent.parentNode);
473
+
474
+ this._scroll( parent, parent, node, 'position' );
475
+ }
476
+ }
477
+
478
+ // Event and finish
479
+ this.s.lastFocus = cell;
480
+
481
+ this._emitEvent( 'key-focus', [ this.s.dt, cell ] );
482
+ dt.state.save();
483
+ },
484
+
485
+
486
+ /**
487
+ * Handle key press
488
+ *
489
+ * @param {object} e Event
490
+ * @private
491
+ */
492
+ _key: function ( e )
493
+ {
494
+ if ( ! this.s.enable ) {
495
+ return;
496
+ }
497
+
498
+ if ( e.keyCode === 0 || e.ctrlKey || e.metaKey || e.altKey ) {
499
+ return;
500
+ }
501
+
502
+ // If not focused, then there is no key action to take
503
+ var cell = this.s.lastFocus;
504
+ if ( ! cell ) {
505
+ return;
506
+ }
507
+
508
+ var that = this;
509
+ var dt = this.s.dt;
510
+
511
+ // If we are not listening for this key, do nothing
512
+ if ( this.c.keys && $.inArray( e.keyCode, this.c.keys ) === -1 ) {
513
+ return;
514
+ }
515
+
516
+ switch( e.keyCode ) {
517
+ case 9: // tab
518
+ this._shift( e, e.shiftKey ? 'left' : 'right', true );
519
+ break;
520
+
521
+ case 27: // esc
522
+ if ( this.s.blurable && this.s.enable === true ) {
523
+ this._blur();
524
+ }
525
+ break;
526
+
527
+ case 33: // page up (previous page)
528
+ case 34: // page down (next page)
529
+ e.preventDefault();
530
+ var index = dt.cells( {page: 'current'} ).nodes().indexOf( cell.node() );
531
+
532
+ dt
533
+ .one( 'draw', function () {
534
+ var nodes = dt.cells( {page: 'current'} ).nodes();
535
+
536
+ that._focus( dt.cell( index < nodes.length ?
537
+ nodes[ index ] :
538
+ nodes[ nodes.length-1 ]
539
+ ) );
540
+ } )
541
+ .page( e.keyCode === 33 ? 'previous' : 'next' )
542
+ .draw( false );
543
+ break;
544
+
545
+ case 35: // end (end of current page)
546
+ case 36: // home (start of current page)
547
+ e.preventDefault();
548
+ var indexes = dt.cells( {page: 'current'} ).indexes();
549
+
550
+ this._focus( dt.cell(
551
+ indexes[ e.keyCode === 35 ? indexes.length-1 : 0 ]
552
+ ) );
553
+ break;
554
+
555
+ case 37: // left arrow
556
+ this._shift( e, 'left' );
557
+ break;
558
+
559
+ case 38: // up arrow
560
+ this._shift( e, 'up' );
561
+ break;
562
+
563
+ case 39: // right arrow
564
+ this._shift( e, 'right' );
565
+ break;
566
+
567
+ case 40: // down arrow
568
+ this._shift( e, 'down' );
569
+ break;
570
+
571
+ default:
572
+ // Everything else - pass through only when fully enabled
573
+ if ( this.s.enable === true ) {
574
+ this._emitEvent( 'key', [ dt, e.keyCode, this.s.lastFocus, e ] );
575
+ }
576
+ break;
577
+ }
578
+ },
579
+
580
+
581
+ /**
582
+ * Scroll a container to make a cell visible in it. This can be used for
583
+ * both DataTables scrolling and native window scrolling.
584
+ *
585
+ * @param {jQuery} container Scrolling container
586
+ * @param {jQuery} scroller Item being scrolled
587
+ * @param {jQuery} cell Cell in the scroller
588
+ * @param {string} posOff `position` or `offset` - which to use for the
589
+ * calculation. `offset` for the document, otherwise `position`
590
+ * @private
591
+ */
592
+ _scroll: function ( container, scroller, cell, posOff )
593
+ {
594
+ var offset = cell[posOff]();
595
+ var height = cell.outerHeight();
596
+ var width = cell.outerWidth();
597
+
598
+ var scrollTop = scroller.scrollTop();
599
+ var scrollLeft = scroller.scrollLeft();
600
+ var containerHeight = container.height();
601
+ var containerWidth = container.width();
602
+
603
+ // Top correction
604
+ if ( offset.top < scrollTop ) {
605
+ scroller.scrollTop( offset.top );
606
+ }
607
+
608
+ // Left correction
609
+ if ( offset.left < scrollLeft ) {
610
+ scroller.scrollLeft( offset.left );
611
+ }
612
+
613
+ // Bottom correction
614
+ if ( offset.top + height > scrollTop + containerHeight && height < containerHeight ) {
615
+ scroller.scrollTop( offset.top + height - containerHeight );
616
+ }
617
+
618
+ // Right correction
619
+ if ( offset.left + width > scrollLeft + containerWidth && width < containerWidth ) {
620
+ scroller.scrollLeft( offset.left + width - containerWidth );
621
+ }
622
+ },
623
+
624
+
625
+ /**
626
+ * Calculate a single offset movement in the table - up, down, left and
627
+ * right and then perform the focus if possible
628
+ *
629
+ * @param {object} e Event object
630
+ * @param {string} direction Movement direction
631
+ * @param {boolean} keyBlurable `true` if the key press can result in the
632
+ * table being blurred. This is so arrow keys won't blur the table, but
633
+ * tab will.
634
+ * @private
635
+ */
636
+ _shift: function ( e, direction, keyBlurable )
637
+ {
638
+ var that = this;
639
+ var dt = this.s.dt;
640
+ var pageInfo = dt.page.info();
641
+ var rows = pageInfo.recordsDisplay;
642
+ var currentCell = this.s.lastFocus;
643
+ var columns = this._columns();
644
+
645
+ if ( ! currentCell ) {
646
+ return;
647
+ }
648
+
649
+ var currRow = dt
650
+ .rows( { filter: 'applied', order: 'applied' } )
651
+ .indexes()
652
+ .indexOf( currentCell.index().row );
653
+
654
+ // When server-side processing, `rows().indexes()` only gives the rows
655
+ // that are available at the client-side, so we need to normalise the
656
+ // row's current position by the display start point
657
+ if ( pageInfo.serverSide ) {
658
+ currRow += pageInfo.start;
659
+ }
660
+
661
+ var currCol = dt
662
+ .columns( columns )
663
+ .indexes()
664
+ .indexOf( currentCell.index().column );
665
+
666
+ var
667
+ row = currRow,
668
+ column = columns[ currCol ]; // row is the display, column is an index
669
+
670
+ if ( direction === 'right' ) {
671
+ if ( currCol >= columns.length - 1 ) {
672
+ row++;
673
+ column = columns[0];
674
+ }
675
+ else {
676
+ column = columns[ currCol+1 ];
677
+ }
678
+ }
679
+ else if ( direction === 'left' ) {
680
+ if ( currCol === 0 ) {
681
+ row--;
682
+ column = columns[ columns.length - 1 ];
683
+ }
684
+ else {
685
+ column = columns[ currCol-1 ];
686
+ }
687
+ }
688
+ else if ( direction === 'up' ) {
689
+ row--;
690
+ }
691
+ else if ( direction === 'down' ) {
692
+ row++;
693
+ }
694
+
695
+ if ( row >= 0 && row < rows && $.inArray( column, columns ) !== -1
696
+ ) {
697
+ e.preventDefault();
698
+
699
+ this._focus( row, column );
700
+ }
701
+ else if ( ! keyBlurable || ! this.c.blurable ) {
702
+ // No new focus, but if the table isn't blurable, then don't loose
703
+ // focus
704
+ e.preventDefault();
705
+ }
706
+ else {
707
+ this._blur();
708
+ }
709
+ },
710
+
711
+
712
+ /**
713
+ * Create a hidden input element that can receive focus on behalf of the
714
+ * table
715
+ *
716
+ * @private
717
+ */
718
+ _tabInput: function ()
719
+ {
720
+ var that = this;
721
+ var dt = this.s.dt;
722
+ var tabIndex = this.c.tabIndex !== null ?
723
+ this.c.tabIndex :
724
+ dt.settings()[0].iTabIndex;
725
+
726
+ if ( tabIndex == -1 ) {
727
+ return;
728
+ }
729
+
730
+ var div = $('<div><input type="text" tabindex="'+tabIndex+'"/></div>')
731
+ .css( {
732
+ position: 'absolute',
733
+ height: 1,
734
+ width: 0,
735
+ overflow: 'hidden'
736
+ } )
737
+ .insertBefore( dt.table().node() );
738
+
739
+ div.children().on( 'focus', function () {
740
+ that._focus( dt.cell(':eq(0)', '0:visible', {page: 'current'}) );
741
+ } );
742
+ }
743
+ } );
744
+
745
+
746
+ /**
747
+ * KeyTable default settings for initialisation
748
+ *
749
+ * @namespace
750
+ * @name KeyTable.defaults
751
+ * @static
752
+ */
753
+ KeyTable.defaults = {
754
+ /**
755
+ * Can focus be removed from the table
756
+ * @type {Boolean}
757
+ */
758
+ blurable: true,
759
+
760
+ /**
761
+ * Class to give to the focused cell
762
+ * @type {String}
763
+ */
764
+ className: 'focus',
765
+
766
+ /**
767
+ * Columns that can be focused. This is automatically merged with the
768
+ * visible columns as only visible columns can gain focus.
769
+ * @type {String}
770
+ */
771
+ columns: '', // all
772
+
773
+ /**
774
+ * Editor instance to automatically perform Excel like navigation
775
+ * @type {Editor}
776
+ */
777
+ editor: null,
778
+
779
+ /**
780
+ * Select a cell to automatically select on start up. `null` for no
781
+ * automatic selection
782
+ * @type {cell-selector}
783
+ */
784
+ focus: null,
785
+
786
+ /**
787
+ * Array of keys to listen for
788
+ * @type {null|array}
789
+ */
790
+ keys: null,
791
+
792
+ /**
793
+ * Tab index for where the table should sit in the document's tab flow
794
+ * @type {integer|null}
795
+ */
796
+ tabIndex: null
797
+ };
798
+
799
+
800
+
801
+ KeyTable.version = "2.1.2";
802
+
803
+
804
+ $.fn.dataTable.KeyTable = KeyTable;
805
+ $.fn.DataTable.KeyTable = KeyTable;
806
+
807
+
808
+ DataTable.Api.register( 'cell.blur()', function () {
809
+ return this.iterator( 'table', function (ctx) {
810
+ if ( ctx.keytable ) {
811
+ ctx.keytable.blur();
812
+ }
813
+ } );
814
+ } );
815
+
816
+ DataTable.Api.register( 'cell().focus()', function () {
817
+ return this.iterator( 'cell', function (ctx, row, column) {
818
+ if ( ctx.keytable ) {
819
+ ctx.keytable.focus( row, column );
820
+ }
821
+ } );
822
+ } );
823
+
824
+ DataTable.Api.register( 'keys.disable()', function () {
825
+ return this.iterator( 'table', function (ctx) {
826
+ if ( ctx.keytable ) {
827
+ ctx.keytable.enable( false );
828
+ }
829
+ } );
830
+ } );
831
+
832
+ DataTable.Api.register( 'keys.enable()', function ( opts ) {
833
+ return this.iterator( 'table', function (ctx) {
834
+ if ( ctx.keytable ) {
835
+ ctx.keytable.enable( opts === undefined ? true : opts );
836
+ }
837
+ } );
838
+ } );
839
+
840
+ // Cell selector
841
+ DataTable.ext.selector.cell.push( function ( settings, opts, cells ) {
842
+ var focused = opts.focused;
843
+ var kt = settings.keytable;
844
+ var out = [];
845
+
846
+ if ( ! kt || focused === undefined ) {
847
+ return cells;
848
+ }
849
+
850
+ for ( var i=0, ien=cells.length ; i<ien ; i++ ) {
851
+ if ( (focused === true && kt.focused( cells[i] ) ) ||
852
+ (focused === false && ! kt.focused( cells[i] ) )
853
+ ) {
854
+ out.push( cells[i] );
855
+ }
856
+ }
857
+
858
+ return out;
859
+ } );
860
+
861
+
862
+ // Attach a listener to the document which listens for DataTables initialisation
863
+ // events so we can automatically initialise
864
+ $(document).on( 'preInit.dt.dtk', function (e, settings, json) {
865
+ if ( e.namespace !== 'dt' ) {
866
+ return;
867
+ }
868
+
869
+ var init = settings.oInit.keys;
870
+ var defaults = DataTable.defaults.keys;
871
+
872
+ if ( init || defaults ) {
873
+ var opts = $.extend( {}, init, defaults );
874
+
875
+ if ( init !== false ) {
876
+ new KeyTable( settings, opts );
877
+ }
878
+ }
879
+ } );
880
+
881
+
882
+ return KeyTable;
883
+ }));