jquery UI Clasificable con tabla y ancho tr

155

Estoy usando jQuery UI clasificable para hacer que la cuadrícula de mi tabla se pueda ordenar. El código parece funcionar bien, pero debido a que no estoy agregando ancho a tds, cuando lo arrastro tr, reduce el contenido.

Por ejemplo; si la fila de mi tabla es de 500 px cuando comienzo a arrastrar, se convierte en 300 px. Supongo que eso está sucediendo porque no se define ancho en la cuadrícula. Eso es porque estoy usando dos clases para la tds ( fixy liquid).

La fixclase hace tdque el ancho del contenido sea igual y liquidhace que el tdancho sea 100%. Es mi enfoque para la tabla de cuadrícula sin tener que asignar ancho a tds.

¿Alguna idea de cómo hacer que mi trabajo funcione con mi enfoque?

j0k
fuente
3
¡La respuesta de Yaroslav es el verdadero MVP!
Brade
Tuve el mismo problema, creo que @Yaroslav tiene la respuesta correcta para lidiar con tablas, que es lo que pregunta el OP
doz87

Respuestas:

254

Encontré la respuesta aquí .

Lo modifiqué ligeramente para clonar la fila, en lugar de agregar anchos al original:

  helper: function(e, tr)
  {
    var $originals = tr.children();
    var $helper = tr.clone();
    $helper.children().each(function(index)
    {
      // Set helper cell sizes to match the original sizes
      $(this).width($originals.eq(index).width());
    });
    return $helper;
  },
Dave James Miller
fuente
@Dave James Miller ¿Cómo haría que funcionara la opción de marcador de posición?
shaun5
55
Dave, gracias por compartir esto, he creado un jsFiddle para mostrar las diferencias entre el original, el modificado y el no aplicado: jsfiddle.net/bgrins/tzYbU . También actualizaré la publicación original con su solución.
Brian Grinstead
9
Esto funciona bastante bien, pero creo que todavía hay un pequeño problema; cuando arrastra / suelta la fila, el resto de las columnas de la tabla pueden cambiar el ancho debido a la fila que falta. Supongo que sus anchos necesitan ser reparados también ...
Jez
1
Esto me ahorró mucho trabajo. Debe marcarse como la respuesta correcta.
Andrew Bessa
3
Encontré que el ancho estaba resultando en celdas acolchadas, no MUY BIEN. Cambié de$(this).width($originals.eq(index).outerWidth());
Barry Carlyon
166

Creo que puede ayudar:

.ui-sortable-helper {
    display: table;
}
Yaroslav
fuente
13
¿Cómo es que esta no es la mejor respuesta? Una simple línea de CSS me lo soluciona.
jcrowson
8
¡Estoy de acuerdo! No creerá cómo una simple línea de CSS arregla su tabla ordenable: ¡los expertos de Stackoverflow están desconcertados!
Brade
3
Esta es la respuesta. Gracias @Yaroslav
Steffi
3
Esta NO es una solución general y dará como resultado una apariencia diferente de la fila arrastrada
Tomas M
13
Esta solución es muy buena, pero puede afectar otras listas que no son de tabla. Mi sugerencia es que edite su respuesta para que sea más específica. De esta manera => table tr.ui-sortable-helper {display: table! Important; }
Rafael Gomes Francisco
29

