| /* | 
|  * 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); | 
| } |