jquery UI Możliwość sortowania według szerokości tabeli i tr


155

Używam sortowania interfejsu użytkownika jQuery, aby umożliwić sortowanie siatki tabeli. Wydaje się, że kod działa dobrze, ale ponieważ nie dodam szerokości do tds, przeciąganie trgo zmniejsza zawartość.

Na przykład; jeśli mój wiersz tabeli ma rozmiar 500 pikseli, kiedy zacznę przeciągać, zmieni się na 300 pikseli. Zakładam, że dzieje się tak, ponieważ w siatce nie określono szerokości. Dzieje się tak, ponieważ używam dwóch klas dla tds ( fixi liquid).

fixKlasa sprawia, że tdrówna szerokości zawartości i liquidsprawia, że tdszerokość 100%. To moje podejście do tabeli grid bez konieczności przypisywania szerokości do tds.

Masz jakiś pomysł, jak zrobić sortowalną pracę z moim podejściem?


3
Odpowiedzią Jarosława jest PRAWDZIWY mvp!
Brade

Miałem ten sam problem, myślę, że @Yaroslav ma poprawną odpowiedź na radzenie sobie ze stołami, o co pyta OP
tuz87

Odpowiedzi:


254

Tutaj znalazłem odpowiedź .

Zmodyfikowałem go nieznacznie, aby sklonować wiersz, zamiast dodawać szerokości do oryginału:

  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 Jak sprawiłbyś, aby opcja symbolu zastępczego działała?
shaun5

5
Dave, dzięki za udostępnienie tego, stworzyłem jsFiddle, aby pokazać różnice między oryginalnym, zmodyfikowanym i bez zastosowanej poprawki: jsfiddle.net/bgrins/tzYbU . Zaktualizuję również oryginalny post z Twoim rozwiązaniem.
Brian Grinstead

9
Działa to całkiem nieźle, ale myślę, że jest jeszcze jeden drobny problem; kiedy przeciągasz / upuszczasz wiersz, pozostałe kolumny tabeli mogą zmienić szerokość z powodu brakującego wiersza. Wydaje mi się, że ich szerokości też muszą zostać poprawione ...
Jez.

1
To zaoszczędziło mi dużo pracy. Powinna być oznaczona jako prawidłowa odpowiedź.
Andrew Bessa,

3
Odkryłem, że szerokość powodowała, że ​​wyściełane komórki nie były w porządku. Zamieniłem się na$(this).width($originals.eq(index).outerWidth());
Barry Carlyon

166

Myślę, że to może pomóc:

.ui-sortable-helper {
    display: table;
}

13
Dlaczego to nie jest najlepsza odpowiedź? Jedna prosta linia CSS rozwiązuje to za mnie.
jcrowson

8
Zgadzam się! Nie uwierzysz, jak jedna prosta linia kodu CSS naprawia twoją sortowalną tabelę - eksperci Stackoverflow są zdumieni!
Brade

3
To jest odpowiedź. Dzięki @Yaroslav
Steffi

3
To NIE jest rozwiązanie ogólne i spowoduje inny wygląd przeciągniętego rzędu
Tomas M

13
To rozwiązanie jest bardzo dobre, ale może mieć wpływ na inne listy, które nie są tabelami. Sugeruję, abyś zredagował swoją odpowiedź, aby była bardziej szczegółowa. W ten sposób => tabela tr.ui-sortable-helper {display: table! Important; }
Rafael Gomes Francisco

29

