文档章节

浏览器兼容的实现table中通过拖拽改变列宽的最佳实践

李玉珏
 李玉珏
发布于 2015/04/01 17:41
字数 1174
阅读 1647
收藏 12
点赞 1
评论 1

        在企业级应用中,表格是非常常见的展现方式,这时当列数据较长时,一种比较自然,体验也较好的处理方式就是通过拖拽改变列宽,这个功能在一些重量级JS组件库中都有提供,实现原理各有不同,但是一个共同点就是实现比较复杂,那我们通过很少的代码,常规的table结构,能实现这个功能么?本文将提供一个经过实际验证的实践,供开发者参考,扩展思路。

        总体思路:

        1.HTML结构:

                为了简化代码,采用标准的HTML结构,即table-tr-td模式,无其他限制,在我们的实际应用中,表格非常复杂,但是核心技术没有变;

        2.事件:

                采用onmousedown、onmousemove、onmouseup三个事件相结合的方式,处理鼠标拖动元素过程中的事件;

        3.浏览器兼容:

                整个实现中,涉及到事件模型,offsetX偏移量计算等存在浏览器差异的情况,本文都提供了精炼的处理,并经过了测试;

        4.列宽度计算:

                拖动改变列宽的核心算法是,鼠标移动过程中计算鼠标在屏幕上滑动过的水平距离,可能是正值可能为负,然后加上单元格原来的宽度,计算得出新的宽度;

        5.边界才可拖动并改变光标样式:

                这个是通过元素的offsetWidth和offsetX数据计算得出,只有在光标位于边框线两侧4px范围内的区域,才可以拖动,并且改变光标样式;

        下面附上代码,供开发者参考:

<!DOCTYPE html PUBLIC "-//W4C//DTD XHTML 1.0 Transitional//EN" "http://www.w4.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
    <META http-equiv=ontent-Type content="text/html; charset=gb2312">
</head>
<table id="tbl" cellspacing="1" cellpadding="5" bgcolor=#660000>
    <tr><td nowrap bgcolor=#bbbbbb style="white-space:nowrap;width:100px">标题一</td><td nowrap bgcolor=#bbbbbb style="white-space:nowrap;;width:100px">标题二</td><td  nowrap bgcolor=#bbbbbb style="width:100px" >标题三</td><td nowrap bgcolor=#bbbbbb style="width:100px" >标题四</td></tr>
    <tr><td bgcolor=#ffffff>内容A</td><td bgcolor=#ffffff>内容B</td><td bgcolor=#ffffff>内容C</td><td bgcolor=#ffffff>内容D</td></tr>
    <tr><td bgcolor=#ffffff>内容A</td><td bgcolor=#ffffff>内容B</td><td bgcolor=#ffffff>内容C</td><td bgcolor=#ffffff>内容D</td></tr>
    <tr><td bgcolor=#ffffff>内容A</td><td bgcolor=#ffffff>内容B</td><td bgcolor=#ffffff>内容C</td><td bgcolor=#ffffff>内容D</td></tr>
    <tr><td bgcolor=#ffffff>内容A</td><td bgcolor=#ffffff>内容B</td><td bgcolor=#ffffff>内容C</td><td bgcolor=#ffffff>内容D</td></tr>
    <tr><td bgcolor=#ffffff>内容A</td><td bgcolor=#ffffff>内容B</td><td bgcolor=#ffffff>内容C</td><td bgcolor=#ffffff>内容D</td></tr>
    <tr><td bgcolor=#ffffff>内容A</td><td bgcolor=#ffffff>内容B</td><td bgcolor=#ffffff>内容C</td><td bgcolor=#ffffff>内容D</td></tr>
    <tr><td bgcolor=#ffffff>内容A</td><td bgcolor=#ffffff>内容B</td><td bgcolor=#ffffff>内容C</td><td bgcolor=#ffffff>内容D</td></tr>
</table>

        可以看到,HTML非常简单。

