GPQAPP

Форк
0
/
dataTables.colReorder.js 
1491 строка · 38.5 Кб
1
/*! ColReorder 1.5.4
2
 * ©2010-2021 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.5.4
9
 * @file        dataTables.colReorder.js
10
 * @author      SpryMedia Ltd (www.sprymedia.co.uk)
11
 * @contact     www.sprymedia.co.uk/contact
12
 * @copyright   Copyright 2010-2021 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
(function( factory ){
24
	if ( typeof define === 'function' && define.amd ) {
25
		// AMD
26
		define( ['jquery', 'datatables.net'], function ( $ ) {
27
			return factory( $, window, document );
28
		} );
29
	}
30
	else if ( typeof exports === 'object' ) {
31
		// CommonJS
32
		module.exports = function (root, $) {
33
			if ( ! root ) {
34
				root = window;
35
			}
36

37
			if ( ! $ || ! $.fn.dataTable ) {
38
				$ = require('datatables.net')(root, $).$;
39
			}
40

41
			return factory( $, root, root.document );
42
		};
43
	}
44
	else {
45
		// Browser
46
		factory( jQuery, window, document );
47
	}
48
}(function( $, window, document, undefined ) {
49
'use strict';
50
var DataTable = $.fn.dataTable;
51

52

53
/**
54
 * Switch the key value pairing of an index array to be value key (i.e. the old value is now the
55
 * key). For example consider [ 2, 0, 1 ] this would be returned as [ 1, 2, 0 ].
56
 *  @method  fnInvertKeyValues
57
 *  @param   array aIn Array to switch around
58
 *  @returns array
59
 */
60
function fnInvertKeyValues( aIn )
61
{
62
	var aRet=[];
63
	for ( var i=0, iLen=aIn.length ; i<iLen ; i++ )
64
	{
65
		aRet[ aIn[i] ] = i;
66
	}
67
	return aRet;
68
}
69

70

71
/**
72
 * Modify an array by switching the position of two elements
73
 *  @method  fnArraySwitch
74
 *  @param   array aArray Array to consider, will be modified by reference (i.e. no return)
75
 *  @param   int iFrom From point
76
 *  @param   int iTo Insert point
77
 *  @returns void
78
 */
79
function fnArraySwitch( aArray, iFrom, iTo )
80
{
81
	var mStore = aArray.splice( iFrom, 1 )[0];
82
	aArray.splice( iTo, 0, mStore );
83
}
84

85

86
/**
87
 * Switch the positions of nodes in a parent node (note this is specifically designed for
88
 * table rows). Note this function considers all element nodes under the parent!
89
 *  @method  fnDomSwitch
90
 *  @param   string sTag Tag to consider
91
 *  @param   int iFrom Element to move
92
 *  @param   int Point to element the element to (before this point), can be null for append
93
 *  @returns void
94
 */
95
function fnDomSwitch( nParent, iFrom, iTo )
96
{
97
	var anTags = [];
98
	for ( var i=0, iLen=nParent.childNodes.length ; i<iLen ; i++ )
99
	{
100
		if ( nParent.childNodes[i].nodeType == 1 )
101
		{
102
			anTags.push( nParent.childNodes[i] );
103
		}
104
	}
105
	var nStore = anTags[ iFrom ];
106

107
	if ( iTo !== null )
108
	{
109
		nParent.insertBefore( nStore, anTags[iTo] );
110
	}
111
	else
112
	{
113
		nParent.appendChild( nStore );
114
	}
115
}
116

117

118
/**
119
 * Plug-in for DataTables which will reorder the internal column structure by taking the column
120
 * from one position (iFrom) and insert it into a given point (iTo).
121
 *  @method  $.fn.dataTableExt.oApi.fnColReorder
122
 *  @param   object oSettings DataTables settings object - automatically added by DataTables!
123
 *  @param   int iFrom Take the column to be repositioned from this point
124
 *  @param   int iTo and insert it into this point
125
 *  @param   bool drop Indicate if the reorder is the final one (i.e. a drop)
126
 *    not a live reorder
127
 *  @param   bool invalidateRows speeds up processing if false passed
128
 *  @returns void
129
 */
