dynamically enable/disable jquery sortable item

25,104

Solution 1

I ran into the same problem, that the items option doesn't seem to remove items which had been previously enabled.

The cancel option, however, does. Note that the disabled items will shift around to make room for the sortable ones (the spot is still available as a drop target), but dragging the disabled items themselves will not work. Using a disabled class also makes it easy to change the style based on whether or not the item is sortable (see on jsfiddle).

The code here is partially based on Bah Bah the Lamb's answer, but it has been greatly tidied and simplified.

The 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>

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

The CSS:

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

.disabled {
  color:#ddd;
}

Solution 2

I had a similar problem and found an easy solution (but in my example I am using a sortable ul not a table, as there is more freedom with mark-up in ul's).

The idea behind it is to leave the list and all its items sortable, but remove the handle, thus disabling the individual item's ability to sort, as seen in this code

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

Solution 3

Try using the disabled option. http://jqueryui.com/demos/sortable/#option-disabled

Solution 4

I've been trying to do the same thing. I really wanted the items feature rather than disabled. As pointed out above, there is a weakness in the jQueryUI implementation whereby the sortable don't refresh the items list should the items matched by the selectors change.

To get around this, I simply destroyed and reinstantiated the sortabled. I've adapted Hannele's JSfiddle to demonstrate (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)"
        });
});
Share:
25,104

Related videos on Youtube

annette
Author by

annette

Updated on July 09, 2022

Comments

  • annette
    annette almost 2 years

    I have table rows that are sortable depending on whether certain radio buttons are checked or not. The sortables are initialized on document.ready as follows:

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

    I have the following function attached to the radio buttons (ids prefixed "active_") onchange which either adds or removes the ui-state-disabled class attribute from table rows (dynamic ids prefixed "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!
    }
    

    If I select a radio button that should make a previously un-sortable row sortable, it works and I can drag and drop the row. The problem is if I select a radio button to make a row that previously was sortable, un-sortable, I can still drag and drop it. The setter .sortable("option", "items", "tr:not..etc") doesn't appear "un-register" a row if it was previously sortable. I also tried .sortable("refresh") with no luck. And I have checked to see if the class attribute is being changed with an alert and it is.

    Any help with this would be greatly appreciated.

  • Ronny
    Ronny over 10 years
    using cancel works for me, even without making room when dragging over like you mentioned - Probably fixed since your answer.
  • Hannele
    Hannele over 10 years
    @Ronny I think there is a way to configure the lack of drop-target, but I can't figure it out just now.

Related