2012-06-10 17 views
11

Tengo una tabla HTML que contiene ROWSPAN y COLSPAN.¿Cómo puedo encontrar la "ubicación visual" de cada celda de tabla usando jQuery?

¿Cómo puedo encontrar la "ubicación visual" de cada celda usando jQuery?

Por ejemplo, aquí es una representación visual de mi mesa, de cada celda llena con lo que el algoritmo de "localización visual" debe devolver:
(Nota: lo único que realmente importa acerca de las células dentro de la <tbody> y la referencia de columna se puede un entero, no un carácter alfabético, sólo he hecho esto para poner de relieve el problema fácilmente)

+--+--+--+--+--+ 
| |A |B |C |D | 
+--+--+--+--+--+ 
|1 |A1|B1 |D1| 
+--+--+--+--+ + 
|2 |A2 |C2| | 
+--+  +--+ + 
|3 |  |C3| | 
+--+--+--+--+--+ 
|4 |A4|B4|C4|D4| 
+--+--+--+--+--+ 
|XYZ   | 
+--+--+--+--+--+ 

he intentado aplicar la primera, sin embargo, la referencia de la celda C3 es inexacta, ya que no toma en cuenta ROWSPANS. El segundo enlace puede fusionarse en la solución del primero, pero no puedo entender cómo.

estoy esperando a utilizar esto como una función llamada getCellLocation(cell) que devolverá una matriz asociativa que devuelve la ubicación de algo como esto:

function getCellLocation(cell) 
{ 
    var row_number = parseInt($(cell).parent().prevAll().length) + 1; 
    var col_number = 1; 
    $(cell).prevAll('td').each(function() { 
     col_number += $(this).attr('colspan') ? parseInt($(this).attr('colspan')) : 1; 
    }); 

    var location = new Array(); 
    location['row'] = row_number; 
    location['col'] = col_number; 
    location['index'] = $('td').index(cell) + 1; 
    return location; 
} 

$('table td').each(function(i){ 
    var cell = getCellLocation($(this)); 
    $(this).prepend('<span class="ref">R' + cell['row'] + ':C' + cell['col'] + ':D' + cell['index'] + '</span>'); 
}); 

Aquí está el código HTML de la tabla de ejemplo:

<table border="1" cellspacing="0"> 
    <thead> 
    <tr> 
     <th></th> 
     <th>A</th> 
     <th>B</th> 
     <th>C</th> 
     <th>D</th> 
    </tr> 
    </thead> 
    <tbody> 
    <tr> 
     <th>1</th> 
     <td>A1</td> 
     <td colspan="2">B1</td> 
     <td rowspan="3">D1</td> 
    </tr> 
    <tr> 
     <th>2</th> 
     <td rowspan="2" colspan="2">A2</td> 
     <td>C2</td> 
    </tr> 
    <tr> 
     <th>3</th> 
     <td>C3</td> 
    </tr> 
    <tr> 
     <th>4</th> 
     <td>A4</td> 
     <td>B4</td> 
     <td>C4</td> 
     <td>D4</td> 
    </tr> 
    </tbody> 
    <tfoot> 
    <tr> 
     <td colspan="5">XYZ</td> 
    </tr> 
    </tfoot> 