130
$.fn.dataTableExt.oApi.fnColReorder = function ( oSettings, iFrom, iTo, drop, invalidateRows )
131
{
132
	var i, iLen, j, jLen, jen, iCols=oSettings.aoColumns.length, nTrs, oCol;
133
	var attrMap = function ( obj, prop, mapping ) {
134
		if ( ! obj[ prop ] || typeof obj[ prop ] === 'function' ) {
135
			return;
136
		}
137

138
		var a = obj[ prop ].split('.');
139
		var num = a.shift();
140

141
		if ( isNaN( num*1 ) ) {
142
			return;
143
		}
144

145
		obj[ prop ] = mapping[ num*1 ]+'.'+a.join('.');
146
	};
147

148
	/* Sanity check in the input */
149
	if ( iFrom == iTo )
150
	{
151
		/* Pointless reorder */
152
		return;
153
	}
154

155
	if ( iFrom < 0 || iFrom >= iCols )
156
	{
157
		this.oApi._fnLog( oSettings, 1, "ColReorder 'from' index is out of bounds: "+iFrom );
158
		return;
159
	}
160

161
	if ( iTo < 0 || iTo >= iCols )
162
	{
163
		this.oApi._fnLog( oSettings, 1, "ColReorder 'to' index is out of bounds: "+iTo );
164
		return;
165
	}
166

167
	/*
168
	 * Calculate the new column array index, so we have a mapping between the old and new
169
	 */
170
	var aiMapping = [];
171
	for ( i=0, iLen=iCols ; i<iLen ; i++ )
172
	{
173
		aiMapping[i] = i;
174
	}
175
	fnArraySwitch( aiMapping, iFrom, iTo );
176
	var aiInvertMapping = fnInvertKeyValues( aiMapping );
177

178

179
	/*
180
	 * Convert all internal indexing to the new column order indexes
181
	 */
182
	/* Sorting */
183
	for ( i=0, iLen=oSettings.aaSorting.length ; i<iLen ; i++ )
184
	{
185
		oSettings.aaSorting[i][0] = aiInvertMapping[ oSettings.aaSorting[i][0] ];
186
	}
187

188
	/* Fixed sorting */
189
	if ( oSettings.aaSortingFixed !== null )
190
	{
191
		for ( i=0, iLen=oSettings.aaSortingFixed.length ; i<iLen ; i++ )
192
		{
193
			oSettings.aaSortingFixed[i][0] = aiInvertMapping[ oSettings.aaSortingFixed[i][0] ];
194
		}
195
	}
196

197
	/* Data column sorting (the column which the sort for a given column should take place on) */
198
	for ( i=0, iLen=iCols ; i<iLen ; i++ )
199
	{
200
		oCol = oSettings.aoColumns[i];
201
		for ( j=0, jLen=oCol.aDataSort.length ; j<jLen ; j++ )
202
		{
203
			oCol.aDataSort[j] = aiInvertMapping[ oCol.aDataSort[j] ];
204
		}
205

206
		// Update the column indexes
207
		oCol.idx = aiInvertMapping[ oCol.idx ];
208
	}
209

210
	// Update 1.10 optimised sort class removal variable
211
	$.each( oSettings.aLastSort, function (i, val) {
212
		oSettings.aLastSort[i].src = aiInvertMapping[ val.src ];
213
	} );
214

215
	/* Update the Get and Set functions for each column */
216
	for ( i=0, iLen=iCols ; i<iLen ; i++ )
217
	{
218
		oCol = oSettings.aoColumns[i];
219

220
		if ( typeof oCol.mData == 'number' ) {
221
			oCol.mData = aiInvertMapping[ oCol.mData ];
222
		}
223
		else if ( $.isPlainObject( oCol.mData ) ) {
224
			// HTML5 data sourced
225
			attrMap( oCol.mData, '_',      aiInvertMapping );
226
			attrMap( oCol.mData, 'filter', aiInvertMapping );
227
			attrMap( oCol.mData, 'sort',   aiInvertMapping );
228
			attrMap( oCol.mData, 'type',   aiInvertMapping );
229
		}
230
	}
231

232
	/*
233
	 * Move the DOM elements
234
	 */
235
	if ( oSettings.aoColumns[iFrom].bVisible )
236
	{
237
		/* Calculate the current visible index and the point to insert the node before. The insert
238
		 * before needs to take into account that there might not be an element to insert before,
239
		 * in which case it will be null, and an appendChild should be used
240
		 */
241
		var iVisibleIndex = this.oApi._fnColumnIndexToVisible( oSettings, iFrom );
242
		var iInsertBeforeIndex = null;
243

244
		i = iTo < iFrom ? iTo : iTo + 1;
245
		while ( iInsertBeforeIndex === null && i < iCols )
246
		{
247
			iInsertBeforeIndex = this.oApi._fnColumnIndexToVisible( oSettings, i );
248
			i++;
249
		}
250

251
		/* Header */
252
		nTrs = oSettings.nTHead.getElementsByTagName('tr');
253
		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
254
		{
255
			fnDomSwitch( nTrs[i], iVisibleIndex, iInsertBeforeIndex );
256
		}
257

258
		/* Footer */
259
		if ( oSettings.nTFoot !== null )
260
		{
261
			nTrs = oSettings.nTFoot.getElementsByTagName('tr');
262
			for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
263
			{
264
				fnDomSwitch( nTrs[i], iVisibleIndex, iInsertBeforeIndex );
265
			}
266
		}
267

268
		/* Body */
269
		for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
270
		{
271
			if ( oSettings.aoData[i].nTr !== null )
272
			{
273
				fnDomSwitch( oSettings.aoData[i].nTr, iVisibleIndex, iInsertBeforeIndex );
274
			}
275
		}
276
	}
277

278
	/*
279
	 * Move the internal array elements
280
	 */
281
	/* Columns */
282
	fnArraySwitch( oSettings.aoColumns, iFrom, iTo );
283

284
	// regenerate the get / set functions
285
	for ( i=0, iLen=iCols ; i<iLen ; i++ ) {
286
		oSettings.oApi._fnColumnOptions( oSettings, i, {} );
287
	}
288

289
	/* Search columns */
290
	fnArraySwitch( oSettings.aoPreSearchCols, iFrom, iTo );
291

292
	/* Array array - internal data anodes cache */
293
	for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
294
	{
295
		var data = oSettings.aoData[i];
296
		var cells = data.anCells;
297

298
		if ( cells ) {
299
			fnArraySwitch( cells, iFrom, iTo );
300

301
			// Longer term, should this be moved into the DataTables' invalidate
302
			// methods?
303
			for ( j=0, jen=cells.length ; j<jen ; j++ ) {
304
				if ( cells[j] && cells[j]._DT_CellIndex ) {
305
					cells[j]._DT_CellIndex.column = j;
306
				}
307
			}
308
		}
309

310
		// For DOM sourced data, the invalidate will reread the cell into
311
		// the data array, but for data sources as an array, they need to
312
		// be flipped
313
		if ( data.src !== 'dom' && Array.isArray( data._aData ) ) {
314
			fnArraySwitch( data._aData, iFrom, iTo );
315
		}
316
	}
317

318
	/* Reposition the header elements in the header layout array */
319
	for ( i=0, iLen=oSettings.aoHeader.length ; i<iLen ; i++ )
320
	{
321
		fnArraySwitch( oSettings.aoHeader[i], iFrom, iTo );
322
	}
323

324
	if ( oSettings.aoFooter !== null )
325
	{
326
		for ( i=0, iLen=oSettings.aoFooter.length ; i<iLen ; i++ )
327
		{
328
			fnArraySwitch( oSettings.aoFooter[i], iFrom, iTo );
329
		}
330
	}
331

332
	if ( invalidateRows || invalidateRows === undefined )
333
	{
334
		$.fn.dataTable.Api( oSettings ).rows().invalidate();
335
	}
336

337
	/*
338
	 * Update DataTables' event handlers
339
	 */
340

341
	/* Sort listener */
342
	for ( i=0, iLen=iCols ; i<iLen ; i++ )
343
	{
344
		$(oSettings.aoColumns[i].nTh).off('.DT');
345
		this.oApi._fnSortAttachListener( oSettings, oSettings.aoColumns[i].nTh, i );
346
	}
347

348

349
	/* Fire an event so other plug-ins can update */
350
	$(oSettings.oInstance).trigger( 'column-reorder.dt', [ oSettings, {
351
		from: iFrom,
352
		to: iTo,
353
		mapping: aiInvertMapping,
354
		drop: drop,
355

356
		// Old style parameters for compatibility
357
		iFrom: iFrom,
358
		iTo: iTo,
359
		aiInvertMapping: aiInvertMapping
360
	} ] );
361
};
362

