jquery UI Sortable с таблицей и шириной tr

Я использую jQuery UI для сортировки, чтобы сделать сетку таблицы сортируемой. Код, кажется, работает нормально, но поскольку я не добавляю ширину к tds, когда я перетаскиваю tr, содержимое сжимается.

Например; если моя строка таблицы составляет 500 пикселей, когда я начинаю перетаскивать, она становится 300 пикселей. Я предполагаю, что это происходит потому, что в сетке не определена ширина. Это потому, что я использую два класса для td (fix и liquid).

Класс fix делает td равным ширине содержимого, а liquid делает ширину td равной 100%. Это мой подход к таблице сетки без необходимости назначать ширину tds.

Любая идея, как сделать сортируемую работу с моим подходом?


person Community    schedule 20.08.2009    source источник
comment
Ответ Ярослава - НАСТОЯЩИЙ MVP!   -  person Brade    schedule 22.05.2015
comment
У меня была такая же проблема, я думаю, что у @Yaroslav есть правильный ответ для работы с таблицами, о чем спрашивает ОП.   -  person doz87    schedule 24.03.2016


Ответы (11)


Я нашел ответ здесь.

Я немного изменил его, чтобы клонировать строку вместо добавления ширины к оригиналу:

  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;
  },
person Dave James Miller    schedule 03.09.2009
comment
@Dave James Miller Как бы вы заставили работать вариант заполнителя? - person shaun5; 27.03.2012
comment
Дэйв, спасибо, что поделились этим, я сделал jsFiddle, чтобы показать различия между оригинальным, измененным и неисправленным: jsfiddle.net/bgrins/tzYbU. Я также обновлю исходный пост вашим решением. - person Brian Grinstead; 31.05.2012
comment
Это работает довольно хорошо, но я думаю, что есть еще одна небольшая проблема; когда вы перетаскиваете строку, остальные столбцы таблицы могут изменить ширину из-за отсутствия строки. Я думаю, что их ширина также должна быть исправлена ​​​​... - person Jez; 07.11.2012
comment
Как я могу применить это исправление к событию перетаскивания, вспомогательный метод работает по-другому. stackoverflow.com/questions/15432555/ - person John Magnolia; 15.03.2013
comment
Вам не хватает точки с запятой после width()). Не могу отредактировать к сожалению. В остальном отличный ответ. - person Grzegorz Kaczan; 23.05.2013
comment
@GrzegorzKaczan Спасибо, исправлено. - person Dave James Miller; 26.05.2013
comment
Это решило ту же проблему, что и у меня. Отличный ответ, я бы порекомендовал это решение всем - person Doidgey; 02.10.2013
comment
Это сэкономило мне столько работы. Он должен быть отмечен как правильный ответ. - person Andrew Bessa; 24.04.2015
comment
Ответ @yaroslav отлично сработал для меня. .ui-sortable-width { display: table } - person stevenspiel; 28.04.2015
comment
При использовании измененного исправления, если у вас есть установленный переключатель в строке, которую вы перемещаете, вы теряете состояние... Но не с исходным исправлением... jsfiddle.net/nw232gaj - person Pouki; 06.01.2016
comment
Я обнаружил, что ширина приводит к тому, что заполненные ячейки не совсем правильные. Я поменял на $(this).width($originals.eq(index).outerWidth()); - person Barry Carlyon; 22.11.2016
comment
я думаю, это происходит потому, что класс начальной загрузки table (v4 alpha5) - person Sagiv b.g; 06.02.2017
comment
Хорошо, я понял, почему это решение не сработало для меня, я использовал col-sm-* классы ботстрапа. поэтому я удалил его и использовал другой подход, чтобы получить аналогичную ширину дизайна <colgroup>, например: <colgroup> <col span="1" style="width: 8.3%;"> <col span="1" style="width: 25%;"> <col span="1" style="width: 50%;"> <col span="1" style="width: 16.6%;"> </colgroup> - person Sagiv b.g; 06.02.2017
comment
@Jez - ширина (или ширина) строки или ячеек также должна применяться к заполнителю. Кажется, лучше копировать ширину ячеек из помощника в заполнитель, корректируя отступы и границы по мере необходимости, вместо того, чтобы просто применять ширину к строке. - person Borgboy; 21.02.2017

Я думаю, это может помочь:

.ui-sortable-helper {
    display: table;
}
person Yaroslav    schedule 27.02.2015
comment
Как это не лучший ответ? Одна простая строка CSS исправляет это для меня. - person jcrowson; 03.04.2015
comment
Я согласен! Вы не поверите, как одна простая строка CSS исправит вашу сортируемую таблицу — эксперты Stackoverflow сбиты с толку! - person Brade; 22.05.2015
comment
Это ответ. Спасибо @Ярослав - person Steffi; 03.06.2015
comment
Это НЕ общее решение, и оно приведет к другому виду перетаскиваемой строки. - person Tomas M; 04.08.2015
comment
В моем случае это привело только к тому, что tr уменьшился МЕНЬШЕ, чем раньше, но он все еще меняет размер и выглядит неправильно. - person little_birdie; 29.08.2015
comment
@little_birdie: Я полностью с тобой согласен. Тем не менее, простота и (я думаю) небольшой размер этого решения в значительной степени компенсируют этот недостаток, ИМХО. - person Ifedi Okonkwo; 12.11.2015
comment
У меня сработало лучше, чем лучшее решение. В верхнем решении были некоторые ошибки при перетаскивании за пределы родительского div. - person Max Flex; 30.11.2015
comment
Это решение очень хорошее, но оно может повлиять на другие списки, которые не являются таблицами. Мое предложение: вы отредактируете свой ответ, чтобы сделать его более конкретным. Вот так =› table tr.ui-sortable-helper { display: table !important; } - person Rafael Gomes Francisco; 15.12.2015
comment
Хорошее решение. Кроме того, если вы хотите, чтобы ячейки вашего помощника также отображались одинаково, вы должны установить для них ширину. Например, если вы полагаетесь на плагин DataTable для установки ширины вашей ячейки, он не будет работать. - person actaram; 19.07.2016
comment
это не работает ни для меня, ни для другого проголосовавшего решения. есть идеи почему? - person Sagiv b.g; 06.02.2017
comment
Исправление не работает с таблицами без определенной ширины в td. Когда строка перетаскивается, td (без ширины - встроенный или css) привязывает/соответствует своей ширине содержимому. Может быть, это и ваш случай @Sagivb.g - person dunli; 07.03.2018
comment
Большое спасибо. - person thedude12; 13.03.2021

