/* * 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("
"); 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('
'); var rowTable = baseTable.shallowClone().removeAttr('id').wrap('
'); var colTable = baseTable.shallowClone().removeAttr('id').wrap('
'); var crossTable = baseTable.shallowClone().removeAttr('id').wrap('
'); 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('
test
'), $outer = jQuery('
').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); }