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