363
/**
364
 * ColReorder provides column visibility control for DataTables
365
 * @class ColReorder
366
 * @constructor
367
 * @param {object} dt DataTables settings object
368
 * @param {object} opts ColReorder options
369
 */
370
var ColReorder = function( dt, opts )
371
{
372
	var settings = new $.fn.dataTable.Api( dt ).settings()[0];
373

374
	// Ensure that we can't initialise on the same table twice
375
	if ( settings._colReorder ) {
376
		return settings._colReorder;
377
	}
378

379
	// Allow the options to be a boolean for defaults
380
	if ( opts === true ) {
381
		opts = {};
382
	}
383

384
	// Convert from camelCase to Hungarian, just as DataTables does
385
	var camelToHungarian = $.fn.dataTable.camelToHungarian;
386
	if ( camelToHungarian ) {
387
		camelToHungarian( ColReorder.defaults, ColReorder.defaults, true );
388
		camelToHungarian( ColReorder.defaults, opts || {} );
389
	}
390

391

392
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
393
	 * Public class variables
394
	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
395

396
	/**
397
	 * @namespace Settings object which contains customisable information for ColReorder instance
398
	 */
399
	this.s = {
400
		/**
401
		 * DataTables settings object
402
		 *  @property dt
403
		 *  @type     Object
404
		 *  @default  null
405
		 */
406
		"dt": null,
407

408
		/**
409
		 * Enable flag
410
		 *  @property dt
411
		 *  @type     Object
412
		 *  @default  null
413
		 */
414
		"enable": null,
415

416
		/**
417
		 * Initialisation object used for this instance
418
		 *  @property init
419
		 *  @type     object
420
		 *  @default  {}
421
		 */
422
		"init": $.extend( true, {}, ColReorder.defaults, opts ),
423

424
		/**
425
		 * Number of columns to fix (not allow to be reordered)
426
		 *  @property fixed
427
		 *  @type     int
428
		 *  @default  0
429
		 */
430
		"fixed": 0,
431

432
		/**
433
		 * Number of columns to fix counting from right (not allow to be reordered)
434
		 *  @property fixedRight
435
		 *  @type     int
436
		 *  @default  0
437
		 */
438
		"fixedRight": 0,
439

440
		/**
441
		 * Callback function for once the reorder has been done
442
		 *  @property reorderCallback
443
		 *  @type     function
444
		 *  @default  null
445
		 */
446
		"reorderCallback": null,
447

448
		/**
449
		 * @namespace Information used for the mouse drag
450
		 */
451
		"mouse": {
452
			"startX": -1,
453
			"startY": -1,
454
			"offsetX": -1,
455
			"offsetY": -1,
456
			"target": -1,
457
			"targetIndex": -1,
458
			"fromIndex": -1
459
		},
460

461
		/**
462
		 * Information which is used for positioning the insert cusor and knowing where to do the
463
		 * insert. Array of objects with the properties:
464
		 *   x: x-axis position
465
		 *   to: insert point
466
		 *  @property aoTargets
467
		 *  @type     array
468
		 *  @default  []
469
		 */
470
		"aoTargets": []
471
	};
472

473

474
	/**
475
	 * @namespace Common and useful DOM elements for the class instance
476
	 */
477
	this.dom = {
478
		/**
479
		 * Dragging element (the one the mouse is moving)
480
		 *  @property drag
481
		 *  @type     element
482
		 *  @default  null
483
		 */
484
		"drag": null,
485

486
		/**
487
		 * The insert cursor
488
		 *  @property pointer
489
		 *  @type     element
490
		 *  @default  null
491
		 */
492
		"pointer": null
493
	};
494

495
	/* Constructor logic */
496
	this.s.enable = this.s.init.bEnable;
497
	this.s.dt = settings;
498
	this.s.dt._colReorder = this;
499
	this._fnConstruct();
500

501
	return this;
502
};
503

504

505

