Subversion-Projekte lars-tiefland.faltradxxs.de

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
2 lars 1
/*! ColReorder 1.1.2
2
 * ©2010-2014 SpryMedia Ltd - datatables.net/license
3
 */
4
 
5
/**
6
 * @summary     ColReorder
7
 * @description Provide the ability to reorder columns in a DataTable
8
 * @version     1.1.2
9
 * @file        dataTables.colReorder.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
 
27
/**
28
 * Switch the key value pairing of an index array to be value key (i.e. the old value is now the
29
 * key). For example consider [ 2, 0, 1 ] this would be returned as [ 1, 2, 0 ].
30
 *  @method  fnInvertKeyValues
31
 *  @param   array aIn Array to switch around
32
 *  @returns array
33
 */
34
function fnInvertKeyValues( aIn )
35
{
36
	var aRet=[];
37
	for ( var i=0, iLen=aIn.length ; i<iLen ; i++ )
38
	{
39
		aRet[ aIn[i] ] = i;
40
	}
41
	return aRet;
42
}
43
 
44
 
45
/**
46
 * Modify an array by switching the position of two elements
47
 *  @method  fnArraySwitch
48
 *  @param   array aArray Array to consider, will be modified by reference (i.e. no return)
49
 *  @param   int iFrom From point
50
 *  @param   int iTo Insert point
51
 *  @returns void
52
 */
53
function fnArraySwitch( aArray, iFrom, iTo )
54
{
55
	var mStore = aArray.splice( iFrom, 1 )[0];
56
	aArray.splice( iTo, 0, mStore );
57
}
58
 
59
 
60
/**
61
 * Switch the positions of nodes in a parent node (note this is specifically designed for
62
 * table rows). Note this function considers all element nodes under the parent!
63
 *  @method  fnDomSwitch
64
 *  @param   string sTag Tag to consider
65
 *  @param   int iFrom Element to move
66
 *  @param   int Point to element the element to (before this point), can be null for append
67
 *  @returns void
68
 */
69
function fnDomSwitch( nParent, iFrom, iTo )
70
{
71
	var anTags = [];
72
	for ( var i=0, iLen=nParent.childNodes.length ; i<iLen ; i++ )
73
	{
74
		if ( nParent.childNodes[i].nodeType == 1 )
75
		{
76
			anTags.push( nParent.childNodes[i] );
77
		}
78
	}
79
	var nStore = anTags[ iFrom ];
80
 
81
	if ( iTo !== null )
82
	{
83
		nParent.insertBefore( nStore, anTags[iTo] );
84
	}
85
	else
86
	{
87
		nParent.appendChild( nStore );
88
	}
89
}
90
 
91
 
92
 
93
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
94
 * DataTables plug-in API functions
95
 *
96
 * This are required by ColReorder in order to perform the tasks required, and also keep this
97
 * code portable, to be used for other column reordering projects with DataTables, if needed.
98
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
99
 
100
 
101
/**
102
 * Plug-in for DataTables which will reorder the internal column structure by taking the column
103
 * from one position (iFrom) and insert it into a given point (iTo).
104
 *  @method  $.fn.dataTableExt.oApi.fnColReorder
105
 *  @param   object oSettings DataTables settings object - automatically added by DataTables!
106
 *  @param   int iFrom Take the column to be repositioned from this point
107
 *  @param   int iTo and insert it into this point
108
 *  @returns void
109
 */
