jquery-datatables-rails 1.10.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Readme.md CHANGED
@@ -2,31 +2,38 @@
2
2
 
3
3
  This gem packages the jQuery [DataTables](http://datatables.net/) plugin for easy use with the Rails 3.1+ asset pipleine.
4
4
 
5
- It provides all the basic DataTables files, but not (yet) the extras.
5
+ It provides all the basic DataTables files, and a few of the extras.
6
6
 
7
- ## Installation
7
+ ## General Installation
8
+
9
+ 1. Add to the assets group in your Gemfile:
10
+
11
+ `gem 'jquery-datatables-rails'`
12
+
13
+ 1. Install the gem:
14
+
15
+ `bundle install`
8
16
 
9
- 1. Add `gem 'jquery-datatables-rails'` to the assets group in your Gemfile and run `bundle install`.
10
17
  1. Add the JavaScript to `application.js`:
11
18
 
12
- `//= require dataTables/jquery.dataTables`
19
+ `//= require dataTables/jquery.dataTables`
13
20
 
14
21
  1. Add the stylesheets to `application.css`:
15
22
 
16
- `*= require dataTables/jquery.dataTables`
23
+ `*= require dataTables/jquery.dataTables`
17
24
 
18
- ## Twitter Bootstrap 2 support
25
+ ## Twitter Bootstrap 2 Installation
19
26
 
20
- 1. Add the JavaScript to `application.js`:
27
+ 1. Complete steps 1-3 of the General Installation
28
+ 1. Add some more JavaScript to `application.js`:
21
29
 
22
- `//= require dataTables/jquery.dataTables.bootstrap`
30
+ `//= require dataTables/jquery.dataTables.bootstrap`
23
31
 
24
- 1. Remove the initial stylesheets from `application.css`
25
- 1. Add the stylesheets to `application.css`:
32
+ 1. Add this (and only this) stylesheet to `application.css`:
26
33
 
27
- `*= require dataTables/jquery.dataTables.bootstrap`
34
+ `*= require dataTables/jquery.dataTables.bootstrap`
28
35
 
29
- 1. Initialize your datatables like this:
36
+ 1. Initialize your datatables using one of these options:
30
37
 
31
38
  ```javascript
32
39
  // For fluid containers
@@ -34,7 +41,8 @@ $('.datatable').dataTable({
34
41
  "sDom": "<'row-fluid'<'span6'l><'span6'f>r>t<'row-fluid'<'span6'i><'span6'p>>",
35
42
  "sPaginationType": "bootstrap"
36
43
  });
37
-
44
+ ```
45
+ ```javascript
38
46
  // For fixed width containers
39
47
  $('.datatable').dataTable({
40
48
  "sDom": "<'row'<'span6'l><'span6'f>r>t<'row'<'span6'i><'span6'p>>",
@@ -47,29 +55,34 @@ $('.datatable').dataTable({
47
55
  Only a few plugins are currently available
48
56
 
49
57
  * api
50
- * fnReloadAjax
51
- * fnGetColumnData
58
+ * fnReloadAjax
59
+ * fnGetColumnData
52
60
  * sorting
53
- * numbersHtml
61
+ * numbersHtml
54
62
  * typeDetection
55
- * numberHtml
63
+ * numberHtml
56
64
 
57
- Check out the [assets directory][assets].
65
+ These files can be found in the [assets directory][assets].
58
66
 
59
67
  ## Extras
60
68
 
61
- Only a few extras are currently available:
69
+ Only the official extras are available:
62
70
 
71
+ * AutoFill
72
+ * ColReorder
73
+ * ColVis
63
74
  * FixedColumns
64
75
  * FixedHeader
76
+ * KeyTable
77
+ * Scroller
78
+ * TableTools
65
79
 
66
80
  To add an extra into your application, include it like follow:
67
81
 
68
- `//= require dataTables/extras/[ExtraName]`
82
+ //= require dataTables/extras/[ExtraName]
69
83
 
70
84
  Make sure to also add it's initialization as described on [datatables extras' site][datatables_extras]
71
85
 
72
86
 
