Динамически включать/отключать сортировку jquery

У меня есть строки таблицы, которые сортируются в зависимости от того, отмечены ли определенные переключатели или нет. Сортировки инициализируются на document.ready следующим образом:

$(document).ready(function() {
    // Return a helper with preserved width of cells
    // handy code I got from http://lanitdev.wordpress.com/2009/07/23/make-table-rows-sortable-using-jquery-ui-sortable/
    var fixHelper = function(e, ui) {
        ui.children().each(function() {
            $(this).width($(this).width());
        });
        return ui;
    };
    // #opts = table id; tr.ui-state-disabled class = rows not sortable
    $("#opts tbody").sortable({
        items: 'tr:not(.ui-state-disabled)',
        cursor: 'crosshair',
        helper: fixHelper
    }).disableSelection();
});

У меня есть следующая функция, прикрепленная к переключателям (ids prefixed "active_" ) onchange, которая либо добавляет, либо удаляет атрибут класса ui-state-disabled из строк таблицы (динамические идентификаторы с префиксом "opt _" ):

    var toggleDrag = function(i){
    if ($('#active_'+i+'-0').is(':checked')) {
        $('#opt_'+i).addClass('ui-state-disabled');
    }
    if ($('#active_'+i+'-1').is(':checked')) {
        $('#opt_'+i).removeClass();
    }
    $("#opts tbody").sortable("option", "items", "tr:not(.ui-state-disabled)");
    //$("#opts tbody").sortable("refresh");
    //alert($('#opt_'+i).attr('class')); - alert indicates that the class attribute is being changed
    //$("#opts tbody").sortable("option", "cursor", "auto"); - this works!
}

Если я выберу переключатель, который должен сделать ранее не сортируемую сортировку строк, он будет работать, и я могу перетащить строку. Проблема в том, что если я выбираю переключатель, чтобы сделать строку, которая ранее была сортируемой, не сортируемой, я все равно могу ее перетащить. Установитель .sortable("option", "items", "tr:not..etc") не отображает "un-register" строку, если она была ранее отсортирована. Я также попробовал .sortable( "обновить" ) без везения. И я проверил, меняется ли атрибут класса с предупреждением, и это.

Любая помощь с этим будет принята с благодарностью.

Ответы

Ответ 1

Я столкнулся с той же проблемой, что параметр items, похоже, не удаляет элементы, которые ранее были включены.

Опция cancel, однако, делает. Обратите внимание, что отключенные элементы будут перемещаться, чтобы освободить место для сортируемых (место по-прежнему доступно как цель перетаскивания), но перетаскивание отключенных элементов не будет работать. Использование класса disabled также упрощает изменение стиля на основе того, сортируется ли элемент (см. jsfiddle).

Код здесь частично основан на ответе Баха Баха, но он был очень пригоден и упрощен.

html:

<ul id="sorted-list">
   <li>
       <p><input type="checkbox" checked="true" /> Item 1</p>
    </li>
   <li>
       <p class="disabled"><input type="checkbox" /> Item 2</p>
   </li>
   <li>
       <p><input type="checkbox" checked="true" /> Item 3</p>
   </li>
</ul>

jQuery:

$("#sorted-list").sortable({
    cancel:".disabled"
});

// add or remove the 'disabled' class based on the value of the checkbox
$("#sorted-list input").click(function() {
    if (this.checked) {
        $(this.parentElement).removeClass("disabled");
    } else { 
        $(this.parentElement).addClass("disabled");
    }
});

CSS:

li {
  border: 1px solid #aaa;
  background-color: #eee;
  color:#555;
  padding: 5px;
}

.disabled {
  color:#ddd;
}

Ответ 2

У меня была аналогичная проблема, и я нашел простое решение (но в моем примере я использую сортируемую ul, а не таблицу, поскольку в ul есть больше свободы с надписью).

Идея заключается в том, чтобы оставить список и все его элементы сортируемыми, но удалить дескриптор, тем самым отключив возможность сортировки отдельных элементов, как показано в этом коде

<ul id="sorted-list">
    <li>
        <div class="handle sortable">
            <p>Item 1</p>
            <input type="button" value="Disable Sort" />
        </div>
    </li>
    <li>
        <div class="handle sortable">
            <p>Item 2</p>
            <input type="button" value="Disable Sort" />
        </div>
    </li>
    <li>
        <div class="handle sortable">
            <p>Item 3</p>
            <input type="button" value="Disable Sort" />
        </div>
    </li>
    <li>
        <div class="handle sortable">
            <p>Item 4</p>
            <input type="button" value="Disable Sort" />
        </div>
    </li>
</ul>
<script>
    $("#sorted-list").sortable({
        items: "li",
        handle: ".handle.sortable"
    });
    $("#sorted-list").find("input").click(function() {
        if ($(this).closest(".handle").hasClass("sortable"))
            $(this).val("Enable Sort").closest(".handle").removeClass("sortable");
        else $(this).val("Disable Sort").closest(".handle").addClass("sortable");
    });
</script>

Ответ 4

Я пытался сделать то же самое. Я действительно хотел, чтобы функции элементов, а не отключены. Как отмечалось выше, в реализации jQueryUI наблюдается слабость, при которой сортируемые не обновляют список элементов, если элементы, соответствующие селекторам, изменяются.

Чтобы обойти это, я просто уничтожил и восстановил сортировку. Я адаптировал Hannele JSfiddle для демонстрации (http://jsfiddle.net/Sxg8D/140/).

$("#sorted-list").sortable({
    items:"li:not(.disabled)"
});

$("#sorted-list input").click(function() {
    if (this.checked) {
        $(this.parentElement).removeClass("disabled");
    } else { 
        $(this.parentElement).addClass("disabled");
    }

    $("#sorted-list")
        .sortable( "destroy" )
        .sortable({
            items:"li:not(.disabled)"
        });
});

Ответ 5

Я знаю, что это старо, но имеет аналогичную проблему. У меня были отсортированные элементы в группах. Я хотел, чтобы определенные группы были отсортированы в любом месте, а некоторые - только для отдельных групп.

<div id="sortBlock">
    <div id="noSort class="itemBlock">
        <div class="item">
        <div class="item">
    </div>
    <div id="canSort" class="itemBlock">
        <div class="item">
        <div class="item">
    </div>
</div>

Элементы из noSort могут сортироваться в любом месте. Элементы из canSort могут сортироваться только в других блоках canSort.

$("#sortBlock").sortable({
    items: "> div.itemBlock > .item"   // this makes sure only the sub items will be sortable
});

Тогда установка этого правила после инициализации, похоже, сделала трюк.

$("#sortBlock").sortable( "option", "items", "> div:not(#noSort) > .item");

пытался делать это динамически в событиях запуска/остановки, но это делало трюк, а не "почему", поэтому хорошо тестируйте.