做了好几天的固定表头特效,总算是搞定了。先说明一下基本功能:我们在一个网页上浏览很多份表格数据的时候,肯定会碰到很多分不清表头,也分不清表 格是哪个的情况,这个时候我们就希望能有一种功能,就是我们再下拉滚动条的时候,表格的表头固定住。这样对付只有一张表格的网页还好,如果表格多了,又会 很麻烦。我做的这个特效综合了固定表格表头的功能,同时,还能在浏览不同表格时候,切换固定的表头。效果如图所示:

网页上有两个表格

拉动滚动条,固定第一个表格的表头

继续拉动滚动条,切换并到第二个表格的表头

我 在做这个特效的时候,首先考虑的是怎样固定住表头。在网上搜到一个不错的固定表头Jquery插件-chromatable。基本的思路都一样,就是现将 整个表格复制一遍,然后将表头和表身分离,分别用div包住,设置好表身最大的高度,并显示滚动条,在拉动滚动条时,表头因为已经和表身分离,所以不会随 着页面下拉而滚动。我将这个插件重写了一遍,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
(function ($) {
$.fn.extend({
ScrollTable: function (options) {
var defaults = {
MaxHeight: 600,
MaxDataItemIndex: 1 // 固定前MaxDataItemIndex作为固定表头
};
options = $.extend(defaults, options);
return this.each(function () {
var $this = $(this);
//设置表格自动换行
$this.css({"table-layout":"fixed"});
$this.find('td').css({"word-break":"break-all","word-wrap":"break-word"});
// 产生表头部分和身体部分
var $cloneTableHeader = $this.clone();
var $cloneTableBody = $this.clone();
$cloneTableHeader.find("tr").filter(function (index) {
return index >= options.MaxDataItemIndex
}).remove();
$cloneTableBody.find("tr").filter(function (index) {
return index < options.MaxDataItemIndex
}).remove();
//设置单元格边框
$cloneTableHeader.find("tr").css({"border":"1px blue solid"});
$cloneTableBody.find("td").css({"border":"1px blue solid"});
// 将产生的表头和身体部分放入Container,并做一些微调
$this.after("<div class='ScrollTableContainer' style='border:1px solid;margin:10px 0;'></div>");
$this.next().append($cloneTableHeader);
$this.next().append("<div class='ScrollDiv' style='overflow-y:scroll;'></div>");
$this.next().css("width", $this.width());
$this.next().find("div.ScrollDiv").css({
"max-height": options.MaxHeight,
"margin-top": -2
});
$this.next().find("div.ScrollDiv").append($cloneTableBody);
$this.remove();
});
}
});
})(jQuery)

