/*
|
* jQuery TableFix plugin ver 1.0.1
|
* Copyright (c) 2010 Otchy
|
* This source file is subject to the MIT license.
|
* http://www.otchy.net/javascript/tablefix/
|
*/
|
(function($){
|
$.fn.tablefix = function(options) {
|
var sbwidth = scrollbarWidth();
|
return this.each(function(index){
|
// 処理継続の判定
|
var opts = $.extend({}, options);
|
var baseTable = $(this);
|
var withWidth = (opts.width > 0);
|
var withHeight = (opts.height > 0);
|
if (withWidth) {
|
withWidth = (opts.width < baseTable.width());
|
} else {
|
opts.width = baseTable.width();
|
}
|
if (withHeight) {
|
withHeight = (opts.height < baseTable.height());
|
} else {
|
opts.height = baseTable.height();
|
}
|
if (withWidth || withHeight) {
|
if (withWidth) {
|
opts.height -= sbwidth;
|
}
|
if (withHeight) {
|
opts.width -= sbwidth;
|
}
|
} else {
|
return;
|
}
|
// 外部 div の設定
|
baseTable.wrap("<div></div>");
|
var div = baseTable.parent();
|
div.css({position: "relative"});
|
// スクロール部オフセットの取得、tdにwidthとheightを固定
|
var fixRows = (opts.fixRows > 0) ? opts.fixRows : 0;
|
var fixCols = (opts.fixCols > 0) ? opts.fixCols : 0;
|
var offsetX = 0;
|
var offsetY = 0;
|
baseTable.find('tr').each(function(indexY) {
|
var trThis = $(this);
|
if(jQuery.browser.msie) {
|
trThis.height(trThis.height() + 1);
|
} else {
|
trThis.height(trThis.height());
|
}
|
trThis.find('td,th').each(function(indexX) {
|
// 先頭の行
|
if (indexY <= fixRows) {
|
var cell = $(this);
|
if (indexY == fixRows && indexX == fixCols) {
|
offsetX = cell.position().left;
|
offsetY = cell.parent('tr').position().top;
|
}
|
cell.width(cell.width());
|
cell.height(cell.height());
|
}
|
// 先頭の列
|
else if (indexX <= fixCols) {
|
var cell = $(this);
|
cell.width(cell.width());
|
cell.height(cell.height());
|
}
|
else {
|
return false;
|
}
|
});
|
});
|
// テーブルの分割と初期化
|
var bodyTable = baseTable.wrap('<div name="bodyTable"></div>');
|
var rowTable = baseTable.shallowClone().removeAttr('id').wrap('<div name="rowTable"></div>');
|
var colTable = baseTable.shallowClone().removeAttr('id').wrap('<div name="colTable"></div>');
|
var crossTable = baseTable.shallowClone().removeAttr('id').wrap('<div name="crossTable"></div>');
|
baseTable.find('tr').each(function(indexY) {
|
var trThis = $(this);
|
var trRow, trCol, trCross;
|
if (indexY < fixRows) {
|
trRow = trThis.shallowClone().removeAttr('id').appendTo(rowTable);
|
trCross = trThis.shallowClone().removeAttr('id').appendTo(crossTable);
|
}
|
trThis.find('td,th').each(function(indexX) {
|
var cell = $(this);
|
// 先頭の行
|
if (indexY < fixRows) {
|
// 同時に先頭の列
|
if (indexX < fixCols) {
|
trCross.append(cell);
|
}
|
// 単なる先頭の行
|
else {
|
trRow.append(cell);
|
}
|
}
|
// 先頭の列
|
else if (indexX < fixCols) {
|
if (!trCol) {
|
trCol = trThis.shallowClone().removeAttr('id').appendTo(colTable);
|
}
|
trCol.append(cell);
|
}
|
else {
|
return false;
|
}
|
});
|
if (indexY < fixRows) {
|
trThis.remove();
|
}
|
});
|
var crossDiv = crossTable.parent().css({position: "absolute", overflow: "hidden"});
|
var rowDiv = rowTable.parent().css({position: "absolute", overflow: "hidden"});
|
var colDiv = colTable.parent().css({position: "absolute", overflow: "hidden"});
|
var bodyDiv = bodyTable.parent().css({position: "absolute", overflow: "auto"});
|
// クリップ領域の設定
|
var bodyWidth = opts.width - offsetX;
|
var bodyHeight = opts.height - offsetY;
|
crossDiv
|
.width(offsetX)
|
.height(offsetY);
|
crossTable.width(offsetX);
|
rowDiv
|
.width(bodyWidth)
|
.height(offsetY)
|
.css({left: offsetX + 'px'});
|
colDiv
|
.width(offsetX)
|
.height(bodyHeight)
|
.css({top: offsetY + 'px'});
|
colTable.width(offsetX);
|
bodyDiv
|
.width(bodyWidth + (withHeight ? sbwidth : 0))
|
.height(bodyHeight + (withWidth ? sbwidth : 0))
|
.css({left: offsetX + 'px', top: offsetY + 'px'});
|
div.append(rowDiv).append(colDiv).append(crossDiv);
|
// スクロール連動
|
bodyDiv.scroll(function() {
|
rowDiv.scrollLeft(bodyDiv.scrollLeft());
|
colDiv.scrollTop(bodyDiv.scrollTop());
|
});
|
rowDiv.scroll(function() {
|
bodyDiv.scrollLeft(rowDiv.scrollLeft());
|
});
|
colDiv.scroll(function() {
|
bodyDiv.scrollLeft(colDiv.scrollLeft());
|
});
|
// 外部 div の設定
|
div
|
.width(opts.width + (withHeight ? sbwidth : 0))
|
.height(opts.height + (withWidth ? sbwidth : 0));
|
});
|
}
|
})(jQuery);
|
|
jQuery.fn.extend({
|
shallowClone: function() {
|
return this.map(function () {
|
return jQuery.shallowClone(this);
|
});
|
}
|
});
|
jQuery.extend({
|
shallowClone: function(elem) {
|
var clone;
|
clone = elem.cloneNode(false);
|
return clone;
|
}
|
});
|
// http://chris-spittles.co.uk/jquery-calculate-scrollbar-width/
|
function scrollbarWidth() {
|
var $inner = jQuery('<div style="width: 100%; height:200px;">test</div>'),
|
$outer = jQuery('<div style="width:200px;height:150px; position: absolute; top: 0; left: 0; visibility: hidden; overflow:hidden;"></div>').append($inner),
|
inner = $inner[0],
|
outer = $outer[0];
|
|
jQuery('body').append(outer);
|
var width1 = inner.offsetWidth;
|
$outer.css('overflow', 'scroll');
|
var width2 = outer.clientWidth;
|
$outer.remove();
|
|
return (width1 - width2);
|
}
|