diff options
Diffstat (limited to 'build/resources/main/static/plugins/datatables-autofill')
6 files changed, 1398 insertions, 0 deletions
diff --git a/build/resources/main/static/plugins/datatables-autofill/css/autoFill.bootstrap4.css b/build/resources/main/static/plugins/datatables-autofill/css/autoFill.bootstrap4.css new file mode 100644 index 0000000..6abac44 --- /dev/null +++ b/build/resources/main/static/plugins/datatables-autofill/css/autoFill.bootstrap4.css @@ -0,0 +1,91 @@ +div.dt-autofill-handle { + position: absolute; + height: 8px; + width: 8px; + z-index: 102; + box-sizing: border-box; + background: #0275d8; + cursor: pointer; +} + +div.dtk-focus-alt div.dt-autofill-handle { + background: #ff8b33; +} + +div.dt-autofill-select { + position: absolute; + z-index: 1001; + background-color: #0275d8; + background-image: repeating-linear-gradient(45deg, transparent, transparent 5px, rgba(255, 255, 255, 0.5) 5px, rgba(255, 255, 255, 0.5) 10px); +} +div.dt-autofill-select.top, div.dt-autofill-select.bottom { + height: 3px; + margin-top: -1px; +} +div.dt-autofill-select.left, div.dt-autofill-select.right { + width: 3px; + margin-left: -1px; +} + +div.dt-autofill-list { + position: fixed; + top: 50%; + left: 50%; + width: 500px; + margin-left: -250px; + background-color: white; + border-radius: 6px; + box-shadow: 0 0 5px #555; + border: 2px solid #444; + z-index: 11; + box-sizing: border-box; + padding: 1.5em 2em; +} +div.dt-autofill-list ul { + display: table; + margin: 0; + padding: 0; + list-style: none; + width: 100%; +} +div.dt-autofill-list ul li { + display: table-row; +} +div.dt-autofill-list ul li:last-child div.dt-autofill-question, div.dt-autofill-list ul li:last-child div.dt-autofill-button { + border-bottom: none; +} +div.dt-autofill-list ul li:hover { + background-color: #f6f6f6; +} +div.dt-autofill-list div.dt-autofill-question { + display: table-cell; + padding: 0.5em 0; + border-bottom: 1px solid #ccc; +} +div.dt-autofill-list div.dt-autofill-question input[type=number] { + padding: 6px; + width: 30px; + margin: -2px 0; +} +div.dt-autofill-list div.dt-autofill-button { + display: table-cell; + padding: 0.5em 0; + border-bottom: 1px solid #ccc; +} + +div.dt-autofill-background { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.7); + background: radial-gradient(ellipse farthest-corner at center, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%); + z-index: 10; +} + +div.dt-autofill-list div.dt-autofill-question input[type=number] { + padding: 6px; + width: 60px; + margin: -2px 0; +} diff --git a/build/resources/main/static/plugins/datatables-autofill/css/autoFill.bootstrap4.min.css b/build/resources/main/static/plugins/datatables-autofill/css/autoFill.bootstrap4.min.css new file mode 100644 index 0000000..50bc3be --- /dev/null +++ b/build/resources/main/static/plugins/datatables-autofill/css/autoFill.bootstrap4.min.css @@ -0,0 +1 @@ +div.dt-autofill-handle{position:absolute;height:8px;width:8px;z-index:102;box-sizing:border-box;background:#0275d8;cursor:pointer}div.dtk-focus-alt div.dt-autofill-handle{background:#ff8b33}div.dt-autofill-select{position:absolute;z-index:1001;background-color:#0275d8;background-image:repeating-linear-gradient(45deg, transparent, transparent 5px, rgba(255, 255, 255, 0.5) 5px, rgba(255, 255, 255, 0.5) 10px)}div.dt-autofill-select.top,div.dt-autofill-select.bottom{height:3px;margin-top:-1px}div.dt-autofill-select.left,div.dt-autofill-select.right{width:3px;margin-left:-1px}div.dt-autofill-list{position:fixed;top:50%;left:50%;width:500px;margin-left:-250px;background-color:white;border-radius:6px;box-shadow:0 0 5px #555;border:2px solid #444;z-index:11;box-sizing:border-box;padding:1.5em 2em}div.dt-autofill-list ul{display:table;margin:0;padding:0;list-style:none;width:100%}div.dt-autofill-list ul li{display:table-row}div.dt-autofill-list ul li:last-child div.dt-autofill-question,div.dt-autofill-list ul li:last-child div.dt-autofill-button{border-bottom:none}div.dt-autofill-list ul li:hover{background-color:#f6f6f6}div.dt-autofill-list div.dt-autofill-question{display:table-cell;padding:.5em 0;border-bottom:1px solid #ccc}div.dt-autofill-list div.dt-autofill-question input[type=number]{padding:6px;width:30px;margin:-2px 0}div.dt-autofill-list div.dt-autofill-button{display:table-cell;padding:.5em 0;border-bottom:1px solid #ccc}div.dt-autofill-background{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0, 0, 0, 0.7);background:radial-gradient(ellipse farthest-corner at center, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);z-index:10}div.dt-autofill-list div.dt-autofill-question input[type=number]{padding:6px;width:60px;margin:-2px 0} diff --git a/build/resources/main/static/plugins/datatables-autofill/js/autoFill.bootstrap4.js b/build/resources/main/static/plugins/datatables-autofill/js/autoFill.bootstrap4.js new file mode 100644 index 0000000..40037e4 --- /dev/null +++ b/build/resources/main/static/plugins/datatables-autofill/js/autoFill.bootstrap4.js @@ -0,0 +1,43 @@ +/*! Bootstrap integration for DataTables' AutoFill + * ©2015 SpryMedia Ltd - datatables.net/license + */ + +(function( factory ){ + if ( typeof define === 'function' && define.amd ) { + // AMD + define( ['jquery', 'datatables.net-bs4', 'datatables.net-autofill'], 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-bs4')(root, $).$; + } + + if ( ! $.fn.dataTable.AutoFill ) { + require('datatables.net-autofill')(root, $); + } + + return factory( $, root, root.document ); + }; + } + else { + // Browser + factory( jQuery, window, document ); + } +}(function( $, window, document, undefined ) { +'use strict'; +var DataTable = $.fn.dataTable; + + +DataTable.AutoFill.classes.btn = 'btn btn-primary'; + + +return DataTable; +}));
\ No newline at end of file diff --git a/build/resources/main/static/plugins/datatables-autofill/js/autoFill.bootstrap4.min.js b/build/resources/main/static/plugins/datatables-autofill/js/autoFill.bootstrap4.min.js new file mode 100644 index 0000000..e97763d --- /dev/null +++ b/build/resources/main/static/plugins/datatables-autofill/js/autoFill.bootstrap4.min.js @@ -0,0 +1,5 @@ +/*! + Bootstrap integration for DataTables' AutoFill + ©2015 SpryMedia Ltd - datatables.net/license +*/ +(function(b){"function"===typeof define&&define.amd?define(["jquery","datatables.net-bs4","datatables.net-autofill"],function(a){return b(a,window,document)}):"object"===typeof exports?module.exports=function(a,c){a||(a=window);c&&c.fn.dataTable||(c=require("datatables.net-bs4")(a,c).$);c.fn.dataTable.AutoFill||require("datatables.net-autofill")(a,c);return b(c,a,a.document)}:b(jQuery,window,document)})(function(b,a,c,d){b=b.fn.dataTable;b.AutoFill.classes.btn="btn btn-primary";return b}); diff --git a/build/resources/main/static/plugins/datatables-autofill/js/dataTables.autoFill.js b/build/resources/main/static/plugins/datatables-autofill/js/dataTables.autoFill.js new file mode 100644 index 0000000..bc13b7d --- /dev/null +++ b/build/resources/main/static/plugins/datatables-autofill/js/dataTables.autoFill.js @@ -0,0 +1,1212 @@ +/*! AutoFill 2.3.9 + * ©2008-2021 SpryMedia Ltd - datatables.net/license + */ + +/** + * @summary AutoFill + * @description Add Excel like click and drag auto-fill options to DataTables + * @version 2.3.9 + * @file dataTables.autoFill.js + * @author SpryMedia Ltd (www.sprymedia.co.uk) + * @contact www.sprymedia.co.uk/contact + * @copyright Copyright 2010-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 + */ +(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; + + +var _instance = 0; + +/** + * AutoFill provides Excel like auto-fill features for a DataTable + * + * @class AutoFill + * @constructor + * @param {object} oTD DataTables settings object + * @param {object} oConfig Configuration object for AutoFill + */ +var AutoFill = function( dt, opts ) +{ + if ( ! DataTable.versionCheck || ! DataTable.versionCheck( '1.10.8' ) ) { + throw( "Warning: AutoFill requires DataTables 1.10.8 or greater"); + } + + // User and defaults configuration object + this.c = $.extend( true, {}, + DataTable.defaults.autoFill, + AutoFill.defaults, + opts + ); + + /** + * @namespace Settings object which contains customisable information for AutoFill instance + */ + this.s = { + /** @type {DataTable.Api} DataTables' API instance */ + dt: new DataTable.Api( dt ), + + /** @type {String} Unique namespace for events attached to the document */ + namespace: '.autoFill'+(_instance++), + + /** @type {Object} Cached dimension information for use in the mouse move event handler */ + scroll: {}, + + /** @type {integer} Interval object used for smooth scrolling */ + scrollInterval: null, + + handle: { + height: 0, + width: 0 + }, + + /** + * Enabled setting + * @type {Boolean} + */ + enabled: false + }; + + + /** + * @namespace Common and useful DOM elements for the class instance + */ + this.dom = { + /** @type {jQuery} AutoFill handle */ + handle: $('<div class="dt-autofill-handle"/>'), + + /** + * @type {Object} Selected cells outline - Need to use 4 elements, + * otherwise the mouse over if you back into the selected rectangle + * will be over that element, rather than the cells! + */ + select: { + top: $('<div class="dt-autofill-select top"/>'), + right: $('<div class="dt-autofill-select right"/>'), + bottom: $('<div class="dt-autofill-select bottom"/>'), + left: $('<div class="dt-autofill-select left"/>') + }, + + /** @type {jQuery} Fill type chooser background */ + background: $('<div class="dt-autofill-background"/>'), + + /** @type {jQuery} Fill type chooser */ + list: $('<div class="dt-autofill-list">'+this.s.dt.i18n('autoFill.info', '')+'<ul/></div>'), + + /** @type {jQuery} DataTables scrolling container */ + dtScroll: null, + + /** @type {jQuery} Offset parent element */ + offsetParent: null + }; + + + /* Constructor logic */ + this._constructor(); +}; + + + +$.extend( AutoFill.prototype, { + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Public methods (exposed via the DataTables API below) + */ + enabled: function () + { + return this.s.enabled; + }, + + + enable: function ( flag ) + { + var that = this; + + if ( flag === false ) { + return this.disable(); + } + + this.s.enabled = true; + + this._focusListener(); + + this.dom.handle.on( 'mousedown', function (e) { + that._mousedown( e ); + return false; + } ); + + return this; + }, + + disable: function () + { + this.s.enabled = false; + + this._focusListenerRemove(); + + return this; + }, + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Constructor + */ + + /** + * Initialise the RowReorder instance + * + * @private + */ + _constructor: function () + { + var that = this; + var dt = this.s.dt; + var dtScroll = $('div.dataTables_scrollBody', this.s.dt.table().container()); + + // Make the instance accessible to the API + dt.settings()[0].autoFill = this; + + if ( dtScroll.length ) { + this.dom.dtScroll = dtScroll; + + // Need to scroll container to be the offset parent + if ( dtScroll.css('position') === 'static' ) { + dtScroll.css( 'position', 'relative' ); + } + } + + if ( this.c.enable !== false ) { + this.enable(); + } + + dt.on( 'destroy.autoFill', function () { + that._focusListenerRemove(); + } ); + }, + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Private methods + */ + + /** + * Display the AutoFill drag handle by appending it to a table cell. This + * is the opposite of the _detach method. + * + * @param {node} node TD/TH cell to insert the handle into + * @private + */ + _attach: function ( node ) + { + var dt = this.s.dt; + var idx = dt.cell( node ).index(); + var handle = this.dom.handle; + var handleDim = this.s.handle; + + if ( ! idx || dt.columns( this.c.columns ).indexes().indexOf( idx.column ) === -1 ) { + this._detach(); + return; + } + + if ( ! this.dom.offsetParent ) { + // We attach to the table's offset parent + this.dom.offsetParent = $( dt.table().node() ).offsetParent(); + } + + if ( ! handleDim.height || ! handleDim.width ) { + // Append to document so we can get its size. Not expecting it to + // change during the life time of the page + handle.appendTo( 'body' ); + handleDim.height = handle.outerHeight(); + handleDim.width = handle.outerWidth(); + } + + // Might need to go through multiple offset parents + var offset = this._getPosition( node, this.dom.offsetParent ); + + this.dom.attachedTo = node; + handle + .css( { + top: offset.top + node.offsetHeight - handleDim.height, + left: offset.left + node.offsetWidth - handleDim.width + } ) + .appendTo( this.dom.offsetParent ); + }, + + + /** + * Determine can the fill type should be. This can be automatic, or ask the + * end user. + * + * @param {array} cells Information about the selected cells from the key + * up function + * @private + */ + _actionSelector: function ( cells ) + { + var that = this; + var dt = this.s.dt; + var actions = AutoFill.actions; + var available = []; + + // "Ask" each plug-in if it wants to handle this data + $.each( actions, function ( key, action ) { + if ( action.available( dt, cells ) ) { + available.push( key ); + } + } ); + + if ( available.length === 1 && this.c.alwaysAsk === false ) { + // Only one action available - enact it immediately + var result = actions[ available[0] ].execute( dt, cells ); + this._update( result, cells ); + } + else if ( available.length > 1 ) { + // Multiple actions available - ask the end user what they want to do + var list = this.dom.list.children('ul').empty(); + + // Add a cancel option + available.push( 'cancel' ); + + $.each( available, function ( i, name ) { + list.append( $('<li/>') + .append( + '<div class="dt-autofill-question">'+ + actions[ name ].option( dt, cells )+ + '<div>' + ) + .append( $('<div class="dt-autofill-button">' ) + .append( $('<button class="'+AutoFill.classes.btn+'">'+dt.i18n('autoFill.button', '>')+'</button>') + .on( 'click', function () { + var result = actions[ name ].execute( + dt, cells, $(this).closest('li') + ); + that._update( result, cells ); + + that.dom.background.remove(); + that.dom.list.remove(); + } ) + ) + ) + ); + } ); + + this.dom.background.appendTo( 'body' ); + this.dom.list.appendTo( 'body' ); + + this.dom.list.css( 'margin-top', this.dom.list.outerHeight()/2 * -1 ); + } + }, + + + /** + * Remove the AutoFill handle from the document + * + * @private + */ + _detach: function () + { + this.dom.attachedTo = null; + this.dom.handle.detach(); + }, + + + /** + * Draw the selection outline by calculating the range between the start + * and end cells, then placing the highlighting elements to draw a rectangle + * + * @param {node} target End cell + * @param {object} e Originating event + * @private + */ + _drawSelection: function ( target, e ) + { + // Calculate boundary for start cell to this one + var dt = this.s.dt; + var start = this.s.start; + var startCell = $(this.dom.start); + var end = { + row: this.c.vertical ? + dt.rows( { page: 'current' } ).nodes().indexOf( target.parentNode ) : + start.row, + column: this.c.horizontal ? + $(target).index() : + start.column + }; + var colIndx = dt.column.index( 'toData', end.column ); + var endRow = dt.row( ':eq('+end.row+')', { page: 'current' } ); // Workaround for M581 + var endCell = $( dt.cell( endRow.index(), colIndx ).node() ); + + // Be sure that is a DataTables controlled cell + if ( ! dt.cell( endCell ).any() ) { + return; + } + + // if target is not in the columns available - do nothing + if ( dt.columns( this.c.columns ).indexes().indexOf( colIndx ) === -1 ) { + return; + } + + this.s.end = end; + + var top, bottom, left, right, height, width; + + top = start.row < end.row ? startCell : endCell; + bottom = start.row < end.row ? endCell : startCell; + left = start.column < end.column ? startCell : endCell; + right = start.column < end.column ? endCell : startCell; + + top = this._getPosition( top.get(0) ).top; + left = this._getPosition( left.get(0) ).left; + height = this._getPosition( bottom.get(0) ).top + bottom.outerHeight() - top; + width = this._getPosition( right.get(0) ).left + right.outerWidth() - left; + + var select = this.dom.select; + select.top.css( { + top: top, + left: left, + width: width + } ); + + select.left.css( { + top: top, + left: left, + height: height + } ); + + select.bottom.css( { + top: top + height, + left: left, + width: width + } ); + + select.right.css( { + top: top, + left: left + width, + height: height + } ); + }, + + + /** + * Use the Editor API to perform an update based on the new data for the + * cells + * + * @param {array} cells Information about the selected cells from the key + * up function + * @private + */ + _editor: function ( cells ) + { + var dt = this.s.dt; + var editor = this.c.editor; + + if ( ! editor ) { + return; + } + + // Build the object structure for Editor's multi-row editing + var idValues = {}; + var nodes = []; + var fields = editor.fields(); + + for ( var i=0, ien=cells.length ; i<ien ; i++ ) { + for ( var j=0, jen=cells[i].length ; j<jen ; j++ ) { + var cell = cells[i][j]; + + // Determine the field name for the cell being edited + var col = dt.settings()[0].aoColumns[ cell.index.column ]; + var fieldName = col.editField; + + if ( fieldName === undefined ) { + var dataSrc = col.mData; + + // dataSrc is the `field.data` property, but we need to set + // using the field name, so we need to translate from the + // data to the name + for ( var k=0, ken=fields.length ; k<ken ; k++ ) { + var field = editor.field( fields[k] ); + + if ( field.dataSrc() === dataSrc ) { + fieldName = field.name(); + break; + } + } + } + + if ( ! fieldName ) { + throw 'Could not automatically determine field data. '+ + 'Please see https://datatables.net/tn/11'; + } + + if ( ! idValues[ fieldName ] ) { + idValues[ fieldName ] = {}; + } + + var id = dt.row( cell.index.row ).id(); + idValues[ fieldName ][ id ] = cell.set; + + // Keep a list of cells so we can activate the bubble editing + // with them + nodes.push( cell.index ); + } + } + + // Perform the edit using bubble editing as it allows us to specify + // the cells to be edited, rather than using full rows + editor + .bubble( nodes, false ) + .multiSet( idValues ) + .submit(); + }, + + + /** + * Emit an event on the DataTable for listeners + * + * @param {string} name Event name + * @param {array} args Event arguments + * @private + */ + _emitEvent: function ( name, args ) + { + this.s.dt.iterator( 'table', function ( ctx, i ) { + $(ctx.nTable).triggerHandler( name+'.dt', args ); + } ); + }, + + + /** + * Attach suitable listeners (based on the configuration) that will attach + * and detach the AutoFill handle in the document. + * + * @private + */ + _focusListener: function () + { + var that = this; + var dt = this.s.dt; + var namespace = this.s.namespace; + var focus = this.c.focus !== null ? + this.c.focus : + dt.init().keys || dt.settings()[0].keytable ? + 'focus' : + 'hover'; + + // All event listeners attached here are removed in the `destroy` + // callback in the constructor + if ( focus === 'focus' ) { + dt + .on( 'key-focus.autoFill', function ( e, dt, cell ) { + that._attach( cell.node() ); + } ) + .on( 'key-blur.autoFill', function ( e, dt, cell ) { + that._detach(); + } ); + } + else if ( focus === 'click' ) { + $(dt.table().body()).on( 'click'+namespace, 'td, th', function (e) { + that._attach( this ); + } ); + + $(document.body).on( 'click'+namespace, function (e) { + if ( ! $(e.target).parents().filter( dt.table().body() ).length ) { + that._detach(); + } + } ); + } + else { + $(dt.table().body()) + .on( 'mouseenter'+namespace, 'td, th', function (e) { + that._attach( this ); + } ) + .on( 'mouseleave'+namespace, function (e) { + if ( $(e.relatedTarget).hasClass('dt-autofill-handle') ) { + return; + } + + that._detach(); + } ); + } + }, + + + _focusListenerRemove: function () + { + var dt = this.s.dt; + + dt.off( '.autoFill' ); + $(dt.table().body()).off( this.s.namespace ); + $(document.body).off( this.s.namespace ); + }, + + + /** + * Get the position of a node, relative to another, including any scrolling + * offsets. + * @param {Node} node Node to get the position of + * @param {jQuery} targetParent Node to use as the parent + * @return {object} Offset calculation + * @private + */ + _getPosition: function ( node, targetParent ) + { + var + currNode = node, + currOffsetParent, + top = 0, + left = 0; + + if ( ! targetParent ) { + targetParent = $( $( this.s.dt.table().node() )[0].offsetParent ); + } + + do { + // Don't use jQuery().position() the behaviour changes between 1.x and 3.x for + // tables + var positionTop = currNode.offsetTop; + var positionLeft = currNode.offsetLeft; + + // jQuery doesn't give a `table` as the offset parent oddly, so use DOM directly + currOffsetParent = $( currNode.offsetParent ); + + top += positionTop + parseInt( currOffsetParent.css('border-top-width') || 0 ) * 1; + left += positionLeft + parseInt( currOffsetParent.css('border-left-width') || 0 ) * 1; + + // Emergency fall back. Shouldn't happen, but just in case! + if ( currNode.nodeName.toLowerCase() === 'body' ) { + break; + } + + currNode = currOffsetParent.get(0); // for next loop + } + while ( currOffsetParent.get(0) !== targetParent.get(0) ) + + return { + top: top, + left: left + }; + }, + + + /** + * Start mouse drag - selects the start cell + * + * @param {object} e Mouse down event + * @private + */ + _mousedown: function ( e ) + { + var that = this; + var dt = this.s.dt; + + this.dom.start = this.dom.attachedTo; + this.s.start = { + row: dt.rows( { page: 'current' } ).nodes().indexOf( $(this.dom.start).parent()[0] ), + column: $(this.dom.start).index() + }; + + $(document.body) + .on( 'mousemove.autoFill', function (e) { + that._mousemove( e ); + } ) + .on( 'mouseup.autoFill', function (e) { + that._mouseup( e ); + } ); + + var select = this.dom.select; + var offsetParent = $( dt.table().node() ).offsetParent(); + select.top.appendTo( offsetParent ); + select.left.appendTo( offsetParent ); + select.right.appendTo( offsetParent ); + select.bottom.appendTo( offsetParent ); + + this._drawSelection( this.dom.start, e ); + + this.dom.handle.css( 'display', 'none' ); + + // Cache scrolling information so mouse move doesn't need to read. + // This assumes that the window and DT scroller will not change size + // during an AutoFill drag, which I think is a fair assumption + var scrollWrapper = this.dom.dtScroll; + this.s.scroll = { + windowHeight: $(window).height(), + windowWidth: $(window).width(), + dtTop: scrollWrapper ? scrollWrapper.offset().top : null, + dtLeft: scrollWrapper ? scrollWrapper.offset().left : null, + dtHeight: scrollWrapper ? scrollWrapper.outerHeight() : null, + dtWidth: scrollWrapper ? scrollWrapper.outerWidth() : null + }; + }, + + + /** + * Mouse drag - selects the end cell and update the selection display for + * the end user + * + * @param {object} e Mouse move event + * @private + */ + _mousemove: function ( e ) + { + var that = this; + var dt = this.s.dt; + var name = e.target.nodeName.toLowerCase(); + if ( name !== 'td' && name !== 'th' ) { + return; + } + + this._drawSelection( e.target, e ); + this._shiftScroll( e ); + }, + + + /** + * End mouse drag - perform the update actions + * + * @param {object} e Mouse up event + * @private + */ + _mouseup: function ( e ) + { + $(document.body).off( '.autoFill' ); + + var that = this; + var dt = this.s.dt; + var select = this.dom.select; + select.top.remove(); + select.left.remove(); + select.right.remove(); + select.bottom.remove(); + + this.dom.handle.css( 'display', 'block' ); + + // Display complete - now do something useful with the selection! + var start = this.s.start; + var end = this.s.end; + + // Haven't selected multiple cells, so nothing to do + if ( start.row === end.row && start.column === end.column ) { + return; + } + + var startDt = dt.cell( ':eq('+start.row+')', start.column+':visible', {page:'current'} ); + + // If Editor is active inside this cell (inline editing) we need to wait for Editor to + // submit and then we can loop back and trigger the fill. + if ( $('div.DTE', startDt.node()).length ) { + var editor = dt.editor(); + + editor + .on( 'submitSuccess.dtaf close.dtaf', function () { + editor.off( '.dtaf'); + + setTimeout( function () { + that._mouseup( e ); + }, 100 ); + } ) + .on( 'submitComplete.dtaf preSubmitCancelled.dtaf close.dtaf', function () { + editor.off( '.dtaf'); + } ); + + // Make the current input submit + editor.submit(); + + return; + } + + // Build a matrix representation of the selected rows + var rows = this._range( start.row, end.row ); + var columns = this._range( start.column, end.column ); + var selected = []; + var dtSettings = dt.settings()[0]; + var dtColumns = dtSettings.aoColumns; + var enabledColumns = dt.columns( this.c.columns ).indexes(); + + // Can't use Array.prototype.map as IE8 doesn't support it + // Can't use $.map as jQuery flattens 2D arrays + // Need to use a good old fashioned for loop + for ( var rowIdx=0 ; rowIdx<rows.length ; rowIdx++ ) { + selected.push( + $.map( columns, function (column) { + var row = dt.row( ':eq('+rows[rowIdx]+')', {page:'current'} ); // Workaround for M581 + var cell = dt.cell( row.index(), column+':visible' ); + var data = cell.data(); + var cellIndex = cell.index(); + var editField = dtColumns[ cellIndex.column ].editField; + + if ( editField !== undefined ) { + data = dtSettings.oApi._fnGetObjectDataFn( editField )( dt.row( cellIndex.row ).data() ); + } + + if ( enabledColumns.indexOf(cellIndex.column) === -1 ) { + return; + } + + return { + cell: cell, + data: data, + label: cell.data(), + index: cellIndex + }; + } ) + ); + } + + this._actionSelector( selected ); + + // Stop shiftScroll + clearInterval( this.s.scrollInterval ); + this.s.scrollInterval = null; + }, + + + /** + * Create an array with a range of numbers defined by the start and end + * parameters passed in (inclusive!). + * + * @param {integer} start Start + * @param {integer} end End + * @private + */ + _range: function ( start, end ) + { + var out = []; + var i; + + if ( start <= end ) { + for ( i=start ; i<=end ; i++ ) { + out.push( i ); + } + } + else { + for ( i=start ; i>=end ; i-- ) { + out.push( i ); + } + } + + return out; + }, + + + /** + * Move the window and DataTables scrolling during a drag to scroll new + * content into view. This is done by proximity to the edge of the scrolling + * container of the mouse - for example near the top edge of the window + * should scroll up. This is a little complicated as there are two elements + * that can be scrolled - the window and the DataTables scrolling view port + * (if scrollX and / or scrollY is enabled). + * + * @param {object} e Mouse move event object + * @private + */ + _shiftScroll: function ( e ) + { + var that = this; + var dt = this.s.dt; + var scroll = this.s.scroll; + var runInterval = false; + var scrollSpeed = 5; + var buffer = 65; + var + windowY = e.pageY - document.body.scrollTop, + windowX = e.pageX - document.body.scrollLeft, + windowVert, windowHoriz, + dtVert, dtHoriz; + + // Window calculations - based on the mouse position in the window, + // regardless of scrolling + if ( windowY < buffer ) { + windowVert = scrollSpeed * -1; + } + else if ( windowY > scroll.windowHeight - buffer ) { + windowVert = scrollSpeed; + } + + if ( windowX < buffer ) { + windowHoriz = scrollSpeed * -1; + } + else if ( windowX > scroll.windowWidth - buffer ) { + windowHoriz = scrollSpeed; + } + + // DataTables scrolling calculations - based on the table's position in + // the document and the mouse position on the page + if ( scroll.dtTop !== null && e.pageY < scroll.dtTop + buffer ) { + dtVert = scrollSpeed * -1; + } + else if ( scroll.dtTop !== null && e.pageY > scroll.dtTop + scroll.dtHeight - buffer ) { + dtVert = scrollSpeed; + } + + if ( scroll.dtLeft !== null && e.pageX < scroll.dtLeft + buffer ) { + dtHoriz = scrollSpeed * -1; + } + else if ( scroll.dtLeft !== null && e.pageX > scroll.dtLeft + scroll.dtWidth - buffer ) { + dtHoriz = scrollSpeed; + } + + // This is where it gets interesting. We want to continue scrolling + // without requiring a mouse move, so we need an interval to be + // triggered. The interval should continue until it is no longer needed, + // but it must also use the latest scroll commands (for example consider + // that the mouse might move from scrolling up to scrolling left, all + // with the same interval running. We use the `scroll` object to "pass" + // this information to the interval. Can't use local variables as they + // wouldn't be the ones that are used by an already existing interval! + if ( windowVert || windowHoriz || dtVert || dtHoriz ) { + scroll.windowVert = windowVert; + scroll.windowHoriz = windowHoriz; + scroll.dtVert = dtVert; + scroll.dtHoriz = dtHoriz; + runInterval = true; + } + else if ( this.s.scrollInterval ) { + // Don't need to scroll - remove any existing timer + clearInterval( this.s.scrollInterval ); + this.s.scrollInterval = null; + } + + // If we need to run the interval to scroll and there is no existing + // interval (if there is an existing one, it will continue to run) + if ( ! this.s.scrollInterval && runInterval ) { + this.s.scrollInterval = setInterval( function () { + // Don't need to worry about setting scroll <0 or beyond the + // scroll bound as the browser will just reject that. + if ( scroll.windowVert ) { + document.body.scrollTop += scroll.windowVert; + } + if ( scroll.windowHoriz ) { + document.body.scrollLeft += scroll.windowHoriz; + } + + // DataTables scrolling + if ( scroll.dtVert || scroll.dtHoriz ) { + var scroller = that.dom.dtScroll[0]; + + if ( scroll.dtVert ) { + scroller.scrollTop += scroll.dtVert; + } + if ( scroll.dtHoriz ) { + scroller.scrollLeft += scroll.dtHoriz; + } + } + }, 20 ); + } + }, + + + /** + * Update the DataTable after the user has selected what they want to do + * + * @param {false|undefined} result Return from the `execute` method - can + * be false internally to do nothing. This is not documented for plug-ins + * and is used only by the cancel option. + * @param {array} cells Information about the selected cells from the key + * up function, argumented with the set values + * @private + */ + _update: function ( result, cells ) + { + // Do nothing on `false` return from an execute function + if ( result === false ) { + return; + } + + var dt = this.s.dt; + var cell; + var columns = dt.columns( this.c.columns ).indexes(); + + // Potentially allow modifications to the cells matrix + this._emitEvent( 'preAutoFill', [ dt, cells ] ); + + this._editor( cells ); + + // Automatic updates are not performed if `update` is null and the + // `editor` parameter is passed in - the reason being that Editor will + // update the data once submitted + var update = this.c.update !== null ? + this.c.update : + this.c.editor ? + false : + true; + + if ( update ) { + for ( var i=0, ien=cells.length ; i<ien ; i++ ) { + for ( var j=0, jen=cells[i].length ; j<jen ; j++ ) { + cell = cells[i][j]; + + if ( columns.indexOf(cell.index.column) !== -1 ) { + cell.cell.data( cell.set ); + } + } + } + + dt.draw(false); + } + + this._emitEvent( 'autoFill', [ dt, cells ] ); + } +} ); + + +/** + * AutoFill actions. The options here determine how AutoFill will fill the data + * in the table when the user has selected a range of cells. Please see the + * documentation on the DataTables site for full details on how to create plug- + * ins. + * + * @type {Object} + */ +AutoFill.actions = { + increment: { + available: function ( dt, cells ) { + var d = cells[0][0].label; + + // is numeric test based on jQuery's old `isNumeric` function + return !isNaN( d - parseFloat( d ) ); + }, + + option: function ( dt, cells ) { + return dt.i18n( + 'autoFill.increment', + 'Increment / decrement each cell by: <input type="number" value="1">' + ); + }, + + execute: function ( dt, cells, node ) { + var value = cells[0][0].data * 1; + var increment = $('input', node).val() * 1; + + for ( var i=0, ien=cells.length ; i<ien ; i++ ) { + for ( var j=0, jen=cells[i].length ; j<jen ; j++ ) { + cells[i][j].set = value; + + value += increment; + } + } + } + }, + + fill: { + available: function ( dt, cells ) { + return true; + }, + + option: function ( dt, cells ) { + return dt.i18n('autoFill.fill', 'Fill all cells with <i>%d</i>', cells[0][0].label ); + }, + + execute: function ( dt, cells, node ) { + var value = cells[0][0].data; + + for ( var i=0, ien=cells.length ; i<ien ; i++ ) { + for ( var j=0, jen=cells[i].length ; j<jen ; j++ ) { + cells[i][j].set = value; + } + } + } + }, + + fillHorizontal: { + available: function ( dt, cells ) { + return cells.length > 1 && cells[0].length > 1; + }, + + option: function ( dt, cells ) { + return dt.i18n('autoFill.fillHorizontal', 'Fill cells horizontally' ); + }, + + execute: function ( dt, cells, node ) { + for ( var i=0, ien=cells.length ; i<ien ; i++ ) { + for ( var j=0, jen=cells[i].length ; j<jen ; j++ ) { + cells[i][j].set = cells[i][0].data; + } + } + } + }, + + fillVertical: { + available: function ( dt, cells ) { + return cells.length > 1; + }, + + option: function ( dt, cells ) { + return dt.i18n('autoFill.fillVertical', 'Fill cells vertically' ); + }, + + execute: function ( dt, cells, node ) { + for ( var i=0, ien=cells.length ; i<ien ; i++ ) { + for ( var j=0, jen=cells[i].length ; j<jen ; j++ ) { + cells[i][j].set = cells[0][j].data; + } + } + } + }, + + // Special type that does not make itself available, but is added + // automatically by AutoFill if a multi-choice list is shown. This allows + // sensible code reuse + cancel: { + available: function () { + return false; + }, + + option: function ( dt ) { + return dt.i18n('autoFill.cancel', 'Cancel' ); + }, + + execute: function () { + return false; + } + } +}; + + +/** + * AutoFill version + * + * @static + * @type String + */ +AutoFill.version = '2.3.9'; + + +/** + * AutoFill defaults + * + * @namespace + */ +AutoFill.defaults = { + /** @type {Boolean} Ask user what they want to do, even for a single option */ + alwaysAsk: false, + + /** @type {string|null} What will trigger a focus */ + focus: null, // focus, click, hover + + /** @type {column-selector} Columns to provide auto fill for */ + columns: '', // all + + /** @type {Boolean} Enable AutoFill on load */ + enable: true, + + /** @type {boolean|null} Update the cells after a drag */ + update: null, // false is editor given, true otherwise + + /** @type {DataTable.Editor} Editor instance for automatic submission */ + editor: null, + + /** @type {boolean} Enable vertical fill */ + vertical: true, + + /** @type {boolean} Enable horizontal fill */ + horizontal: true +}; + + +/** + * Classes used by AutoFill that are configurable + * + * @namespace + */ +AutoFill.classes = { + /** @type {String} Class used by the selection button */ + btn: 'btn' +}; + + +/* + * API + */ +var Api = $.fn.dataTable.Api; + +// Doesn't do anything - Not documented +Api.register( 'autoFill()', function () { + return this; +} ); + +Api.register( 'autoFill().enabled()', function () { + var ctx = this.context[0]; + + return ctx.autoFill ? + ctx.autoFill.enabled() : + false; +} ); + +Api.register( 'autoFill().enable()', function ( flag ) { + return this.iterator( 'table', function ( ctx ) { + if ( ctx.autoFill ) { + ctx.autoFill.enable( flag ); + } + } ); +} ); + +Api.register( 'autoFill().disable()', function () { + return this.iterator( 'table', function ( ctx ) { + if ( ctx.autoFill ) { + ctx.autoFill.disable(); + } + } ); +} ); + + +// Attach a listener to the document which listens for DataTables initialisation +// events so we can automatically initialise +$(document).on( 'preInit.dt.autofill', function (e, settings, json) { + if ( e.namespace !== 'dt' ) { + return; + } + + var init = settings.oInit.autoFill; + var defaults = DataTable.defaults.autoFill; + + if ( init || defaults ) { + var opts = $.extend( {}, init, defaults ); + + if ( init !== false ) { + new AutoFill( settings, opts ); + } + } +} ); + + +// Alias for access +DataTable.AutoFill = AutoFill; +DataTable.AutoFill = AutoFill; + + +return AutoFill; +})); diff --git a/build/resources/main/static/plugins/datatables-autofill/js/dataTables.autoFill.min.js b/build/resources/main/static/plugins/datatables-autofill/js/dataTables.autoFill.min.js new file mode 100644 index 0000000..efed9c1 --- /dev/null +++ b/build/resources/main/static/plugins/datatables-autofill/js/dataTables.autoFill.min.js @@ -0,0 +1,46 @@ +/*! + Copyright 2010-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 + AutoFill 2.3.9 + ©2008-2021 SpryMedia Ltd - datatables.net/license +*/ +var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.arrayIteratorImpl=function(c){var h=0;return function(){return h<c.length?{done:!1,value:c[h++]}:{done:!0}}};$jscomp.arrayIterator=function(c){return{next:$jscomp.arrayIteratorImpl(c)}};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.SIMPLE_FROUND_POLYFILL=!1;$jscomp.ISOLATE_POLYFILLS=!1; +$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(c,h,g){if(c==Array.prototype||c==Object.prototype)return c;c[h]=g.value;return c};$jscomp.getGlobal=function(c){c=["object"==typeof globalThis&&globalThis,c,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var h=0;h<c.length;++h){var g=c[h];if(g&&g.Math==Math)return g}throw Error("Cannot find global object");};$jscomp.global=$jscomp.getGlobal(this); +$jscomp.IS_SYMBOL_NATIVE="function"===typeof Symbol&&"symbol"===typeof Symbol("x");$jscomp.TRUST_ES6_POLYFILLS=!$jscomp.ISOLATE_POLYFILLS||$jscomp.IS_SYMBOL_NATIVE;$jscomp.polyfills={};$jscomp.propertyToPolyfillSymbol={};$jscomp.POLYFILL_PREFIX="$jscp$";var $jscomp$lookupPolyfilledValue=function(c,h){var g=$jscomp.propertyToPolyfillSymbol[h];if(null==g)return c[h];g=c[g];return void 0!==g?g:c[h]}; +$jscomp.polyfill=function(c,h,g,k){h&&($jscomp.ISOLATE_POLYFILLS?$jscomp.polyfillIsolated(c,h,g,k):$jscomp.polyfillUnisolated(c,h,g,k))};$jscomp.polyfillUnisolated=function(c,h,g,k){g=$jscomp.global;c=c.split(".");for(k=0;k<c.length-1;k++){var l=c[k];if(!(l in g))return;g=g[l]}c=c[c.length-1];k=g[c];h=h(k);h!=k&&null!=h&&$jscomp.defineProperty(g,c,{configurable:!0,writable:!0,value:h})}; +$jscomp.polyfillIsolated=function(c,h,g,k){var l=c.split(".");c=1===l.length;k=l[0];k=!c&&k in $jscomp.polyfills?$jscomp.polyfills:$jscomp.global;for(var y=0;y<l.length-1;y++){var r=l[y];if(!(r in k))return;k=k[r]}l=l[l.length-1];g=$jscomp.IS_SYMBOL_NATIVE&&"es6"===g?k[l]:null;h=h(g);null!=h&&(c?$jscomp.defineProperty($jscomp.polyfills,l,{configurable:!0,writable:!0,value:h}):h!==g&&($jscomp.propertyToPolyfillSymbol[l]=$jscomp.IS_SYMBOL_NATIVE?$jscomp.global.Symbol(l):$jscomp.POLYFILL_PREFIX+l,l= +$jscomp.propertyToPolyfillSymbol[l],$jscomp.defineProperty(k,l,{configurable:!0,writable:!0,value:h})))};$jscomp.initSymbol=function(){}; +$jscomp.polyfill("Symbol",function(c){if(c)return c;var h=function(l,y){this.$jscomp$symbol$id_=l;$jscomp.defineProperty(this,"description",{configurable:!0,writable:!0,value:y})};h.prototype.toString=function(){return this.$jscomp$symbol$id_};var g=0,k=function(l){if(this instanceof k)throw new TypeError("Symbol is not a constructor");return new h("jscomp_symbol_"+(l||"")+"_"+g++,l)};return k},"es6","es3");$jscomp.initSymbolIterator=function(){}; +$jscomp.polyfill("Symbol.iterator",function(c){if(c)return c;c=Symbol("Symbol.iterator");for(var h="Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" "),g=0;g<h.length;g++){var k=$jscomp.global[h[g]];"function"===typeof k&&"function"!=typeof k.prototype[c]&&$jscomp.defineProperty(k.prototype,c,{configurable:!0,writable:!0,value:function(){return $jscomp.iteratorPrototype($jscomp.arrayIteratorImpl(this))}})}return c},"es6", +"es3");$jscomp.initSymbolAsyncIterator=function(){};$jscomp.iteratorPrototype=function(c){c={next:c};c[Symbol.iterator]=function(){return this};return c};$jscomp.iteratorFromArray=function(c,h){c instanceof String&&(c+="");var g=0,k={next:function(){if(g<c.length){var l=g++;return{value:h(l,c[l]),done:!1}}k.next=function(){return{done:!0,value:void 0}};return k.next()}};k[Symbol.iterator]=function(){return k};return k}; +$jscomp.polyfill("Array.prototype.keys",function(c){return c?c:function(){return $jscomp.iteratorFromArray(this,function(h){return h})}},"es6","es3"); +(function(c){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(h){return c(h,window,document)}):"object"===typeof exports?module.exports=function(h,g){h||(h=window);g&&g.fn.dataTable||(g=require("datatables.net")(h,g).$);return c(g,h,h.document)}:c(jQuery,window,document)})(function(c,h,g,k){var l=c.fn.dataTable,y=0,r=function(a,d){if(!l.versionCheck||!l.versionCheck("1.10.8"))throw"Warning: AutoFill requires DataTables 1.10.8 or greater";this.c=c.extend(!0,{},l.defaults.autoFill, +r.defaults,d);this.s={dt:new l.Api(a),namespace:".autoFill"+y++,scroll:{},scrollInterval:null,handle:{height:0,width:0},enabled:!1};this.dom={handle:c('<div class="dt-autofill-handle"/>'),select:{top:c('<div class="dt-autofill-select top"/>'),right:c('<div class="dt-autofill-select right"/>'),bottom:c('<div class="dt-autofill-select bottom"/>'),left:c('<div class="dt-autofill-select left"/>')},background:c('<div class="dt-autofill-background"/>'),list:c('<div class="dt-autofill-list">'+this.s.dt.i18n("autoFill.info", +"")+"<ul/></div>"),dtScroll:null,offsetParent:null};this._constructor()};c.extend(r.prototype,{enabled:function(){return this.s.enabled},enable:function(a){var d=this;if(!1===a)return this.disable();this.s.enabled=!0;this._focusListener();this.dom.handle.on("mousedown",function(b){d._mousedown(b);return!1});return this},disable:function(){this.s.enabled=!1;this._focusListenerRemove();return this},_constructor:function(){var a=this,d=this.s.dt,b=c("div.dataTables_scrollBody",this.s.dt.table().container()); +d.settings()[0].autoFill=this;b.length&&(this.dom.dtScroll=b,"static"===b.css("position")&&b.css("position","relative"));!1!==this.c.enable&&this.enable();d.on("destroy.autoFill",function(){a._focusListenerRemove()})},_attach:function(a){var d=this.s.dt,b=d.cell(a).index(),e=this.dom.handle,f=this.s.handle;b&&-1!==d.columns(this.c.columns).indexes().indexOf(b.column)?(this.dom.offsetParent||(this.dom.offsetParent=c(d.table().node()).offsetParent()),f.height&&f.width||(e.appendTo("body"),f.height= +e.outerHeight(),f.width=e.outerWidth()),d=this._getPosition(a,this.dom.offsetParent),this.dom.attachedTo=a,e.css({top:d.top+a.offsetHeight-f.height,left:d.left+a.offsetWidth-f.width}).appendTo(this.dom.offsetParent)):this._detach()},_actionSelector:function(a){var d=this,b=this.s.dt,e=r.actions,f=[];c.each(e,function(p,q){q.available(b,a)&&f.push(p)});if(1===f.length&&!1===this.c.alwaysAsk){var m=e[f[0]].execute(b,a);this._update(m,a)}else if(1<f.length){var n=this.dom.list.children("ul").empty(); +f.push("cancel");c.each(f,function(p,q){n.append(c("<li/>").append('<div class="dt-autofill-question">'+e[q].option(b,a)+"<div>").append(c('<div class="dt-autofill-button">').append(c('<button class="'+r.classes.btn+'">'+b.i18n("autoFill.button",">")+"</button>").on("click",function(){var v=e[q].execute(b,a,c(this).closest("li"));d._update(v,a);d.dom.background.remove();d.dom.list.remove()}))))});this.dom.background.appendTo("body");this.dom.list.appendTo("body");this.dom.list.css("margin-top", +this.dom.list.outerHeight()/2*-1)}},_detach:function(){this.dom.attachedTo=null;this.dom.handle.detach()},_drawSelection:function(a,d){var b=this.s.dt;d=this.s.start;var e=c(this.dom.start),f={row:this.c.vertical?b.rows({page:"current"}).nodes().indexOf(a.parentNode):d.row,column:this.c.horizontal?c(a).index():d.column};a=b.column.index("toData",f.column);var m=b.row(":eq("+f.row+")",{page:"current"});m=c(b.cell(m.index(),a).node());if(b.cell(m).any()&&-1!==b.columns(this.c.columns).indexes().indexOf(a)){this.s.end= +f;b=d.row<f.row?e:m;var n=d.row<f.row?m:e;a=d.column<f.column?e:m;e=d.column<f.column?m:e;b=this._getPosition(b.get(0)).top;a=this._getPosition(a.get(0)).left;d=this._getPosition(n.get(0)).top+n.outerHeight()-b;e=this._getPosition(e.get(0)).left+e.outerWidth()-a;f=this.dom.select;f.top.css({top:b,left:a,width:e});f.left.css({top:b,left:a,height:d});f.bottom.css({top:b+d,left:a,width:e});f.right.css({top:b,left:a+e,height:d})}},_editor:function(a){var d=this.s.dt,b=this.c.editor;if(b){for(var e={}, +f=[],m=b.fields(),n=0,p=a.length;n<p;n++)for(var q=0,v=a[n].length;q<v;q++){var u=a[n][q],w=d.settings()[0].aoColumns[u.index.column],t=w.editField;if(t===k){w=w.mData;for(var x=0,z=m.length;x<z;x++){var A=b.field(m[x]);if(A.dataSrc()===w){t=A.name();break}}}if(!t)throw"Could not automatically determine field data. Please see https://datatables.net/tn/11";e[t]||(e[t]={});w=d.row(u.index.row).id();e[t][w]=u.set;f.push(u.index)}b.bubble(f,!1).multiSet(e).submit()}},_emitEvent:function(a,d){this.s.dt.iterator("table", +function(b,e){c(b.nTable).triggerHandler(a+".dt",d)})},_focusListener:function(){var a=this,d=this.s.dt,b=this.s.namespace,e=null!==this.c.focus?this.c.focus:d.init().keys||d.settings()[0].keytable?"focus":"hover";if("focus"===e)d.on("key-focus.autoFill",function(f,m,n){a._attach(n.node())}).on("key-blur.autoFill",function(f,m,n){a._detach()});else if("click"===e)c(d.table().body()).on("click"+b,"td, th",function(f){a._attach(this)}),c(g.body).on("click"+b,function(f){c(f.target).parents().filter(d.table().body()).length|| +a._detach()});else c(d.table().body()).on("mouseenter"+b,"td, th",function(f){a._attach(this)}).on("mouseleave"+b,function(f){c(f.relatedTarget).hasClass("dt-autofill-handle")||a._detach()})},_focusListenerRemove:function(){var a=this.s.dt;a.off(".autoFill");c(a.table().body()).off(this.s.namespace);c(g.body).off(this.s.namespace)},_getPosition:function(a,d){var b=0,e=0;d||(d=c(c(this.s.dt.table().node())[0].offsetParent));do{var f=a.offsetTop,m=a.offsetLeft;var n=c(a.offsetParent);b+=f+1*parseInt(n.css("border-top-width")|| +0);e+=m+1*parseInt(n.css("border-left-width")||0);if("body"===a.nodeName.toLowerCase())break;a=n.get(0)}while(n.get(0)!==d.get(0));return{top:b,left:e}},_mousedown:function(a){var d=this,b=this.s.dt;this.dom.start=this.dom.attachedTo;this.s.start={row:b.rows({page:"current"}).nodes().indexOf(c(this.dom.start).parent()[0]),column:c(this.dom.start).index()};c(g.body).on("mousemove.autoFill",function(f){d._mousemove(f)}).on("mouseup.autoFill",function(f){d._mouseup(f)});var e=this.dom.select;b=c(b.table().node()).offsetParent(); +e.top.appendTo(b);e.left.appendTo(b);e.right.appendTo(b);e.bottom.appendTo(b);this._drawSelection(this.dom.start,a);this.dom.handle.css("display","none");a=this.dom.dtScroll;this.s.scroll={windowHeight:c(h).height(),windowWidth:c(h).width(),dtTop:a?a.offset().top:null,dtLeft:a?a.offset().left:null,dtHeight:a?a.outerHeight():null,dtWidth:a?a.outerWidth():null}},_mousemove:function(a){var d=a.target.nodeName.toLowerCase();if("td"===d||"th"===d)this._drawSelection(a.target,a),this._shiftScroll(a)},_mouseup:function(a){c(g.body).off(".autoFill"); +var d=this,b=this.s.dt,e=this.dom.select;e.top.remove();e.left.remove();e.right.remove();e.bottom.remove();this.dom.handle.css("display","block");e=this.s.start;var f=this.s.end;if(e.row!==f.row||e.column!==f.column){var m=b.cell(":eq("+e.row+")",e.column+":visible",{page:"current"});if(c("div.DTE",m.node()).length){var n=b.editor();n.on("submitSuccess.dtaf close.dtaf",function(){n.off(".dtaf");setTimeout(function(){d._mouseup(a)},100)}).on("submitComplete.dtaf preSubmitCancelled.dtaf close.dtaf", +function(){n.off(".dtaf")});n.submit()}else{var p=this._range(e.row,f.row);e=this._range(e.column,f.column);f=[];for(var q=b.settings()[0],v=q.aoColumns,u=b.columns(this.c.columns).indexes(),w=0;w<p.length;w++)f.push(c.map(e,function(t){var x=b.row(":eq("+p[w]+")",{page:"current"});t=b.cell(x.index(),t+":visible");x=t.data();var z=t.index(),A=v[z.column].editField;A!==k&&(x=q.oApi._fnGetObjectDataFn(A)(b.row(z.row).data()));if(-1!==u.indexOf(z.column))return{cell:t,data:x,label:t.data(),index:z}})); +this._actionSelector(f);clearInterval(this.s.scrollInterval);this.s.scrollInterval=null}}},_range:function(a,d){var b=[];if(a<=d)for(;a<=d;a++)b.push(a);else for(;a>=d;a--)b.push(a);return b},_shiftScroll:function(a){var d=this,b=this.s.scroll,e=!1,f=a.pageY-g.body.scrollTop,m=a.pageX-g.body.scrollLeft,n,p,q,v;65>f?n=-5:f>b.windowHeight-65&&(n=5);65>m?p=-5:m>b.windowWidth-65&&(p=5);null!==b.dtTop&&a.pageY<b.dtTop+65?q=-5:null!==b.dtTop&&a.pageY>b.dtTop+b.dtHeight-65&&(q=5);null!==b.dtLeft&&a.pageX< +b.dtLeft+65?v=-5:null!==b.dtLeft&&a.pageX>b.dtLeft+b.dtWidth-65&&(v=5);n||p||q||v?(b.windowVert=n,b.windowHoriz=p,b.dtVert=q,b.dtHoriz=v,e=!0):this.s.scrollInterval&&(clearInterval(this.s.scrollInterval),this.s.scrollInterval=null);!this.s.scrollInterval&&e&&(this.s.scrollInterval=setInterval(function(){b.windowVert&&(g.body.scrollTop+=b.windowVert);b.windowHoriz&&(g.body.scrollLeft+=b.windowHoriz);if(b.dtVert||b.dtHoriz){var u=d.dom.dtScroll[0];b.dtVert&&(u.scrollTop+=b.dtVert);b.dtHoriz&&(u.scrollLeft+= +b.dtHoriz)}},20))},_update:function(a,d){if(!1!==a){a=this.s.dt;var b=a.columns(this.c.columns).indexes();this._emitEvent("preAutoFill",[a,d]);this._editor(d);if(null!==this.c.update?this.c.update:!this.c.editor){for(var e=0,f=d.length;e<f;e++)for(var m=0,n=d[e].length;m<n;m++){var p=d[e][m];-1!==b.indexOf(p.index.column)&&p.cell.data(p.set)}a.draw(!1)}this._emitEvent("autoFill",[a,d])}}});r.actions={increment:{available:function(a,d){a=d[0][0].label;return!isNaN(a-parseFloat(a))},option:function(a, +d){return a.i18n("autoFill.increment",'Increment / decrement each cell by: <input type="number" value="1">')},execute:function(a,d,b){a=1*d[0][0].data;b=1*c("input",b).val();for(var e=0,f=d.length;e<f;e++)for(var m=0,n=d[e].length;m<n;m++)d[e][m].set=a,a+=b}},fill:{available:function(a,d){return!0},option:function(a,d){return a.i18n("autoFill.fill","Fill all cells with <i>%d</i>",d[0][0].label)},execute:function(a,d,b){a=d[0][0].data;b=0;for(var e=d.length;b<e;b++)for(var f=0,m=d[b].length;f<m;f++)d[b][f].set= +a}},fillHorizontal:{available:function(a,d){return 1<d.length&&1<d[0].length},option:function(a,d){return a.i18n("autoFill.fillHorizontal","Fill cells horizontally")},execute:function(a,d,b){a=0;for(b=d.length;a<b;a++)for(var e=0,f=d[a].length;e<f;e++)d[a][e].set=d[a][0].data}},fillVertical:{available:function(a,d){return 1<d.length},option:function(a,d){return a.i18n("autoFill.fillVertical","Fill cells vertically")},execute:function(a,d,b){a=0;for(b=d.length;a<b;a++)for(var e=0,f=d[a].length;e<f;e++)d[a][e].set= +d[0][e].data}},cancel:{available:function(){return!1},option:function(a){return a.i18n("autoFill.cancel","Cancel")},execute:function(){return!1}}};r.version="2.3.9";r.defaults={alwaysAsk:!1,focus:null,columns:"",enable:!0,update:null,editor:null,vertical:!0,horizontal:!0};r.classes={btn:"btn"};var B=c.fn.dataTable.Api;B.register("autoFill()",function(){return this});B.register("autoFill().enabled()",function(){var a=this.context[0];return a.autoFill?a.autoFill.enabled():!1});B.register("autoFill().enable()", +function(a){return this.iterator("table",function(d){d.autoFill&&d.autoFill.enable(a)})});B.register("autoFill().disable()",function(){return this.iterator("table",function(a){a.autoFill&&a.autoFill.disable()})});c(g).on("preInit.dt.autofill",function(a,d,b){"dt"===a.namespace&&(a=d.oInit.autoFill,b=l.defaults.autoFill,a||b)&&(b=c.extend({},a,b),!1!==a&&new r(d,b))});l.AutoFill=r;return l.AutoFill=r}); |