X Library Viewer

Download the X Distribution File.

X Index

Animation

xAniLine, xAnimation.arc, xAnimation.corner, xAnimation.css, xAnimation.imgSize, xAnimation.line, xAnimation.opacity, xAnimation.para, xAnimation.rgb, xAnimation.rgbByClass, xAnimation.scroll, xAnimation.size, xAnimation, xAniOpacity, xAniRgb, xAniWH, xAniXY, xEllipse, xParaEq, xSequence, xSlideCornerTo, xSlideTo, xWinScrollTo.

DOM

xFirstChild, xGetElementById, xGetElementsByAttribute, xGetElementsByClassName, xGetElementsByTagName, xLoadLink, xLoadScript, xNextSib, xParent, xParentN, xPrevSib, xSmartLoad, xSmartLoad2, xSmartLoadScript.

Debug

xConsole, xEditable, xName, xParentChain, xSetIETitle.

Event

xAddEventListener, xDisableDrag, xDisableDrop, xEnableDrag, xEnableDrag2, xEnableDrop, xEvent, xHttpRequest, xPreventDefault, xRemoveEventListener, xStopPropagation.

Image

xImgAsyncWait, xImgRollSetup, xTriStateImage.

Iteration

xEach, xEachE, xEachN, xEachUntilReturn, xTimes, xWalkToFirst, xWalkToLast, xWalkTree, xWalkTree2, xWalkTree3, xWalkTreeRev, xWalkUL.

Misc

xCookie, xDef, xDeg, xGetURLArguments, xLibrary, xLinearScale, xNum, xRad, xRound, xStr.

Position

xCardinalPosition, xCen, xCenter, xGetEleAtPoint, xHasPoint, xIntersection, xLeft, xMoveTo, xOffset, xPageX, xPageY, xScrollLeft, xScrollTop, xTop.

Size

xClip, xColEqualizer, xDocSize, xHeight, xResizeTo, xWidth.

String

xCamelize, xCapitalize, xHex, xPad, xParseColor, xRgbToHex, xStrEndsWith, xStrReplaceEnd, xStrStartsWith, xTrim.

Style

xAddClass, xDisplay, xFindAfterByClassName, xFindBeforeByClassName, xGetComputedStyle, xGetCSSRules, xGetStyleSheetFromLink, xHasClass, xHasStyleSelector, xHasStyleSheets, xInsertRule, xOpacity, xRemoveClass, xStyle, xTagStyle, xToggleClass, xTraverseDocumentStyleSheets, xTraverseStyleSheet.

Table

xTable, xTableCellVisibility, xTableColDisplay, xTableCursor, xTableCursor2, xTableHeaderFixed, xTableIterate, xTableRowDisplay, xTableSync.

UI

xBar, xCollapsible, xDialog, xFenster, xFenster2, xMenu1, xMenu1A, xMenu1B, xMenu5, xMenu6, xModalDialog, xPopup, xSelect, xSplitter, xTabPanelGroup, xTextArea, xTooltipGroup.

Window

xClientHeight, xClientWidth, xWinClass, xWindow, xWinOpen.

xTableHeaderFixed

Description

xTableHeaderFixed is an unobtrusive table enhancement. It makes a copy of a table's THEAD section. While the table is visible in its container the THEAD copy will be fixed to the top of the container, so you can scroll up and down in a long table and the header will always be visible. The container can be a window or a scrollable element. The position and size of the THEAD copy will be adjusted when the window is resized. You only need to instantiate one xTableHeaderFixed object for each group of tables that have the same styling - and so those tables should have a common className, which you pass to the constructor. You must assign all of the table's styles relative to this className so that the THEAD copy will be styled just like it. View the source of a demo page to see the required CSS. It takes the widths of all THs (not TDs) in the THEAD and assigns them to the corresponding THs in the THEAD copy. When instantiating, you do not have to keep a reference to the object - it keeps a reference to itself, but if you plan on calling the init method later then you'll need to keep a reference to the object.

Syntax

new xTableHeaderFixed(tableClass, container, isWin, yOffset)

Parameters

tableClassThe enhancement will be applied to all tables having this className.
containerA window object, or a scrollable element's ID string or object reference.
isWinSet to true if "container" is a window object, else omit.
yOffsetIf isWin then set this to be a Y offset for the header table, or omit.

Source

// xTableHeaderFixed r10, Copyright 2006-2010 Michael Foster (Cross-Browser.com)
// Part of X, a Cross-Browser Javascript Library, Distributed under the terms of the GNU LGPL

