Subversion-Projekte lars-tiefland.faltradxxs.de

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
2 lars 1
/*! ColVis 1.1.1
2
 * ©2010-2014 SpryMedia Ltd - datatables.net/license
3
 */
4
 
5
/**
6
 * @summary     ColVis
7
 * @description Controls for column visibility in DataTables
8
 * @version     1.1.1
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
var factory = function( $, DataTable ) {
28
"use strict";
29
 
30
/**
31
 * ColVis provides column visibility control for DataTables
32
 *
33
 * @class ColVis
34
 * @constructor
35
 * @param {object} DataTables settings object. With DataTables 1.10 this can
36
 *   also be and API instance, table node, jQuery collection or jQuery selector.
37
 * @param {object} ColVis configuration options
38
 */
39
var ColVis = function( oDTSettings, oInit )
40
{
41
	/* Santiy check that we are a new instance */
42
	if ( !this.CLASS || this.CLASS != "ColVis" )
43
	{
44
		alert( "Warning: ColVis must be initialised with the keyword 'new'" );
45
	}
46
 
47
	if ( typeof oInit == 'undefined' )
48
	{
49
		oInit = {};
50
	}
51
 
52
	if ( $.fn.dataTable.camelToHungarian ) {
53
		$.fn.dataTable.camelToHungarian( ColVis.defaults, oInit );
54
	}
55
 
56
 
57
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
58
	 * Public class variables
59
	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
60
 
61
	/**
62
	 * @namespace Settings object which contains customisable information for
63
	 *     ColVis instance. Augmented by ColVis.defaults
64
	 */
65
	this.s = {
66
		/**
67
		 * DataTables settings object
68
		 *  @property dt
69
		 *  @type     Object
70
		 *  @default  null
71
		 */
72
		"dt": null,
73
 
74
		/**
75
		 * Customisation object
76
		 *  @property oInit
77
		 *  @type     Object
78
		 *  @default  passed in
79
		 */
80
		"oInit": oInit,
81
 
82
		/**
83
		 * Flag to say if the collection is hidden
84
		 *  @property hidden
85
		 *  @type     boolean
86
		 *  @default  true
87
		 */
88
		"hidden": true,
89
 
90
		/**
91
		 * Store the original visibility settings so they could be restored
92
		 *  @property abOriginal
93
		 *  @type     Array
94
		 *  @default  []
95
		 */
96
		"abOriginal": []
97
	};
98
 
99
 
100
	/**
101
	 * @namespace Common and useful DOM elements for the class instance
102
	 */
103
	this.dom = {
104
		/**
105
		 * Wrapper for the button - given back to DataTables as the node to insert
106
		 *  @property wrapper
107
		 *  @type     Node
108
		 *  @default  null
109
		 */
110
		"wrapper": null,
111
 
112
		/**
113
		 * Activation button
114
		 *  @property button
115
		 *  @type     Node
116
		 *  @default  null
117
		 */
118
		"button": null,
119
 
120
		/**
121
		 * Collection list node
122
		 *  @property collection
123
		 *  @type     Node
124
		 *  @default  null
125
		 */
126
		"collection": null,
127
 
128
		/**
129
		 * Background node used for shading the display and event capturing
130
		 *  @property background
131
		 *  @type     Node
132
		 *  @default  null
133
		 */
134
		"background": null,
135
 
136
		/**
137
		 * Element to position over the activation button to catch mouse events when using mouseover
138
		 *  @property catcher
139
		 *  @type     Node
140
		 *  @default  null
141
		 */
142
		"catcher": null,
143
 
144
		/**
145
		 * List of button elements
146
		 *  @property buttons
147
		 *  @type     Array
148
		 *  @default  []
149
		 */
150
		"buttons": [],
151
 
152
		/**
153
		 * List of group button elements
154
		 *  @property groupButtons
155
		 *  @type     Array
156
		 *  @default  []
157
		 */
158
		"groupButtons": [],
159
 
160
		/**
161
		 * Restore button
162
		 *  @property restore
163
		 *  @type     Node
164
		 *  @default  null
165
		 */
166
		"restore": null
167
	};
168
 
169
	/* Store global reference */
170
	ColVis.aInstances.push( this );
171
 
172
	/* Constructor logic */
173
	this.s.dt = $.fn.dataTable.Api ?
174
		new $.fn.dataTable.Api( oDTSettings ).settings()[0] :
175
		oDTSettings;
176
 
177
	this._fnConstruct( oInit );
178
	return this;
179
};
180
 
181
 
182
 
183
ColVis.prototype = {
184
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
185
	 * Public methods
186
	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
187
 
188
	/**
189
	 * Get the ColVis instance's control button so it can be injected into the
190
	 * DOM
191
	 *  @method  button
192
	 *  @returns {node} ColVis button
193
	 */
194
	button: function ()
195
	{
196
		return this.dom.wrapper;
197
	},
198
 
199
	/**
200
	 * Alias of `rebuild` for backwards compatibility
201
	 *  @method  fnRebuild
202
	 */
203
	"fnRebuild": function ()
204
	{
205
		this.rebuild();
206
	},
207
 
208
	/**
209
	 * Rebuild the list of buttons for this instance (i.e. if there is a column
210
	 * header update)
211
	 *  @method  fnRebuild
212
	 */
213
	rebuild: function ()
214
	{
215
		/* Remove the old buttons */
216
		for ( var i=this.dom.buttons.length-1 ; i>=0 ; i-- ) {
217
			this.dom.collection.removeChild( this.dom.buttons[i] );
218
		}
219
		this.dom.buttons.splice( 0, this.dom.buttons.length );
220
 
221
		if ( this.dom.restore ) {
222
			this.dom.restore.parentNode( this.dom.restore );
223
		}
224
 
225
		/* Re-add them (this is not the optimal way of doing this, it is fast and effective) */
226
		this._fnAddGroups();
227
		this._fnAddButtons();
228
 
229
		/* Update the checkboxes */
230
		this._fnDrawCallback();
231
	},
232
 
233
 
234
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
235
	 * Private methods (they are of course public in JS, but recommended as private)
236
	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
237
 
238
	/**
239
	 * Constructor logic
240
	 *  @method  _fnConstruct
241
	 *  @returns void
242
	 *  @private
243
	 */
244
	"_fnConstruct": function ( init )
245
	{
246
		this._fnApplyCustomisation( init );
247
 
248
		var that = this;
249
		var i, iLen;
250
		this.dom.wrapper = document.createElement('div');
251
		this.dom.wrapper.className = "ColVis";
252
 
253
		this.dom.button = $( '<button />', {
254
				'class': !this.s.dt.bJUI ?
255
					"ColVis_Button ColVis_MasterButton" :
256
					"ColVis_Button ColVis_MasterButton ui-button ui-state-default"
257
			} )
258
			.append( '<span>'+this.s.buttonText+'</span>' )
259
			.bind( this.s.activate=="mouseover" ? "mouseover" : "click", function (e) {
260
				e.preventDefault();
261
				that._fnCollectionShow();
262
			} )
263
			.appendTo( this.dom.wrapper )[0];
264
 
265
		this.dom.catcher = this._fnDomCatcher();
266
		this.dom.collection = this._fnDomCollection();
267
		this.dom.background = this._fnDomBackground();
268
 
269
		this._fnAddGroups();
270
		this._fnAddButtons();
271
 
272
		/* Store the original visibility information */
273
		for ( i=0, iLen=this.s.dt.aoColumns.length ; i<iLen ; i++ )
274
		{
275
			this.s.abOriginal.push( this.s.dt.aoColumns[i].bVisible );
276
		}
277
 
278
		/* Update on each draw */
279
		this.s.dt.aoDrawCallback.push( {
280
			"fn": function () {
281
				that._fnDrawCallback.call( that );
282
			},
283
			"sName": "ColVis"
284
		} );
285
 
286
		/* If columns are reordered, then we need to update our exclude list and
287
		 * rebuild the displayed list
288
		 */
289
		$(this.s.dt.oInstance).bind( 'column-reorder', function ( e, oSettings, oReorder ) {
290
			for ( i=0, iLen=that.s.aiExclude.length ; i<iLen ; i++ ) {
291
				that.s.aiExclude[i] = oReorder.aiInvertMapping[ that.s.aiExclude[i] ];
292
			}
293
 
294
			var mStore = that.s.abOriginal.splice( oReorder.iFrom, 1 )[0];
295
			that.s.abOriginal.splice( oReorder.iTo, 0, mStore );
296
 
297
			that.fnRebuild();
298
		} );
299
 
300
		// Set the initial state
301
		this._fnDrawCallback();
302
	},
303
 
304
 
305
	/**
306
	 * Apply any customisation to the settings from the DataTables initialisation
307
	 *  @method  _fnApplyCustomisation
308
	 *  @returns void
309
	 *  @private
310
	 */
311
	"_fnApplyCustomisation": function ( init )
312
	{
313
		$.extend( true, this.s, ColVis.defaults, init );
314
 
315
		// Slightly messy overlap for the camelCase notation
316
		if ( ! this.s.showAll && this.s.bShowAll ) {
317
			this.s.showAll = this.s.sShowAll;
318
		}
319
 
320
		if ( ! this.s.restore && this.s.bRestore ) {
321
			this.s.restore = this.s.sRestore;
322
		}
323
 
324
		// CamelCase to Hungarian for the column groups
325
		var groups = this.s.groups;
326
		var hungarianGroups = this.s.aoGroups;
327
		if ( groups ) {
328
			for ( var i=0, ien=groups.length ; i<ien ; i++ ) {
329
				if ( groups[i].title ) {
330
					hungarianGroups[i].sTitle = groups[i].title;
331
				}
332
				if ( groups[i].columns ) {
333
					hungarianGroups[i].aiColumns = groups[i].columns;
334
				}
335
			}
336
		}
337
	},
338
 
339
 
340
	/**
341
	 * On each table draw, check the visibility checkboxes as needed. This allows any process to
342
	 * update the table's column visibility and ColVis will still be accurate.
343
	 *  @method  _fnDrawCallback
344
	 *  @returns void
345
	 *  @private
346
	 */
347
	"_fnDrawCallback": function ()
348
	{
349
		var columns = this.s.dt.aoColumns;
350
		var buttons = this.dom.buttons;
351
		var groups = this.s.aoGroups;
352
		var button;
353
 
354
		for ( var i=0, ien=buttons.length ; i<ien ; i++ ) {
355
			button = buttons[i];
356
 
357
			if ( button.__columnIdx !== undefined ) {
358
				$('input', button).prop( 'checked', columns[ button.__columnIdx ].bVisible );
359
			}
360
		}
361
 
362
		var allVisible = function ( columnIndeces ) {
363
			for ( var k=0, kLen=columnIndeces.length ; k<kLen ; k++ )
364
			{
365
				if (  columns[columnIndeces[k]].bVisible === false ) { return false; }
366
			}
367
			return true;
368
		};
369
		var allHidden = function ( columnIndeces ) {
370
			for ( var m=0 , mLen=columnIndeces.length ; m<mLen ; m++ )
371
			{
372
				if ( columns[columnIndeces[m]].bVisible === true ) { return false; }
373
			}
374
			return true;
375
		};
376
 
377
		for ( var j=0, jLen=groups.length ; j<jLen ; j++ )
378
		{
379
			if ( allVisible(groups[j].aiColumns) )
380
			{
381
				$('input', this.dom.groupButtons[j]).prop('checked', true);
382
				$('input', this.dom.groupButtons[j]).prop('indeterminate', false);
383
			}
384
			else if ( allHidden(groups[j].aiColumns) )
385
			{
386
				$('input', this.dom.groupButtons[j]).prop('checked', false);
387
				$('input', this.dom.groupButtons[j]).prop('indeterminate', false);
388
			}
389
			else
390
			{
391
				$('input', this.dom.groupButtons[j]).prop('indeterminate', true);
392
			}
393
		}
394
	},
395
 
396
 
397
	/**
398
	 * Loop through the groups (provided in the settings) and create a button for each.
399
	 *  @method  _fnAddgroups
400
	 *  @returns void
401
	 *  @private
402
	 */
403
	"_fnAddGroups": function ()
404
	{
405
		var nButton;
406
 
407
		if ( typeof this.s.aoGroups != 'undefined' )
408
		{
409
			for ( var i=0, iLen=this.s.aoGroups.length ; i<iLen ; i++ )
410
			{
411
				nButton = this._fnDomGroupButton( i );
412
				this.dom.groupButtons.push( nButton );
413
				this.dom.buttons.push( nButton );
414
				this.dom.collection.appendChild( nButton );
415
			}
416
		}
417
	},
418
 
419
 
420
	/**
421
	 * Loop through the columns in the table and as a new button for each one.
422
	 *  @method  _fnAddButtons
423
	 *  @returns void
424
	 *  @private
425
	 */
426
	"_fnAddButtons": function ()
427
	{
428
		var
429
			nButton,
430
			columns = this.s.dt.aoColumns;
431
 
432
		if ( $.inArray( 'all', this.s.aiExclude ) === -1 ) {
433
			for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
434
			{
435
				if ( $.inArray( i, this.s.aiExclude ) === -1 )
436
				{
437
					nButton = this._fnDomColumnButton( i );
438
					nButton.__columnIdx = i;
439
					this.dom.buttons.push( nButton );
440
				}
441
			}
442
		}
443
 
444
		if ( this.s.order === 'alpha' ) {
445
			this.dom.buttons.sort( function ( a, b ) {
446
				var titleA = columns[ a.__columnIdx ].sTitle;
447
				var titleB = columns[ b.__columnIdx ].sTitle;
448
 
449
				return titleA === titleB ?
450
 
451
					titleA < titleB ?
452
						-1 :
453
						1;
454
			} );
455
		}
456
 
457
		if ( this.s.restore )
458
		{
459
			nButton = this._fnDomRestoreButton();
460
			nButton.className += " ColVis_Restore";
461
			this.dom.buttons.push( nButton );
462
		}
463
 
464
		if ( this.s.showAll )
465
		{
466
			nButton = this._fnDomShowXButton( this.s.showAll, true );
467
			nButton.className += " ColVis_ShowAll";
468
			this.dom.buttons.push( nButton );
469
		}
470
 
471
		if ( this.s.showNone )
472
		{
473
			nButton = this._fnDomShowXButton( this.s.showNone, false );
474
			nButton.className += " ColVis_ShowNone";
475
			this.dom.buttons.push( nButton );
476
		}
477
 
478
		$(this.dom.collection).append( this.dom.buttons );
479
	},
480
 
481
 
482
	/**
483
	 * Create a button which allows a "restore" action
484
	 *  @method  _fnDomRestoreButton
485
	 *  @returns {Node} Created button
486
	 *  @private
487
	 */
488
	"_fnDomRestoreButton": function ()
489
	{
490
		var
491
			that = this,
492
			dt = this.s.dt;
493
 
494
		return $(
495
				'<li class="ColVis_Special '+(dt.bJUI ? 'ui-button ui-state-default' : '')+'">'+
496
					this.s.restore+
497
				'</li>'
498
			)
499
			.click( function (e) {
500
				for ( var i=0, iLen=that.s.abOriginal.length ; i<iLen ; i++ )
501
				{
502
					that.s.dt.oInstance.fnSetColumnVis( i, that.s.abOriginal[i], false );
503
				}
504
				that._fnAdjustOpenRows();
505
				that.s.dt.oInstance.fnAdjustColumnSizing( false );
506
				that.s.dt.oInstance.fnDraw( false );
507
			} )[0];
508
	},
509
 
510
 
511
	/**
512
	 * Create a button which allows show all and show node actions
513
	 *  @method  _fnDomShowXButton
514
	 *  @returns {Node} Created button
515
	 *  @private
516
	 */
517
	"_fnDomShowXButton": function ( str, action )
518
	{
519
		var
520
			that = this,
521
			dt = this.s.dt;
522
 
523
		return $(
524
				'<li class="ColVis_Special '+(dt.bJUI ? 'ui-button ui-state-default' : '')+'">'+
525
					str+
526
				'</li>'
527
			)
528
			.click( function (e) {
529
				for ( var i=0, iLen=that.s.abOriginal.length ; i<iLen ; i++ )
530
				{
531
					if (that.s.aiExclude.indexOf(i) === -1)
532
					{
533
						that.s.dt.oInstance.fnSetColumnVis( i, action, false );
534
					}
535
				}
536
				that._fnAdjustOpenRows();
537
				that.s.dt.oInstance.fnAdjustColumnSizing( false );
538
				that.s.dt.oInstance.fnDraw( false );
539
			} )[0];
540
	},
541
 
542
 
543
	/**
544
	 * Create the DOM for a show / hide group button
545
	 *  @method  _fnDomGroupButton
546
	 *  @param {int} i Group in question, order based on that provided in settings
547
	 *  @returns {Node} Created button
548
	 *  @private
549
	 */
550
	"_fnDomGroupButton": function ( i )
551
	{
552
		var
553
			that = this,
554
			dt = this.s.dt,
555
			oGroup = this.s.aoGroups[i];
556
 
557
		return $(
558
				'<li class="ColVis_Special '+(dt.bJUI ? 'ui-button ui-state-default' : '')+'">'+
559
					'<label>'+
560
						'<input type="checkbox" />'+
561
						'<span>'+oGroup.sTitle+'</span>'+
562
					'</label>'+
563
				'</li>'
564
			)
565
			.click( function (e) {
566
				var showHide = !$('input', this).is(":checked");
567
				if (  e.target.nodeName.toLowerCase() !== "li" )
568
				{
569
					showHide = ! showHide;
570
				}
571
 
572
				for ( var j=0 ; j < oGroup.aiColumns.length ; j++ )
573
				{
574
					that.s.dt.oInstance.fnSetColumnVis( oGroup.aiColumns[j], showHide );
575
				}
576
			} )[0];
577
	},
578
 
579
 
580
	/**
581
	 * Create the DOM for a show / hide button
582
	 *  @method  _fnDomColumnButton
583
	 *  @param {int} i Column in question
584
	 *  @returns {Node} Created button
585
	 *  @private
586
	 */
587
	"_fnDomColumnButton": function ( i )
588
	{
589
		var
590
			that = this,
591
			column = this.s.dt.aoColumns[i],
592
			dt = this.s.dt;
593
 
594
		var title = this.s.fnLabel===null ?
595
			column.sTitle :
596
			this.s.fnLabel( i, column.sTitle, column.nTh );
597
 
598
		return $(
599
				'<li '+(dt.bJUI ? 'class="ui-button ui-state-default"' : '')+'>'+
600
					'<label>'+
601
						'<input type="checkbox" />'+
602
						'<span>'+title+'</span>'+
603
					'</label>'+
604
				'</li>'
605
			)
606
			.click( function (e) {
607
				var showHide = !$('input', this).is(":checked");
608
				if (  e.target.nodeName.toLowerCase() !== "li" )
609
				{
610
					showHide = ! showHide;
611
				}
612
 
613
				/* Need to consider the case where the initialiser created more than one table - change the
614
				 * API index that DataTables is using
615
				 */
616
				var oldIndex = $.fn.dataTableExt.iApiIndex;
617
				$.fn.dataTableExt.iApiIndex = that._fnDataTablesApiIndex.call(that);
618
 
619
				// Optimisation for server-side processing when scrolling - don't do a full redraw
620
				if ( dt.oFeatures.bServerSide )
621
				{
622
					that.s.dt.oInstance.fnSetColumnVis( i, showHide, false );
623
					that.s.dt.oInstance.fnAdjustColumnSizing( false );
624
					if (dt.oScroll.sX !== "" || dt.oScroll.sY !== "" )
625
					{
626
						that.s.dt.oInstance.oApi._fnScrollDraw( that.s.dt );
627
					}
628
					that._fnDrawCallback();
629
				}
630
				else
631
				{
632
					that.s.dt.oInstance.fnSetColumnVis( i, showHide );
633
				}
634
 
635
				$.fn.dataTableExt.iApiIndex = oldIndex; /* Restore */
636
 
637
				if ( e.target.nodeName.toLowerCase() === 'input' && that.s.fnStateChange !== null )
638
				{
639
					that.s.fnStateChange.call( that, i, showHide );
640
				}
641
			} )[0];
642
	},
643
 
644
 
645
	/**
646
	 * Get the position in the DataTables instance array of the table for this
647
	 * instance of ColVis
648
	 *  @method  _fnDataTablesApiIndex
649
	 *  @returns {int} Index
650
	 *  @private
651
	 */
652
	"_fnDataTablesApiIndex": function ()
653
	{
654
		for ( var i=0, iLen=this.s.dt.oInstance.length ; i<iLen ; i++ )
655
		{
656
			if ( this.s.dt.oInstance[i] == this.s.dt.nTable )
657
			{
658
				return i;
659
			}
660
		}
661
		return 0;
662
	},
663
 
664
 
665
	/**
666
	 * Create the element used to contain list the columns (it is shown and
667
	 * hidden as needed)
668
	 *  @method  _fnDomCollection
669
	 *  @returns {Node} div container for the collection
670
	 *  @private
671
	 */
672
	"_fnDomCollection": function ()
673
	{
674
		return $('<ul />', {
675
				'class': !this.s.dt.bJUI ?
676
					"ColVis_collection" :
677
					"ColVis_collection ui-buttonset ui-buttonset-multi"
678
			} )
679
		.css( {
680
			'display': 'none',
681
			'opacity': 0,
682
			'position': ! this.s.bCssPosition ?
683
				'absolute' :
684
				''
685
		} )[0];
686
	},
687
 
688
 
689
	/**
690
	 * An element to be placed on top of the activate button to catch events
691
	 *  @method  _fnDomCatcher
692
	 *  @returns {Node} div container for the collection
693
	 *  @private
694
	 */
695
	"_fnDomCatcher": function ()
696
	{
697
		var
698
			that = this,
699
			nCatcher = document.createElement('div');
700
		nCatcher.className = "ColVis_catcher";
701
 
702
		$(nCatcher).click( function () {
703
			that._fnCollectionHide.call( that, null, null );
704
		} );
705
 
706
		return nCatcher;
707
	},
708
 
709
 
710
	/**
711
	 * Create the element used to shade the background, and capture hide events (it is shown and
712
	 * hidden as needed)
713
	 *  @method  _fnDomBackground
714
	 *  @returns {Node} div container for the background
715
	 *  @private
716
	 */
717
	"_fnDomBackground": function ()
718
	{
719
		var that = this;
720
 
721
		var background = $('<div></div>')
722
			.addClass( 'ColVis_collectionBackground' )
723
			.css( 'opacity', 0 )
724
			.click( function () {
725
				that._fnCollectionHide.call( that, null, null );
726
			} );
727
 
728
		/* When considering a mouse over action for the activation, we also consider a mouse out
729
		 * which is the same as a mouse over the background - without all the messing around of
730
		 * bubbling events. Use the catcher element to avoid messing around with bubbling
731
		 */
732
		if ( this.s.activate == "mouseover" )
733
		{
734
			background.mouseover( function () {
735
				that.s.overcollection = false;
736
				that._fnCollectionHide.call( that, null, null );
737
			} );
738
		}
739
 
740
		return background[0];
741
	},
742
 
743
 
744
	/**
745
	 * Show the show / hide list and the background
746
	 *  @method  _fnCollectionShow
747
	 *  @returns void
748
	 *  @private
749
	 */
750
	"_fnCollectionShow": function ()
751
	{
752
		var that = this, i, iLen, iLeft;
753
		var oPos = $(this.dom.button).offset();
754
		var nHidden = this.dom.collection;
755
		var nBackground = this.dom.background;
756
		var iDivX = parseInt(oPos.left, 10);
757
		var iDivY = parseInt(oPos.top + $(this.dom.button).outerHeight(), 10);
758
 
759
		if ( ! this.s.bCssPosition )
760
		{
761
			nHidden.style.top = iDivY+"px";
762
			nHidden.style.left = iDivX+"px";
763
		}
764
 
765
		$(nHidden).css( {
766
			'display': 'block',
767
			'opacity': 0
768
		} );
769
 
770
		nBackground.style.bottom ='0px';
771
		nBackground.style.right = '0px';
772
 
773
		var oStyle = this.dom.catcher.style;
774
		oStyle.height = $(this.dom.button).outerHeight()+"px";
775
		oStyle.width = $(this.dom.button).outerWidth()+"px";
776
		oStyle.top = oPos.top+"px";
777
		oStyle.left = iDivX+"px";
778
 
779
		document.body.appendChild( nBackground );
780
		document.body.appendChild( nHidden );
781
		document.body.appendChild( this.dom.catcher );
782
 
783
		/* This results in a very small delay for the end user but it allows the animation to be
784
		 * much smoother. If you don't want the animation, then the setTimeout can be removed
785
		 */
786
		$(nHidden).animate({"opacity": 1}, that.s.iOverlayFade);
787
		$(nBackground).animate({"opacity": 0.1}, that.s.iOverlayFade, 'linear', function () {
788
			/* In IE6 if you set the checked attribute of a hidden checkbox, then this is not visually
789
			 * reflected. As such, we need to do it here, once it is visible. Unbelievable.
790
			 */
791
			if ( $.browser && $.browser.msie && $.browser.version == "6.0" )
792
			{
793
				that._fnDrawCallback();
794
			}
795
		});
796
 
797
		/* Visual corrections to try and keep the collection visible */
798
		if ( !this.s.bCssPosition )
799
		{
800
			iLeft = ( this.s.sAlign=="left" ) ?
801
				iDivX :
802
				iDivX - $(nHidden).outerWidth() + $(this.dom.button).outerWidth();
803
 
804
			nHidden.style.left = iLeft+"px";
805
 
806
			var iDivWidth = $(nHidden).outerWidth();
807
			var iDivHeight = $(nHidden).outerHeight();
808
			var iDocWidth = $(document).width();
809
 
810
			if ( iLeft + iDivWidth > iDocWidth )
811
			{
812
				nHidden.style.left = (iDocWidth-iDivWidth)+"px";
813
			}
814
		}
815
 
816
		this.s.hidden = false;
817
	},
818
 
819
 
820
	/**
821
	 * Hide the show / hide list and the background
822
	 *  @method  _fnCollectionHide
823
	 *  @returns void
824
	 *  @private
825
	 */
826
	"_fnCollectionHide": function (  )
827
	{
828
		var that = this;
829
 
830
		if ( !this.s.hidden && this.dom.collection !== null )
831
		{
832
			this.s.hidden = true;
833
 
834
			$(this.dom.collection).animate({"opacity": 0}, that.s.iOverlayFade, function (e) {
835
				this.style.display = "none";
836
			} );
837
 
838
			$(this.dom.background).animate({"opacity": 0}, that.s.iOverlayFade, function (e) {
839
				document.body.removeChild( that.dom.background );
840
				document.body.removeChild( that.dom.catcher );
841
			} );
842
		}
843
	},
844
 
845
 
846
	/**
847
	 * Alter the colspan on any fnOpen rows
848
	 */
849
	"_fnAdjustOpenRows": function ()
850
	{
851
		var aoOpen = this.s.dt.aoOpenRows;
852
		var iVisible = this.s.dt.oApi._fnVisbleColumns( this.s.dt );
853
 
854
		for ( var i=0, iLen=aoOpen.length ; i<iLen ; i++ ) {
855
			aoOpen[i].nTr.getElementsByTagName('td')[0].colSpan = iVisible;
856
		}
857
	}
858
};
859
 
860
 
861
 
862
 
863
 
864
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
865
 * Static object methods
866
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
867
 
868
/**
869
 * Rebuild the collection for a given table, or all tables if no parameter given
870
 *  @method  ColVis.fnRebuild
871
 *  @static
872
 *  @param   object oTable DataTable instance to consider - optional
873
 *  @returns void
874
 */
875
ColVis.fnRebuild = function ( oTable )
876
{
877
	var nTable = null;
878
	if ( typeof oTable != 'undefined' )
879
	{
880
		nTable = oTable.fnSettings().nTable;
881
	}
882
 
883
	for ( var i=0, iLen=ColVis.aInstances.length ; i<iLen ; i++ )
884
	{
885
		if ( typeof oTable == 'undefined' || nTable == ColVis.aInstances[i].s.dt.nTable )
886
		{
887
			ColVis.aInstances[i].fnRebuild();
888
		}
889
	}
890
};
891
 
892
 
893
ColVis.defaults = {
894
	/**
895
	 * Mode of activation. Can be 'click' or 'mouseover'
896
	 *  @property activate
897
	 *  @type     string
898
	 *  @default  click
899
	 */
900
	active: 'click',
901
 
902
	/**
903
	 * Text used for the button
904
	 *  @property buttonText
905
	 *  @type     string
906
	 *  @default  Show / hide columns
907
	 */
908
	buttonText: 'Show / hide columns',
909
 
910
	/**
911
	 * List of columns (integers) which should be excluded from the list
912
	 *  @property aiExclude
913
	 *  @type     array
914
	 *  @default  []
915
	 */
916
	aiExclude: [],
917
 
918
	/**
919
	 * Show restore button
920
	 *  @property bRestore
921
	 *  @type     boolean
922
	 *  @default  false
923
	 */
924
	bRestore: false,
925
 
926
	/**
927
	 * Restore button text
928
	 *  @property sRestore
929
	 *  @type     string
930
	 *  @default  Restore original
931
	 */
932
	sRestore: 'Restore original',
933
 
934
	/**
935
	 * Show Show-All button
936
	 *  @property bShowAll
937
	 *  @type     boolean
938
	 *  @default  false
939
	 */
940
	bShowAll: false,
941
 
942
	/**
943
	 * Show All button text
944
	 *  @property sShowAll
945
	 *  @type     string
946
	 *  @default  Restore original
947
	 */
948
	sShowAll: 'Show All',
949
 
950
	/**
951
	 * Position of the collection menu when shown - align "left" or "right"
952
	 *  @property sAlign
953
	 *  @type     string
954
	 *  @default  left
955
	 */
956
	sAlign: 'left',
957
 
958
	/**
959
	 * Callback function to tell the user when the state has changed
960
	 *  @property fnStateChange
961
	 *  @type     function
962
	 *  @default  null
963
	 */
964
	fnStateChange: null,
965
 
966
	/**
967
	 * Overlay animation duration in mS
968
	 *  @property iOverlayFade
969
	 *  @type     integer|false
970
	 *  @default  500
971
	 */
972
	iOverlayFade: 500,
973
 
974
	/**
975
	 * Label callback for column names. Takes three parameters: 1. the
976
	 * column index, 2. the column title detected by DataTables and 3. the
977
	 * TH node for the column
978
	 *  @property fnLabel
979
	 *  @type     function
980
	 *  @default  null
981
	 */
982
	fnLabel: null,
983
 
984
	/**
985
	 * Indicate if the column list should be positioned by Javascript,
986
	 * visually below the button or allow CSS to do the positioning
987
	 *  @property bCssPosition
988
	 *  @type     boolean
989
	 *  @default  false
990
	 */
991
	bCssPosition: false,
992
 
993
	/**
994
	 * Group buttons
995
	 *  @property aoGroups
996
	 *  @type     array
997
	 *  @default  []
998
	 */
999
	aoGroups: [],
1000
 
1001
	/**
1002
	 * Button ordering - 'alpha' (alphabetical) or 'column' (table column
1003
	 * order)
1004
	 *  @property order
1005
	 *  @type     string
1006
	 *  @default  column
1007
	 */
1008
	order: 'column'
1009
};
1010
 