接下来,我在网上搜了一下怎样固定,同时切换块级元素。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<script>
$(function () {
//设置内容块的宽度与导航块的宽度一样
$(".Xc_list_top").css("width",$(".Xc_list_main").width());
var resetRightPanelPostion = function () {
  //在JQuery中,可以利用导航工具类$.browser来判断浏览器类型
  var msie6 = $.browser.msie && $.browser.version == '6.0' && $.browser.version < 7;
  //获取body元素标签
  if ($.browser.safari) {
    bodyelem = $("body");
  } else {
    bodyelem = $("html,body");
  }
  //$(selector).scrollTop(offset),offset是相对滚动条顶部的偏移,以像素计。获取滚动条距离顶部的距离。
  var bodyTop = bodyelem.scrollTop();
  //offset() 方法返回或设置匹配元素相对于文档的偏移(位置)。这里是获取相对于文档的顶部偏移。
  var top = $(".Xc_left").offset().top;
  //var t = $("#public_footer").offset().top;
  var t = $("#footerDestinationBox").offset().top;
  //var bottom = $("#footerDestinationBox").offset().top;
  //循环遍历class为Xc_list_top的数组的成员
  for(var i = 0; i < $(".Xc_list .Xc_list_top").length ; i++){
    /*标准浏览器下:
    height:高度
    innerHeight:高度+补白
    outerHeight:高度+补白+边框,参数为true时:高度+补白+边框+边距*/
    //当滚动条向下移动的偏移量大于等于元素相对文档顶部的偏移量时(即左边的div顶部接触到窗口顶部)
    //滚动条往下拉动的距离等于底部相对顶部偏移量不断减少的距离,所以
    //bodyTop = t - $("#footerDestinationBox").offset().top
    //当底部div距离顶部的长度等于左边div的
    //outheight = $("#footerDestinationBox").offset().top时,
    //底部与$('.Xc_left')接触
    //所以(bodyTop + $(".Xc_left").outerHeight())<t)指底部的div还没有将左边的div完全顶出。
if (bodyTop >= top && ((bodyTop + $(".Xc_left").outerHeight()) < t)) {
//如果ie浏览器的版本不是6或6以下
  if (!msie6) {
    if (bodyTop + $(".Xc_gg").outerHeight() >= t) {
        $(".Xc_gg").removeClass('fixed').css({
           "position": "absolute",
           "top": t - $(".Xc_gg").outerHeight() + "px"
        });
    } else {
        $(".Xc_gg").css({
           "position": "fixed",
           "top": 0
        });
    }
  }
} else {
  if (!msie6) {
    $(".Xc_gg").css({
    "position": "static"
  });
  }
}
/*if(bodyTop>$(".Xc_list").eq(i).offset().top){
  $(".Xc_list_top").eq(i).css({position:"absolute",top:top-168});
}*/
   if(bodyTop>$(".Xc_list").eq(i).offset().top){
     $(".Xc_list_top").eq(i).css({position:"fixed",top:0});
   }
   if(bodyTop<=$(".Xc_list").eq(i).offset().top){
     $(".Xc_list_top").eq(i).css({position:"static",top:0});
   }
 }
};
window.onload = function () {
//判断div.Xc_gg是否存在
if ($(".Xc_gg").length) {
  resetRightPanelPostion();
   $(window).scroll(function () {
      resetRightPanelPostion();
   });
  }
}
})
</script>

最后,综合上面的两种功能,先修改插件chromatable中的代码,将 "$this.next().append("<div class='ScrollDiv' style='overflow-y:scroll;'></div>");"

这一行代码中的style='overflow-y:scroll'样式去掉,这样就不会出现滚动条。然后,将头部的代码包裹在一个class属性
为'ScrollHeader'的div中。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
(function ($) {
    $.fn.extend({
      ScrollTable : function(options){
          var defaults = {
             // SwitchTag : 'tr', //默认表头标签为tr
              MaxHeight : 400,
              MaxDataItemIndex : 1   //固定前多少列为表头
          };
          options = $.extend(defaults,options);
          return this.each(function(){
              var $this = $(this);
              //设置表格内容自动换行
              $this.css({ "table-layout" : "fixed" });
              $this.find('td').css({"word-break":"break-all","word-wrap":"break-word"});
                // 产生表头部分和身体部分
              // 复制表格内容
              var $newTableHeader = $this.clone();
              var $newTableBody = $this.clone();
              // 产生表头部分和身体部分,filter()遍历并根据参数做为选择器来筛选。
              $newTableHeader.find("tr").filter(function(index){
                   return index >= options.MaxDataItemIndex
              }).remove();
              $newTableBody.find("tr").filter(function(index){
                   return index < options.MaxDataItemIndex
              }).remove();
              //设置单元格边框
              $newTableHeader.find("tr").css({"border":"1px blue solid"});
              $newTableBody.find("td").css({"border":"1px blue solid"});
         // 将产生的表头和身体部分放入Container
         $this.after("<div class='ScrollTableContainer' style='border:1px solid;margin:10px 0;'></div>");
              $this.next().append("<div class='ScrollHeader'></div>");
              //$this.next().append($newTableHeader);
              $this.next().append("<div class='ScrollDiv'></div>");
              $this.next().css("width", $this.width());
              //将表头部分添加到class属性为ScrollHeader的div元素中
             $this.next().find("div.ScrollHeader").append($newTableHeader);
              $this.next().find("div.ScrollDiv").css({
                    "max-height": options.MaxHeight,
                    //"margin-top": -2
                });
              $this.next().find("div.ScrollDiv").append($newTableBody);
              $this.remove();
        });
      }
    });
})(jQuery);

