jquery-datatables-rails 1.10.0 → 1.11.0

Sign up to get free protection for your applications and to get access to all the features.
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);