La respuesta seleccionada aquí es una solución realmente agradable, pero tiene un error grave que es evidente en el violín JS original ( http://jsfiddle.net/bgrins/tzYbU/ ): intente arrastrar la fila más larga ( Dios lo bendiga, Sr. . Rosewater ), y el resto de los anchos de celda colapsan.

Esto significa que fijar los anchos de las celdas en la celda arrastrada no es suficiente; también debe corregir los anchos en la tabla.

$(function () {
    $('td, th', '#sortFixed').each(function () {
        var cell = $(this);
        cell.width(cell.width());
    });

    $('#sortFixed tbody').sortable().disableSelection();
});

JS Fiddle: http://jsfiddle.net/rp4fV/3/

Esto soluciona el problema del colapso de la tabla después de arrastrar la primera columna, pero introduce una nueva: si cambia el contenido de la tabla, los tamaños de celda ahora se arreglan.

Para solucionar este problema al agregar o cambiar contenido, deberá borrar los anchos establecidos:

$('td, th', '#sortFixed').each(function () {
    var cell = $(this);
    cell.css('width','');
});

Luego agregue su contenido, luego corrija los anchos nuevamente.

Esto todavía no es una solución completa, ya que (especialmente con una tabla) necesita un marcador de posición de caída. Para eso necesitamos agregar una función al inicio que construya el marcador de posición:

$('#sortFixed tbody').sortable({
    items: '> tr',
    forcePlaceholderSize: true,
    placeholder:'must-have-class',
    start: function (event, ui) {
        // Build a placeholder cell that spans all the cells in the row
        var cellCount = 0;
        $('td, th', ui.helper).each(function () {
            // For each TD or TH try and get it's colspan attribute, and add that or 1 to the total
            var colspan = 1;
            var colspanAttr = $(this).attr('colspan');
            if (colspanAttr > 1) {
                colspan = colspanAttr;
            }
            cellCount += colspan;
        });

        // Add the placeholder UI - note that this is the item's content, so TD rather than TR
        ui.placeholder.html('<td colspan="' + cellCount + '">&nbsp;</td>');
    }
}).disableSelection();

JS Fiddle: http://jsfiddle.net/rp4fV/4/

Keith
fuente
Gracias, me ahorras tiempo
super pantera
¡La técnica de marcador de posición aquí es asesina! Totalmente resuelto mi problema.
jessegavin
1
Esta solución es realmente muy buena, y la técnica de marcador de posición es realmente sólida, esta debería ser la respuesta seleccionada en mi opinión.
Chris James Champeau
1
Esto todavía causa un comportamiento desagradable cuando tienes una fila muy alta. Todas las demás filas se esconderán detrás de él. Agregaría esto al método de inicio:$(".must-have-class").css("height", $(ui.item).outerHeight());
Itzik Ben Hutta
6

Parece que clonar la fila no funciona bien en IE8, pero la solución original sí.

Probado con el jsFiddle .

vincentp
fuente
Gracias por configurar jsFiddle. Voy con la solución original porque, como Jez notó, las otras celdas de fila pueden cambiar el ancho al arrastrar una fila.
Roger
4

Llame a este código siguiente cuando su tabla esté lista para ser ordenada, esto se asegurará de que sus elementos td se arreglen sin romper la estructura de la tabla.

 $(".tableToSort td").each(function () {
            $(this).css("width", $(this).width());
        });  
Teoman shipahi
fuente
Sí, eso es más o menos lo mismo que mi respuesta, aunque la mía funciona thigual de bien td. Repara el colapso de la fila arrastrada y el colapso de la tabla, pero a costa de arreglar los anchos.
Keith
1

jsFiddle

Después de muchos intentos diferentes, acabo de probar una solución simple que completa la solución de Dave James Miller para evitar que la tabla se encoja mientras arrastra la fila más grande. Espero que ayude :)

// Make sure the placeholder has the same with as the orignal
var start = function(e, ui) {
    let $originals = ui.helper.children();
    ui.placeholder.children().each(function (index) {
        $(this).width($originals.eq(index).width());
    });
}
// Return a helper with preserved width of cells
var helper = function(e, tr) {
    let $helper = tr.clone();
    let $originals = tr.children();
    $helper.children().each(function (index) {
        $(this).width($originals.eq(index).outerWidth(true));
    });
    return $helper;
};
Ach
fuente
0

La solución de Keith está bien, pero produjo un pequeño caos en Firefox que no sumó los colspans sino que los indicó. (El viejo tipo de cuerda js duele en la rodilla)

reemplazando esta línea:

 cellCount += colspan;

con:

 cellCount += colspan-0;

Soluciona el problema. (Como js se ve obligado a tratar las variables como números en lugar de cadenas)

Max
fuente
0

La respuesta de Dave James Miller funcionó para mí, pero debido al diseño de las divisiones del contenedor en mi página, el ayudante que arrastra con el cursor del mouse está desplazado de la posición de mi mouse. Para solucionar eso, agregué lo siguiente a la devolución de llamada auxiliar

$(document.body).append($helper);

Aquí está la devolución de llamada completa con la línea anterior agregada:

helper: function (e, tr) {
  var $originals = tr.children();
  var $helper = tr.clone();
  $helper.children().each(function (index) {
    // Set helper cell sizes to match the original sizes
    $(this).width($originals.eq(index).width());
  });

  // append it to the body to avoid offset dragging
  $(document.body).append($helper);

  return $helper;
}

Hubiera agregado esto como un comentario a la respuesta de Dave, pero no tenía suficiente representante en esta cuenta.

Shea Riley
fuente
Después de leer la documentación de jQuery, descubrí que el ordenable también toma una opción "appendTo" que especifica a qué elemento se agrega el asistente.
Shea Riley
0

Parece que el disableSelection()método es malo y está en desuso hoy en día. Ya no puedo usar entradas de texto dentro de la fila ordenable en Mozilla Firefox 35.0. Simplemente ya no es enfocable.

Miika Kontio
fuente
-1
$(function() {
    $( "#sort tbody" ).sortable({
        update: function () {
                                var order = $(this).sortable("toArray").join();
                                $.cookie("sortableOrder", order);
                        }
    });
    if($.cookie("sortableOrder")){
        var order = $.cookie("sortableOrder").split(",");
        reorder(order, $("#sort tbody"));
    }
    function reorder(aryOrder, element){
      $.each(aryOrder, function(key, val){
              element.append($("#"+val));
      });
    }
  });
Peter
fuente
1
¡Se necesita más explicación!
Afsanefda
-1
.sortable({
    helper: function (e, ui) {
        ui.children().each(function () {
            $(this).width($(this).width());
        });
        return ui;
    }
});
mspiderv
fuente
-4

Aplique el ordenable al elemento tbody de la tabla y simplemente configure el asistente para 'clonar', como se describe en la API de jquery-ui

$("$my-table-tbody").sortable({
    helper: "clone"
});
Regis Zaleman
fuente
1
No parece ayudar
Andrew