Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

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