How can I disable sort on a specific element?
Asked Answered
A

2

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?

Alkane answered 10/2, 2016 at 13:31 Comment(4)
So you are or you are not using jQuery UI sortable?Nanaam
@epascarello, no I'm sorry. I removed the tag.Alkane
what happens when you try it? can we have a jsfiddle?Bewilder
its the filter option = filter: '.static',Saccharoid
U
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>
Uncork answered 10/2, 2016 at 14:58 Comment(1)
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 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.)Figurant
H
2

You need to add two options when creating the sortable instance:

    var container = document.getElementById('my-list');
    var sortable = Sortable.create(container, {
       // 1.) Exclude all elements having class '.static' from being draggable.
       draggable: 'li:not(.static)',
       // 2.) Prevent all elements having class '.static' from being moved.
       onMove(e) {
         return e.related.className.indexOf('static') === -1;          
       }
    });

Why should I not use filter option?

Looking at the accepted answer, it seems like the filter option would do the job. But whenever you use multiple instances with interchangeable elements, it becomes problematic if one of the lists get empty. Suddenly you won't be able to add elements to that list again. This is due to Sortable's internal logic, which still treats the .static element as a draggable element. Even setting the emptyInsertThreshold option to be really high won't fix that, because for Sortable, the list is not empty.

Example 1 using filter option: (Try to add 'Apple' to COMPANIES - it won't work!)

var el = document.getElementById('items');
var sortable = Sortable.create(el, {
   draggable: 'li:not(.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>
<ul id="items">
    <li class="static">FRUITS</li>
    <li>Strawberry</li>
    <li>Banana</li>
    <li>Peach</li>
    <li>Apple</li>
</ul><ul id="items2">
    <li class="static">COMPANIES</li>
</ul>

Example 2 using draggable option: (Try to add 'Apple' to COMPANIES - it works!)

var el = document.getElementById('items');
var sortable = Sortable.create(el, {
   draggable: 'li:not(.static)',
   group: {
     name: 'list'
   },
   onMove(e) {
     return e.related.className.indexOf('static') === -1;          
   }
});
var items2 = document.getElementById('items2');
var sortable = Sortable.create(items2, {
   draggable: 'li:not(.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>
<ul id="items">
    <li class="static">FRUITS</li>
    <li>Strawberry</li>
    <li>Banana</li>
    <li>Peach</li>
    <li>Apple</li>
</ul><ul id="items2">
    <li class="static">COMPANIES</li>
</ul>
Haerle answered 4/3, 2022 at 11:4 Comment(2)
This works nice, but when there are no elements in the group one cant move elemnts from other group to itRational
@Rational Thank's for pointing that out! I updated my answer, seems likefilter is not the best way to make it work.Haerle

© 2022 - 2024 — McMap. All rights reserved.