506
$.extend( ColReorder.prototype, {
507
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
508
	 * Public methods
509
	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
510

511
	/**
512
	 * Enable / disable end user interaction
513
	 */
514
	fnEnable: function ( flag )
515
	{
516
		if ( flag === false ) {
517
			return fnDisable();
518
		}
519

520
		this.s.enable = true;
521
	},
522

523
	/**
524
	 * Disable end user interaction
525
	 */
526
	fnDisable: function ()
527
	{
528
		this.s.enable = false;
529
	},
530

531
	/**
532
	 * Reset the column ordering to the original ordering that was detected on
533
	 * start up.
534
	 *  @return {this} Returns `this` for chaining.
535
	 *
536
	 *  @example
537
	 *    // DataTables initialisation with ColReorder
538
	 *    var table = $('#example').dataTable( {
539
	 *        "sDom": 'Rlfrtip'
540
	 *    } );
541
	 *
542
	 *    // Add click event to a button to reset the ordering
543
	 *    $('#resetOrdering').click( function (e) {
544
	 *        e.preventDefault();
545
	 *        $.fn.dataTable.ColReorder( table ).fnReset();
546
	 *    } );
547
	 */
548
	"fnReset": function ()
549
	{
550
		this._fnOrderColumns( this.fnOrder() );
551

552
		return this;
553
	},
554

555
	/**
556
	 * `Deprecated` - Get the current order of the columns, as an array.
557
	 *  @return {array} Array of column identifiers
558
	 *  @deprecated `fnOrder` should be used in preference to this method.
559
	 *      `fnOrder` acts as a getter/setter.
560
	 */
561
	"fnGetCurrentOrder": function ()
562
	{
563
		return this.fnOrder();
564
	},
565

566
	/**
567
	 * Get the current order of the columns, as an array. Note that the values
568
	 * given in the array are unique identifiers for each column. Currently
569
	 * these are the original ordering of the columns that was detected on
570
	 * start up, but this could potentially change in future.
571
	 *  @return {array} Array of column identifiers
572
	 *
573
	 *  @example
574
	 *    // Get column ordering for the table
575
	 *    var order = $.fn.dataTable.ColReorder( dataTable ).fnOrder();
576
	 *//**
577
	 * Set the order of the columns, from the positions identified in the
578
	 * ordering array given. Note that ColReorder takes a brute force approach
579
	 * to reordering, so it is possible multiple reordering events will occur
580
	 * before the final order is settled upon.
581
	 *  @param {array} [set] Array of column identifiers in the new order. Note
582
	 *    that every column must be included, uniquely, in this array.
583
	 *  @return {this} Returns `this` for chaining.
584
	 *
585
	 *  @example
586
	 *    // Swap the first and second columns
587
	 *    $.fn.dataTable.ColReorder( dataTable ).fnOrder( [1, 0, 2, 3, 4] );
588
	 *
589
	 *  @example
590
	 *    // Move the first column to the end for the table `#example`
591
	 *    var curr = $.fn.dataTable.ColReorder( '#example' ).fnOrder();
592
	 *    var first = curr.shift();
593
	 *    curr.push( first );
594
	 *    $.fn.dataTable.ColReorder( '#example' ).fnOrder( curr );
595
	 *
596
	 *  @example
597
	 *    // Reverse the table's order
598
	 *    $.fn.dataTable.ColReorder( '#example' ).fnOrder(
599
	 *      $.fn.dataTable.ColReorder( '#example' ).fnOrder().reverse()
600
	 *    );
601
	 */
602
	"fnOrder": function ( set, original )
603
	{
604
		var a = [], i, ien, j, jen;
605
		var columns = this.s.dt.aoColumns;
606

607
		if ( set === undefined ){
608
			for ( i=0, ien=columns.length ; i<ien ; i++ ) {
609
				a.push( columns[i]._ColReorder_iOrigCol );
610
			}
611

612
			return a;
613
		}
614

615
		// The order given is based on the original indexes, rather than the
616
		// existing ones, so we need to translate from the original to current
617
		// before then doing the order
618
		if ( original ) {
619
			var order = this.fnOrder();
620

621
			for ( i=0, ien=set.length ; i<ien ; i++ ) {
622
				a.push( $.inArray( set[i], order ) );
623
			}
624

625
			set = a;
626
		}
627

628
		this._fnOrderColumns( fnInvertKeyValues( set ) );
629

630
		return this;
631
	},
632

633

634
	/**
635
	 * Convert from the original column index, to the original
636
	 *
637
	 * @param  {int|array} idx Index(es) to convert
638
	 * @param  {string} dir Transpose direction - `fromOriginal` / `toCurrent`
639
	 *   or `'toOriginal` / `fromCurrent`
640
	 * @return {int|array}     Converted values
641
	 */
642
	fnTranspose: function ( idx, dir )
643
	{
644
		if ( ! dir ) {
645
			dir = 'toCurrent';
646
		}
647

648
		var order = this.fnOrder();
649
		var columns = this.s.dt.aoColumns;
650

651
		if ( dir === 'toCurrent' ) {
652
			// Given an original index, want the current
653
			return ! Array.isArray( idx ) ?
654
				$.inArray( idx, order ) :
655
				$.map( idx, function ( index ) {
656
					return $.inArray( index, order );
657
				} );
658
		}
659
		else {
660
			// Given a current index, want the original
661
			return ! Array.isArray( idx ) ?
662
				columns[idx]._ColReorder_iOrigCol :
663
				$.map( idx, function ( index ) {
664
					return columns[index]._ColReorder_iOrigCol;
665
				} );
666
		}
667
	},
668

669

670
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
671
	 * Private methods (they are of course public in JS, but recommended as private)
672
	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
673

674
	/**
675
	 * Constructor logic
676
	 *  @method  _fnConstruct
677
	 *  @returns void
678
	 *  @private
679
	 */
680
	"_fnConstruct": function ()
681
	{
682
		var that = this;
683
		var iLen = this.s.dt.aoColumns.length;
684
		var table = this.s.dt.nTable;
685
		var i;
686

687
		/* Columns discounted from reordering - counting left to right */
688
		if ( this.s.init.iFixedColumns )
689
		{
690
			this.s.fixed = this.s.init.iFixedColumns;
691
		}
692

693
		if ( this.s.init.iFixedColumnsLeft )
694
		{
695
			this.s.fixed = this.s.init.iFixedColumnsLeft;
696
		}
697

698
		/* Columns discounted from reordering - counting right to left */
699
		this.s.fixedRight = this.s.init.iFixedColumnsRight ?
700
			this.s.init.iFixedColumnsRight :
701
			0;
702

703
		/* Drop callback initialisation option */
704
		if ( this.s.init.fnReorderCallback )
705
		{
706
			this.s.reorderCallback = this.s.init.fnReorderCallback;
707
		}
708

709
		/* Add event handlers for the drag and drop, and also mark the original column order */
710
		for ( i = 0; i < iLen; i++ )
711
		{
712
			if ( i > this.s.fixed-1 && i < iLen - this.s.fixedRight )
713
			{
714
				this._fnMouseListener( i, this.s.dt.aoColumns[i].nTh );
715
			}
716

717
			/* Mark the original column order for later reference */
718
			this.s.dt.aoColumns[i]._ColReorder_iOrigCol = i;
719
		}
720

721
		/* State saving */
722
		this.s.dt.oApi._fnCallbackReg( this.s.dt, 'aoStateSaveParams', function (oS, oData) {
723
			that._fnStateSave.call( that, oData );
724
		}, "ColReorder_State" );
725

726
		/* An initial column order has been specified */
727
		var aiOrder = null;
728
		if ( this.s.init.aiOrder )
729
		{
730
			aiOrder = this.s.init.aiOrder.slice();
731
		}
732

733
		/* State loading, overrides the column order given */
734
		if ( this.s.dt.oLoadedState && typeof this.s.dt.oLoadedState.ColReorder != 'undefined' &&
735
		  this.s.dt.oLoadedState.ColReorder.length == this.s.dt.aoColumns.length )
736
		{
737
			aiOrder = this.s.dt.oLoadedState.ColReorder;
738
		}
739

740
		/* If we have an order to apply - do so */
741
		if ( aiOrder )
742
		{
743
			/* We might be called during or after the DataTables initialisation. If before, then we need
744
			 * to wait until the draw is done, if after, then do what we need to do right away
745
			 */
746
			if ( !that.s.dt._bInitComplete )
747
			{
748
				var bDone = false;
749
				$(table).on( 'draw.dt.colReorder', function () {
750
					if ( !that.s.dt._bInitComplete && !bDone )
751
					{
752
						bDone = true;
753
						var resort = fnInvertKeyValues( aiOrder );
754
						that._fnOrderColumns.call( that, resort );
755
					}
756
				} );
757
			}
758
			else
759
			{
760
				var resort = fnInvertKeyValues( aiOrder );
761
				that._fnOrderColumns.call( that, resort );
762
			}
763
		}
764
		else {
765
			this._fnSetColumnIndexes();
766
		}
767

768
		// Destroy clean up
769
		$(table).on( 'destroy.dt.colReorder', function () {
770
			$(table).off( 'destroy.dt.colReorder draw.dt.colReorder' );
771

772
			$.each( that.s.dt.aoColumns, function (i, column) {
773
				$(column.nTh).off('.ColReorder');
774
				$(column.nTh).removeAttr('data-column-index');
775
			} );
776

777
			that.s.dt._colReorder = null;
778
			that.s = null;
779
		} );
780
	},
781

782

783
	/**
784
	 * Set the column order from an array
785
	 *  @method  _fnOrderColumns
786
	 *  @param   array a An array of integers which dictate the column order that should be applied
787
	 *  @returns void
788
	 *  @private
789
	 */
790
	"_fnOrderColumns": function ( a )
791
	{
792
		var changed = false;
793

794
		if ( a.length != this.s.dt.aoColumns.length )
795
		{
796
			this.s.dt.oInstance.oApi._fnLog( this.s.dt, 1, "ColReorder - array reorder does not "+
797
				"match known number of columns. Skipping." );
798
			return;
799
		}
800

801
		for ( var i=0, iLen=a.length ; i<iLen ; i++ )
802
		{
803
			var currIndex = $.inArray( i, a );
804
			if ( i != currIndex )
805
			{
806
				/* Reorder our switching array */
807
				fnArraySwitch( a, currIndex, i );
808

809
				/* Do the column reorder in the table */
810
				this.s.dt.oInstance.fnColReorder( currIndex, i, true, false );
811

812
				changed = true;
813
			}
814
		}
815

816
		this._fnSetColumnIndexes();
817

818
		// Has anything actually changed? If not, then nothing else to do
819
		if ( ! changed ) {
820
			return;
821
		}
822

823
		$.fn.dataTable.Api( this.s.dt ).rows().invalidate();
824

825
		/* When scrolling we need to recalculate the column sizes to allow for the shift */
826
		if ( this.s.dt.oScroll.sX !== "" || this.s.dt.oScroll.sY !== "" )
827
		{
828
			this.s.dt.oInstance.fnAdjustColumnSizing( false );
829
		}
830

831
		/* Save the state */
832
		this.s.dt.oInstance.oApi._fnSaveState( this.s.dt );
833

834
		if ( this.s.reorderCallback !== null )
835
		{
836
			this.s.reorderCallback.call( this );
837
		}
838
	},
839

840

841
	/**
842
	 * Because we change the indexes of columns in the table, relative to their starting point
843
	 * we need to reorder the state columns to what they are at the starting point so we can
844
	 * then rearrange them again on state load!
845
	 *  @method  _fnStateSave
846
	 *  @param   object oState DataTables state
847
	 *  @returns string JSON encoded cookie string for DataTables
848
	 *  @private
849
	 */
850
	"_fnStateSave": function ( oState )
851
	{
852
		var i, iLen, aCopy, iOrigColumn;
853
		var oSettings = this.s.dt;
854
		var columns = oSettings.aoColumns;
855

856
		oState.ColReorder = [];
857

858
		/* Sorting */
859
		if ( oState.aaSorting ) {
860
			// 1.10.0-
861
			for ( i=0 ; i<oState.aaSorting.length ; i++ ) {
862
				oState.aaSorting[i][0] = columns[ oState.aaSorting[i][0] ]._ColReorder_iOrigCol;
863
			}
864

865
			var aSearchCopy = $.extend( true, [], oState.aoSearchCols );
866

867
			for ( i=0, iLen=columns.length ; i<iLen ; i++ )
868
			{
869
				iOrigColumn = columns[i]._ColReorder_iOrigCol;
870

871
				/* Column filter */
872
				oState.aoSearchCols[ iOrigColumn ] = aSearchCopy[i];
873

874
				/* Visibility */
875
				oState.abVisCols[ iOrigColumn ] = columns[i].bVisible;
876

877
				/* Column reordering */
878
				oState.ColReorder.push( iOrigColumn );
879
			}
880
		}
881
		else if ( oState.order ) {
882
			// 1.10.1+
883
			for ( i=0 ; i<oState.order.length ; i++ ) {
884
				oState.order[i][0] = columns[ oState.order[i][0] ]._ColReorder_iOrigCol;
885
			}
886

887
			var stateColumnsCopy = $.extend( true, [], oState.columns );
888

889
			for ( i=0, iLen=columns.length ; i<iLen ; i++ )
890
			{
891
				iOrigColumn = columns[i]._ColReorder_iOrigCol;
892

893
				/* Columns */
894
				oState.columns[ iOrigColumn ] = stateColumnsCopy[i];
895

896
				/* Column reordering */
897
				oState.ColReorder.push( iOrigColumn );
898
			}
899
		}
900
	},
901

902

903
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
904
	 * Mouse drop and drag
905
	 */
906

907
	/**
908
	 * Add a mouse down listener to a particluar TH element
909
	 *  @method  _fnMouseListener
910
	 *  @param   int i Column index
911
	 *  @param   element nTh TH element clicked on
912
	 *  @returns void
913
	 *  @private
914
	 */
915
	"_fnMouseListener": function ( i, nTh )
916
	{
917
		var that = this;
918
		$(nTh)
919
			.on( 'mousedown.ColReorder', function (e) {
920
				if ( that.s.enable && e.which === 1 ) {
921
					that._fnMouseDown.call( that, e, nTh );
922
				}
923
			} )
924
			.on( 'touchstart.ColReorder', function (e) {
925
				if ( that.s.enable ) {
926
					that._fnMouseDown.call( that, e, nTh );
927
				}
928
			} );
929
	},
930

931

932
	/**
933
	 * Mouse down on a TH element in the table header
934
	 *  @method  _fnMouseDown
935
	 *  @param   event e Mouse event
936
	 *  @param   element nTh TH element to be dragged
937
	 *  @returns void
938
	 *  @private
939
	 */
940
	"_fnMouseDown": function ( e, nTh )
941
	{
942
		var that = this;
943

944
		/* Store information about the mouse position */
945
		var target = $(e.target).closest('th, td');
946
		var offset = target.offset();
947
		var idx = parseInt( $(nTh).attr('data-column-index'), 10 );
948

949
		if ( idx === undefined ) {
950
			return;
951
		}
952

953
		this.s.mouse.startX = this._fnCursorPosition( e, 'pageX' );
954
		this.s.mouse.startY = this._fnCursorPosition( e, 'pageY' );
955
		this.s.mouse.offsetX = this._fnCursorPosition( e, 'pageX' ) - offset.left;
956
		this.s.mouse.offsetY = this._fnCursorPosition( e, 'pageY' ) - offset.top;
957
		this.s.mouse.target = this.s.dt.aoColumns[ idx ].nTh;//target[0];
958
		this.s.mouse.targetIndex = idx;
959
		this.s.mouse.fromIndex = idx;
960

961
		this._fnRegions();
962

963
		/* Add event handlers to the document */
964
		$(document)
965
			.on( 'mousemove.ColReorder touchmove.ColReorder', function (e) {
966
				that._fnMouseMove.call( that, e );
967
			} )
968
			.on( 'mouseup.ColReorder touchend.ColReorder', function (e) {
969
				that._fnMouseUp.call( that, e );
970
			} );
971
	},
972

973

974
	/**
975
	 * Deal with a mouse move event while dragging a node
976
	 *  @method  _fnMouseMove
977
	 *  @param   event e Mouse event
978
	 *  @returns void
979
	 *  @private
980
	 */
981
	"_fnMouseMove": function ( e )
982
	{
983
		var that = this;
984

985
		if ( this.dom.drag === null )
986
		{
987
			/* Only create the drag element if the mouse has moved a specific distance from the start
988
			 * point - this allows the user to make small mouse movements when sorting and not have a
989
			 * possibly confusing drag element showing up
990
			 */
991
			if ( Math.pow(
992
				Math.pow(this._fnCursorPosition( e, 'pageX') - this.s.mouse.startX, 2) +
993
				Math.pow(this._fnCursorPosition( e, 'pageY') - this.s.mouse.startY, 2), 0.5 ) < 5 )
994
			{
995
				return;
996
			}
997
			this._fnCreateDragNode();
998
		}
999

1000
		/* Position the element - we respect where in the element the click occured */
1001
		this.dom.drag.css( {
1002
			left: this._fnCursorPosition( e, 'pageX' ) - this.s.mouse.offsetX,
1003
			top: this._fnCursorPosition( e, 'pageY' ) - this.s.mouse.offsetY
1004
		} );
1005

1006
		/* Based on the current mouse position, calculate where the insert should go */
1007
		var target;
1008
		var lastToIndex = this.s.mouse.toIndex;
1009
		var cursorXPosiotion = this._fnCursorPosition(e, 'pageX');
1010
		var targetsPrev = function (i) {
1011
			while (i >= 0) {
1012
				i--;
1013

1014
				if (i <= 0) {
1015
					return null;
1016
				}
1017

1018
				if (that.s.aoTargets[i+1].x !== that.s.aoTargets[i].x) {
1019
					return that.s.aoTargets[i];
1020
				}
1021
			}
1022
		};
1023
		var firstNotHidden = function () {
1024
			for (var i=0 ; i<that.s.aoTargets.length-1 ; i++) {
1025
				if (that.s.aoTargets[i].x !== that.s.aoTargets[i+1].x) {
1026
					return that.s.aoTargets[i];
1027
				}
1028
			}
1029
		};
1030
		var lastNotHidden = function () {
1031
			for (var i=that.s.aoTargets.length-1 ; i>0 ; i--) {
1032
				if (that.s.aoTargets[i].x !== that.s.aoTargets[i-1].x) {
1033
					return that.s.aoTargets[i];
1034
				}
1035
			}
1036
		};
1037

1038
        for (var i = 1; i < this.s.aoTargets.length; i++) {
1039
			var prevTarget = targetsPrev(i);
1040
			if (! prevTarget) {
1041
				prevTarget = firstNotHidden();
1042
			}
1043

1044
			var prevTargetMiddle = prevTarget.x + (this.s.aoTargets[i].x - prevTarget.x) / 2;
1045

1046
            if (this._fnIsLtr()) {
1047
                if (cursorXPosiotion < prevTargetMiddle ) {
1048
                    target = prevTarget;
1049
                    break;
1050
                }
1051
            }
1052
            else {
1053
                if (cursorXPosiotion > prevTargetMiddle) {
1054
                    target = prevTarget;
1055
                    break;
1056
                }
1057
            }
1058
		}
1059

1060
        if (target) {
1061
            this.dom.pointer.css('left', target.x);
1062
            this.s.mouse.toIndex = target.to;
1063
        }
1064
        else {
1065
			// The insert element wasn't positioned in the array (less than
1066
			// operator), so we put it at the end
1067
			this.dom.pointer.css( 'left', lastNotHidden().x );
1068
			this.s.mouse.toIndex = lastNotHidden().to;
1069
		}
1070

1071
		// Perform reordering if realtime updating is on and the column has moved
1072
		if ( this.s.init.bRealtime && lastToIndex !== this.s.mouse.toIndex ) {
1073
			this.s.dt.oInstance.fnColReorder( this.s.mouse.fromIndex, this.s.mouse.toIndex );
1074
			this.s.mouse.fromIndex = this.s.mouse.toIndex;
1075

1076
			// Not great for performance, but required to keep everything in alignment
1077
			if ( this.s.dt.oScroll.sX !== "" || this.s.dt.oScroll.sY !== "" )
1078
			{
1079
				this.s.dt.oInstance.fnAdjustColumnSizing( false );
1080
			}
1081

1082
			this._fnRegions();
1083
		}
1084
	},
1085

1086

1087
	/**
1088
	 * Finish off the mouse drag and insert the column where needed
1089
	 *  @method  _fnMouseUp
1090
	 *  @param   event e Mouse event
1091
	 *  @returns void
1092
	 *  @private
1093
	 */
1094
	"_fnMouseUp": function ( e )
1095
	{
1096
		var that = this;
1097

1098
		$(document).off( '.ColReorder' );
1099

1100
		if ( this.dom.drag !== null )
1101
		{
1102
			/* Remove the guide elements */
1103
			this.dom.drag.remove();
1104
			this.dom.pointer.remove();
1105
			this.dom.drag = null;
1106
			this.dom.pointer = null;
1107

1108
			/* Actually do the reorder */
1109
			this.s.dt.oInstance.fnColReorder( this.s.mouse.fromIndex, this.s.mouse.toIndex, true );
1110
			this._fnSetColumnIndexes();
1111

1112
			/* When scrolling we need to recalculate the column sizes to allow for the shift */
1113
			if ( this.s.dt.oScroll.sX !== "" || this.s.dt.oScroll.sY !== "" )
1114
			{
1115
				this.s.dt.oInstance.fnAdjustColumnSizing( false );
1116
			}
1117

1118
			/* Save the state */
1119
			this.s.dt.oInstance.oApi._fnSaveState( this.s.dt );
1120

1121
			if ( this.s.reorderCallback !== null )
1122
			{
1123
				this.s.reorderCallback.call( this );
1124
			}
1125
		}
1126
	},
1127

1128

1129
	/**
1130
	 * Calculate a cached array with the points of the column inserts, and the
1131
	 * 'to' points
1132
	 *  @method  _fnRegions
1133
	 *  @returns void
1134
	 *  @private
1135
	 */
1136
	"_fnRegions": function ()
1137
	{
1138
		var aoColumns = this.s.dt.aoColumns;
1139
        var isLTR = this._fnIsLtr();
1140
		this.s.aoTargets.splice(0, this.s.aoTargets.length);
1141
		var lastBound = $(this.s.dt.nTable).offset().left;
1142

1143
        var aoColumnBounds = [];
1144
        $.each(aoColumns, function (i, column) {
1145
            if (column.bVisible && column.nTh.style.display !== 'none') {
1146
                var nth = $(column.nTh);
1147
				var bound = nth.offset().left;
1148

1149
                if (isLTR) {
1150
                    bound += nth.outerWidth();
1151
                }
1152

1153
                aoColumnBounds.push({
1154
                    index: i,
1155
                    bound: bound
1156
				});
1157

1158
				lastBound = bound;
1159
			}
1160
			else {
1161
                aoColumnBounds.push({
1162
					index: i,
1163
					bound: lastBound
1164
                });
1165
			}
1166
		});
1167

1168
        var firstColumn = aoColumnBounds[0];
1169
		var firstColumnWidth = $(aoColumns[firstColumn.index].nTh).outerWidth();
1170

1171
        this.s.aoTargets.push({
1172
            to: 0,
1173
			x: firstColumn.bound - firstColumnWidth
1174
        });
1175

1176
        for (var i = 0; i < aoColumnBounds.length; i++) {
1177
            var columnBound = aoColumnBounds[i];
1178
            var iToPoint = columnBound.index;
1179

1180
            /* For the column / header in question, we want it's position to remain the same if the
1181
            * position is just to it's immediate left or right, so we only increment the counter for
1182
            * other columns
1183
            */
1184
            if (columnBound.index < this.s.mouse.fromIndex) {
1185
                iToPoint++;
1186
            }
1187

1188
            this.s.aoTargets.push({
1189
				to: iToPoint,
1190
                x: columnBound.bound
1191
            });
1192
        }
1193

1194
		/* Disallow columns for being reordered by drag and drop, counting right to left */
1195
		if ( this.s.fixedRight !== 0 )
1196
		{
1197
			this.s.aoTargets.splice( this.s.aoTargets.length - this.s.fixedRight );
1198
		}
1199

1200
		/* Disallow columns for being reordered by drag and drop, counting left to right */
1201
		if ( this.s.fixed !== 0 )
1202
		{
1203
			this.s.aoTargets.splice( 0, this.s.fixed );
1204
		}
1205
	},
1206

1207

1208
	/**
1209
	 * Copy the TH element that is being drags so the user has the idea that they are actually
1210
	 * moving it around the page.
1211
	 *  @method  _fnCreateDragNode
1212
	 *  @returns void
1213
	 *  @private
1214
	 */
1215
	"_fnCreateDragNode": function ()
1216
	{
1217
		var scrolling = this.s.dt.oScroll.sX !== "" || this.s.dt.oScroll.sY !== "";
1218

1219
		var origCell = this.s.dt.aoColumns[ this.s.mouse.targetIndex ].nTh;
1220
		var origTr = origCell.parentNode;
1221
		var origThead = origTr.parentNode;
1222
		var origTable = origThead.parentNode;
1223
		var cloneCell = $(origCell).clone();
1224

1225
		// This is a slightly odd combination of jQuery and DOM, but it is the
1226
		// fastest and least resource intensive way I could think of cloning
1227
		// the table with just a single header cell in it.
1228
		this.dom.drag = $(origTable.cloneNode(false))
1229
			.addClass( 'DTCR_clonedTable' )
1230
			.append(
1231
				$(origThead.cloneNode(false)).append(
1232
					$(origTr.cloneNode(false)).append(
1233
						cloneCell[0]
1234
					)
1235
				)
1236
			)
1237
			.css( {
1238
				position: 'absolute',
1239
				top: 0,
1240
				left: 0,
1241
				width: $(origCell).outerWidth(),
1242
				height: $(origCell).outerHeight()
1243
			} )
1244
			.appendTo( 'body' );
1245

1246
		this.dom.pointer = $('<div></div>')
1247
			.addClass( 'DTCR_pointer' )
1248
			.css( {
1249
				position: 'absolute',
1250
				top: scrolling ?
1251
					$('div.dataTables_scroll', this.s.dt.nTableWrapper).offset().top :
1252
					$(this.s.dt.nTable).offset().top,
1253
				height : scrolling ?
1254
					$('div.dataTables_scroll', this.s.dt.nTableWrapper).height() :
1255
					$(this.s.dt.nTable).height()
1256
			} )
1257
			.appendTo( 'body' );
1258
	},
1259

1260

1261
	/**
1262
	 * Add a data attribute to the column headers, so we know the index of
1263
	 * the row to be reordered. This allows fast detection of the index, and
1264
	 * for this plug-in to work with FixedHeader which clones the nodes.
1265
	 *  @private
1266
	 */
1267
	"_fnSetColumnIndexes": function ()
1268
	{
1269
		$.each( this.s.dt.aoColumns, function (i, column) {
1270
			$(column.nTh).attr('data-column-index', i);
1271
		} );
1272
	},
1273

1274

1275
	/**
1276
	 * Get cursor position regardless of mouse or touch input
1277
	 * @param  {Event}  e    jQuery Event
1278
	 * @param  {string} prop Property to get
1279
	 * @return {number}      Value
1280
	 */
1281
	_fnCursorPosition: function ( e, prop ) {
1282
		if ( e.type.indexOf('touch') !== -1 ) {
1283
			return e.originalEvent.touches[0][ prop ];
1284
		}
1285
		return e[ prop ];
1286
    },
1287

1288
    _fnIsLtr: function () {
1289
        return $(this.s.dt.nTable).css('direction') !== "rtl";
1290
    }
1291
} );
1292

