简体   繁体   English

处理重叠的jQuery可排序列表

[英]Dealing with overlapping jQuery sortable lists

This is a bit of an obscure issue, but I'm using jQuery Sortables and trying to get two connected lists working together nicely when one is positioned as fixed . 这是一个不起眼的问题,但我正在使用jQuery Sortables并试图让两个连接列表在一个定位为fixed时很好地协同工作。 It all works fine until you scroll the page a bit such that the two lists end up positioned on top of each other. 一切正常,直到你滚动页面,使两个列表最终位于彼此的顶部。 Then the lists seem to get confused as to which one should be receiving the item that's being dragged, meaning you get a bunch of jittering happening as it appears/disappears in each list. 然后列表似乎对哪一个应该接收被拖动的项目感到困惑,这意味着当它在每个列表中出现/消失时会发生一堆抖动。

It looks like the issue is that both lists are handling the mouse/sort events since the item being dragged is technically over both lists, but what I want is to have the overlayed list (ie the position: fixed one) swallow the events so that the underlying main list doesn't try to receive the item. 看起来问题是两个列表都在处理鼠标/排序事件,因为被拖动的项目在技术上是在两个列表上,但我想要的是使覆盖列表(即position: fixed )吞下事件,以便底层主列表不会尝试接收该项目。

Here's the minimal code example: 这是最小的代码示例:

<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>

So the question is, how do I fix it? 所以问题是,我该如何解决?

I ended up fixing this issue by extending the built in sortable functionality to create a fixedSortable that detects and selectively ignores hovering over lists when there's a overlay in place. 我最后通过扩展内置的sortable功能来修复此问题,以创建一个fixedSortable ,当存在覆盖时,它会检测并选择性地忽略在列表上的悬停。 For my purposes, I just hard coded the rules, since that suited my needs/time constraints, but you should be able to make it completely generic without too much effort. 出于我的目的,我只是硬编码规则,因为这符合我的需求/时间限制,但你应该能够完全通用而不需要太多努力。

Firstly here's the code (explanation below): 首先是代码(下面的解释):

<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 adapting this yourself, you'll need to change the two commented lines marked above. 如果您自己进行调整,则需要更改上面标记的两条注释行。 Basically the if statements should evaluate to true (and thus return false) if the item being hovered over ( item.instance.element and containerCache.sortable.element ) is not the overlay and the event ( this ) is occurring within the bounds of the overlay. 如果正在悬停的项目( item.instance.elementcontainerCache.sortable.element不是覆盖并且事件( this )发生在覆盖范围内,则if语句基本上应该评估为true(因此返回false)覆盖。 This way the main list never receives events in the location of the page where the overlay is. 这样,主列表永远不会在覆盖所在的页面位置接收事件。 So in this code the main list doesn't receive any events if they occur in the top 87 pixels of the screen, since that's where my fixed overlay was (which is not quite accurate in this dumbed down example, but hopefully it still makes sense). 因此,在此代码中,如果主列表出现在屏幕的前87个像素中,则主列表不会接收任何事件,因为那是我的固定叠加层所在的位置(在这个愚蠢的示例中这不太准确,但希望它仍然有意义)。

I implemented the change to sortable for it to take the z-index into account. 我将更改实现为可排序,以便将z-index考虑在内。

See my fork here: https://github.com/david04/jquery-ui/commit/feaf94ebabacee4d11b5e98c412d795d68ca9d51 (10 lines of code, quite simple change) 请看我的叉子: https//github.com/david04/jquery-ui/commit/feaf94ebabacee4d11b5e98c412d795d68ca9d51 (10行代码,非常简单的更改)

You'll need to add the option compareZIndex=true when calling sortable . 调用sortable时,您需要添加选项compareZIndex=true

This is the bug I think you're encountering, and the fix is a lot simpler: 这是我认为你遇到的错误,修复更简单:

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

I ran into this problem on a page where I have one list vertically above a second list. 我在一个页面上遇到了这个问题,我在第二个列表的垂直上方有一个列表。 Even though overflow is set to hidden, the unseen overflow of the top list is still blocking the move over event for the list below it (this can be confirmed by setting overflow to auto in the top list to help visualize the overlap). 即使溢出被设置为隐藏,顶部列表的看不见的溢出仍然阻止其下方列表的移动事件(这可以通过在顶部列表中设置溢出到自动来帮助可视化重叠来确认)。 It's a z-index issue. 这是一个z指数问题。

My fix was to place this code in the sortable stop event: 我的修复是将此代码放在可排序的停止事件中:

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

What I'm doing here is explicitly hiding the top list elements, leaving only the top 5 visible so that there is no DOM offset overlap between the top and bottom list. 我在这里做的是显式隐藏顶部列表元素,只留下前5个可见,以便顶部和底部列表之间没有DOM偏移重叠。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM