在企業級應用中,表格是很是常見的展示方式,這時當列數據較長時,一種比較天然,體驗也較好的處理方式就是經過拖拽改變列寬,這個功能在一些重量級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等主流瀏覽器。