1293

1294

1295

1296

1297
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1298
 * Static parameters
1299
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1300

1301

1302
/**
1303
 * ColReorder default settings for initialisation
1304
 *  @namespace
1305
 *  @static
1306
 */
1307
ColReorder.defaults = {
1308
	/**
1309
	 * Predefined ordering for the columns that will be applied automatically
1310
	 * on initialisation. If not specified then the order that the columns are
1311
	 * found to be in the HTML is the order used.
1312
	 *  @type array
1313
	 *  @default null
1314
	 *  @static
1315
	 */
1316
	aiOrder: null,
1317

1318
	/**
1319
	 * ColReorder enable on initialisation
1320
	 *  @type boolean
1321
	 *  @default true
1322
	 *  @static
1323
	 */
1324
	bEnable: true,
1325

1326
	/**
1327
	 * Redraw the table's column ordering as the end user draws the column
1328
	 * (`true`) or wait until the mouse is released (`false` - default). Note
1329
	 * that this will perform a redraw on each reordering, which involves an
1330
	 * Ajax request each time if you are using server-side processing in
1331
	 * DataTables.
1332
	 *  @type boolean
1333
	 *  @default false
1334
	 *  @static
1335
	 */
1336
	bRealtime: true,
1337

1338
	/**
1339
	 * Indicate how many columns should be fixed in position (counting from the
1340
	 * left). This will typically be 1 if used, but can be as high as you like.
1341
	 *  @type int
1342
	 *  @default 0
1343
	 *  @static
1344
	 */
1345
	iFixedColumnsLeft: 0,
1346

1347
	/**
1348
	 * As `iFixedColumnsRight` but counting from the right.
1349
	 *  @type int
1350
	 *  @default 0
1351
	 *  @static
1352
	 */
1353
	iFixedColumnsRight: 0,
1354

1355
	/**
1356
	 * Callback function that is fired when columns are reordered. The `column-
1357
	 * reorder` event is preferred over this callback
1358
	 *  @type function():void
1359
	 *  @default null
1360
	 *  @static
1361
	 */
1362
	fnReorderCallback: null
1363
};
1364