<script language="javascript">
var headerTds = document.getElementById("tbl").rows[0].cells;
var mousedown = false;
var resizeable = false;
var targetTd;
var screenXStart =0;
var tdWidth = 0;
var headerWidth = 0;
var tblObj = document.getElementById("tbl");
for(var i = 0;i<headerTds.length;i++){
    addListener(headerTds[i],"mousedown",onmousedown);
    addListener(headerTds[i],"mousemove",onmousemove);
}
function onmousedown(event){
    if (resizeable == true){
        var evt =event||window.event;
        mousedown = true;
        screenXStart = evt.screenX;
        tdWidth = targetTd.offsetWidth;
        headerWidth = tblObj.offsetWidth;
    }
}
function onmousemove(event){
    var evt =event||window.event;
    var srcObj = getTarget(evt);
    var offsetX = evt.offsetX || (evt.clientX - srcObj.getBoundingClientRect().left);//这个比较关键,解决了Firefox无offsetX属性的问题
    if (mousedown == true){
        var width = (tdWidth + (evt.screenX - screenXStart)) + "px";//计算后的新的宽度
        targetTd.style.width = width;
        tblObj.style.width = (headerWidth + (evt.screenX - screenXStart)) + "px";
    }else{
        var trObj = tblObj.rows[0];
        if(srcObj.offsetWidth - offsetX <=4){//实际改变本单元格列宽
            targetTd=srcObj;
            resizeable = true;
            srcObj.style.cursor='col-resize';//修改光标样式
        }else if(offsetX <=4 && srcObj.cellIndex > 0){//实际改变前一单元格列宽,但是表格左边框线不可拖动
            targetTd=trObj.cells[srcObj.cellIndex - 1];
            resizeable = true;
            srcObj.style.cursor='col-resize';
        }else{
            resizeable = false;
            srcObj.style.cursor='default';
        }
    }
}
document.onmouseup = function(event){
    tartgetTd = null;
    resizeable = false;
    mousedown = false;
    document.body.style.cursor='default';
}
function getTarget(evt){
    return evt.target || evt.srcElement;
}
function addListener(element,type,listener,useCapture){
    element.addEventListener?element.addEventListener(type,listener,useCapture):element.attachEvent("on" + type,listener);
}
</script>

        上述代码非常精炼的实现了拖拽改变列宽的功能,经过测试,兼容IE8以上、Firefox、Chrome等主流浏览器。

© 著作权归作者所有

共有 人打赏支持
李玉珏

李玉珏

粉丝 262
博文 57
码字总数 92143
作品 0
沈阳
技术主管
加载中

评论(1)

ejzhang
ejzhang
79
15款提高表格操作的jQuery插件

table表格由于它的浏览器兼容性和复杂的标签嵌套方式,可以算是添加样式最困难的对象之一了。大多数前端er都把网页中的table标签替换为div,主要就是因为div要比table更容易添加CSS样式。但是...

鉴客 ⋅ 2010/08/12 ⋅ 1

拭目以待/GridManager

GridManager.js 文档及演示 文档 演示 使用需知 下载时请选择对应的tag进行下载, 请不要直接使用master分支上的代码. v2.0和之前版本为jquery版本 v2.1开始为原生js版本 实现功能 GridManage...

拭目以待 ⋅ 2016/08/28 ⋅ 0

快速、灵活的对Table标签进行实例化,让Table标签充满活力。 - GridManager.js

GridManager特色: 原生实现: 无任何框架依赖 宽度调整: 表格的列宽度可进行拖拽式调整 位置更换: 表格的列位置进行拖拽式调整 配置列: 可通过配置对列进行显示隐藏转换 表头吸顶: 在表存在可...

拭目以待 ⋅ 2015/06/12 ⋅ 8

idialog & idrag

iDrag & iDialog 介绍 特点: iDialog.js 依赖于 jquery 编写的简单易用的对话框,同时还可以通过添加css3,改变对话框的展现动画。 提供了两个方法: 1、拖拽函数 iDrag() 或 $.drag(); 2、...

孟回头 ⋅ 2013/12/26 ⋅ 0

JqueryMobile实践点滴

最近在用JqueryMobile写点东西,就遇到的一些小问题加以记录,也希望能帮到遇到相同问题的朋友。 1、动态改变图标data-icon,这个只是改变data-icon属性是不行的,之所以会有图标是因为jquer...

Bingo许 ⋅ 2013/05/16 ⋅ 0

原生Javascript+HTML5一步步实现拖拽排序

前言 本文的内容就如题所述,之所以写这么个东西是有原因的,因为这两天重做公司的一个功能发现里面需要一个拖拽排序的功能.以前都是使用jquery各种插件去搞,因为这个项目不限制浏览器兼容问题...

顽Shi ⋅ 2014/04/05 ⋅ 6

GridView鼠标拖拽改变列宽

晨曦之光 ⋅ 2012/05/16 ⋅ 0