1011
 
1012
 
1013
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1014
 * Static object properties
1015
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1016
 
1017
/**
1018
 * Collection of all ColVis instances
1019
 *  @property ColVis.aInstances
1020
 *  @static
1021
 *  @type     Array
1022
 *  @default  []
1023
 */
1024
ColVis.aInstances = [];
1025
 
1026
 
1027
 
1028
 
1029
 
1030
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1031
 * Constants
1032
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1033
 
1034
/**
1035
 * Name of this class
1036
 *  @constant CLASS
1037
 *  @type     String
1038
 *  @default  ColVis
1039
 */
1040
ColVis.prototype.CLASS = "ColVis";
1041
 
1042
 
1043
/**
1044
 * ColVis version
1045
 *  @constant  VERSION
1046
 *  @type      String
1047
 *  @default   See code
1048
 */
1049
ColVis.VERSION = "1.1.1";
1050
ColVis.prototype.VERSION = ColVis.VERSION;
1051
 
1052
 
1053
 
1054
 
1055
 
1056
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1057
 * Initialisation
1058
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1059
 
1060
/*
1061
 * Register a new feature with DataTables
1062
 */
1063
if ( typeof $.fn.dataTable == "function" &&
1064
     typeof $.fn.dataTableExt.fnVersionCheck == "function" &&
1065
     $.fn.dataTableExt.fnVersionCheck('1.7.0') )