1365

1366

1367
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1368
 * Constants
1369
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1370

1371
/**
1372
 * ColReorder version
1373
 *  @constant  version
1374
 *  @type      String
1375
 *  @default   As code
1376
 */
1377
ColReorder.version = "1.5.4";
1378

1379

1380

1381
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1382
 * DataTables interfaces
1383
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1384

1385
// Expose
1386
$.fn.dataTable.ColReorder = ColReorder;
1387
$.fn.DataTable.ColReorder = ColReorder;
1388

1389

1390
// Register a new feature with DataTables
1391
if ( typeof $.fn.dataTable == "function" &&
1392
     typeof $.fn.dataTableExt.fnVersionCheck == "function" &&
1393
     $.fn.dataTableExt.fnVersionCheck('1.10.8') )
1394
{
1395
	$.fn.dataTableExt.aoFeatures.push( {
1396
		"fnInit": function( settings ) {
1397
			var table = settings.oInstance;
1398

1399
			if ( ! settings._colReorder ) {
1400
				var dtInit = settings.oInit;
1401
				var opts = dtInit.colReorder || dtInit.oColReorder || {};
1402

1403
				new ColReorder( settings, opts );
1404
			}
1405
			else {
1406
				table.oApi._fnLog( settings, 1, "ColReorder attempted to initialise twice. Ignoring second" );
1407
			}
1408

1409
			return null; /* No node for DataTables to insert */
1410
		},
1411
		"cFeature": "R",
1412
		"sFeature": "ColReorder"
1413
	} );
1414
}
1415
else {
1416
	alert( "Warning: ColReorder requires DataTables 1.10.8 or greater - www.datatables.net/download");
1417
}
1418

