數據表格表頭與首列固定的完全實現


前幾天項目經理跟我說有這么個需求:一個很大的表格,垂直滑動時表頭固定,水平滑動里第一、二列固定。我一想這也太難實現了,直接回復說可能實現不了,可是沒過會經理發個12306網站的一個現存的實現樣子,汗!我只能說那我先調研下實現的成本吧。心里想想反正客戶給錢,沒有什么理由不做啊。

1. 前期調研

先打開12306網站上面的那個表格,打開瀏覽器調試工具,發現他們好像用的是插件(dhtmlxgrid),再看了下布局,發現它們把固定的表頭和列放在一個DIV里面,心里想這樣的需求肯定很常見,說不定網上早有相應插件了,於是上google搜“table header fixed  ”(個人比較喜歡用英文關鍵字搜索信息),第一條信息就是一個基於jquery的插件叫Fixed Header Table,而且還不要錢的,於是下載下來,研究它的源碼,發現它的布局與12306上面的類似也是把固定的表頭和列放在一個DIV,然后在此DIV里面放table,整體布局如下圖所示:

table_thumb1

通過控制單元格的寬度和高度,使整體的單元格對齊,最后監聽maindiv的滑動事件,當它滑動時通過js去滑動headerdiv與columndiv的滑動。其實里面最麻煩的應該是單元格對齊問題,因為單元格寬和高會隨里面的內容變化(如果你想自適應的話)。

知道實現原理后,然后對照下我實際的項目,我項目中的表格和12306中的表格有的類似,不是普通的數據表格,里面的單元格的合並,而且我項目中的表格還有分組(grounp),截個圖:

image_thumb1_thumb

里面有編輯功能,還得在行和列分別加個total,表格夠復雜吧。Fixed Header Table這個插件不支持我的表格(單元格的合並),dhtmlxgrid插件很強大,但要錢,項目中本來就有jquery了,不想再引用其它框架了,自己動手,豐衣足食!

2. 具體實現

2.1 簡化需求

以前的布局就是一個table,要做這種行列鎖定的表格,布局肯定大改,為了簡單點,我把我表格中的單元格寬度和高度固定,超出的文字用…表示,呵呵,我還是想怎么簡單怎么來,這么做客戶也接受。把單元格定死后,代碼量會少很多。布局盡量用CSS去控制,JS只控制滑動和初始化區域大小(因為我頁面是自適應的)。

2.2 html+CSS

先畫個兩行兩列的表格,把整體布局定好,我做布局都先做整體,再做局部。先看下整體布局的html:

<table>
    <thead>
        <tr >
           <th></th>
           <th>
               <div id="Headerdiv" style=" overflow: hidden"></div>
           </th>  
        </tr>
    </thead>
    <tbody>
        <tr>
            <td >
                <div id="Columndiv" style=" overflow: hidden"></div>
            </td>
            <td>
                <div id="maindiv" style=" overflow: scroll" onscroll="fnScroll()"></div>
            </td>
        </tr>
    </tbody>
</table>

里面div的主要屬性和事件都已經聲明,接下來做thead里的兩行固定列,第一個th的源代碼:

<th id="firstTd " class="tdborder">
    <table cellspacing="0" cellpadding="0">
        <tr>
            <td  class="tableFirstCol  txtcenter td_right td_bottom">Project</td>
            <td class="tableSecondCol   td_bottom">
                     <table cellspacing="0" cellpadding="0" class="Tamount">
                        <tr>
                            <td colspan="3" class="txtcenter td_bottom">Total</td>
                        </tr>
                        <tr>
                            <td class="current td_right">current</td>
                            <td class="scenario td_right">scenario</td>
                            <td class="different">different</td>
                        </tr>
                    </table>
              
              </td>
        </tr>
        <tr>
            <td class="tableFirstCol td_right">Total</td>
            <td class="tableSecondCol ">
                <table cellpadding="0" cellspacing="0">
                      <tr>
                            <td class="current td_right"><input type="text" /></td>
                            <td class="scenario td_right"><input type="text" /</td>
                            <td class="different"><input type="text" /</td>
                        </tr>
                </table>
            </td>
        </tr>
    </table>
    </th>

然后是第二個th里面的Headerdiv的源代碼:

 

<div id="Headerdiv" >
       <table cellspacing="0" cellpadding="0"  width="1560" id="headertable" class="td_right" >
          <tr >
            <td class="td_left">
              
              <table cellspacing="0" cellpadding="0" class="Tamount">
                        <tr>
                            <td colspan="3"  class="txtcenter td_bottom">1999</td>
                        </tr>
                        <tr>
                            <td class="current td_right">current</td>
                            <td class="scenario td_right">scenario</td>
                            <td class="different">different</td>
                        </tr>
                    </table>
            </td>
           重復TD...
          </tr>
        <tr >
            <td class="td_left td_top">
                <table cellpadding="0" cellspacing="0">
                      <tr>
                            <td class="current td_right"><input type="text" /></td>
                            <td class="scenario td_right"><input type="text" /</td>
                            <td class="different"><input type="text" /</td>
                        </tr>
                </table>

            </td>
           重復TD...
        </tr>
        </table>
       </div>  

大家可能注意到里面對套了這么多table有異議,本人是為了站單元格對齊才出此下策,在整個頁面的制作過程中單元格的邊框對齊是最煩人的。

接下來展示固定列的html源碼:

 <div id="Columndiv"  class="fixedcol">
        <table cellspacing="0" cellpadding="0" >
            <tr>
                <td colspan="2" class="tdgroup">
                     group name group name group name group nam name group name group name
                    </td>
            </tr>
          <tr>
            <td class="tableFirstCol">Project Name 1 </td>
            <td class="tableSecondCol">
                <table cellpadding="0" cellspacing="0">
                      <tr>
                            <td class="current td_right"><input type="text" /></td>
                            <td class="scenario td_right"><input type="text" /</td>
                            <td class="different"><input type="text" /</td>
                        </tr>
                </table>
            </td>
          </tr>

里面class為tdgrounp的為表格的分組名,這分組名如果太長就會換行,我會在JS里面控制maindiv里對應單元格的高度,也是JS代碼里唯一控制單元格的代碼。

maindiv里的HTML就不粘出來了,里就就放了一個table。

3.3 javascript

接下來講講JS,JS 還是很簡單的(基於jquery):

 $(document).ready(function () {
        fnAdjustTable();
        //先求頁面給定的高度
        var _h = $("#tablediv").height();
        var _w = $("#tablediv").width();

        //然后設定相關div的高度
        var _head_h = $("#thead").height();
        $("#maindiv").height(_h - _head_h);
        $("#Columndiv").height(_h - _head_h - 18);//18是空出了相應滾動條的距離
        var _clo_w = $("#Columndiv").width();
        $("#Headerdiv").width(_w - _clo_w-18 );
        $("#maindiv").width(_w - _clo_w);
      
    });

    function fnAdjustTable() {
        //調整組名的單元格高度
        $('#Columndiv .tdgroup').each(function (i) {
            //不同瀏覽器這高度可能不一樣,相關一兩個像素
            if ($.browser.msie) {
                $("#maindiv .tdgroup:eq(" + i + ")").height($(this).height());
            } else {
                $("#maindiv .tdgroup:eq(" + i + ")").height($(this).height() + 1);
            }
           
        });
    }

    //滑動事件
     function fnScroll () {
        $('#Headerdiv').scrollLeft($('#maindiv').scrollLeft());
        $('#Columndiv').scrollTop($('#maindiv').scrollTop());
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM