{"version":3,"sourceRoot":"/cv/scripts/DAC0/eng/include/lib","sources":["dataTables.keyTable.js"],"sourcesContent":["/*! KeyTable 2.5.3\r\n * ©2009-2020 SpryMedia Ltd - datatables.net/license\r\n */\r\n\r\n/**\r\n * @summary KeyTable\r\n * @description Spreadsheet like keyboard navigation for DataTables\r\n * @version 2.5.3\r\n * @file dataTables.keyTable.js\r\n * @author SpryMedia Ltd (www.sprymedia.co.uk)\r\n * @contact www.sprymedia.co.uk/contact\r\n * @copyright Copyright 2009-2020 SpryMedia Ltd.\r\n *\r\n * This source file is free software, available under the following license:\r\n * MIT license - http://datatables.net/license/mit\r\n *\r\n * This source file is distributed in the hope that it will be useful, but\r\n * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r\n * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.\r\n *\r\n * For details please refer to: http://www.datatables.net\r\n */\r\n\r\n(function( factory ){\r\n\tif ( typeof define === 'function' && define.amd ) {\r\n\t\t// AMD\r\n\t\tdefine( ['jquery', 'datatables.net'], function ( $ ) {\r\n\t\t\treturn factory( $, window, document );\r\n\t\t} );\r\n\t}\r\n\telse if ( typeof exports === 'object' ) {\r\n\t\t// CommonJS\r\n\t\tmodule.exports = function (root, $) {\r\n\t\t\tif ( ! root ) {\r\n\t\t\t\troot = window;\r\n\t\t\t}\r\n\r\n\t\t\tif ( ! $ || ! $.fn.dataTable ) {\r\n\t\t\t\t$ = require('datatables.net')(root, $).$;\r\n\t\t\t}\r\n\r\n\t\t\treturn factory( $, root, root.document );\r\n\t\t};\r\n\t}\r\n\telse {\r\n\t\t// Browser\r\n\t\tfactory( jQuery, window, document );\r\n\t}\r\n}(function( $, window, document, undefined ) {\r\n'use strict';\r\nvar DataTable = $.fn.dataTable;\r\nvar namespaceCounter = 0;\r\nvar editorNamespaceCounter = 0;\r\n\r\n\r\nvar KeyTable = function ( dt, opts ) {\r\n\t// Sanity check that we are using DataTables 1.10 or newer\r\n\tif ( ! DataTable.versionCheck || ! DataTable.versionCheck( '1.10.8' ) ) {\r\n\t\tthrow 'KeyTable requires DataTables 1.10.8 or newer';\r\n\t}\r\n\r\n\t// User and defaults configuration object\r\n\tthis.c = $.extend( true, {},\r\n\t\tDataTable.defaults.keyTable,\r\n\t\tKeyTable.defaults,\r\n\t\topts\r\n\t);\r\n\r\n\t// Internal settings\r\n\tthis.s = {\r\n\t\t/** @type {DataTable.Api} DataTables' API instance */\r\n\t\tdt: new DataTable.Api( dt ),\r\n\r\n\t\tenable: true,\r\n\r\n\t\t/** @type {bool} Flag for if a draw is triggered by focus */\r\n\t\tfocusDraw: false,\r\n\r\n\t\t/** @type {bool} Flag to indicate when waiting for a draw to happen.\r\n\t\t * Will ignore key presses at this point\r\n\t\t */\r\n\t\twaitingForDraw: false,\r\n\r\n\t\t/** @type {object} Information about the last cell that was focused */\r\n\t\tlastFocus: null,\r\n\r\n\t\t/** @type {string} Unique namespace per instance */\r\n\t\tnamespace: '.keyTable-'+(namespaceCounter++),\r\n\r\n\t\t/** @type {Node} Input element for tabbing into the table */\r\n\t\ttabInput: null\r\n\t};\r\n\r\n\t// DOM items\r\n\tthis.dom = {\r\n\r\n\t};\r\n\r\n\t// Check if row reorder has already been initialised on this table\r\n\tvar settings = this.s.dt.settings()[0];\r\n\tvar exisiting = settings.keytable;\r\n\tif ( exisiting ) {\r\n\t\treturn exisiting;\r\n\t}\r\n\r\n\tsettings.keytable = this;\r\n\tthis._constructor();\r\n};\r\n\r\n\r\n$.extend( KeyTable.prototype, {\r\n\t/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\r\n\t * API methods for DataTables API interface\r\n\t */\r\n\r\n\t/**\r\n\t * Blur the table's cell focus\r\n\t */\r\n\tblur: function ()\r\n\t{\r\n\t\tthis._blur();\r\n\t},\r\n\r\n\t/**\r\n\t * Enable cell focus for the table\r\n\t *\r\n\t * @param {string} state Can be `true`, `false` or `-string navigation-only`\r\n\t */\r\n\tenable: function ( state )\r\n\t{\r\n\t\tthis.s.enable = state;\r\n\t},\r\n\r\n\t/**\r\n\t * Focus on a cell\r\n\t * @param {integer} row Row index\r\n\t * @param {integer} column Column index\r\n\t */\r\n\tfocus: function ( row, column )\r\n\t{\r\n\t\tthis._focus( this.s.dt.cell( row, column ) );\r\n\t},\r\n\r\n\t/**\r\n\t * Is the cell focused\r\n\t * @param {object} cell Cell index to check\r\n\t * @returns {boolean} true if focused, false otherwise\r\n\t */\r\n\tfocused: function ( cell )\r\n\t{\r\n\t\tvar lastFocus = this.s.lastFocus;\r\n\r\n\t\tif ( ! lastFocus ) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tvar lastIdx = this.s.lastFocus.cell.index();\r\n\t\treturn cell.row === lastIdx.row && cell.column === lastIdx.column;\r\n\t},\r\n\r\n\r\n\t/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\r\n\t * Constructor\r\n\t */\r\n\r\n\t/**\r\n\t * Initialise the KeyTable instance\r\n\t *\r\n\t * @private\r\n\t */\r\n\t_constructor: function ()\r\n\t{\r\n\t\tthis._tabInput();\r\n\r\n\t\tvar that = this;\r\n\t\tvar dt = this.s.dt;\r\n\t\tvar table = $( dt.table().node() );\r\n\t\tvar namespace = this.s.namespace;\r\n\t\tvar editorBlock = false;\r\n\r\n\t\t// Need to be able to calculate the cell positions relative to the table\r\n\t\tif ( table.css('position') === 'static' ) {\r\n\t\t\ttable.css( 'position', 'relative' );\r\n\t\t}\r\n\r\n\t\t// Click to focus\r\n\t\t$( dt.table().body() ).on( 'click'+namespace, 'th, td', function (e) {\r\n\t\t\tif ( that.s.enable === false ) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tvar cell = dt.cell( this );\r\n\r\n\t\t\tif ( ! cell.any() ) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tthat._focus( cell, null, false, e );\r\n\t\t} );\r\n\r\n\t\t// Key events\r\n\t\t$( document ).on( 'keydown'+namespace, function (e) {\r\n\t\t\tif ( ! editorBlock && $(dt.table().body()).find($(e.target)).length) { // GLOBYS: do not emit key events when focus is outside of the datatable body\r\n\t\t\t\tthat._key( e );\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t\t// Click blur\r\n\t\tif ( this.c.blurable ) {\r\n\t\t\t$( document ).on( 'mousedown'+namespace, function ( e ) {\r\n\t\t\t\t// Click on the search input will blur focus\r\n\t\t\t\tif ( $(e.target).parents( '.dataTables_filter' ).length ) {\r\n\t\t\t\t\tthat._blur();\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// If the click was inside the DataTables container, don't blur\r\n\t\t\t\tif ( $(e.target).parents().filter( dt.table().container() ).length ) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Don't blur in Editor form\r\n\t\t\t\tif ( $(e.target).parents('div.DTE').length ) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Or an Editor date input\r\n\t\t\t\tif ( $(e.target).parents('div.editor-datetime').length ) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t//If the click was inside the fixed columns container, don't blur\r\n\t\t\t\tif ( $(e.target).parents().filter('.DTFC_Cloned').length ) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthat._blur();\r\n\t\t\t} );\r\n\t\t}\r\n\r\n\t\tif ( this.c.editor ) {\r\n\t\t\tvar editor = this.c.editor;\r\n\r\n\t\t\t// Need to disable KeyTable when the main editor is shown\r\n\t\t\teditor.on( 'open.keyTableMain', function (e, mode, action) {\r\n\t\t\t\tif ( mode !== 'inline' && that.s.enable ) {\r\n\t\t\t\t\tthat.enable( false );\r\n\r\n\t\t\t\t\teditor.one( 'close'+namespace, function () {\r\n\t\t\t\t\t\tthat.enable( true );\r\n\t\t\t\t\t} );\r\n\t\t\t\t}\r\n\t\t\t} );\r\n\r\n\t\t\tif ( this.c.editOnFocus ) {\r\n\t\t\t\tdt.on( 'key-focus'+namespace+' key-refocus'+namespace, function ( e, dt, cell, orig ) {\r\n\t\t\t\t\tthat._editor( null, orig, true );\r\n\t\t\t\t} );\r\n\t\t\t}\r\n\r\n\t\t\t// Activate Editor when a key is pressed (will be ignored, if\r\n\t\t\t// already active).\r\n\t\t\tdt.on( 'key'+namespace, function ( e, dt, key, cell, orig ) {\r\n\t\t\t\tthat._editor( key, orig, false );\r\n\t\t\t} );\r\n\r\n\t\t\t// Active editing on double click - it will already have focus from\r\n\t\t\t// the click event handler above\r\n\t\t\t$( dt.table().body() ).on( 'dblclick'+namespace, 'th, td', function (e) {\r\n\t\t\t\tif ( that.s.enable === false ) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar cell = dt.cell( this );\r\n\r\n\t\t\t\tif ( ! cell.any() ) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( that.s.lastFocus && this !== that.s.lastFocus.cell.node() ) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthat._editor( null, e, true );\r\n\t\t\t} );\r\n\r\n\t\t\t// While Editor is busy processing, we don't want to process any key events\r\n\t\t\teditor\r\n\t\t\t\t.on('preSubmit', function () {\r\n\t\t\t\t\teditorBlock = true;\r\n\t\t\t\t} )\r\n\t\t\t\t.on('preSubmitCancelled', function () {\r\n\t\t\t\t\teditorBlock = false;\r\n\t\t\t\t} )\r\n\t\t\t\t.on('submitComplete', function () {\r\n\t\t\t\t\teditorBlock = false;\r\n\t\t\t\t} );\r\n\t\t}\r\n\r\n\t\t// Stave saving\r\n\t\tif ( dt.settings()[0].oFeatures.bStateSave ) {\r\n\t\t\tdt.on( 'stateSaveParams'+namespace, function (e, s, d) {\r\n\t\t\t\td.keyTable = that.s.lastFocus ?\r\n\t\t\t\t\tthat.s.lastFocus.cell.index() :\r\n\t\t\t\t\tnull;\r\n\t\t\t} );\r\n\t\t}\r\n\r\n\t\tdt.on( 'column-visibility'+namespace, function (e) {\r\n\t\t\tthat._tabInput();\r\n\t\t} );\r\n\r\n dt.on('length' + namespace, (_e, _settings, _newLength, previousStart) => {\r\n let lastFocus = that.s.lastFocus;\r\n if (lastFocus) {\r\n lastFocus.absoluteRow = previousStart + lastFocus.relative.row;\r\n }\r\n });\r\n\r\n // Redraw - retain focus on the current cell\r\n dt.on('draw' + namespace, function (e) {\r\n that._tabInput();\r\n\r\n if (that.s.focusDraw) {\r\n return;\r\n }\r\n\r\n let lastFocus = that.s.lastFocus;\r\n\r\n if (lastFocus) {\r\n const info = dt.page.info();\r\n\r\n if (info.recordsDisplay === 0) {\r\n return;\r\n }\r\n\r\n const relative = lastFocus.relative;\r\n const column = relative.column;\r\n \r\n let row = lastFocus.absoluteRow ?? lastFocus.relative.row + info.start;\r\n\r\n // Reverse if needed\r\n if (row >= info.recordsDisplay) {\r\n row = info.recordsDisplay - 1;\r\n }\r\n\r\n that._focus(row, column, true, e);\r\n\r\n lastFocus.absoluteRow = null;\r\n }\r\n });\r\n\r\n\t\t// Clipboard support\r\n\t\tif ( this.c.clipboard ) {\r\n\t\t\tthis._clipboard();\r\n\t\t}\r\n\r\n\t\tdt.on( 'destroy'+namespace, function () {\r\n\t\t\tthat._blur( true );\r\n\r\n\t\t\t// Event tidy up\r\n\t\t\tdt.off( namespace );\r\n\r\n\t\t\t$( dt.table().body() )\r\n\t\t\t\t.off( 'click'+namespace, 'th, td' )\r\n\t\t\t\t.off( 'dblclick'+namespace, 'th, td' );\r\n\r\n\t\t\t$( document )\r\n\t\t\t\t.off( 'mousedown'+namespace )\r\n\t\t\t\t.off( 'keydown'+namespace )\r\n\t\t\t\t.off( 'copy'+namespace )\r\n\t\t\t\t.off( 'paste'+namespace );\r\n\t\t} );\r\n\r\n\t\t// Initial focus comes from state or options\r\n\t\tvar state = dt.state.loaded();\r\n\r\n\t\tif ( state && state.keyTable ) {\r\n\t\t\t// Wait until init is done\r\n\t\t\tdt.one( 'init', function () {\r\n\t\t\t\tvar cell = dt.cell( state.keyTable );\r\n\r\n\t\t\t\t// Ensure that the saved cell still exists\r\n\t\t\t\tif ( cell.any() ) {\r\n\t\t\t\t\tcell.focus();\r\n\t\t\t\t}\r\n\t\t\t} );\r\n\t\t}\r\n\t\telse if ( this.c.focus ) {\r\n\t\t\tdt.cell( this.c.focus ).focus();\r\n\t\t}\r\n\t},\r\n\r\n\r\n\t/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\r\n\t * Private methods\r\n\t */\r\n\r\n\t/**\r\n\t * Blur the control\r\n\t *\r\n\t * @param {boolean} [noEvents=false] Don't trigger updates / events (for destroying)\r\n\t * @private\r\n\t */\r\n\t_blur: function (noEvents)\r\n\t{\r\n\t\tif ( ! this.s.enable || ! this.s.lastFocus ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tvar cell = this.s.lastFocus.cell;\r\n\r\n\t\t$( cell.node() ).removeClass( this.c.className );\r\n\t\tthis.s.lastFocus = null;\r\n\r\n\t\tif ( ! noEvents ) {\r\n\t\t\tthis._updateFixedColumns(cell.index().column);\r\n\r\n\t\t\tthis._emitEvent( 'key-blur', [ this.s.dt, cell ] );\r\n\t\t}\r\n\t},\r\n\r\n\r\n\t/**\r\n\t * Clipboard interaction handlers\r\n\t *\r\n\t * @private\r\n\t */\r\n\t_clipboard: function () {\r\n\t\tvar dt = this.s.dt;\r\n\t\tvar that = this;\r\n\t\tvar namespace = this.s.namespace;\r\n\r\n\t\t// IE8 doesn't support getting selected text\r\n\t\tif ( ! window.getSelection ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t$(document).on( 'copy'+namespace, function (ejq) {\r\n\t\t\tvar e = ejq.originalEvent;\r\n\t\t\tvar selection = window.getSelection().toString();\r\n\t\t\tvar focused = that.s.lastFocus;\r\n\r\n\t\t\t// Only copy cell text to clipboard if there is no other selection\r\n\t\t\t// and there is a focused cell\r\n\t\t\tif ( ! selection && focused ) {\r\n\t\t\t\te.clipboardData.setData(\r\n\t\t\t\t\t'text/plain',\r\n\t\t\t\t\tfocused.cell.render( that.c.clipboardOrthogonal )\r\n\t\t\t\t);\r\n\t\t\t\te.preventDefault();\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t\t$(document).on( 'paste'+namespace, function (ejq) {\r\n\t\t\tvar e = ejq.originalEvent;\r\n\t\t\tvar focused = that.s.lastFocus;\r\n\t\t\tvar activeEl = document.activeElement;\r\n\t\t\tvar editor = that.c.editor;\r\n\t\t\tvar pastedText;\r\n\r\n\t\t\tif ( focused && (! activeEl || activeEl.nodeName.toLowerCase() === 'body') ) {\r\n\t\t\t\te.preventDefault();\r\n\r\n\t\t\t\tif ( window.clipboardData && window.clipboardData.getData ) {\r\n\t\t\t\t\t// IE\r\n\t\t\t\t\tpastedText = window.clipboardData.getData('Text');\r\n\t\t\t\t}\r\n\t\t\t\telse if ( e.clipboardData && e.clipboardData.getData ) {\r\n\t\t\t\t\t// Everything else\r\n\t\t\t\t\tpastedText = e.clipboardData.getData('text/plain');\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( editor ) {\r\n\t\t\t\t\t// Got Editor - need to activate inline editing,\r\n\t\t\t\t\t// set the value and submit\r\n\t\t\t\t\teditor\r\n\t\t\t\t\t\t.inline( focused.cell.index() )\r\n\t\t\t\t\t\t.set( editor.displayed()[0], pastedText )\r\n\t\t\t\t\t\t.submit();\r\n\t\t\t\t}\r\n\t\t\t\telse {\r\n\t\t\t\t\t// No editor, so just dump the data in\r\n\t\t\t\t\tfocused.cell.data( pastedText );\r\n\t\t\t\t\tdt.draw(false);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} );\r\n\t},\r\n\r\n\r\n\t/**\r\n\t * Get an array of the column indexes that KeyTable can operate on. This\r\n\t * is a merge of the user supplied columns and the visible columns.\r\n\t *\r\n\t * @private\r\n\t */\r\n\t_columns: function ()\r\n\t{\r\n\t\tvar dt = this.s.dt;\r\n\t\tvar user = dt.columns( this.c.columns ).indexes();\r\n\t\tvar out = [];\r\n\r\n\t\tdt.columns( ':visible' ).every( function (i) {\r\n\t\t\tif ( user.indexOf( i ) !== -1 ) {\r\n\t\t\t\tout.push( i );\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t\treturn out;\r\n\t},\r\n\r\n\r\n\t/**\r\n\t * Perform excel like navigation for Editor by triggering an edit on key\r\n\t * press\r\n\t *\r\n\t * @param {integer} key Key code for the pressed key\r\n\t * @param {object} orig Original event\r\n\t * @private\r\n\t */\r\n\t_editor: function ( key, orig, hardEdit )\r\n\t{\r\n\t\t// If nothing focused, we can't take any action\r\n\t\tif (! this.s.lastFocus) {\r\n\t\t\treturn;\t\r\n\t\t}\r\n\r\n\t\tvar that = this;\r\n\t\tvar dt = this.s.dt;\r\n\t\tvar editor = this.c.editor;\r\n\t\tvar editCell = this.s.lastFocus.cell;\r\n\t\tvar namespace = this.s.namespace + 'e' + editorNamespaceCounter++;\r\n\r\n\t\t// Do nothing if there is already an inline edit in this cell\r\n\t\tif ( $('div.DTE', editCell.node()).length ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Don't activate Editor on control key presses\r\n\t\tif ( key !== null && (\r\n\t\t\t(key >= 0x00 && key <= 0x09) ||\r\n\t\t\tkey === 0x0b ||\r\n\t\t\tkey === 0x0c ||\r\n\t\t\t(key >= 0x0e && key <= 0x1f) ||\r\n\t\t\t(key >= 0x70 && key <= 0x7b) ||\r\n\t\t\t(key >= 0x7f && key <= 0x9f)\r\n\t\t) ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\torig.stopPropagation();\r\n\r\n\t\t// Return key should do nothing - for textareas it would empty the\r\n\t\t// contents\r\n\t\tif ( key === 13 ) {\r\n\t\t\torig.preventDefault();\r\n\t\t}\r\n\r\n\t\tvar editInline = function () {\r\n\t\t\teditor\r\n\t\t\t\t.one( 'open'+namespace, function () {\r\n\t\t\t\t\t// Remove cancel open\r\n\t\t\t\t\teditor.off( 'cancelOpen'+namespace );\r\n\r\n\t\t\t\t\t// Excel style - select all text\r\n\t\t\t\t\tif ( ! hardEdit ) {\r\n\t\t\t\t\t\t$('div.DTE_Field_InputControl input, div.DTE_Field_InputControl textarea').select();\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Reduce the keys the Keys listens for\r\n\t\t\t\t\tdt.keys.enable( hardEdit ? 'tab-only' : 'navigation-only' );\r\n\r\n\t\t\t\t\t// On blur of the navigation submit\r\n\t\t\t\t\tdt.on( 'key-blur.editor', function (e, dt, cell) {\r\n\t\t\t\t\t\tif ( editor.displayed() && cell.node() === editCell.node() ) {\r\n\t\t\t\t\t\t\teditor.submit();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t} );\r\n\r\n\t\t\t\t\t// Highlight the cell a different colour on full edit\r\n\t\t\t\t\tif ( hardEdit ) {\r\n\t\t\t\t\t\t$( dt.table().container() ).addClass('dtk-focus-alt');\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// If the dev cancels the submit, we need to return focus\r\n\t\t\t\t\teditor.on( 'preSubmitCancelled'+namespace, function () {\r\n\t\t\t\t\t\tsetTimeout( function () {\r\n\t\t\t\t\t\t\tthat._focus( editCell, null, false );\r\n\t\t\t\t\t\t}, 50 );\r\n\t\t\t\t\t} );\r\n\r\n\t\t\t\t\teditor.on( 'submitUnsuccessful'+namespace, function () {\r\n\t\t\t\t\t\tthat._focus( editCell, null, false );\r\n\t\t\t\t\t} );\r\n\r\n\t\t\t\t\t// Restore full key navigation on close\r\n\t\t\t\t\teditor.one( 'close'+namespace, function () {\r\n\t\t\t\t\t\tdt.keys.enable( true );\r\n\t\t\t\t\t\tdt.off( 'key-blur.editor' );\r\n\t\t\t\t\t\teditor.off( namespace );\r\n\t\t\t\t\t\t$( dt.table().container() ).removeClass('dtk-focus-alt');\r\n\t\t\t\t\t} );\r\n\t\t\t\t} )\r\n\t\t\t\t.one( 'cancelOpen'+namespace, function () {\r\n\t\t\t\t\t// `preOpen` can cancel the display of the form, so it\r\n\t\t\t\t\t// might be that the open event handler isn't needed\r\n\t\t\t\t\teditor.off( namespace );\r\n\t\t\t\t} )\r\n\t\t\t\t.inline( editCell.index() );\r\n\t\t};\r\n\r\n\t\t// Editor 1.7 listens for `return` on keyup, so if return is the trigger\r\n\t\t// key, we need to wait for `keyup` otherwise Editor would just submit\r\n\t\t// the content triggered by this keypress.\r\n\t\tif ( key === 13 ) {\r\n\t\t\thardEdit = true;\r\n\r\n\t\t\t$(document).one( 'keyup', function () { // immediately removed\r\n\t\t\t\teditInline();\r\n\t\t\t} );\r\n\t\t}\r\n\t\telse {\r\n\t\t\teditInline();\r\n\t\t}\r\n\t},\r\n\r\n\r\n\t/**\r\n\t * Emit an event on the DataTable for listeners\r\n\t *\r\n\t * @param {string} name Event name\r\n\t * @param {array} args Event arguments\r\n\t * @private\r\n\t */\r\n\t_emitEvent: function ( name, args )\r\n\t{\r\n\t\tthis.s.dt.iterator( 'table', function ( ctx, i ) {\r\n\t\t\t$(ctx.nTable).triggerHandler( name, args );\r\n\t\t} );\r\n\t},\r\n\r\n\r\n\t/**\r\n\t * Focus on a particular cell, shifting the table's paging if required\r\n\t *\r\n\t * @param {DataTables.Api|integer} row Can be given as an API instance that\r\n\t * contains the cell to focus or as an integer. As the latter it is the\r\n\t * visible row index (from the whole data set) - NOT the data index\r\n\t * @param {integer} [column] Not required if a cell is given as the first\r\n\t * parameter. Otherwise this is the column data index for the cell to\r\n\t * focus on\r\n\t * @param {boolean} [shift=true] Should the viewport be moved to show cell\r\n\t * @private\r\n\t */\r\n\t_focus: function ( row, column, shift, originalEvent )\r\n\t{\r\n\t\tvar that = this;\r\n\t\tvar dt = this.s.dt;\r\n\t\tvar pageInfo = dt.page.info();\r\n\t\tvar lastFocus = this.s.lastFocus;\r\n\r\n\t\tif ( ! originalEvent) {\r\n\t\t\toriginalEvent = null;\r\n\t\t}\r\n\r\n\t\tif ( ! this.s.enable ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( typeof row !== 'number' ) {\r\n\t\t\t// Its an API instance - check that there is actually a row\r\n\t\t\tif ( ! row.any() ) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\t// Convert the cell to a row and column\r\n\t\t\tvar index = row.index();\r\n\t\t\tcolumn = index.column;\r\n\t\t\trow = dt\r\n\t\t\t\t.rows( { filter: 'applied', order: 'applied' } )\r\n\t\t\t\t.indexes()\r\n\t\t\t\t.indexOf( index.row );\r\n\t\t\t\r\n\t\t\t// Don't focus rows that were filtered out.\r\n\t\t\tif ( row < 0 ) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\t// For server-side processing normalise the row by adding the start\r\n\t\t\t// point, since `rows().indexes()` includes only rows that are\r\n\t\t\t// available at the client-side\r\n\t\t\tif ( pageInfo.serverSide ) {\r\n\t\t\t\trow += pageInfo.start;\r\n\t\t\t}\r\n\t\t}\r\n\r\n // Is the row on the current page? If not, we need to redraw to show the\r\n // page\r\n if (pageInfo.length !== -1 && (row < pageInfo.start || row >= pageInfo.start + pageInfo.length)) {\r\n this.s.focusDraw = true;\r\n this.s.waitingForDraw = true;\r\n\r\n setTimeout(() => {\r\n dt\r\n .one('draw', function () {\r\n that.s.focusDraw = false;\r\n that.s.waitingForDraw = false;\r\n that._focus(row, column, undefined, originalEvent);\r\n })\r\n .page(Math.floor(row / pageInfo.length))\r\n .draw(false);\r\n });\r\n\r\n return;\r\n }\r\n\r\n\t\t// In the available columns?\r\n\t\tif ( $.inArray( column, this._columns() ) === -1 ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// De-normalise the server-side processing row, so we select the row\r\n\t\t// in its displayed position\r\n\t\tif ( pageInfo.serverSide ) {\r\n\t\t\trow -= pageInfo.start;\r\n\t\t}\r\n\r\n\t\t// Get the cell from the current position - ignoring any cells which might\r\n\t\t// not have been rendered (therefore can't use `:eq()` selector).\r\n\t\tvar cells = dt.cells( null, column, {search: 'applied', order: 'applied'} ).flatten();\r\n\t\tvar cell = dt.cell( cells[ row ] );\r\n\r\n\t\tif ( lastFocus ) {\r\n\t\t\t// Don't trigger a refocus on the same cell\r\n\t\t\tif ( lastFocus.node === cell.node() ) {\r\n\t\t\t\tthis._emitEvent( 'key-refocus', [ this.s.dt, cell, originalEvent || null ] );\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\t// Otherwise blur the old focus\r\n\t\t\tthis._blur();\r\n\t\t}\r\n\r\n\t\t// Clear focus from other tables\r\n\t\tthis._removeOtherFocus();\r\n\r\n\t\tvar node = $( cell.node() );\r\n\t\tnode.addClass( this.c.className );\r\n\r\n\t\tthis._updateFixedColumns(column);\r\n\r\n\t\t// Shift viewpoint and page to make cell visible\r\n\t\tif ( shift === undefined || shift === true ) {\r\n\t\t\tthis._scroll( $(window), $(document.body), node, 'offset' );\r\n\r\n\t\t\tvar bodyParent = dt.table().body().parentNode;\r\n\t\t\tif ( bodyParent !== dt.table().header().parentNode ) {\r\n\t\t\t\tvar parent = $(bodyParent.parentNode);\r\n\r\n\t\t\t\tthis._scroll( parent, parent, node, 'position' );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Event and finish\r\n this.s.lastFocus = {\r\n cell: cell,\r\n node: cell.node(),\r\n relative: {\r\n\t\t\t\trow: dt.rows( { page: 'current' } ).indexes().indexOf( cell.index().row ),\r\n column: cell.index().column\r\n\t\t\t}\r\n };\r\n\r\n\t\tthis._emitEvent( 'key-focus', [ this.s.dt, cell, originalEvent || null ] );\r\n\t\tdt.state.save();\r\n\t},\r\n\r\n\r\n\t/**\r\n\t * Handle key press\r\n\t *\r\n\t * @param {object} e Event\r\n\t * @private\r\n\t */\r\n\t_key: function ( e )\r\n\t{\r\n\t\t// If we are waiting for a draw to happen from another key event, then\r\n\t\t// do nothing for this new key press.\r\n\t\tif ( this.s.waitingForDraw ) {\r\n\t\t\te.preventDefault();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tvar enable = this.s.enable;\r\n\t\tvar navEnable = enable === true || enable === 'navigation-only';\r\n\t\tif ( ! enable ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( (e.keyCode === 0 || e.ctrlKey || e.metaKey || e.altKey) && !(e.ctrlKey && e.altKey) ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// If not focused, then there is no key action to take\r\n\t\tvar lastFocus = this.s.lastFocus;\r\n\t\t// *** START GLOBYS: If not focused and target element is in the table, place focus on the cell that contains the element ***\r\n\t\tif ( ! lastFocus && $(this.s.dt.table().body()).find($(e.target)).length) {\r\n\t\t\tlastFocus = this.s.dt.cell(function ( idx, data, node ) {\r\n\t\t\t\treturn $(node).find($(e.target)).length\t ?\r\n\t\t\t\t\ttrue : false;\r\n\t\t\t});\r\n\t\t\tif (lastFocus && typeof lastFocus.focus == 'function') {\r\n\t\t\t\tlastFocus.focus();\r\n\t\t\t}\r\n\t\t}\r\n\t\t// *** END GLOBYS ***\r\n\r\n\t\t// And the last focus still exists!\r\n\t\tif ( ! this.s.dt.cell(lastFocus.node).any() ) {\r\n\t\t\tthis.s.lastFocus = null;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tvar that = this;\r\n\t\tvar dt = this.s.dt;\r\n\t\tvar scrolling = this.s.dt.settings()[0].oScroll.sY ? true : false;\r\n\r\n\t\t// If we are not listening for this key, do nothing\r\n\t\tif ( this.c.keys && $.inArray( e.keyCode, this.c.keys ) === -1 ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tswitch( e.keyCode ) {\r\n\t\t\t// *** START GLOBYS - disable tab key handling in keyTable ***\r\n\t\t\t// case 9: // tab\r\n\t\t\t// \t// `enable` can be tab-only\r\n\t\t\t// \tthis._shift( e, e.shiftKey ? 'left' : 'right', true );\r\n\t\t\t// \tbreak;\r\n\t\t\t// *** END GLOBYS ***\r\n\r\n\t\t\tcase 27: // esc\r\n\t\t\t\tif ( this.s.blurable && enable === true ) {\r\n\t\t\t\t\tthis._blur();\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase 33: // page up (previous page)\r\n\t\t\tcase 34: // page down (next page)\r\n\t\t\t\tif ( navEnable && !scrolling ) {\r\n\t\t\t\t\te.preventDefault();\r\n\r\n\t\t\t\t\tdt\r\n\t\t\t\t\t\t.page( e.keyCode === 33 ? 'previous' : 'next' )\r\n\t\t\t\t\t\t.draw( false );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase 35: // end (end of current page)\r\n\t\t\tcase 36: // home (start of current page)\r\n\t\t\t\tif ( navEnable ) {\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t\tvar indexes = dt.cells( {page: 'current'} ).indexes();\r\n\t\t\t\t\tvar colIndexes = this._columns();\r\n\r\n\t\t\t\t\tthis._focus( dt.cell(\r\n\t\t\t\t\t\tindexes[ e.keyCode === 35 ? indexes.length-1 : colIndexes[0] ]\r\n\t\t\t\t\t), null, true, e );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase 37: // left arrow\r\n\t\t\t\tif ( navEnable ) {\r\n\t\t\t\t\tthis._shift( e, 'left' );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase 38: // up arrow\r\n\t\t\t\tif ( navEnable ) {\r\n\t\t\t\t\tthis._shift( e, 'up' );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase 39: // right arrow\r\n\t\t\t\tif ( navEnable ) {\r\n\t\t\t\t\tthis._shift( e, 'right' );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase 40: // down arrow\r\n\t\t\t\tif ( navEnable ) {\r\n\t\t\t\t\tthis._shift( e, 'down' );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase 113: // F2 - Excel like hard edit\r\n\t\t\t\tif ( this.c.editor ) {\r\n\t\t\t\t\tthis._editor(null, e, true);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t// else fallthrough\r\n\r\n\t\t\tdefault:\r\n\t\t\t\t// Everything else - pass through only when fully enabled\r\n\t\t\t\tif ( enable === true ) {\r\n\t\t\t\t\tthis._emitEvent( 'key', [ dt, e.keyCode, this.s.lastFocus.cell, e ] );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t},\r\n\r\n\t/**\r\n\t * Remove focus from all tables other than this one\r\n\t */\r\n\t_removeOtherFocus: function ()\r\n\t{\r\n\t\tvar thisTable = this.s.dt.table().node();\r\n\r\n\t\t$.fn.dataTable.tables({api:true}).iterator('table', function (settings) {\r\n\t\t\tif (this.table().node() !== thisTable) {\r\n\t\t\t\tthis.cell.blur();\r\n\t\t\t}\r\n\t\t});\r\n\t},\r\n\r\n\t/**\r\n\t * Scroll a container to make a cell visible in it. This can be used for\r\n\t * both DataTables scrolling and native window scrolling.\r\n\t *\r\n\t * @param {jQuery} container Scrolling container\r\n\t * @param {jQuery} scroller Item being scrolled\r\n\t * @param {jQuery} cell Cell in the scroller\r\n\t * @param {string} posOff `position` or `offset` - which to use for the\r\n\t * calculation. `offset` for the document, otherwise `position`\r\n\t * @private\r\n\t */\r\n\t_scroll: function ( container, scroller, cell, posOff )\r\n\t{\r\n\t\tvar offset = cell[posOff]();\r\n\t\tvar height = cell.outerHeight();\r\n\t\tvar width = cell.outerWidth();\r\n\r\n\t\tvar scrollTop = scroller.scrollTop();\r\n\t\tvar scrollLeft = scroller.scrollLeft();\r\n\t\tvar containerHeight = container.height();\r\n\t\tvar containerWidth = container.width();\r\n\r\n\t\t// If Scroller is being used, the table can be `position: absolute` and that\r\n\t\t// needs to be taken account of in the offset. If no Scroller, this will be 0\r\n\t\tif ( posOff === 'position' ) {\r\n\t\t\toffset.top += parseInt( cell.closest('table').css('top'), 10 );\r\n\t\t}\r\n\r\n\t\t// Top correction\r\n\t\tif ( offset.top < scrollTop ) {\r\n\t\t\tscroller.scrollTop( offset.top );\r\n\t\t}\r\n\r\n\t\t// Left correction\r\n\t\tif ( offset.left < scrollLeft ) {\r\n\t\t\tscroller.scrollLeft( offset.left );\r\n\t\t}\r\n\r\n\t\t// Bottom correction\r\n\t\tif ( offset.top + height > scrollTop + containerHeight && height < containerHeight ) {\r\n\t\t\tscroller.scrollTop( offset.top + height - containerHeight );\r\n\t\t}\r\n\r\n\t\t// Right correction\r\n\t\tif ( offset.left + width > scrollLeft + containerWidth && width < containerWidth ) {\r\n\t\t\tscroller.scrollLeft( offset.left + width - containerWidth );\r\n\t\t}\r\n\t},\r\n\r\n\r\n\t/**\r\n\t * Calculate a single offset movement in the table - up, down, left and\r\n\t * right and then perform the focus if possible\r\n\t *\r\n\t * @param {object} e Event object\r\n\t * @param {string} direction Movement direction\r\n\t * @param {boolean} keyBlurable `true` if the key press can result in the\r\n\t * table being blurred. This is so arrow keys won't blur the table, but\r\n\t * tab will.\r\n\t * @private\r\n\t */\r\n\t_shift: function ( e, direction, keyBlurable )\r\n\t{\r\n\t\tvar that = this;\r\n\t\tvar dt = this.s.dt;\r\n\t\tvar pageInfo = dt.page.info();\r\n\t\tvar rows = pageInfo.recordsDisplay;\r\n\t\tvar currentCell = this.s.lastFocus.cell;\r\n\t\tvar columns = this._columns();\r\n\r\n\t\tif ( ! currentCell ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tvar currRow = dt\r\n\t\t\t.rows( { filter: 'applied', order: 'applied' } )\r\n\t\t\t.indexes()\r\n\t\t\t.indexOf( currentCell.index().row );\r\n\r\n\t\t// When server-side processing, `rows().indexes()` only gives the rows\r\n\t\t// that are available at the client-side, so we need to normalise the\r\n\t\t// row's current position by the display start point\r\n\t\tif ( pageInfo.serverSide ) {\r\n\t\t\tcurrRow += pageInfo.start;\r\n\t\t}\r\n\r\n\t\tvar currCol = dt\r\n\t\t\t.columns( columns )\r\n\t\t\t.indexes()\r\n\t\t\t.indexOf( currentCell.index().column );\r\n\r\n\t\tvar\r\n\t\t\trow = currRow,\r\n\t\t\tcolumn = columns[ currCol ]; // row is the display, column is an index\r\n\r\n\t\tif ( direction === 'right' ) {\r\n\t\t\tif ( currCol >= columns.length - 1 ) {\r\n\t\t\t\trow++;\r\n\t\t\t\tcolumn = columns[0];\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tcolumn = columns[ currCol+1 ];\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( direction === 'left' ) {\r\n\t\t\tif ( currCol === 0 ) {\r\n\t\t\t\trow--;\r\n\t\t\t\tcolumn = columns[ columns.length - 1 ];\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tcolumn = columns[ currCol-1 ];\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( direction === 'up' ) {\r\n\t\t\trow--;\r\n\t\t}\r\n\t\telse if ( direction === 'down' ) {\r\n\t\t\trow++;\r\n\t\t}\r\n\r\n\t\tif ( row >= 0 && row < rows && $.inArray( column, columns ) !== -1 ) {\r\n\t\t\tif (e) {\r\n\t\t\t\te.preventDefault();\r\n\t\t\t}\r\n\r\n\t\t\tthis._focus( row, column, true, e );\r\n\t\t}\r\n\t\telse if ( ! keyBlurable || ! this.c.blurable ) {\r\n\t\t\t// No new focus, but if the table isn't blurable, then don't loose\r\n\t\t\t// focus\r\n\t\t\tif (e) {\r\n\t\t\t\te.preventDefault();\r\n\t\t\t}\r\n\t\t}\r\n\t\telse {\r\n\t\t\tthis._blur();\r\n\t\t}\r\n\t},\r\n\r\n\r\n\t/**\r\n\t * Create and insert a hidden input element that can receive focus on behalf\r\n\t * of the table\r\n\t *\r\n\t * @private\r\n\t */\r\n\t_tabInput: function ()\r\n\t{\r\n\t\tvar that = this;\r\n\t\tvar dt = this.s.dt;\r\n\t\tvar tabIndex = this.c.tabIndex !== null ?\r\n\t\t\tthis.c.tabIndex :\r\n\t\t\tdt.settings()[0].iTabIndex;\r\n\r\n\t\tif ( tabIndex == -1 ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Only create the input element once on first class\r\n\t\tif (! this.s.tabInput) {\r\n\t\t\tvar div = $('
') // *** GLOBYS Add aria-hidden=\"true\" ***\r\n\t\t\t\t.css( {\r\n\t\t\t\t\tposition: 'absolute',\r\n\t\t\t\t\theight: 1,\r\n\t\t\t\t\twidth: 0,\r\n\t\t\t\t\tpadding: 0,\r\n\t\t\t\t\toverflow: 'hidden'\r\n\t\t\t\t} );\r\n\r\n\t\t\tdiv.children().on( 'focus', function (e) {\r\n\t\t\t\tvar cell = dt.cell(':eq(0)', that._columns(), {page: 'current'});\r\n\t\r\n\t\t\t\tif ( cell.any() ) {\r\n\t\t\t\t\tthat._focus( cell, null, true, e );\r\n\t\t\t\t}\r\n\t\t\t} );\r\n\r\n\t\t\tthis.s.tabInput = div;\r\n\t\t}\r\n\r\n\t\t// Insert the input element into the first cell in the table's body\r\n\t\tvar cell = this.s.dt.cell(':eq(0)', '0:visible', {page: 'current', order: 'current'}).node();\r\n\t\tif (cell) {\r\n\t\t\t$(cell).prepend(this.s.tabInput);\r\n\t\t}\r\n\t},\r\n\r\n\t/**\r\n\t * Update fixed columns if they are enabled and if the cell we are\r\n\t * focusing is inside a fixed column\r\n\t * @param {integer} column Index of the column being changed\r\n\t * @private\r\n\t */\r\n\t_updateFixedColumns: function( column )\r\n\t{\r\n\t\tvar dt = this.s.dt;\r\n\t\tvar settings = dt.settings()[0];\r\n\r\n\t\tif ( settings._oFixedColumns ) {\r\n\t\t\tvar leftCols = settings._oFixedColumns.s.iLeftColumns;\r\n\t\t\tvar rightCols = settings.aoColumns.length - settings._oFixedColumns.s.iRightColumns;\r\n\r\n\t\t\tif (column < leftCols || column >= rightCols) {\r\n\t\t\t\tdt.fixedColumns().update();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n} );\r\n\r\n\r\n/**\r\n * KeyTable default settings for initialisation\r\n *\r\n * @namespace\r\n * @name KeyTable.defaults\r\n * @static\r\n */\r\nKeyTable.defaults = {\r\n\t/**\r\n\t * Can focus be removed from the table\r\n\t * @type {Boolean}\r\n\t */\r\n\tblurable: true,\r\n\r\n\t/**\r\n\t * Class to give to the focused cell\r\n\t * @type {String}\r\n\t */\r\n\tclassName: 'focus',\r\n\r\n\t/**\r\n\t * Enable or disable clipboard support\r\n\t * @type {Boolean}\r\n\t */\r\n\tclipboard: true,\r\n\r\n\t/**\r\n\t * Orthogonal data that should be copied to clipboard\r\n\t * @type {string}\r\n\t */\r\n\tclipboardOrthogonal: 'display',\r\n\r\n\t/**\r\n\t * Columns that can be focused. This is automatically merged with the\r\n\t * visible columns as only visible columns can gain focus.\r\n\t * @type {String}\r\n\t */\r\n\tcolumns: '', // all\r\n\r\n\t/**\r\n\t * Editor instance to automatically perform Excel like navigation\r\n\t * @type {Editor}\r\n\t */\r\n\teditor: null,\r\n\r\n\t/**\r\n\t * Trigger editing immediately on focus\r\n\t * @type {boolean}\r\n\t */\r\n\teditOnFocus: false,\r\n\r\n\t/**\r\n\t * Select a cell to automatically select on start up. `null` for no\r\n\t * automatic selection\r\n\t * @type {cell-selector}\r\n\t */\r\n\tfocus: null,\r\n\r\n\t/**\r\n\t * Array of keys to listen for\r\n\t * @type {null|array}\r\n\t */\r\n\tkeys: null,\r\n\r\n\t/**\r\n\t * Tab index for where the table should sit in the document's tab flow\r\n\t * @type {integer|null}\r\n\t */\r\n\ttabIndex: null\r\n};\r\n\r\n\r\n\r\nKeyTable.version = \"2.5.3\";\r\n\r\n\r\n$.fn.dataTable.KeyTable = KeyTable;\r\n$.fn.DataTable.KeyTable = KeyTable;\r\n\r\n\r\nDataTable.Api.register( 'cell.blur()', function () {\r\n\treturn this.iterator( 'table', function (ctx) {\r\n\t\tif ( ctx.keytable ) {\r\n\t\t\tctx.keytable.blur();\r\n\t\t}\r\n\t} );\r\n} );\r\n\r\nDataTable.Api.register( 'cell().focus()', function () {\r\n\treturn this.iterator( 'cell', function (ctx, row, column) {\r\n\t\tif ( ctx.keytable ) {\r\n\t\t\tctx.keytable.focus( row, column );\r\n\t\t}\r\n\t} );\r\n} );\r\n\r\nDataTable.Api.register( 'keys.disable()', function () {\r\n\treturn this.iterator( 'table', function (ctx) {\r\n\t\tif ( ctx.keytable ) {\r\n\t\t\tctx.keytable.enable( false );\r\n\t\t}\r\n\t} );\r\n} );\r\n\r\nDataTable.Api.register( 'keys.enable()', function ( opts ) {\r\n\treturn this.iterator( 'table', function (ctx) {\r\n\t\tif ( ctx.keytable ) {\r\n\t\t\tctx.keytable.enable( opts === undefined ? true : opts );\r\n\t\t}\r\n\t} );\r\n} );\r\n\r\nDataTable.Api.register( 'keys.move()', function ( dir ) {\r\n\treturn this.iterator( 'table', function (ctx) {\r\n\t\tif ( ctx.keytable ) {\r\n\t\t\tctx.keytable._shift( null, dir, false );\r\n\t\t}\r\n\t} );\r\n} );\r\n\r\n// Cell selector\r\nDataTable.ext.selector.cell.push( function ( settings, opts, cells ) {\r\n\tvar focused = opts.focused;\r\n\tvar kt = settings.keytable;\r\n\tvar out = [];\r\n\r\n\tif ( ! kt || focused === undefined ) {\r\n\t\treturn cells;\r\n\t}\r\n\r\n\tfor ( var i=0, ien=cells.length ; i