110
$.fn.dataTableExt.oApi.fnColReorder = function ( oSettings, iFrom, iTo )
111
{
112
	var v110 = $.fn.dataTable.Api ? true : false;
113
	var i, iLen, j, jLen, iCols=oSettings.aoColumns.length, nTrs, oCol;
114
	var attrMap = function ( obj, prop, mapping ) {
115
		if ( ! obj[ prop ] ) {
116
			return;
117
		}
118
 
119
		var a = obj[ prop ].split('.');
120
		var num = a.shift();
121
 
122
		if ( isNaN( num*1 ) ) {
123
			return;
124
		}
125
 
126
		obj[ prop ] = mapping[ num*1 ]+'.'+a.join('.');
127
	};
128
 
129
	/* Sanity check in the input */
130
	if ( iFrom == iTo )
131
	{
132
		/* Pointless reorder */
133
		return;
134
	}
135
 
136
	if ( iFrom < 0 || iFrom >= iCols )
137
	{
138
		this.oApi._fnLog( oSettings, 1, "ColReorder 'from' index is out of bounds: "+iFrom );
139
		return;
140
	}
141
 
142
	if ( iTo < 0 || iTo >= iCols )
143
	{
144
		this.oApi._fnLog( oSettings, 1, "ColReorder 'to' index is out of bounds: "+iTo );
145
		return;
146
	}
147
 
148
	/*
149
	 * Calculate the new column array index, so we have a mapping between the old and new
150
	 */
151
	var aiMapping = [];
152
	for ( i=0, iLen=iCols ; i<iLen ; i++ )
153
	{
154
		aiMapping[i] = i;
155
	}
156
	fnArraySwitch( aiMapping, iFrom, iTo );
157
	var aiInvertMapping = fnInvertKeyValues( aiMapping );
158
 
159
 
160
	/*
161
	 * Convert all internal indexing to the new column order indexes
162
	 */
163
	/* Sorting */
164
	for ( i=0, iLen=oSettings.aaSorting.length ; i<iLen ; i++ )
165
	{
166
		oSettings.aaSorting[i][0] = aiInvertMapping[ oSettings.aaSorting[i][0] ];
167
	}
168
 
169
	/* Fixed sorting */
170
	if ( oSettings.aaSortingFixed !== null )
171
	{
172
		for ( i=0, iLen=oSettings.aaSortingFixed.length ; i<iLen ; i++ )
173
		{
174
			oSettings.aaSortingFixed[i][0] = aiInvertMapping[ oSettings.aaSortingFixed[i][0] ];
175
		}
176
	}
177
 
178
	/* Data column sorting (the column which the sort for a given column should take place on) */
179
	for ( i=0, iLen=iCols ; i<iLen ; i++ )
180
	{
181
		oCol = oSettings.aoColumns[i];
182
		for ( j=0, jLen=oCol.aDataSort.length ; j<jLen ; j++ )
183
		{
184
			oCol.aDataSort[j] = aiInvertMapping[ oCol.aDataSort[j] ];
185
		}
186
 
187
		// Update the column indexes
188
		if ( v110 ) {
189
			oCol.idx = aiInvertMapping[ oCol.idx ];
190
		}
191
	}
192
 
193
	if ( v110 ) {
194
		// Update 1.10 optimised sort class removal variable
195
		$.each( oSettings.aLastSort, function (i, val) {
196
			oSettings.aLastSort[i].src = aiInvertMapping[ val.src ];
197
		} );
198
	}
199
 
200
	/* Update the Get and Set functions for each column */
201
	for ( i=0, iLen=iCols ; i<iLen ; i++ )
202
	{
203
		oCol = oSettings.aoColumns[i];
204
 
205
		if ( typeof oCol.mData == 'number' ) {
206
			oCol.mData = aiInvertMapping[ oCol.mData ];
207
 
208
			// regenerate the get / set functions
209
			oSettings.oApi._fnColumnOptions( oSettings, i, {} );
210
		}
211
		else if ( $.isPlainObject( oCol.mData ) ) {
212
			// HTML5 data sourced
213
			attrMap( oCol.mData, '_',      aiInvertMapping );
214
			attrMap( oCol.mData, 'filter', aiInvertMapping );
215
			attrMap( oCol.mData, 'sort',   aiInvertMapping );
216
			attrMap( oCol.mData, 'type',   aiInvertMapping );
217
 
218
			// regenerate the get / set functions
219
			oSettings.oApi._fnColumnOptions( oSettings, i, {} );
220
		}
221
	}
222
 
223
 
224
	/*
225
	 * Move the DOM elements
226
	 */
227
	if ( oSettings.aoColumns[iFrom].bVisible )
228
	{
229
		/* Calculate the current visible index and the point to insert the node before. The insert
230
		 * before needs to take into account that there might not be an element to insert before,
231
		 * in which case it will be null, and an appendChild should be used
232
		 */
233
		var iVisibleIndex = this.oApi._fnColumnIndexToVisible( oSettings, iFrom );
234
		var iInsertBeforeIndex = null;
235
 
236
		i = iTo < iFrom ? iTo : iTo + 1;
237
		while ( iInsertBeforeIndex === null && i < iCols )
238
		{
239
			iInsertBeforeIndex = this.oApi._fnColumnIndexToVisible( oSettings, i );
240
			i++;
241
		}
242
 
243
		/* Header */
244
		nTrs = oSettings.nTHead.getElementsByTagName('tr');
245
		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
246
		{
247
			fnDomSwitch( nTrs[i], iVisibleIndex, iInsertBeforeIndex );
248
		}
249
 
250
		/* Footer */
251
		if ( oSettings.nTFoot !== null )
252
		{
253
			nTrs = oSettings.nTFoot.getElementsByTagName('tr');
254
			for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
255
			{
256
				fnDomSwitch( nTrs[i], iVisibleIndex, iInsertBeforeIndex );
257
			}
258
		}
259
 
260
		/* Body */
261
		for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
262
		{
263
			if ( oSettings.aoData[i].nTr !== null )
264
			{
265
				fnDomSwitch( oSettings.aoData[i].nTr, iVisibleIndex, iInsertBeforeIndex );
266
			}
267
		}
268
	}
269
 
270
	/*
271
	 * Move the internal array elements
272
	 */
273
	/* Columns */
274
	fnArraySwitch( oSettings.aoColumns, iFrom, iTo );
275
 
276
	/* Search columns */
277
	fnArraySwitch( oSettings.aoPreSearchCols, iFrom, iTo );
278
 
279
	/* Array array - internal data anodes cache */
280
	for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
281
	{
282
		var data = oSettings.aoData[i];
283
 
284
		if ( v110 ) {
285
			// DataTables 1.10+
286
			if ( data.anCells ) {
287
				fnArraySwitch( data.anCells, iFrom, iTo );
288
			}
289
 
290
			// For DOM sourced data, the invalidate will reread the cell into
291
			// the data array, but for data sources as an array, they need to
292
			// be flipped
293
			if ( data.src !== 'dom' && $.isArray( data._aData ) ) {
294
				fnArraySwitch( data._aData, iFrom, iTo );
295
			}
296
		}
297
		else {
298
			// DataTables 1.9-
299
			if ( $.isArray( data._aData ) ) {
300
				fnArraySwitch( data._aData, iFrom, iTo );
301
			}
302
			fnArraySwitch( data._anHidden, iFrom, iTo );
303
		}
304
	}
305
 
306
	/* Reposition the header elements in the header layout array */
307
	for ( i=0, iLen=oSettings.aoHeader.length ; i<iLen ; i++ )
308
	{
309
		fnArraySwitch( oSettings.aoHeader[i], iFrom, iTo );
310
	}
311
 
312
	if ( oSettings.aoFooter !== null )
313
	{
314
		for ( i=0, iLen=oSettings.aoFooter.length ; i<iLen ; i++ )
315
		{
316
			fnArraySwitch( oSettings.aoFooter[i], iFrom, iTo );
317
		}
318
	}
319
 
320
	// In 1.10 we need to invalidate row cached data for sorting, filtering etc
321
	if ( v110 ) {
322
		var api = new $.fn.dataTable.Api( oSettings );
323
		api.rows().invalidate();
324
	}
325
 
326
	/*
327
	 * Update DataTables' event handlers
328
	 */
329
 
330
	/* Sort listener */
331
	for ( i=0, iLen=iCols ; i<iLen ; i++ )
332
	{
333
		$(oSettings.aoColumns[i].nTh).off('click.DT');
334
		this.oApi._fnSortAttachListener( oSettings, oSettings.aoColumns[i].nTh, i );
335
	}
336
 
337
 
338
	/* Fire an event so other plug-ins can update */
339
	$(oSettings.oInstance).trigger( 'column-reorder', [ oSettings, {
340
		"iFrom": iFrom,
341
		"iTo": iTo,
342
		"aiInvertMapping": aiInvertMapping
343
	} ] );
344
};
345
 