var xIE8Up; // yuck!
/*@cc_on
@if (@_jscript_version > 5.7)
  xIE8Up = true;
@end @*/

var xGecko = window.navigator.product == 'Gecko'; // yuckier!

function xTableHeaderFixed(tclass, tcon, w, yofs)
{
  // Public Methods
  this.init = function(tclass, tcon, w, yofs)
  {
    _dtor();
    return _ctor(tclass, tcon, w, yofs);
  };
  this.paint = function()
  {
    _event({type:'resize'});
  };
  // Constructor Code
  var _i = this, con, tbl, win, cbl = 0, cbt = 0, fp = true, yo = 0,
    fc = 'xthf-fix-tbl', ac = 'xthf-abs-tbl'; // private properties
  if (tclass) { _ctor(tclass, tcon, w, yofs); }
  // Private Methods
  function _ctor(tclass, tcon, w, yofs)
  {
    var i, h, t, htc = (w ? fc : ac);
    tbl = xGetElementsByClassName(tclass, document, 'table');
    con = xGetElementById(tcon);
    if (!tbl || !tbl.length || !con) { return false; }
    if (!(win = w)) { con.scrollTop = 0; }
    // Create a header table for each table with tclass.
    for (i = 0; i < tbl.length; ++i) {
      h = tbl[i].tHead;
      if (h) {
        t = document.createElement('table');
        t.className = tclass + ' ' + htc;
        if (tbl[i].cellSpacing !== '') { t.cellSpacing = tbl[i].cellSpacing; }
        t.appendChild(h.cloneNode(true));
        t.id = tbl[i].xthfHdrTblId = 'xthf-' + tclass + '-' + i;
        if (typeof yofs != 'undefined') {
          yo = yofs;
          if (yo === 0) {      //
            t.style.top = xPageY(tbl[i]) + 'px'; // r10
          }                      //
          else {
            t.style.top = yo + 'px';
          }
        }
        document.body.appendChild(t);
      }
      else {
        tbl[i] = null;
      }
    }
    // begin DEBUG
    if (!w && !xIE8Up && !window.opera) {
      cbl = xGetComputedStyle(con, 'border-left-width', true),
      cbt = xGetComputedStyle(con, 'border-top-width', true);
    }
    // end DEBUG
    _event({type:'resize'});
    xAddEventListener(con, 'scroll', _event, false);
    xAddEventListener(window, 'resize', _event, false);
    xAddEventListener(window, 'unload', _dtor, false);
    return true;
  }
  function _dtor()
  {
    var i, ht;
    if (con) {
      xRemoveEventListener(con, 'scroll', _event);
      xRemoveEventListener(window, 'resize', _event);
      xRemoveEventListener(window, 'unload', _dtor);
      // Remove the header tables from the DOM.
      for (i = 0; i < tbl.length; ++i) {
        ht = xGetElementById(tbl[i].xthfHdrTblId);
        if (ht) { document.body.removeChild(ht); }
        tbl[i] = null;
      }
      tbl = null;
      con = null;
    }
  }
  function _event(e) // handles scroll and resize events
  {
    var i, r;
    e = e || window.event;
    r = e.type == 'resize';
    for (i = 0; i < tbl.length; ++i) {
      _paint(tbl[i], r);
    }
  }
  function _paint(t, r)
  {
    var i, ht, c1, c2, st, ty, thy, w, sep;
    if (!t) { return; }
    ht = xGetElementById(t.xthfHdrTblId);
    // Hide or show the header table.
    st = xScrollTop(con, win) + (yo || 0);
    if (win) { ty = xPageY(t); }
    else { ty = t.offsetTop; }
    thy = ty + t.rows[0].offsetTop;
    if (yo !== 0 && (st <= thy || st > ty + t.offsetHeight - ht.offsetHeight)) {
      ht.style.left = '-2000px'; // hide it
      fp = true; // first-paint after being hidden
      return;
    }
    // Position the header table.
    ht.style.left = (xPageX(t) - xScrollLeft(con, win) + cbl) + 'px';
    if (!win) { ht.style.top = (xPageY(con) + cbt) + 'px'; }
    if (fp || r) {
      // Resize the header table THs.
      c1 = xGetElementsByTagName('th', t.tHead);
      c2 = xGetElementsByTagName('th', ht.tHead);
      for (i = 0; i < c1.length; ++i) {
        w = c1[i].offsetWidth;
        xTableHeaderFixed.xWidth(c2[i], w);
      }
      fp = false;
    }
  }
} // end xTableHeaderFixed

// xWidth r8?, Copyright 2001-2010 Michael Foster (Cross-Browser.com)
// Part of X, a Cross-Browser Javascript Library, Distributed under the terms of the GNU LGPL
// This function is currently experimental and used only by xTableHeaderFixed.
xTableHeaderFixed.xWidth = function(e,w)
{
  var pl=0, pr=0, b=0, gcs;
  if (!(e = xGetElementById(e))) return false;
  if (xNum(w)) {
    if (w < 0) w = 0; // return false ???
    else w = Math.round(w);
  }
  else w = -1;
  if (xDef(e.style, e.offsetWidth, e.clientWidth)) {
    if (w >= 0) {
      if (document.compatMode=='CSS1Compat') {
        gcs = xGetComputedStyle;
        pl = gcs(e, 'padding-left', 1);
        pr = gcs(e, 'padding-right', 1);
        b = e.offsetWidth - e.clientWidth;
        if (window.opera && e.tagName.toLowerCase() != 'table') {
          b = Math.round(b / 2); // possibly only for TDs and THs !!! haven't yet finished testing in Opera !!!
        }
        w -= (pl + pr + b);
        if (isNaN(w) || w < 0) return false;
      }
      e.style.width = w + 'px';
    }
    w = e.offsetWidth;
  }
  else  {
    return false;
  }
  return w;
};

/* DEBUG
      sep = xGetComputedStyle(t, 'border-collapse') == 'separate';/////////////////
      for (i = 0; i < c1.length; ++i) {
        /////// testing something for table 3 ///////
        w = c1[i].offsetWidth;
        //if ((xGecko || xIE8Up) && c1[i].colSpan > 1) {
        if (xGecko && (win || sep) && c1[i].colSpan > 1) {
          --w; // ???????????????
        }
        xTableHeaderFixed.xWidth(c2[i], w);
      }
*/

Dependencies

xGetElementById, xPageX, xPageY, xScrollLeft, xScrollTop, xGetComputedStyle, xGetElementsByTagName, xGetElementsByClassName, xAddEventListener, xRemoveEventListener

Public Methods

init(tableClass, container, isWin, yOffset)If you did not pass arguments on instantiation then use this method to initialize the object - or you can call this method to re-initialize the object, with different arguments, any number of times.

Demos

xthf1 - This is the first of several xTableHeaderFixed demos.

Notes

08Jul10This object is in good shape altho not perfect. It has been one of the tougher cross-browser nuts to crack. The demo pages have notes and links to relevant forum topics.

Revisions

10: 09Jul10When yofs === 0 the thead copy is positioned directly on top of the thead original.
9: 08Jul10Added public method 'paint'. Added constructor argument 'yofs' (a Y offset when isWin). Removed use of xLeft and xTop and write to style property directly.
8: 27Jan10Improved support for "border-collapse:collapse", and other improvements.
7: 17Dec09It has been adapted to work with Ajax apps.
6: 12Nov09Rev 6 is in the works.
5: 08Nov09I ended up with three different variations of this object, so now I've combined them into one. The original "catfish" version is still available: "http://cross-browser.com/x/examples/xthf0.html".
-: 25Sep09See xTableHeaderFixed2 which implements this in a scrollable container.
4: 27Jul09No longer adding tableBorder and thBorder (I don't know why I thought that was needed in the first place). These parameters are now not needed, but I'll leave them for now, to be backwards-compatible.
3: 03Apr09Let each table have different styling. Found a bug while doing this: the generated id of fixed table was not unique with multiple xTableHeaderFixed objects on a page.
2: 21May07The loop adding tables to the 'tables' array was starting on the wrong index. Thanks very much to Thiago for finding this bug and submitting a fix.
-: 15Feb07added a "@media print" rule so the fixed container will not print. Thanks to bunsen!
1: 30Jan07Initial inclusion in X.

License

By your use of X and/or CBE and/or any Javascript from this site you consent to the GNU LGPL - please read it. If you have any questions about the license, read the FAQ and/or come to the forums.

Tech Support

Forum support is available at the X Library Support Forums.

About Cross-Browser.com

Cross-Browser.com is the home of X - a cross-browser Javascript library, and many demos, applications, articles and documentation.

Search

Cross-Browser.com

World Wide Web

User Projects

If you are using X, XC or anything from this site, show off your work by posting a link in the X Showcase forum.