2

对于所有 colspan 和 rowspan 定义,我想验证给定的 html 表语法是否正确。

JSFiddle 上的示例

下表在语法上是正确的:

<table id="correct">
    <tr>
        <td>a</td>
        <td>b</td>
        <td rowspan="2">c</td>
    </tr>
    <tr>
        <td colspan="2">d</td>
    </tr>
</table>

下一个表是错误的,因为列和行都不匹配:

<table id="wrong1">
    <tr>
        <td>a</td>
        <td>b</td>
        <td rowspan="1">c</td>
    </tr>
    <tr>
        <td colspan="1">d</td>
    </tr>
</table>

我希望能够验证表格是正确还是错误。给定的代码只是一个示例,它应该使用任何给定的表进行验证,无论其复杂性如何。

我可以开始编写自己的验证器,但在此之前,我想知道是否有任何库或已经工作的解决方案。你能帮我解决这个问题吗?

/编辑

刚刚找到这个在线验证器:

http://wet-boew.github.com/wet-boew/demos/tableparser/validator-htmltable.html

我的第一个错误表#wrong1会引发错误,但#wrong2不会(参见fiddle)。似乎它不支持太大的数字。

4

2 回答 2

1

你去,这是一个工作代码:

function validateTable(id){
    var rows = document.getElementById(id).tBodies[0].rows;
    var totalCells=0;
    // total rows and columns
    var totalRows=rows.length;;
    var totalColumns=0;;
    var foundCells=new Array();    
    var maxRows=rows.length;
    var maxColumns=0;
    var maxCellIndex = 0;
    // First we get totalRows and totalColumns
    for(var i=0;i<rows.length;i++){     
        totalColumns = Math.max(totalColumns,rows[i].cells.length);
    }

    // The matrix now should be totalRows x totalColumns
    for(var i=0;i<totalRows;i++){
        for(var j=0;j<totalColumns;j++){
            maxCellIndex = (i*totalColumns)+j;
            foundCells[ maxCellIndex ] = 0;
        }
    }

    for(var i=0;i<rows.length;i++){     
        maxColumns = Math.max(rows[i].cells.length,maxColumns);
        for(var j = 0;j<rows[i].cells.length;j++){
            var cellPosition = (i*totalColumns)+j;
            var cols=0;
            var tcells=0;
            cols = parseInt( rows[i].cells[j].rowSpan );           
            tcells = parseInt( rows[i].cells[j].colSpan );
            if(tcells>0){
                for(var k=0;k<tcells;k++){
                     foundCells[cellPosition + k] = 1; 
                }
            }
            if(cols > 0){
               for(var k=0;k<cols;k++){
                     foundCells[cellPosition + (k*totalColumns)  ] = 1;
                }
            }
           // totalCells += ( tcells * cols) ;
        }        
    }     
    // This is the updated part
    var allCellsAlignedCorrectly=true;
    for(var n=0;n<=maxCellIndex;n++){        
       if(isNaN(foundCells[n]) || parseInt(foundCells[n]) == 0){
          allCellsAlignedCorrectly = false;
       }
    }
    for(var n=0;n<=foundCells.length;n++){
        if(!isNaN(foundCells[n])){
           totalCells+=foundCells[n];
        }
    }
    // alert(foundCells);
    // alert(totalCells+":"+totalColumns+":"+totalRows);
    return (((totalCells) == (maxRows*maxColumns)) && allCellsAlignedCorrectly);
}

再次更新再次检查

你可以在这里看到它:

http://jsfiddle.net/UkV35/8/

于 2013-01-26T11:52:35.400 回答
1

根据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;
}

--

于 2013-01-29T00:37:55.110 回答