Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / pybind / mgr / dashboard / static / AdminLTE-2.3.7 / plugins / datatables / extensions / AutoFill / js / dataTables.autoFill.js
1 /*! AutoFill 1.2.1
2  * ©2008-2014 SpryMedia Ltd - datatables.net/license
3  */
4
5 /**
6  * @summary     AutoFill
7  * @description Add Excel like click and drag auto-fill options to DataTables
8  * @version     1.2.1
9  * @file        dataTables.autoFill.js
10  * @author      SpryMedia Ltd (www.sprymedia.co.uk)
11  * @contact     www.sprymedia.co.uk/contact
12  * @copyright   Copyright 2010-2014 SpryMedia Ltd.
13  *
14  * This source file is free software, available under the following license:
15  *   MIT license - http://datatables.net/license/mit
16  *
17  * This source file is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19  * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
20  *
21  * For details please refer to: http://www.datatables.net
22  */
23
24 (function( window, document, undefined ) {
25
26 var factory = function( $, DataTable ) {
27 "use strict";
28
29 /** 
30  * AutoFill provides Excel like auto-fill features for a DataTable
31  *
32  * @class AutoFill
33  * @constructor
34  * @param {object} oTD DataTables settings object
35  * @param {object} oConfig Configuration object for AutoFill
36  */
37 var AutoFill = function( oDT, oConfig )
38 {
39         /* Sanity check that we are a new instance */
40         if ( ! (this instanceof AutoFill) ) {
41                 throw( "Warning: AutoFill must be initialised with the keyword 'new'" );
42         }
43
44         if ( ! $.fn.dataTableExt.fnVersionCheck('1.7.0') ) {
45                 throw( "Warning: AutoFill requires DataTables 1.7 or greater");
46         }
47
48
49         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
50          * Public class variables
51          * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
52
53         this.c = {};
54
55         /**
56          * @namespace Settings object which contains customisable information for AutoFill instance
57          */
58         this.s = {
59                 /**
60                  * @namespace Cached information about the little dragging icon (the filler)
61                  */
62                 "filler": {
63                         "height": 0,
64                         "width": 0
65                 },
66
67                 /**
68                  * @namespace Cached information about the border display
69                  */
70                 "border": {
71                         "width": 2
72                 },
73
74                 /**
75                  * @namespace Store for live information for the current drag
76                  */
77                 "drag": {
78                         "startX": -1,
79                         "startY": -1,
80                         "startTd": null,
81                         "endTd": null,
82                         "dragging": false
83                 },
84
85                 /**
86                  * @namespace Data cache for information that we need for scrolling the screen when we near
87                  *   the edges
88                  */
89                 "screen": {
90                         "interval": null,
91                         "y": 0,
92                         "height": 0,
93                         "scrollTop": 0
94                 },
95
96                 /**
97                  * @namespace Data cache for the position of the DataTables scrolling element (when scrolling
98                  *   is enabled)
99                  */
100                 "scroller": {
101                         "top": 0,
102                         "bottom": 0
103                 },
104
105                 /**
106                  * @namespace Information stored for each column. An array of objects
107                  */
108                 "columns": []
109         };
110
111
112         /**
113          * @namespace Common and useful DOM elements for the class instance
114          */
115         this.dom = {
116                 "table": null,
117                 "filler": null,
118                 "borderTop": null,
119                 "borderRight": null,
120                 "borderBottom": null,
121                 "borderLeft": null,
122                 "currentTarget": null
123         };
124
125
126
127         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
128          * Public class methods
129          * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
130
131         /**
132          * Retreieve the settings object from an instance
133          *  @method fnSettings
134          *  @returns {object} AutoFill settings object
135          */
136         this.fnSettings = function () {
137                 return this.s;
138         };
139
140
141         /* Constructor logic */
142         this._fnInit( oDT, oConfig );
143         return this;
144 };
145
146
147
148 AutoFill.prototype = {
149         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
150          * Private methods (they are of course public in JS, but recommended as private)
151          * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
152
153         /**
154          * Initialisation
155          *  @method _fnInit
156          *  @param {object} dt DataTables settings object
157          *  @param {object} config Configuration object for AutoFill
158          *  @returns void
159          */
160         "_fnInit": function ( dt, config )
161         {
162                 var
163                         that = this,
164                         i, iLen;
165
166                 // Use DataTables API to get the settings allowing selectors, instances
167                 // etc to be used, or for backwards compatibility get from the old
168                 // fnSettings method
169                 this.s.dt = DataTable.Api ?
170                         new DataTable.Api( dt ).settings()[0] :
171                         dt.fnSettings();
172                 this.s.init = config || {};
173                 this.dom.table = this.s.dt.nTable;
174
175                 $.extend( true, this.c, AutoFill.defaults, config );
176
177                 /* Add and configure the columns */
178                 this._initColumns();
179
180                 /* Auto Fill click and drag icon */
181                 var filler = $('<div/>', {
182                                 'class': 'AutoFill_filler'
183                         } )
184                         .appendTo( 'body' );
185                 this.dom.filler = filler[0];
186
187                 // Get the height / width of the click element
188                 this.s.filler.height = filler.height();
189                 this.s.filler.width = filler.width();
190                 filler[0].style.display = "none";
191
192                 /* Border display - one div for each side. We can't just use a single
193                  * one with a border, as we want the events to effectively pass through
194                  * the transparent bit of the box
195                  */
196                 var border;
197                 var appender = document.body;
198                 if ( that.s.dt.oScroll.sY !== "" ) {
199                         that.s.dt.nTable.parentNode.style.position = "relative";
200                         appender = that.s.dt.nTable.parentNode;
201                 }
202
203                 border = $('<div/>', {
204                         "class": "AutoFill_border"
205                 } );
206                 this.dom.borderTop    = border.clone().appendTo( appender )[0];
207                 this.dom.borderRight  = border.clone().appendTo( appender )[0];
208                 this.dom.borderBottom = border.clone().appendTo( appender )[0];
209                 this.dom.borderLeft   = border.clone().appendTo( appender )[0];
210
211                 /* Events */
212                 filler.on( 'mousedown.DTAF', function (e) {
213                         this.onselectstart = function() { return false; };
214                         that._fnFillerDragStart.call( that, e );
215                         return false;
216                 } );
217
218                 $('tbody', this.dom.table).on(
219                         'mouseover.DTAF mouseout.DTAF',
220                         '>tr>td, >tr>th',
221                         function (e) {
222                                 that._fnFillerDisplay.call( that, e );
223                         }
224                 );
225
226                 $(this.dom.table).on( 'destroy.dt.DTAF', function () {
227                         filler.off( 'mousedown.DTAF' ).remove();
228                         $('tbody', this.dom.table).off( 'mouseover.DTAF mouseout.DTAF' );
229                 } );
230         },
231
232
233         _initColumns: function ( )
234         {
235                 var that = this;
236                 var i, ien;
237                 var dt = this.s.dt;
238                 var config = this.s.init;
239
240                 for ( i=0, ien=dt.aoColumns.length ; i<ien ; i++ ) {
241                         this.s.columns[i] = $.extend( true, {}, AutoFill.defaults.column );
242                 }
243
244                 dt.oApi._fnApplyColumnDefs(
245                         dt,
246                         config.aoColumnDefs || config.columnDefs,
247                         config.aoColumns || config.columns,
248                         function (colIdx, def) {
249                                 that._fnColumnOptions( colIdx, def );
250                         }
251                 );
252
253                 // For columns which don't have read, write, step functions defined,
254                 // use the default ones
255                 for ( i=0, ien=dt.aoColumns.length ; i<ien ; i++ ) {
256                         var column = this.s.columns[i];
257
258                         if ( ! column.read ) {
259                                 column.read = this._fnReadCell;
260                         }
261                         if ( ! column.write ) {
262                                 column.read = this._fnWriteCell;
263                         }
264                         if ( ! column.step ) {
265                                 column.read = this._fnStep;
266                         }
267                 }
268         },
269
270
271         "_fnColumnOptions": function ( i, opts )
272         {
273                 var column = this.s.columns[ i ];
274                 var set = function ( outProp, inProp ) {
275                         if ( opts[ inProp[0] ] !== undefined ) {
276                                 column[ outProp ] = opts[ inProp[0] ];
277                         }
278                         if ( opts[ inProp[1] ] !== undefined ) {
279                                 column[ outProp ] = opts[ inProp[1] ];
280                         }
281                 };
282
283                 // Compatibility with the old Hungarian style of notation
284                 set( 'enable',    ['bEnable',     'enable'] );
285                 set( 'read',      ['fnRead',      'read'] );
286                 set( 'write',     ['fnWrite',     'write'] );
287                 set( 'step',      ['fnStep',      'step'] );
288                 set( 'increment', ['bIncrement',  'increment'] );
289         },
290
291
292         /**
293          * Find out the coordinates of a given TD cell in a table
294          *  @method  _fnTargetCoords
295          *  @param   {Node} nTd
296          *  @returns {Object} x and y properties, for the position of the cell in the tables DOM
297          */
298         "_fnTargetCoords": function ( nTd )
299         {
300                 var nTr = $(nTd).parents('tr')[0];
301                 var position = this.s.dt.oInstance.fnGetPosition( nTd );
302
303                 return {
304                         "x":      $('td', nTr).index(nTd),
305                         "y":      $('tr', nTr.parentNode).index(nTr),
306                         "row":    position[0],
307                         "column": position[2]
308                 };
309         },
310
311
312         /**
313          * Display the border around one or more cells (from start to end)
314          *  @method  _fnUpdateBorder
315          *  @param   {Node} nStart Starting cell
316          *  @param   {Node} nEnd Ending cell
317          *  @returns void
318          */
319         "_fnUpdateBorder": function ( nStart, nEnd )
320         {
321                 var
322                         border = this.s.border.width,
323                         offsetStart = $(nStart).offset(),
324                         offsetEnd = $(nEnd).offset(),
325                         x1 = offsetStart.left - border,
326                         x2 = offsetEnd.left + $(nEnd).outerWidth(),
327                         y1 = offsetStart.top - border,
328                         y2 = offsetEnd.top + $(nEnd).outerHeight(),
329                         width = offsetEnd.left + $(nEnd).outerWidth() - offsetStart.left + (2*border),
330                         height = offsetEnd.top + $(nEnd).outerHeight() - offsetStart.top + (2*border),
331                         oStyle;
332
333                 // Recalculate start and end (when dragging "backwards")  
334                 if( offsetStart.left > offsetEnd.left) {
335                         x1 = offsetEnd.left - border;
336                         x2 = offsetStart.left + $(nStart).outerWidth();
337                         width = offsetStart.left + $(nStart).outerWidth() - offsetEnd.left + (2*border);
338                 }
339
340                 if ( this.s.dt.oScroll.sY !== "" )
341                 {
342                         /* The border elements are inside the DT scroller - so position relative to that */
343                         var
344                                 offsetScroll = $(this.s.dt.nTable.parentNode).offset(),
345                                 scrollTop = $(this.s.dt.nTable.parentNode).scrollTop(),
346                                 scrollLeft = $(this.s.dt.nTable.parentNode).scrollLeft();
347
348                         x1 -= offsetScroll.left - scrollLeft;
349                         x2 -= offsetScroll.left - scrollLeft;
350                         y1 -= offsetScroll.top - scrollTop;
351                         y2 -= offsetScroll.top - scrollTop;
352                 }
353
354                 /* Top */
355                 oStyle = this.dom.borderTop.style;
356                 oStyle.top = y1+"px";
357                 oStyle.left = x1+"px";
358                 oStyle.height = this.s.border.width+"px";
359                 oStyle.width = width+"px";
360
361                 /* Bottom */
362                 oStyle = this.dom.borderBottom.style;
363                 oStyle.top = y2+"px";
364                 oStyle.left = x1+"px";
365                 oStyle.height = this.s.border.width+"px";
366                 oStyle.width = width+"px";
367
368                 /* Left */
369                 oStyle = this.dom.borderLeft.style;
370                 oStyle.top = y1+"px";
371                 oStyle.left = x1+"px";
372                 oStyle.height = height+"px";
373                 oStyle.width = this.s.border.width+"px";
374
375                 /* Right */
376                 oStyle = this.dom.borderRight.style;
377                 oStyle.top = y1+"px";
378                 oStyle.left = x2+"px";
379                 oStyle.height = height+"px";
380                 oStyle.width = this.s.border.width+"px";
381         },
382
383
384         /**
385          * Mouse down event handler for starting a drag
386          *  @method  _fnFillerDragStart
387          *  @param   {Object} e Event object
388          *  @returns void
389          */
390         "_fnFillerDragStart": function (e)
391         {
392                 var that = this;
393                 var startingTd = this.dom.currentTarget;
394
395                 this.s.drag.dragging = true;
396
397                 that.dom.borderTop.style.display = "block";
398                 that.dom.borderRight.style.display = "block";
399                 that.dom.borderBottom.style.display = "block";
400                 that.dom.borderLeft.style.display = "block";
401
402                 var coords = this._fnTargetCoords( startingTd );
403                 this.s.drag.startX = coords.x;
404                 this.s.drag.startY = coords.y;
405
406                 this.s.drag.startTd = startingTd;
407                 this.s.drag.endTd = startingTd;
408
409                 this._fnUpdateBorder( startingTd, startingTd );
410
411                 $(document).bind('mousemove.AutoFill', function (e) {
412                         that._fnFillerDragMove.call( that, e );
413                 } );
414
415                 $(document).bind('mouseup.AutoFill', function (e) {
416                         that._fnFillerFinish.call( that, e );
417                 } );
418
419                 /* Scrolling information cache */
420                 this.s.screen.y = e.pageY;
421                 this.s.screen.height = $(window).height();
422                 this.s.screen.scrollTop = $(document).scrollTop();
423
424                 if ( this.s.dt.oScroll.sY !== "" )
425                 {
426                         this.s.scroller.top = $(this.s.dt.nTable.parentNode).offset().top;
427                         this.s.scroller.bottom = this.s.scroller.top + $(this.s.dt.nTable.parentNode).height();
428                 }
429
430                 /* Scrolling handler - we set an interval (which is cancelled on mouse up) which will fire
431                  * regularly and see if we need to do any scrolling
432                  */
433                 this.s.screen.interval = setInterval( function () {
434                         var iScrollTop = $(document).scrollTop();
435                         var iScrollDelta = iScrollTop - that.s.screen.scrollTop;
436                         that.s.screen.y += iScrollDelta;
437
438                         if ( that.s.screen.height - that.s.screen.y + iScrollTop < 50 )
439                         {
440                                 $('html, body').animate( {
441                                         "scrollTop": iScrollTop + 50
442                                 }, 240, 'linear' );
443                         }
444                         else if ( that.s.screen.y - iScrollTop < 50 )
445                         {
446                                 $('html, body').animate( {
447                                         "scrollTop": iScrollTop - 50
448                                 }, 240, 'linear' );
449                         }
450
451                         if ( that.s.dt.oScroll.sY !== "" )
452                         {
453                                 if ( that.s.screen.y > that.s.scroller.bottom - 50 )
454                                 {
455                                         $(that.s.dt.nTable.parentNode).animate( {
456                                                 "scrollTop": $(that.s.dt.nTable.parentNode).scrollTop() + 50
457                                         }, 240, 'linear' );
458                                 }
459                                 else if ( that.s.screen.y < that.s.scroller.top + 50 )
460                                 {
461                                         $(that.s.dt.nTable.parentNode).animate( {
462                                                 "scrollTop": $(that.s.dt.nTable.parentNode).scrollTop() - 50
463                                         }, 240, 'linear' );
464                                 }
465                         }
466                 }, 250 );
467         },
468
469
470         /**
471          * Mouse move event handler for during a move. See if we want to update the display based on the
472          * new cursor position
473          *  @method  _fnFillerDragMove
474          *  @param   {Object} e Event object
475          *  @returns void
476          */
477         "_fnFillerDragMove": function (e)
478         {
479                 if ( e.target && e.target.nodeName.toUpperCase() == "TD" &&
480                          e.target != this.s.drag.endTd )
481                 {
482                         var coords = this._fnTargetCoords( e.target );
483
484                         if ( this.c.mode == "y" && coords.x != this.s.drag.startX )
485                         {
486                                 e.target = $('tbody>tr:eq('+coords.y+')>td:eq('+this.s.drag.startX+')', this.dom.table)[0];
487                         }
488                         if ( this.c.mode == "x" && coords.y != this.s.drag.startY )
489                         {
490                                 e.target = $('tbody>tr:eq('+this.s.drag.startY+')>td:eq('+coords.x+')', this.dom.table)[0];
491                         }
492
493                         if ( this.c.mode == "either")
494                         {
495                                 if(coords.x != this.s.drag.startX )
496                                 {
497                                         e.target = $('tbody>tr:eq('+this.s.drag.startY+')>td:eq('+coords.x+')', this.dom.table)[0];
498                                 }
499                                 else if ( coords.y != this.s.drag.startY ) {
500                                         e.target = $('tbody>tr:eq('+coords.y+')>td:eq('+this.s.drag.startX+')', this.dom.table)[0];
501                                 }
502                         }
503
504                         // update coords
505                         if ( this.c.mode !== "both" ) {
506                                 coords = this._fnTargetCoords( e.target );
507                         }
508
509                         var drag = this.s.drag;
510                         drag.endTd = e.target;
511
512                         if ( coords.y >= this.s.drag.startY ) {
513                                 this._fnUpdateBorder( drag.startTd, drag.endTd );
514                         }
515                         else {
516                                 this._fnUpdateBorder( drag.endTd, drag.startTd );
517                         }
518                         this._fnFillerPosition( e.target );
519                 }
520
521                 /* Update the screen information so we can perform scrolling */
522                 this.s.screen.y = e.pageY;
523                 this.s.screen.scrollTop = $(document).scrollTop();
524
525                 if ( this.s.dt.oScroll.sY !== "" )
526                 {
527                         this.s.scroller.scrollTop = $(this.s.dt.nTable.parentNode).scrollTop();
528                         this.s.scroller.top = $(this.s.dt.nTable.parentNode).offset().top;
529                         this.s.scroller.bottom = this.s.scroller.top + $(this.s.dt.nTable.parentNode).height();
530                 }
531         },
532
533
534         /**
535          * Mouse release handler - end the drag and take action to update the cells with the needed values
536          *  @method  _fnFillerFinish
537          *  @param   {Object} e Event object
538          *  @returns void
539          */
540         "_fnFillerFinish": function (e)
541         {
542                 var that = this, i, iLen, j;
543
544                 $(document).unbind('mousemove.AutoFill mouseup.AutoFill');
545
546                 this.dom.borderTop.style.display = "none";
547                 this.dom.borderRight.style.display = "none";
548                 this.dom.borderBottom.style.display = "none";
549                 this.dom.borderLeft.style.display = "none";
550
551                 this.s.drag.dragging = false;
552
553                 clearInterval( this.s.screen.interval );
554
555                 var cells = [];
556                 var table = this.dom.table;
557                 var coordsStart = this._fnTargetCoords( this.s.drag.startTd );
558                 var coordsEnd = this._fnTargetCoords( this.s.drag.endTd );
559                 var columnIndex = function ( visIdx ) {
560                         return that.s.dt.oApi._fnVisibleToColumnIndex( that.s.dt, visIdx );
561                 };
562
563                 // xxx - urgh - there must be a way of reducing this...
564                 if ( coordsStart.y <= coordsEnd.y ) {
565                         for ( i=coordsStart.y ; i<=coordsEnd.y ; i++ ) {
566                                 if ( coordsStart.x <= coordsEnd.x ) {
567                                         for ( j=coordsStart.x ; j<=coordsEnd.x ; j++ ) {
568                                                 cells.push( {
569                                                         node:   $('tbody>tr:eq('+i+')>td:eq('+j+')', table)[0],
570                                                         x:      j - coordsStart.x,
571                                                         y:      i - coordsStart.y,
572                                                         colIdx: columnIndex( j )
573                                                 } );
574                                         }
575                                 }
576                                 else {
577                                         for ( j=coordsStart.x ; j>=coordsEnd.x ; j-- ) {
578                                                 cells.push( {
579                                                         node:   $('tbody>tr:eq('+i+')>td:eq('+j+')', table)[0],
580                                                         x:      j - coordsStart.x,
581                                                         y:      i - coordsStart.y,
582                                                         colIdx: columnIndex( j )
583                                                 } );
584                                         }
585                                 }
586                         }
587                 }
588                 else {
589                         for ( i=coordsStart.y ; i>=coordsEnd.y ; i-- ) {
590                                 if ( coordsStart.x <= coordsEnd.x ) {
591                                         for ( j=coordsStart.x ; j<=coordsEnd.x ; j++ ) {
592                                                 cells.push( {
593                                                         node:   $('tbody>tr:eq('+i+')>td:eq('+j+')', table)[0],
594                                                         x:      j - coordsStart.x,
595                                                         y:      i - coordsStart.y,
596                                                         colIdx: columnIndex( j )
597                                                 } );
598                                         }
599                                 }
600                                 else {
601                                         for ( j=coordsStart.x ; j>=coordsEnd.x ; j-- ) {
602                                                 cells.push( {
603                                                         node:   $('tbody>tr:eq('+i+')>td:eq('+j+')', table)[0],
604                                                         x:      coordsStart.x - j,
605                                                         y:      coordsStart.y - i,
606                                                         colIdx: columnIndex( j )
607                                                 } );
608                                         }
609                                 }
610                         }
611                 }
612
613                 // An auto-fill requires 2 or more cells
614                 if ( cells.length <= 1 ) {
615                         return;
616                 }
617
618                 var edited = [];
619                 var previous;
620
621                 for ( i=0, iLen=cells.length ; i<iLen ; i++ ) {
622                         var cell      = cells[i];
623                         var column    = this.s.columns[ cell.colIdx ];
624                         var read      = column.read.call( column, cell.node );
625                         var stepValue = column.step.call( column, cell.node, read, previous, i, cell.x, cell.y );
626
627                         column.write.call( column, cell.node, stepValue );
628
629                         previous = stepValue;
630                         edited.push( {
631                                 cell:     cell,
632                                 colIdx:   cell.colIdx,
633                                 newValue: stepValue,
634                                 oldValue: read
635                         } );
636                 }
637
638                 if ( this.c.complete !== null ) {
639                         this.c.complete.call( this, edited );
640                 }
641
642                 // In 1.10 we can do a static draw
643                 if ( DataTable.Api ) {
644                         new DataTable.Api( this.s.dt ).draw( false );
645                 }
646                 else {
647                         this.s.dt.oInstance.fnDraw();
648                 }
649         },
650
651
652         /**
653          * Display the drag handle on mouse over cell
654          *  @method  _fnFillerDisplay
655          *  @param   {Object} e Event object
656          *  @returns void
657          */
658         "_fnFillerDisplay": function (e)
659         {
660                 var filler = this.dom.filler;
661
662                 /* Don't display automatically when dragging */
663                 if ( this.s.drag.dragging)
664                 {
665                         return;
666                 }
667
668                 /* Check that we are allowed to AutoFill this column or not */
669                 var nTd = (e.target.nodeName.toLowerCase() == 'td') ? e.target : $(e.target).parents('td')[0];
670                 var iX = this._fnTargetCoords(nTd).column;
671                 if ( !this.s.columns[iX].enable )
672                 {
673                         filler.style.display = "none";
674                         return;
675                 }
676
677                 if (e.type == 'mouseover')
678                 {
679                         this.dom.currentTarget = nTd;
680                         this._fnFillerPosition( nTd );
681
682                         filler.style.display = "block";
683                 }
684                 else if ( !e.relatedTarget || !e.relatedTarget.className.match(/AutoFill/) )
685                 {
686                         filler.style.display = "none";
687                 }
688         },
689
690
691         /**
692          * Position the filler icon over a cell
693          *  @method  _fnFillerPosition
694          *  @param   {Node} nTd Cell to position filler icon over
695          *  @returns void
696          */
697         "_fnFillerPosition": function ( nTd )
698         {
699                 var offset = $(nTd).offset();
700                 var filler = this.dom.filler;
701                 filler.style.top = (offset.top - (this.s.filler.height / 2)-1 + $(nTd).outerHeight())+"px";
702                 filler.style.left = (offset.left - (this.s.filler.width / 2)-1 + $(nTd).outerWidth())+"px";
703         }
704 };
705
706
707 // Alias for access
708 DataTable.AutoFill = AutoFill;
709 DataTable.AutoFill = AutoFill;
710
711
712
713 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
714  * Constants
715  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
716
717 /**
718  * AutoFill version
719  *  @constant  version
720  *  @type      String
721  *  @default   See code
722  */
723 AutoFill.version = "1.2.1";
724
725
726 /**
727  * AutoFill defaults
728  *  @namespace
729  */
730 AutoFill.defaults = {
731         /**
732          * Mode for dragging (restrict to y-axis only, x-axis only, either one or none):
733          *
734          *  * `y`      - y-axis only (default)
735          *  * `x`      - x-axis only
736          *  * `either` - either one, but not both axis at the same time
737          *  * `both`   - multiple cells allowed
738          *
739          * @type {string}
740          * @default `y`
741          */
742         mode: 'y',
743
744         complete: null,
745
746         /**
747          * Column definition defaults
748          *  @namespace
749          */
750         column: {
751                 /**
752                  * If AutoFill should be enabled on this column
753                  *
754                  * @type {boolean}
755                  * @default true
756                  */
757                 enable: true,
758
759                 /**
760                  * Allow automatic increment / decrement on this column if a number
761                  * is found.
762                  *
763                  * @type {boolean}
764                  * @default true
765                  */
766                 increment: true,
767
768                 /**
769                  * Cell read function
770                  *
771                  * Default function will simply read the value from the HTML of the
772                  * cell.
773                  *
774                  * @type   {function}
775                  * @param  {node} cell `th` / `td` element to read the value from
776                  * @return {string}    Data that has been read
777                  */
778                 read: function ( cell ) {
779                         return $(cell).html();
780                 },
781
782                 /**
783                  * Cell write function
784                  *
785                  * Default function will simply write to the HTML and tell the DataTable
786                  * to update.
787                  *
788                  * @type   {function}
789                  * @param  {node} cell `th` / `td` element to write the value to
790                  * @return {string}    Data two write
791                  */
792                 write: function ( cell, val ) {
793                         var table = $(cell).parents('table');
794                         if ( DataTable.Api ) {
795                                 // 1.10
796                                 table.DataTable().cell( cell ).data( val );
797                         }
798                         else {
799                                 // 1.9
800                                 var dt = table.dataTable();
801                                 var pos = dt.fnGetPosition( cell );
802                                 dt.fnUpdate( val, pos[0], pos[2], false );
803                         }
804                 },
805
806                 /**
807                  * Step function. This provides the ability to customise how the values
808                  * are incremented.
809                  *
810                  * @param  {node} cell `th` / `td` element that is being operated upon
811                  * @param  {string} read Cell value from `read` function
812                  * @param  {string} last Value of the previous cell
813                  * @param  {integer} i Loop counter
814                  * @param  {integer} x Cell x-position in the current auto-fill. The
815                  *   starting cell is coordinate 0 regardless of its physical position
816                  *   in the DataTable.
817                  * @param  {integer} y Cell y-position in the current auto-fill. The
818                  *   starting cell is coordinate 0 regardless of its physical position
819                  *   in the DataTable.
820                  * @return {string} Value to write
821                  */
822                 step: function ( cell, read, last, i, x, y ) {
823                         // Increment a number if it is found
824                         var re = /(\-?\d+)/;
825                         var match = this.increment && last ? last.match(re) : null;
826                         if ( match ) {
827                                 return last.replace( re, parseInt(match[1],10) + (x<0 || y<0 ? -1 : 1) );
828                         }
829                         return last === undefined ?
830                                 read :
831                                 last;
832                 }
833         }
834 };
835
836 return AutoFill;
837 };
838
839
840 // Define as an AMD module if possible
841 if ( typeof define === 'function' && define.amd ) {
842         define( ['jquery', 'datatables'], factory );
843 }
844 else if ( typeof exports === 'object' ) {
845     // Node/CommonJS
846     factory( require('jquery'), require('datatables') );
847 }
848 else if ( jQuery && !jQuery.fn.dataTable.AutoFill ) {
849         // Otherwise simply initialise as normal, stopping multiple evaluation
850         factory( jQuery, jQuery.fn.dataTable );
851 }
852
853
854 }(window, document));
855