/*
* jquery.fixheadertable
*
* Copyright (c) 2010 Benjamin LĂ©ouzon
* http://www.tablefixedheader.com/
*
* Licensed under MIT
* http://www.opensource.org/licenses/mit-license.php
*
* http://docs.jquery.com/Plugins/Authoring
* jQuery authoring guidelines
*
* Launch : December 2010
* Version : 2.0
*/
(function($) {
$.fn.fixheadertable = function(options) {
var defaults = {
caption : '',
showhide : true,
theme : 'ui',
height : null,
width : null,
minWidth : null,
minWidthAuto : false,
colratio : [],
whiteSpace : 'nowrap',
addTitles : false,
zebra : false,
zebraClass : 'ui-state-active',
sortable : false,
sortedColId : null,
sortType : [],
dateFormat : 'd-m-y',
pager : false,
rowsPerPage : 10,
resizeCol : false,
minColWidth : 100,
wrapper : true
};
var options = $.extend(defaults, options);
function util_getComputedStyle(element, property) {
if (element.currentStyle) {
var y = x.currentStyle[property];
} else if (window.getComputedStyle) {
var y = document.defaultView.getComputedStyle(element, null).getPropertyValue(property);
}
return y;
}
function util_getScrollbarWidth () {
var inner = $('
').addClass('t_fixed_header_scroll_inner');
var outer = $('').addClass('t_fixed_header_scroll_outer');
outer.append(inner);
$(document.body).append(outer);
var w1 = inner[0].offsetWidth;
outer.css('overflow', 'scroll');
var w2 = inner[0].offsetWidth;
if (w1 == w2) w2 = outer[0].clientWidth;
outer.remove();
return (w1 - w2);
}
function util_parseDate (format, date) {
/*
* Function taken to jqGrid
* Thanks to jqGrid
* Author: Mark Williams
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl-2.0.html
*/
var tsp = {m : 1, d : 1, y : 1970, h : 0, i : 0, s : 0}, k, hl, dM;
if(date && date !== null && date !== undefined){
date = $.trim(date);
date = date.split(/[\\\/:_;.\t\T\s-]/);
format = format.split(/[\\\/:_;.\t\T\s-]/);
var dfmt = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var afmt = ["am", "pm", "AM", "PM"];
var h12to24 = function(ampm, h){
if (ampm === 0){ if (h == 12) { h = 0;} }
else { if (h != 12) { h += 12; } }
return h;
};
for (k=0, hl=format.length; k < hl; k++){
if(format[k] == 'M') {
dM = $.inArray(date[k],dfmt);
if(dM !== -1 && dM < 12){date[k] = dM+1;}
}
if(format[k] == 'F') {
dM = $.inArray(date[k],dfmt);
if(dM !== -1 && dM > 11){date[k] = dM+1-12;}
}
if(format[k] == 'a') {
dM = $.inArray(date[k],afmt);
if(dM !== -1 && dM < 2 && date[k] == afmt[dM]){
date[k] = dM;
tsp.h = h12to24(date[k], tsp.h);
}
}
if(format[k] == 'A') {
dM = $.inArray(date[k],afmt);
if(dM !== -1 && dM > 1 && date[k] == afmt[dM]){
date[k] = dM-2;
tsp.h = h12to24(date[k], tsp.h);
}
}
if(date[k] !== undefined) {
tsp[format[k].toLowerCase()] = parseInt(date[k],10);
}
}
tsp.m = parseInt(tsp.m,10)-1;
var ty = tsp.y;
if (ty >= 70 && ty <= 99) {tsp.y = 1900 + tsp.y;}
else if (ty >=0 && ty <=69) {tsp.y= 2000 + tsp.y;}
}
return new Date(tsp.y, tsp.m, tsp.d, tsp.h, tsp.i, tsp.s,0);
}
return this.each(function() {
var _table = $(this);
var main_wrapper = null;
var nbcol = $('thead th', this).length;
var _initialWidth = $(this).width();
var _wrapper = null;
var _headerscontainer = null;
var _fillScrollbar = null;
var _body = null;
var _headers = null;
var _scrollWidth = util_getScrollbarWidth();
var _colgroup = buildColgroup(nbcol);
var _colgroup_body = null;
var _nbRowsPerPage = 10;
var _new_nbRowsPerPage = null;
var _nbpages = null;
var _nbpagesDiv = null;
var _currentpage = null;
var _pager = null;
var _objectTable = null;
var _stripNum = /[\$,%]/g;
var _resizeInfo = null;
var _resizeGhost = null;
function buildTop (table) {
_fillScrollbar = $('');
_headerscontainer = _fillScrollbar;
_headerscontainer.insertBefore(table);
}
function buildColgroup (nbcol) {
var colgroup = $('');
if (options.colratio.length == 0) {
var temp = null;
for (var i = 0; i < nbcol; i++) {
temp = $('');
colgroup.append(temp);
temp = null;
}
} else if (options.colratio.length == nbcol) {
var cw = 0;
for (var i = 0; i < nbcol; i++) {
temp = $('');
colgroup.append(temp);
temp = null;
cw += parseInt(options.colratio[i]);
}
$(_table).css('width', cw + 'px');
}
return colgroup;
}
function sortColumn (table, number, sens, th) {
/*
* Function inspired by jqGrid
* Author: Mark Williams
*/
if ((options.sortType.length != 0) && (options.sortType.length == nbcol)) {
var type = options.sortType[number];
if (type == 'float') {
getSortKey = function(cell) {
var key = parseFloat( String(cell).replace(_stripNum, ''));
return isNaN(key) ? 0.00 : key;
}
} else if (type == 'integer') {
getSortKey = function(cell) {
return cell ? parseFloat(String(cell).replace(_stripNum, '')) : 0;
}
} else if (type == 'date') {
getSortKey = function(cell) {
return util_parseDate(options.dateFormat, cell).getTime();
}
} else {
getSortKey = function(cell) {
if(!cell) { cell =""; }
return $.trim(String(cell).toLowerCase());
}
}
} else {
getSortKey = function(cell) {
if(!cell) { cell =""; }
return $.trim(String(cell).toLowerCase());
}
}
_objectTable.sort(function(a, b){
var x = getSortKey(a[number]);
var y = getSortKey(b[number]);
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
})
if(sens == 'DESC'){
_objectTable.reverse();
}
(options.pager) ? moveToPage(table) : objectToTable(_objectTable, table);
}
function objectToTable(objectArray, table) {
var body = $('tbody', table);
body.children().remove();
if(options.zebra){
for (var i = 0; i < objectArray.length; i++){
(i%2) ? (tr = $('
')) : (tr = $('
'));
for (var j in objectArray[i]){
tr.append($(' | ').html(objectArray[i][j]));
}
body.append(tr);
}
} else {
for (var i = 0; i < objectArray.length; i++){
tr = $('
');
for (var j in objectArray[i]){
tr.append($(' | ').html(objectArray[i][j]));
}
body.append(tr);
}
}
}
function tableToObject(table) {
var objectArray = [];
$('tr', table).each(function(i){
var data = {};
$('td', this).each(function(j){
data[j] = $(this).html();
})
objectArray.push(data);
});
return objectArray;
}
function buildHeaders(table) {
_headers = $('').append(_colgroup).append($('thead', table));
_headerscontainer.append(_headers);
_headers.wrap('');
var tab_headers = $('th', _headers);
tab_headers.addClass('ui-widget-content ui-state-default');
if(options.sortable){
var th_div_sort = null;
tab_headers.each(function(i){
$(this).contents().wrapAll('');
th_div_sort = $('div.ui-sort', this);
th_div_sort.click(function(){
tab_headers.removeClass('ui-state-hover');
$(this).parent().removeClass('ui-state-active').addClass('ui-state-hover');
$('span.ui-icon', tab_headers).remove();
if($(this).hasClass('sortedUp')){
sortColumn(table, i, "DESC", this);
$(this).removeClass('sortedUp').addClass('sortedDown');
$(this).append('');
} else {
sortColumn(table, i, "ASC", this);
$(this).removeClass('sortedDown').addClass('sortedUp');
$(this).append('');
}
_headerscontainer[0].scrollLeft = _body[0].scrollLeft;
})
});
$('div.ui-sort', tab_headers).addClass('hover');
}
if(options.resizeCol && (options.colratio.length == nbcol)){
tab_headers.each(function(i){
var resizer = $('');
$(this).prepend(resizer);
resizer.mousedown(function(e){
dragStart(i, e);
return false;
})
});
_main_wrapper.mousemove(function(e){
if (_resizeInfo){
dragMove(e);
return false;
}
}).mouseup(function(){
if (_resizeInfo){
dragEnd();
return false;
}
return true;
});
function getOffset(col){
var ret = 0, cell = $('col', _colgroup), handler = $('th > span.ui-resize', _headers)[col], bso = _body[0].scrollLeft;
for(var i = 0; i < col; i++){
ret += parseInt(cell[i].style.width);
}
return handler.offsetLeft + 5 + ret - bso;
}
function dragStart(i, x){
_resizeInfo = { id : i, startX : x.clientX , initTableWidth : getColratioWidth(), offset : getOffset(i) };
_resizeGhost.css({ display : 'block', height : _headerscontainer.height() + _body.height() + 2 + 'px', left : _resizeInfo.offset + 'px', cursor : 'col-resize' });
}
function dragMove(x){
var diff = x.clientX - _resizeInfo.startX;
_resizeInfo.newWidth = parseInt($('col', _colgroup)[_resizeInfo.id].style.width) + diff;
_resizeInfo.newTableWidth = _resizeInfo.initTableWidth + diff;
if(_resizeInfo.newWidth > parseInt(options.minColWidth)){
_resizeGhost.css({ left : _resizeInfo.offset + diff + 'px' });
} else {
_resizeInfo.newWidth = parseInt(options.minColWidth);
}
}
function dragEnd(){
$(_colgroup.children()[_resizeInfo.id]).css({ width : _resizeInfo.newWidth + 'px' });
$(_colgroup_body.children()[_resizeInfo.id]).css({ width : _resizeInfo.newWidth + 'px' });
var wrapper_width = _resizeInfo.newTableWidth;
_headers.css({ 'width' : wrapper_width + 'px' });
$(_table).css({ 'width' : wrapper_width + 'px' });
_resizeInfo = null;
_resizeGhost.css({ display : 'none' });
_headerscontainer[0].scrollLeft = _body[0].scrollLeft;
}
}
}
function isIE6_7() {
if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) {
var ieversion = new Number(RegExp.$1);
if (ieversion == 7 || ieversion == 6) {
return true;
} else {
return false;
}
}
}
function isIE8() {
if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) {
var ieversion = new Number(RegExp.$1);
if (ieversion == 8) {
return true;
} else {
return false;
}
}
}
function buildBody (table) {
_body = $('').insertBefore(table).append(table);
if(options.height != null && !isNaN(parseInt(options.height))) {
_body.css('height', options.height + 'px');
}
_colgroup_body = _colgroup.clone();
$(table).prepend(_colgroup_body);
$('td', table).addClass('ui-widget-content');
$(table).wrap('');
if (options.addTitles == true) {
$('td', table).each(function() {
$(this).attr('title', $(this).text());
});
}
if (options.zebra) {
$('tr:odd', table).addClass(options.zebraClass);
}
}
function adaptScroll (table) {
var scrollwidth = _scrollWidth;
if(isIE6_7()){
scrollwidth = 0;
}
var width = 0;
if (parseInt($(table).height()) > parseInt(options.height)) {
width = scrollwidth;
overflow = 'scroll';
} else {
width = 0;
overflow = 'auto';
}
if($.browser.msie && options.height) {
width = scrollwidth;
overflow = 'scroll';
}
_fillScrollbar.css('margin-right', width);
return overflow;
}
function restrictRows(table, nbrows) {
var length = _objectTable.length;
var limit = 0;
if(length < nbrows) {
limit = length;
} else {
limit = nbrows;
}
var _objectTableSliced = _objectTable.slice(0, limit);
objectToTable(_objectTableSliced, table);
_nbpages = Math.ceil(length / nbrows);
_currentpage = 1;
_nbpagesDiv.html('Showing page ' + _currentpage + ' of ' + _nbpages);
_body.css('overflow-y', adaptScroll(table));
$('tr:last td', table).css('border-bottom-width', '1px');
}
function moveToNextPage(table) {
_currentpage++;
if(_currentpage >= (_nbpages)) {
_currentpage = (_nbpages);
}
moveToPage(table);
}
function moveToPreviousPage(table) {
_currentpage--;
if(_currentpage <= 1) {
_currentpage = 1;
}
moveToPage(table);
}
function moveToPage(table) {
var length = _objectTable.length;
var start, limit = 0;
start = (_currentpage - 1) * _new_nbRowsPerPage;
if(length < (_currentpage * _new_nbRowsPerPage)) {
limit = length;
} else {
limit = (_currentpage * _new_nbRowsPerPage);
}
var _objectTableSliced = _objectTable.slice(start, limit);
objectToTable(_objectTableSliced, table);
_nbpagesDiv.html('Showing page ' + _currentpage + ' of ' + _nbpages);
_body.css('overflow-y', adaptScroll(table));
$('tr:last td', table).css('border-bottom-width', '1px');
}
function buildNavButton(className, callbackClick, buttonClass) {
var button = $('
');
_pager.append(button);
button.mouseover(function(){
$(this).addClass('ui-state-hover');
}).mousedown(function(){
$(this).addClass('ui-state-active');
}).mouseup(function(){
$(this).removeClass('ui-state-active');
}).mouseout(function(){
$(this).removeClass('ui-state-active');
$(this).removeClass('ui-state-hover');
}).click(callbackClick);
}
function buildPager(table) {
_pager = $('');
_main_wrapper.append(_pager);
buildNavButton('ui-icon-arrowthickstop-1-e', function(){
_currentpage = _nbpages;
moveToPage(table);
}, 'ui-corner-right');
buildNavButton('ui-icon ui-icon-arrowthick-1-e', function(){
moveToNextPage(table);
}, 'noborder');
buildNavButton('ui-icon ui-icon-arrowthick-1-w', function(){
moveToPreviousPage(table);
}, 'noborder');
buildNavButton('ui-icon-arrowthickstop-1-w', function(){
_currentpage = 1;
moveToPage(table);
}, 'ui-corner-left noborder');
_button_set =
$('' +
'' +
'' +
'' +
'' +
'
');
_pager.append(_button_set);
$('#' + table.id + '_show_10_rows', _pager).click(function(){
_new_nbRowsPerPage = _nbRowsPerPage;
restrictRows(table, _new_nbRowsPerPage);
});
$('#' + table.id + '_show_25_rows', _pager).click(function(){
_new_nbRowsPerPage = _nbRowsPerPage * 2.5;
restrictRows(table, _new_nbRowsPerPage);
});
$('#' + table.id + '_show_50_rows', _pager).click(function(){
_new_nbRowsPerPage = _nbRowsPerPage * 5;
restrictRows(table, _new_nbRowsPerPage);
});
$('#' + table.id + '_show_100_rows', _pager).click(function(){
_new_nbRowsPerPage = _nbRowsPerPage * 10;
restrictRows(table, _new_nbRowsPerPage);
});
_nbpagesDiv = $('');
_pager.append(_nbpagesDiv);
_new_nbRowsPerPage = _nbRowsPerPage;
$('#' + table.id + '_show_' + options.rowsPerPage + '_rows', _pager).click();
_button_set.buttonset();
}
function getColratioWidth(){
var tw = 0;
for(var i = 0; i < options.colratio.length; i++){
tw += parseInt(options.colratio[i]);
}
return tw;
}
/***********************/
/********* MAIN ********/
/***********************/
_wrapper = $('').addClass('t_fixed_header ui-state-default default ' + options.theme).insertBefore(this).append(this);
_wrapper.css('border', 'none').css('font-weight', 'normal');
_main_wrapper = $('');
if (options.whiteSpace == 'normal') {
_wrapper.addClass('t_fixed_header_wrap');
}
buildTop(this);
buildHeaders(this);
buildBody(this);
if(options.wrapper){
var tampon = _wrapper.wrap('').parent();
} else {
var tampon = _wrapper.wrap('').parent();
}
if (options.width != null && !isNaN(parseInt(options.width)) && options.width > 0) {
tampon.css('width', options.width + 'px');
}
var res = _wrapper.detach();
var main_wrapper_child = $('');
_main_wrapper.append(main_wrapper_child);
main_wrapper_child.append(res);
tampon.append(_main_wrapper);
if(isIE6_7()){
_body.css('margin-bottom', 17 + 'px');
}
if (options.caption != '') {
var caption = $('');
_main_wrapper.prepend(caption).addClass('ui-corner-all');
if (options.showhide) {
var showhide = $('
');
caption.append(showhide);
showhide.click(function(){
main_wrapper_child.toggle();
caption.toggleClass('toggle')
if(_pager) _pager.toggle();
$('span', showhide).toggleClass('ui-icon-triangle-1-s');
});
}
}
if (options.sortable || options.pager) {
_objectTable = tableToObject(this);
}
if (options.pager) {
buildPager(this);
}
if(options.sortable && !isNaN(parseInt(options.sortedColId))) {
var cur_th = $('th', _headers)[options.sortedColId];
$(cur_th).addClass('ui-state-hover')
$('div.ui-sort', cur_th).click();
}
if(options.resizeCol && (options.colratio.length == nbcol)){
_resizeGhost = $('');
_wrapper.append(_resizeGhost);
}
_body.css('overflow-y', adaptScroll(this));
if (options.minWidth != null && !isNaN(parseInt(options.minWidth)) && options.minWidth > 0) {
var minWidth = options.minWidth + 'px';
} else if (options.minWidthAuto) {
if (options.colratio.length == nbcol) {
var minWidth = $(this).width() + 'px';
} else {
var minWidth = (_initialWidth + 150) + 'px';
}
}
_headerscontainer.children().first().css('min-width', minWidth);
_body.children().first().css('min-width', minWidth);
_body.scroll(function(){
_headerscontainer[0].scrollLeft = _body[0].scrollLeft;
if(isIE6_7()) { $(_headerscontainer[0]).css('margin-left', -_body[0].scrollLeft + 'px'); }
});
if (options.colratio.length == nbcol) {
_wrapper.removeClass('default');
$(_headers).css('width', getColratioWidth() + 'px');
}
});
};
})(jQuery);