| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855 | /*! AutoFill 1.2.1 * ©2008-2014 SpryMedia Ltd - datatables.net/license *//** * @summary     AutoFill * @description Add Excel like click and drag auto-fill options to DataTables * @version     1.2.1 * @file        dataTables.autoFill.js * @author      SpryMedia Ltd (www.sprymedia.co.uk) * @contact     www.sprymedia.co.uk/contact * @copyright   Copyright 2010-2014 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( window, document, undefined ) {var factory = function( $, DataTable ) {"use strict";/**  * 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( oDT, oConfig ){	/* Sanity check that we are a new instance */	if ( ! (this instanceof AutoFill) ) {		throw( "Warning: AutoFill must be initialised with the keyword 'new'" );	}	if ( ! $.fn.dataTableExt.fnVersionCheck('1.7.0') ) {		throw( "Warning: AutoFill requires DataTables 1.7 or greater");	}	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *	 * Public class variables	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	this.c = {};	/**	 * @namespace Settings object which contains customisable information for AutoFill instance	 */	this.s = {		/**		 * @namespace Cached information about the little dragging icon (the filler)		 */		"filler": {			"height": 0,			"width": 0		},		/**		 * @namespace Cached information about the border display		 */		"border": {			"width": 2		},		/**		 * @namespace Store for live information for the current drag		 */		"drag": {			"startX": -1,			"startY": -1,			"startTd": null,			"endTd": null,			"dragging": false		},		/**		 * @namespace Data cache for information that we need for scrolling the screen when we near		 *   the edges		 */		"screen": {			"interval": null,			"y": 0,			"height": 0,			"scrollTop": 0		},		/**		 * @namespace Data cache for the position of the DataTables scrolling element (when scrolling		 *   is enabled)		 */		"scroller": {			"top": 0,			"bottom": 0		},		/**		 * @namespace Information stored for each column. An array of objects		 */		"columns": []	};	/**	 * @namespace Common and useful DOM elements for the class instance	 */	this.dom = {		"table": null,		"filler": null,		"borderTop": null,		"borderRight": null,		"borderBottom": null,		"borderLeft": null,		"currentTarget": null	};	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *	 * Public class methods	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	/**	 * Retreieve the settings object from an instance	 *  @method fnSettings	 *  @returns {object} AutoFill settings object	 */	this.fnSettings = function () {		return this.s;	};	/* Constructor logic */	this._fnInit( oDT, oConfig );	return this;};AutoFill.prototype = {	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *	 * Private methods (they are of course public in JS, but recommended as private)	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	/**	 * Initialisation	 *  @method _fnInit	 *  @param {object} dt DataTables settings object	 *  @param {object} config Configuration object for AutoFill	 *  @returns void	 */	"_fnInit": function ( dt, config )	{		var			that = this,			i, iLen;		// Use DataTables API to get the settings allowing selectors, instances		// etc to be used, or for backwards compatibility get from the old		// fnSettings method		this.s.dt = DataTable.Api ?			new DataTable.Api( dt ).settings()[0] :			dt.fnSettings();		this.s.init = config || {};		this.dom.table = this.s.dt.nTable;		$.extend( true, this.c, AutoFill.defaults, config );		/* Add and configure the columns */		this._initColumns();		/* Auto Fill click and drag icon */		var filler = $('<div/>', {				'class': 'AutoFill_filler'			} )			.appendTo( 'body' );		this.dom.filler = filler[0];		// Get the height / width of the click element		this.s.filler.height = filler.height();		this.s.filler.width = filler.width();		filler[0].style.display = "none";		/* Border display - one div for each side. We can't just use a single		 * one with a border, as we want the events to effectively pass through		 * the transparent bit of the box		 */		var border;		var appender = document.body;		if ( that.s.dt.oScroll.sY !== "" ) {			that.s.dt.nTable.parentNode.style.position = "relative";			appender = that.s.dt.nTable.parentNode;		}		border = $('<div/>', {			"class": "AutoFill_border"		} );		this.dom.borderTop    = border.clone().appendTo( appender )[0];		this.dom.borderRight  = border.clone().appendTo( appender )[0];		this.dom.borderBottom = border.clone().appendTo( appender )[0];		this.dom.borderLeft   = border.clone().appendTo( appender )[0];		/* Events */		filler.on( 'mousedown.DTAF', function (e) {			this.onselectstart = function() { return false; };			that._fnFillerDragStart.call( that, e );			return false;		} );		$('tbody', this.dom.table).on(			'mouseover.DTAF mouseout.DTAF',			'>tr>td, >tr>th',			function (e) {				that._fnFillerDisplay.call( that, e );			}		);		$(this.dom.table).on( 'destroy.dt.DTAF', function () {			filler.off( 'mousedown.DTAF' ).remove();			$('tbody', this.dom.table).off( 'mouseover.DTAF mouseout.DTAF' );		} );	},	_initColumns: function ( )	{		var that = this;		var i, ien;		var dt = this.s.dt;		var config = this.s.init;		for ( i=0, ien=dt.aoColumns.length ; i<ien ; i++ ) {			this.s.columns[i] = $.extend( true, {}, AutoFill.defaults.column );		}		dt.oApi._fnApplyColumnDefs(			dt,			config.aoColumnDefs || config.columnDefs,			config.aoColumns || config.columns,			function (colIdx, def) {				that._fnColumnOptions( colIdx, def );			}		);		// For columns which don't have read, write, step functions defined,		// use the default ones		for ( i=0, ien=dt.aoColumns.length ; i<ien ; i++ ) {			var column = this.s.columns[i];			if ( ! column.read ) {				column.read = this._fnReadCell;			}			if ( ! column.write ) {				column.read = this._fnWriteCell;			}			if ( ! column.step ) {				column.read = this._fnStep;			}		}	},	"_fnColumnOptions": function ( i, opts )	{		var column = this.s.columns[ i ];		var set = function ( outProp, inProp ) {			if ( opts[ inProp[0] ] !== undefined ) {				column[ outProp ] = opts[ inProp[0] ];			}			if ( opts[ inProp[1] ] !== undefined ) {				column[ outProp ] = opts[ inProp[1] ];			}		};		// Compatibility with the old Hungarian style of notation		set( 'enable',    ['bEnable',     'enable'] );		set( 'read',      ['fnRead',      'read'] );		set( 'write',     ['fnWrite',     'write'] );		set( 'step',      ['fnStep',      'step'] );		set( 'increment', ['bIncrement',  'increment'] );	},	/**	 * Find out the coordinates of a given TD cell in a table	 *  @method  _fnTargetCoords	 *  @param   {Node} nTd	 *  @returns {Object} x and y properties, for the position of the cell in the tables DOM	 */	"_fnTargetCoords": function ( nTd )	{		var nTr = $(nTd).parents('tr')[0];		var position = this.s.dt.oInstance.fnGetPosition( nTd );		return {			"x":      $('td', nTr).index(nTd),			"y":      $('tr', nTr.parentNode).index(nTr),			"row":    position[0],			"column": position[2]		};	},	/**	 * Display the border around one or more cells (from start to end)	 *  @method  _fnUpdateBorder	 *  @param   {Node} nStart Starting cell	 *  @param   {Node} nEnd Ending cell	 *  @returns void	 */	"_fnUpdateBorder": function ( nStart, nEnd )	{		var			border = this.s.border.width,			offsetStart = $(nStart).offset(),			offsetEnd = $(nEnd).offset(),			x1 = offsetStart.left - border,			x2 = offsetEnd.left + $(nEnd).outerWidth(),			y1 = offsetStart.top - border,			y2 = offsetEnd.top + $(nEnd).outerHeight(),			width = offsetEnd.left + $(nEnd).outerWidth() - offsetStart.left + (2*border),			height = offsetEnd.top + $(nEnd).outerHeight() - offsetStart.top + (2*border),			oStyle;		// Recalculate start and end (when dragging "backwards")  		if( offsetStart.left > offsetEnd.left) {			x1 = offsetEnd.left - border;			x2 = offsetStart.left + $(nStart).outerWidth();			width = offsetStart.left + $(nStart).outerWidth() - offsetEnd.left + (2*border);		}		if ( this.s.dt.oScroll.sY !== "" )		{			/* The border elements are inside the DT scroller - so position relative to that */			var				offsetScroll = $(this.s.dt.nTable.parentNode).offset(),				scrollTop = $(this.s.dt.nTable.parentNode).scrollTop(),				scrollLeft = $(this.s.dt.nTable.parentNode).scrollLeft();			x1 -= offsetScroll.left - scrollLeft;			x2 -= offsetScroll.left - scrollLeft;			y1 -= offsetScroll.top - scrollTop;			y2 -= offsetScroll.top - scrollTop;		}		/* Top */		oStyle = this.dom.borderTop.style;		oStyle.top = y1+"px";		oStyle.left = x1+"px";		oStyle.height = this.s.border.width+"px";		oStyle.width = width+"px";		/* Bottom */		oStyle = this.dom.borderBottom.style;		oStyle.top = y2+"px";		oStyle.left = x1+"px";		oStyle.height = this.s.border.width+"px";		oStyle.width = width+"px";		/* Left */		oStyle = this.dom.borderLeft.style;		oStyle.top = y1+"px";		oStyle.left = x1+"px";		oStyle.height = height+"px";		oStyle.width = this.s.border.width+"px";		/* Right */		oStyle = this.dom.borderRight.style;		oStyle.top = y1+"px";		oStyle.left = x2+"px";		oStyle.height = height+"px";		oStyle.width = this.s.border.width+"px";	},	/**	 * Mouse down event handler for starting a drag	 *  @method  _fnFillerDragStart	 *  @param   {Object} e Event object	 *  @returns void	 */	"_fnFillerDragStart": function (e)	{		var that = this;		var startingTd = this.dom.currentTarget;		this.s.drag.dragging = true;		that.dom.borderTop.style.display = "block";		that.dom.borderRight.style.display = "block";		that.dom.borderBottom.style.display = "block";		that.dom.borderLeft.style.display = "block";		var coords = this._fnTargetCoords( startingTd );		this.s.drag.startX = coords.x;		this.s.drag.startY = coords.y;		this.s.drag.startTd = startingTd;		this.s.drag.endTd = startingTd;		this._fnUpdateBorder( startingTd, startingTd );		$(document).bind('mousemove.AutoFill', function (e) {			that._fnFillerDragMove.call( that, e );		} );		$(document).bind('mouseup.AutoFill', function (e) {			that._fnFillerFinish.call( that, e );		} );		/* Scrolling information cache */		this.s.screen.y = e.pageY;		this.s.screen.height = $(window).height();		this.s.screen.scrollTop = $(document).scrollTop();		if ( this.s.dt.oScroll.sY !== "" )		{			this.s.scroller.top = $(this.s.dt.nTable.parentNode).offset().top;			this.s.scroller.bottom = this.s.scroller.top + $(this.s.dt.nTable.parentNode).height();		}		/* Scrolling handler - we set an interval (which is cancelled on mouse up) which will fire		 * regularly and see if we need to do any scrolling		 */		this.s.screen.interval = setInterval( function () {			var iScrollTop = $(document).scrollTop();			var iScrollDelta = iScrollTop - that.s.screen.scrollTop;			that.s.screen.y += iScrollDelta;			if ( that.s.screen.height - that.s.screen.y + iScrollTop < 50 )			{				$('html, body').animate( {					"scrollTop": iScrollTop + 50				}, 240, 'linear' );			}			else if ( that.s.screen.y - iScrollTop < 50 )			{				$('html, body').animate( {					"scrollTop": iScrollTop - 50				}, 240, 'linear' );			}			if ( that.s.dt.oScroll.sY !== "" )			{				if ( that.s.screen.y > that.s.scroller.bottom - 50 )				{					$(that.s.dt.nTable.parentNode).animate( {						"scrollTop": $(that.s.dt.nTable.parentNode).scrollTop() + 50					}, 240, 'linear' );				}				else if ( that.s.screen.y < that.s.scroller.top + 50 )				{					$(that.s.dt.nTable.parentNode).animate( {						"scrollTop": $(that.s.dt.nTable.parentNode).scrollTop() - 50					}, 240, 'linear' );				}			}		}, 250 );	},	/**	 * Mouse move event handler for during a move. See if we want to update the display based on the	 * new cursor position	 *  @method  _fnFillerDragMove	 *  @param   {Object} e Event object	 *  @returns void	 */	"_fnFillerDragMove": function (e)	{		if ( e.target && e.target.nodeName.toUpperCase() == "TD" &&			 e.target != this.s.drag.endTd )		{			var coords = this._fnTargetCoords( e.target );			if ( this.c.mode == "y" && coords.x != this.s.drag.startX )			{				e.target = $('tbody>tr:eq('+coords.y+')>td:eq('+this.s.drag.startX+')', this.dom.table)[0];			}			if ( this.c.mode == "x" && coords.y != this.s.drag.startY )			{				e.target = $('tbody>tr:eq('+this.s.drag.startY+')>td:eq('+coords.x+')', this.dom.table)[0];			}			if ( this.c.mode == "either")			{				if(coords.x != this.s.drag.startX )				{					e.target = $('tbody>tr:eq('+this.s.drag.startY+')>td:eq('+coords.x+')', this.dom.table)[0];				}				else if ( coords.y != this.s.drag.startY ) {					e.target = $('tbody>tr:eq('+coords.y+')>td:eq('+this.s.drag.startX+')', this.dom.table)[0];				}			}			// update coords			if ( this.c.mode !== "both" ) {				coords = this._fnTargetCoords( e.target );			}			var drag = this.s.drag;			drag.endTd = e.target;			if ( coords.y >= this.s.drag.startY ) {				this._fnUpdateBorder( drag.startTd, drag.endTd );			}			else {				this._fnUpdateBorder( drag.endTd, drag.startTd );			}			this._fnFillerPosition( e.target );		}		/* Update the screen information so we can perform scrolling */		this.s.screen.y = e.pageY;		this.s.screen.scrollTop = $(document).scrollTop();		if ( this.s.dt.oScroll.sY !== "" )		{			this.s.scroller.scrollTop = $(this.s.dt.nTable.parentNode).scrollTop();			this.s.scroller.top = $(this.s.dt.nTable.parentNode).offset().top;			this.s.scroller.bottom = this.s.scroller.top + $(this.s.dt.nTable.parentNode).height();		}	},	/**	 * Mouse release handler - end the drag and take action to update the cells with the needed values	 *  @method  _fnFillerFinish	 *  @param   {Object} e Event object	 *  @returns void	 */	"_fnFillerFinish": function (e)	{		var that = this, i, iLen, j;		$(document).unbind('mousemove.AutoFill mouseup.AutoFill');		this.dom.borderTop.style.display = "none";		this.dom.borderRight.style.display = "none";		this.dom.borderBottom.style.display = "none";		this.dom.borderLeft.style.display = "none";		this.s.drag.dragging = false;		clearInterval( this.s.screen.interval );		var cells = [];		var table = this.dom.table;		var coordsStart = this._fnTargetCoords( this.s.drag.startTd );		var coordsEnd = this._fnTargetCoords( this.s.drag.endTd );		var columnIndex = function ( visIdx ) {			return that.s.dt.oApi._fnVisibleToColumnIndex( that.s.dt, visIdx );		};		// xxx - urgh - there must be a way of reducing this...		if ( coordsStart.y <= coordsEnd.y ) {			for ( i=coordsStart.y ; i<=coordsEnd.y ; i++ ) {				if ( coordsStart.x <= coordsEnd.x ) {					for ( j=coordsStart.x ; j<=coordsEnd.x ; j++ ) {						cells.push( {							node:   $('tbody>tr:eq('+i+')>td:eq('+j+')', table)[0],							x:      j - coordsStart.x,							y:      i - coordsStart.y,							colIdx: columnIndex( j )						} );					}				}				else {					for ( j=coordsStart.x ; j>=coordsEnd.x ; j-- ) {						cells.push( {							node:   $('tbody>tr:eq('+i+')>td:eq('+j+')', table)[0],							x:      j - coordsStart.x,							y:      i - coordsStart.y,							colIdx: columnIndex( j )						} );					}				}			}		}		else {			for ( i=coordsStart.y ; i>=coordsEnd.y ; i-- ) {				if ( coordsStart.x <= coordsEnd.x ) {					for ( j=coordsStart.x ; j<=coordsEnd.x ; j++ ) {						cells.push( {							node:   $('tbody>tr:eq('+i+')>td:eq('+j+')', table)[0],							x:      j - coordsStart.x,							y:      i - coordsStart.y,							colIdx: columnIndex( j )						} );					}				}				else {					for ( j=coordsStart.x ; j>=coordsEnd.x ; j-- ) {						cells.push( {							node:   $('tbody>tr:eq('+i+')>td:eq('+j+')', table)[0],							x:      coordsStart.x - j,							y:      coordsStart.y - i,							colIdx: columnIndex( j )						} );					}				}			}		}		// An auto-fill requires 2 or more cells		if ( cells.length <= 1 ) {			return;		}		var edited = [];		var previous;		for ( i=0, iLen=cells.length ; i<iLen ; i++ ) {			var cell      = cells[i];			var column    = this.s.columns[ cell.colIdx ];			var read      = column.read.call( column, cell.node );			var stepValue = column.step.call( column, cell.node, read, previous, i, cell.x, cell.y );			column.write.call( column, cell.node, stepValue );			previous = stepValue;			edited.push( {				cell:     cell,				colIdx:   cell.colIdx,				newValue: stepValue,				oldValue: read			} );		}		if ( this.c.complete !== null ) {			this.c.complete.call( this, edited );		}		// In 1.10 we can do a static draw		if ( DataTable.Api ) {			new DataTable.Api( this.s.dt ).draw( false );		}		else {			this.s.dt.oInstance.fnDraw();		}	},	/**	 * Display the drag handle on mouse over cell	 *  @method  _fnFillerDisplay	 *  @param   {Object} e Event object	 *  @returns void	 */	"_fnFillerDisplay": function (e)	{		var filler = this.dom.filler;		/* Don't display automatically when dragging */		if ( this.s.drag.dragging)		{			return;		}		/* Check that we are allowed to AutoFill this column or not */		var nTd = (e.target.nodeName.toLowerCase() == 'td') ? e.target : $(e.target).parents('td')[0];		var iX = this._fnTargetCoords(nTd).column;		if ( !this.s.columns[iX].enable )		{			filler.style.display = "none";			return;		}		if (e.type == 'mouseover')		{			this.dom.currentTarget = nTd;			this._fnFillerPosition( nTd );			filler.style.display = "block";		}		else if ( !e.relatedTarget || !e.relatedTarget.className.match(/AutoFill/) )		{			filler.style.display = "none";		}	},	/**	 * Position the filler icon over a cell	 *  @method  _fnFillerPosition	 *  @param   {Node} nTd Cell to position filler icon over	 *  @returns void	 */	"_fnFillerPosition": function ( nTd )	{		var offset = $(nTd).offset();		var filler = this.dom.filler;		filler.style.top = (offset.top - (this.s.filler.height / 2)-1 + $(nTd).outerHeight())+"px";		filler.style.left = (offset.left - (this.s.filler.width / 2)-1 + $(nTd).outerWidth())+"px";	}};// Alias for accessDataTable.AutoFill = AutoFill;DataTable.AutoFill = AutoFill;/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Constants * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//** * AutoFill version *  @constant  version *  @type      String *  @default   See code */AutoFill.version = "1.2.1";/** * AutoFill defaults *  @namespace */AutoFill.defaults = {	/**	 * Mode for dragging (restrict to y-axis only, x-axis only, either one or none):	 *	 *  * `y`      - y-axis only (default)	 *  * `x`      - x-axis only	 *  * `either` - either one, but not both axis at the same time	 *  * `both`   - multiple cells allowed	 *	 * @type {string}	 * @default `y`	 */	mode: 'y',	complete: null,	/**	 * Column definition defaults	 *  @namespace	 */	column: {		/**		 * If AutoFill should be enabled on this column		 *		 * @type {boolean}		 * @default true		 */		enable: true,		/**		 * Allow automatic increment / decrement on this column if a number		 * is found.		 *		 * @type {boolean}		 * @default true		 */		increment: true,		/**		 * Cell read function		 *		 * Default function will simply read the value from the HTML of the		 * cell.		 *		 * @type   {function}		 * @param  {node} cell `th` / `td` element to read the value from		 * @return {string}    Data that has been read		 */		read: function ( cell ) {			return $(cell).html();		},		/**		 * Cell write function		 *		 * Default function will simply write to the HTML and tell the DataTable		 * to update.		 *		 * @type   {function}		 * @param  {node} cell `th` / `td` element to write the value to		 * @return {string}    Data two write		 */		write: function ( cell, val ) {			var table = $(cell).parents('table');			if ( DataTable.Api ) {				// 1.10				table.DataTable().cell( cell ).data( val );			}			else {				// 1.9				var dt = table.dataTable();				var pos = dt.fnGetPosition( cell );				dt.fnUpdate( val, pos[0], pos[2], false );			}		},		/**		 * Step function. This provides the ability to customise how the values		 * are incremented.		 *		 * @param  {node} cell `th` / `td` element that is being operated upon		 * @param  {string} read Cell value from `read` function		 * @param  {string} last Value of the previous cell		 * @param  {integer} i Loop counter		 * @param  {integer} x Cell x-position in the current auto-fill. The		 *   starting cell is coordinate 0 regardless of its physical position		 *   in the DataTable.		 * @param  {integer} y Cell y-position in the current auto-fill. The		 *   starting cell is coordinate 0 regardless of its physical position		 *   in the DataTable.		 * @return {string} Value to write		 */		step: function ( cell, read, last, i, x, y ) {			// Increment a number if it is found			var re = /(\-?\d+)/;			var match = this.increment && last ? last.match(re) : null;			if ( match ) {				return last.replace( re, parseInt(match[1],10) + (x<0 || y<0 ? -1 : 1) );			}			return last === undefined ?				read :				last;		}	}};return AutoFill;};// Define as an AMD module if possibleif ( typeof define === 'function' && define.amd ) {	define( ['jquery', 'datatables'], factory );}else if ( typeof exports === 'object' ) {    // Node/CommonJS    factory( require('jquery'), require('datatables') );}else if ( jQuery && !jQuery.fn.dataTable.AutoFill ) {	// Otherwise simply initialise as normal, stopping multiple evaluation	factory( jQuery, jQuery.fn.dataTable );}}(window, document));
 |