1 | /*! Select for DataTables 1.3.1
|
---|
2 | * 2015-2019 SpryMedia Ltd - datatables.net/license/mit
|
---|
3 | */
|
---|
4 |
|
---|
5 | /**
|
---|
6 | * @summary Select for DataTables
|
---|
7 | * @description A collection of API methods, events and buttons for DataTables
|
---|
8 | * that provides selection options of the items in a DataTable
|
---|
9 | * @version 1.3.1
|
---|
10 | * @file dataTables.select.js
|
---|
11 | * @author SpryMedia Ltd (www.sprymedia.co.uk)
|
---|
12 | * @contact datatables.net/forums
|
---|
13 | * @copyright Copyright 2015-2019 SpryMedia Ltd.
|
---|
14 | *
|
---|
15 | * This source file is free software, available under the following license:
|
---|
16 | * MIT license - http://datatables.net/license/mit
|
---|
17 | *
|
---|
18 | * This source file is distributed in the hope that it will be useful, but
|
---|
19 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
---|
20 | * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
|
---|
21 | *
|
---|
22 | * For details please refer to: http://www.datatables.net/extensions/select
|
---|
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 | // Version information for debugger
|
---|
55 | DataTable.select = {};
|
---|
56 |
|
---|
57 | DataTable.select.version = '1.3.1';
|
---|
58 |
|
---|
59 | DataTable.select.init = function ( dt ) {
|
---|
60 | var ctx = dt.settings()[0];
|
---|
61 | var init = ctx.oInit.select;
|
---|
62 | var defaults = DataTable.defaults.select;
|
---|
63 | var opts = init === undefined ?
|
---|
64 | defaults :
|
---|
65 | init;
|
---|
66 |
|
---|
67 | // Set defaults
|
---|
68 | var items = 'row';
|
---|
69 | var style = 'api';
|
---|
70 | var blurable = false;
|
---|
71 | var toggleable = true;
|
---|
72 | var info = true;
|
---|
73 | var selector = 'td, th';
|
---|
74 | var className = 'selected';
|
---|
75 | var setStyle = false;
|
---|
76 |
|
---|
77 | ctx._select = {};
|
---|
78 |
|
---|
79 | // Initialisation customisations
|
---|
80 | if ( opts === true ) {
|
---|
81 | style = 'os';
|
---|
82 | setStyle = true;
|
---|
83 | }
|
---|
84 | else if ( typeof opts === 'string' ) {
|
---|
85 | style = opts;
|
---|
86 | setStyle = true;
|
---|
87 | }
|
---|
88 | else if ( $.isPlainObject( opts ) ) {
|
---|
89 | if ( opts.blurable !== undefined ) {
|
---|
90 | blurable = opts.blurable;
|
---|
91 | }
|
---|
92 |
|
---|
93 | if ( opts.toggleable !== undefined ) {
|
---|
94 | toggleable = opts.toggleable;
|
---|
95 | }
|
---|
96 |
|
---|
97 | if ( opts.info !== undefined ) {
|
---|
98 | info = opts.info;
|
---|
99 | }
|
---|
100 |
|
---|
101 | if ( opts.items !== undefined ) {
|
---|
102 | items = opts.items;
|
---|
103 | }
|
---|
104 |
|
---|
105 | if ( opts.style !== undefined ) {
|
---|
106 | style = opts.style;
|
---|
107 | setStyle = true;
|
---|
108 | }
|
---|
109 | else {
|
---|
110 | style = 'os';
|
---|
111 | setStyle = true;
|
---|
112 | }
|
---|
113 |
|
---|
114 | if ( opts.selector !== undefined ) {
|
---|
115 | selector = opts.selector;
|
---|
116 | }
|
---|
117 |
|
---|
118 | if ( opts.className !== undefined ) {
|
---|
119 | className = opts.className;
|
---|
120 | }
|
---|
121 | }
|
---|
122 |
|
---|
123 | dt.select.selector( selector );
|
---|
124 | dt.select.items( items );
|
---|
125 | dt.select.style( style );
|
---|
126 | dt.select.blurable( blurable );
|
---|
127 | dt.select.toggleable( toggleable );
|
---|
128 | dt.select.info( info );
|
---|
129 | ctx._select.className = className;
|
---|
130 |
|
---|
131 |
|
---|
132 | // Sort table based on selected rows. Requires Select Datatables extension
|
---|
133 | $.fn.dataTable.ext.order['select-checkbox'] = function ( settings, col ) {
|
---|
134 | return this.api().column( col, {order: 'index'} ).nodes().map( function ( td ) {
|
---|
135 | if ( settings._select.items === 'row' ) {
|
---|
136 | return $( td ).parent().hasClass( settings._select.className );
|
---|
137 | } else if ( settings._select.items === 'cell' ) {
|
---|
138 | return $( td ).hasClass( settings._select.className );
|
---|
139 | }
|
---|
140 | return false;
|
---|
141 | });
|
---|
142 | };
|
---|
143 |
|
---|
144 | // If the init options haven't enabled select, but there is a selectable
|
---|
145 | // class name, then enable
|
---|
146 | if ( ! setStyle && $( dt.table().node() ).hasClass( 'selectable' ) ) {
|
---|
147 | dt.select.style( 'os' );
|
---|
148 | }
|
---|
149 | };
|
---|
150 |
|
---|
151 | /*
|
---|
152 |
|
---|
153 | Select is a collection of API methods, event handlers, event emitters and
|
---|
154 | buttons (for the `Buttons` extension) for DataTables. It provides the following
|
---|
155 | features, with an overview of how they are implemented:
|
---|
156 |
|
---|
157 | ## Selection of rows, columns and cells. Whether an item is selected or not is
|
---|
158 | stored in:
|
---|
159 |
|
---|
160 | * rows: a `_select_selected` property which contains a boolean value of the
|
---|
161 | DataTables' `aoData` object for each row
|
---|
162 | * columns: a `_select_selected` property which contains a boolean value of the
|
---|
163 | DataTables' `aoColumns` object for each column
|
---|
164 | * cells: a `_selected_cells` property which contains an array of boolean values
|
---|
165 | of the `aoData` object for each row. The array is the same length as the
|
---|
166 | columns array, with each element of it representing a cell.
|
---|
167 |
|
---|
168 | This method of using boolean flags allows Select to operate when nodes have not
|
---|
169 | been created for rows / cells (DataTables' defer rendering feature).
|
---|
170 |
|
---|
171 | ## API methods
|
---|
172 |
|
---|
173 | A range of API methods are available for triggering selection and de-selection
|
---|
174 | of rows. Methods are also available to configure the selection events that can
|
---|
175 | be triggered by an end user (such as which items are to be selected). To a large
|
---|
176 | extent, these of API methods *is* Select. It is basically a collection of helper
|
---|
177 | functions that can be used to select items in a DataTable.
|
---|
178 |
|
---|
179 | Configuration of select is held in the object `_select` which is attached to the
|
---|
180 | DataTables settings object on initialisation. Select being available on a table
|
---|
181 | is not optional when Select is loaded, but its default is for selection only to
|
---|
182 | be available via the API - so the end user wouldn't be able to select rows
|
---|
183 | without additional configuration.
|
---|
184 |
|
---|
185 | The `_select` object contains the following properties:
|
---|
186 |
|
---|
187 | ```
|
---|
188 | {
|
---|
189 | items:string - Can be `rows`, `columns` or `cells`. Defines what item
|
---|
190 | will be selected if the user is allowed to activate row
|
---|
191 | selection using the mouse.
|
---|
192 | style:string - Can be `none`, `single`, `multi` or `os`. Defines the
|
---|
193 | interaction style when selecting items
|
---|
194 | blurable:boolean - If row selection can be cleared by clicking outside of
|
---|
195 | the table
|
---|
196 | toggleable:boolean - If row selection can be cancelled by repeated clicking
|
---|
197 | on the row
|
---|
198 | info:boolean - If the selection summary should be shown in the table
|
---|
199 | information elements
|
---|
200 | }
|
---|
201 | ```
|
---|
202 |
|
---|
203 | In addition to the API methods, Select also extends the DataTables selector
|
---|
204 | options for rows, columns and cells adding a `selected` option to the selector
|
---|
205 | options object, allowing the developer to select only selected items or
|
---|
206 | unselected items.
|
---|
207 |
|
---|
208 | ## Mouse selection of items
|
---|
209 |
|
---|
210 | Clicking on items can be used to select items. This is done by a simple event
|
---|
211 | handler that will select the items using the API methods.
|
---|
212 |
|
---|
213 | */
|
---|
214 |
|
---|
215 |
|
---|
216 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
---|
217 | * Local functions
|
---|
218 | */
|
---|
219 |
|
---|
220 | /**
|
---|
221 | * Add one or more cells to the selection when shift clicking in OS selection
|
---|
222 | * style cell selection.
|
---|
223 | *
|
---|
224 | * Cell range is more complicated than row and column as we want to select
|
---|
225 | * in the visible grid rather than by index in sequence. For example, if you
|
---|
226 | * click first in cell 1-1 and then shift click in 2-2 - cells 1-2 and 2-1
|
---|
227 | * should also be selected (and not 1-3, 1-4. etc)
|
---|
228 | *
|
---|
229 | * @param {DataTable.Api} dt DataTable
|
---|
230 | * @param {object} idx Cell index to select to
|
---|
231 | * @param {object} last Cell index to select from
|
---|
232 | * @private
|
---|
233 | */
|
---|
234 | function cellRange( dt, idx, last )
|
---|
235 | {
|
---|
236 | var indexes;
|
---|
237 | var columnIndexes;
|
---|
238 | var rowIndexes;
|
---|
239 | var selectColumns = function ( start, end ) {
|
---|
240 | if ( start > end ) {
|
---|
241 | var tmp = end;
|
---|
242 | end = start;
|
---|
243 | start = tmp;
|
---|
244 | }
|
---|
245 |
|
---|
246 | var record = false;
|
---|
247 | return dt.columns( ':visible' ).indexes().filter( function (i) {
|
---|
248 | if ( i === start ) {
|
---|
249 | record = true;
|
---|
250 | }
|
---|
251 |
|
---|
252 | if ( i === end ) { // not else if, as start might === end
|
---|
253 | record = false;
|
---|
254 | return true;
|
---|
255 | }
|
---|
256 |
|
---|
257 | return record;
|
---|
258 | } );
|
---|
259 | };
|
---|
260 |
|
---|
261 | var selectRows = function ( start, end ) {
|
---|
262 | var indexes = dt.rows( { search: 'applied' } ).indexes();
|
---|
263 |
|
---|
264 | // Which comes first - might need to swap
|
---|
265 | if ( indexes.indexOf( start ) > indexes.indexOf( end ) ) {
|
---|
266 | var tmp = end;
|
---|
267 | end = start;
|
---|
268 | start = tmp;
|
---|
269 | }
|
---|
270 |
|
---|
271 | var record = false;
|
---|
272 | return indexes.filter( function (i) {
|
---|
273 | if ( i === start ) {
|
---|
274 | record = true;
|
---|
275 | }
|
---|
276 |
|
---|
277 | if ( i === end ) {
|
---|
278 | record = false;
|
---|
279 | return true;
|
---|
280 | }
|
---|
281 |
|
---|
282 | return record;
|
---|
283 | } );
|
---|
284 | };
|
---|
285 |
|
---|
286 | if ( ! dt.cells( { selected: true } ).any() && ! last ) {
|
---|
287 | // select from the top left cell to this one
|
---|
288 | columnIndexes = selectColumns( 0, idx.column );
|
---|
289 | rowIndexes = selectRows( 0 , idx.row );
|
---|
290 | }
|
---|
291 | else {
|
---|
292 | // Get column indexes between old and new
|
---|
293 | columnIndexes = selectColumns( last.column, idx.column );
|
---|
294 | rowIndexes = selectRows( last.row , idx.row );
|
---|
295 | }
|
---|
296 |
|
---|
297 | indexes = dt.cells( rowIndexes, columnIndexes ).flatten();
|
---|
298 |
|
---|
299 | if ( ! dt.cells( idx, { selected: true } ).any() ) {
|
---|
300 | // Select range
|
---|
301 | dt.cells( indexes ).select();
|
---|
302 | }
|
---|
303 | else {
|
---|
304 | // Deselect range
|
---|
305 | dt.cells( indexes ).deselect();
|
---|
306 | }
|
---|
307 | }
|
---|
308 |
|
---|
309 | /**
|
---|
310 | * Disable mouse selection by removing the selectors
|
---|
311 | *
|
---|
312 | * @param {DataTable.Api} dt DataTable to remove events from
|
---|
313 | * @private
|
---|
314 | */
|
---|
315 | function disableMouseSelection( dt )
|
---|
316 | {
|
---|
317 | var ctx = dt.settings()[0];
|
---|
318 | var selector = ctx._select.selector;
|
---|
319 |
|
---|
320 | $( dt.table().container() )
|
---|
321 | .off( 'mousedown.dtSelect', selector )
|
---|
322 | .off( 'mouseup.dtSelect', selector )
|
---|
323 | .off( 'click.dtSelect', selector );
|
---|
324 |
|
---|
325 | $('body').off( 'click.dtSelect' + _safeId(dt.table().node()) );
|
---|
326 | }
|
---|
327 |
|
---|
328 | /**
|
---|
329 | * Attach mouse listeners to the table to allow mouse selection of items
|
---|
330 | *
|
---|
331 | * @param {DataTable.Api} dt DataTable to remove events from
|
---|
332 | * @private
|
---|
333 | */
|
---|
334 | function enableMouseSelection ( dt )
|
---|
335 | {
|
---|
336 | var container = $( dt.table().container() );
|
---|
337 | var ctx = dt.settings()[0];
|
---|
338 | var selector = ctx._select.selector;
|
---|
339 | var matchSelection;
|
---|
340 |
|
---|
341 | container
|
---|
342 | .on( 'mousedown.dtSelect', selector, function(e) {
|
---|
343 | // Disallow text selection for shift clicking on the table so multi
|
---|
344 | // element selection doesn't look terrible!
|
---|
345 | if ( e.shiftKey || e.metaKey || e.ctrlKey ) {
|
---|
346 | container
|
---|
347 | .css( '-moz-user-select', 'none' )
|
---|
348 | .one('selectstart.dtSelect', selector, function () {
|
---|
349 | return false;
|
---|
350 | } );
|
---|
351 | }
|
---|
352 |
|
---|
353 | if ( window.getSelection ) {
|
---|
354 | matchSelection = window.getSelection();
|
---|
355 | }
|
---|
356 | } )
|
---|
357 | .on( 'mouseup.dtSelect', selector, function() {
|
---|
358 | // Allow text selection to occur again, Mozilla style (tested in FF
|
---|
359 | // 35.0.1 - still required)
|
---|
360 | container.css( '-moz-user-select', '' );
|
---|
361 | } )
|
---|
362 | .on( 'click.dtSelect', selector, function ( e ) {
|
---|
363 | var items = dt.select.items();
|
---|
364 | var idx;
|
---|
365 |
|
---|
366 | // If text was selected (click and drag), then we shouldn't change
|
---|
367 | // the row's selected state
|
---|
368 | if ( matchSelection ) {
|
---|
369 | var selection = window.getSelection();
|
---|
370 |
|
---|
371 | // If the element that contains the selection is not in the table, we can ignore it
|
---|
372 | // This can happen if the developer selects text from the click event
|
---|
373 | if ( ! selection.anchorNode || $(selection.anchorNode).closest('table')[0] === dt.table().node() ) {
|
---|
374 | if ( selection !== matchSelection ) {
|
---|
375 | return;
|
---|
376 | }
|
---|
377 | }
|
---|
378 | }
|
---|
379 |
|
---|
380 | var ctx = dt.settings()[0];
|
---|
381 | var wrapperClass = $.trim(dt.settings()[0].oClasses.sWrapper).replace(/ +/g, '.');
|
---|
382 |
|
---|
383 | // Ignore clicks inside a sub-table
|
---|
384 | if ( $(e.target).closest('div.'+wrapperClass)[0] != dt.table().container() ) {
|
---|
385 | return;
|
---|
386 | }
|
---|
387 |
|
---|
388 | var cell = dt.cell( $(e.target).closest('td, th') );
|
---|
389 |
|
---|
390 | // Check the cell actually belongs to the host DataTable (so child
|
---|
391 | // rows, etc, are ignored)
|
---|
392 | if ( ! cell.any() ) {
|
---|
393 | return;
|
---|
394 | }
|
---|
395 |
|
---|
396 | var event = $.Event('user-select.dt');
|
---|
397 | eventTrigger( dt, event, [ items, cell, e ] );
|
---|
398 |
|
---|
399 | if ( event.isDefaultPrevented() ) {
|
---|
400 | return;
|
---|
401 | }
|
---|
402 |
|
---|
403 | var cellIndex = cell.index();
|
---|
404 | if ( items === 'row' ) {
|
---|
405 | idx = cellIndex.row;
|
---|
406 | typeSelect( e, dt, ctx, 'row', idx );
|
---|
407 | }
|
---|
408 | else if ( items === 'column' ) {
|
---|
409 | idx = cell.index().column;
|
---|
410 | typeSelect( e, dt, ctx, 'column', idx );
|
---|
411 | }
|
---|
412 | else if ( items === 'cell' ) {
|
---|
413 | idx = cell.index();
|
---|
414 | typeSelect( e, dt, ctx, 'cell', idx );
|
---|
415 | }
|
---|
416 |
|
---|
417 | ctx._select_lastCell = cellIndex;
|
---|
418 | } );
|
---|
419 |
|
---|
420 | // Blurable
|
---|
421 | $('body').on( 'click.dtSelect' + _safeId(dt.table().node()), function ( e ) {
|
---|
422 | if ( ctx._select.blurable ) {
|
---|
423 | // If the click was inside the DataTables container, don't blur
|
---|
424 | if ( $(e.target).parents().filter( dt.table().container() ).length ) {
|
---|
425 | return;
|
---|
426 | }
|
---|
427 |
|
---|
428 | // Ignore elements which have been removed from the DOM (i.e. paging
|
---|
429 | // buttons)
|
---|
430 | if ( $(e.target).parents('html').length === 0 ) {
|
---|
431 | return;
|
---|
432 | }
|
---|
433 |
|
---|
434 | // Don't blur in Editor form
|
---|
435 | if ( $(e.target).parents('div.DTE').length ) {
|
---|
436 | return;
|
---|
437 | }
|
---|
438 |
|
---|
439 | clear( ctx, true );
|
---|
440 | }
|
---|
441 | } );
|
---|
442 | }
|
---|
443 |
|
---|
444 | /**
|
---|
445 | * Trigger an event on a DataTable
|
---|
446 | *
|
---|
447 | * @param {DataTable.Api} api DataTable to trigger events on
|
---|
448 | * @param {boolean} selected true if selected, false if deselected
|
---|
449 | * @param {string} type Item type acting on
|
---|
450 | * @param {boolean} any Require that there are values before
|
---|
451 | * triggering
|
---|
452 | * @private
|
---|
453 | */
|
---|
454 | function eventTrigger ( api, type, args, any )
|
---|
455 | {
|
---|
456 | if ( any && ! api.flatten().length ) {
|
---|
457 | return;
|
---|
458 | }
|
---|
459 |
|
---|
460 | if ( typeof type === 'string' ) {
|
---|
461 | type = type +'.dt';
|
---|
462 | }
|
---|
463 |
|
---|
464 | args.unshift( api );
|
---|
465 |
|
---|
466 | $(api.table().node()).trigger( type, args );
|
---|
467 | }
|
---|
468 |
|
---|
469 | /**
|
---|
470 | * Update the information element of the DataTable showing information about the
|
---|
471 | * items selected. This is done by adding tags to the existing text
|
---|
472 | *
|
---|
473 | * @param {DataTable.Api} api DataTable to update
|
---|
474 | * @private
|
---|
475 | */
|
---|
476 | function info ( api )
|
---|
477 | {
|
---|
478 | var ctx = api.settings()[0];
|
---|
479 |
|
---|
480 | if ( ! ctx._select.info || ! ctx.aanFeatures.i ) {
|
---|
481 | return;
|
---|
482 | }
|
---|
483 |
|
---|
484 | if ( api.select.style() === 'api' ) {
|
---|
485 | return;
|
---|
486 | }
|
---|
487 |
|
---|
488 | var rows = api.rows( { selected: true } ).flatten().length;
|
---|
489 | var columns = api.columns( { selected: true } ).flatten().length;
|
---|
490 | var cells = api.cells( { selected: true } ).flatten().length;
|
---|
491 |
|
---|
492 | var add = function ( el, name, num ) {
|
---|
493 | el.append( $('<span class="select-item"/>').append( api.i18n(
|
---|
494 | 'select.'+name+'s',
|
---|
495 | { _: '%d '+name+'s selected', 0: '', 1: '1 '+name+' selected' },
|
---|
496 | num
|
---|
497 | ) ) );
|
---|
498 | };
|
---|
499 |
|
---|
500 | // Internal knowledge of DataTables to loop over all information elements
|
---|
501 | $.each( ctx.aanFeatures.i, function ( i, el ) {
|
---|
502 | el = $(el);
|
---|
503 |
|
---|
504 | var output = $('<span class="select-info"/>');
|
---|
505 | add( output, 'row', rows );
|
---|
506 | add( output, 'column', columns );
|
---|
507 | add( output, 'cell', cells );
|
---|
508 |
|
---|
509 | var exisiting = el.children('span.select-info');
|
---|
510 | if ( exisiting.length ) {
|
---|
511 | exisiting.remove();
|
---|
512 | }
|
---|
513 |
|
---|
514 | if ( output.text() !== '' ) {
|
---|
515 | el.append( output );
|
---|
516 | }
|
---|
517 | } );
|
---|
518 | }
|
---|
519 |
|
---|
520 | /**
|
---|
521 | * Initialisation of a new table. Attach event handlers and callbacks to allow
|
---|
522 | * Select to operate correctly.
|
---|
523 | *
|
---|
524 | * This will occur _after_ the initial DataTables initialisation, although
|
---|
525 | * before Ajax data is rendered, if there is ajax data
|
---|
526 | *
|
---|
527 | * @param {DataTable.settings} ctx Settings object to operate on
|
---|
528 | * @private
|
---|
529 | */
|
---|
530 | function init ( ctx ) {
|
---|
531 | var api = new DataTable.Api( ctx );
|
---|
532 |
|
---|
533 | // Row callback so that classes can be added to rows and cells if the item
|
---|
534 | // was selected before the element was created. This will happen with the
|
---|
535 | // `deferRender` option enabled.
|
---|
536 | //
|
---|
537 | // This method of attaching to `aoRowCreatedCallback` is a hack until
|
---|
538 | // DataTables has proper events for row manipulation If you are reviewing
|
---|
539 | // this code to create your own plug-ins, please do not do this!
|
---|
540 | ctx.aoRowCreatedCallback.push( {
|
---|
541 | fn: function ( row, data, index ) {
|
---|
542 | var i, ien;
|
---|
543 | var d = ctx.aoData[ index ];
|
---|
544 |
|
---|
545 | // Row
|
---|
546 | if ( d._select_selected ) {
|
---|
547 | $( row ).addClass( ctx._select.className );
|
---|
548 | }
|
---|
549 |
|
---|
550 | // Cells and columns - if separated out, we would need to do two
|
---|
551 | // loops, so it makes sense to combine them into a single one
|
---|
552 | for ( i=0, ien=ctx.aoColumns.length ; i<ien ; i++ ) {
|
---|
553 | if ( ctx.aoColumns[i]._select_selected || (d._selected_cells && d._selected_cells[i]) ) {
|
---|
554 | $(d.anCells[i]).addClass( ctx._select.className );
|
---|
555 | }
|
---|
556 | }
|
---|
557 | },
|
---|
558 | sName: 'select-deferRender'
|
---|
559 | } );
|
---|
560 |
|
---|
561 | // On Ajax reload we want to reselect all rows which are currently selected,
|
---|
562 | // if there is an rowId (i.e. a unique value to identify each row with)
|
---|
563 | api.on( 'preXhr.dt.dtSelect', function () {
|
---|
564 | // note that column selection doesn't need to be cached and then
|
---|
565 | // reselected, as they are already selected
|
---|
566 | var rows = api.rows( { selected: true } ).ids( true ).filter( function ( d ) {
|
---|
567 | return d !== undefined;
|
---|
568 | } );
|
---|
569 |
|
---|
570 | var cells = api.cells( { selected: true } ).eq(0).map( function ( cellIdx ) {
|
---|
571 | var id = api.row( cellIdx.row ).id( true );
|
---|
572 | return id ?
|
---|
573 | { row: id, column: cellIdx.column } :
|
---|
574 | undefined;
|
---|
575 | } ).filter( function ( d ) {
|
---|
576 | return d !== undefined;
|
---|
577 | } );
|
---|
578 |
|
---|
579 | // On the next draw, reselect the currently selected items
|
---|
580 | api.one( 'draw.dt.dtSelect', function () {
|
---|
581 | api.rows( rows ).select();
|
---|
582 |
|
---|
583 | // `cells` is not a cell index selector, so it needs a loop
|
---|
584 | if ( cells.any() ) {
|
---|
585 | cells.each( function ( id ) {
|
---|
586 | api.cells( id.row, id.column ).select();
|
---|
587 | } );
|
---|
588 | }
|
---|
589 | } );
|
---|
590 | } );
|
---|
591 |
|
---|
592 | // Update the table information element with selected item summary
|
---|
593 | api.on( 'draw.dtSelect.dt select.dtSelect.dt deselect.dtSelect.dt info.dt', function () {
|
---|
594 | info( api );
|
---|
595 | } );
|
---|
596 |
|
---|
597 | // Clean up and release
|
---|
598 | api.on( 'destroy.dtSelect', function () {
|
---|
599 | disableMouseSelection( api );
|
---|
600 | api.off( '.dtSelect' );
|
---|
601 | } );
|
---|
602 | }
|
---|
603 |
|
---|
604 | /**
|
---|
605 | * Add one or more items (rows or columns) to the selection when shift clicking
|
---|
606 | * in OS selection style
|
---|
607 | *
|
---|
608 | * @param {DataTable.Api} dt DataTable
|
---|
609 | * @param {string} type Row or column range selector
|
---|
610 | * @param {object} idx Item index to select to
|
---|
611 | * @param {object} last Item index to select from
|
---|
612 | * @private
|
---|
613 | */
|
---|
614 | function rowColumnRange( dt, type, idx, last )
|
---|
615 | {
|
---|
616 | // Add a range of rows from the last selected row to this one
|
---|
617 | var indexes = dt[type+'s']( { search: 'applied' } ).indexes();
|
---|
618 | var idx1 = $.inArray( last, indexes );
|
---|
619 | var idx2 = $.inArray( idx, indexes );
|
---|
620 |
|
---|
621 | if ( ! dt[type+'s']( { selected: true } ).any() && idx1 === -1 ) {
|
---|
622 | // select from top to here - slightly odd, but both Windows and Mac OS
|
---|
623 | // do this
|
---|
624 | indexes.splice( $.inArray( idx, indexes )+1, indexes.length );
|
---|
625 | }
|
---|
626 | else {
|
---|
627 | // reverse so we can shift click 'up' as well as down
|
---|
628 | if ( idx1 > idx2 ) {
|
---|
629 | var tmp = idx2;
|
---|
630 | idx2 = idx1;
|
---|
631 | idx1 = tmp;
|
---|
632 | }
|
---|
633 |
|
---|
634 | indexes.splice( idx2+1, indexes.length );
|
---|
635 | indexes.splice( 0, idx1 );
|
---|
636 | }
|
---|
637 |
|
---|
638 | if ( ! dt[type]( idx, { selected: true } ).any() ) {
|
---|
639 | // Select range
|
---|
640 | dt[type+'s']( indexes ).select();
|
---|
641 | }
|
---|
642 | else {
|
---|
643 | // Deselect range - need to keep the clicked on row selected
|
---|
644 | indexes.splice( $.inArray( idx, indexes ), 1 );
|
---|
645 | dt[type+'s']( indexes ).deselect();
|
---|
646 | }
|
---|
647 | }
|
---|
648 |
|
---|
649 | /**
|
---|
650 | * Clear all selected items
|
---|
651 | *
|
---|
652 | * @param {DataTable.settings} ctx Settings object of the host DataTable
|
---|
653 | * @param {boolean} [force=false] Force the de-selection to happen, regardless
|
---|
654 | * of selection style
|
---|
655 | * @private
|
---|
656 | */
|
---|
657 | function clear( ctx, force )
|
---|
658 | {
|
---|
659 | if ( force || ctx._select.style === 'single' ) {
|
---|
660 | var api = new DataTable.Api( ctx );
|
---|
661 |
|
---|
662 | api.rows( { selected: true } ).deselect();
|
---|
663 | api.columns( { selected: true } ).deselect();
|
---|
664 | api.cells( { selected: true } ).deselect();
|
---|
665 | }
|
---|
666 | }
|
---|
667 |
|
---|
668 | /**
|
---|
669 | * Select items based on the current configuration for style and items.
|
---|
670 | *
|
---|
671 | * @param {object} e Mouse event object
|
---|
672 | * @param {DataTables.Api} dt DataTable
|
---|
673 | * @param {DataTable.settings} ctx Settings object of the host DataTable
|
---|
674 | * @param {string} type Items to select
|
---|
675 | * @param {int|object} idx Index of the item to select
|
---|
676 | * @private
|
---|
677 | */
|
---|
678 | function typeSelect ( e, dt, ctx, type, idx )
|
---|
679 | {
|
---|
680 | var style = dt.select.style();
|
---|
681 | var toggleable = dt.select.toggleable();
|
---|
682 | var isSelected = dt[type]( idx, { selected: true } ).any();
|
---|
683 |
|
---|
684 | if ( isSelected && ! toggleable ) {
|
---|
685 | return;
|
---|
686 | }
|
---|
687 |
|
---|
688 | if ( style === 'os' ) {
|
---|
689 | if ( e.ctrlKey || e.metaKey ) {
|
---|
690 | // Add or remove from the selection
|
---|
691 | dt[type]( idx ).select( ! isSelected );
|
---|
692 | }
|
---|
693 | else if ( e.shiftKey ) {
|
---|
694 | if ( type === 'cell' ) {
|
---|
695 | cellRange( dt, idx, ctx._select_lastCell || null );
|
---|
696 | }
|
---|
697 | else {
|
---|
698 | rowColumnRange( dt, type, idx, ctx._select_lastCell ?
|
---|
699 | ctx._select_lastCell[type] :
|
---|
700 | null
|
---|
701 | );
|
---|
702 | }
|
---|
703 | }
|
---|
704 | else {
|
---|
705 | // No cmd or shift click - deselect if selected, or select
|
---|
706 | // this row only
|
---|
707 | var selected = dt[type+'s']( { selected: true } );
|
---|
708 |
|
---|
709 | if ( isSelected && selected.flatten().length === 1 ) {
|
---|
710 | dt[type]( idx ).deselect();
|
---|
711 | }
|
---|
712 | else {
|
---|
713 | selected.deselect();
|
---|
714 | dt[type]( idx ).select();
|
---|
715 | }
|
---|
716 | }
|
---|
717 | } else if ( style == 'multi+shift' ) {
|
---|
718 | if ( e.shiftKey ) {
|
---|
719 | if ( type === 'cell' ) {
|
---|
720 | cellRange( dt, idx, ctx._select_lastCell || null );
|
---|
721 | }
|
---|
722 | else {
|
---|
723 | rowColumnRange( dt, type, idx, ctx._select_lastCell ?
|
---|
724 | ctx._select_lastCell[type] :
|
---|
725 | null
|
---|
726 | );
|
---|
727 | }
|
---|
728 | }
|
---|
729 | else {
|
---|
730 | dt[ type ]( idx ).select( ! isSelected );
|
---|
731 | }
|
---|
732 | }
|
---|
733 | else {
|
---|
734 | dt[ type ]( idx ).select( ! isSelected );
|
---|
735 | }
|
---|
736 | }
|
---|
737 |
|
---|
738 | function _safeId( node ) {
|
---|
739 | return node.id.replace(/[^a-zA-Z0-9\-\_]/g, '-');
|
---|
740 | }
|
---|
741 |
|
---|
742 |
|
---|
743 |
|
---|
744 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
---|
745 | * DataTables selectors
|
---|
746 | */
|
---|
747 |
|
---|
748 | // row and column are basically identical just assigned to different properties
|
---|
749 | // and checking a different array, so we can dynamically create the functions to
|
---|
750 | // reduce the code size
|
---|
751 | $.each( [
|
---|
752 | { type: 'row', prop: 'aoData' },
|
---|
753 | { type: 'column', prop: 'aoColumns' }
|
---|
754 | ], function ( i, o ) {
|
---|
755 | DataTable.ext.selector[ o.type ].push( function ( settings, opts, indexes ) {
|
---|
756 | var selected = opts.selected;
|
---|
757 | var data;
|
---|
758 | var out = [];
|
---|
759 |
|
---|
760 | if ( selected !== true && selected !== false ) {
|
---|
761 | return indexes;
|
---|
762 | }
|
---|
763 |
|
---|
764 | for ( var i=0, ien=indexes.length ; i<ien ; i++ ) {
|
---|
765 | data = settings[ o.prop ][ indexes[i] ];
|
---|
766 |
|
---|
767 | if ( (selected === true && data._select_selected === true) ||
|
---|
768 | (selected === false && ! data._select_selected )
|
---|
769 | ) {
|
---|
770 | out.push( indexes[i] );
|
---|
771 | }
|
---|
772 | }
|
---|
773 |
|
---|
774 | return out;
|
---|
775 | } );
|
---|
776 | } );
|
---|
777 |
|
---|
778 | DataTable.ext.selector.cell.push( function ( settings, opts, cells ) {
|
---|
779 | var selected = opts.selected;
|
---|
780 | var rowData;
|
---|
781 | var out = [];
|
---|
782 |
|
---|
783 | if ( selected === undefined ) {
|
---|
784 | return cells;
|
---|
785 | }
|
---|
786 |
|
---|
787 | for ( var i=0, ien=cells.length ; i<ien ; i++ ) {
|
---|
788 | rowData = settings.aoData[ cells[i].row ];
|
---|
789 |
|
---|
790 | if ( (selected === true && rowData._selected_cells && rowData._selected_cells[ cells[i].column ] === true) ||
|
---|
791 | (selected === false && ( ! rowData._selected_cells || ! rowData._selected_cells[ cells[i].column ] ) )
|
---|
792 | ) {
|
---|
793 | out.push( cells[i] );
|
---|
794 | }
|
---|
795 | }
|
---|
796 |
|
---|
797 | return out;
|
---|
798 | } );
|
---|
799 |
|
---|
800 |
|
---|
801 |
|
---|
802 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
---|
803 | * DataTables API
|
---|
804 | *
|
---|
805 | * For complete documentation, please refer to the docs/api directory or the
|
---|
806 | * DataTables site
|
---|
807 | */
|
---|
808 |
|
---|
809 | // Local variables to improve compression
|
---|
810 | var apiRegister = DataTable.Api.register;
|
---|
811 | var apiRegisterPlural = DataTable.Api.registerPlural;
|
---|
812 |
|
---|
813 | apiRegister( 'select()', function () {
|
---|
814 | return this.iterator( 'table', function ( ctx ) {
|
---|
815 | DataTable.select.init( new DataTable.Api( ctx ) );
|
---|
816 | } );
|
---|
817 | } );
|
---|
818 |
|
---|
819 | apiRegister( 'select.blurable()', function ( flag ) {
|
---|
820 | if ( flag === undefined ) {
|
---|
821 | return this.context[0]._select.blurable;
|
---|
822 | }
|
---|
823 |
|
---|
824 | return this.iterator( 'table', function ( ctx ) {
|
---|
825 | ctx._select.blurable = flag;
|
---|
826 | } );
|
---|
827 | } );
|
---|
828 |
|
---|
829 | apiRegister( 'select.toggleable()', function ( flag ) {
|
---|
830 | if ( flag === undefined ) {
|
---|
831 | return this.context[0]._select.toggleable;
|
---|
832 | }
|
---|
833 |
|
---|
834 | return this.iterator( 'table', function ( ctx ) {
|
---|
835 | ctx._select.toggleable = flag;
|
---|
836 | } );
|
---|
837 | } );
|
---|
838 |
|
---|
839 | apiRegister( 'select.info()', function ( flag ) {
|
---|
840 | if ( info === undefined ) {
|
---|
841 | return this.context[0]._select.info;
|
---|
842 | }
|
---|
843 |
|
---|
844 | return this.iterator( 'table', function ( ctx ) {
|
---|
845 | ctx._select.info = flag;
|
---|
846 | } );
|
---|
847 | } );
|
---|
848 |
|
---|
849 | apiRegister( 'select.items()', function ( items ) {
|
---|
850 | if ( items === undefined ) {
|
---|
851 | return this.context[0]._select.items;
|
---|
852 | }
|
---|
853 |
|
---|
854 | return this.iterator( 'table', function ( ctx ) {
|
---|
855 | ctx._select.items = items;
|
---|
856 |
|
---|
857 | eventTrigger( new DataTable.Api( ctx ), 'selectItems', [ items ] );
|
---|
858 | } );
|
---|
859 | } );
|
---|
860 |
|
---|
861 | // Takes effect from the _next_ selection. None disables future selection, but
|
---|
862 | // does not clear the current selection. Use the `deselect` methods for that
|
---|
863 | apiRegister( 'select.style()', function ( style ) {
|
---|
864 | if ( style === undefined ) {
|
---|
865 | return this.context[0]._select.style;
|
---|
866 | }
|
---|
867 |
|
---|
868 | return this.iterator( 'table', function ( ctx ) {
|
---|
869 | ctx._select.style = style;
|
---|
870 |
|
---|
871 | if ( ! ctx._select_init ) {
|
---|
872 | init( ctx );
|
---|
873 | }
|
---|
874 |
|
---|
875 | // Add / remove mouse event handlers. They aren't required when only
|
---|
876 | // API selection is available
|
---|
877 | var dt = new DataTable.Api( ctx );
|
---|
878 | disableMouseSelection( dt );
|
---|
879 |
|
---|
880 | if ( style !== 'api' ) {
|
---|
881 | enableMouseSelection( dt );
|
---|
882 | }
|
---|
883 |
|
---|
884 | eventTrigger( new DataTable.Api( ctx ), 'selectStyle', [ style ] );
|
---|
885 | } );
|
---|
886 | } );
|
---|
887 |
|
---|
888 | apiRegister( 'select.selector()', function ( selector ) {
|
---|
889 | if ( selector === undefined ) {
|
---|
890 | return this.context[0]._select.selector;
|
---|
891 | }
|
---|
892 |
|
---|
893 | return this.iterator( 'table', function ( ctx ) {
|
---|
894 | disableMouseSelection( new DataTable.Api( ctx ) );
|
---|
895 |
|
---|
896 | ctx._select.selector = selector;
|
---|
897 |
|
---|
898 | if ( ctx._select.style !== 'api' ) {
|
---|
899 | enableMouseSelection( new DataTable.Api( ctx ) );
|
---|
900 | }
|
---|
901 | } );
|
---|
902 | } );
|
---|
903 |
|
---|
904 |
|
---|
905 |
|
---|
906 | apiRegisterPlural( 'rows().select()', 'row().select()', function ( select ) {
|
---|
907 | var api = this;
|
---|
908 |
|
---|
909 | if ( select === false ) {
|
---|
910 | return this.deselect();
|
---|
911 | }
|
---|
912 |
|
---|
913 | this.iterator( 'row', function ( ctx, idx ) {
|
---|
914 | clear( ctx );
|
---|
915 |
|
---|
916 | ctx.aoData[ idx ]._select_selected = true;
|
---|
917 | $( ctx.aoData[ idx ].nTr ).addClass( ctx._select.className );
|
---|
918 | } );
|
---|
919 |
|
---|
920 | this.iterator( 'table', function ( ctx, i ) {
|
---|
921 | eventTrigger( api, 'select', [ 'row', api[i] ], true );
|
---|
922 | } );
|
---|
923 |
|
---|
924 | return this;
|
---|
925 | } );
|
---|
926 |
|
---|
927 | apiRegisterPlural( 'columns().select()', 'column().select()', function ( select ) {
|
---|
928 | var api = this;
|
---|
929 |
|
---|
930 | if ( select === false ) {
|
---|
931 | return this.deselect();
|
---|
932 | }
|
---|
933 |
|
---|
934 | this.iterator( 'column', function ( ctx, idx ) {
|
---|
935 | clear( ctx );
|
---|
936 |
|
---|
937 | ctx.aoColumns[ idx ]._select_selected = true;
|
---|
938 |
|
---|
939 | var column = new DataTable.Api( ctx ).column( idx );
|
---|
940 |
|
---|
941 | $( column.header() ).addClass( ctx._select.className );
|
---|
942 | $( column.footer() ).addClass( ctx._select.className );
|
---|
943 |
|
---|
944 | column.nodes().to$().addClass( ctx._select.className );
|
---|
945 | } );
|
---|
946 |
|
---|
947 | this.iterator( 'table', function ( ctx, i ) {
|
---|
948 | eventTrigger( api, 'select', [ 'column', api[i] ], true );
|
---|
949 | } );
|
---|
950 |
|
---|
951 | return this;
|
---|
952 | } );
|
---|
953 |
|
---|
954 | apiRegisterPlural( 'cells().select()', 'cell().select()', function ( select ) {
|
---|
955 | var api = this;
|
---|
956 |
|
---|
957 | if ( select === false ) {
|
---|
958 | return this.deselect();
|
---|
959 | }
|
---|
960 |
|
---|
961 | this.iterator( 'cell', function ( ctx, rowIdx, colIdx ) {
|
---|
962 | clear( ctx );
|
---|
963 |
|
---|
964 | var data = ctx.aoData[ rowIdx ];
|
---|
965 |
|
---|
966 | if ( data._selected_cells === undefined ) {
|
---|
967 | data._selected_cells = [];
|
---|
968 | }
|
---|
969 |
|
---|
970 | data._selected_cells[ colIdx ] = true;
|
---|
971 |
|
---|
972 | if ( data.anCells ) {
|
---|
973 | $( data.anCells[ colIdx ] ).addClass( ctx._select.className );
|
---|
974 | }
|
---|
975 | } );
|
---|
976 |
|
---|
977 | this.iterator( 'table', function ( ctx, i ) {
|
---|
978 | eventTrigger( api, 'select', [ 'cell', api[i] ], true );
|
---|
979 | } );
|
---|
980 |
|
---|
981 | return this;
|
---|
982 | } );
|
---|
983 |
|
---|
984 |
|
---|
985 | apiRegisterPlural( 'rows().deselect()', 'row().deselect()', function () {
|
---|
986 | var api = this;
|
---|
987 |
|
---|
988 | this.iterator( 'row', function ( ctx, idx ) {
|
---|
989 | ctx.aoData[ idx ]._select_selected = false;
|
---|
990 | $( ctx.aoData[ idx ].nTr ).removeClass( ctx._select.className );
|
---|
991 | } );
|
---|
992 |
|
---|
993 | this.iterator( 'table', function ( ctx, i ) {
|
---|
994 | eventTrigger( api, 'deselect', [ 'row', api[i] ], true );
|
---|
995 | } );
|
---|
996 |
|
---|
997 | return this;
|
---|
998 | } );
|
---|
999 |
|
---|
1000 | apiRegisterPlural( 'columns().deselect()', 'column().deselect()', function () {
|
---|
1001 | var api = this;
|
---|
1002 |
|
---|
1003 | this.iterator( 'column', function ( ctx, idx ) {
|
---|
1004 | ctx.aoColumns[ idx ]._select_selected = false;
|
---|
1005 |
|
---|
1006 | var api = new DataTable.Api( ctx );
|
---|
1007 | var column = api.column( idx );
|
---|
1008 |
|
---|
1009 | $( column.header() ).removeClass( ctx._select.className );
|
---|
1010 | $( column.footer() ).removeClass( ctx._select.className );
|
---|
1011 |
|
---|
1012 | // Need to loop over each cell, rather than just using
|
---|
1013 | // `column().nodes()` as cells which are individually selected should
|
---|
1014 | // not have the `selected` class removed from them
|
---|
1015 | api.cells( null, idx ).indexes().each( function (cellIdx) {
|
---|
1016 | var data = ctx.aoData[ cellIdx.row ];
|
---|
1017 | var cellSelected = data._selected_cells;
|
---|
1018 |
|
---|
1019 | if ( data.anCells && (! cellSelected || ! cellSelected[ cellIdx.column ]) ) {
|
---|
1020 | $( data.anCells[ cellIdx.column ] ).removeClass( ctx._select.className );
|
---|
1021 | }
|
---|
1022 | } );
|
---|
1023 | } );
|
---|
1024 |
|
---|
1025 | this.iterator( 'table', function ( ctx, i ) {
|
---|
1026 | eventTrigger( api, 'deselect', [ 'column', api[i] ], true );
|
---|
1027 | } );
|
---|
1028 |
|
---|
1029 | return this;
|
---|
1030 | } );
|
---|
1031 |
|
---|
1032 | apiRegisterPlural( 'cells().deselect()', 'cell().deselect()', function () {
|
---|
1033 | var api = this;
|
---|
1034 |
|
---|
1035 | this.iterator( 'cell', function ( ctx, rowIdx, colIdx ) {
|
---|
1036 | var data = ctx.aoData[ rowIdx ];
|
---|
1037 |
|
---|
1038 | data._selected_cells[ colIdx ] = false;
|
---|
1039 |
|
---|
1040 | // Remove class only if the cells exist, and the cell is not column
|
---|
1041 | // selected, in which case the class should remain (since it is selected
|
---|
1042 | // in the column)
|
---|
1043 | if ( data.anCells && ! ctx.aoColumns[ colIdx ]._select_selected ) {
|
---|
1044 | $( data.anCells[ colIdx ] ).removeClass( ctx._select.className );
|
---|
1045 | }
|
---|
1046 | } );
|
---|
1047 |
|
---|
1048 | this.iterator( 'table', function ( ctx, i ) {
|
---|
1049 | eventTrigger( api, 'deselect', [ 'cell', api[i] ], true );
|
---|
1050 | } );
|
---|
1051 |
|
---|
1052 | return this;
|
---|
1053 | } );
|
---|
1054 |
|
---|
1055 |
|
---|
1056 |
|
---|
1057 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
---|
1058 | * Buttons
|
---|
1059 | */
|
---|
1060 | function i18n( label, def ) {
|
---|
1061 | return function (dt) {
|
---|
1062 | return dt.i18n( 'buttons.'+label, def );
|
---|
1063 | };
|
---|
1064 | }
|
---|
1065 |
|
---|
1066 | // Common events with suitable namespaces
|
---|
1067 | function namespacedEvents ( config ) {
|
---|
1068 | var unique = config._eventNamespace;
|
---|
1069 |
|
---|
1070 | return 'draw.dt.DT'+unique+' select.dt.DT'+unique+' deselect.dt.DT'+unique;
|
---|
1071 | }
|
---|
1072 |
|
---|
1073 | function enabled ( dt, config ) {
|
---|
1074 | if ( $.inArray( 'rows', config.limitTo ) !== -1 && dt.rows( { selected: true } ).any() ) {
|
---|
1075 | return true;
|
---|
1076 | }
|
---|
1077 |
|
---|
1078 | if ( $.inArray( 'columns', config.limitTo ) !== -1 && dt.columns( { selected: true } ).any() ) {
|
---|
1079 | return true;
|
---|
1080 | }
|
---|
1081 |
|
---|
1082 | if ( $.inArray( 'cells', config.limitTo ) !== -1 && dt.cells( { selected: true } ).any() ) {
|
---|
1083 | return true;
|
---|
1084 | }
|
---|
1085 |
|
---|
1086 | return false;
|
---|
1087 | }
|
---|
1088 |
|
---|
1089 | var _buttonNamespace = 0;
|
---|
1090 |
|
---|
1091 | $.extend( DataTable.ext.buttons, {
|
---|
1092 | selected: {
|
---|
1093 | text: i18n( 'selected', 'Selected' ),
|
---|
1094 | className: 'buttons-selected',
|
---|
1095 | limitTo: [ 'rows', 'columns', 'cells' ],
|
---|
1096 | init: function ( dt, node, config ) {
|
---|
1097 | var that = this;
|
---|
1098 | config._eventNamespace = '.select'+(_buttonNamespace++);
|
---|
1099 |
|
---|
1100 | // .DT namespace listeners are removed by DataTables automatically
|
---|
1101 | // on table destroy
|
---|
1102 | dt.on( namespacedEvents(config), function () {
|
---|
1103 | that.enable( enabled(dt, config) );
|
---|
1104 | } );
|
---|
1105 |
|
---|
1106 | this.disable();
|
---|
1107 | },
|
---|
1108 | destroy: function ( dt, node, config ) {
|
---|
1109 | dt.off( config._eventNamespace );
|
---|
1110 | }
|
---|
1111 | },
|
---|
1112 | selectedSingle: {
|
---|
1113 | text: i18n( 'selectedSingle', 'Selected single' ),
|
---|
1114 | className: 'buttons-selected-single',
|
---|
1115 | init: function ( dt, node, config ) {
|
---|
1116 | var that = this;
|
---|
1117 | config._eventNamespace = '.select'+(_buttonNamespace++);
|
---|
1118 |
|
---|
1119 | dt.on( namespacedEvents(config), function () {
|
---|
1120 | var count = dt.rows( { selected: true } ).flatten().length +
|
---|
1121 | dt.columns( { selected: true } ).flatten().length +
|
---|
1122 | dt.cells( { selected: true } ).flatten().length;
|
---|
1123 |
|
---|
1124 | that.enable( count === 1 );
|
---|
1125 | } );
|
---|
1126 |
|
---|
1127 | this.disable();
|
---|
1128 | },
|
---|
1129 | destroy: function ( dt, node, config ) {
|
---|
1130 | dt.off( config._eventNamespace );
|
---|
1131 | }
|
---|
1132 | },
|
---|
1133 | selectAll: {
|
---|
1134 | text: i18n( 'selectAll', 'Select all' ),
|
---|
1135 | className: 'buttons-select-all',
|
---|
1136 | action: function () {
|
---|
1137 | var items = this.select.items();
|
---|
1138 | this[ items+'s' ]().select();
|
---|
1139 | }
|
---|
1140 | },
|
---|
1141 | selectNone: {
|
---|
1142 | text: i18n( 'selectNone', 'Deselect all' ),
|
---|
1143 | className: 'buttons-select-none',
|
---|
1144 | action: function () {
|
---|
1145 | clear( this.settings()[0], true );
|
---|
1146 | },
|
---|
1147 | init: function ( dt, node, config ) {
|
---|
1148 | var that = this;
|
---|
1149 | config._eventNamespace = '.select'+(_buttonNamespace++);
|
---|
1150 |
|
---|
1151 | dt.on( namespacedEvents(config), function () {
|
---|
1152 | var count = dt.rows( { selected: true } ).flatten().length +
|
---|
1153 | dt.columns( { selected: true } ).flatten().length +
|
---|
1154 | dt.cells( { selected: true } ).flatten().length;
|
---|
1155 |
|
---|
1156 | that.enable( count > 0 );
|
---|
1157 | } );
|
---|
1158 |
|
---|
1159 | this.disable();
|
---|
1160 | },
|
---|
1161 | destroy: function ( dt, node, config ) {
|
---|
1162 | dt.off( config._eventNamespace );
|
---|
1163 | }
|
---|
1164 | }
|
---|
1165 | } );
|
---|
1166 |
|
---|
1167 | $.each( [ 'Row', 'Column', 'Cell' ], function ( i, item ) {
|
---|
1168 | var lc = item.toLowerCase();
|
---|
1169 |
|
---|
1170 | DataTable.ext.buttons[ 'select'+item+'s' ] = {
|
---|
1171 | text: i18n( 'select'+item+'s', 'Select '+lc+'s' ),
|
---|
1172 | className: 'buttons-select-'+lc+'s',
|
---|
1173 | action: function () {
|
---|
1174 | this.select.items( lc );
|
---|
1175 | },
|
---|
1176 | init: function ( dt ) {
|
---|
1177 | var that = this;
|
---|
1178 |
|
---|
1179 | dt.on( 'selectItems.dt.DT', function ( e, ctx, items ) {
|
---|
1180 | that.active( items === lc );
|
---|
1181 | } );
|
---|
1182 | }
|
---|
1183 | };
|
---|
1184 | } );
|
---|
1185 |
|
---|
1186 |
|
---|
1187 |
|
---|
1188 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
---|
1189 | * Initialisation
|
---|
1190 | */
|
---|
1191 |
|
---|
1192 | // DataTables creation - check if select has been defined in the options. Note
|
---|
1193 | // this required that the table be in the document! If it isn't then something
|
---|
1194 | // needs to trigger this method unfortunately. The next major release of
|
---|
1195 | // DataTables will rework the events and address this.
|
---|
1196 | $(document).on( 'preInit.dt.dtSelect', function (e, ctx) {
|
---|
1197 | if ( e.namespace !== 'dt' ) {
|
---|
1198 | return;
|
---|
1199 | }
|
---|
1200 |
|
---|
1201 | DataTable.select.init( new DataTable.Api( ctx ) );
|
---|
1202 | } );
|
---|
1203 |
|
---|
1204 |
|
---|
1205 | return DataTable.select;
|
---|
1206 | }));
|
---|