You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

315 lines
7.5 KiB
JavaScript

/*
* File: FixedColumns.js
* Version: 1.0.0
* Description: "Fix" columns on the left of a scrolling DataTable
* Author: Allan Jardine (www.sprymedia.co.uk)
* Created: Sat Sep 18 09:28:54 BST 2010
* Language: Javascript
* License: GPL v2 or BSD 3 point style
* Project: Just a little bit of fun - enjoy :-)
* Contact: www.sprymedia.co.uk/contact
*
* Copyright 2010 Allan Jardine, all rights reserved.
*/
var FixedColumns = function ( oDT, oInit ) {
/* Sanity check - you just know it will happen */
if ( typeof this._fnConstruct != 'function' )
{
alert( "FixedColumns warning: FixedColumns must be initialised with the 'new' keyword." );
return;
}
if ( typeof oInit == 'undefined' )
{
oInit = {};
}
/**
* @namespace Settings object which contains customisable information for FixedColumns instance
*/
this.s = {
/**
* DataTables settings objects
* @property dt
* @type object
* @default null
*/
"dt": oDT.fnSettings(),
/**
* Number of columns to fix in position
* @property columns
* @type int
* @default 1
*/
"columns": 1
};
/**
* @namespace Common and useful DOM elements for the class instance
*/
this.dom = {
/**
* DataTables scrolling element
* @property scroller
* @type node
* @default null
*/
"scroller": null,
/**
* DataTables header table
* @property header
* @type node
* @default null
*/
"header": null,
/**
* DataTables body table
* @property body
* @type node
* @default null
*/
"body": null,
/**
* DataTables footer table
* @property footer
* @type node
* @default null
*/
"footer": null,
/**
* @namespace Cloned table nodes
*/
"clone": {
/**
* Cloned header table
* @property header
* @type node
* @default null
*/
"header": null,
/**
* Cloned body table
* @property body
* @type node
* @default null
*/
"body": null,
/**
* Cloned footer table
* @property footer
* @type node
* @default null
*/
"footer": null
}
};
/* Let's do it */
this._fnConstruct( oInit );
};
FixedColumns.prototype = {
/**
* Initialisation for FixedColumns
* @method _fnConstruct
* @param {Object} oInit User settings for initialisation
* @returns void
*/
"_fnConstruct": function ( oInit )
{
var that = this;
/* Sanity checking */
if ( typeof this.s.dt.oInstance.fnVersionCheck != 'function' ||
this.s.dt.oInstance.fnVersionCheck( '1.7.0' ) !== true )
{
alert( "FixedColumns 2 required DataTables 1.7.0 or later. "+
"Please upgrade your DataTables installation" );
return;
}
if ( this.s.dt.oScroll.sX === "" )
{
this.s.dt.oInstance.oApi._fnLog( this.s.dt, 1, "FixedColumns is not needed (no "+
"x-scrolling in DataTables enabled), so no action will be taken. Use 'FixedHeader' for "+
"column fixing when scrolling is not enabled" );
return;
}
if ( typeof oInit.columns != 'undefined' )
{
if ( oInit.columns < 1 )
{
this.s.dt.oInstance.oApi._fnLog( this.s.dt, 1, "FixedColumns is not needed (no "+
"columns to be fixed), so no action will be taken" );
return;
}
this.s.columns = oInit.columns;
}
/* Set up the DOM as we need it and cache nodes */
this.dom.body = this.s.dt.nTable;
this.dom.scroller = this.dom.body.parentNode;
this.dom.scroller.style.position = "relative";
this.dom.header = this.s.dt.nTHead.parentNode;
this.dom.header.parentNode.style.position = "relative";
if ( this.s.dt.nTFoot )
{
this.dom.footer = this.s.dt.nTFoot.parentNode;
this.dom.footer.parentNode.style.position = "relative";
}
/* Event handlers */
$(this.dom.scroller).scroll( function () {
that._fnScroll.call( that );
} );
this.s.dt.aoDrawCallback.push( {
"fn": function () {
that._fnClone.call( that );
that._fnScroll.call( that );
},
"sName": "FixedColumns"
} );
/* Get things right to start with */
this._fnClone();
this._fnScroll();
},
/**
* Clone the DataTable nodes and place them in the DOM (sized correctly)
* @method _fnClone
* @returns void
* @private
*/
"_fnClone": function ()
{
var
that = this,
iTableWidth = 0,
aiCellWidth = [],
i, iLen, jq;
/* Grab the widths that we are going to need */
for ( i=0, iLen=this.s.columns ; i<iLen ; i++ )
{
jq = $('thead th:eq('+i+')', this.dom.header);
iTableWidth += jq.outerWidth();
aiCellWidth.push( jq.width() );
}
/* Header */
if ( this.dom.clone.header !== null )
{
this.dom.clone.header.parentNode.removeChild( this.dom.clone.header );
}
this.dom.clone.header = $(this.dom.header).clone(true)[0];
this.dom.clone.header.className += " FixedColumns_Cloned";
$('thead tr', this.dom.clone.header).each( function () {
$('th:gt('+(that.s.columns-1)+')', this).remove();
} );
$('thead th', this.dom.clone.header).each( function (i) {
this.style.width = aiCellWidth[i]+"px";
} );
this.dom.clone.header.style.position = "absolute";
this.dom.clone.header.style.top = "0px";
this.dom.clone.header.style.left = "0px";
this.dom.clone.header.style.width = iTableWidth+"px";
this.dom.header.parentNode.appendChild( this.dom.clone.header );
/* Body */
if ( this.dom.clone.body !== null )
{
this.dom.clone.body.parentNode.removeChild( this.dom.clone.body );
}
this.dom.clone.body = $(this.dom.body).clone(true)[0];
this.dom.clone.body.className += " FixedColumns_Cloned";
$('thead tr', this.dom.clone.body).each( function () {
$('th:gt('+(that.s.columns-1)+')', this).remove();
} );
$('tbody tr', this.dom.clone.body).each( function () {
$('td:gt('+(that.s.columns-1)+')', this).remove();
} );
$('tfoot tr', this.dom.clone.body).each( function () {
$('th:gt('+(that.s.columns-1)+')', this).remove();
} );
$('thead th', this.dom.clone.body).each( function (i) {
this.style.width = aiCellWidth[i]+"px";
} );
this.dom.clone.body.style.position = "absolute";
this.dom.clone.body.style.top = "0px";
this.dom.clone.body.style.left = "0px";
this.dom.clone.body.style.width = iTableWidth+"px";
this.dom.body.parentNode.appendChild( this.dom.clone.body );
/* Footer */
if ( this.s.dt.nTFoot !== null )
{
if ( this.dom.clone.footer !== null )
{
this.dom.clone.footer.parentNode.removeChild( this.dom.clone.footer );
}
this.dom.clone.footer = $(this.dom.footer).clone(true)[0];
this.dom.clone.footer.className += " FixedColumns_Cloned";
$('tfoot tr', this.dom.clone.footer).each( function () {
$('th:gt('+(that.s.columns-1)+')', this).remove();
} );
$('tfoot th', this.dom.clone.footer).each( function (i) {
this.style.width = aiCellWidth[i]+"px";
} );
this.dom.clone.footer.style.position = "absolute";
this.dom.clone.footer.style.top = "0px";
this.dom.clone.footer.style.left = "0px";
this.dom.clone.footer.style.width = iTableWidth+"px";
this.dom.footer.parentNode.appendChild( this.dom.clone.footer );
}
},
/**
* Set the absolute position of the fixed column tables when scrolling the DataTable
* @method _fnScroll
* @returns void
* @private
*/
"_fnScroll": function ()
{
var iScrollLeft = $(this.dom.scroller).scrollLeft();
this.dom.clone.header.style.left = iScrollLeft+"px";
this.dom.clone.body.style.left = iScrollLeft+"px";
if ( this.dom.footer )
{
this.dom.clone.footer.style.left = iScrollLeft+"px";
}
}
};