接着,我们还要将切换代码写进去,我们来到表格页面,加入以下jquery代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
    <script src="./jquery.chrometable.js"></script>
    <script>
        $(function(){
            $('table').ScrollTable();
<span style="text-decoration: underline;"><span style="color: #ff0000; text-decoration: underline;">//$(window).scroll(function(){}),当鼠标拖动滚动条时触发一次该函数,如果不这样写,就无法动态地获取bodyTop,
//也就是滚动条距离顶部距离的值。但是如果不断地触发ScroolTable()会造成脚本运行错乱。</span></span>
            //单独将动态获取bodyTop写成一个函数。
            var bodyTop = function(){
                //获取body元素标签
                if ($.browser.safari) {
                    bodyelem = $("body");
                }else {
                    bodyelem = $("html,body");
                }
                //获取滚动条与body元素顶部的距离
                var bodyTop = bodyelem.scrollTop();
                var num = $(".ScrollTableContainer .ScrollHeader").length;
                //循环遍历class为ScrollTableContainer的div成员,即遍历多个表格table元素中的表头
                for(var i = 0;i<num;i++){
                    if(bodyTop >$(".ScrollTableContainer").eq(i).offset().top){
                        $(".ScrollHeader").eq(i).css({position:"fixed",top:0,backgroundColor:"red"});
                    }
                    if(bodyTop <=$(".ScrollTableContainer").eq(i).offset().top){
                        $(".ScrollHeader").eq(i).css({position:"static",top:0});
                    }
                }
            }
            $(window).scroll(function () {
                bodyTop();
            });
        })
    </script>

最后,我在这里要说明以下我犯的两个小错误,第一个就是在写Jquery代码时,将固定格式:

1
(function($){})(jQuery)

中的"jQuery"写成了Jquery,耗了我很多精力去排错!

jQuery(function(){ });用于存放操作DOM对象的代码,执行其中代码时DOM对象已存在。不可用于存放开发插件的代码,因为jQuery对象没有得到传递,外部通过jQuery.method也调用不了其中的方法(函数)。
(function(){ })(jQuery);用于存放开发插件的代码,执行其中代码时DOM不一定存在,所以直接自动执行DOM操作的代码请小心使用。


二个就是,我刚刚开始把切换表头的代码写在插件文件一起,发现bodyTop的值一直没有变过,只有刷新一下才能实现功能,原来是要加入滚动条事件来不断
触发函数保证动态获取滚动条鼓励顶部的值bodyTop。但是,一定要将这个函数分离出来,如果写在一起,就会让整个固定表头的脚本也随着滚动条的拖动而
不断运行。

最后,将上面的三个例子全部都共享出来给大家下载。

DEMO下载地址>>(说明:demo1:表头固定插件,demo2:切换和固定div,demo3:切换和固定表头。)

jQuery制作多表格固定表头、切换表头的特效的更多相关文章

  1. 纯css实现table表格固定列和表头,中间横向滚动的思路-附案例

    最近做的后台管理系统要处理大量的表格 原项目是采用的for循环加拼接字符串的方式实现;导致js代码一大堆;各种单引号和双引号的嵌套;让人头疼;遂引入vue.js;用v-for做模板渲染;工作量顿时减轻 ...

  2. jQuery制作table表格布局插件带有列左右拖动效果

    压缩包:http://www.xwcms.net/js/bddm/99004.html

  3. jQuery手机触屏左右滑动切换焦点图特效代码

    原文地址:http://www.17sucai.com/pins/4857.html 演示地址:http://www.17sucai.com/pins/demoshow/4857 干净演示地址:htt ...

  4. bootstrap table 实现固定悬浮table 表头并可以水平滚动

    在开发项目中,需要将表格头部固定,而且表格大多数情况下是会水平滚动的.项目的css框架是bootstrap 3,故也可以叫做bootstrap table. 需要实现的是:表格头部固定,并且支持水平滚 ...

  5. jquery datatable设置垂直滚动后,表头(th)错位问题

    jquery datatable设置垂直滚动后,表头(th)错位问题 问题描述: 我在datatable里设置:"scrollY": '300px',垂直滚动属性后,表头的宽度就会 ...

  6. (转)supertable像excel那样固定table的表头和第一列

    <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"/> <title> ...

  7. ElementUI2.0组件库el-table表格组件如何自定义表头?

    效果图: npm run dev 编译项目之后,报错,要使用jsx语法需要先安装编译插件 1.安装下列安装包 npm install babel-plugin-syntax-jsx --save-de ...

  8. jquery 动态添加表格行

    jquery 动态添加表格行 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <h ...

  9. JQuery制作网页——第五章 初识 jQuery

    1.jQuery简介: ● jQuery由美国人John Resig于2006年创建 ● jQuery是目前最流行的JavaScript程序库,它是对JavaScript对象和函数的封装 ● 它的设计 ...

