Free cookie consent management tool by TermsFeed Policy Generator

source: branches/WebApplication/MVC2/HeuristicLabWeb.PluginHost/HLWebPluginHost/Content/jQuery/jQueryPlugins/DataTables-1.7.6/extras/ColVis/media/js/ColVis.js @ 6286

Last change on this file since 6286 was 6286, checked in by dkahn, 13 years ago

#1198 Added jQuery plus plugins

File size: 19.6 KB
RevLine 
[6286]1/*
2 * File:        ColVis.js
3 * Version:     1.0.4
4 * CVS:         $Id$
5 * Description: Controls for column visiblity in DataTables
6 * Author:      Allan Jardine (www.sprymedia.co.uk)
7 * Created:     Wed Sep 15 18:23:29 BST 2010
8 * Modified:    $Date$ by $Author$
9 * Language:    Javascript
10 * License:     LGPL
11 * Project:     Just a little bit of fun :-)
12 * Contact:     www.sprymedia.co.uk/contact
13 *
14 * Copyright 2010 Allan Jardine, all rights reserved.
15 *
16 */
17
18(function($) {
19
20/**
21 * ColVis provides column visiblity control for DataTables
22 * @class ColVis
23 * @constructor
24 * @param {object} DataTables settings object
25 */
26ColVis = function( oDTSettings, oInit )
27{
28  /* Santiy check that we are a new instance */
29  if ( !this.CLASS || this.CLASS != "ColVis" )
30  {
31    alert( "Warning: ColVis must be initialised with the keyword 'new'" );
32  }
33 
34  if ( typeof oInit == 'undefined' )
35  {
36    oInit = {};
37  }
38 
39 
40  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
41   * Public class variables
42   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
43 
44  /**
45   * @namespace Settings object which contains customisable information for ColVis instance
46   */
47  this.s = {
48    /**
49     * DataTables settings object
50     *  @property dt
51     *  @type     Object
52     *  @default  null
53     */
54    "dt": null,
55   
56    /**
57     * Customisation object
58     *  @property oInit
59     *  @type     Object
60     *  @default  passed in
61     */
62    "oInit": oInit,
63   
64    /**
65     * Callback function to tell the user when the state has changed
66     *  @property fnStateChange
67     *  @type     function
68     *  @default  null
69     */
70    "fnStateChange": null,
71   
72    /**
73     * Mode of activation. Can be 'click' or 'mouseover'
74     *  @property activate
75     *  @type     String
76     *  @default  click
77     */
78    "activate": "click",
79   
80    /**
81     * Position of the collection menu when shown - align "left" or "right"
82     *  @property sAlign
83     *  @type     String
84     *  @default  right
85     */
86    "sAlign": "left",
87   
88    /**
89     * Text used for the button
90     *  @property buttonText
91     *  @type     String
92     *  @default  Show / hide columns
93     */
94    "buttonText": "Show / hide columns",
95   
96    /**
97     * Flag to say if the collection is hidden
98     *  @property hidden
99     *  @type     boolean
100     *  @default  true
101     */
102    "hidden": true,
103   
104    /**
105     * List of columns (integers) which should be excluded from the list
106     *  @property aiExclude
107     *  @type     Array
108     *  @default  []
109     */
110    "aiExclude": [],
111   
112    /**
113     * Store the original viisbility settings so they could be restored
114     *  @property abOriginal
115     *  @type     Array
116     *  @default  []
117     */
118    "abOriginal": [],
119   
120    /**
121     * Show restore button
122     *  @property bRestore
123     *  @type     Array
124     *  @default  []
125     */
126    "bRestore": false,
127   
128    /**
129     * Restore button text
130     *  @property sRestore
131     *  @type     String
132     *  @default  Restore original
133     */
134    "sRestore": "Restore original"
135  };
136 
137 
138  /**
139   * @namespace Common and useful DOM elements for the class instance
140   */
141  this.dom = {
142    /**
143     * Wrapper for the button - given back to DataTables as the node to insert
144     *  @property wrapper
145     *  @type     Node
146     *  @default  null
147     */
148    "wrapper": null,
149   
150    /**
151     * Activation button
152     *  @property button
153     *  @type     Node
154     *  @default  null
155     */
156    "button": null,
157   
158    /**
159     * Collection list node
160     *  @property collection
161     *  @type     Node
162     *  @default  null
163     */
164    "collection": null,
165   
166    /**
167     * Background node used for shading the display and event capturing
168     *  @property background
169     *  @type     Node
170     *  @default  null
171     */
172    "background": null,
173   
174    /**
175     * Element to position over the activation button to catch mouse events when using mouseover
176     *  @property catcher
177     *  @type     Node
178     *  @default  null
179     */
180    "catcher": null,
181   
182    /**
183     * List of button elements
184     *  @property buttons
185     *  @type     Array
186     *  @default  []
187     */
188    "buttons": [],
189   
190    /**
191     * Restore button
192     *  @property restore
193     *  @type     Node
194     *  @default  null
195     */
196    "restore": null
197  };
198 
199  /* Store global reference */
200  ColVis.aInstances.push( this );
201 
202  /* Constructor logic */
203  this.s.dt = oDTSettings;
204  this._fnConstruct();
205  return this;
206};
207
208
209
210ColVis.prototype = {
211  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
212   * Public methods
213   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
214 
215  /**
216   * Rebuild the list of buttons for this instance (i.e. if there is a column header update)
217   *  @method  fnRebuild
218   *  @returns void
219   */
220  "fnRebuild": function ()
221  {
222    /* Remove the old buttons */
223    for ( var i=this.dom.buttons.length-1 ; i>=0 ; i-- )
224    {
225      if ( this.dom.buttons[i] !== null )
226      {
227        this.dom.collection.removeChild( this.dom.buttons[i] );
228      }
229    }
230    this.dom.buttons.splice( 0, this.dom.buttons.length );
231   
232    if ( this.dom.restore )
233    {
234      this.dom.restore.parentNode( this.dom.restore );
235    }
236   
237    /* Re-add them (this is not the optimal way of doing this, it is fast and effective) */
238    this._fnAddButtons();
239   
240    /* Update the checkboxes */
241    this._fnDrawCallback();
242  },
243 
244 
245 
246  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
247   * Private methods (they are of course public in JS, but recommended as private)
248   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
249 
250  /**
251   * Constructor logic
252   *  @method  _fnConstruct
253   *  @returns void
254   *  @private
255   */
256  "_fnConstruct": function ()
257  {
258    this._fnApplyCustomisation();
259   
260    var that = this;
261    this.dom.wrapper = document.createElement('div');
262    this.dom.wrapper.className = "ColVis TableTools";
263   
264    this.dom.button = this._fnDomBaseButton( this.s.buttonText );
265    this.dom.button.className += " ColVis_MasterButton";
266    this.dom.wrapper.appendChild( this.dom.button );
267   
268    this.dom.catcher = this._fnDomCatcher();
269    this.dom.collection = this._fnDomCollection();
270    this.dom.background = this._fnDomBackground();
271   
272    this._fnAddButtons();
273   
274    /* Store the original visbility information */
275    for ( var i=0, iLen=this.s.dt.aoColumns.length ; i<iLen ; i++ )
276    {
277      this.s.abOriginal.push( this.s.dt.aoColumns[i].bVisible );
278    }
279   
280    /* Update on each draw */
281    this.s.dt.aoDrawCallback.push( {
282      "fn": function () {
283        that._fnDrawCallback.call( that );
284      },
285      "sName": "ColVis"
286    } );
287  },
288 
289 
290  /**
291   * Apply any customisation to the settings from the DataTables initialisation
292   *  @method  _fnApplyCustomisation
293   *  @returns void
294   *  @private
295   */
296  "_fnApplyCustomisation": function ()
297  {
298    var oConfig = this.s.oInit;
299   
300    if ( typeof oConfig.activate != 'undefined' )
301    {
302      this.s.activate = oConfig.activate;
303    }
304   
305    if ( typeof oConfig.buttonText != 'undefined' )
306    {
307      this.s.buttonText = oConfig.buttonText;
308    }
309   
310    if ( typeof oConfig.aiExclude != 'undefined' )
311    {
312      this.s.aiExclude = oConfig.aiExclude;
313    }
314   
315    if ( typeof oConfig.bRestore != 'undefined' )
316    {
317      this.s.bRestore = oConfig.bRestore;
318    }
319   
320    if ( typeof oConfig.sRestore != 'undefined' )
321    {
322      this.s.sRestore = oConfig.sRestore;
323    }
324   
325    if ( typeof oConfig.sAlign != 'undefined' )
326    {
327      this.s.sAlign = oConfig.sAlign;
328    }
329   
330    if ( typeof oConfig.fnStateChange != 'undefined' )
331    {
332      this.s.fnStateChange = oConfig.fnStateChange;
333    }
334  },
335 
336 
337  /**
338   * On each table draw, check the visiblity checkboxes as needed. This allows any process to
339   * update the table's column visiblity and ColVis will still be accurate.
340   *  @method  _fnDrawCallback
341   *  @returns void
342   *  @private
343   */
344  "_fnDrawCallback": function ()
345  {
346    var aoColumns = this.s.dt.aoColumns;
347   
348    for ( var i=0, iLen=aoColumns.length ; i<iLen ; i++ )
349    {
350      if ( this.dom.buttons[i] !== null )
351      {
352        if ( aoColumns[i].bVisible )
353        {
354          $('input', this.dom.buttons[i]).attr('checked','checked');
355        }
356        else
357        {
358          $('input', this.dom.buttons[i]).removeAttr('checked');
359        }
360      }
361    }
362  },
363 
364 
365  /**
366   * Loop through the columns in the table and as a new button for each one.
367   *  @method  _fnAddButtons
368   *  @returns void
369   *  @private
370   */
371  "_fnAddButtons": function ()
372  {
373    var
374      nButton,
375      sExclude = ","+this.s.aiExclude.join(',')+",";
376   
377    for ( var i=0, iLen=this.s.dt.aoColumns.length ; i<iLen ; i++ )
378    {
379      if ( sExclude.indexOf( ","+i+"," ) == -1 )
380      {
381        nButton = this._fnDomColumnButton( i );
382        this.dom.buttons.push( nButton );
383        this.dom.collection.appendChild( nButton );
384      }
385      else
386      {
387        this.dom.buttons.push( null );
388      }
389    }
390   
391    if ( this.s.bRestore )
392    {
393      nButton = this._fnDomRestoreButton();
394      nButton.className += " ColVis_Restore";
395      this.dom.buttons.push( nButton );
396      this.dom.collection.appendChild( nButton );
397    }
398  },
399 
400 
401  /**
402   * Create a button which allows a "restore" action
403   *  @method  _fnDomRestoreButton
404   *  @returns {Node} Created button
405   *  @private
406   */
407  "_fnDomRestoreButton": function ()
408  {
409    var
410      that = this,
411      nButton = document.createElement('button'),
412      nSpan = document.createElement('span');
413   
414    nButton.className = !this.s.dt.bJUI ? "ColVis_Button TableTools_Button" :
415      "ColVis_Button TableTools_Button ui-button ui-state-default";
416    nButton.appendChild( nSpan );
417    $(nSpan).html( '<span class="ColVis_title">'+this.s.sRestore+'</span>' );
418   
419    $(nButton).click( function (e) {
420      for ( var i=0, iLen=that.s.abOriginal.length ; i<iLen ; i++ )
421      {
422        that.s.dt.oInstance.fnSetColumnVis( i, that.s.abOriginal[i], false );
423      }
424      that.s.dt.oInstance.fnDraw( false );
425    } );
426   
427    return nButton;
428  },
429 
430 
431  /**
432   * Create the DOM for a show / hide button
433   *  @method  _fnDomColumnButton
434   *  @param {int} i Column in question
435   *  @returns {Node} Created button
436   *  @private
437   */
438  "_fnDomColumnButton": function ( i )
439  {
440    var
441      that = this,
442      oColumn = this.s.dt.aoColumns[i],
443      nButton = document.createElement('button'),
444      nSpan = document.createElement('span');
445   
446    nButton.className = !this.s.dt.bJUI ? "ColVis_Button TableTools_Button" :
447      "ColVis_Button TableTools_Button ui-button ui-state-default";
448    nButton.appendChild( nSpan );
449    $(nSpan).html(
450      '<span class="ColVis_radio"><input type="checkbox"></span>'+
451      '<span class="ColVis_title">'+oColumn.sTitle+'</span>' );
452   
453    $(nButton).click( function (e) {
454      var showHide = $('input',this).attr('checked')===true ? false : true;
455      if ( e.target.nodeName.toLowerCase() == "input" )
456      {
457        showHide = $('input',this).attr('checked');
458      }
459     
460      /* Need to consider the case where the initialiser created more than one table - change the
461       * API index that DataTables is using
462       */
463      var oldIndex = $.fn.dataTableExt.iApiIndex;
464      $.fn.dataTableExt.iApiIndex = that._fnDataTablesApiIndex.call(that);
465      that.s.dt.oInstance.fnSetColumnVis( i, showHide );
466      $.fn.dataTableExt.iApiIndex = oldIndex; /* Restore */
467     
468      if ( that.s.fnStateChange !== null )
469      {
470        that.s.fnStateChange.call( that, i, showHide );
471      }
472    } );
473   
474    return nButton;
475  },
476 
477 
478  /**
479   * Get the position in the DataTables instance array of the table for this instance of ColVis
480   *  @method  _fnDataTablesApiIndex
481   *  @returns {int} Index
482   *  @private
483   */
484  "_fnDataTablesApiIndex": function ()
485  {
486    for ( var i=0, iLen=this.s.dt.oInstance.length ; i<iLen ; i++ )
487    {
488      if ( this.s.dt.oInstance[i] == this.s.dt.nTable )
489      {
490        return i;
491      }
492    }
493    return 0;
494  },
495 
496 
497  /**
498   * Create the DOM needed for the button and apply some base properties. All buttons start here
499   *  @method  _fnDomBaseButton
500   *  @param   {String} text Button text
501   *  @returns {Node} DIV element for the button
502   *  @private
503   */
504  "_fnDomBaseButton": function ( text )
505  {
506    var
507      that = this,
508      nButton = document.createElement('button'),
509      nSpan = document.createElement('span'),
510      sEvent = this.s.activate=="mouseover" ? "mouseover" : "click";
511   
512    nButton.className = !this.s.dt.bJUI ? "ColVis_Button TableTools_Button" :
513      "ColVis_Button TableTools_Button ui-button ui-state-default";
514    nButton.appendChild( nSpan );
515    nSpan.innerHTML = text;
516   
517    $(nButton).bind( sEvent, function (e) {
518      that._fnCollectionShow();
519      e.preventDefault();
520    } );
521   
522    return nButton;
523  },
524 
525 
526  /**
527   * Create the element used to contain list the columns (it is shown and hidden as needed)
528   *  @method  _fnDomCollection
529   *  @returns {Node} div container for the collection
530   *  @private
531   */
532  "_fnDomCollection": function ()
533  {
534    var that = this;
535    var nHidden = document.createElement('div');
536    nHidden.style.display = "none";
537    nHidden.className = !this.s.dt.bJUI ? "ColVis_collection TableTools_collection" :
538      "ColVis_collection TableTools_collection ui-buttonset ui-buttonset-multi";
539    nHidden.style.position = "absolute";
540    $(nHidden).css('opacity', 0);
541   
542    return nHidden;
543  },
544 
545 
546  /**
547   * An element to be placed on top of the activate button to catch events
548   *  @method  _fnDomCatcher
549   *  @returns {Node} div container for the collection
550   *  @private
551   */
552  "_fnDomCatcher": function ()
553  {
554    var
555      that = this,
556      nCatcher = document.createElement('div');
557    nCatcher.className = "ColVis_catcher TableTools_catcher";
558   
559    $(nCatcher).click( function () {
560      that._fnCollectionHide.call( that, null, null );
561    } );
562   
563    return nCatcher;
564  },
565 
566 
567  /**
568   * Create the element used to shade the background, and capture hide events (it is shown and
569   * hidden as needed)
570   *  @method  _fnDomBackground
571   *  @returns {Node} div container for the background
572   *  @private
573   */
574  "_fnDomBackground": function ()
575  {
576    var that = this;
577   
578    var nBackground = document.createElement('div');
579    nBackground.style.position = "absolute";
580    nBackground.style.left = "0px";
581    nBackground.style.top = "0px";
582    nBackground.className = "ColVis_collectionBackground TableTools_collectionBackground";
583    $(nBackground).css('opacity', 0);
584   
585    $(nBackground).click( function () {
586      that._fnCollectionHide.call( that, null, null );
587    } );
588   
589    /* When considering a mouse over action for the activation, we also consider a mouse out
590     * which is the same as a mouse over the background - without all the messing around of
591     * bubbling events. Use the catcher element to avoid messing around with bubbling
592     */
593    if ( this.s.activate == "mouseover" )
594    {
595      $(nBackground).mouseover( function () {
596        that.s.overcollection = false;
597        that._fnCollectionHide.call( that, null, null );
598      } );
599    }
600   
601    return nBackground;
602  },
603 
604 
605  /**
606   * Show the show / hide list and the background
607   *  @method  _fnCollectionShow
608   *  @returns void
609   *  @private
610   */
611  "_fnCollectionShow": function ()
612  {
613    var that = this;
614    var oPos = $(this.dom.button).offset();
615    var nHidden = this.dom.collection;
616    var nBackground = this.dom.background;
617    var iDivX = parseInt(oPos.left, 10);
618    var iDivY = parseInt(oPos.top + $(this.dom.button).outerHeight(), 10);
619   
620    nHidden.style.top = iDivY+"px";
621    nHidden.style.left = iDivX+"px";
622    nHidden.style.display = "block";
623    $(nHidden).css('opacity',0);
624   
625    var iWinHeight = $(window).height(), iDocHeight = $(document).height(),
626      iWinWidth = $(window).width(), iDocWidth = $(document).width();
627   
628    nBackground.style.height = ((iWinHeight>iDocHeight)? iWinHeight : iDocHeight) +"px";
629    nBackground.style.width = ((iWinWidth<iDocWidth)? iWinWidth : iDocWidth) +"px";
630   
631    var oStyle = this.dom.catcher.style;
632    oStyle.height = $(this.dom.button).outerHeight()+"px";
633    oStyle.width = $(this.dom.button).outerWidth()+"px";
634    oStyle.top = oPos.top+"px";
635    oStyle.left = iDivX+"px";
636   
637    document.body.appendChild( nBackground );
638    document.body.appendChild( nHidden );
639    document.body.appendChild( this.dom.catcher );
640   
641    /* Visual corrections to try and keep the collection visible */
642    nHidden.style.left = this.s.sAlign=="left" ?
643      iDivX+"px" : (iDivX-$(nHidden).outerWidth()+$(this.dom.button).outerWidth())+"px";
644   
645    var iDivWidth = $(nHidden).outerWidth();
646    var iDivHeight = $(nHidden).outerHeight();
647   
648    if ( iDivX + iDivWidth > iDocWidth )
649    {
650      nHidden.style.left = (iDocWidth-iDivWidth)+"px";
651    }
652   
653    if ( iDivY + iDivHeight > iDocHeight )
654    {
655      nHidden.style.top = (iDivY-iDivHeight-$(this.dom.button).outerHeight())+"px";
656    }
657   
658   
659    /* This results in a very small delay for the end user but it allows the animation to be
660     * much smoother. If you don't want the animation, then the setTimeout can be removed
661     */
662    setTimeout( function () {
663      $(nHidden).animate({"opacity": 1}, 500);
664      $(nBackground).animate({"opacity": 0.1}, 500, 'linear', function () {
665        /* In IE6 if you set the checked attribute of a hidden checkbox, then this is not visually
666         * reflected. As such, we need to do it here, once it is visible. Unbelievable.
667         */
668        if ( jQuery.browser.msie && jQuery.browser.version == "6.0" )
669        {
670          that._fnDrawCallback();
671        }
672      });
673    }, 10 );
674   
675    this.s.hidden = false;
676  },
677 
678 
679  /**
680   * Hide the show / hide list and the background
681   *  @method  _fnCollectionHide
682   *  @returns void
683   *  @private
684   */
685  "_fnCollectionHide": function (  )
686  {
687    var that = this;
688   
689    if ( !this.s.hidden && this.dom.collection !== null )
690    {
691      this.s.hidden = true;
692     
693      $(this.dom.collection).animate({"opacity": 0}, 500, function (e) {
694        this.style.display = "none";
695      } );
696     
697      $(this.dom.background).animate({"opacity": 0}, 500, function (e) {
698        document.body.removeChild( that.dom.background );
699        document.body.removeChild( that.dom.catcher );
700      } );
701    }
702  }
703};
704
705
706
707
708
709/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
710 * Static object methods
711 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
712
713/**
714 * Rebuild the collection for a given table, or all tables if no parameter given
715 *  @method  ColVis.fnRebuild
716 *  @static
717 *  @param   object oTable DataTable instance to consider - optional
718 *  @returns void
719 */
720ColVis.fnRebuild = function ( oTable )
721{
722  var nTable = null;
723  if ( typeof oTable != 'undefined' )
724  {
725    nTable = oTable.fnSettings().nTable;
726  }
727 
728  for ( var i=0, iLen=ColVis.aInstances.length ; i<iLen ; i++ )
729  {
730    if ( typeof oTable == 'undefined' || nTable == ColVis.aInstances[i].s.dt.nTable )
731    {
732      ColVis.aInstances[i].fnRebuild();
733    }
734  }
735};
736
737
738
739
740
741/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
742 * Static object propterties
743 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
744
745/**
746 * Collection of all ColVis instances
747 *  @property ColVis.aInstances
748 *  @static
749 *  @type     Array
750 *  @default  []
751 */
752ColVis.aInstances = [];
753
754
755
756
757
758/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
759 * Constants
760 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
761
762/**
763 * Name of this class
764 *  @constant CLASS
765 *  @type     String
766 *  @default  ColVis
767 */
768ColVis.prototype.CLASS = "ColVis";
769
770
771/**
772 * ColVis version
773 *  @constant  VERSION
774 *  @type      String
775 *  @default   1.0.4.dev
776 */
777ColVis.VERSION = "1.0.4";
778ColVis.prototype.VERSION = ColVis.VERSION;
779
780
781
782
783
784/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
785 * Initialisation
786 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
787
788/*
789 * Register a new feature with DataTables
790 */
791if ( typeof $.fn.dataTable == "function" &&
792     typeof $.fn.dataTableExt.fnVersionCheck == "function" &&
793     $.fn.dataTableExt.fnVersionCheck('1.7.0') )
794{
795  $.fn.dataTableExt.aoFeatures.push( {
796    "fnInit": function( oDTSettings ) {
797      var init = (typeof oDTSettings.oInit.oColVis == 'undefined') ?
798        {} : oDTSettings.oInit.oColVis;
799      var oColvis = new ColVis( oDTSettings, init );
800      return oColvis.dom.wrapper;
801    },
802    "cFeature": "C",
803    "sFeature": "ColVis"
804  } );
805}
806else
807{
808  alert( "Warning: ColVis requires DataTables 1.7 or greater - www.datatables.net/download");
809}
810
811})(jQuery);
Note: See TracBrowser for help on using the repository browser.