| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183 |
- /*! Select for DataTables 1.3.2
- * 2015-2021 SpryMedia Ltd - datatables.net/license/mit
- */
-
- /**
- * @summary Select for DataTables
- * @description A collection of API methods, events and buttons for DataTables
- * that provides selection options of the items in a DataTable
- * @version 1.3.2
- * @file dataTables.select.js
- * @author SpryMedia Ltd (www.sprymedia.co.uk)
- * @contact datatables.net/forums
- * @copyright Copyright 2015-2021 SpryMedia Ltd.
- *
- * This source file is free software, available under the following license:
- * MIT license - http://datatables.net/license/mit
- *
- * This source file is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
- *
- * For details please refer to: http://www.datatables.net/extensions/select
- */
- (function (factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD
- define(['jquery', 'datatables.net'], function ($) {
- return factory($, window, document);
- });
- } else if (typeof exports === 'object') {
- // CommonJS
- module.exports = function (root, $) {
- if (!root) {
- root = window;
- }
-
- if (!$ || !$.fn.dataTable) {
- $ = require('datatables.net')(root, $).$;
- }
-
- return factory($, root, root.document);
- };
- } else {
- // Browser
- factory(jQuery, window, document);
- }
- }(function ($, window, document, undefined) {
- 'use strict';
- var DataTable = $.fn.dataTable;
-
-
- // Version information for debugger
- DataTable.select = {};
-
- DataTable.select.version = '1.3.2';
-
- DataTable.select.init = function (dt) {
- var ctx = dt.settings()[0];
- var init = ctx.oInit.select;
- var defaults = DataTable.defaults.select;
- var opts = init === undefined ?
- defaults :
- init;
-
- // Set defaults
- var items = 'row';
- var style = 'api';
- var blurable = false;
- var toggleable = true;
- var info = true;
- var selector = 'td, th';
- var className = 'selected';
- var setStyle = false;
-
- ctx._select = {};
-
- // Initialisation customisations
- if (opts === true) {
- style = 'os';
- setStyle = true;
- } else if (typeof opts === 'string') {
- style = opts;
- setStyle = true;
- } else if ($.isPlainObject(opts)) {
- if (opts.blurable !== undefined) {
- blurable = opts.blurable;
- }
-
- if (opts.toggleable !== undefined) {
- toggleable = opts.toggleable;
- }
-
- if (opts.info !== undefined) {
- info = opts.info;
- }
-
- if (opts.items !== undefined) {
- items = opts.items;
- }
-
- if (opts.style !== undefined) {
- style = opts.style;
- setStyle = true;
- } else {
- style = 'os';
- setStyle = true;
- }
-
- if (opts.selector !== undefined) {
- selector = opts.selector;
- }
-
- if (opts.className !== undefined) {
- className = opts.className;
- }
- }
-
- dt.select.selector(selector);
- dt.select.items(items);
- dt.select.style(style);
- dt.select.blurable(blurable);
- dt.select.toggleable(toggleable);
- dt.select.info(info);
- ctx._select.className = className;
-
-
- // Sort table based on selected rows. Requires Select Datatables extension
- $.fn.dataTable.ext.order['select-checkbox'] = function (settings, col) {
- return this.api().column(col, {order: 'index'}).nodes().map(function (td) {
- if (settings._select.items === 'row') {
- return $(td).parent().hasClass(settings._select.className);
- } else if (settings._select.items === 'cell') {
- return $(td).hasClass(settings._select.className);
- }
- return false;
- });
- };
-
- // If the init options haven't enabled select, but there is a selectable
- // class name, then enable
- if (!setStyle && $(dt.table().node()).hasClass('selectable')) {
- dt.select.style('os');
- }
- };
-
- /*
-
- Select is a collection of API methods, event handlers, event emitters and
- buttons (for the `Buttons` extension) for DataTables. It provides the following
- features, with an overview of how they are implemented:
-
- ## Selection of rows, columns and cells. Whether an item is selected or not is
- stored in:
-
- * rows: a `_select_selected` property which contains a boolean value of the
- DataTables' `aoData` object for each row
- * columns: a `_select_selected` property which contains a boolean value of the
- DataTables' `aoColumns` object for each column
- * cells: a `_selected_cells` property which contains an array of boolean values
- of the `aoData` object for each row. The array is the same length as the
- columns array, with each element of it representing a cell.
-
- This method of using boolean flags allows Select to operate when nodes have not
- been created for rows / cells (DataTables' defer rendering feature).
-
- ## API methods
-
- A range of API methods are available for triggering selection and de-selection
- of rows. Methods are also available to configure the selection events that can
- be triggered by an end user (such as which items are to be selected). To a large
- extent, these of API methods *is* Select. It is basically a collection of helper
- functions that can be used to select items in a DataTable.
-
- Configuration of select is held in the object `_select` which is attached to the
- DataTables settings object on initialisation. Select being available on a table
- is not optional when Select is loaded, but its default is for selection only to
- be available via the API - so the end user wouldn't be able to select rows
- without additional configuration.
-
- The `_select` object contains the following properties:
-
- ```
- {
- items:string - Can be `rows`, `columns` or `cells`. Defines what item
- will be selected if the user is allowed to activate row
- selection using the mouse.
- style:string - Can be `none`, `single`, `multi` or `os`. Defines the
- interaction style when selecting items
- blurable:boolean - If row selection can be cleared by clicking outside of
- the table
- toggleable:boolean - If row selection can be cancelled by repeated clicking
- on the row
- info:boolean - If the selection summary should be shown in the table
- information elements
- }
- ```
-
- In addition to the API methods, Select also extends the DataTables selector
- options for rows, columns and cells adding a `selected` option to the selector
- options object, allowing the developer to select only selected items or
- unselected items.
-
- ## Mouse selection of items
-
- Clicking on items can be used to select items. This is done by a simple event
- handler that will select the items using the API methods.
-
- */
-
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Local functions
- */
-
- /**
- * Add one or more cells to the selection when shift clicking in OS selection
- * style cell selection.
- *
- * Cell range is more complicated than row and column as we want to select
- * in the visible grid rather than by index in sequence. For example, if you
- * click first in cell 1-1 and then shift click in 2-2 - cells 1-2 and 2-1
- * should also be selected (and not 1-3, 1-4. etc)
- *
- * @param {DataTable.Api} dt DataTable
- * @param {object} idx Cell index to select to
- * @param {object} last Cell index to select from
- * @private
- */
- function cellRange(dt, idx, last) {
- var indexes;
- var columnIndexes;
- var rowIndexes;
- var selectColumns = function (start, end) {
- if (start > end) {
- var tmp = end;
- end = start;
- start = tmp;
- }
-
- var record = false;
- return dt.columns(':visible').indexes().filter(function (i) {
- if (i === start) {
- record = true;
- }
-
- if (i === end) { // not else if, as start might === end
- record = false;
- return true;
- }
-
- return record;
- });
- };
-
- var selectRows = function (start, end) {
- var indexes = dt.rows({search: 'applied'}).indexes();
-
- // Which comes first - might need to swap
- if (indexes.indexOf(start) > indexes.indexOf(end)) {
- var tmp = end;
- end = start;
- start = tmp;
- }
-
- var record = false;
- return indexes.filter(function (i) {
- if (i === start) {
- record = true;
- }
-
- if (i === end) {
- record = false;
- return true;
- }
-
- return record;
- });
- };
-
- if (!dt.cells({selected: true}).any() && !last) {
- // select from the top left cell to this one
- columnIndexes = selectColumns(0, idx.column);
- rowIndexes = selectRows(0, idx.row);
- } else {
- // Get column indexes between old and new
- columnIndexes = selectColumns(last.column, idx.column);
- rowIndexes = selectRows(last.row, idx.row);
- }
-
- indexes = dt.cells(rowIndexes, columnIndexes).flatten();
-
- if (!dt.cells(idx, {selected: true}).any()) {
- // Select range
- dt.cells(indexes).select();
- } else {
- // Deselect range
- dt.cells(indexes).deselect();
- }
- }
-
- /**
- * Disable mouse selection by removing the selectors
- *
- * @param {DataTable.Api} dt DataTable to remove events from
- * @private
- */
- function disableMouseSelection(dt) {
- var ctx = dt.settings()[0];
- var selector = ctx._select.selector;
-
- $(dt.table().container())
- .off('mousedown.dtSelect', selector)
- .off('mouseup.dtSelect', selector)
- .off('click.dtSelect', selector);
-
- $('body').off('click.dtSelect' + _safeId(dt.table().node()));
- }
-
- /**
- * Attach mouse listeners to the table to allow mouse selection of items
- *
- * @param {DataTable.Api} dt DataTable to remove events from
- * @private
- */
- function enableMouseSelection(dt) {
- var container = $(dt.table().container());
- var ctx = dt.settings()[0];
- var selector = ctx._select.selector;
- var matchSelection;
-
- container
- .on('mousedown.dtSelect', selector, function (e) {
- // Disallow text selection for shift clicking on the table so multi
- // element selection doesn't look terrible!
- if (e.shiftKey || e.metaKey || e.ctrlKey) {
- container
- .css('-moz-user-select', 'none')
- .one('selectstart.dtSelect', selector, function () {
- return false;
- });
- }
-
- if (window.getSelection) {
- matchSelection = window.getSelection();
- }
- })
- .on('mouseup.dtSelect', selector, function () {
- // Allow text selection to occur again, Mozilla style (tested in FF
- // 35.0.1 - still required)
- container.css('-moz-user-select', '');
- })
- .on('click.dtSelect', selector, function (e) {
- var items = dt.select.items();
- var idx;
-
- // If text was selected (click and drag), then we shouldn't change
- // the row's selected state
- if (matchSelection) {
- var selection = window.getSelection();
-
- // If the element that contains the selection is not in the table, we can ignore it
- // This can happen if the developer selects text from the click event
- if (!selection.anchorNode || $(selection.anchorNode).closest('table')[0] === dt.table().node()) {
- if (selection !== matchSelection) {
- return;
- }
- }
- }
-
- var ctx = dt.settings()[0];
- var wrapperClass = dt.settings()[0].oClasses.sWrapper.trim().replace(/ +/g, '.');
-
- // Ignore clicks inside a sub-table
- if ($(e.target).closest('div.' + wrapperClass)[0] != dt.table().container()) {
- return;
- }
-
- var cell = dt.cell($(e.target).closest('td, th'));
-
- // Check the cell actually belongs to the host DataTable (so child
- // rows, etc, are ignored)
- if (!cell.any()) {
- return;
- }
-
- var event = $.Event('user-select.dt');
- eventTrigger(dt, event, [items, cell, e]);
-
- if (event.isDefaultPrevented()) {
- return;
- }
-
- var cellIndex = cell.index();
- if (items === 'row') {
- idx = cellIndex.row;
- typeSelect(e, dt, ctx, 'row', idx);
- } else if (items === 'column') {
- idx = cell.index().column;
- typeSelect(e, dt, ctx, 'column', idx);
- } else if (items === 'cell') {
- idx = cell.index();
- typeSelect(e, dt, ctx, 'cell', idx);
- }
-
- ctx._select_lastCell = cellIndex;
- });
-
- // Blurable
- $('body').on('click.dtSelect' + _safeId(dt.table().node()), function (e) {
- if (ctx._select.blurable) {
- // If the click was inside the DataTables container, don't blur
- if ($(e.target).parents().filter(dt.table().container()).length) {
- return;
- }
-
- // Ignore elements which have been removed from the DOM (i.e. paging
- // buttons)
- if ($(e.target).parents('html').length === 0) {
- return;
- }
-
- // Don't blur in Editor form
- if ($(e.target).parents('div.DTE').length) {
- return;
- }
-
- clear(ctx, true);
- }
- });
- }
-
- /**
- * Trigger an event on a DataTable
- *
- * @param {DataTable.Api} api DataTable to trigger events on
- * @param {boolean} selected true if selected, false if deselected
- * @param {string} type Item type acting on
- * @param {boolean} any Require that there are values before
- * triggering
- * @private
- */
- function eventTrigger(api, type, args, any) {
- if (any && !api.flatten().length) {
- return;
- }
-
- if (typeof type === 'string') {
- type = type + '.dt';
- }
-
- args.unshift(api);
-
- $(api.table().node()).trigger(type, args);
- }
-
- /**
- * Update the information element of the DataTable showing information about the
- * items selected. This is done by adding tags to the existing text
- *
- * @param {DataTable.Api} api DataTable to update
- * @private
- */
- function info(api) {
- var ctx = api.settings()[0];
-
- if (!ctx._select.info || !ctx.aanFeatures.i) {
- return;
- }
-
- if (api.select.style() === 'api') {
- return;
- }
-
- var rows = api.rows({selected: true}).flatten().length;
- var columns = api.columns({selected: true}).flatten().length;
- var cells = api.cells({selected: true}).flatten().length;
-
- var add = function (el, name, num) {
- el.append($('<span class="select-item"/>').append(api.i18n(
- 'select.' + name + 's',
- {_: '%d ' + name + 's selected', 0: '', 1: '1 ' + name + ' selected'},
- num
- )));
- };
-
- // Internal knowledge of DataTables to loop over all information elements
- $.each(ctx.aanFeatures.i, function (i, el) {
- el = $(el);
-
- var output = $('<span class="select-info"/>');
- add(output, 'row', rows);
- add(output, 'column', columns);
- add(output, 'cell', cells);
-
- var exisiting = el.children('span.select-info');
- if (exisiting.length) {
- exisiting.remove();
- }
-
- if (output.text() !== '') {
- el.append(output);
- }
- });
- }
-
- /**
- * Initialisation of a new table. Attach event handlers and callbacks to allow
- * Select to operate correctly.
- *
- * This will occur _after_ the initial DataTables initialisation, although
- * before Ajax data is rendered, if there is ajax data
- *
- * @param {DataTable.settings} ctx Settings object to operate on
- * @private
- */
- function init(ctx) {
- var api = new DataTable.Api(ctx);
-
- // Row callback so that classes can be added to rows and cells if the item
- // was selected before the element was created. This will happen with the
- // `deferRender` option enabled.
- //
- // This method of attaching to `aoRowCreatedCallback` is a hack until
- // DataTables has proper events for row manipulation If you are reviewing
- // this code to create your own plug-ins, please do not do this!
- ctx.aoRowCreatedCallback.push({
- fn: function (row, data, index) {
- var i, ien;
- var d = ctx.aoData[index];
-
- // Row
- if (d._select_selected) {
- $(row).addClass(ctx._select.className);
- }
-
- // Cells and columns - if separated out, we would need to do two
- // loops, so it makes sense to combine them into a single one
- for (i = 0, ien = ctx.aoColumns.length; i < ien; i++) {
- if (ctx.aoColumns[i]._select_selected || (d._selected_cells && d._selected_cells[i])) {
- $(d.anCells[i]).addClass(ctx._select.className);
- }
- }
- },
- sName: 'select-deferRender'
- });
-
- // On Ajax reload we want to reselect all rows which are currently selected,
- // if there is an rowId (i.e. a unique value to identify each row with)
- api.on('preXhr.dt.dtSelect', function (e, settings) {
- if (settings !== api.settings()[0]) {
- // Not triggered by our DataTable!
- return;
- }
-
- // note that column selection doesn't need to be cached and then
- // reselected, as they are already selected
- var rows = api.rows({selected: true}).ids(true).filter(function (d) {
- return d !== undefined;
- });
-
- var cells = api.cells({selected: true}).eq(0).map(function (cellIdx) {
- var id = api.row(cellIdx.row).id(true);
- return id ?
- {row: id, column: cellIdx.column} :
- undefined;
- }).filter(function (d) {
- return d !== undefined;
- });
-
- // On the next draw, reselect the currently selected items
- api.one('draw.dt.dtSelect', function () {
- api.rows(rows).select();
-
- // `cells` is not a cell index selector, so it needs a loop
- if (cells.any()) {
- cells.each(function (id) {
- api.cells(id.row, id.column).select();
- });
- }
- });
- });
-
- // Update the table information element with selected item summary
- api.on('draw.dtSelect.dt select.dtSelect.dt deselect.dtSelect.dt info.dt', function () {
- info(api);
- });
-
- // Clean up and release
- api.on('destroy.dtSelect', function () {
- api.rows({selected: true}).deselect();
-
- disableMouseSelection(api);
- api.off('.dtSelect');
- });
- }
-
- /**
- * Add one or more items (rows or columns) to the selection when shift clicking
- * in OS selection style
- *
- * @param {DataTable.Api} dt DataTable
- * @param {string} type Row or column range selector
- * @param {object} idx Item index to select to
- * @param {object} last Item index to select from
- * @private
- */
- function rowColumnRange(dt, type, idx, last) {
- // Add a range of rows from the last selected row to this one
- var indexes = dt[type + 's']({search: 'applied'}).indexes();
- var idx1 = $.inArray(last, indexes);
- var idx2 = $.inArray(idx, indexes);
-
- if (!dt[type + 's']({selected: true}).any() && idx1 === -1) {
- // select from top to here - slightly odd, but both Windows and Mac OS
- // do this
- indexes.splice($.inArray(idx, indexes) + 1, indexes.length);
- } else {
- // reverse so we can shift click 'up' as well as down
- if (idx1 > idx2) {
- var tmp = idx2;
- idx2 = idx1;
- idx1 = tmp;
- }
-
- indexes.splice(idx2 + 1, indexes.length);
- indexes.splice(0, idx1);
- }
-
- if (!dt[type](idx, {selected: true}).any()) {
- // Select range
- dt[type + 's'](indexes).select();
- } else {
- // Deselect range - need to keep the clicked on row selected
- indexes.splice($.inArray(idx, indexes), 1);
- dt[type + 's'](indexes).deselect();
- }
- }
-
- /**
- * Clear all selected items
- *
- * @param {DataTable.settings} ctx Settings object of the host DataTable
- * @param {boolean} [force=false] Force the de-selection to happen, regardless
- * of selection style
- * @private
- */
- function clear(ctx, force) {
- if (force || ctx._select.style === 'single') {
- var api = new DataTable.Api(ctx);
-
- api.rows({selected: true}).deselect();
- api.columns({selected: true}).deselect();
- api.cells({selected: true}).deselect();
- }
- }
-
- /**
- * Select items based on the current configuration for style and items.
- *
- * @param {object} e Mouse event object
- * @param {DataTables.Api} dt DataTable
- * @param {DataTable.settings} ctx Settings object of the host DataTable
- * @param {string} type Items to select
- * @param {int|object} idx Index of the item to select
- * @private
- */
- function typeSelect(e, dt, ctx, type, idx) {
- var style = dt.select.style();
- var toggleable = dt.select.toggleable();
- var isSelected = dt[type](idx, {selected: true}).any();
-
- if (isSelected && !toggleable) {
- return;
- }
-
- if (style === 'os') {
- if (e.ctrlKey || e.metaKey) {
- // Add or remove from the selection
- dt[type](idx).select(!isSelected);
- } else if (e.shiftKey) {
- if (type === 'cell') {
- cellRange(dt, idx, ctx._select_lastCell || null);
- } else {
- rowColumnRange(dt, type, idx, ctx._select_lastCell ?
- ctx._select_lastCell[type] :
- null
- );
- }
- } else {
- // No cmd or shift click - deselect if selected, or select
- // this row only
- var selected = dt[type + 's']({selected: true});
-
- if (isSelected && selected.flatten().length === 1) {
- dt[type](idx).deselect();
- } else {
- selected.deselect();
- dt[type](idx).select();
- }
- }
- } else if (style == 'multi+shift') {
- if (e.shiftKey) {
- if (type === 'cell') {
- cellRange(dt, idx, ctx._select_lastCell || null);
- } else {
- rowColumnRange(dt, type, idx, ctx._select_lastCell ?
- ctx._select_lastCell[type] :
- null
- );
- }
- } else {
- dt[type](idx).select(!isSelected);
- }
- } else {
- dt[type](idx).select(!isSelected);
- }
- }
-
- function _safeId(node) {
- return node.id.replace(/[^a-zA-Z0-9\-\_]/g, '-');
- }
-
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * DataTables selectors
- */
-
- // row and column are basically identical just assigned to different properties
- // and checking a different array, so we can dynamically create the functions to
- // reduce the code size
- $.each([
- {type: 'row', prop: 'aoData'},
- {type: 'column', prop: 'aoColumns'}
- ], function (i, o) {
- DataTable.ext.selector[o.type].push(function (settings, opts, indexes) {
- var selected = opts.selected;
- var data;
- var out = [];
-
- if (selected !== true && selected !== false) {
- return indexes;
- }
-
- for (var i = 0, ien = indexes.length; i < ien; i++) {
- data = settings[o.prop][indexes[i]];
-
- if ((selected === true && data._select_selected === true) ||
- (selected === false && !data._select_selected)
- ) {
- out.push(indexes[i]);
- }
- }
-
- return out;
- });
- });
-
- DataTable.ext.selector.cell.push(function (settings, opts, cells) {
- var selected = opts.selected;
- var rowData;
- var out = [];
-
- if (selected === undefined) {
- return cells;
- }
-
- for (var i = 0, ien = cells.length; i < ien; i++) {
- rowData = settings.aoData[cells[i].row];
-
- if ((selected === true && rowData._selected_cells && rowData._selected_cells[cells[i].column] === true) ||
- (selected === false && (!rowData._selected_cells || !rowData._selected_cells[cells[i].column]))
- ) {
- out.push(cells[i]);
- }
- }
-
- return out;
- });
-
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * DataTables API
- *
- * For complete documentation, please refer to the docs/api directory or the
- * DataTables site
- */
-
- // Local variables to improve compression
- var apiRegister = DataTable.Api.register;
- var apiRegisterPlural = DataTable.Api.registerPlural;
-
- apiRegister('select()', function () {
- return this.iterator('table', function (ctx) {
- DataTable.select.init(new DataTable.Api(ctx));
- });
- });
-
- apiRegister('select.blurable()', function (flag) {
- if (flag === undefined) {
- return this.context[0]._select.blurable;
- }
-
- return this.iterator('table', function (ctx) {
- ctx._select.blurable = flag;
- });
- });
-
- apiRegister('select.toggleable()', function (flag) {
- if (flag === undefined) {
- return this.context[0]._select.toggleable;
- }
-
- return this.iterator('table', function (ctx) {
- ctx._select.toggleable = flag;
- });
- });
-
- apiRegister('select.info()', function (flag) {
- if (flag === undefined) {
- return this.context[0]._select.info;
- }
-
- return this.iterator('table', function (ctx) {
- ctx._select.info = flag;
- });
- });
-
- apiRegister('select.items()', function (items) {
- if (items === undefined) {
- return this.context[0]._select.items;
- }
-
- return this.iterator('table', function (ctx) {
- ctx._select.items = items;
-
- eventTrigger(new DataTable.Api(ctx), 'selectItems', [items]);
- });
- });
-
- // Takes effect from the _next_ selection. None disables future selection, but
- // does not clear the current selection. Use the `deselect` methods for that
- apiRegister('select.style()', function (style) {
- if (style === undefined) {
- return this.context[0]._select.style;
- }
-
- return this.iterator('table', function (ctx) {
- ctx._select.style = style;
-
- if (!ctx._select_init) {
- init(ctx);
- }
-
- // Add / remove mouse event handlers. They aren't required when only
- // API selection is available
- var dt = new DataTable.Api(ctx);
- disableMouseSelection(dt);
-
- if (style !== 'api') {
- enableMouseSelection(dt);
- }
-
- eventTrigger(new DataTable.Api(ctx), 'selectStyle', [style]);
- });
- });
-
- apiRegister('select.selector()', function (selector) {
- if (selector === undefined) {
- return this.context[0]._select.selector;
- }
-
- return this.iterator('table', function (ctx) {
- disableMouseSelection(new DataTable.Api(ctx));
-
- ctx._select.selector = selector;
-
- if (ctx._select.style !== 'api') {
- enableMouseSelection(new DataTable.Api(ctx));
- }
- });
- });
-
-
- apiRegisterPlural('rows().select()', 'row().select()', function (select) {
- var api = this;
-
- if (select === false) {
- return this.deselect();
- }
-
- this.iterator('row', function (ctx, idx) {
- clear(ctx);
-
- ctx.aoData[idx]._select_selected = true;
- $(ctx.aoData[idx].nTr).addClass(ctx._select.className);
- });
-
- this.iterator('table', function (ctx, i) {
- eventTrigger(api, 'select', ['row', api[i]], true);
- });
-
- return this;
- });
-
- apiRegisterPlural('columns().select()', 'column().select()', function (select) {
- var api = this;
-
- if (select === false) {
- return this.deselect();
- }
-
- this.iterator('column', function (ctx, idx) {
- clear(ctx);
-
- ctx.aoColumns[idx]._select_selected = true;
-
- var column = new DataTable.Api(ctx).column(idx);
-
- $(column.header()).addClass(ctx._select.className);
- $(column.footer()).addClass(ctx._select.className);
-
- column.nodes().to$().addClass(ctx._select.className);
- });
-
- this.iterator('table', function (ctx, i) {
- eventTrigger(api, 'select', ['column', api[i]], true);
- });
-
- return this;
- });
-
- apiRegisterPlural('cells().select()', 'cell().select()', function (select) {
- var api = this;
-
- if (select === false) {
- return this.deselect();
- }
-
- this.iterator('cell', function (ctx, rowIdx, colIdx) {
- clear(ctx);
-
- var data = ctx.aoData[rowIdx];
-
- if (data._selected_cells === undefined) {
- data._selected_cells = [];
- }
-
- data._selected_cells[colIdx] = true;
-
- if (data.anCells) {
- $(data.anCells[colIdx]).addClass(ctx._select.className);
- }
- });
-
- this.iterator('table', function (ctx, i) {
- eventTrigger(api, 'select', ['cell', api.cells(api[i]).indexes().toArray()], true);
- });
-
- return this;
- });
-
-
- apiRegisterPlural('rows().deselect()', 'row().deselect()', function () {
- var api = this;
-
- this.iterator('row', function (ctx, idx) {
- ctx.aoData[idx]._select_selected = false;
- ctx._select_lastCell = null;
- $(ctx.aoData[idx].nTr).removeClass(ctx._select.className);
- });
-
- this.iterator('table', function (ctx, i) {
- eventTrigger(api, 'deselect', ['row', api[i]], true);
- });
-
- return this;
- });
-
- apiRegisterPlural('columns().deselect()', 'column().deselect()', function () {
- var api = this;
-
- this.iterator('column', function (ctx, idx) {
- ctx.aoColumns[idx]._select_selected = false;
-
- var api = new DataTable.Api(ctx);
- var column = api.column(idx);
-
- $(column.header()).removeClass(ctx._select.className);
- $(column.footer()).removeClass(ctx._select.className);
-
- // Need to loop over each cell, rather than just using
- // `column().nodes()` as cells which are individually selected should
- // not have the `selected` class removed from them
- api.cells(null, idx).indexes().each(function (cellIdx) {
- var data = ctx.aoData[cellIdx.row];
- var cellSelected = data._selected_cells;
-
- if (data.anCells && (!cellSelected || !cellSelected[cellIdx.column])) {
- $(data.anCells[cellIdx.column]).removeClass(ctx._select.className);
- }
- });
- });
-
- this.iterator('table', function (ctx, i) {
- eventTrigger(api, 'deselect', ['column', api[i]], true);
- });
-
- return this;
- });
-
- apiRegisterPlural('cells().deselect()', 'cell().deselect()', function () {
- var api = this;
-
- this.iterator('cell', function (ctx, rowIdx, colIdx) {
- var data = ctx.aoData[rowIdx];
-
- data._selected_cells[colIdx] = false;
-
- // Remove class only if the cells exist, and the cell is not column
- // selected, in which case the class should remain (since it is selected
- // in the column)
- if (data.anCells && !ctx.aoColumns[colIdx]._select_selected) {
- $(data.anCells[colIdx]).removeClass(ctx._select.className);
- }
- });
-
- this.iterator('table', function (ctx, i) {
- eventTrigger(api, 'deselect', ['cell', api[i]], true);
- });
-
- return this;
- });
-
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Buttons
- */
- function i18n(label, def) {
- return function (dt) {
- return dt.i18n('buttons.' + label, def);
- };
- }
-
- // Common events with suitable namespaces
- function namespacedEvents(config) {
- var unique = config._eventNamespace;
-
- return 'draw.dt.DT' + unique + ' select.dt.DT' + unique + ' deselect.dt.DT' + unique;
- }
-
- function enabled(dt, config) {
- if ($.inArray('rows', config.limitTo) !== -1 && dt.rows({selected: true}).any()) {
- return true;
- }
-
- if ($.inArray('columns', config.limitTo) !== -1 && dt.columns({selected: true}).any()) {
- return true;
- }
-
- if ($.inArray('cells', config.limitTo) !== -1 && dt.cells({selected: true}).any()) {
- return true;
- }
-
- return false;
- }
-
- var _buttonNamespace = 0;
-
- $.extend(DataTable.ext.buttons, {
- selected: {
- text: i18n('selected', 'Selected'),
- className: 'buttons-selected',
- limitTo: ['rows', 'columns', 'cells'],
- init: function (dt, node, config) {
- var that = this;
- config._eventNamespace = '.select' + (_buttonNamespace++);
-
- // .DT namespace listeners are removed by DataTables automatically
- // on table destroy
- dt.on(namespacedEvents(config), function () {
- that.enable(enabled(dt, config));
- });
-
- this.disable();
- },
- destroy: function (dt, node, config) {
- dt.off(config._eventNamespace);
- }
- },
- selectedSingle: {
- text: i18n('selectedSingle', 'Selected single'),
- className: 'buttons-selected-single',
- init: function (dt, node, config) {
- var that = this;
- config._eventNamespace = '.select' + (_buttonNamespace++);
-
- dt.on(namespacedEvents(config), function () {
- var count = dt.rows({selected: true}).flatten().length +
- dt.columns({selected: true}).flatten().length +
- dt.cells({selected: true}).flatten().length;
-
- that.enable(count === 1);
- });
-
- this.disable();
- },
- destroy: function (dt, node, config) {
- dt.off(config._eventNamespace);
- }
- },
- selectAll: {
- text: i18n('selectAll', 'Select all'),
- className: 'buttons-select-all',
- action: function () {
- var items = this.select.items();
- this[items + 's']().select();
- }
- },
- selectNone: {
- text: i18n('selectNone', 'Deselect all'),
- className: 'buttons-select-none',
- action: function () {
- clear(this.settings()[0], true);
- },
- init: function (dt, node, config) {
- var that = this;
- config._eventNamespace = '.select' + (_buttonNamespace++);
-
- dt.on(namespacedEvents(config), function () {
- var count = dt.rows({selected: true}).flatten().length +
- dt.columns({selected: true}).flatten().length +
- dt.cells({selected: true}).flatten().length;
-
- that.enable(count > 0);
- });
-
- this.disable();
- },
- destroy: function (dt, node, config) {
- dt.off(config._eventNamespace);
- }
- }
- });
-
- $.each(['Row', 'Column', 'Cell'], function (i, item) {
- var lc = item.toLowerCase();
-
- DataTable.ext.buttons['select' + item + 's'] = {
- text: i18n('select' + item + 's', 'Select ' + lc + 's'),
- className: 'buttons-select-' + lc + 's',
- action: function () {
- this.select.items(lc);
- },
- init: function (dt) {
- var that = this;
-
- dt.on('selectItems.dt.DT', function (e, ctx, items) {
- that.active(items === lc);
- });
- }
- };
- });
-
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Initialisation
- */
-
- // DataTables creation - check if select has been defined in the options. Note
- // this required that the table be in the document! If it isn't then something
- // needs to trigger this method unfortunately. The next major release of
- // DataTables will rework the events and address this.
- $(document).on('preInit.dt.dtSelect', function (e, ctx) {
- if (e.namespace !== 'dt') {
- return;
- }
-
- DataTable.select.init(new DataTable.Api(ctx));
- });
-
-
- return DataTable.select;
- }));
|