Misleading cellIndex values with rowspan/colspan

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Matt Kruse

    Misleading cellIndex values with rowspan/colspan

    Using the .cellIndex property of a TH element to find out which table column
    it is over can cause misleading results when the table has cells which have
    rowspans or colspans greater than 1.
    See example: http://www.javascripttoolbox.com/tem...cellindex.html
    (code pasted below for reference)

    This behaves according to specs and expectations, however the value of the
    cellIndex property becomes less useful when using it to determine which
    column to sort onclick, etc.

    I plan to write some code to calculate the "actual" column index of each
    cell in a <theadof a table. But if anyone has already done this exercise,
    please do share so I can perhaps use my time working on something else :)

    Thanks!

    EXAMPLE CODE:

    <html>
    <head>
    <title></title>
    <script type="text/javascript">
    window.onload = function() {
    var ths = document.getEle mentsByTagName( 'TH');
    for (var i=0; i<ths.length; i++) {
    ths[i].innerHTML = ths[i].parentNode.row Index + "," + ths[i].cellIndex;
    }
    }
    </script>
    <style>
    th {
    vertical-align:top;
    text-align:left;
    width:50px;
    }
    </style>
    </head>
    <body>
    <table border="1">
    <thead>
    <tr>
    <th rowspan="2">&nb sp;</th>
    <th>&nbsp;</th>
    <th>&nbsp;</th>
    <th>&nbsp;</th>
    <th>&nbsp;</th>
    </tr>
    <tr>
    <th colspan="2">&nb sp;</th>
    <th rowspan="2">&nb sp;</th>
    <th>&nbsp;</th>
    </tr>
    <tr>
    <th colspan="2">&nb sp;</th>
    <th>&nbsp;</th>
    <th>&nbsp;</th>
    </tr>
    </thead>
    </table>
    </body>
    </html>


    --
    Matt Kruse




  • Csaba  Gabor

    #2
    Re: Misleading cellIndex values with rowspan/colspan

    Matt Kruse wrote:
    Using the .cellIndex property of a TH element to find out which table column
    it is over can cause misleading results when the table has cells which have
    rowspans or colspans greater than 1.
    See example: http://www.javascripttoolbox.com/tem...cellindex.html
    (code pasted below for reference)
    >
    This behaves according to specs and expectations, however the value of the
    cellIndex property becomes less useful when using it to determine which
    column to sort onclick, etc.
    >
    I plan to write some code to calculate the "actual" column index of each
    cell in a <theadof a table. But if anyone has already done this exercise,
    please do share so I can perhaps use my time working on something else :)
    Hiya Matt,

    The good news: I have done this before. I think I did it because I
    wanted a general routine such that when someone clicked on any table
    cell, I could find every other cell in the same row or column.
    The bad news: I don't know where I put it offhand.
    More bad news: The situation is more complicated than your nice
    example shows:

    <table border bgcolor=blue>
    <tr>
    <td bgcolor=yellow> 1x1</td>
    <td bgcolor=purple colspan=2>2 wide</td>
    <td rowspan=3 bgcolor=green valign=bottom>3 deep</td>
    </tr>
    <tr><td bgcolor=red>1x1 </td></tr>
    <tr><td colspan=2 bgcolor=pink>2 wide</td>
    <td colspan=2>2 wide</td>
    </tr>
    </table>

    In particular, as my example shows, multiple cells can overlap the same
    "tile", and a given "tile" need not be overlapped by any cells at all!

    So I might be able to advise you in this endeavor of yours. It seems
    like you're after:

    function colSpan(tableCe ll) {
    // returns [leftCol,rightCo l] that the tableCell corresponds to
    // leftCol equals rightCol if colSpan of the tableCell is 1 }

    If you can guarantee that you will only query on the top row of the
    table, then this function is fairly straightforward because you get the
    first row of the table
    (tableCell.pare ntNode.parentNo de.parentNode.r ows[0]) and then you march
    through the cells one by one determining the colSpan array of each
    till you get to the tableCell in question.

    function colSpan(topRowC ell) {
    // returns [leftCol,rightCo l] that topRowCell corresponds to
    // leftCol equals rightCol iff colSpan of the tableCell is 1
    // function fails badly if topRowCell isn't in the table's top row
    var topRow=topRowCe ll.parentNode.p arentNode.paren tNode.rows[0];
    var priorRight = -1;
    for (var i=0;topRow.cell s[i]!=topRowCell;++ i)
    priorRight += topRow.cells[i].colspan;
    return [priorRight+1,pr iorRight+topRow .cells[i].colspan]; }


    Disclaimer: I have not tested the above function, even for syntax
    errors
    If you can't make the top row guarantee, then it is much messier.

    Csaba Gabor from Vienna

    Comment

    • Matt Kruse

      #3
      Re: Misleading cellIndex values with rowspan/colspan

      Csaba Gabor wrote:
      In particular, as my example shows, multiple cells can overlap the
      same "tile", and a given "tile" need not be overlapped by any cells
      at all!
      Overlapping of cells is, I believe, invalid.
      If you can guarantee that you will only query on the top row of the
      table
      Which, of course, isn't possible.
      If it were, then it would be trivial to find the true cellIndex value.
      Colspans are easy to taken into consideration. Rowspans are more difficult,
      and seem to require traversal through every row before and including the row
      of the cell for which you want to find the true cellIndex.

      --
      Matt Kruse




      Comment

      • Randy Webb

        #4
        Re: Misleading cellIndex values with rowspan/colspan

        Matt Kruse said the following on 8/3/2006 4:43 PM:
        Csaba Gabor wrote:
        >In particular, as my example shows, multiple cells can overlap the
        >same "tile", and a given "tile" need not be overlapped by any cells
        >at all!
        >
        Overlapping of cells is, I believe, invalid.
        It is, and is only "honored" by IE by joining all the cells.

        --
        Randy
        comp.lang.javas cript FAQ - http://jibbering.com/faq & newsgroup weekly
        Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/

        Comment

        • Csaba  Gabor

          #5
          Re: Misleading cellIndex values with rowspan/colspan

          Randy Webb wrote:
          Matt Kruse said the following on 8/3/2006 4:43 PM:
          Csaba Gabor wrote:
          In particular, as my example shows, multiple cells can overlap the
          same "tile", and a given "tile" need not be overlapped by any cells
          at all!
          Overlapping of cells is, I believe, invalid.
          >
          It is, and is only "honored" by IE by joining all the cells.
          I don't really understand the above two comments.
          I have tested the table that I gave on both IE 6 and FF 1.5 (and
          similar tables on earlier versions a few years ago), and they exhibit
          both the "hole" at tiles [1,1] and [1,2] (coordinates are 0 based) with
          a blue color (the bgcolor of the table), and a tile overlapped by two
          cells at [2,3].

          Note that this latter tile shows the (overlapped) text of two cells.
          Furthermore, if I had set a bgcolor on the last cell, then it would
          have covered the green cell so that the effect would not have been
          readily observable.

          Csaba

          Comment

          • Matt Kruse

            #6
            Re: Misleading cellIndex values with rowspan/colspan

            Matt Kruse wrote:
            Colspans are easy to taken into consideration. Rowspans are more
            difficult, and seem to require traversal through every row before and
            including the row of the cell for which you want to find the true
            cellIndex.
            Well, I've thrown together a really messy proof-of-concept at the same url:


            It appears to work, so I'm going to clean it up, optimize it, and add it to
            my table lib.
            If anyone sees any problem with the general logic, please do critique.
            I guarantee the "finished" version will be much prettier ;)

            --
            Matt Kruse




            Comment

            • Csaba  Gabor

              #7
              Re: Misleading cellIndex values with rowspan/colspan

              Matt Kruse wrote:
              Csaba Gabor wrote:
              If you can guarantee that you will only query on the top row of the
              table
              >
              Which, of course, isn't possible.
              If it were, then it would be trivial to find the true cellIndex value.
              Colspans are easy to taken into consideration. Rowspans are more difficult,
              and seem to require traversal through every row before and including the row
              of the cell for which you want to find the true cellIndex.
              OK, then here's the approach that I would take if I were to do this
              again. I would build an associative array of all tiles and have the
              value of each one be the cell that covers it (I am assuming that the
              table is such that no two cells overlap the same tile - if so, you
              could generalize my scheme). The index of tile at position [n,m] will
              be n+"x"+m. Thus, the pseudo code is something like:

              function nextFreeIdx(aTi les, rowNum, colStart, maxCol) {
              for (;colStart<=max Col;++colStart) // find first free index
              if (!aTiles[rowNum+"x"+colS tart]) break;
              return colStart; }

              function findTileToCellM ap(table, terminatingCell ) {
              // pass in terminatingCell if you want to get a specific cell's info
              // aTiles maps tile position to cell that covers it.
              var i,j,csp,maxCol=-1, aTiles = [];
              for (rowNum=0;rowNu m<table.rows.le ngth;++rowNum) {
              var thisRow=table.r ows[rowNum];
              var colNum=-1;
              for (cellNum=0;cell Num<thisRow.cel ls.length;++cel lNum) {
              thisCell=thisRo w.cells[cellNum];
              csp=thisCell.co lspan;
              colNum=nextFree Idx(aTiles, rowNum, colNum+1, maxCol);
              for (i=0;i<thisCell .rowspan;++i)
              for (j=0;j<csp;++j)
              aTiles[(thisRow+i)+"x" +(colNum+j)]=thisCell;
              if (colNum+csp-1>maxCol) maxCol=colNum+c sp-1;
              if (thisCell==term inatingCell) return [rowNum, colNum]; // [top, left]
              } }
              return aTiles; }

              To make this more usable, you should really affix to each cell it's top
              left tile position as you compute it. That way, you can not only go
              from the tile to the cell, but from the cell to the tile (which is what
              was desired in the first place). One should be aware of possible
              issues when cells are collapsed/combined (eg. table is 3 tiles high.
              Cell at tile 0,3 is two by two, cell at tile 2,3 is two wide by 1 high
              =cols 3 and 4 are collapsed into one).

              Csaba Gabor

              Comment

              • Csaba  Gabor

                #8
                Re: Misleading cellIndex values with rowspan/colspan

                Matt Kruse wrote:
                Matt Kruse wrote:
                Colspans are easy to taken into consideration. Rowspans are more
                difficult, and seem to require traversal through every row before and
                including the row of the cell for which you want to find the true
                cellIndex.
                >
                Well, I've thrown together a really messy proof-of-concept at the same url:

                >
                It appears to work, so I'm going to clean it up, optimize it, and add it to
                my table lib.
                If anyone sees any problem with the general logic, please do critique.
                I guarantee the "finished" version will be much prettier ;)
                Seems to work pretty nicely. Nice job.
                Since I sent in my suggestion before seeing that you'd already solved
                your problem, I figured I may as well clean up my work, too. I've cast
                it into the form that you are using. Just cut and paste and you should
                see no difference :)


                function findTileToCellM ap(table, terminatingCell ) {
                // pass in terminatingCell if you want to get a specific cell's info
                // aTiles maps tile position to cell that covers it.
                var cellNum, colNum, aTiles = [];
                for (var rowNum=0;rowNum <table.rows.len gth;++rowNum) {
                var thisRow=table.r ows[rowNum];
                for (cellNum=0, colNum=-1;cellNum<thisR ow.cells.length ;++cellNum) {
                var thisCell=thisRo w.cells[cellNum];
                while (aTiles[rowNum+"x"+ ++colNum]); // next free index
                for (var i=0;i<(thisCell .rowSpan || 1);++i)
                for (var j=0;j<(thisCell .colSpan || 1);++j)
                aTiles[(rowNum+i)+"x"+ (colNum+j)]=thisCell;
                thisCell.tile = [rowNum, colNum]; // [top, left] - cache value
                if (thisCell==term inatingCell) return thisCell.tile; } }
                return aTiles; }


                function getActualCellIn dex(cell) {
                if (cell.tile) return cell.tile[1]; // cached
                var table = cell.parentNode .parentNode.par entNode;
                findTileToCellM ap (table); // cache values here
                return cell.tile[1]; }


                You could also implement getActualCellIn dex as:

                function getActualCellIn dex(cell) {
                // doesn't use cached values
                var table = cell.parentNode .parentNode.par entNode;
                return findTileToCellM ap (table, cell)[1]; }

                Csaba Gabor

                Comment

                Working...