• 重识手写固定表头固定列


    在做能源管理系统的时候,因为客户特殊要求,需要将表格固定表头与固定列

    思路:将表格固定的部分分为3快,

        第一部分:表头

          实现过程:

            监听滚动条的滚动事件,判断滚动式是横向滚动的还是纵向滚动的,实现过程就是定义一个全局变量,滚动的时候去滚动的scrollTop对比,相同为横向,不等则为纵向,

              实现代码1:

        //固定表头
        var beforscrollTop=$("#content")[0].scrollTop;
        $("#content").css("position","relative");
        $("#content").on('scroll',function(){
            var s=$(this)[0].scrollTop;
            buildEl3();
            if(s!==beforscrollTop){
                buildEl1();
            }else{
                buildEl2();
            }
            beforscrollTop=$(this)[0].scrollTop;
        })

            如果为纵向滚动找到页面中表头的部分进行克隆,设置克隆元素的宽度,

    /*固定表头*/
    function buildEl1(){
        var me=$("#content");
        var el1=me.find(".top-fixed");
        //判断是否有el
        if(!el1[0]){
            me.append("<div class='top-fixed' style='position:absolute;top:0'><table style='table-layout:fixed'></table></div>");
            var otbl=me.find(".otbl thead tr").children();
            //创建,找到表格的第一行进行克隆
            var $thead=me.find(".otbl thead").clone();
            $thead.find("tr").children().each(function(idx,ele){
                $(ele).each(function(i,e){
                    $(e).css("width",otbl.eq(idx).width()+1+"px");
                    $(e).css("height",otbl.eq(idx).height()+1+"px");
                })
            })
            $("#content").find('.top-fixed table').append($thead);
        }
        //就设置top值
        el1.css("top",me[0].scrollTop+"px")
    }

        第二部分:左边列

          实现过程:

            判断为纵向滚动时,找到需要固定的列,

              1、克隆整个表格的内容,依次遍历去掉不要固定的列(多列)

              2、找到第一列克隆,遍历克隆后的元素,在外层包上tr,因为不在一行(单列)outerHtml使用

          实现代码(以克隆整个表格为例):

    /*固定列*/
    function buildEl2(){
        var me=$("#content");
        var el2=me.find(".left-fixed");
        if(!el2[0]){
            me.append("<div class='left-fixed' style='position:absolute;top:0'><table style='table-layout:fixed'></table></div>");
            var otbl=me.find(".otbl tr>td:first-child");
            //复制整个表格的tr,将td>2的全部删除掉
            var newTr=$("#content").find(".otbl tr").clone();
            newTr.each(function(idx,ele){
                //原始的tr
                var _tr=$("#content").find(".otbl tr:eq("+idx+")");
                $(ele).children().each(function(i,e){
                    if(i<2){
                        //设置宽度
                        $(e).css("width",_tr.children().eq(i).width()+1+"px")
                        $(e).css("height",_tr.children().eq(i).height()+1+"px")
                    }else{
                        $(e).remove()
                    }
                })
            })
            me.find('.left-fixed table').append(newTr);
        }
        //就设置left值
        el2.css("left",me[0].scrollLeft+"px")
    }

        第三部分:顶部加左边

          实现代码(以克隆整个表格为例):

    function buildEl3(){
        var me=$("#content");
        var el3=me.find(".title-fixed");//不动的那块
        if(!el3[0]){
            me.append("<div class='title-fixed' style='position:absolute;top:0;left:0;background-color:#e4393c'><table style='table-layout:fixed'></table></div>");
            var $cloze=$("#content").find(".otbl thead tr>th:lt(2)").clone();
            var o=$("#content").find(".otbl thead tr>th:lt(2)");
            $cloze.each(function(idx,ele){
                $(ele).css("width",o.eq(idx).width()+1+"px");
                $(ele).css("height",o.eq(idx).height()+1+"px");
            })
            me.find('.title-fixed table').append($cloze);
        }
        el3.css("top",me[0].scrollTop+"px");
        el3.css("left",me[0].scrollLeft+"px");
        el3.css("z-index",999)
    }

       效果:

     

     代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        body{
            100%;
            height:100%;
            position:fixed;
            margin:0;
            padding:0;
        }
        #content{
            1000px;
            height:150px;
            margin:0 auto;
            border:1px solid #ddd;
            margin-top:20px;
            overflow:auto;
            position:relative
        }
        /*固定表头*/
        /*通用*/
        #content table th,#content table td{
            text-align:center;
            border:1px solid #ddd;
        }
        #content table{
            border-collapse:collapse;
            table-layout:fixed;
        }
        #content>table,#content .table-fixed table,.top-fixed table{
            700px;
        }
        #content>table th{
            100px;
        }
        #content .otbl thead tr:first-child{background-color:#e4393c}
        .table-fixed tr:first-child{background-color:#e4393c}
        #content .otbl tr td:nth-child(1),#content .otbl tr td:nth-child(2){background-color:#e4393c}
        .left-fixed,.top-fixed{background-color:#e4393c}
    </style>
    </head>
    <body>
    <div id="content">
        <table class="otbl">
            <thead>
                <tr>
                    <th>固定列</th>
                    <th>固定列</th>
                    <th>1</th>
                    <th>1</th>
                    <th>1</th>
                    <th>1</th>
                    <th>1</th>
                    <th>1</th>
                    <th>1</th>
                    <th>1</th>
                    <th>1</th>
                    <th>1</th>
                    <th>1</th>
                    <th>1</th>
                    <th>1</th>
                </tr>        
            </thead>
            <tbody>
                <tr>
                    <td>固定列</td>
                    <td>固定列</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                </tr>
                <tr>
                    <td>固定列</td>
                    <td>固定列</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                </tr>       
                <tr>
                    <td>固定列</td>
                    <td>固定列</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                </tr>  
                            <tr>
                    <td>固定列</td>
                    <td>固定列</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                </tr>  
                            <tr>
                    <td>固定列</td>
                    <td>固定列</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                </tr>  
                <tr>
                    <td>固定列</td>
                    <td>固定列</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                </tr> 
                <tr>
                    <td>固定列</td>
                    <td>固定列</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1</td>
                </tr> 
            </tbody>
        </table>
    </div>
    <script src="js/jquery-1.11.3.js"></script>
    <script>
    $(function(){
        //固定表头
        var beforscrollTop=$("#content")[0].scrollTop;
        $("#content").css("position","relative");
        $("#content").on('scroll',function(){
            var s=$(this)[0].scrollTop;
            buildEl3();
            if(s!==beforscrollTop){
                buildEl1();
            }else{
                buildEl2();
            }
            beforscrollTop=$(this)[0].scrollTop;
        })
    })
    /*固定表头*/
    function buildEl1(){
        var me=$("#content");
        var el1=me.find(".top-fixed");
        //判断是否有el
        if(!el1[0]){
            me.append("<div class='top-fixed' style='position:absolute;top:0'><table style='table-layout:fixed'></table></div>");
            var otbl=me.find(".otbl thead tr").children();
            //创建,找到表格的第一行进行克隆
            var $thead=me.find(".otbl thead").clone();
            $thead.find("tr").children().each(function(idx,ele){
                $(ele).each(function(i,e){
                    $(e).css("width",otbl.eq(idx).width()+1+"px");
                    $(e).css("height",otbl.eq(idx).height()+1+"px");
                })
            })
            $("#content").find('.top-fixed table').append($thead);
        }
        //就设置top值
        el1.css("top",me[0].scrollTop+"px")
    }
    /*固定列*/
    function buildEl2(){
        var me=$("#content");
        var el2=me.find(".left-fixed");
        if(!el2[0]){
            me.append("<div class='left-fixed' style='position:absolute;top:0'><table style='table-layout:fixed'></table></div>");
            var otbl=me.find(".otbl tr>td:first-child");
            //复制整个表格的tr,将td>2的全部删除掉
            var newTr=$("#content").find(".otbl tr").clone();
            newTr.each(function(idx,ele){
                //原始的tr
                var _tr=$("#content").find(".otbl tr:eq("+idx+")");
                $(ele).children().each(function(i,e){
                    if(i<2){
                        //设置宽度
                        $(e).css("width",_tr.children().eq(i).width()+1+"px")
                        $(e).css("height",_tr.children().eq(i).height()+1+"px")
                    }else{
                        $(e).remove()
                    }
                })
            })
            me.find('.left-fixed table').append(newTr);
        }
        //就设置left值
        el2.css("left",me[0].scrollLeft+"px")
    }
    function buildEl3(){
        var me=$("#content");
        var el3=me.find(".title-fixed");//不动的那块
        if(!el3[0]){
            me.append("<div class='title-fixed' style='position:absolute;top:0;left:0;background-color:#e4393c'><table style='table-layout:fixed'></table></div>");
            var $cloze=$("#content").find(".otbl thead tr>th:lt(2)").clone();
            var o=$("#content").find(".otbl thead tr>th:lt(2)");
            $cloze.each(function(idx,ele){
                $(ele).css("width",o.eq(idx).width()+1+"px");
                $(ele).css("height",o.eq(idx).height()+1+"px");
            })
            me.find('.title-fixed table').append($cloze);
        }
        el3.css("top",me[0].scrollTop+"px");
        el3.css("left",me[0].scrollLeft+"px");
        el3.css("z-index",999)
    }
    </script>
    </body>
    </html>
    View Code

    案例:

    区间能耗统计

    公共的方法:

    $(function(){
        var beforscrollTop=$(".scroll-tbl")[0].scrollTop;
        $('.scroll-tbl').on('scroll',function(){
            var top=$(this)[0].scrollTop;
            buildEl3();//不动的部分
            if(top!==beforscrollTop){
                buildEl1();//固定表头
            }else{
                buildEl2();//固定列
            }
            beforscrollTop=$(this)[0].scrollTop;
        });
        var Timer;
        $(window).resize(function(){
            Timer=setTimeout(function(){
                if(Timer){clearTimeout(Timer)}
                $('ul.th-fixed').each(function(index,ele){
                    setUlWidth($(ele),true);
                });
            },200);
        });
    })
    function buildEl1(){
        var me=$(".scroll-tbl");
        var el=me.find('ul.th-fixed');
        if(!el[0]){return false}
        setUlWidth(el,el.next()[0].offsetWidth!=el[0].offsetWidth);
        if(el.css('display')!=='block'){el.show();}
        el.css('top',me[0].scrollTop+"px");    
    }
    function setUlWidth(el,t){
        if(!t){return false;}
        el.css('width',el.next()[0].offsetWidth+'px');
        el.find('li').each(function(i,e){
            var w=el.next().find('thead>tr>th');
            $(e).css('width',w[i].offsetWidth+'px');
            $(e).css('height',w[i].offsetHeight+'px');
        });
    }
    
    function buildEl2(){
        var me=$(".scroll-tbl");
        var el2=me.find(".left-fixed");
        if(!el2[0]){
            me.append("<div class='left-fixed' style='position:absolute;'><table class='table table-striped table-bordered g-tbl' style='table-layout:fixed;60px'></table></div>");
            //设置top值
            var h=$(".scroll-tbl").find("thead th:first").css("height");
            $(".scroll-tbl").find(".left-fixed").css("top",h)
            //复制整个表格的tr,遍历,将大于第一列的删除掉
            //var newTr=$("#content-tbl").find("tr").clone();
            var newTd=$("#tbl").find("tr>td:first-child").clone();
            var oTd=$("#tbl").find("tr>td:first-child")
            //设置td的宽度
            var str="";
            newTd.each(function(i,e){
                $(e).css("width",oTd.eq(i).css('width'));
                $(e).css("height",oTd.eq(i).css('height'));
                str+='<tr>'+e.outerHTML+'</tr>';
            })
            me.find('.left-fixed table').append(str);
        }
        //就设置left值
        me.find(".left-fixed").css("left",(me[0].scrollLeft)+"px")
    }
    function buildEl3(){
        var me=$(".scroll-tbl");
        var el3=me.find(".title-fixed");//不动的那块    
        if(!el3[0]){
            me.append("<div class='title-fixed' style='position:absolute;top:0;left:0'><table style='table-layout:fixed'></table></div>");
            var $cloze=me.find("thead tr:first").clone();
            var o=me.find("thead tr:first");
            $cloze.children().each(function(idx,ele){
                if(idx==0){
                    var _boxType=o.children().eq(idx).css("box-sizing")//此处很重要
                    if(_boxType=="border-box"){
                        var pl=parseInt(o.children().eq(idx).css("padding-left"));
                        var pr=parseInt(o.children().eq(idx).css("padding-right"));
                        var bl=parseInt(o.children().eq(idx).css("border-right"));
                        var br=parseInt(o.children().eq(idx).css("border-right"));
                        $(ele).css("width",o.children().eq(idx).width()+pl+pr+bl+br+"px");
                        $(ele).css("height",o.children().eq(idx).height()+"px");
                    }else{
                        $(ele).css("width",o.children().eq(idx).width()+"px");
                        $(ele).css("height",o.children().eq(idx).height()+"px");
                    }
                }else{
                    $(ele).remove();
                }
            })
            me.find('.title-fixed table').append($cloze);
        }
        $(".scroll-tbl").find(".title-fixed").css("top",me[0].scrollTop+"px");
        $(".scroll-tbl").find(".title-fixed").css("left",me[0].scrollLeft+"px");
        $(".scroll-tbl").find(".title-fixed").css("z-index",999)
    }

    实现过程类似上面,但是中间出现了一系列的问题,总结如下:

    1、克隆的时候只能克隆属性,克隆不了样式,样式的问题自己慢慢调试了

    2、为克隆元素设置宽度的时候,特别需要注意,否则因为宽度问题会错位,上图因为是表格的原因,宽度有自己的计算方法

      在添加固定的第二块的时候(滚动一直固定的),当用户在左侧选中很多项的时候不会出现问题,但是如果用户选中的只有两三个的时候,问题就层现了

    问题分析:

      因为克隆之后设置宽度时,此处的盒子模型为border-box,所以元素设置宽度的时候还需要加上元素的padding,border等

      原先错误的写法

            $cloze.children().each(function(idx,ele){
                if(idx==0){
                    $(ele).css("width",o.children().eq(idx).width()+"px");
                    $(ele).css("height",o.children().eq(idx).height()+"px");
                }else{
                    $(ele).remove();
                }
            })

    正确的写法,还需改成float

            $cloze.children().each(function(idx,ele){
                if(idx==0){
                    var _boxType=o.children().eq(idx).css("box-sizing")//此处很重要
                    if(_boxType=="border-box"){
                        var pl=parseInt(o.children().eq(idx).css("padding-left"));
                        var pr=parseInt(o.children().eq(idx).css("padding-right"));
                        var bl=parseInt(o.children().eq(idx).css("border-right"));
                        var br=parseInt(o.children().eq(idx).css("border-right"));
                        $(ele).css("width",o.children().eq(idx).width()+pl+pr+bl+br+"px");
                        $(ele).css("height",o.children().eq(idx).height()+"px");
                    }else{
                        $(ele).css("width",o.children().eq(idx).width()+"px");
                        $(ele).css("height",o.children().eq(idx).height()+"px");
                    }
                }else{
                    $(ele).remove();
                }
            })

    0920修改:

    问题一:左侧固定列的时候将页面缩小至一定的宽度时,然后横向拖动,这时候问题就出来了,如下

    原因分析:是因为表格的宽度超过了页面的宽度,但是为什么会超过呢?这个问题当时也纠结了很久,发现时因为table的宽度加上滚动的设置了左侧列的left值加起来超过了页面的宽度,当页面宽度超过时,没有没有设置宽度,table-layout:fixed不会生效,按照表格的生成原理,表格就会进行压缩,所以就呈现出上图现象

    解决办法;

      第一种:为表格设置一个固定宽度,让属性table-layout:fixed生效

        找到第一行中固定列的th,循环遍历加起来得出宽度

      第二种:li元素模拟

        将克隆列改成li模拟,找到所有的需要固定列的th,循环构建li,同时设置样式,

         注意:

          1、li需要浮动,ul要设置一个宽度,宽度得到方法如上

          2、设置样式,li的内容溢出同时需要垂直居中,解决办法查找随笔“css分类”

      实例代码(参考)

    /**
     * 左边列固定(元素模拟的方式)
     */
    function buildEl2(){
        var me=$("#tblForm");
        var el2=me.find(".left-fixed1");
        var w=0;//为坐标的固定部分设置宽度限制
        var $tr='';
        var str='';
        if(!el2[0]){
            me.append("<div class='left-fixed1' style='position:absolute;top:0'><ul></ul></div>");
            //找到所有的th,遍历th直接构建li
            var newTh=$("#content-tbl").find("th");
            newTh.each(function(idx,ele){
                var w=$(ele).width()+'px',h=$(ele).height()+'px',t=$(ele).text();
                str+="<li style='"+w+";height:"+h+";'><span>"+t+"</span></li>";
            })
            var _tr=$("#content-tbl th:first");
            if(_tr.next().next().next()[0].nodeName=='TD'){//为什么加了两个next,因为9月19号加了固定两列,
                $tr=_tr.parent();
            }else{
                $tr=_tr.parent().next();
            }
            //遍历得出ul的宽度
            $tr.find("th").each(function(idx,ele){
                w+=$(ele).width();
            })
            me.find('.left-fixed1').css('width',w+4+'px');
            me.find('.left-fixed1 ul').append(str);
            $("#tblForm").find(".left-fixed1").css("left",me[0].scrollLeft+"px")
        }else{
            //就设置left值
            $("#tblForm").find(".left-fixed1").css("left",me[0].scrollLeft+"px")
        }
    }

    样式:

    #tblForm .left-fixed1 ul{
        border-top:1px solid #A3C0E8;
        border-left:1px solid #A3C0E8;
    }
    #tblForm .left-fixed1 li{
        
        text-align: center;
        list-style: none;
        word-break: normal;
        font-size:14px;
        padding:8px 0px 8px 0px;
        background-color:#E2F0FF;
        float:left;
        border-right:1px solid #A3C0E8;
        border-bottom:1px solid #A3C0E8;
    }
    #tblForm .left-fixed1 li>span{
         display:inline-block;
         vertical-align:middle; 
    }
    #tblForm .left-fixed1 li::before{
        content:'';
        display:inline-block;
        height:100%;
        vertical-align: middle;
    }

    效果:

      最后当浏览器触发了resize事件的时候,记得重新构建依次三块

        var Timer;
        $(window).resize(function(){
            Timer=setTimeout(function(){
                if(Timer){clearTimeout(Timer)}
                //清空所有的固定部分重新构建
                var el1=$('#tblForm').find(".h-fixed");//表头
                var el2=$('#tblForm').find(".left-fixed");;//
                //两种方法构建,克隆和元素li模拟
                var el3=$('#tblForm').find(".title-fixed");//不动的那块(克隆)
                if(el1[0]){el1.remove()}
                if(el2[0]){el2.remove()}
                if(el3[0]){el3.remove()}
                buildEl1()
                buildEl2()
                buildEl3()
            },200)
        });
  • 相关阅读:
    Single Threaded Execution
    多线程(第三天)
    多线程(第二天)
    IE中float:right单独一行
    web.xml配置
    java调用asmx的webservice
    跨域访问
    jsp页面导入jstl标签
    搜索dwr做即时聊天的时候看到的问题
    LigerUI tree在ie下显示不出来/LigerUI 控件在ie下错乱
  • 原文地址:https://www.cnblogs.com/pengfei25/p/9580356.html
Copyright © 2020-2023  润新知