Sortable icon indicating copy to clipboard operation
Sortable copied to clipboard

Nested sortable max level.

Open tiennguyen1991 opened this issue 4 years ago • 5 comments

How do I find it? "deep , maxDeep"

"pull": function(event) { if(deep > maxDeep) return false; return true; },

tiennguyen1991 avatar Jul 22 '20 09:07 tiennguyen1991

You'll have to define your own functions to figure this out. The question is out of scope, but happy to keep it open for a while so others can answer.

waynevanson avatar Aug 31 '20 23:08 waynevanson

Very late to comment, but take a look at this comment: https://github.com/SortableJS/Sortable/issues/1979#issuecomment-757687788

So if you take a look at the source code for nested lists: https://github.com/SortableJS/Sortable/blob/0656d6245f222c4dc26cd08777d7bd04b7699c29/index.html#L312-L318

we can classify list items as those that do not have div children and "folders" as those that have children, specifically a div with class "list-group". Disclaimer, this is just my specific use case if you're familiar with that interface there; otherwise, the only other way I can describe the following is like a "filesystem". Using the aforementioned comments code, set every "list-group-item" to have an attribute "data-level" to specify depth, then:

onMove(ev) {
            const lvl = parseInt(ev.related.getAttribute("data-level"));
            if (ev.dragged.querySelector(".list-group") && lvl >= 2)
                return false;
            const diff = parseInt(ev.dragged.getAttribute("data-level")) - lvl;
            ev.dragged.setAttribute("data-level", lvl);
            for (let x of ev.dragged.querySelectorAll(".list-group-item")) {
                x.setAttribute("data-level",
                    parseInt(x.getAttribute("data-level")) - diff
                )
            }
        }

where that last for loop is for constantly updating the level. return false will prevent the item from dropping. 3 is the depth. It's up to you to make up whatever conditions and initial levels are given.

For my specific use case, I only allowed one nested folder. If the level start from 0, then I could have one folder inside another folder but that was it. That second folder could still contain items though. To accomplish this, the if statement should have an AND i.e. && that asks ev.dragged.querySelector(".list-group") basically checking if the currently dragged item is a folder.

Andrew-Chen-Wang avatar Apr 01 '21 06:04 Andrew-Chen-Wang

@Andrew-Chen-Wang I also needed to limit to a depth of 1 nested folder. i started with your code, but ended up with this, i think it achieves the same. I used JQuery to turn event.to in a JQuery object. It counts the number of parents with the nested-sortable class:

onMove(event) {
        const lvl = $(event.to).parents('.nested-sortable').length;
        if (lvl > 1)
        {
            return false;
        }
    }

Hope this helps someone else.

VincentVanWijk avatar May 31 '21 12:05 VincentVanWijk

if use in project JQuery code @VincentVanWijk work. but if i don't use jquery, how get current lvl for item?

reimax avatar Dec 16 '21 05:12 reimax

I spent some time searching internet and nothing worked, so I made my own version which works:

<html lang="en">

<head>
    <meta charset="UTF-8">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.15.2/Sortable.min.js"></script>
</head>

<body>
    <div id="nestedDemo" class="list-group col nested-sortable">
        <div class="list-group-item is-folder">Folder 1
            <div class="list-group nested-sortable folder">
                <div class="list-group-item">File 1</div>
                <div class="list-group-item">File 2</div>
                <div class="list-group-item">File 3</div>
            </div>
        </div>
        <div class="list-group-item is-folder">Folder 2
            <div class="list-group nested-sortable folder"></div>
        </div>
        <div class="list-group-item is-folder">File 4</div>
        <div class="list-group-item is-folder">Folder 3
            <div class="list-group nested-sortable folder">
                <div class="list-group-item">File 5</div>
            </div>
        </div>
        <div class="list-group-item">File 6</div>
    </div>

    <script>
        // Loop through each nested sortable element
        nestedSortables = document.getElementsByClassName('nested-sortable');
        for (var i = 0; i < nestedSortables.length; i++) {
            new Sortable(nestedSortables[i], {
                group: 'nested',
                animation: 150,
                fallbackOnBody: true,
                swapThreshold: 0.65,
                onMove(ev) {
                    var into_folder = ev.to.classList.contains('folder');
                    var is_folder = ev.dragged.classList.contains('is-folder');

                    if (into_folder && is_folder)
                        return false;

                    return true;
                }
            });
        }
    </script>
    <style>
        .list-group-item {
            margin: 0 0 0 10px;
        }
    </style>

</body>

</html>

ondrejsudoma avatar Jan 17 '24 15:01 ondrejsudoma