summaryrefslogtreecommitdiff
path: root/src/main/resources/static/plugins/datatables-autofill
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/resources/static/plugins/datatables-autofill')
-rw-r--r--src/main/resources/static/plugins/datatables-autofill/css/autoFill.bootstrap4.css91
-rw-r--r--src/main/resources/static/plugins/datatables-autofill/css/autoFill.bootstrap4.min.css1
-rw-r--r--src/main/resources/static/plugins/datatables-autofill/js/autoFill.bootstrap4.js43
-rw-r--r--src/main/resources/static/plugins/datatables-autofill/js/autoFill.bootstrap4.min.js5
-rw-r--r--src/main/resources/static/plugins/datatables-autofill/js/dataTables.autoFill.js1212
-rw-r--r--src/main/resources/static/plugins/datatables-autofill/js/dataTables.autoFill.min.js46
6 files changed, 1398 insertions, 0 deletions
diff --git a/src/main/resources/static/plugins/datatables-autofill/css/autoFill.bootstrap4.css b/src/main/resources/static/plugins/datatables-autofill/css/autoFill.bootstrap4.css
new file mode 100644
index 0000000..6abac44
--- /dev/null
+++ b/src/main/resources/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/src/main/resources/static/plugins/datatables-autofill/css/autoFill.bootstrap4.min.css b/src/main/resources/static/plugins/datatables-autofill/css/autoFill.bootstrap4.min.css
new file mode 100644
index 0000000..50bc3be
--- /dev/null
+++ b/src/main/resources/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/src/main/resources/static/plugins/datatables-autofill/js/autoFill.bootstrap4.js b/src/main/resources/static/plugins/datatables-autofill/js/autoFill.bootstrap4.js
new file mode 100644
index 0000000..40037e4
--- /dev/null
+++ b/src/main/resources/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/src/main/resources/static/plugins/datatables-autofill/js/autoFill.bootstrap4.min.js b/src/main/resources/static/plugins/datatables-autofill/js/autoFill.bootstrap4.min.js
new file mode 100644
index 0000000..e97763d
--- /dev/null
+++ b/src/main/resources/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/src/main/resources/static/plugins/datatables-autofill/js/dataTables.autoFill.js b/src/main/resources/static/plugins/datatables-autofill/js/dataTables.autoFill.js
new file mode 100644
index 0000000..bc13b7d
--- /dev/null
+++ b/src/main/resources/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', '&gt;')+'</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/src/main/resources/static/plugins/datatables-autofill/js/dataTables.autoFill.min.js b/src/main/resources/static/plugins/datatables-autofill/js/dataTables.autoFill.min.js
new file mode 100644
index 0000000..efed9c1
--- /dev/null
+++ b/src/main/resources/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","&gt;")+"</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});