Question

I have a container with a list of draggable items and container with a list of sortable items. The draggables & the sortable list is connected, allowing the user to drag clones of the draggables to the sorted list.

The draggable items appear in a vertical list, however the sortable items appear in a horizontal list, achieved by floating them left. The container of the sortable items has its overflow set to auto, resulting in a horizontal scrollbar if the contents overflow. The two containers appear right next to each other, the draggables to the left & the sortables to the right.

The problem I'm experiencing is when the container of sortable items is scrolled to the right, dragging from the draggables' container immediately fires the sortables' events. It appears as if the contents of the sortables' container is moved behind the draggables' container.

Here is my code:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">
<head>
    <title>Sortables in scrollable divs</title>
    <script type="text/javascript" language="JavaScript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
    <script type="text/javascript" language="JavaScript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.1/jquery-ui.min.js"></script>
    <script type="text/javascript" language="javascript">
        $(function() {
            $("#sortable").sortable({
                start: function(event, ui) {
                    if (ui.helper !== null) console.log("sortable \"" + ui.helper.text() + "\" drag start");
                },
                stop: function(event, ui) {
                    if (ui.helper !== null) console.log("sortable \"" + ui.helper.text() + "\" drag stopped");
                    if (ui.item !== null) console.log("sortable item \"" + ui.item.text() + "\" drag stopped");
                }
            });

            $("#sortable").sortable("disable");

            $("#draggable li").draggable({
                connectToSortable: '#sortable',
                helper: 'clone',
                revert: 'invalid',
                cursor: "default",
                cursorAt: { top: -5, left: -5 },
                start: function(event, ui) {
                    if (ui.helper !== null) console.log("draggable \"" + ui.helper.text() + "\" drag start");
                },
                stop: function(event, ui) {
                    if (ui.helper !== null) console.log("draggable \"" + ui.helper.text() + "\" drag stopped");
                }
            });

            $("#container2").mouseenter(function() {
                console.log("enter sortable container");
                $("#sortable").sortable("enable");
            }).mouseleave(function() {
                console.log("leaving sortable container");
                $("#sortable").sortable("disable");
            });

            $("#draggable, #sortable").disableSelection();
        });
    </script>
    <style type="text/css">
        html, body, p, td, th, li, input, select, option, textarea
        {
            font-family: Verdana, Arial, Helvetica, sans-serif;
            font-size: 11px;
            color:#343E41;
        }

        .wrapper
        {
            position: relative;
            width: 100%;
            height: 100%;
            overflow: hidden;
            height: expression(this.parentNode.offsetHeight + "px");
        }

        .scroll-wrapper
        {
            position: relative;
            width: 100%;
            height: 100%;
            overflow: auto;
            height: expression(this.parentNode.offsetHeight + "px");
        }

        #container1
        {
            float:left;
            width:200px;
            height:400px;
            overflow:auto;
            border:solid #000 1px;
            margin:5px;
        }

        #container2
        {
            float:left;
            width:600px;
            height:400px;
            overflow:auto;
            border:solid #000 1px;
            margin:5px;
        }

        ul#draggable
        {
            padding:0;
            margin:0;
            list-style-image:none;
            list-style-position:outside;
            list-style-type:none;
        }

        ul#draggable li
        {
            display:block;
            margin:5px;
            border:solid #000 1px;
            height:50px;
            width:150px;
        }

        ul#sortable
        {
            padding:0;
            margin:0;
            list-style-image:none;
            list-style-position:outside;
            list-style-type:none;
            height:380px;
            width:744px;
        }

        ul#sortable li
        {
            display:block;
            float:left;
            margin:5px;
            border:solid #000 1px;
            height:370px;
            width:50px;
            text-align:center;
        }
    </style>
</head>
<body>
    <form id="form1" action="">
        <div id="container1">
            <ul id="draggable">
                <li>1A</li>
                <li>2A</li>
                <li>3A</li>
                <li>4A</li>
                <li>5A</li>
                <li>6A</li>
                <li>7A</li>
                <li>8A</li>
                <li>9A</li>
                <li>10A</li>
                <li>11A</li>
                <li>12A</li>
            </ul>
        </div>
        <div id="container2">
            <ul id="sortable">
                <li class="ui-state-default">1</li>
                <li class="ui-state-default">2</li>
                <li class="ui-state-default">3</li>
                <li class="ui-state-default">4</li>
                <li class="ui-state-default">5</li>
                <li class="ui-state-default">6</li>
                <li class="ui-state-default">7</li>
                <li class="ui-state-default">8</li>
                <li class="ui-state-default">9</li>
                <li class="ui-state-default">10</li>
                <li class="ui-state-default">11</li>
                <li class="ui-state-default">12</li>
            </ul>
        </div>
    </form>
