🔥 fix(table): 修复表格列宽计算问题 (#2187)
* fix(table): 修复表格列宽计算问题 rebase * update * update * update * update
This commit is contained in:
parent
045ac836ba
commit
8d14ef50e7
@ -15,6 +15,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
|
|||||||
var util = layui.util;
|
var util = layui.util;
|
||||||
var hint = layui.hint();
|
var hint = layui.hint();
|
||||||
var device = layui.device();
|
var device = layui.device();
|
||||||
|
var isChrome = layui.device('chrome').chrome;
|
||||||
|
|
||||||
// api
|
// api
|
||||||
var table = {
|
var table = {
|
||||||
@ -483,9 +484,21 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
|
|||||||
options.clientWidth = options.width || function(){ //获取容器宽度
|
options.clientWidth = options.width || function(){ //获取容器宽度
|
||||||
//如果父元素宽度为0(一般为隐藏元素),则继续查找上层元素,直到找到真实宽度为止
|
//如果父元素宽度为0(一般为隐藏元素),则继续查找上层元素,直到找到真实宽度为止
|
||||||
var getWidth = function(parent){
|
var getWidth = function(parent){
|
||||||
var width, isNone;
|
var width;
|
||||||
parent = parent || options.elem.parent()
|
var isNone;
|
||||||
width = parent.width();
|
parent = parent || options.elem.parent();
|
||||||
|
|
||||||
|
if(!window.getComputedStyle){
|
||||||
|
// IE 中的 `currentStyle` 获取未显式设置的宽高时会得到 'auto',jQuery 中有一些 hack 方法获取准确值
|
||||||
|
width = parent.width();
|
||||||
|
}else{
|
||||||
|
var size = that.getElementSize(parent[0]);
|
||||||
|
// IE BUG
|
||||||
|
// border-box: getComputedStyle 得到的 width/height 是按照 content-box 计算出来的
|
||||||
|
width = size.boxSizing === 'border-box' && !lay.ie
|
||||||
|
? size.width - size.paddingLeft - size.paddingRight - size.borderLeftWidth - size.borderRightWidth
|
||||||
|
: size.width
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
isNone = parent.css('display') === 'none';
|
isNone = parent.css('display') === 'none';
|
||||||
} catch(e){}
|
} catch(e){}
|
||||||
@ -902,16 +915,23 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
|
|||||||
var autoWidth = 0; // 自动列分配的宽度
|
var autoWidth = 0; // 自动列分配的宽度
|
||||||
var countWidth = 0; // 所有列总宽度和
|
var countWidth = 0; // 所有列总宽度和
|
||||||
var cntrWidth = that.setInit('width');
|
var cntrWidth = that.setInit('width');
|
||||||
|
var borderWidth = parseFloat(layui.getStyle(that.elem[0], 'border-right-width'));
|
||||||
|
var lastSpreadCol;
|
||||||
|
|
||||||
// 统计列个数
|
// 统计列个数和最后一个分配宽度的列
|
||||||
that.eachCols(function(i, item){
|
that.eachCols(function(i, item){
|
||||||
item.hide || colNums++;
|
if(!item.hide){
|
||||||
|
colNums++;
|
||||||
|
if(!(item.width || item.type !== 'normal')){
|
||||||
|
lastSpreadCol = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 减去边框差和滚动条宽
|
// 减去边框差和滚动条宽
|
||||||
cntrWidth = cntrWidth - function(){
|
cntrWidth = cntrWidth - function(){
|
||||||
return (options.skin === 'line' || options.skin === 'nob') ? 2 : colNums + 1;
|
return (options.skin === 'line' || options.skin === 'nob') ? 2 : colNums + 1;
|
||||||
}() - that.getScrollWidth(that.layMain[0]) - 1;
|
}() * borderWidth - that.getScrollWidth(that.layMain[0]);
|
||||||
|
|
||||||
// 计算自动分配的宽度
|
// 计算自动分配的宽度
|
||||||
var getAutoWidth = function(back){
|
var getAutoWidth = function(back){
|
||||||
@ -932,7 +952,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
|
|||||||
if(!back){
|
if(!back){
|
||||||
width = item2.width || 0;
|
width = item2.width || 0;
|
||||||
if(/\d+%$/.test(width)){ // 列宽为百分比
|
if(/\d+%$/.test(width)){ // 列宽为百分比
|
||||||
width = Math.floor((parseFloat(width) / 100) * cntrWidth);
|
width = (parseFloat(width) / 100) * cntrWidth;
|
||||||
width < minWidth && (width = minWidth);
|
width < minWidth && (width = minWidth);
|
||||||
width > maxWidth && (width = maxWidth);
|
width > maxWidth && (width = maxWidth);
|
||||||
} else if(!width){ // 列宽未填写
|
} else if(!width){ // 列宽未填写
|
||||||
@ -969,31 +989,34 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
|
|||||||
// 记录自动列数
|
// 记录自动列数
|
||||||
that.autoColNums = autoColNums = autoColNums > 0 ? autoColNums : 0;
|
that.autoColNums = autoColNums = autoColNums > 0 ? autoColNums : 0;
|
||||||
|
|
||||||
// 设置列宽
|
var pixelsForLastCol = cntrWidth;
|
||||||
that.eachCols(function(i3, item3){
|
that.eachCols(function(i3, item3){
|
||||||
var minWidth = item3.minWidth || options.cellMinWidth;
|
var minWidth = item3.minWidth || options.cellMinWidth;
|
||||||
var maxWidth = item3.maxWidth || options.cellMaxWidth;
|
var maxWidth = item3.maxWidth || options.cellMaxWidth;
|
||||||
|
|
||||||
if(item3.colGroup || item3.hide) return;
|
if(item3.colGroup || item3.hide || (lastSpreadCol && lastSpreadCol.key === item3.key)) return;
|
||||||
|
|
||||||
// 给未分配宽的列平均分配宽
|
// 给未分配宽的列平均分配宽
|
||||||
if(item3.width === 0){
|
if(item3.width === 0){
|
||||||
that.cssRules(item3.key, function(item){
|
that.cssRules(item3.key, function(item){
|
||||||
item.style.width = Math.floor(function(){
|
var newWidth = Math.round(function(){
|
||||||
if(autoWidth < minWidth) return minWidth;
|
if(autoWidth < minWidth) return minWidth;
|
||||||
if(autoWidth > maxWidth) return maxWidth;
|
if(autoWidth > maxWidth) return maxWidth;
|
||||||
return autoWidth;
|
return autoWidth;
|
||||||
}()) + 'px';
|
}());
|
||||||
|
item.style.width = newWidth + 'px';
|
||||||
|
pixelsForLastCol = pixelsForLastCol - newWidth;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 给设定百分比的列分配列宽
|
// 给设定百分比的列分配列宽
|
||||||
else if(/\d+%$/.test(item3.width)){
|
else if(/\d+%$/.test(item3.width)){
|
||||||
that.cssRules(item3.key, function(item){
|
that.cssRules(item3.key, function(item){
|
||||||
var width = Math.floor((parseFloat(item3.width) / 100) * cntrWidth);
|
var width = Math.round((parseFloat(item3.width) / 100) * cntrWidth);
|
||||||
width < minWidth && (width = minWidth);
|
width < minWidth && (width = minWidth);
|
||||||
width > maxWidth && (width = maxWidth);
|
width > maxWidth && (width = maxWidth);
|
||||||
item.style.width = width + 'px';
|
item.style.width = width + 'px';
|
||||||
|
pixelsForLastCol = pixelsForLastCol - width;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1001,33 +1024,20 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
|
|||||||
else {
|
else {
|
||||||
that.cssRules(item3.key, function(item){
|
that.cssRules(item3.key, function(item){
|
||||||
item.style.width = item3.width + 'px';
|
item.style.width = item3.width + 'px';
|
||||||
|
pixelsForLastCol = pixelsForLastCol - item3.width;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// 最后一列获取剩余的空间,避免舍入导致的布局问题
|
||||||
// 填补 Math.floor 造成的数差
|
if(lastSpreadCol){
|
||||||
var patchNums = that.layMain.width() - that.getScrollWidth(that.layMain[0])
|
that.cssRules(lastSpreadCol.key, function(item){
|
||||||
- that.layMain.children('table').outerWidth();
|
var minWidth = lastSpreadCol.minWidth || options.cellMinWidth;
|
||||||
|
var maxWidth = lastSpreadCol.maxWidth || options.cellMaxWidth;
|
||||||
if(that.autoColNums > 0 && patchNums >= -colNums && patchNums <= colNums){
|
var newWidth = Math.max(Math.min(pixelsForLastCol, maxWidth), minWidth);
|
||||||
var getEndTh = function(th){
|
item.style.width = newWidth + 'px';
|
||||||
var field;
|
|
||||||
th = th || that.layHeader.eq(0).find('thead > tr:first-child > th:last-child')
|
|
||||||
field = th.data('field');
|
|
||||||
if(!field && th.prev()[0]){
|
|
||||||
return getEndTh(th.prev())
|
|
||||||
}
|
|
||||||
return th;
|
|
||||||
};
|
|
||||||
var th = getEndTh();
|
|
||||||
var key = th.data('key');
|
|
||||||
|
|
||||||
that.cssRules(key, function(item){
|
|
||||||
var width = item.style.width || th.outerWidth();
|
|
||||||
item.style.width = (parseFloat(width) + patchNums) + 'px';
|
|
||||||
|
|
||||||
// 二次校验,如果仍然出现横向滚动条(通常是 1px 的误差导致)
|
// 二次校验,如果仍然出现横向滚动条(通常是 1px 的误差导致)
|
||||||
if(that.layMain.height() - that.layMain.prop('clientHeight') > 0){
|
if(isChrome && that.layMain.prop('offsetHeight') > that.layMain.prop('clientHeight')){
|
||||||
item.style.width = (parseFloat(item.style.width) - 1) + 'px';
|
item.style.width = (parseFloat(item.style.width) - 1) + 'px';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -1043,7 +1053,6 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
|
|||||||
} else {
|
} else {
|
||||||
that.layMain.find('table').width('auto');
|
that.layMain.find('table').width('auto');
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 重置表格尺寸/结构
|
// 重置表格尺寸/结构
|
||||||
@ -2789,6 +2798,33 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
|
|||||||
that.layMain.scrollTop(scrollTop + (delta > 0 ? -step : step));
|
that.layMain.scrollTop(scrollTop + (delta > 0 ? -step : step));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取元素的大小
|
||||||
|
* @param {HTMLElement} elem - HTML 元素
|
||||||
|
*/
|
||||||
|
Class.prototype.getElementSize = function(elem){
|
||||||
|
if(!window.getComputedStyle) return;
|
||||||
|
|
||||||
|
var style = window.getComputedStyle(elem, null);
|
||||||
|
return {
|
||||||
|
height: parseFloat(style.height || '0'),
|
||||||
|
width: parseFloat(style.width || '0'),
|
||||||
|
borderTopWidth: parseFloat(style.borderTopWidth || '0'),
|
||||||
|
borderRightWidth: parseFloat(style.borderRightWidth || '0'),
|
||||||
|
borderBottomWidth: parseFloat(style.borderBottomWidth || '0'),
|
||||||
|
borderLeftWidth: parseFloat(style.borderLeftWidth || '0'),
|
||||||
|
paddingTop: parseFloat(style.paddingTop || '0'),
|
||||||
|
paddingRight: parseFloat(style.paddingRight || '0'),
|
||||||
|
paddingBottom: parseFloat(style.paddingBottom || '0'),
|
||||||
|
paddingLeft: parseFloat(style.paddingLeft || '0'),
|
||||||
|
marginTop: parseFloat(style.marginTop || '0'),
|
||||||
|
marginRight: parseFloat(style.marginRight || '0'),
|
||||||
|
marginBottom: parseFloat(style.marginBottom || '0'),
|
||||||
|
marginLeft: parseFloat(style.marginLeft || '0'),
|
||||||
|
boxSizing: style.boxSizing
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 全局事件
|
// 全局事件
|
||||||
|
Loading…
Reference in New Issue
Block a user