Datatables笔记

1.若对Datatables提供的css不够满意,可以自己修改page.css和table.css. 比如,单元格的内容过多会导致自动换行,我修改成了过多内容以省略号代替,同时增加了left类: table.css table.disp...

叶落花开 ⋅ 2012/02/11 ⋅ 0

使用 JavaScript File API 实现文件上传

File API 是 Mozilla 向 W3C 提出的一个草案,旨在用标准 JavaScript API 实现本地文件的读取。File API 将极大地方便 Web 端的文件上传等操作,并有望成为未来的 HTML 5 规范的一部分。本文...

红薯 ⋅ 2011/01/24 ⋅ 6

Google HTML5训练营:图片旋转墙

六月末,第一次去参加Google的HTML5训练营,估计其他同学多少都接触过。从下午一点到晚上10点,将近9个小时的时间里,首先由杜欢、寒蕊、胡坤做了一些技术上的分享,我对Google工程师寒蕊MM的...

冯尚实 ⋅ 2011/07/15 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

大数据工程师需要精通算法吗,要达到一个什么程度呢?

机器学习是人工智能的一个重要分支,而机器学习下最重要的就是算法,本文讲述归纳了入门级的几个机器学习算法,加大数据学习群:716581014一起加入AI技术大本营。 1、监督学习算法 这个算法由...

董黎明 ⋅ 25分钟前 ⋅ 0

Kylin 对维度表的的要求

1.要具有数据一致性,主键值必须是唯一的;Kylin 会进行检查,如果有两行的主键值相同则会报错。 2.维度表越小越好,因为 Kylin 会将维度表加载到内存中供查询;过大的表不适合作为维度表,默...

无精疯 ⋅ 28分钟前 ⋅ 0

58到家数据库30条军规解读

军规适用场景:并发量大、数据量大的互联网业务 军规:介绍内容 解读:讲解原因,解读比军规更重要 一、基础规范 (1)必须使用InnoDB存储引擎 解读:支持事务、行级锁、并发性能更好、CPU及...

kim_o ⋅ 31分钟前 ⋅ 0

代码注释中顺序更改 文件读写换行

`package ssh; import com.xxx.common.log.LogFactory; import com.xxx.common.log.LoggerUtil; import org.apache.commons.lang3.StringUtils; import java.io.*; public class DirErgodic ......

林伟琨 ⋅ 39分钟前 ⋅ 0

linux实用操作命令

参考 http://blog.csdn.net/qwe6112071/article/details/50806734 ls [选项] [目录名 | 列出相关目录下的所有目录和文件 -a 列出包括.a开头的隐藏文件的所有文件-A 同-a,但不列出"."和"...

简心 ⋅ 55分钟前 ⋅ 0

preg_match处理中文符号 url编码方法

之前想过直接用符号来替换,但失败了,或者用其他方式,但有有些复杂,这个是一个新的思路,亲测可用 <?php$str='637朗逸·超速新风王(300)(白光)'; $str=iconv("UTF-8","GBK",$s...

大灰狼wow ⋅ 今天 ⋅ 0

DevOps 资讯 | PostgreSQL 的时代到来了吗 ?

PostgreSQL是对象-关系型数据库,BSD 许可证。拼读为"post-gress-Q-L"。 作者: Tony Baer 原文: Has the time finally come for PostgreSQL?(有删节) 近30年来 PostgreSQL 无疑是您从未听...

RiboseYim ⋅ 今天 ⋅ 0

github太慢

1:用浏览器访问 IPAddress.com or http://tool.chinaz.com 使用 IP Lookup 工具获得github.com和github.global.ssl.fastly.net域名的ip地址 2:/etc/hosts文件中添加如下格式(IP最好自己查一...

whoisliang ⋅ 今天 ⋅ 0

非阻塞同步之 CAS

为解决线程安全问题,互斥同步相当于以时间换空间。多线程情况下,只有一个线程可以访问同步代码。这种同步也叫阻塞同步(Blocking Synchronization). 这种同步属于一种悲观并发策略。认为只...

长安一梦 ⋅ 今天 ⋅ 0

云计算的选择悖论如何对待?

人们都希望在工作和生活中有所选择。但心理学家的调查研究表明,在多种选项中进行选择并不一定会使人们更快乐,甚至不会产生更好的决策。心理学家Barry Schwartz称之为“选择悖论”。云计算为...

linux-tao ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部