3

My fiddle: http://jsfiddle.net/Yc9WY/42/

What you'll see here are two groups, each with 3 droppable containers defined. You can move events from group 1 to group 2, and into any slot. This works just fine.

Once a group is full, I would like to give the user the ability to sort that group by moving events up and down. They should still be able to move the event out of the group if they choose however.

You'll see my commented out code where I began to integrate the sortable library, but am getting odd behavior.

Note: I cannot replace my draggable/dropable with sortable solely. I need explicitly defined droppable areas (3 per group) so that an event can exist in slot 1 and 3 of group 1.

Here's my code

$(document).ready(function() {

// $(".sort").sortable({
//     revert: true
// });

$(".drag").draggable({
    //connectToSortable: ".sort",
    revert: true
    //helper: clone
});

$(".sort").droppable({
    drop: function(event, ui) {

        if (!($(this).children(".drag").size() == 1)) {
            $(this).append(ui.draggable);

            ui.draggable.css({
                left: 0,
                top: 0
            });
        }
    }

});
});

<div>Group 1:
<ul class="parent">
    <li class="sort"><a href="" class="drag">event 1</a></li>
    <li class="sort"><a href="" class="drag">event 2</a></li>
    <li class="sort"></li>
</ul>
</div>
<div>
Group 2
<ul class="parent">
    <li class="sort"></li>
    <li class="sort"><a href="" class="drag">event 3</a></li>
    <li class="sort"><a href="" class="drag">event 4</a></li>
</ul>
</div>

I'm really struggling with this, thanks all!

2
  • Please add the relevant code to your question. While jsfiddle is great for testing, it shouldn't be relied on for question context. Commented Apr 26, 2012 at 21:50
  • Sorry about that Dan, code added Commented Apr 26, 2012 at 21:57

1 Answer 1

7

I cracked it :)

Fiddle (and CSS): http://jsfiddle.net/jhogervorst/CPA5Y/

HTML:

<div class="group">
    <h1>Group 1</h1>

    <ul class="parent">
        <li class="droppable"><span class="draggable">Item 1</span></li>
        <li class="droppable"><span class="draggable">Item 2</span></li>
        <li class="droppable"></li>
    </ul>
</div>

<div class="group">
    <h1>Group 2</h1>

    <ul class="parent">
        <li class="droppable"><span class="draggable">Item 3</span></li>
        <li class="droppable"></li>
        <li class="droppable"><span class="draggable">Item 4</span></li>
    </ul>
</div>​

JavaScript:

$(".draggable").draggable({
    revert: true,
    revertDuration: 0
});

$(".droppable").droppable({
    activeClass: "active",
    hoverClass: "hover",

    accept: function (draggable) {
        // The droppable (li element).
        var droppable = $(this);

        // The droppable which contains the draggable, i.e., the parent element of the draggable (li element).
        var draggablesDropable = draggable.parent();

        // Is the draggable being dragged/sorted to the same group?
        // => We could just sort it, because there's always enough space inside the group.
        if (droppable.parent().is(draggablesDropable.parent())) {
           return true;
        }

        // Nope, the draggable is being dragged/sorted to another group.
        // => Is there an empty droppable left in the group to which the draggable is being dragged/sorted?
        else if (droppable.parent().find(".draggable").size() < droppable.parent().find(".droppable").size()) {
            return true;
        }

        // Nothing true?
        return false;
    },

    drop: function(event, ui) {
        // The droppable (li element).
        var droppable = $(this);

        // The draggable (span element).
        var draggable = ui.draggable;

        // The droppable which contains the draggable, i.e., the parent element of the draggable (li element).
        var draggablesDropable = draggable.parent();

        // Is the draggable being dragged to it's own droppable?
        // => Abort, there's nothing to drag/sort!
        if (droppable.is(draggablesDropable)) {
            return;
        }

        // Is the draggable being dragged to an empty droppable?
        else if (!droppable.find(".draggable").size()) {
            // Just drop the draggable there.
            droppable.append(draggable);
        }

        // Is the draggable being dragged/sorted to the same group?
        // => We can just sort it, because there's always enough space inside the group.
        else if (droppable.parent().is(draggablesDropable.parent())) {
            // Is the draggable being dragged up?
            if (droppable.parent().find(".droppable").index(draggablesDropable) > droppable.parent().find(".droppable").index(droppable)) {
                // Add the dragged draggable's droppable before the droppable.
                draggablesDropable.insertBefore(droppable);
            }

            // No, the draggable is being dragged down.
            else {
                // Add the dragged draggable's droppable after the droppable.
                draggablesDropable.insertAfter(droppable);
            }
        }

        // Nope, the draggable is being dragged/sorted to another group.
        // => Is there an empty droppable left in the group to which the draggable is being dragged/sorted?
        else if (droppable.parent().find(".draggable").size() < droppable.parent().find(".droppable").size()) {
            // Find the first empty droppable in which the draggable is being dragged/sorted.
            var emptyDroppable = $($.grep(droppable.parent().find(".droppable"), function (item) {
                // Are there draggables inside this droppable?
                // => Return TRUE if not.
                return !$(item).find(".draggable").size();
            })).first();

            // Clone the dragged draggable's droppable before itself, because we need to remember it's position after moving it.
            var draggablesDropableClone = draggablesDropable.clone().insertBefore(draggablesDropable);

            // Is the draggable being dragged above the empty droppable?
            if (droppable.parent().find(".droppable").index(emptyDroppable) > droppable.parent().find(".droppable").index(droppable)) {
                // Add the dragged draggable's droppable before the droppable.
                draggablesDropable.insertBefore(droppable);
            }

            // No, the draggable is being dragged below the empty droppable.
            else {
                // Add the dragged draggable's droppable after the droppable.
                draggablesDropable.insertAfter(droppable);
            }

            // Remove the position of the dragged draggable, because there's still some css left of the dragging.
            draggable.css({"top": 0, "left": 0});

            // Add the first empty droppable before the cloned draggable's droppable. Remove the latter afterwards.
            draggablesDropableClone.before(emptyDroppable).remove();
        }
    }
});​
Sign up to request clarification or add additional context in comments.

11 Comments

Hi Jonathan, your code actually does the exact same thing mine does :) - Maybe I wasn't clear on what the problem was. Once you fill a column up with 3 events, try and drag the bottom one to the top. I.E, Sort the events in the column. That's what I am looking for.
@JasonWells Try dragging the darker grey part of the boxes. (I've added an icon indicating the sortable area: jsfiddle.net/jhogervorst/CPA5Y/1)
Ah I see. Thanks! What would be optimal is if the user could still grab the link and have it be sortable within the same group, but turn into a draggable if outside of the original group. This way I am not relying on my users selecting an area next to the text/link. Does that make sense?
Yeah, I definitely see your point. Can't you make a sortable spanning two columns with just two empty items? With some CSS you could achieve the same as I made. --- Edit: Hmm, now I think about it that seems not possible. Items would jump to other positions when sorting. Difficult one …
I'm working on it. Kind of difficult though. Are there always just three events in a group?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.