Free cookie consent management tool by TermsFeed Policy Generator

source: branches/WebApplication/MVC2/HeuristicLabWeb.PluginHost/HLWebPluginHost/Content/jQuery/jQueryPlugins/DataTables-1.7.6/extras/FixedHeader/js/FixedHeader.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: 25.8 KB
Line 
1/*
2 * File:        FixedHeader.js
3 * Version:     2.0.4
4 * Description: "Fix" a header at the top of the table, so it scrolls with the table
5 * Author:      Allan Jardine (www.sprymedia.co.uk)
6 * Created:     Wed 16 Sep 2009 19:46:30 BST
7 * Language:    Javascript
8 * License:     LGPL
9 * Project:     Just a little bit of fun - enjoy :-)
10 * Contact:     www.sprymedia.co.uk/contact
11 *
12 * Copyright 2009-2010 Allan Jardine, all rights reserved.
13 */
14
15/*
16 * Function: FixedHeader
17 * Purpose:  Provide 'fixed' header, footer and columns on an HTML table
18 * Returns:  object:FixedHeader - must be called with 'new'
19 * Inputs:   mixed:mTable - target table
20 *             1. DataTable object - when using FixedHeader with DataTables, or
21 *             2. HTML table node - when using FixedHeader without DataTables
22 *           object:oInit - initialisation settings, with the following properties (each optional)
23 *             bool:top -    fix the header (default true)
24 *             bool:bottom - fix the footer (default false)
25 *             bool:left -   fix the left most column (default false)
26 *             bool:right -  fix the right most column (default false)
27 *             int:zTop -    fixed header zIndex
28 *             int:zBottom - fixed footer zIndex
29 *             int:zLeft -   fixed left zIndex
30 *             int:zRight -  fixed right zIndex
31 */
32var FixedHeader = function ( mTable, oInit ) {
33  /* Sanity check - you just know it will happen */
34  if ( typeof this.fnInit != 'function' )
35  {
36    alert( "FixedHeader warning: FixedHeader must be initialised with the 'new' keyword." );
37    return;
38  }
39 
40  var that = this;
41  var oSettings = {
42    "aoCache": [],
43    "oSides": {
44      "top": true,
45      "bottom": false,
46      "left": false,
47      "right": false
48    },
49    "oZIndexes": {
50      "top": 104,
51      "bottom": 103,
52      "left": 102,
53      "right": 101
54    },
55    "oMes": {
56      "iTableWidth": 0,
57      "iTableHeight": 0,
58      "iTableLeft": 0,
59      "iTableRight": 0, /* note this is left+width, not actually "right" */
60      "iTableTop": 0,
61      "iTableBottom": 0 /* note this is top+height, not actually "bottom" */
62    },
63    "nTable": null,
64    "bUseAbsPos": false,
65    "bFooter": false
66  };
67 
68  /*
69   * Function: fnGetSettings
70   * Purpose:  Get the settings for this object
71   * Returns:  object: - settings object
72   * Inputs:   -
73   */
74  this.fnGetSettings = function () {
75    return oSettings;
76  };
77 
78  /*
79   * Function: fnUpdate
80   * Purpose:  Update the positioning and copies of the fixed elements
81   * Returns:  -
82   * Inputs:   -
83   */
84  this.fnUpdate = function () {
85    this._fnUpdateClones();
86    this._fnUpdatePositions();
87  };
88 
89  /* Let's do it */
90  this.fnInit( mTable, oInit );
91};
92
93
94/*
95 * Variable: FixedHeader
96 * Purpose:  Prototype for FixedHeader
97 * Scope:    global
98 */
99FixedHeader.prototype = {
100  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
101   * Initialisation
102   */
103 
104  /*
105   * Function: fnInit
106   * Purpose:  The "constructor"
107   * Returns:  -
108   * Inputs:   {as FixedHeader function}
109   */
110  fnInit: function ( oTable, oInit )
111  {
112    var s = this.fnGetSettings();
113    var that = this;
114   
115    /* Record the user definable settings */
116    this.fnInitSettings( s, oInit );
117   
118    /* DataTables specific stuff */
119    if ( typeof oTable.fnSettings == 'function' )
120    {
121      if ( typeof oTable.fnVersionCheck == 'functon' &&
122           oTable.fnVersionCheck( '1.6.0' ) !== true )
123      {
124        alert( "FixedHeader 2 required DataTables 1.6.0 or later. "+
125          "Please upgrade your DataTables installation" );
126        return;
127      }
128     
129      var oDtSettings = oTable.fnSettings();
130     
131      if ( oDtSettings.oScroll.sX != "" || oDtSettings.oScroll.sY != "" )
132      {
133        alert( "FixedHeader 2 is not supported with DataTables' scrolling mode at this time" );
134        return;
135      }
136     
137      s.nTable = oDtSettings.nTable;
138      oDtSettings.aoDrawCallback.push( {
139        "fn": function () {
140          FixedHeader.fnMeasure();
141          that._fnUpdateClones.call(that);
142          that._fnUpdatePositions.call(that);
143        },
144        "sName": "FixedHeader"
145      } );
146    }
147    else
148    {
149      s.nTable = oTable;
150    }
151   
152    s.bFooter = ($('>tfoot', s.nTable).length > 0) ? true : false;
153   
154    /* "Detect" browsers that don't support absolute positioing - or have bugs */
155    s.bUseAbsPos = (jQuery.browser.msie && (jQuery.browser.version=="6.0"||jQuery.browser.version=="7.0"));
156   
157    /* Add the 'sides' that are fixed */
158    if ( s.oSides.top )
159    {
160      s.aoCache.push( that._fnCloneTable( "fixedHeader", "FixedHeader_Header", that._fnCloneThead ) );
161    }
162    if ( s.oSides.bottom )
163    {
164      s.aoCache.push( that._fnCloneTable( "fixedFooter", "FixedHeader_Footer", that._fnCloneTfoot ) );
165    }
166    if ( s.oSides.left )
167    {
168      s.aoCache.push( that._fnCloneTable( "fixedLeft", "FixedHeader_Left", that._fnCloneTLeft ) );
169    }
170    if ( s.oSides.right )
171    {
172      s.aoCache.push( that._fnCloneTable( "fixedRight", "FixedHeader_Right", that._fnCloneTRight ) );
173    }
174   
175    /* Event listeners for window movement */
176    FixedHeader.afnScroll.push( function () {
177      that._fnUpdatePositions.call(that);
178    } );
179   
180    jQuery(window).resize( function () {
181      FixedHeader.fnMeasure();
182      that._fnUpdateClones.call(that);
183      that._fnUpdatePositions.call(that);
184    } );
185   
186    /* Get things right to start with */
187    FixedHeader.fnMeasure();
188    that._fnUpdateClones();
189    that._fnUpdatePositions();
190  },
191 
192 
193  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
194   * Support functions
195   */
196 
197  /*
198   * Function: fnInitSettings
199   * Purpose:  Take the user's settings and copy them to our local store
200   * Returns:  -
201   * Inputs:   object:s - the local settings object
202   *           object:oInit - the user's settings object
203   */
204  fnInitSettings: function ( s, oInit )
205  {
206    if ( typeof oInit != 'undefined' )
207    {
208      if ( typeof oInit.top != 'undefined' ) {
209        s.oSides.top = oInit.top;
210      }
211      if ( typeof oInit.bottom != 'undefined' ) {
212        s.oSides.bottom = oInit.bottom;
213      }
214      if ( typeof oInit.left != 'undefined' ) {
215        s.oSides.left = oInit.left;
216      }
217      if ( typeof oInit.right != 'undefined' ) {
218        s.oSides.right = oInit.right;
219      }
220     
221      if ( typeof oInit.zTop != 'undefined' ) {
222        s.oZIndexes.top = oInit.zTop;
223      }
224      if ( typeof oInit.zBottom != 'undefined' ) {
225        s.oZIndexes.bottom = oInit.zBottom;
226      }
227      if ( typeof oInit.zLeft != 'undefined' ) {
228        s.oZIndexes.left = oInit.zLeft;
229      }
230      if ( typeof oInit.zRight != 'undefined' ) {
231        s.oZIndexes.right = oInit.zRight;
232      }
233    }
234   
235    /* Detect browsers which have poor position:fixed support so we can use absolute positions.
236     * This is much slower since the position must be updated for each scroll, but widens
237     * compatibility
238     */
239    s.bUseAbsPos = (jQuery.browser.msie &&
240      (jQuery.browser.version=="6.0"||jQuery.browser.version=="7.0"));
241  },
242 
243  /*
244   * Function: _fnCloneTable
245   * Purpose:  Clone the table node and do basic initialisation
246   * Returns:  -
247   * Inputs:   -
248   */
249  _fnCloneTable: function ( sType, sClass, fnClone )
250  {
251    var s = this.fnGetSettings();
252    var nCTable;
253   
254    /* We know that the table _MUST_ has a DIV wrapped around it, because this is simply how
255     * DataTables works. Therefore, we can set this to be relatively position (if it is not
256     * alreadu absolute, and use this as the base point for the cloned header
257     */
258    if ( jQuery(s.nTable.parentNode).css('position') != "absolute" )
259    {
260      s.nTable.parentNode.style.position = "relative";
261    }
262   
263    /* Just a shallow clone will do - we only want the table node */
264    nCTable = s.nTable.cloneNode( false );
265   
266    var nDiv = document.createElement( 'div' );
267    nDiv.style.position = "absolute";
268    nDiv.className += " FixedHeader_Cloned "+sType+" "+sClass;
269   
270    /* Set the zIndexes */
271    if ( sType == "fixedHeader" )
272    {
273      nDiv.style.zIndex = s.oZIndexes.top;
274    }
275    if ( sType == "fixedFooter" )
276    {
277      nDiv.style.zIndex = s.oZIndexes.bottom;
278    }
279    if ( sType == "fixedLeft" )
280    {
281      nDiv.style.zIndex = s.oZIndexes.left;
282    }
283    else if ( sType == "fixedRight" )
284    {
285      nDiv.style.zIndex = s.oZIndexes.right;
286    }
287   
288    /* Insert the newly cloned table into the DOM, on top of the "real" header */
289    nDiv.appendChild( nCTable );
290    document.body.appendChild( nDiv );
291   
292    return {
293      "nNode": nCTable,
294      "nWrapper": nDiv,
295      "sType": sType,
296      "sPosition": "",
297      "sTop": "",
298      "sLeft": "",
299      "fnClone": fnClone
300    };
301  },
302 
303  /*
304   * Function: _fnUpdatePositions
305   * Purpose:  Get the current positioning of the table in the DOM
306   * Returns:  -
307   * Inputs:   -
308   */
309  _fnMeasure: function ()
310  {
311    var
312      s = this.fnGetSettings(),
313      m = s.oMes,
314      jqTable = jQuery(s.nTable),
315      oOffset = jqTable.offset(),
316      iParentScrollTop = this._fnSumScroll( s.nTable.parentNode, 'scrollTop' ),
317      iParentScrollLeft = this._fnSumScroll( s.nTable.parentNode, 'scrollLeft' );
318   
319    m.iTableWidth = jqTable.outerWidth();
320    m.iTableHeight = jqTable.outerHeight();
321    m.iTableLeft = oOffset.left + s.nTable.parentNode.scrollLeft;
322    m.iTableTop = oOffset.top + iParentScrollTop;
323    m.iTableRight = m.iTableLeft + m.iTableWidth;
324    m.iTableRight = FixedHeader.oDoc.iWidth - m.iTableLeft - m.iTableWidth;
325    m.iTableBottom = FixedHeader.oDoc.iHeight - m.iTableTop - m.iTableHeight;
326  },
327 
328  /*
329   * Function: _fnSumScroll
330   * Purpose:  Sum node parameters all the way to the top
331   * Returns:  int: sum
332   * Inputs:   node:n - node to consider
333   *           string:side - scrollTop or scrollLeft
334   */
335  _fnSumScroll: function ( n, side )
336  {
337    var i = n[side];
338    while ( n = n.parentNode )
339    {
340      if ( n.nodeName != 'HTML' && n.nodeName != 'BODY' )
341      {
342        break;
343      }
344      i = n[side];
345    }
346    return i;
347  },
348 
349  /*
350   * Function: _fnUpdatePositions
351   * Purpose:  Loop over the fixed elements for this table and update their positions
352   * Returns:  -
353   * Inputs:   -
354   */
355  _fnUpdatePositions: function ()
356  {
357    var s = this.fnGetSettings();
358    this._fnMeasure();
359   
360    for ( var i=0, iLen=s.aoCache.length ; i<iLen ; i++ )
361    {
362      if ( s.aoCache[i].sType == "fixedHeader" )
363      {
364        this._fnScrollFixedHeader( s.aoCache[i] );
365      }
366      else if ( s.aoCache[i].sType == "fixedFooter" )
367      {
368        this._fnScrollFixedFooter( s.aoCache[i] );
369      }
370      else if ( s.aoCache[i].sType == "fixedLeft" )
371      {
372        this._fnScrollHorizontalLeft( s.aoCache[i] );
373      }
374      else
375      {
376        this._fnScrollHorizontalRight( s.aoCache[i] );
377      }
378    }
379  },
380 
381  /*
382   * Function: _fnUpdateClones
383   * Purpose:  Loop over the fixed elements for this table and call their cloning functions
384   * Returns:  -
385   * Inputs:   -
386   */
387  _fnUpdateClones: function ()
388  {
389    var s = this.fnGetSettings();
390    for ( var i=0, iLen=s.aoCache.length ; i<iLen ; i++ )
391    {
392      s.aoCache[i].fnClone.call( this, s.aoCache[i] );
393    }
394  },
395 
396 
397  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
398   * Scrolling functions
399   */
400 
401  /*
402   * Function: _fnScrollHorizontalLeft
403   * Purpose:  Update the positioning of the scrolling elements
404   * Returns:  -
405   * Inputs:   object:oCache - the cahced values for this fixed element
406   */
407  _fnScrollHorizontalRight: function ( oCache )
408  {
409    var
410      s = this.fnGetSettings(),
411      oMes = s.oMes,
412      oWin = FixedHeader.oWin,
413      oDoc = FixedHeader.oDoc,
414      nTable = oCache.nWrapper,
415      iFixedWidth = jQuery(nTable).outerWidth();
416   
417    if ( oWin.iScrollRight < oMes.iTableRight )
418    {
419      /* Fully right aligned */
420      this._fnUpdateCache( oCache, 'sPosition', 'absolute', 'position', nTable.style );
421      this._fnUpdateCache( oCache, 'sTop', oMes.iTableTop+"px", 'top', nTable.style );
422      this._fnUpdateCache( oCache, 'sLeft', (oMes.iTableLeft+oMes.iTableWidth-iFixedWidth)+"px", 'left', nTable.style ); 
423    }
424    else if ( oMes.iTableLeft < oDoc.iWidth-oWin.iScrollRight-iFixedWidth )
425    {
426      /* Middle */
427      if ( s.bUseAbsPos )
428      {
429        this._fnUpdateCache( oCache, 'sPosition', 'absolute', 'position', nTable.style );
430        this._fnUpdateCache( oCache, 'sTop', oMes.iTableTop+"px", 'top', nTable.style );
431        this._fnUpdateCache( oCache, 'sLeft', (oDoc.iWidth-oWin.iScrollRight-iFixedWidth)+"px", 'left', nTable.style );
432      }
433      else
434      {
435        this._fnUpdateCache( oCache, 'sPosition', 'fixed', 'position', nTable.style );
436        this._fnUpdateCache( oCache, 'sTop', (oMes.iTableTop-oWin.iScrollTop)+"px", 'top', nTable.style );
437        this._fnUpdateCache( oCache, 'sLeft', (oWin.iWidth-iFixedWidth)+"px", 'left', nTable.style );
438      }
439    }
440    else
441    {
442      /* Fully left aligned */
443      this._fnUpdateCache( oCache, 'sPosition', 'absolute', 'position', nTable.style );
444      this._fnUpdateCache( oCache, 'sTop', oMes.iTableTop+"px", 'top', nTable.style );
445      this._fnUpdateCache( oCache, 'sLeft', oMes.iTableLeft+"px", 'left', nTable.style );
446    }
447  },
448 
449  /*
450   * Function: _fnScrollHorizontalLeft
451   * Purpose:  Update the positioning of the scrolling elements
452   * Returns:  -
453   * Inputs:   object:oCache - the cahced values for this fixed element
454   */
455  _fnScrollHorizontalLeft: function ( oCache )
456  {
457    var
458      s = this.fnGetSettings(),
459      oMes = s.oMes,
460      oWin = FixedHeader.oWin,
461      oDoc = FixedHeader.oDoc,
462      nTable = oCache.nWrapper,
463      iCellWidth = jQuery(nTable).outerWidth();
464   
465    if ( oWin.iScrollLeft < oMes.iTableLeft )
466    {
467      /* Fully left align */
468      this._fnUpdateCache( oCache, 'sPosition', 'absolute', 'position', nTable.style );
469      this._fnUpdateCache( oCache, 'sTop', oMes.iTableTop+"px", 'top', nTable.style );
470      this._fnUpdateCache( oCache, 'sLeft', oMes.iTableLeft+"px", 'left', nTable.style );
471    }
472    else if ( oWin.iScrollLeft < oMes.iTableLeft+oMes.iTableWidth-iCellWidth )
473    {
474      /* Middle */
475      if ( s.bUseAbsPos )
476      {
477        this._fnUpdateCache( oCache, 'sPosition', 'absolute', 'position', nTable.style );
478        this._fnUpdateCache( oCache, 'sTop', oMes.iTableTop+"px", 'top', nTable.style );
479        this._fnUpdateCache( oCache, 'sLeft', oWin.iScrollLeft+"px", 'left', nTable.style );
480      }
481      else
482      {
483        this._fnUpdateCache( oCache, 'sPosition', 'fixed', 'position', nTable.style );
484        this._fnUpdateCache( oCache, 'sTop', (oMes.iTableTop-oWin.iScrollTop)+"px", 'top', nTable.style );
485        this._fnUpdateCache( oCache, 'sLeft', "0px", 'left', nTable.style );
486      }
487    }
488    else
489    {
490      /* Fully right align */
491      this._fnUpdateCache( oCache, 'sPosition', 'absolute', 'position', nTable.style );
492      this._fnUpdateCache( oCache, 'sTop', oMes.iTableTop+"px", 'top', nTable.style );
493      this._fnUpdateCache( oCache, 'sLeft', (oMes.iTableLeft+oMes.iTableWidth-iCellWidth)+"px", 'left', nTable.style );
494    }
495  },
496 
497  /*
498   * Function: _fnScrollFixedFooter
499   * Purpose:  Update the positioning of the scrolling elements
500   * Returns:  -
501   * Inputs:   object:oCache - the cahced values for this fixed element
502   */
503  _fnScrollFixedFooter: function ( oCache )
504  {
505    var
506      s = this.fnGetSettings(),
507      oMes = s.oMes,
508      oWin = FixedHeader.oWin,
509      oDoc = FixedHeader.oDoc,
510      nTable = oCache.nWrapper,
511      iTheadHeight = jQuery("thead", s.nTable).outerHeight(),
512      iCellHeight = jQuery(nTable).outerHeight();
513   
514    if ( oWin.iScrollBottom < oMes.iTableBottom )
515    {
516      /* Below */
517      this._fnUpdateCache( oCache, 'sPosition', 'absolute', 'position', nTable.style );
518      this._fnUpdateCache( oCache, 'sTop', (oMes.iTableTop+oMes.iTableHeight-iCellHeight)+"px", 'top', nTable.style );
519      this._fnUpdateCache( oCache, 'sLeft', oMes.iTableLeft+"px", 'left', nTable.style );
520    }
521    else if ( oWin.iScrollBottom < oMes.iTableBottom+oMes.iTableHeight-iCellHeight-iTheadHeight )
522    {
523      /* Middle */
524      if ( s.bUseAbsPos )
525      {
526        this._fnUpdateCache( oCache, 'sPosition', "absolute", 'position', nTable.style );
527        this._fnUpdateCache( oCache, 'sTop', (oDoc.iHeight-oWin.iScrollBottom-iCellHeight)+"px", 'top', nTable.style );
528        this._fnUpdateCache( oCache, 'sLeft', oMes.iTableLeft+"px", 'left', nTable.style );
529      }
530      else
531      {
532        this._fnUpdateCache( oCache, 'sPosition', 'fixed', 'position', nTable.style );
533        this._fnUpdateCache( oCache, 'sTop', (oWin.iHeight-iCellHeight)+"px", 'top', nTable.style );
534        this._fnUpdateCache( oCache, 'sLeft', (oMes.iTableLeft-oWin.iScrollLeft)+"px", 'left', nTable.style ); 
535      }
536    }
537    else
538    {
539      /* Above */
540      this._fnUpdateCache( oCache, 'sPosition', 'absolute', 'position', nTable.style );
541      this._fnUpdateCache( oCache, 'sTop', (oMes.iTableTop+iCellHeight)+"px", 'top', nTable.style );
542      this._fnUpdateCache( oCache, 'sLeft', oMes.iTableLeft+"px", 'left', nTable.style );
543    }
544  },
545 
546  /*
547   * Function: _fnScrollFixedHeader
548   * Purpose:  Update the positioning of the scrolling elements
549   * Returns:  -
550   * Inputs:   object:oCache - the cahced values for this fixed element
551   */
552  _fnScrollFixedHeader: function ( oCache )
553  {
554    var
555      s = this.fnGetSettings(),
556      oMes = s.oMes,
557      oWin = FixedHeader.oWin,
558      oDoc = FixedHeader.oDoc,
559      nTable = oCache.nWrapper,
560      iTbodyHeight = s.nTable.getElementsByTagName('tbody')[0].offsetHeight;
561   
562    if ( oMes.iTableTop > oWin.iScrollTop )
563    {
564      /* Above the table */
565      this._fnUpdateCache( oCache, 'sPosition', "absolute", 'position', nTable.style );
566      this._fnUpdateCache( oCache, 'sTop', oMes.iTableTop+"px", 'top', nTable.style );
567      this._fnUpdateCache( oCache, 'sLeft', oMes.iTableLeft+"px", 'left', nTable.style );
568    }
569    else if ( oWin.iScrollTop > oMes.iTableTop+iTbodyHeight )
570    {
571      /* At the bottom of the table */
572      this._fnUpdateCache( oCache, 'sPosition', "absolute", 'position', nTable.style );
573      this._fnUpdateCache( oCache, 'sTop', (oMes.iTableTop+iTbodyHeight)+"px", 'top', nTable.style );
574      this._fnUpdateCache( oCache, 'sLeft', oMes.iTableLeft+"px", 'left', nTable.style );
575    }
576    else
577    {
578      /* In the middle of the table */
579      if ( s.bUseAbsPos )
580      {
581        this._fnUpdateCache( oCache, 'sPosition', "absolute", 'position', nTable.style );
582        this._fnUpdateCache( oCache, 'sTop', oWin.iScrollTop+"px", 'top', nTable.style );
583        this._fnUpdateCache( oCache, 'sLeft', oMes.iTableLeft+"px", 'left', nTable.style );
584      }
585      else
586      {
587        this._fnUpdateCache( oCache, 'sPosition', 'fixed', 'position', nTable.style );
588        this._fnUpdateCache( oCache, 'sTop', "0px", 'top', nTable.style );
589        this._fnUpdateCache( oCache, 'sLeft', (oMes.iTableLeft-oWin.iScrollLeft)+"px", 'left', nTable.style );
590      }
591    }
592  },
593 
594  /*
595   * Function: _fnUpdateCache
596   * Purpose:  Check the cache and update cache and value if needed
597   * Returns:  -
598   * Inputs:   object:oCache - local cache object
599   *           string:sCache - cache property
600   *           string:sSet - value to set
601   *           string:sProperty - object property to set
602   *           object:oObj - object to update
603   */
604  _fnUpdateCache: function ( oCache, sCache, sSet, sProperty, oObj )
605  {
606    if ( oCache[sCache] != sSet )
607    {
608      oObj[sProperty] = sSet;
609      oCache[sCache] = sSet;
610    }
611  },
612 
613 
614 
615  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
616   * Cloning functions
617   */
618 
619  /*
620   * Function: _fnCloneThead
621   * Purpose:  Clone the thead element
622   * Returns:  -
623   * Inputs:   object:oCache - the cahced values for this fixed element
624   */
625  _fnCloneThead: function ( oCache )
626  {
627    var s = this.fnGetSettings();
628    var nTable = oCache.nNode;
629   
630    /* Set the wrapper width to match that of the cloned table */
631    oCache.nWrapper.style.width = jQuery(s.nTable).outerWidth()+"px";
632   
633    /* Remove any children the cloned table has */
634    while ( nTable.childNodes.length > 0 )
635    {
636      jQuery('thead th', nTable).unbind( 'click' );
637      nTable.removeChild( nTable.childNodes[0] );
638    }
639   
640    /* Clone the DataTables header */
641    var nThead = jQuery('thead', s.nTable).clone(true)[0];
642    nTable.appendChild( nThead );
643   
644    /* Copy the widths across - apparently a clone isn't good enough for this */
645    jQuery("thead:eq(0)>tr th", s.nTable).each( function (i) {
646      jQuery("thead:eq(0)>tr th:eq("+i+")", nTable).width( jQuery(this).width() );
647    } );
648   
649    jQuery("thead:eq(0)>tr td", s.nTable).each( function (i) {
650      jQuery("thead:eq(0)>tr th:eq("+i+")", nTable)[0].style.width( jQuery(this).width() );
651    } );
652  },
653 
654  /*
655   * Function: _fnCloneTfoot
656   * Purpose:  Clone the tfoot element
657   * Returns:  -
658   * Inputs:   object:oCache - the cahced values for this fixed element
659   */
660  _fnCloneTfoot: function ( oCache )
661  {
662    var s = this.fnGetSettings();
663    var nTable = oCache.nNode;
664   
665    /* Set the wrapper width to match that of the cloned table */
666    oCache.nWrapper.style.width = jQuery(s.nTable).outerWidth()+"px";
667   
668    /* Remove any children the cloned table has */
669    while ( nTable.childNodes.length > 0 )
670    {
671      nTable.removeChild( nTable.childNodes[0] );
672    }
673   
674    /* Clone the DataTables footer */
675    var nTfoot = jQuery('tfoot', s.nTable).clone(true)[0];
676    nTable.appendChild( nTfoot );
677   
678    /* Copy the widths across - apparently a clone isn't good enough for this */
679    jQuery("tfoot:eq(0)>tr th", s.nTable).each( function (i) {
680      jQuery("tfoot:eq(0)>tr th:eq("+i+")", nTable).width( jQuery(this).width() );
681    } );
682   
683    jQuery("tfoot:eq(0)>tr td", s.nTable).each( function (i) {
684      jQuery("tfoot:eq(0)>tr th:eq("+i+")", nTable)[0].style.width( jQuery(this).width() );
685    } );
686  },
687 
688  /*
689   * Function: _fnCloneTLeft
690   * Purpose:  Clone the left column
691   * Returns:  -
692   * Inputs:   object:oCache - the cahced values for this fixed element
693   */
694  _fnCloneTLeft: function ( oCache )
695  {
696    var s = this.fnGetSettings();
697    var nTable = oCache.nNode;
698    var iCols = jQuery('tbody tr:eq(0) td', s.nTable).length;
699    var bRubbishOldIE = ($.browser.msie && ($.browser.version == "6.0" || $.browser.version == "7.0"));
700   
701    /* Remove any children the cloned table has */
702    while ( nTable.childNodes.length > 0 )
703    {
704      nTable.removeChild( nTable.childNodes[0] );
705    }
706   
707    /* Is this the most efficient way to do this - it looks horrible... */
708    nTable.appendChild( jQuery("thead", s.nTable).clone(true)[0] );
709    nTable.appendChild( jQuery("tbody", s.nTable).clone(true)[0] );
710    if ( s.bFooter )
711    {
712      nTable.appendChild( jQuery("tfoot", s.nTable).clone(true)[0] );
713    }
714   
715    jQuery('thead tr th:gt(0)', nTable).remove();
716    jQuery('tfoot tr th:gt(0)', nTable).remove();
717   
718    /* Basically the same as used in FixedColumns - remove and copy heights */
719    $('tbody tr', nTable).each( function (k) {
720      $('td:gt(0)', this).remove();
721     
722      /* Can we use some kind of object detection here?! This is very nasty - damn browsers */
723      if ( $.browser.mozilla || $.browser.opera )
724      {
725        $('td', this).height( $('tbody tr:eq('+k+')', that.dom.body).outerHeight() );
726      }
727      else
728      {
729        $('td', this).height( $('tbody tr:eq('+k+')', that.dom.body).outerHeight() - iBoxHack );
730      }
731     
732      if ( !bRubbishOldIE )
733      {
734        $('tbody tr:eq('+k+')', that.dom.body).height( $('tbody tr:eq('+k+')', that.dom.body).outerHeight() );   
735      }
736    } );
737   
738    var iWidth = jQuery('thead tr th:eq(0)', s.nTable).outerWidth();
739    nTable.style.width = iWidth+"px";
740    oCache.nWrapper.style.width = iWidth+"px";
741  },
742 
743  /*
744   * Function: _fnCloneTRight
745   * Purpose:  Clone the right most colun
746   * Returns:  -
747   * Inputs:   object:oCache - the cahced values for this fixed element
748   */
749  _fnCloneTRight: function ( oCache )
750  {
751    var s = this.fnGetSettings();
752    var nTable = oCache.nNode;
753    var iCols = jQuery('tbody tr:eq(0) td', s.nTable).length;
754    var bRubbishOldIE = ($.browser.msie && ($.browser.version == "6.0" || $.browser.version == "7.0"));
755   
756    /* Remove any children the cloned table has */
757    while ( nTable.childNodes.length > 0 )
758    {
759      nTable.removeChild( nTable.childNodes[0] );
760    }
761   
762    /* Is this the most efficient way to do this - it looks horrible... */
763    nTable.appendChild( jQuery("thead", s.nTable).clone(true)[0] );
764    nTable.appendChild( jQuery("tbody", s.nTable).clone(true)[0] );
765    if ( s.bFooter )
766    {
767      nTable.appendChild( jQuery("tfoot", s.nTable).clone(true)[0] );
768    }
769    jQuery('thead tr th:not(:nth-child('+iCols+'n))', nTable).remove();
770    jQuery('tfoot tr th:not(:nth-child('+iCols+'n))', nTable).remove();
771   
772    /* Basically the same as used in FixedColumns - remove and copy heights */
773    $('tbody tr', nTable).each( function (k) {
774      $('td:lt('+iCols-1+')', this).remove();
775     
776      /* Can we use some kind of object detection here?! This is very nasty - damn browsers */
777      if ( $.browser.mozilla || $.browser.opera )
778      {
779        $('td', this).height( $('tbody tr:eq('+k+')', that.dom.body).outerHeight() );
780      }
781      else
782      {
783        $('td', this).height( $('tbody tr:eq('+k+')', that.dom.body).outerHeight() - iBoxHack );
784      }
785     
786      if ( !bRubbishOldIE )
787      {
788        $('tbody tr:eq('+k+')', that.dom.body).height( $('tbody tr:eq('+k+')', that.dom.body).outerHeight() );   
789      }
790    } );
791   
792    var iWidth = jQuery('thead tr th:eq('+(iCols-1)+')', s.nTable).outerWidth();
793    nTable.style.width = iWidth+"px";
794    oCache.nWrapper.style.width = iWidth+"px";
795  }
796};
797
798 
799/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
800 * Static properties and methods
801 *   We use these for speed! This information is common to all instances of FixedHeader, so no
802 * point if having them calculated and stored for each different instance.
803 */
804
805/*
806 * Variable: oWin
807 * Purpose:  Store information about the window positioning
808 * Scope:    FixedHeader
809 */
810FixedHeader.oWin = {
811  "iScrollTop": 0,
812  "iScrollRight": 0,
813  "iScrollBottom": 0,
814  "iScrollLeft": 0,
815  "iHeight": 0,
816  "iWidth": 0
817};
818
819/*
820 * Variable: oDoc
821 * Purpose:  Store information about the document size
822 * Scope:    FixedHeader
823 */
824FixedHeader.oDoc = {
825  "iHeight": 0,
826  "iWidth": 0
827};
828
829/*
830 * Variable: afnScroll
831 * Purpose:  Array of functions that are to be used for the scrolling components
832 * Scope:    FixedHeader
833 */
834FixedHeader.afnScroll = [];
835
836/*
837 * Function: fnMeasure
838 * Purpose:  Update the measurements for the window and document
839 * Returns:  -
840 * Inputs:   -
841 */
842FixedHeader.fnMeasure = function ()
843{
844  var
845    jqWin = jQuery(window),
846    jqDoc = jQuery(document),
847    oWin = FixedHeader.oWin,
848    oDoc = FixedHeader.oDoc;
849 
850  oDoc.iHeight = jqDoc.height();
851  oDoc.iWidth = jqDoc.width();
852 
853  oWin.iHeight = jqWin.height();
854  oWin.iWidth = jqWin.width();
855  oWin.iScrollTop = jqWin.scrollTop();
856  oWin.iScrollLeft = jqWin.scrollLeft();
857  oWin.iScrollRight = oDoc.iWidth - oWin.iScrollLeft - oWin.iWidth;
858  oWin.iScrollBottom = oDoc.iHeight - oWin.iScrollTop - oWin.iHeight;
859};
860
861 
862/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
863 * Global processing
864 */
865
866/*
867 * Just one 'scroll' event handler in FixedHeader, which calls the required components. This is
868 * done as an optimisation, to reduce calculation and proagation time
869 */
870jQuery(window).scroll( function () {
871  FixedHeader.fnMeasure();
872  for ( var i=0, iLen=FixedHeader.afnScroll.length ; i<iLen ; i++ )
873  {
874    FixedHeader.afnScroll[i]();
875  }
876} );
Note: See TracBrowser for help on using the repository browser.