Wybrana tutaj odpowiedź jest naprawdę fajnym rozwiązaniem, ale ma jeden poważny błąd, który jest widoczny w oryginalnych skrzypcach JS ( http://jsfiddle.net/bgrins/tzYbU/ ): spróbuj przeciągnąć najdłuższy wiersz ( God Bless You, Mr. . Rosewater ), a pozostałe szerokości komórek zapadają się.

Oznacza to, że ustalenie szerokości komórek w przeciągniętej komórce nie wystarczy - musisz również naprawić szerokości w tabeli.

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

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

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

Rozwiązuje to problem zwijania tabeli po przeciągnięciu pierwszej kolumny, ale wprowadza nową: jeśli zmienisz zawartość tabeli, rozmiary komórek są teraz ustalone.

Aby obejść ten problem podczas dodawania lub zmiany treści, musisz wyczyścić ustawione szerokości:

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

Następnie dodaj zawartość, a następnie ponownie popraw szerokość.

To wciąż nie jest kompletne rozwiązanie, ponieważ (szczególnie w przypadku tabeli) potrzebujesz symbolu zastępczego kropli. W tym celu musimy dodać na początku funkcję, która buduje symbol zastępczy:

$('#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/


Dzięki, oszczędzasz mój czas
super pantera

Ta technika zastępcza jest zabójcza! Całkowicie rozwiązało mój problem.
jessegavin

1
To rozwiązanie jest naprawdę dobre, a technika zastępcza jest naprawdę solidna, moim zdaniem powinna to być wybrana odpowiedź.
Chris James Champeau

1
Nadal powoduje to nieprzyjemne zachowanie, gdy masz bardzo wysoki rząd. Wszystkie inne rzędy ukryją się za nim. Dodałbym to do metody startowej:$(".must-have-class").css("height", $(ui.item).outerHeight());
Itzik Ben Hutta

6

Wygląda na to, że klonowanie wiersza nie działa dobrze w IE8, ale oryginalne rozwiązanie tak.

Przetestowane za pomocą jsFiddle .


Dzięki za skonfigurowanie jsFiddle. Idę z oryginalnym rozwiązaniem, ponieważ Jez zauważył, że inne komórki wiersza mogą zmieniać szerokość podczas przeciągania wiersza.
Roger,

4

Wywołaj poniższy kod, gdy tabela jest gotowa do posortowania, dzięki czemu upewnisz się, że elementy td są ustalone z bez przerywania struktury tabeli.

 $(".tableToSort td").each(function () {
            $(this).css("width", $(this).width());
        });  

Tak, to prawie to samo, co moja odpowiedź, chociaż moja działa thrównie dobrze dla jak td. Naprawia zwijanie się przeciągniętego wiersza i zwijanie tabeli, ale kosztem naprawy szerokości.
Keith

1

jsFiddle

Po wielu różnych próbach po prostu wypróbowałem proste rozwiązanie, które uzupełnia rozwiązanie Dave'a Jamesa Millera, aby zapobiec kurczeniu się tabeli podczas przeciągania największego wiersza. Mam nadzieję, że to pomoże :)

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

0

Rozwiązanie Keitha jest w porządku, ale spowodowało małe spustoszenie w Firefoksie, które nie zsumowało parametrów, ale je wskazało. (Stary js typu struna ból w kolanie)

zastępując tę ​​linię:

 cellCount += colspan;

z:

 cellCount += colspan-0;

Rozwiązuje problem. (Ponieważ js jest zmuszony traktować zmienne jako liczby zamiast łańcuchów)


0

Odpowiedź Dave'a Jamesa Millera zadziałała dla mnie, ale ze względu na układ kontenerów div na mojej stronie, element pomocniczy, który przeciąga kursor myszy, jest przesunięty w stosunku do pozycji mojej myszy. Aby to naprawić, do wywołania zwrotnego pomocnika dodałem następujący kod

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

Oto pełne wywołanie zwrotne z dodaną powyższą linią:

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

Dodałbym to jako komentarz do odpowiedzi Dave'a, ale nie miałem wystarczającej reputacji na tym koncie.


Po przeczytaniu dokumentacji jQuery stwierdziłem, że sortable przyjmuje również opcję „appendTo”, która określa, do jakiego elementu dołączany jest helper.
Shea Riley

0

Wygląda na to, że disableSelection()metoda jest obecnie zła i przestarzała. Nie mogę już używać wprowadzania tekstu w wierszu z możliwością sortowania w Mozilla Firefox 35.0. Po prostu nie można już na nim skupić się.


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

1
Potrzeba więcej wyjaśnień!
Afsanefda

-1
.sortable({
    helper: function (e, ui) {
        ui.children().each(function () {
            $(this).width($(this).width());
        });
        return ui;
    }
});

-4

Zastosuj sortable do elementu tbody tabeli i po prostu ustaw helpera na 'clone', jak opisano w API jquery-ui

$("$my-table-tbody").sortable({
    helper: "clone"
});

1
Nie wydaje się pomagać.
Andrew,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.