瀏覽器兼容的實現table中經過拖拽改變列寬的最佳實踐

        在企業級應用中,表格是很是常見的展示方式,這時當列數據較長時,一種比較天然,體驗也較好的處理方式就是經過拖拽改變列寬,這個功能在一些重量級JS組件庫中都有提供,實現原理各有不一樣,可是一個共同點就是實現比較複雜,那咱們經過不多的代碼,常規的table結構,能實現這個功能麼?本文將提供一個通過實際驗證的實踐,供開發者參考,擴展思路。javascript

        整體思路:html

        1.HTML結構:java

                爲了簡化代碼,採用標準的HTML結構,即table-tr-td模式,無其餘限制,在咱們的實際應用中,表格很是複雜,可是核心技術沒有變;算法

        2.事件:瀏覽器

                採用onmousedown、onmousemove、onmouseup三個事件相結合的方式,處理鼠標拖動元素過程當中的事件;測試

        3.瀏覽器兼容:ui

                整個實現中,涉及到事件模型,offsetX偏移量計算等存在瀏覽器差別的狀況,本文都提供了精煉的處理,並通過了測試;spa

        4.列寬度計算:code

                拖動改變列寬的核心算法是,鼠標移動過程當中計算鼠標在屏幕上滑動過的水平距離,多是正值可能爲負,而後加上單元格原來的寬度,計算得出新的寬度;htm

        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等主流瀏覽器。

相關文章
相關標籤/搜索