1419

1420
// Attach a listener to the document which listens for DataTables initialisation
1421
// events so we can automatically initialise
1422
$(document).on( 'preInit.dt.colReorder', function (e, settings) {
1423
	if ( e.namespace !== 'dt' ) {
1424
		return;
1425
	}
1426

1427
	var init = settings.oInit.colReorder;
1428
	var defaults = DataTable.defaults.colReorder;
1429

1430
	if ( init || defaults ) {
1431
		var opts = $.extend( {}, init, defaults );
1432

1433
		if ( init !== false ) {
1434
			new ColReorder( settings, opts  );
1435
		}
1436
	}
1437
} );
1438

1439

1440
// API augmentation
1441
$.fn.dataTable.Api.register( 'colReorder.reset()', function () {
1442
	return this.iterator( 'table', function ( ctx ) {
1443
		ctx._colReorder.fnReset();
1444
	} );
1445
} );
1446

1447
$.fn.dataTable.Api.register( 'colReorder.order()', function ( set, original ) {
1448
	if ( set ) {
1449
		return this.iterator( 'table', function ( ctx ) {
1450
			ctx._colReorder.fnOrder( set, original );
1451
		} );
1452
	}
1453

1454
	return this.context.length ?
1455
		this.context[0]._colReorder.fnOrder() :
1456
		null;
1457
} );
1458