73
- [assets]: https://github.com/rweng/jquery-datatables-rails/tree/master/vendor/assets/javascripts
74
- [extras]: https://github.com/rweng/jquery-datatables-rails/tree/master/vendor/assets/javascripts/dataTables/extras
87
+ [assets]: https://github.com/rweng/jquery-datatables-rails/tree/master/vendor/assets/javascripts/dataTables
75
88
  [datatables_extras]: http://datatables.net/extras/
@@ -1,7 +1,7 @@
1
1
  module Jquery
2
2
  module Datatables
3
3
  module Rails
4
- VERSION = "1.10.0"
4
+ VERSION = "1.11.0"
5
5
  end
6
6
  end
7
7
  end
@@ -0,0 +1,820 @@
1
+ /*
2
+ * File: AutoFill.js
3
+ * Version: 1.1.2
4
+ * CVS: $Id$
5
+ * Description: AutoFill for DataTables
6
+ * Author: Allan Jardine (www.sprymedia.co.uk)
7
+ * Created: Mon 6 Sep 2010 16:54:41 BST
8
+ * Modified: $Date$ by $Author$
9
+ * Language: Javascript
10
+ * License: GPL v2 or BSD 3 point
11
+ * Project: DataTables
12
+ * Contact: www.sprymedia.co.uk/contact
13
+ *
14
+ * Copyright 2010-2011 Allan Jardine, all rights reserved.
15
+ *
16
+ * This source file is free software, under either the GPL v2 license or a
17
+ * BSD style license, available at:
18
+ * http://datatables.net/license_gpl2
19
+ * http://datatables.net/license_bsd
20
+ *
21
+ */
22
+
23
+ /* Global scope for AutoFill */
24
+ var AutoFill;
25
+
26
+ (function($) {
27
+
28
+ /**
29
+ * AutoFill provides Excel like auto fill features for a DataTable
30
+ * @class AutoFill
31
+ * @constructor
32
+ * @param {object} DataTables settings object
33
+ * @param {object} Configuration object for AutoFill
34
+ */
35
+ AutoFill = function( oDT, oConfig )
36
+ {
37
+ /* Santiy check that we are a new instance */
38
+ if ( !this.CLASS || this.CLASS != "AutoFill" )
39
+ {
40
+ alert( "Warning: AutoFill must be initialised with the keyword 'new'" );
41
+ return;
42
+ }
43
+
44
+ if ( !$.fn.dataTableExt.fnVersionCheck('1.7.0') )
45
+ {
46
+ alert( "Warning: AutoFill requires DataTables 1.7 or greater - www.datatables.net/download");
47
+ return;
48
+ }
49
+
50
+
51
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
52
+ * Public class variables
53
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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
+ /**
107
+ * @namespace Information stored for each column. An array of objects
108
+ */
109
+ "columns": []
110
+ };
111
+
112
+
113
+ /**
114
+ * @namespace Common and useful DOM elements for the class instance
115
+ */
116
+ this.dom = {
117
+ "table": null,
118
+ "filler": null,
119
+ "borderTop": null,
120
+ "borderRight": null,
121
+ "borderBottom": null,
122
+ "borderLeft": null,
123
+ "currentTarget": null
124
+ };
125
+
126
+
127
+
128
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
129
+ * Public class methods
130
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
131
+
132
+ /**
133
+ * Retreieve the settings object from an instance
134
+ * @method fnSettings
135
+ * @returns {object} AutoFill settings object
136
+ */
137
+ this.fnSettings = function () {
138
+ return this.s;
139
+ };
140
+
141
+
142
+ /* Constructor logic */
143
+ this._fnInit( oDT, oConfig );
144
+ return this;
145
+ };
146
+
147
+
148
+
149
+ AutoFill.prototype = {
150
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
151
+ * Private methods (they are of course public in JS, but recommended as private)
152
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
153
+
154
+ /**
155
+ * Initialisation
156
+ * @method _fnInit
157
+ * @param {object} oDT DataTables settings object
158
+ * @param {object} oConfig Configuration object for AutoFill
159
+ * @returns void
160
+ */
161
+ "_fnInit": function ( oDT, oConfig )
162
+ {
163
+ var
164
+ that = this,
165
+ i, iLen;
166
+
167
+ /*
168
+ * Settings
169
+ */
170
+ this.s.dt = oDT.fnSettings();
171
+
172
+ this.dom.table = this.s.dt.nTable;
173
+
174
+ /* Add and configure the columns */
175
+ for ( i=0, iLen=this.s.dt.aoColumns.length ; i<iLen ; i++ )
176
+ {
177
+ this._fnAddColumn( i );
178
+ }
179
+
180
+ if ( typeof oConfig != 'undefined' && typeof oConfig.aoColumnDefs != 'undefined' )
181
+ {
182
+ this._fnColumnDefs( oConfig.aoColumnDefs );
183
+ }
184
+
185
+ if ( typeof oConfig != 'undefined' && typeof oConfig.aoColumns != 'undefined' )
186
+ {
187
+ this._fnColumnsAll( oConfig.aoColumns );
188
+ }
189
+
190
+
191
+ /*
192
+ * DOM
193
+ */
194
+
195
+ /* Auto Fill click and drag icon */
196
+ var filler = document.createElement('div');
197
+ filler.className = "AutoFill_filler";
198
+ document.body.appendChild( filler );
199
+ this.dom.filler = filler;
200
+
201
+ filler.style.display = "block";
202
+ this.s.filler.height = $(filler).height();
203
+ this.s.filler.width = $(filler).width();
204
+ filler.style.display = "none";
205
+
206
+ /* Border display - one div for each side. We can't just use a single one with a border, as
207
+ * we want the events to effectively pass through the transparent bit of the box
208
+ */
209
+ var border;
210
+ var appender = document.body;
211
+ if ( that.s.dt.oScroll.sY !== "" )
212
+ {
213
+ that.s.dt.nTable.parentNode.style.position = "relative";
214
+ appender = that.s.dt.nTable.parentNode;
215
+ }
216
+
217
+ border = document.createElement('div');
218
+ border.className = "AutoFill_border";
219
+ appender.appendChild( border );
220
+ this.dom.borderTop = border;
221
+
222
+ border = document.createElement('div');
223
+ border.className = "AutoFill_border";
224
+ appender.appendChild( border );
225
+ this.dom.borderRight = border;
226
+
227
+ border = document.createElement('div');
228
+ border.className = "AutoFill_border";
229
+ appender.appendChild( border );
230
+ this.dom.borderBottom = border;
231
+
232
+ border = document.createElement('div');
233
+ border.className = "AutoFill_border";
234
+ appender.appendChild( border );
235
+ this.dom.borderLeft = border;
236
+
237
+ /*
238
+ * Events
239
+ */
240
+
241
+ $(filler).mousedown( function (e) {
242
+ this.onselectstart = function() { return false; };
243
+ that._fnFillerDragStart.call( that, e );
244
+ return false;
245
+ } );
246
+
247
+ $('tbody>tr>td', this.dom.table).live( 'mouseover mouseout', function (e) {
248
+ that._fnFillerDisplay.call( that, e );
249
+ } );
250
+ },
251
+
252
+
253
+ "_fnColumnDefs": function ( aoColumnDefs )
254
+ {
255
+ var
256
+ i, j, k, iLen, jLen, kLen,
257
+ aTargets;
258
+
259
+ /* Loop over the column defs array - loop in reverse so first instace has priority */
260
+ for ( i=aoColumnDefs.length-1 ; i>=0 ; i-- )
261
+ {
262
+ /* Each column def can target multiple columns, as it is an array */
263
+ aTargets = aoColumnDefs[i].aTargets;
264
+ for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
265
+ {
266
+ if ( typeof aTargets[j] == 'number' && aTargets[j] >= 0 )
267
+ {
268
+ /* 0+ integer, left to right column counting. */
269
+ this._fnColumnOptions( aTargets[j], aoColumnDefs[i] );
270
+ }
271
+ else if ( typeof aTargets[j] == 'number' && aTargets[j] < 0 )
272
+ {
273
+ /* Negative integer, right to left column counting */
274
+ this._fnColumnOptions( this.s.dt.aoColumns.length+aTargets[j], aoColumnDefs[i] );
275
+ }
276
+ else if ( typeof aTargets[j] == 'string' )
277
+ {
278
+ /* Class name matching on TH element */
279
+ for ( k=0, kLen=this.s.dt.aoColumns.length ; k<kLen ; k++ )
280
+ {
281
+ if ( aTargets[j] == "_all" ||
282
+ this.s.dt.aoColumns[k].nTh.className.indexOf( aTargets[j] ) != -1 )
283
+ {
284
+ this._fnColumnOptions( k, aoColumnDefs[i] );
285
+ }
286
+ }
287
+ }
288
+ }
289
+ }
290
+ },
291
+
292
+
293
+ "_fnColumnsAll": function ( aoColumns )
294
+ {
295
+ for ( var i=0, iLen=this.s.dt.aoColumns.length ; i<iLen ; i++ )
296
+ {
297
+ this._fnColumnOptions( i, aoColumns[i] );
298
+ }
299
+ },
300
+
301
+
302
+ "_fnAddColumn": function ( i )
303
+ {
304
+ this.s.columns[i] = {
305
+ "enable": true,
306
+ "read": this._fnReadCell,
307
+ "write": this._fnWriteCell,
308
+ "step": this._fnStep,
309
+ "complete": null
310
+ };
311
+ },
312
+
313
+ "_fnColumnOptions": function ( i, opts )
314
+ {
315
+ if ( typeof opts.bEnable != 'undefined' )
316
+ {
317
+ this.s.columns[i].enable = opts.bEnable;
318
+ }
319
+
320
+ if ( typeof opts.fnRead != 'undefined' )
321
+ {
322
+ this.s.columns[i].read = opts.fnRead;
323
+ }
324
+
325
+ if ( typeof opts.fnWrite != 'undefined' )
326
+ {
327
+ this.s.columns[i].write = opts.fnWrite;
328
+ }
329
+
330
+ if ( typeof opts.fnStep != 'undefined' )
331
+ {
332
+ this.s.columns[i].step = opts.fnStep;
333
+ }
334
+
335
+ if ( typeof opts.fnCallback != 'undefined' )
336
+ {
337
+ this.s.columns[i].complete = opts.fnCallback;
338
+ }
339
+ },
340
+
341
+
342
+ /**
343
+ * Find out the coordinates of a given TD cell in a table
344
+ * @method _fnTargetCoords
345
+ * @param {Node} nTd
346
+ * @returns {Object} x and y properties, for the position of the cell in the tables DOM
347
+ */
348
+ "_fnTargetCoords": function ( nTd )
349
+ {
350
+ var nTr = $(nTd).parents('tr')[0];
351
+
352
+ return {
353
+ "x": $('td', nTr).index(nTd),
354
+ "y": $('tr', nTr.parentNode).index(nTr)
355
+ };
356
+ },
357
+
358
+
359
+ /**
360
+ * Display the border around one or more cells (from start to end)
361
+ * @method _fnUpdateBorder
362
+ * @param {Node} nStart Starting cell
363
+ * @param {Node} nEnd Ending cell
364
+ * @returns void
365
+ */
366
+ "_fnUpdateBorder": function ( nStart, nEnd )
367
+ {
368
+ var
369
+ border = this.s.border.width,
370
+ offsetStart = $(nStart).offset(),
371
+ offsetEnd = $(nEnd).offset(),
372
+ x1 = offsetStart.left - border,
373
+ x2 = offsetEnd.left + $(nEnd).outerWidth(),
374
+ y1 = offsetStart.top - border,
375
+ y2 = offsetEnd.top + $(nEnd).outerHeight(),
376
+ width = offsetEnd.left + $(nEnd).outerWidth() - offsetStart.left + (2*border),
377
+ height = offsetEnd.top + $(nEnd).outerHeight() - offsetStart.top + (2*border),
378
+ oStyle;
379
+
380
+ if ( this.s.dt.oScroll.sY !== "" )
381
+ {
382
+ /* The border elements are inside the DT scroller - so position relative to that */
383
+ var
384
+ offsetScroll = $(this.s.dt.nTable.parentNode).offset(),
385
+ scrollTop = $(this.s.dt.nTable.parentNode).scrollTop(),
386
+ scrollLeft = $(this.s.dt.nTable.parentNode).scrollLeft();
387
+
388
+ x1 -= offsetScroll.left - scrollLeft;
389
+ x2 -= offsetScroll.left - scrollLeft;
390
+ y1 -= offsetScroll.top - scrollTop;
391
+ y2 -= offsetScroll.top - scrollTop;
392
+ }
393
+
394
+ /* Top */
395
+ oStyle = this.dom.borderTop.style;
396
+ oStyle.top = y1+"px";
397
+ oStyle.left = x1+"px";
398
+ oStyle.height = this.s.border.width+"px";
399
+ oStyle.width = width+"px";
400
+
401
+ /* Bottom */
402
+ oStyle = this.dom.borderBottom.style;
403
+ oStyle.top = y2+"px";
404
+ oStyle.left = x1+"px";
405
+ oStyle.height = this.s.border.width+"px";
406
+ oStyle.width = width+"px";
407
+
408
+ /* Left */
409
+ oStyle = this.dom.borderLeft.style;
410
+ oStyle.top = y1+"px";
411
+ oStyle.left = x1+"px";
412
+ oStyle.height = height+"px";
413
+ oStyle.width = this.s.border.width+"px";
414
+
415
+ /* Right */
416
+ oStyle = this.dom.borderRight.style;
417
+ oStyle.top = y1+"px";
418
+ oStyle.left = x2+"px";
419
+ oStyle.height = height+"px";
420
+ oStyle.width = this.s.border.width+"px";
421
+ },
422
+
423
+
424
+ /**
425
+ * Mouse down event handler for starting a drag
426
+ * @method _fnFillerDragStart
427
+ * @param {Object} e Event object
428
+ * @returns void
429
+ */
430
+ "_fnFillerDragStart": function (e)
431
+ {
432
+ var that = this;
433
+ var startingTd = this.dom.currentTarget;
434
+
435
+ this.s.drag.dragging = true;
436
+
437
+ that.dom.borderTop.style.display = "block";
438
+ that.dom.borderRight.style.display = "block";
439
+ that.dom.borderBottom.style.display = "block";
440
+ that.dom.borderLeft.style.display = "block";
441
+
442
+ var coords = this._fnTargetCoords( startingTd );
443
+ this.s.drag.startX = coords.x;
444
+ this.s.drag.startY = coords.y;
445
+
446
+ this.s.drag.startTd = startingTd;
447
+ this.s.drag.endTd = startingTd;
448
+
449
+ this._fnUpdateBorder( startingTd, startingTd );
450
+
451
+ $(document).bind('mousemove.AutoFill', function (e) {
452
+ that._fnFillerDragMove.call( that, e );
453
+ } );
454
+
455
+ $(document).bind('mouseup.AutoFill', function (e) {
456
+ that._fnFillerFinish.call( that, e );
457
+ } );
458
+
459
+ /* Scrolling information cache */
460
+ this.s.screen.y = e.pageY;
461
+ this.s.screen.height = $(window).height();
462
+ this.s.screen.scrollTop = $(document).scrollTop();
463
+
464
+ if ( this.s.dt.oScroll.sY !== "" )
465
+ {
466
+ this.s.scroller.top = $(this.s.dt.nTable.parentNode).offset().top;
467
+ this.s.scroller.bottom = this.s.scroller.top + $(this.s.dt.nTable.parentNode).height();
468
+ }
469
+
470
+ /* Scrolling handler - we set an interval (which is cancelled on mouse up) which will fire
471
+ * regularly and see if we need to do any scrolling
472
+ */
473
+ this.s.screen.interval = setInterval( function () {
474
+ var iScrollTop = $(document).scrollTop();
475
+ var iScrollDelta = iScrollTop - that.s.screen.scrollTop;
476
+ that.s.screen.y += iScrollDelta;
477
+
478
+ if ( that.s.screen.height - that.s.screen.y + iScrollTop < 50 )
479
+ {
480
+ $('html, body').animate( {
481
+ "scrollTop": iScrollTop + 50
482
+ }, 240, 'linear' );
483
+ }
484
+ else if ( that.s.screen.y - iScrollTop < 50 )
485
+ {
486
+ $('html, body').animate( {
487
+ "scrollTop": iScrollTop - 50
488
+ }, 240, 'linear' );
489
+ }
490
+
491
+ if ( that.s.dt.oScroll.sY !== "" )
492
+ {
493
+ if ( that.s.screen.y > that.s.scroller.bottom - 50 )
494
+ {
495
+ $(that.s.dt.nTable.parentNode).animate( {
496
+ "scrollTop": $(that.s.dt.nTable.parentNode).scrollTop() + 50
497
+ }, 240, 'linear' );
498
+ }
499
+ else if ( that.s.screen.y < that.s.scroller.top + 50 )
500
+ {
501
+ $(that.s.dt.nTable.parentNode).animate( {
502
+ "scrollTop": $(that.s.dt.nTable.parentNode).scrollTop() - 50
503
+ }, 240, 'linear' );
504
+ }
505
+ }
506
+ }, 250 );
507
+ },
508
+
509
+
510
+ /**
511
+ * Mouse move event handler for during a move. See if we want to update the display based on the
512
+ * new cursor position
513
+ * @method _fnFillerDragMove
514
+ * @param {Object} e Event object
515
+ * @returns void
516
+ */
517
+ "_fnFillerDragMove": function (e)
518
+ {
519
+ if ( e.target && e.target.nodeName.toUpperCase() == "TD" &&
520
+ e.target != this.s.drag.endTd )
521
+ {
522
+ var coords = this._fnTargetCoords( e.target );
523
+
524
+ if ( coords.x != this.s.drag.startX )
525
+ {
526
+ e.target = $('tbody>tr:eq('+coords.y+')>td:eq('+this.s.drag.startX+')', this.dom.table)[0];
527
+ coords = this._fnTargetCoords( e.target );
528
+ }
529
+
530
+ if ( coords.x == this.s.drag.startX )
531
+ {
532
+ var drag = this.s.drag;
533
+ drag.endTd = e.target;
534
+
535
+ if ( coords.y >= this.s.drag.startY )
536
+ {
537
+ this._fnUpdateBorder( drag.startTd, drag.endTd );
538
+ }
539
+ else
540
+ {
541
+ this._fnUpdateBorder( drag.endTd, drag.startTd );
542
+ }
543
+ this._fnFillerPosition( e.target );
544
+ }
545
+ }
546
+
547
+ /* Update the screen information so we can perform scrolling */
548
+ this.s.screen.y = e.pageY;
549
+ this.s.screen.scrollTop = $(document).scrollTop();
550
+
551
+ if ( this.s.dt.oScroll.sY !== "" )
552
+ {
553
+ this.s.scroller.scrollTop = $(this.s.dt.nTable.parentNode).scrollTop();
554
+ this.s.scroller.top = $(this.s.dt.nTable.parentNode).offset().top;
555
+ this.s.scroller.bottom = this.s.scroller.top + $(this.s.dt.nTable.parentNode).height();
556
+ }
557
+ },
558
+
559
+
560
+ /**
561
+ * Mouse release handler - end the drag and take action to update the cells with the needed values
562
+ * @method _fnFillerFinish
563
+ * @param {Object} e Event object
564
+ * @returns void
565
+ */
566
+ "_fnFillerFinish": function (e)
567
+ {
568
+ var that = this;
569
+
570
+ $(document).unbind('mousemove.AutoFill');
571
+ $(document).unbind('mouseup.AutoFill');
572
+
573
+ this.dom.borderTop.style.display = "none";
574
+ this.dom.borderRight.style.display = "none";
575
+ this.dom.borderBottom.style.display = "none";
576
+ this.dom.borderLeft.style.display = "none";
577
+
578
+ this.s.drag.dragging = false;
579
+
580
+ clearInterval( this.s.screen.interval );
581
+
582
+ var coordsStart = this._fnTargetCoords( this.s.drag.startTd );
583
+ var coordsEnd = this._fnTargetCoords( this.s.drag.endTd );
584
+ var aTds = [];
585
+ var bIncrement;
586
+
587
+ if ( coordsStart.y <= coordsEnd.y )
588
+ {
589
+ bIncrement = true;
590
+ for ( i=coordsStart.y ; i<=coordsEnd.y ; i++ )
591
+ {
592
+ aTds.push( $('tbody>tr:eq('+i+')>td:eq('+coordsStart.x+')', this.dom.table)[0] );
593
+ }
594
+ }
595
+ else
596
+ {
597
+ bIncrement = false;
598
+ for ( i=coordsStart.y ; i>=coordsEnd.y ; i-- )
599
+ {
600
+ aTds.push( $('tbody>tr:eq('+i+')>td:eq('+coordsStart.x+')', this.dom.table)[0] );
601
+ }
602
+ }
603
+
604
+
605
+ var iColumn = coordsStart.x;
606
+ var bLast = false;
607
+ var aoEdited = [];
608
+ var sStart = this.s.columns[iColumn].read.call( this, this.s.drag.startTd );
609
+ var oPrepped = this._fnPrep( sStart );
610
+
611
+ for ( i=0, iLen=aTds.length ; i<iLen ; i++ )
612
+ {
613
+ if ( i==iLen-1 )
614
+ {
615
+ bLast = true;
616
+ }
617
+
618
+ var original = this.s.columns[iColumn].read.call( this, aTds[i] );
619
+ var step = this.s.columns[iColumn].step.call( this, aTds[i], oPrepped, i, bIncrement,
620
+ 'SPRYMEDIA_AUTOFILL_STEPPER' );
621
+ this.s.columns[iColumn].write.call( this, aTds[i], step, bLast );
622
+
623
+ aoEdited.push( {
624
+ "td": aTds[i],
625
+ "newValue": step,
626
+ "oldValue": original
627
+ } );
628
+ }
629
+
630
+ if ( this.s.columns[iColumn].complete !== null )
631
+ {
632
+ this.s.columns[iColumn].complete.call( this, aoEdited );
633
+ }
634
+ },
635
+
636
+
637
+ /**
638
+ * Chunk a string such that it can be filled in by the stepper function
639
+ * @method _fnPrep
640
+ * @param {String} sStr String to prep
641
+ * @returns {Object} with parameters, iStart, sStr and sPostFix
642
+ */
643
+ "_fnPrep": function ( sStr )
644
+ {
645
+ var aMatch = sStr.match(/[\d\.]+/g);
646
+ if ( !aMatch || aMatch.length === 0 )
647
+ {
648
+ return {
649
+ "iStart": 0,
650
+ "sStr": sStr,
651
+ "sPostFix": ""
652
+ };
653
+ }
654
+
655
+ var sLast = aMatch[ aMatch.length-1 ];
656
+ var num = parseInt(sLast, 10);
657
+ var regex = new RegExp( '^(.*)'+sLast+'(.*?)$' );
658
+ var decimal = sLast.match(/\./) ? "."+sLast.split('.')[1] : "";
659
+
660
+ return {
661
+ "iStart": num,
662
+ "sStr": sStr.replace(regex, "$1SPRYMEDIA_AUTOFILL_STEPPER$2"),
663
+ "sPostFix": decimal
664
+ };
665
+ },
666
+
667
+
668
+ /**
669
+ * Render a string for it's position in the table after the drag (incrememt numbers)
670
+ * @method _fnStep
671
+ * @param {Node} nTd Cell being written to
672
+ * @param {Object} oPrepped Prepared object for the stepper (from _fnPrep)
673
+ * @param {Int} iDiff Step difference
674
+ * @param {Boolean} bIncrement Increment (true) or decriment (false)
675
+ * @param {String} sToken Token to replace
676
+ * @returns {String} Rendered information
677
+ */
678
+ "_fnStep": function ( nTd, oPrepped, iDiff, bIncrement, sToken )
679
+ {
680
+ var iReplace = bIncrement ? (oPrepped.iStart+iDiff) : (oPrepped.iStart-iDiff);
681
+ if ( isNaN(iReplace) )
682
+ {
683
+ iReplace = "";
684
+ }
685
+ return oPrepped.sStr.replace( sToken, iReplace+oPrepped.sPostFix );
686
+ },
687
+
688
+
689
+ /**
690
+ * Read informaiton from a cell, possibly using live DOM elements if suitable
691
+ * @method _fnReadCell
692
+ * @param {Node} nTd Cell to read
693
+ * @returns {String} Read value
694
+ */
695
+ "_fnReadCell": function ( nTd )
696
+ {
697
+ var jq = $('input', nTd);
698
+ if ( jq.length > 0 )
699
+ {
700
+ return $(jq).val();
701
+ }
702
+
703
+ jq = $('select', nTd);
704
+ if ( jq.length > 0 )
705
+ {
706
+ return $(jq).val();
707
+ }
708
+
709
+ return nTd.innerHTML;
710
+ },
711
+
712
+
713
+ /**
714
+ * Write informaiton to a cell, possibly using live DOM elements if suitable
715
+ * @method _fnWriteCell
716
+ * @param {Node} nTd Cell to write
717
+ * @param {String} sVal Value to write
718
+ * @param {Boolean} bLast Flag to show if this is that last update
719
+ * @returns void
720
+ */
721
+ "_fnWriteCell": function ( nTd, sVal, bLast )
722
+ {
723
+ var jq = $('input', nTd);
724
+ if ( jq.length > 0 )
725
+ {
726
+ $(jq).val( sVal );
727
+ return;
728
+ }
729
+
730
+ jq = $('select', nTd);
731
+ if ( jq.length > 0 )
732
+ {
733
+ $(jq).val( sVal );
734
+ return;
735
+ }
736
+
737
+ var pos = this.s.dt.oInstance.fnGetPosition( nTd );
738
+ this.s.dt.oInstance.fnUpdate( sVal, pos[0], pos[2], bLast );
739
+ },
740
+
741
+
742
+ /**
743
+ * Display the drag handle on mouse over cell
744
+ * @method _fnFillerDisplay
745
+ * @param {Object} e Event object
746
+ * @returns void
747
+ */
748
+ "_fnFillerDisplay": function (e)
749
+ {
750
+ /* Don't display automatically when dragging */
751
+ if ( this.s.drag.dragging)
752
+ {
753
+ return;
754
+ }
755
+
756
+ /* Check that we are allowed to AutoFill this column or not */
757
+ var nTd = (e.target.nodeName.toLowerCase() == 'td') ? e.target : $(e.target).parents('td')[0];
758
+ var iX = this._fnTargetCoords(nTd).x;
759
+ if ( !this.s.columns[iX].enable )
760
+ {
761
+ return;
762
+ }
763
+
764
+ var filler = this.dom.filler;
765
+ if (e.type == 'mouseover')
766
+ {
767
+ this.dom.currentTarget = nTd;
768
+ this._fnFillerPosition( nTd );
769
+
770
+ filler.style.display = "block";
771
+ }
772
+ else if ( !e.relatedTarget || !e.relatedTarget.className.match(/AutoFill/) )
773
+ {
774
+ filler.style.display = "none";
775
+ }
776
+ },
777
+
778
+
779
+ /**
780
+ * Position the filler icon over a cell
781
+ * @method _fnFillerPosition
782
+ * @param {Node} nTd Cell to position filler icon over
783
+ * @returns void
784
+ */
785
+ "_fnFillerPosition": function ( nTd )
786
+ {
787
+ var offset = $(nTd).offset();
788
+ var filler = this.dom.filler;
789
+ filler.style.top = (offset.top - (this.s.filler.height / 2)-1 + $(nTd).outerHeight())+"px";
790
+ filler.style.left = (offset.left - (this.s.filler.width / 2)-1 + $(nTd).outerWidth())+"px";
791
+ }
792
+ };
793
+
794
+
795
+
796
+
797
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
798
+ * Constants
799
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
800
+
801
+ /**
802
+ * Name of this class
803
+ * @constant CLASS
804
+ * @type String
805
+ * @default AutoFill
806
+ */
807
+ AutoFill.prototype.CLASS = "AutoFill";
808
+
809
+
810
+ /**
811
+ * AutoFill version
812
+ * @constant VERSION
813
+ * @type String
814
+ * @default 1.1.2
815
+ */
816
+ AutoFill.VERSION = "1.1.2";
817
+ AutoFill.prototype.VERSION = AutoFill.VERSION;
818
+
819
+
820
+ })(jQuery);