</table> 
<style> span { background-color: #ffc; margin-right: .5em;} </style> 

Respuesta

7

Aquí está mi solución:

function getCellLocation(cell) { 

    var cols = cell.closest("tr").children("td").index(cell); 
    var rows = cell.closest("tbody").children("tr").index(cell.closest("tr")); 
    var coltemp = cols; 
    var rowtemp = rows; 

    cell.prevAll("td").each(function() { 
     cols += ($(this).attr("colspan")) ? parseInt($(this).attr("colspan")) - 1 : 0; 
    }); 

    cell.parent("tr").prevAll("tr").each(function() { 
     //get row index for search cells 
     var rowindex = cell.closest("tbody").children("tr").index($(this)); 
     // assign the row to a variable for later use 
     var row = $(this); 
     row.children("td").each(function() { 
      // fetch all cells of this row 
      var colindex = row.children("td").index($(this)); 
      //check if this cell comes before our cell 
      if (cell.offset().left > $(this).offset().left) { 
       // check if it has both rowspan and colspan, because the single ones are handled before 
       var colspn = parseInt($(this).attr("colspan")); 
       var rowspn = parseInt($(this).attr("rowspan")); 
       if (colspn && rowspn) { 
        if(rowindex + rowspn > rows) 
        cols += colspn;      
       } 
       if(rowspn && rowindex + rowspn > rows) cols +=1; 
      } 

     }); 
    }); 

estoy comprobando para las células que tienen tanto colspan y rowspan, porque el resto son manejados por las cinco primeras líneas de este código. Si las celdas tienen tanto rowspan como colspan, deberían afectar a otras celdas que no están por debajo O a un lado de esta celda, por lo que necesito buscar las celdas previas de cada celda para la interacción.

+0

y aquí está la jsFiddle de ella: http://jsfiddle.net/bcnEW/ –

+0

Parece que hay un pequeño problema o doble recuento en algunos escenarios. Considere el resultado cuando se aplica a esta tabla (vea la celda Col3 Row2): [http://jsfiddle.net/tUn54/](http://jsfiddle.net/tUn54/) – Turgs

+0

actualizó mi respuesta y el violín: http: //jsfiddle.net/bcnEW/1/ –

0

para este diseño específico (es decir si la primera fila no tiene colspan y más o menos uniformes bordes de las celdas) puede hacerlo de esta manera:

function getCellLocation(cell) 
{ 
    var row_number = cell.parentNode.rowIndex; 
    var col_number = ""; 
    $(cell).parents('table').find('tr:first th').each(function() 
    { 
     if (cell.offsetLeft >= this.offsetLeft) 
     { 
      col_number = $(this).text(); 
     } 
     else return false; 
    }); 
    return col_number + row_number; 
} 

si quieres columna numérica cambiarlo a

var col_number = 0; 
    ... 
if (cell.offsetLeft >= this.offsetLeft) 
{ 
    col_number++; 
} 
0

Aquí una solución de jQuery que es capaz de manejar estructuras de tablas complejas. Esta solución utiliza el Open Source WxT Table Parser disponible aquí: https://raw.github.com/wet-boew/wet-boew/master/src/js/dependencies/parserTable.js

Encontrará la documentación en el Table Usability Concept Github Repository. Use la documentación de API que se encuentra en "Table Parser - WET 3.0 release".

El análisis de la tabla se realiza mediante el marcado de tabla HTML y las relaciones visuales entre la celda de datos (TD) y la celda de cabecera (th)

// Used to get the reference to the WxT table parser 
var _pe = window.pe || { 
    fn : {} 
}; 

// For each table elements 
$('table').each(function() { 

    var $tbl = $(this); 

    // Parse the table 
    _pe.fn.parsertable.parse($tbl); 

    // For each data cell 
    $('td', $tbl).each(function() { 

     var $td = $(this), 
      tblparser; 

     // Get the API structure as defined under "Table Parser - WET 3.0 release" (https://github.com/duboisp/Table-Usability-Concept/blob/master/API/td.md#table-parser---wet-30-release) 
     tblparser = $td.data().tblparser; 

     // Set the cell location (x, y) 
     $td.html(tblparser.row.rowpos + ', ' + tblparser.col.start); 


    }); 
}); 

Encontrará un ejemplo de trabajo aquí: http://jsfiddle.net/TVttA/

Saludos

:-)

1
your solution  my proposed table design 
+--+--+--+--+--+  +--+--+--+--+--+ 
| |A |B |C |D |  | |A |B |C |D |  length 5 vs 5 
+--+--+--+--+--+  +--+--+--+--+--+ 
|1 |A1|B1 |D1|  |1 |A1|B1|//|D1| 
+--+--+--+--+ +  +--+--+--+--+--+ 
|2 |A2 |C2| |  |2 |A2|//|C2|//|  length 3 vs 5 
+--+  +--+ +  +--+--+--+--+--+ 
|3 |  |C3| |  |3 |//|//|C3|//| 
+--+--+--+--+--+  +--+--+--+--+--+ 
|4 |A4|B4|C4|D4|  |4 |A4|B4|C4|D4| 
+--+--+--+--+--+  +--+--+--+--+--+ 
|XYZ   |  |XY|//|//|//|//|  length 1 vs 5 
+--+--+--+--+--+  +--+--+--+--+--+ 
// cells labeled '//' above have this class 

td.stuffing { display: none; } 

¿Ves lo que hice allí?

Ésta es la tercera fila, por ejemplo:

<tr> 
    <th>2</th> 
    <td rowspan="2" colspan="2">A2</td> 
    <td class="stuffing"></td> 
    <td>C2</td> 
    <td class="stuffing"></td> 
</tr> 

Ahora la función para recuperar índice correcto es muy simple.

function getCellLocation(cell) { 
    return {row:cell.parentNode.rowIndex, cell:cell.cellIndex} 
} 


Y aquí es una ventaja. Si tuviera acceso a una celda oculta, esta atravesaría automáticamente la correcta, que se extiende sobre las ocultas.

function getSmartCell(table, row, col) { 
    var cell = table.rows[row].cells[col]; 
    if (cell.className.indexOf("stuffing") == -1) return cell; 

    // traverse Left 
    while ((row>0) && (col>0) && (cell.className.indexOf("stuffing") >= 0)) { 
     cell = table.rows[row].cells[--col]; 
    } 

    // roll back one cell if no colSpan is found 
    if (cell.colSpan == 1) cell = table.rows[row].cells[++col]; 

    // traverse Up 
    while ((row>0) && (col>0) && (cell.className.indexOf("stuffing") >= 0)) { 
     cell = table.rows[--row].cells[col]; 
    } 

    return cell; 
} 

Uso:

var tb = document.querySelector("table"); 
getCellLocation(getSmartCell(tb,3,2)); // {row: 2, cell: 1} 

ATENCIÓN acabo de haber comprobado el código de getSmartCell y devuelve un resultado erróneo si hay dos rowspans vecinos. Necesito arreglar esto.

Aquí es un ejemplo https://jsfiddle.net/goua3m13/

+0

había una razón deliberada por la cual las celdas se "fusionaron" para abarcar columnas y filas en mi pregunta. Para el caso de uso, tenía que ser de esa manera y no podía usar celdas en blanco y ocultarlas. – Turgs

+1

@Turgs. Puede seguir usando colspans y rowspans mientras usa celdas ocultas. – Qwerty

+0

Buena idea. ¡¡¡El mejor rendimiento que otros algoritmos !!! –

Cuestiones relacionadas