346
 
347
 
348
var factory = function( $, DataTable ) {
349
"use strict";
350
 
351
/**
352
 * ColReorder provides column visibility control for DataTables
353
 * @class ColReorder
354
 * @constructor
355
 * @param {object} dt DataTables settings object
356
 * @param {object} opts ColReorder options
357
 */
358
var ColReorder = function( dt, opts )
359
{
360
	var oDTSettings;
361
 
362
	if ( $.fn.dataTable.Api ) {
363
		oDTSettings = new $.fn.dataTable.Api( dt ).settings()[0];
364
	}
365
	// 1.9 compatibility
366
	else if ( dt.fnSettings ) {
367
		// DataTables object, convert to the settings object
368
		oDTSettings = dt.fnSettings();
369
	}
370
	else if ( typeof dt === 'string' ) {
371
		// jQuery selector
372
		if ( $.fn.dataTable.fnIsDataTable( $(dt)[0] ) ) {
373
			oDTSettings = $(dt).eq(0).dataTable().fnSettings();
374
		}
375
	}
376
	else if ( dt.nodeName && dt.nodeName.toLowerCase() === 'table' ) {
377
		// Table node
378
		if ( $.fn.dataTable.fnIsDataTable( dt.nodeName ) ) {
379
			oDTSettings = $(dt.nodeName).dataTable().fnSettings();
380
		}
381
	}
382
	else if ( dt instanceof jQuery ) {
383
		// jQuery object
384
		if ( $.fn.dataTable.fnIsDataTable( dt[0] ) ) {
385
			oDTSettings = dt.eq(0).dataTable().fnSettings();
386
		}
387
	}
388
	else {
389
		// DataTables settings object
390
		oDTSettings = dt;
391
	}
392
 
393
	// Convert from camelCase to Hungarian, just as DataTables does
394
	var camelToHungarian = $.fn.dataTable.camelToHungarian;
395
	if ( camelToHungarian ) {
396
		camelToHungarian( ColReorder.defaults, ColReorder.defaults, true );
397
		camelToHungarian( ColReorder.defaults, opts || {} );
398
	}
399
 
400
 
401
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
402
	 * Public class variables
403
	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
404
 
405
	/**
406
	 * @namespace Settings object which contains customisable information for ColReorder instance
407
	 */
408
	this.s = {
409
		/**
410
		 * DataTables settings object
411
		 *  @property dt
412
		 *  @type     Object
413
		 *  @default  null
414
		 */
415
		"dt": null,
416
 
417
		/**
418
		 * Initialisation object used for this instance
419
		 *  @property init
420
		 *  @type     object
421
		 *  @default  {}
422
		 */
423
		"init": $.extend( true, {}, ColReorder.defaults, opts ),
424
 
425
		/**
426
		 * Number of columns to fix (not allow to be reordered)
427
		 *  @property fixed
428
		 *  @type     int
429
		 *  @default  0
430
		 */
431
		"fixed": 0,
432
 
433
		/**
434
		 * Number of columns to fix counting from right (not allow to be reordered)
435
		 *  @property fixedRight
436
		 *  @type     int
437
		 *  @default  0
438
		 */
439
		"fixedRight": 0,
440
 
441
		/**
442
		 * Callback function for once the reorder has been done
443
		 *  @property dropcallback
444
		 *  @type     function
445
		 *  @default  null
446
		 */
447
		"dropCallback": null,
448
 
449
		/**
450
		 * @namespace Information used for the mouse drag
451
		 */
452
		"mouse": {
453
			"startX": -1,
454
			"startY": -1,
455
			"offsetX": -1,
456
			"offsetY": -1,
457
			"target": -1,
458
			"targetIndex": -1,
459
			"fromIndex": -1
460
		},
461
 
462
		/**
463
		 * Information which is used for positioning the insert cusor and knowing where to do the
464
		 * insert. Array of objects with the properties:
465
		 *   x: x-axis position
466
		 *   to: insert point
467
		 *  @property aoTargets
468
		 *  @type     array
469
		 *  @default  []
470
		 */
471
		"aoTargets": []
472
	};
473
 
474
 
475
	/**
476
	 * @namespace Common and useful DOM elements for the class instance
477
	 */
478
	this.dom = {
479
		/**
480
		 * Dragging element (the one the mouse is moving)
481
		 *  @property drag
482
		 *  @type     element
483
		 *  @default  null
484
		 */
485
		"drag": null,
486
 
487
		/**
488
		 * The insert cursor
489
		 *  @property pointer
490
		 *  @type     element
491
		 *  @default  null
492
		 */
493
		"pointer": null
494
	};
495
 
496
 
497
	/* Constructor logic */
498
	this.s.dt = oDTSettings.oInstance.fnSettings();
499
	this.s.dt._colReorder = this;
500
	this._fnConstruct();
501
 
502
	/* Add destroy callback */
503
	oDTSettings.oApi._fnCallbackReg(oDTSettings, 'aoDestroyCallback', $.proxy(this._fnDestroy, this), 'ColReorder');
504
 
505
	return this;
506
};
507
 
508
 
509
 
510
ColReorder.prototype = {
511
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
512
	 * Public methods
513
	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
514
 
515
	/**
516
	 * Reset the column ordering to the original ordering that was detected on
517
	 * start up.
518
	 *  @return {this} Returns `this` for chaining.
519
	 *
520
	 *  @example
521
	 *    // DataTables initialisation with ColReorder
522
	 *    var table = $('#example').dataTable( {
523
	 *        "sDom": 'Rlfrtip'
524
	 *    } );
525
	 *
526
	 *    // Add click event to a button to reset the ordering
527
	 *    $('#resetOrdering').click( function (e) {
528
	 *        e.preventDefault();
529
	 *        $.fn.dataTable.ColReorder( table ).fnReset();
530
	 *    } );
531
	 */
532
	"fnReset": function ()
533
	{
534
		var a = [];
535
		for ( var i=0, iLen=this.s.dt.aoColumns.length ; i<iLen ; i++ )
536
		{
537
			a.push( this.s.dt.aoColumns[i]._ColReorder_iOrigCol );
538
		}
539
 
540
		this._fnOrderColumns( a );
541
 
542
		return this;
543
	},
544
 
545
	/**
546
	 * `Deprecated` - Get the current order of the columns, as an array.
547
	 *  @return {array} Array of column identifiers
548
	 *  @deprecated `fnOrder` should be used in preference to this method.
549
	 *      `fnOrder` acts as a getter/setter.
550
	 */
551
	"fnGetCurrentOrder": function ()
552
	{
553
		return this.fnOrder();
554
	},
555
 
556
	/**
557
	 * Get the current order of the columns, as an array. Note that the values
558
	 * given in the array are unique identifiers for each column. Currently
559
	 * these are the original ordering of the columns that was detected on
560
	 * start up, but this could potentially change in future.
561
	 *  @return {array} Array of column identifiers
562
	 *
563
	 *  @example
564
	 *    // Get column ordering for the table
565
	 *    var order = $.fn.dataTable.ColReorder( dataTable ).fnOrder();
566
	 *//**
567
	 * Set the order of the columns, from the positions identified in the
568
	 * ordering array given. Note that ColReorder takes a brute force approach
569
	 * to reordering, so it is possible multiple reordering events will occur
570
	 * before the final order is settled upon.
571
	 *  @param {array} [set] Array of column identifiers in the new order. Note
572
	 *    that every column must be included, uniquely, in this array.
573
	 *  @return {this} Returns `this` for chaining.
574
	 *
575
	 *  @example
576
	 *    // Swap the first and second columns
577
	 *    $.fn.dataTable.ColReorder( dataTable ).fnOrder( [1, 0, 2, 3, 4] );
578
	 *
579
	 *  @example
580
	 *    // Move the first column to the end for the table `#example`
581
	 *    var curr = $.fn.dataTable.ColReorder( '#example' ).fnOrder();
582
	 *    var first = curr.shift();
583
	 *    curr.push( first );
584
	 *    $.fn.dataTable.ColReorder( '#example' ).fnOrder( curr );
585
	 *
586
	 *  @example
587
	 *    // Reverse the table's order
588
	 *    $.fn.dataTable.ColReorder( '#example' ).fnOrder(
589
	 *      $.fn.dataTable.ColReorder( '#example' ).fnOrder().reverse()
590
	 *    );
591
	 */
592
	"fnOrder": function ( set )
593
	{
594
		if ( set === undefined )
595
		{
596
			var a = [];
597
			for ( var i=0, iLen=this.s.dt.aoColumns.length ; i<iLen ; i++ )
598
			{
599
				a.push( this.s.dt.aoColumns[i]._ColReorder_iOrigCol );
600
			}
601
			return a;
602
		}
603
 
604
		this._fnOrderColumns( fnInvertKeyValues( set ) );
605
 
606
		return this;
607
	},
608
 
609
 
610
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
611
	 * Private methods (they are of course public in JS, but recommended as private)
612
	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
613
 
614
	/**
615
	 * Constructor logic
616
	 *  @method  _fnConstruct
617
	 *  @returns void
618
	 *  @private
619
	 */
620
	"_fnConstruct": function ()
621
	{
622
		var that = this;
623
		var iLen = this.s.dt.aoColumns.length;
624
		var i;
625
 
626
		/* Columns discounted from reordering - counting left to right */
627
		if ( this.s.init.iFixedColumns )
628
		{
629
			this.s.fixed = this.s.init.iFixedColumns;
630
		}
631
 
632
		/* Columns discounted from reordering - counting right to left */
633
		this.s.fixedRight = this.s.init.iFixedColumnsRight ?
634
			this.s.init.iFixedColumnsRight :
635
			0;
636
 
637
		/* Drop callback initialisation option */
638
		if ( this.s.init.fnReorderCallback )
639
		{
640
			this.s.dropCallback = this.s.init.fnReorderCallback;
641
		}
642
 
643
		/* Add event handlers for the drag and drop, and also mark the original column order */
644
		for ( i = 0; i < iLen; i++ )
645
		{
646
			if ( i > this.s.fixed-1 && i < iLen - this.s.fixedRight )
647
			{
648
				this._fnMouseListener( i, this.s.dt.aoColumns[i].nTh );
649
			}
650
 
651
			/* Mark the original column order for later reference */
652
			this.s.dt.aoColumns[i]._ColReorder_iOrigCol = i;
653
		}
654
 
655
		/* State saving */
656
		this.s.dt.oApi._fnCallbackReg( this.s.dt, 'aoStateSaveParams', function (oS, oData) {
657
			that._fnStateSave.call( that, oData );
658
		}, "ColReorder_State" );
659
 
660
		/* An initial column order has been specified */
661
		var aiOrder = null;
662
		if ( this.s.init.aiOrder )
663
		{
664
			aiOrder = this.s.init.aiOrder.slice();
665
		}
666
 
667
		/* State loading, overrides the column order given */
668
		if ( this.s.dt.oLoadedState && typeof this.s.dt.oLoadedState.ColReorder != 'undefined' &&
669
		  this.s.dt.oLoadedState.ColReorder.length == this.s.dt.aoColumns.length )
670
		{
671
			aiOrder = this.s.dt.oLoadedState.ColReorder;
672
		}
673
 
674
		/* If we have an order to apply - do so */
675
		if ( aiOrder )
676
		{
677
			/* We might be called during or after the DataTables initialisation. If before, then we need
678
			 * to wait until the draw is done, if after, then do what we need to do right away
679
			 */
680
			if ( !that.s.dt._bInitComplete )
681
			{
682
				var bDone = false;
683
				this.s.dt.aoDrawCallback.push( {
684
					"fn": function () {
685
						if ( !that.s.dt._bInitComplete && !bDone )
686
						{
687
							bDone = true;
688
							var resort = fnInvertKeyValues( aiOrder );
689
							that._fnOrderColumns.call( that, resort );
690
						}
691
					},
692
					"sName": "ColReorder_Pre"
693
				} );
694
			}
695
			else
696
			{
697
				var resort = fnInvertKeyValues( aiOrder );
698
				that._fnOrderColumns.call( that, resort );
699
			}
700
		}
701
		else {
702
			this._fnSetColumnIndexes();
703
		}
704
	},
705
 
706
 
707
	/**
708
	 * Set the column order from an array
709
	 *  @method  _fnOrderColumns
710
	 *  @param   array a An array of integers which dictate the column order that should be applied
711
	 *  @returns void
712
	 *  @private
713
	 */
714
	"_fnOrderColumns": function ( a )
715
	{
716
		if ( a.length != this.s.dt.aoColumns.length )
717
		{
718
			this.s.dt.oInstance.oApi._fnLog( this.s.dt, 1, "ColReorder - array reorder does not "+
719
				"match known number of columns. Skipping." );
720
			return;
721
		}
722
 
723
		for ( var i=0, iLen=a.length ; i<iLen ; i++ )
724
		{
725
			var currIndex = $.inArray( i, a );
726
			if ( i != currIndex )
727
			{
728
				/* Reorder our switching array */
729
				fnArraySwitch( a, currIndex, i );
730
 
731
				/* Do the column reorder in the table */
732
				this.s.dt.oInstance.fnColReorder( currIndex, i );
733
			}
734
		}
735
 
736
		/* When scrolling we need to recalculate the column sizes to allow for the shift */
737
		if ( this.s.dt.oScroll.sX !== "" || this.s.dt.oScroll.sY !== "" )
738
		{
739
			this.s.dt.oInstance.fnAdjustColumnSizing();
740
		}
741
 
742
		/* Save the state */
743
		this.s.dt.oInstance.oApi._fnSaveState( this.s.dt );
744
 
745
		this._fnSetColumnIndexes();
746
	},
747
 
748
 
749
	/**
750
	 * Because we change the indexes of columns in the table, relative to their starting point
751
	 * we need to reorder the state columns to what they are at the starting point so we can
752
	 * then rearrange them again on state load!
753
	 *  @method  _fnStateSave
754
	 *  @param   object oState DataTables state
755
	 *  @returns string JSON encoded cookie string for DataTables
756
	 *  @private
757
	 */
758
	"_fnStateSave": function ( oState )
759
	{
760
		var i, iLen, aCopy, iOrigColumn;
761
		var oSettings = this.s.dt;
762
		var columns = oSettings.aoColumns;
763
 
764
		oState.ColReorder = [];
765
 
766
		/* Sorting */
767
		if ( oState.aaSorting ) {
768
			// 1.10.0-
769
			for ( i=0 ; i<oState.aaSorting.length ; i++ ) {
770
				oState.aaSorting[i][0] = columns[ oState.aaSorting[i][0] ]._ColReorder_iOrigCol;
771
			}
772
 
773
			var aSearchCopy = $.extend( true, [], oState.aoSearchCols );
774
 
775
			for ( i=0, iLen=columns.length ; i<iLen ; i++ )
776
			{
777
				iOrigColumn = columns[i]._ColReorder_iOrigCol;
778
 
779
				/* Column filter */
780
				oState.aoSearchCols[ iOrigColumn ] = aSearchCopy[i];
781
 
782
				/* Visibility */
783
				oState.abVisCols[ iOrigColumn ] = columns[i].bVisible;
784
 
785
				/* Column reordering */
786
				oState.ColReorder.push( iOrigColumn );
787
			}
788
		}
789
		else if ( oState.order ) {
790
			// 1.10.1+
791
			for ( i=0 ; i<oState.order.length ; i++ ) {
792
				oState.order[i][0] = columns[ oState.order[i][0] ]._ColReorder_iOrigCol;
793
			}
794
 
795
			var stateColumnsCopy = $.extend( true, [], oState.columns );
796
 
797
			for ( i=0, iLen=columns.length ; i<iLen ; i++ )
798
			{
799
				iOrigColumn = columns[i]._ColReorder_iOrigCol;
800
 
801
				/* Columns */
802
				oState.columns[ iOrigColumn ] = stateColumnsCopy[i];
803
 
804
				/* Column reordering */
805
				oState.ColReorder.push( iOrigColumn );
806
			}
807
		}
808
	},
809
 
810
 
811
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
812
	 * Mouse drop and drag
813
	 */
814
 
815
	/**
816
	 * Add a mouse down listener to a particluar TH element
817
	 *  @method  _fnMouseListener
818
	 *  @param   int i Column index
819
	 *  @param   element nTh TH element clicked on
820
	 *  @returns void
821
	 *  @private
822
	 */
823
	"_fnMouseListener": function ( i, nTh )
824
	{
825
		var that = this;
826
		$(nTh).on( 'mousedown.ColReorder', function (e) {
827
			e.preventDefault();
828
			that._fnMouseDown.call( that, e, nTh );
829
		} );
830
	},
831
 
832
 
833
	/**
834
	 * Mouse down on a TH element in the table header
835
	 *  @method  _fnMouseDown
836
	 *  @param   event e Mouse event
837
	 *  @param   element nTh TH element to be dragged
838
	 *  @returns void
839
	 *  @private
840
	 */
841
	"_fnMouseDown": function ( e, nTh )
842
	{
843
		var that = this;
844
 
845
		/* Store information about the mouse position */
846
		var target = $(e.target).closest('th, td');
847
		var offset = target.offset();
848
		var idx = parseInt( $(nTh).attr('data-column-index'), 10 );
849
 
850
		if ( idx === undefined ) {
851
			return;
852
		}
853
 
854
		this.s.mouse.startX = e.pageX;
855
		this.s.mouse.startY = e.pageY;
856
		this.s.mouse.offsetX = e.pageX - offset.left;
857
		this.s.mouse.offsetY = e.pageY - offset.top;
858
		this.s.mouse.target = this.s.dt.aoColumns[ idx ].nTh;//target[0];
859
		this.s.mouse.targetIndex = idx;
860
		this.s.mouse.fromIndex = idx;
861
 
862
		this._fnRegions();
863
 
864
		/* Add event handlers to the document */
865
		$(document)
866
			.on( 'mousemove.ColReorder', function (e) {
867
				that._fnMouseMove.call( that, e );
868
			} )
869
			.on( 'mouseup.ColReorder', function (e) {
870
				that._fnMouseUp.call( that, e );
871
			} );
872
	},
873
 
874
 
875
	/**
876
	 * Deal with a mouse move event while dragging a node
877
	 *  @method  _fnMouseMove
878
	 *  @param   event e Mouse event
879
	 *  @returns void
880
	 *  @private
881
	 */
882
	"_fnMouseMove": function ( e )
883
	{
884
		var that = this;
885
 
886
		if ( this.dom.drag === null )
887
		{
888
			/* Only create the drag element if the mouse has moved a specific distance from the start
889
			 * point - this allows the user to make small mouse movements when sorting and not have a
890
			 * possibly confusing drag element showing up
891
			 */
892
			if ( Math.pow(
893
				Math.pow(e.pageX - this.s.mouse.startX, 2) +
894
				Math.pow(e.pageY - this.s.mouse.startY, 2), 0.5 ) < 5 )
895
			{
896
				return;
897
			}
898
			this._fnCreateDragNode();
899
		}
900
 
901
		/* Position the element - we respect where in the element the click occured */
902
		this.dom.drag.css( {
903
			left: e.pageX - this.s.mouse.offsetX,
904
			top: e.pageY - this.s.mouse.offsetY
905
		} );
906
 
907
		/* Based on the current mouse position, calculate where the insert should go */
908
		var bSet = false;
909
		var lastToIndex = this.s.mouse.toIndex;
910
 
911
		for ( var i=1, iLen=this.s.aoTargets.length ; i<iLen ; i++ )
912
		{
913
			if ( e.pageX < this.s.aoTargets[i-1].x + ((this.s.aoTargets[i].x-this.s.aoTargets[i-1].x)/2) )
914
			{
915
				this.dom.pointer.css( 'left', this.s.aoTargets[i-1].x );
916
				this.s.mouse.toIndex = this.s.aoTargets[i-1].to;
917
				bSet = true;
918
				break;
919
			}
920
		}
921
 
922
		// The insert element wasn't positioned in the array (less than
923
		// operator), so we put it at the end
924
		if ( !bSet )
925
		{
926
			this.dom.pointer.css( 'left', this.s.aoTargets[this.s.aoTargets.length-1].x );
927
			this.s.mouse.toIndex = this.s.aoTargets[this.s.aoTargets.length-1].to;
928
		}
929
 
930
		// Perform reordering if realtime updating is on and the column has moved
931
		if ( this.s.init.bRealtime && lastToIndex !== this.s.mouse.toIndex ) {
932
			this.s.dt.oInstance.fnColReorder( this.s.mouse.fromIndex, this.s.mouse.toIndex );
933
			this.s.mouse.fromIndex = this.s.mouse.toIndex;
934
			this._fnRegions();
935
		}
936
	},
937
 
938
 
939
	/**
940
	 * Finish off the mouse drag and insert the column where needed
941
	 *  @method  _fnMouseUp
942
	 *  @param   event e Mouse event
943
	 *  @returns void
944
	 *  @private
945
	 */
946
	"_fnMouseUp": function ( e )
947
	{
948
		var that = this;
949
 
950
		$(document).off( 'mousemove.ColReorder mouseup.ColReorder' );
951
 
952
		if ( this.dom.drag !== null )
953
		{
954
			/* Remove the guide elements */
955
			this.dom.drag.remove();
956
			this.dom.pointer.remove();
957
			this.dom.drag = null;
958
			this.dom.pointer = null;
959
 
960
			/* Actually do the reorder */
961
			this.s.dt.oInstance.fnColReorder( this.s.mouse.fromIndex, this.s.mouse.toIndex );
962
			this._fnSetColumnIndexes();
963
 
964
			/* When scrolling we need to recalculate the column sizes to allow for the shift */
965
			if ( this.s.dt.oScroll.sX !== "" || this.s.dt.oScroll.sY !== "" )
966
			{
967
				this.s.dt.oInstance.fnAdjustColumnSizing();
968
			}
969
 
970
			if ( this.s.dropCallback !== null )
971
			{
972
				this.s.dropCallback.call( this );
973
			}
974
 
975
			/* Save the state */
976
			this.s.dt.oInstance.oApi._fnSaveState( this.s.dt );
977
		}
978
	},
979
 
980
 
981
	/**
982
	 * Calculate a cached array with the points of the column inserts, and the
983
	 * 'to' points
984
	 *  @method  _fnRegions
985
	 *  @returns void
986
	 *  @private
987
	 */
988
	"_fnRegions": function ()
989
	{
990
		var aoColumns = this.s.dt.aoColumns;
991
 
992
		this.s.aoTargets.splice( 0, this.s.aoTargets.length );
993
 
994
		this.s.aoTargets.push( {
995
			"x":  $(this.s.dt.nTable).offset().left,
996
			"to": 0
997
		} );
998
 
999
		var iToPoint = 0;
1000
		for ( var i=0, iLen=aoColumns.length ; i<iLen ; i++ )
1001
		{
1002
			/* For the column / header in question, we want it's position to remain the same if the
1003
			 * position is just to it's immediate left or right, so we only incremement the counter for
1004
			 * other columns
1005
			 */
1006
			if ( i != this.s.mouse.fromIndex )
1007
			{
1008
				iToPoint++;
1009
			}
1010
 
1011
			if ( aoColumns[i].bVisible )
1012
			{
1013
				this.s.aoTargets.push( {
1014
					"x":  $(aoColumns[i].nTh).offset().left + $(aoColumns[i].nTh).outerWidth(),
1015
					"to": iToPoint
1016
				} );
1017
			}
1018
		}
1019
 
1020
		/* Disallow columns for being reordered by drag and drop, counting right to left */
1021
		if ( this.s.fixedRight !== 0 )
1022
		{
1023
			this.s.aoTargets.splice( this.s.aoTargets.length - this.s.fixedRight );
1024
		}
1025
 
1026
		/* Disallow columns for being reordered by drag and drop, counting left to right */
1027
		if ( this.s.fixed !== 0 )
1028
		{
1029
			this.s.aoTargets.splice( 0, this.s.fixed );
1030
		}
1031
	},
1032
 
1033
 
1034
	/**
1035
	 * Copy the TH element that is being drags so the user has the idea that they are actually
1036
	 * moving it around the page.
1037
	 *  @method  _fnCreateDragNode
1038
	 *  @returns void
1039
	 *  @private
1040
	 */
1041
	"_fnCreateDragNode": function ()
1042
	{
1043
		var scrolling = this.s.dt.oScroll.sX !== "" || this.s.dt.oScroll.sY !== "";
1044
 
1045
		var origCell = this.s.dt.aoColumns[ this.s.mouse.targetIndex ].nTh;
1046
		var origTr = origCell.parentNode;
1047
		var origThead = origTr.parentNode;
1048
		var origTable = origThead.parentNode;
1049
		var cloneCell = $(origCell).clone();
1050
 
1051
		// This is a slightly odd combination of jQuery and DOM, but it is the
1052
		// fastest and least resource intensive way I could think of cloning
1053
		// the table with just a single header cell in it.
1054
		this.dom.drag = $(origTable.cloneNode(false))
1055
			.addClass( 'DTCR_clonedTable' )
1056
			.append(
1057
				origThead.cloneNode(false).appendChild(
1058
					origTr.cloneNode(false).appendChild(
1059
						cloneCell[0]
1060
					)
1061
				)
1062
			)
1063
			.css( {
1064
				position: 'absolute',
1065
				top: 0,
1066
				left: 0,
1067
				width: $(origCell).outerWidth(),
1068
				height: $(origCell).outerHeight()
1069
			} )
1070
			.appendTo( 'body' );
1071
 
1072
		this.dom.pointer = $('<div></div>')
1073
			.addClass( 'DTCR_pointer' )
1074
			.css( {
1075
				position: 'absolute',
1076
				top: scrolling ?
1077
					$('div.dataTables_scroll', this.s.dt.nTableWrapper).offset().top :
1078
					$(this.s.dt.nTable).offset().top,
1079
				height : scrolling ?
1080
					$('div.dataTables_scroll', this.s.dt.nTableWrapper).height() :
1081
					$(this.s.dt.nTable).height()
1082
			} )
1083
			.appendTo( 'body' );
1084
	},
1085
 
1086
	/**
1087
	 * Clean up ColReorder memory references and event handlers
1088
	 *  @method  _fnDestroy
1089
	 *  @returns void
1090
	 *  @private
1091
	 */
1092
	"_fnDestroy": function ()
1093
	{
1094
		var i, iLen;
1095
 
1096
		for ( i=0, iLen=this.s.dt.aoDrawCallback.length ; i<iLen ; i++ )
1097
		{
1098
			if ( this.s.dt.aoDrawCallback[i].sName === 'ColReorder_Pre' )
1099
			{
1100
				this.s.dt.aoDrawCallback.splice( i, 1 );
1101
				break;
1102
			}
1103
		}
1104
 
1105
		$(this.s.dt.nTHead).find( '*' ).off( '.ColReorder' );
1106
 
1107
		$.each( this.s.dt.aoColumns, function (i, column) {
1108
			$(column.nTh).removeAttr('data-column-index');
1109
		} );
1110
 
1111
		this.s.dt._colReorder = null;
1112
		this.s = null;
1113
	},
1114
 
1115
 
1116
	/**
1117
	 * Add a data attribute to the column headers, so we know the index of
1118
	 * the row to be reordered. This allows fast detection of the index, and
1119
	 * for this plug-in to work with FixedHeader which clones the nodes.
1120
	 *  @private
1121
	 */
1122
	"_fnSetColumnIndexes": function ()
1123
	{
1124
		$.each( this.s.dt.aoColumns, function (i, column) {
1125
			$(column.nTh).attr('data-column-index', i);
1126
		} );
1127
	}
1128
};
1129
 
1130
 
1131
 
1132
 
1133
 
1134
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1135
 * Static parameters
1136
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1137
 
1138
 
1139
/**
1140
 * ColReorder default settings for initialisation
1141
 *  @namespace
1142
 *  @static
1143
 */
1144
ColReorder.defaults = {
1145
	/**
1146
	 * Predefined ordering for the columns that will be applied automatically
1147
	 * on initialisation. If not specified then the order that the columns are
1148
	 * found to be in the HTML is the order used.
1149
	 *  @type array
1150
	 *  @default null
1151
	 *  @static
1152
	 *  @example
1153
	 *      // Using the `oColReorder` option in the DataTables options object
1154
	 *      $('#example').dataTable( {
1155
	 *          "sDom": 'Rlfrtip',
1156
	 *          "oColReorder": {
1157
	 *              "aiOrder": [ 4, 3, 2, 1, 0 ]
1158
	 *          }
1159
	 *      } );
1160
	 *
1161
	 *  @example
1162
	 *      // Using `new` constructor
1163
	 *      $('#example').dataTable()
1164
	 *
1165
	 *      new $.fn.dataTable.ColReorder( '#example', {
1166
	 *          "aiOrder": [ 4, 3, 2, 1, 0 ]
1167
	 *      } );
1168
	 */
1169
	aiOrder: null,
1170
 
1171
	/**
1172
	 * Redraw the table's column ordering as the end user draws the column
1173
	 * (`true`) or wait until the mouse is released (`false` - default). Note
1174
	 * that this will perform a redraw on each reordering, which involves an
1175
	 * Ajax request each time if you are using server-side processing in
1176
	 * DataTables.
1177
	 *  @type boolean
1178
	 *  @default false
1179
	 *  @static
1180
	 *  @example
1181
	 *      // Using the `oColReorder` option in the DataTables options object
1182
	 *      $('#example').dataTable( {
1183
	 *          "sDom": 'Rlfrtip',
1184
	 *          "oColReorder": {
1185
	 *              "bRealtime": true
1186
	 *          }
1187
	 *      } );
1188
	 *
1189
	 *  @example
1190
	 *      // Using `new` constructor
1191
	 *      $('#example').dataTable()
1192
	 *
1193
	 *      new $.fn.dataTable.ColReorder( '#example', {
1194
	 *          "bRealtime": true
1195
	 *      } );
1196
	 */
1197
	bRealtime: false,
1198
 
1199
	/**
1200
	 * Indicate how many columns should be fixed in position (counting from the
1201
	 * left). This will typically be 1 if used, but can be as high as you like.
1202
	 *  @type int
1203
	 *  @default 0
1204
	 *  @static
1205
	 *  @example
1206
	 *      // Using the `oColReorder` option in the DataTables options object
1207
	 *      $('#example').dataTable( {
1208
	 *          "sDom": 'Rlfrtip',
1209
	 *          "oColReorder": {
1210
	 *              "iFixedColumns": 1
1211
	 *          }
1212
	 *      } );
1213
	 *
1214
	 *  @example
1215
	 *      // Using `new` constructor
1216
	 *      $('#example').dataTable()
1217
	 *
1218
	 *      new $.fn.dataTable.ColReorder( '#example', {
1219
	 *          "iFixedColumns": 1
1220
	 *      } );
1221
	 */
1222
	iFixedColumns: 0,
1223
 
1224
	/**
1225
	 * As `iFixedColumnsRight` but counting from the right.
1226
	 *  @type int
1227
	 *  @default 0
1228
	 *  @static
1229
	 *  @example
1230
	 *      // Using the `oColReorder` option in the DataTables options object
1231
	 *      $('#example').dataTable( {
1232
	 *          "sDom": 'Rlfrtip',
1233
	 *          "oColReorder": {
1234
	 *              "iFixedColumnsRight": 1
1235
	 *          }
1236
	 *      } );
1237
	 *
1238
	 *  @example
1239
	 *      // Using `new` constructor
1240
	 *      $('#example').dataTable()
1241
	 *
1242
	 *      new $.fn.dataTable.ColReorder( '#example', {
1243
	 *          "iFixedColumnsRight": 1
1244
	 *      } );
1245
	 */
1246
	iFixedColumnsRight: 0,
1247
 
1248
	/**
1249
	 * Callback function that is fired when columns are reordered
1250
	 *  @type function():void
1251
	 *  @default null
1252
	 *  @static
1253
	 *  @example
1254
	 *      // Using the `oColReorder` option in the DataTables options object
1255
	 *      $('#example').dataTable( {
1256
	 *          "sDom": 'Rlfrtip',
1257
	 *          "oColReorder": {
1258
	 *              "fnReorderCallback": function () {
1259
	 *                  alert( 'Columns reordered' );
1260
	 *              }
1261
	 *          }
1262
	 *      } );
1263
	 *
1264
	 *  @example
1265
	 *      // Using `new` constructor
1266
	 *      $('#example').dataTable()
1267
	 *
1268
	 *      new $.fn.dataTable.ColReorder( '#example', {
1269
	 *          "fnReorderCallback": function () {
1270
	 *              alert( 'Columns reordered' );
1271
	 *          }
1272
	 *      } );
1273
	 */
1274
	fnReorderCallback: null
1275
};
1276
 
1277
 
1278
 
1279
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1280
 * Constants
1281
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1282
 
1283
/**
1284
 * ColReorder version
1285
 *  @constant  version
1286
 *  @type      String
1287
 *  @default   As code
1288
 */
1289
ColReorder.version = "1.1.2";
1290
 
1291
 
1292
 
1293
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1294
 * DataTables interfaces
1295
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1296
 
1297
// Expose
1298
$.fn.dataTable.ColReorder = ColReorder;
1299
$.fn.DataTable.ColReorder = ColReorder;
1300
 
1301
 
1302
// Register a new feature with DataTables
1303
if ( typeof $.fn.dataTable == "function" &&
1304
     typeof $.fn.dataTableExt.fnVersionCheck == "function" &&
1305
     $.fn.dataTableExt.fnVersionCheck('1.9.3') )
1306
{
1307
	$.fn.dataTableExt.aoFeatures.push( {
1308
		"fnInit": function( settings ) {
1309
			var table = settings.oInstance;
1310
 
1311
			if ( ! settings._colReorder ) {
1312
				var dtInit = settings.oInit;
1313
				var opts = dtInit.colReorder || dtInit.oColReorder || {};
1314
 
1315
				new ColReorder( settings, opts );
1316
			}
1317
			else {
1318
				table.oApi._fnLog( settings, 1, "ColReorder attempted to initialise twice. Ignoring second" );
1319
			}
1320
 
1321
			return null; /* No node for DataTables to insert */
1322
		},
1323
		"cFeature": "R",
1324
		"sFeature": "ColReorder"
1325
	} );
1326
}
1327
else {
1328
	alert( "Warning: ColReorder requires DataTables 1.9.3 or greater - www.datatables.net/download");
1329
}
1330
 
1331
 
1332
// API augmentation
1333
if ( $.fn.dataTable.Api ) {
1334
	$.fn.dataTable.Api.register( 'colReorder.reset()', function () {
1335
		return this.iterator( 'table', function ( ctx ) {
1336
			ctx._colReorder.fnReset();
1337
		} );
1338
	} );
1339
 
1340
	$.fn.dataTable.Api.register( 'colReorder.order()', function ( set ) {
1341
		if ( set ) {
1342
			return this.iterator( 'table', function ( ctx ) {
1343
				ctx._colReorder.fnOrder( set );
1344
			} );
1345
		}
1346
 
1347
		return this.context.length ?
1348
			this.context[0]._colReorder.fnOrder() :
1349
			null;
1350
	} );
1351
}
1352
 
1353
return ColReorder;
1354
}; // /factory
1355
 
1356
 
1357
// Define as an AMD module if possible
1358
if ( typeof define === 'function' && define.amd ) {
1359
	define( ['jquery', 'datatables'], factory );
1360
}
1361
else if ( typeof exports === 'object' ) {
1362
    // Node/CommonJS
1363
    factory( require('jquery'), require('datatables') );
1364
}
1365
else if ( jQuery && !jQuery.fn.dataTable.ColReorder ) {
1366
	// Otherwise simply initialise as normal, stopping multiple evaluation
1367
	factory( jQuery, jQuery.fn.dataTable );
1368
}
1369
 
1370
 
1371
})(window, document);