根据Shehabix的回答,我重写了验证器。主要改进:
- 正确计算所有 colspan 和 rowspan 组合(希望如此)
- 检测重叠、表格尺寸外的单元格和缺失的单元格
- 输出特定的错误信息
(查看开发者控制台的输出)
JavaScript
function validateTable(id){
console.log('[validating table #' + id + ']');
var rows = document.getElementById(id).tBodies[0].rows;
var hasErrors = false;
// total rows and columns
var totalRows = rows.length;
var totalColumns= 0;
for(var row=0; row<rows.length; row++) {
var cells = rows[row].cells;
var cols = 0;
for(var col=0; col<cells.length; col++) {
var cell = rows[row].cells[col];
var colspan = parseInt(cell.colSpan);
if(colspan > 1) {
cols += colspan;
} else {
cols++;
}
}
totalColumns = Math.max(totalColumns, cols);
}
var cells = {};
cells.init = function(row, col, options) {
cells[row + ':' + col] = $.extend({
row: row,
col: col,
count: 0
}, options);
}
cells.update = function(row, col, options) {
var cell = cells[row + ':' + col];
if(!cell) {
hasErrors = true;
console.log('cell outside of table dimensions (cell ' + (row+1) + ':' + (col+1) + ' is outside of allowed table size ' + totalRows + ':' + totalColumns + ')');
return;
}
cells[row + ':' + col].count++;
if(options) {
cells[row + ':' + col] = $.extend(cells[row + ':' + col], options);
}
}
cells.get = function(row, col) {
return cells[row + ':' + col];
}
var colspans = {};
colspans.add = function(row, col, count) {
for(var coladd=0; coladd<count; coladd++) {
colspans[row + ':' + (col+coladd)] = true;
}
};
colspans.check = function(row, col) {
return colspans[row + ':' + col];
};
var rowspans = {};
rowspans.add = function(row, col, count) {
for(var rowadd=0; rowadd<count; rowadd++) {
rowspans[(row+rowadd) + ':' + col] = true;
}
};
rowspans.check = function(row, col) {
return rowspans[row + ':' + col];
};
// init cell matrix
for(var row=0; row<totalRows; row++) {
for(var col=0; col<totalColumns; col++) {
cells.init(row, col);
}
}
for(var row=0; row<rows.length; row++) {
var colskip = 0;
var rowskip = 0;
for(var col=0; col<totalColumns; col++) {
// check if this cell is pushed by a colspan
if(colspans.check(row, col)) continue;
// check if this cell is pushed by a rowspan
if(rowspans.check(row, col)) {
rowskip++;
continue;
}
console.log("row: " + row + " - col: " + (col-colskip-rowskip));
var cell = rows[row].cells[col-colskip-rowskip];
if(!cell) continue;
var rowspan = parseInt(cell.rowSpan);
var colspan = parseInt(cell.colSpan);
cells.update(row, col, {
element: cell
});
if(colspan > 1){
colskip += colspan-1;
colspans.add(row, col+1, colspan-1);
for(var coladd=1; coladd<colspan; coladd++) {
cells.update(row, col+coladd, {
element: cell
});
}
}
if(rowspan > 1){
rowspans.add(row+1, col, rowspan-1);
for(var rowadd=1; rowadd<rowspan; rowadd++) {
cells.update(row+rowadd, col, {
element: cell
});
}
}
}
}
for(var row=0; row<totalRows; row++) {
for(var col=0; col<totalColumns; col++) {
var cell = cells.get(row, col);
if(cell.count == 1) {
// everything is fine
} else if(cell.count == 0) {
hasErrors = true;
console.log("cell " + (row+1) + ':' + (col+1) + " is missing");
} else {
hasErrors = true;
console.log("cell " + (row+1) + ':' + (col+1) + " is overlapping with rowspan (cell usage count of " + cell.count + ")");
}
}
}
console.log('table is ' + (hasErrors ? 'invalid' : 'valid'));
return hasErrors;
}
--