Работа с перекрывающимися сортируемыми списками jQuery - PullRequest
9 голосов
/ 04 ноября 2010

Это немного неясная проблема, но я использую jQuery Sortables и пытаюсь заставить два связанных списка работать вместе, когда один позиционируется как fixed. Все работает нормально, пока вы не прокрутите страницу так, что два списка окажутся друг над другом. Затем списки, похоже, запутались в отношении того, какой из них должен получать перетаскиваемый элемент, а это означает, что в каждом списке возникает куча дрожания, когда он появляется / исчезает.

Похоже, проблема в том, что оба списка обрабатывают события мыши / сортировки, так как перетаскиваемый элемент технически находится над обоими списками, но я хочу, чтобы наложенный список (то есть position: fixed один) проглотил события, так что основной список не пытается получить элемент.

Вот минимальный пример кода:

<html>
<head>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.6/jquery-ui.min.js"></script>
    <style type="text/css">
        ul { list-style-type: none; padding: 0; float: left; }
        li { margin: 5px; padding: 5px; width: 500px; border: solid 1px #F00; background-color: #FFF; }
        #overlayed { position: fixed; top: 0; background-color: #000; margin: 20px; padding: 10px; }
        #overlayed li { width: 50px; float: left; }
    </style>
    <script type="text/javascript">
        $(function() {
            $("ul").sortable({ connectWith: "ul", opacity: 0.6 }).disableSelection();
        });
    </script>
</head>
<body>
<div id="overlayed"> 
    <ul>
        <li>Item X</li>
        <li>Item Y</li>
        <li>Item Z</li>
    </ul>
</div>
<br/><br/><br/><br/><br/>
<ul>
    <li>Item 01</li>
    <li>Item 02</li>
    <li>Item 03</li>
    <li>Item 04</li>
    <li>Item 05</li>
    <li>Item 06</li>
    <li>Item 07</li>
    <li>Item 08</li>
    <li>Item 09</li>
    <li>Item 10</li>
    <li>Item 11</li>
    <li>Item 12</li>
    <li>Item 13</li>
    <li>Item 14</li>
    <li>Item 15</li>
    <li>Item 16</li>
    <li>Item 17</li>
    <li>Item 18</li>
    <li>Item 19</li>
    <li>Item 20</li>
    <li>Item 21</li>
    <li>Item 22</li>
    <li>Item 23</li>
    <li>Item 24</li>
    <li>Item 25</li>
    <li>Item 26</li>
    <li>Item 27</li>
    <li>Item 28</li>
    <li>Item 29</li>
    <li>Item 30</li>
</ul>
</body>
</html>

Так вот вопрос, как мне это исправить?

Ответы [ 4 ]

5 голосов
/ 07 декабря 2010

Я решил эту проблему, расширив встроенную функциональность sortable, чтобы создать fixedSortable, который обнаруживает и выборочно игнорирует наведение на списки, когда наложение на месте. Для моих целей я просто жестко закодировал правила, так как это соответствовало моим потребностям / временным ограничениям, но вы должны сделать его полностью универсальным без особых усилий.

Во-первых, вот код (пояснение ниже):

<html>
<head>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.6/jquery-ui.min.js"></script>
    <style type="text/css">
        ul { list-style-type: none; padding: 0; float: left; }
        li { margin: 5px; padding: 5px; width: 500px; border: solid 1px #F00; background-color: #FFF; }
        #overlayed { position: fixed; top: 0; background-color: #000; margin: 20px; padding: 10px; }
        #overlayed li { width: 50px; float: left; }
    </style>
    <script type="text/javascript">
        (function ($, undefined) {
            $.widget("ui.fixedSortable", $.ui.sortable, {
                _init: function () {
                    this.element.data("sortable", this.element.data("fixedSortable"));
                    return $.ui.sortable.prototype._init.apply(this, arguments);
                },
                _create:function() {
                    var result = $.ui.sortable.prototype._create.apply(this, arguments);
                    this.containerCache.sortable = this;
                    return result;
                },
                _intersectsWithPointer: function (item) {
//This line....
                    if (item.instance.element.hasClass("main-list") && this.positionAbs.top + this.offset.click.top < $(window).scrollTop() + 87) { 
                        return false;
                    }
                    return $.ui.sortable.prototype._intersectsWithPointer.apply(this, arguments);
                },
                _intersectsWith: function(containerCache) {
//Also this line....
                    if (containerCache.sortable.element.hasClass("main-list") && this.positionAbs.top + this.offset.click.top < $(window).scrollTop() + 87) {
                        return false;
                    }
                    return $.ui.sortable.prototype._intersectsWith.apply(this, arguments);
                }
            });
        })(jQuery);

        $(function() {
            $("ul").fixedSortable({ connectWith: "ul", opacity: 0.6 }).disableSelection();
        });
    </script>
</head>
<body>
<div id="overlayed"> 
    <ul>
        <li>Item X</li>
        <li>Item Y</li>
        <li>Item Z</li>
    </ul>
</div>
<br/><br/><br/><br/><br/>
<ul class="main-list" >
    <li>Item 01</li>
    <li>Item 02</li>
    <li>Item 03</li>
    <li>Item 04</li>
    <li>Item 05</li>
    <li>Item 06</li>
    <li>Item 07</li>
    <li>Item 08</li>
    <li>Item 09</li>
    <li>Item 10</li>
    <li>Item 11</li>
    <li>Item 12</li>
    <li>Item 13</li>
    <li>Item 14</li>
    <li>Item 15</li>
    <li>Item 16</li>
    <li>Item 17</li>
    <li>Item 18</li>
    <li>Item 19</li>
    <li>Item 20</li>
    <li>Item 21</li>
    <li>Item 22</li>
    <li>Item 23</li>
    <li>Item 24</li>
    <li>Item 25</li>
    <li>Item 26</li>
    <li>Item 27</li>
    <li>Item 28</li>
    <li>Item 29</li>
    <li>Item 30</li>
</ul>
</body>
</html>

Если вы адаптируете это самостоятельно, вам нужно изменить две закомментированные строки, отмеченные выше. В основном операторы if должны принимать значение true (и, следовательно, возвращать false), если элемент, на который наведен курсор (item.instance.element и containerCache.sortable.element), равен , а не , наложение и событие (this) происходят внутри границы наложения. Таким образом, основной список никогда не получает события в той части страницы, где находится оверлей. Таким образом, в этом коде основной список не получает никаких событий, если они происходят в верхних 87 пикселях экрана, поскольку именно там находился мой фиксированный оверлей (что не совсем точно в этом дурацком примере, но, надеюсь, это все еще имеет смысл ).

3 голосов
/ 16 мая 2014

Я применил изменение к сортируемому, чтобы оно учитывало z-индекс.

См. Мой ответ здесь: https://github.com/david04/jquery-ui/commit/feaf94ebabacee4d11b5e98c412d795d68ca9d51 (10 строк кода, довольно простое изменение)

Вам нужно будет добавить опцию compareZIndex=true при вызове sortable.

2 голосов
/ 18 ноября 2011

Я думаю, что вы столкнулись с этой ошибкой, и исправить это намного проще:

http://bugs.jqueryui.com/ticket/7065

0 голосов
/ 10 мая 2012

Я столкнулся с этой проблемой на странице, где у меня есть один список вертикально над вторым списком. Несмотря на то, что переполнение установлено как скрытое, невидимое переполнение верхнего списка по-прежнему блокирует событие перемещения по списку под ним (это можно подтвердить, установив для переполнения автоматический в верхнем списке, чтобы помочь визуализировать перекрытие). Это проблема z-index.

Мое исправление заключалось в том, чтобы поместить этот код в событие сортируемой остановки:

 //expliclty hide the overflow items
 $('.topList .item:gt(5)').hide();
 $('.topeList .item:first').show();

Я явно скрываю элементы верхнего списка, оставляя видимыми только верхние 5, чтобы не перекрывать смещение DOM между верхним и нижним списком.

...