Question

I'm using jQuery UI sortable on an unordered list. I want every list item to be sortable except for the one that has an .active class:

<ul>
    <li class="active">Item 1</li> <!-- This item should NOT be sortable -->
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
</ul>

So I've initialized the sortable like this:

$("ul").sortable({
    items: "li:not('.active')"
});

The problem is that clicking a list item moves the .active class to that item. For example, if I click the third item, I get:

<ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li class="active">Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
</ul>

But the sortable doesn't seem to "notice" that change, so the third item remains sortable.

How do I make the items option apply even when the .active class is added to a different item, so that the sortable handles it how I want?

Was it helpful?

Solution

You should dynamically check for this in the start event.

If the target element has the active class, cancel the action :

$('#list').sortable({
    items: 'li',
    start: function(e, ui){
        if ( ui.item.hasClass('active') ) {
        // "return false" does not work - the widget does not seem to consider
        //  that it should cancel the whole dragging, and enters a broken state.
        //
        // When this callback is executed, the "start" event is not
        // fully handled yet.
        // You have to wait for its end, then cancel the action :
            setTimeout(function(){
                $('#list').sortable('cancel');
            }, 0);
        }
    }
});

fiddle - jQuery 1.8.3, jQuery-ui 1.9.2

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top