6

I'm having difficulty disabling sorting on a specific li in my ul. I'm using SortableJS.

<ul id="items">
    <li class="static">
        <div class="image"><img src="image.jpg" /></div>
        <div class="text">Static</div>
        <div class="clearboth"></div>
    </li>
    <li>
        <div class="image"><img src="image.jpg" /></div>
        <div class="text">Dynamic</div>
        <div class="clearboth"></div>
    </li>
    <li>
        <div class="image"><img src="image.jpg" /></div>
        <div class="text">Dynamic</div>
        <div class="clearboth"></div>
    </li>
</ul>

One li with class static should NOT be sortable. The others should be sortable.

var el = document.getElementById('items');

var sortable = new Sortable(el, {
    onUpdate: function (evt) {
        var itemEl = evt.item;

        // here happens some stuff
    },
    filter: '.js-remove',
    onFilter: function (evt) {
        // here happens some stuff
    }
});

I know you can do it in jQuery UI sortable like this:

$( ".sortable" ).sortable({
    cancel: ".static"
});

How can I do this in SortableJS?

Bob Stein
  • 16,271
  • 10
  • 88
  • 101
nielsv
  • 6,540
  • 35
  • 111
  • 215

2 Answers2

11

Further to @BenG comment, you need to use filter instead of cancel.

var el = document.getElementById('items');
var sortable = Sortable.create(el, {
   filter: ".static"
});
<script src="//cdnjs.cloudflare.com/ajax/libs/Sortable/1.4.2/Sortable.min.js"></script>
<link href="http://rubaxa.github.io/Sortable/st/app.css" rel="stylesheet" />
<ul id="items" class="block__list block__list_words">
    <li>item 1</li>
    <li class="static">item 2</li>
    <li>item 3</li>
</ul>
Mosh Feu
  • 28,354
  • 16
  • 88
  • 135
  • 19
    The `filter` option disables **dragging**. But the element can still be rearranged by dropping a different element on top of it. To disable **dropping**. you need [the technique](https://jsbin.com/voroqedeqo/edit?html,js,output) of checking the `related` property in an `onMove` event handler: `onMove: function (e) { return e.related.className.indexOf('static') === -1; }` (This answer does fulfill the original question, but just to augment it a bit for a closely related issue. For posterity.) – Bob Stein Jul 04 '19 at 20:51
2

As Bob Stein mentionend in the comments:

You need to add both:

  • the filter: 'selector' property
  • the onMove: function (e) { return e.related.className.indexOf('static') === -1; } callback listener function

to completely prevent an element from being rearranged at the beginning or end of a list.

Working with multiple sortable instances:
If you have multiple lists, from which you can exchange elements, you would add the same code to the sortable instances. This is because a dragged element from another sortable instance does not call the callback functions of the sortable instance to be added, but those of its source sortable instance. See this example below:

var el = document.getElementById('items');
var sortable = Sortable.create(el, {
   filter: ".static",
   group: {
     name: 'list'
   },
   onMove(e) {
     return e.related.className.indexOf('static') === -1;          
   }
});
var items2 = document.getElementById('items2');
var sortable = Sortable.create(items2, {
   filter: ".static",
   group: {
     name: 'list'
   },
   onMove(e) {
     return e.related.className.indexOf('static') === -1;          
   }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/Sortable/1.14.0/Sortable.min.js"></script>
<link href="http://rubaxa.github.io/Sortable/st/app.css" rel="stylesheet" />
<ul id="items" class="block__list block__list_words">
    <li class="static">FRUITS</li>
    <li>Strawberry</li>
    <li>Banana</li>
    <li>Peach</li>
</ul><ul id="items2" class="block__list block__list_words">
    <li class="static">COMPANIES</li>
    <li>Microsoft</li>
    <li>Apple</li>
    <li>Intel</li>
</ul>
noChance
  • 418
  • 2
  • 13
  • This works nice, but when there are no elements in the group one cant move elemnts from other group to it – Jan May 26 '23 at 21:12