</body>

How can I avoid the sortable events to fire until the item is dragged over the sortable container?

Thanks in advance

Was it helpful?

Solution

It has been a long time since I posted this question and since then, new versions of jQuery & jQuery UI has been released.

In addition, the development team of jQuery UI added an example of draggables connected with sortables, were added.

So I have updated my original sample code above and modified it so that it maches my scenario. I wanted a horizontal scrolling sortable section that will automatically expand when new items have been added.

My example below has resolved my issue and the code looks much cleaner & simpler:

$(function () {
            $("#sortable").sortable({
                revert: true,
                start: function (event, ui) {
                    $(this).width($(this).width() + ui.helper.width() + 12);
                },
                stop: function (event, ui) {
                    var w = 0;
                    $(this).children("li").each(function () {
                        w += $(this).width() + parseInt($(this).css("margin-left")) + parseInt($(this).css("margin-right")) + 2;
                    });
                    $(this).width(w);
                }
            });

            var w = 0;
            $("#sortable").children("li").each(function () {
                w += $(this).width() + parseInt($(this).css("margin-left")) + parseInt($(this).css("margin-right")) + 2;
            });
            $("#sortable").width(w);

            $("#draggable li").draggable({
                connectToSortable: "#sortable",
                helper: "clone",
                revert: "invalid"
            });
            $("ul, li").disableSelection();
        });
html, body, p, td, th, li, input, select, option, textarea
                {
                        font-family: Verdana, Arial, Helvetica, sans-serif;
                        font-size: 11px;
                        color:#343E41;
                }

                .wrapper
                {
                        position: relative;
                        width: 100%;
                        height: 100%;
                        overflow: hidden;
                        height: expression(this.parentNode.offsetHeight + "px");
                }

                .scroll-wrapper
                {
                        position: relative;
                        width: 100%;
                        height: 100%;
                        overflow: auto;
                        height: expression(this.parentNode.offsetHeight + "px");
                }

                #container1
                {
                        float:left;
                        width:200px;
                        height:400px;
                        overflow:auto;
                        border:solid #000 1px;
                        margin:5px;
                }

                #container2
                {
                        float:left;
                        width:600px;
                        height:400px;
                        overflow:auto;
                        border:solid #000 1px;
                        margin:5px;
                }

                ul#draggable
                {
                        padding:0;
                        margin:0;
                        list-style-image:none;
                        list-style-position:outside;
                        list-style-type:none;
                }

                ul#draggable li
                {
                        display:block;
                        margin:5px;
                        border:solid #000 1px;
                        height:50px;
                        width:150px;
                }

                ul#sortable
                {
                        padding:0;
                        margin:0;
                        list-style-image:none;
                        list-style-position:outside;
                        list-style-type:none;
                        height:380px;
                }

                ul#sortable li
                {
                        display:block;
                        float:left;
                        margin:5px;
                        border:solid #000 1px;
                        height:370px;
                        width:50px;
                        text-align:center;
                }
           <script type="text/javascript" language="JavaScript" src="http://code.jquery.com/jquery-1.4.4.min.js"></script>
        <script type="text/javascript" language="JavaScript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.6/jquery-ui.min.js"></script>
 
    <form id="form1" action="">
    <div id="container1">
    <ul id="draggable">
    <li>1A</li>
    <li>2A</li>
    <li>3A</li>
    <li>4A</li>
    <li>5A</li>
    <li>6A</li>
    <li>7A</li>
    <li>8A</li>
    <li>9A</li>
    <li>10A</li>
    <li>11A</li>
    <li>12A</li>
    </ul>
    </div>
    <div id="container2">
    <ul id="sortable">
    <li class="ui-state-default">1</li>
    <li class="ui-state-default">2</li>
    <li class="ui-state-default">3</li>
    <li class="ui-state-default">4</li>
    <li class="ui-state-default">5</li>
    <li class="ui-state-default">6</li>
    <li class="ui-state-default">7</li>
    <li class="ui-state-default">8</li>
    <li class="ui-state-default">9</li>
    <li class="ui-state-default">10</li>
    <li class="ui-state-default">11</li>
    <li class="ui-state-default">12</li>
    </ul>
    </div>
    </form>

Thought someone, somewhere might like to do the same and needs some help :D

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