jquery UI Classificável com tabela e largura tr

155

Estou usando a interface do usuário do jQuery classificável para tornar minha grade da tabela classificável. O código parece funcionar bem, mas como não estou adicionando largura a tds, quando arrasto o trbotão reduz o conteúdo.

Por exemplo; se a linha da minha tabela tiver 500 px quando eu começar a arrastar, ela se tornará 300 px. Suponho que isso esteja acontecendo porque nenhuma largura é definida na grade. Isso porque eu estou usando duas classes para os td( fixe liquid).

A fixclasse faz com que a tdigual à largura do conteúdo e liquidfaz com que a tdlargura de 100%. É minha abordagem para tabela de grade sem ter que atribuir largura a tds.

Alguma idéia de como fazer um trabalho classificável com minha abordagem?

j0k
fonte
3
A resposta de Yaroslav é o mvp REAL!
Brade
Eu tive o mesmo problema, eu acho que @Yaroslav tem a resposta correta para lidar com mesas que é o que o OP é perguntando sobre
doz87

Respostas:

254

Encontrei a resposta aqui .

Modifiquei-o levemente para clonar a linha, em vez de adicionar larguras ao 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
fonte
@ Dave James Miller Como você faria a opção de espaço reservado funcionar?
shaun5
5
Dave, obrigado por compartilhar isso, criei um jsFiddle para mostrar as diferenças entre correção original, modificada e nenhuma correção aplicada: jsfiddle.net/bgrins/tzYbU . Também atualizarei a postagem original com sua solução.
Brian Grinstead
9
Isso funciona muito bem, mas acho que ainda há um pequeno problema; Quando você está arrastando / soltando a linha, o restante das colunas da tabela pode mudar de largura devido à linha ausente. Eu acho que suas larguras precisam ser corrigidos, bem ...
Jez
1
Isso me salvou muito trabalho. Deve ser marcado como a resposta correta.
Andrew Bessa
3
Descobri que a largura estava resultando em células acolchoadas que não estavam QUITAS. Eu troquei por$(this).width($originals.eq(index).outerWidth());
Barry Carlyon 22/11
166

Eu acho que isso pode ajudar:

.ui-sortable-helper {
    display: table;
}
Yaroslav
fonte
13
Como essa não é a resposta principal? Uma simples linha de CSS corrige isso para mim.
Jcrowson
8
Concordo! Você não vai acreditar como uma simples linha de CSS corrige sua tabela classificável - os especialistas em Stackoverflow ficam confusos!
Brade
3
Esta é a resposta. Obrigado @Yaroslav
Steffi
3
Esta não é uma solução geral e irá resultar em diferentes olhar da linha arrastada
Tomas M
13
Esta solução é muito boa, mas pode afetar outras listas que não são tabela. Minha sugestão é que você edite sua resposta para torná-la mais específica. Assim => tabela tr.ui-sortable-helper {display: table! Important; }
Rafael Gomes Francisco
29

A resposta selecionada aqui é uma solução muito boa, mas tem um bug grave que é aparente no violino JS original ( http://jsfiddle.net/bgrins/tzYbU/ ): tente arrastar a linha mais longa ( Deus o abençoe, senhor) (Água de rosas ) e o restante das larguras das células colapsam.

Isso significa que corrigir as larguras das células na célula arrastada não é suficiente - você também precisa corrigir as larguras na tabela.

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

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

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

Isso corrige o problema do recolhimento da tabela depois que você arrasta a primeira coluna, mas introduz uma nova: se você alterar o conteúdo da tabela, os tamanhos das células serão corrigidos.

Para contornar isso ao adicionar ou alterar o conteúdo, você precisa limpar as larguras definidas:

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

Adicione seu conteúdo e corrija as larguras novamente.

Essa ainda não é uma solução completa, pois (especialmente com uma tabela) você precisa de um espaço reservado para soltar. Para isso, precisamos adicionar uma função no início que construa o espaço reservado:

$('#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
fonte
Obrigado, você salvar o meu tempo
super-pantera
A técnica de espaço reservado aqui é assassina! Resolvi totalmente o meu problema.
Jessegavin
1
Essa solução é realmente muito boa e a técnica de espaço reservado é realmente sólida. Essa deve ser a resposta selecionada na minha opinião.
precisa
1
Isso ainda causa um comportamento desagradável quando você tem uma linha muito alta. Todas as outras linhas se escondem atrás dela. Eu adicionaria isso ao método start:$(".must-have-class").css("height", $(ui.item).outerHeight());
Itzik Ben Hutta 15/01
6

Parece que a clonagem da linha não funciona bem no IE8, mas a solução original funciona.

Testado com o jsFiddle .

vincentp
fonte
Obrigado por configurar o jsFiddle. Eu vou com a solução original porque, como Jez observou, as outras células da linha podem mudar de largura ao arrastar uma linha.
Roger
4

Chame este código a seguir quando sua tabela estiver pronta para ser classificada, isso garantirá que seus elementos td sejam corrigidos sem quebrar a estrutura da tabela.

 $(".tableToSort td").each(function () {
            $(this).css("width", $(this).width());
        });  
Teoman shipahi
fonte
Sim, é praticamente o mesmo que a minha resposta, embora a minha funcione thtambém td. Ele corrige o recolhimento da linha arrastada e a tabela, mas com o custo de corrigir as larguras.
Keith
1

jsFiddle

Depois de várias tentativas diferentes, tentei apenas uma solução simples que completa a solução de Dave James Miller para evitar que a tabela encolha enquanto arrasta a maior linha. Espero que ajude :)

// 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
fonte
0

A solução de Keith é boa, mas causou um pequeno estrago no Firefox, que não adicionou os colspans, mas os cedeu. (A velha dor tipo js string no joelho)

substituindo esta linha:

 cellCount += colspan;

com:

 cellCount += colspan-0;

Corrige o problema. (Como js é forçado a tratar as variáveis ​​como números em vez de cadeias)

Máx.
fonte
0

A resposta de Dave James Miller funcionou para mim, mas devido ao layout das divs do contêiner na minha página, o auxiliar que arrasta com o cursor do mouse é deslocado da posição do mouse. Para corrigir isso, adicionei o seguinte ao retorno de chamada auxiliar

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

Aqui está o retorno de chamada completo com a linha acima adicionada:

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

Eu adicionaria isso como um comentário à resposta de Dave, mas não tinha representante suficiente nessa conta.

Shea Riley
fonte
Depois de ler a documentação do jQuery, descobri que o classificável também possui uma opção "appendTo" que especifica em qual elemento o auxiliar é anexado.
Shea Riley
0

Parece que disableSelection()- o método está ruim e obsoleto hoje em dia. Não posso mais usar entradas de texto dentro de uma linha classificável Mozilla Firefox 35.0. Apenas não é mais focável.

Miika Kontio
fonte
-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
fonte
1
É necessária mais explicação!
Afsanefda 17/08/19
-1
.sortable({
    helper: function (e, ui) {
        ui.children().each(function () {
            $(this).width($(this).width());
        });
        return ui;
    }
});
mspiderv
fonte
-4

Aplique a classificável ao elemento tbody da tabela e defina o auxiliar como 'clone', conforme descrito na API do jquery-ui

$("$my-table-tbody").sortable({
    helper: "clone"
});
Regis Zaleman
fonte
1
Não parece ajudar.
21414 Andrew Andrew