1066
{
1067
	$.fn.dataTableExt.aoFeatures.push( {
1068
		"fnInit": function( oDTSettings ) {
1069
			var init = oDTSettings.oInit;
1070
			var colvis = new ColVis( oDTSettings, init.colVis || init.oColVis || {} );
1071
			return colvis.button();
1072
		},
1073
		"cFeature": "C",
1074
		"sFeature": "ColVis"
1075
	} );
1076
}
1077
else
1078
{
1079
	alert( "Warning: ColVis requires DataTables 1.7 or greater - www.datatables.net/download");
1080
}
1081
 
1082
 
1083
// Make ColVis accessible from the DataTables instance
1084
$.fn.dataTable.ColVis = ColVis;
1085
$.fn.DataTable.ColVis = ColVis;
1086
 
1087
 
1088
return ColVis;
1089
}; // /factory
1090
 
1091
 
1092
// Define as an AMD module if possible
1093
if ( typeof define === 'function' && define.amd ) {
1094
	define( ['jquery', 'datatables'], factory );
1095
}
1096
else if ( typeof exports === 'object' ) {
1097
    // Node/CommonJS
1098
    factory( require('jquery'), require('datatables') );
1099
}
1100
else if ( jQuery && !jQuery.fn.dataTable.ColVis ) {
1101
	// Otherwise simply initialise as normal, stopping multiple evaluation
1102
	factory( jQuery, jQuery.fn.dataTable );
1103
}
1104
 
1105
 
1106
})(window, document);
1107