1459
$.fn.dataTable.Api.register( 'colReorder.transpose()', function ( idx, dir ) {
1460
	return this.context.length && this.context[0]._colReorder ?
1461
		this.context[0]._colReorder.fnTranspose( idx, dir ) :
1462
		idx;
1463
} );
1464

1465
$.fn.dataTable.Api.register( 'colReorder.move()', function( from, to, drop, invalidateRows ) {
1466
	if (this.context.length) {
1467
		this.context[0]._colReorder.s.dt.oInstance.fnColReorder( from, to, drop, invalidateRows );
1468
		this.context[0]._colReorder._fnSetColumnIndexes();
1469
	}
1470
	return this;
1471
} );
1472

1473
$.fn.dataTable.Api.register( 'colReorder.enable()', function( flag ) {
1474
	return this.iterator( 'table', function ( ctx ) {
1475
		if ( ctx._colReorder ) {
1476
			ctx._colReorder.fnEnable( flag );
1477
		}
1478
	} );
1479
} );
1480

1481
$.fn.dataTable.Api.register( 'colReorder.disable()', function() {
1482
	return this.iterator( 'table', function ( ctx ) {
1483
		if ( ctx._colReorder ) {
1484
			ctx._colReorder.fnDisable();
1485
		}
1486
	} );
1487
} );
1488

1489

1490
return ColReorder;
1491
}));
1492

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.