Выбранный здесь ответ является действительно хорошим решением, но в нем есть одна серьезная ошибка, которая очевидна в оригинальной скрипте JS (http://jsfiddle.net/bgrins/tzYbU/): попробуйте перетащить самую длинную строку (Да благословит вас Бог, мистер Роузуотер), и остальная ширина ячеек исчезнет.

Это означает, что зафиксировать ширину ячейки на перетаскиваемой ячейке недостаточно — нужно также зафиксировать ширину на таблице.

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

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

JS-скрипт: http://jsfiddle.net/rp4fV/3/

Это устраняет проблему схлопывания таблицы после перетаскивания первого столбца, но вводит новую проблему: если вы изменяете содержимое таблицы, размеры ячеек теперь фиксированы.

Чтобы обойти это при добавлении или изменении содержимого, вам необходимо очистить установленную ширину:

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

Затем добавьте свой контент, затем снова исправьте ширину.

Это все еще не полное решение, так как (особенно с таблицей) вам нужен заполнитель для перетаскивания. Для этого нам нужно добавить функцию при запуске, которая создает заполнитель:

$('#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-скрипт: http://jsfiddle.net/rp4fV/4/

person Keith    schedule 22.05.2013
comment
Спасибо, вы экономите мое время - person super pantera; 26.09.2013
comment
Техника заполнителя здесь просто убийственная! Полностью решил мою проблему. - person jessegavin; 27.02.2014
comment
Это решение на самом деле действительно хорошее, и техника заполнителя действительно надежная, на мой взгляд, это должен быть выбранный ответ. - person Chris James Champeau; 15.03.2016
comment
Это по-прежнему вызывает неприятное поведение, когда у вас очень высокий ряд. Все остальные ряды спрячутся за ним. Я бы добавил это в метод запуска: $(".must-have-class").css("height", $(ui.item).outerHeight()); - person Itzik Ben Hutta; 15.01.2017

Кажется, что клонирование строки не работает в IE8, но исходное решение работает.

Протестировано с помощью jsFiddle.

person vincentp    schedule 20.09.2012
comment
Спасибо за настройку jsFiddle. Я использую исходное решение, потому что, как заметил Джез, другие ячейки строки могут изменить ширину при перетаскивании строки. - person Roger; 21.06.2013

Вызовите этот следующий код, когда ваша таблица будет готова к сортировке, это гарантирует, что ваши элементы td имеют фиксированную структуру без нарушения структуры таблицы.

 $(".tableToSort td").each(function () {
            $(this).css("width", $(this).width());
        });  
person Teoman shipahi    schedule 23.05.2013
comment
Да, это почти то же самое, что и мой ответ, хотя мой работает как для th, так и для td. Он исправляет схлопывание перетаскиваемой строки и коллапс таблицы, но за счет исправления ширины. - person Keith; 28.05.2013

jsFiddle

После множества разных попыток я просто попробовал простое решение, которое дополняет решение Дейва Джеймса Миллера, чтобы предотвратить сжатие таблицы при перетаскивании самой большой строки. Я надеюсь, что это поможет :)

// 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;
};
person Ach    schedule 22.08.2019

Решение Кейта в порядке, но вызвало небольшой хаос в Firefox, который не суммировал столбцы, а показывал их. (Старая боль в колене типа js string)

заменив эту строку:

 cellCount += colspan;

с участием:

 cellCount += colspan-0;

Устраняет проблему. (Поскольку js вынужден обрабатывать переменные как числа, а не строки)

person Max    schedule 17.11.2014

Ответ Дэйва Джеймса Миллера сработал для меня, но из-за расположения контейнеров div на моей странице помощник, который перетаскивает курсор мыши, смещается от положения моей мыши. Чтобы исправить это, я добавил следующее в обратный вызов помощника

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

Вот полный обратный вызов с добавленной строкой выше:

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

Я бы добавил это как комментарий к ответу Дэйва, но мне не хватило репутации в этой учетной записи.

person Shea Riley    schedule 07.01.2015
comment
Прочитав документацию по jQuery, я обнаружил, что sortable также принимает параметр appendTo, указывающий, к какому элементу добавляется помощник. - person Shea Riley; 09.01.2015

Кажется, что disableSelection() - метод плохой и устарел в настоящее время. Я больше не могу использовать текстовые вводы внутри сортируемой строки в Mozilla Firefox 35.0. Это просто больше не фокусируется.

person Miika Kontio    schedule 21.01.2015

Примените сортировку к элементу tbody таблицы и просто установите помощника на «клонирование», как описано в jquery-ui API

$("$my-table-tbody").sortable({
    helper: "clone"
});
person Regis Zaleman    schedule 03.12.2013
comment
Не похоже, чтобы помочь. - person Andrew; 21.02.2014

person    schedule
comment
Требуется больше объяснений! - person Afsanefda; 17.08.2019