随机推荐

  1. MVC、MVP、MVVM、Angular.js、Knockout.js、Backbone.js、React.js、Ember.js、Avalon.js、Vue.js 概念摘录

    注:文章内容都是摘录性文字,自己阅读的一些笔记,方便日后查看. MVC MVC(Model-View-Controller),M 是指业务模型,V 是指用户界面,C 则是控制器,使用 MVC 的目的是 ...

  2. .NET程序员转Java不完全指南

    首先要声明一点,“转”字并不包含那种语言牛B的意思. 然后要声明一点,“转”字仅限于企业应用开发的语言的转. 假设各种数据库切换无代沟, 假设各种WEB客户端技术无障碍. 1.搭建环境,IDE主流是e ...

  3. java 静态函数锁对象说明

    在内存加载.class文件后,会自动创建一个对象,用于保存class的信息,与我们程序员手工创建的对象不一样.

  4. Android 主题和选择器

    今天在做底部tab的时候因为样式都一样 所以就自定义一个style 这样省的写很多重复的样式(懒懒懒懒), 修改的话直接在样式里修改省去一个一个修改一样的代码 1 在values/styles.xml ...

  5. Codeforces Beta Round #2B(dp+数学)

    贡献了一列WA.. 数学很神奇啊 这个题的关键是怎么才能算尾0的个数 只能相乘 可以想一下所有一位数相乘 除0之外,只有2和5相乘才能得到0 当然那些本身带0的多位数 里面肯定含有多少尾0 就含有多少 ...

  6. 当xcode里点运行出现treating unicode character as whites

    可能是由于粘贴网页上的代码的时候两行之间的回车引起的,两行之间重新输入回车就行......删掉重新写一遍就ok了 引入网页上的回车时  可能  网页对其格式做了处理,所以Xcode  不认识了

  7. [转] IPC之管道、FIFO、socketpair

    管道和FIFO作为最初的UNIX IPC形式,现在已用得较少.SocketPair可作为全双工版本的管道,较为常用,这里简单做个笔记 管道 * 只用于有亲缘关系的进程间通信 * 单向,即半双工 (双向 ...

  8. kvm虚拟机中鼠标不同步的问题解决方法

    环境:Centos7.6安装kvm创建windows虚拟机,通过novnc连接到虚拟机上发现存在鼠标位置偏移问题 解决方法: 方法一: 经测试,windows系列虚拟机关闭鼠标加速亦可缓解该问题,不过 ...

  9. SQL Server 连接(内连接,外连接,完全连接,交叉连接,联合)

    1.连接 有时候需要将连个表的数据合并成一个结果集来显示.为了解决这个问题,就需要用到JOIN连接. 2.内部连接 内部连接根据一个或几个共同的字段将记录匹配到一起.内部连接仅仅返回那些存在字段匹配的 ...

  10. HTML5无刷新修改URL

    HTML5新添加了两个api分别是pushState和replaceState,DOM中的window对象通过window.history方法提供了对浏览器历史记录的读取,可以在用户的访问记录中前进和 ...