Return to Snippet

Revision: 35118
at November 3, 2010 00:31 by chrisf


Initial Code
// 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;
        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');
                // EDIT - setting these styles explicitly - removes the need to have .css file (unless we are printing)
                t.className = tclass + ' ' + (w ? fc : ac);
                t.style.top = 0;
                t.style.position = (w ? "fixed" : "absolute"); 
                
                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 = '-2000%'; // hide it //EDIT - previously was "-2000px" my VDUs are getting bigger!  Mine is 1920x1200 and when I expanded across 2 screens I would see the "hidden" table. 
            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;

            //EDIT - Set the width of the header explicitly
            try {
                w = t.offsetWidth;
                xTableHeaderFixed.xWidth(ht, w);
            }
            catch (exception) {
                alert(exception);
            }
        }
    }
} // 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);
}
*/

Initial URL


Initial Description
Some minor changes to xTableHeaderFixed from http://cross-browser.com/x/lib/view.php?s=xTableHeaderFixed

Initial Title
xTableHeaderFixed

Initial Tags


Initial Language
JavaScript