滚动可拖动项目的内容时禁用 jQuery 拖动

发布于 2024-12-28 22:17:56 字数 680 浏览 2 评论 0原文

我通常不会提出此类问题/答案,但我想我会这样做,因为我已经看到这个问题被问了 20 多次,但没有一个答案真正有效。简而言之,问题是,如果您在可拖动 jQuery 项目内的任何位置有可滚动内容(overflow: auto;),则当您单击并拖动滚动条时,父可拖动容器也会随之拖动。因此,我花了一些时间来研究解决方案,

下面是一些可能会出现此问题的 html 示例:

<div class="draggable" style="width:100px;height:100px;">
  <div id="content" style="width:80px;height:80px;overflow:auto;">
    Nullam quis risus eget urna mollis ornare vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam id dolor id nibh ultricies vehicula ut id elit.
  </div>
</div>

将元素初始化为可拖动的典型方法如下:

$(".draggable").draggable()

I don't normally make this sort of question / answer, but figured I'd do so, since I've seen this question asked 20+ times, and not a single answer actually works. In short, the problem is that if you have scrollable content (overflow: auto; anywhere inside of a draggable jQuery item, when you click and drag the scrollbar's the parent draggable container drags along with it. So, I spent some time working up a solution.

Here's an example of some html that would present this problem:

<div class="draggable" style="width:100px;height:100px;">
  <div id="content" style="width:80px;height:80px;overflow:auto;">
    Nullam quis risus eget urna mollis ornare vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam id dolor id nibh ultricies vehicula ut id elit.
  </div>
</div>

The typical way you initialize an element to be draggable, is something like this:

$(".draggable").draggable()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

慕巷 2025-01-04 22:17:56

我建议基于 [1] 和 PriorityMark 提供的解决方案的组合的解决方案。这个解决方案工作更可靠,而且我认为它也更高效。

$(".draggable").draggable({
    start: function(event) {
        var content = $(this).children('.content');

        // if we're scrolling, don't start and cancel drag
        if (event.originalEvent.pageX-content.offset().left > content.innerWidth())
        {
            console.log('should-cancel');
            $(this).trigger("mouseup");
            return false;
        }
    }
});

为了实现这一点,我稍微调整了示例 DOM(但这不应该是一个大问题):

<div class="draggable" style="width:100px;height:100px;overflow:auto;">
  <div class="content" style="width:80px;height:80px;">
    Nullam quis risus eget urna mollis ornare vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam id dolor id nibh ultricies vehicula ut id elit.
  </div>
</div>​

请注意,这里的 draggable div 具有 overflow,而不是内容 div。对于解决方案来说,这并不重要,但我不想添加额外的 div 级别,因为这并不是严格必要的。

这是 jsfiddle

[1] - 监听鼠标事件...除了 div 的溢出:滚动滚动条?

I suggest a solution based on a mix of [1] and the solution provided by PriorityMark. This solution works more reliably and I think it's a little more efficient as well.

$(".draggable").draggable({
    start: function(event) {
        var content = $(this).children('.content');

        // if we're scrolling, don't start and cancel drag
        if (event.originalEvent.pageX-content.offset().left > content.innerWidth())
        {
            console.log('should-cancel');
            $(this).trigger("mouseup");
            return false;
        }
    }
});

For this to work, I slightly adjusted the example DOM (but this shouldn't be that big a problem):

<div class="draggable" style="width:100px;height:100px;overflow:auto;">
  <div class="content" style="width:80px;height:80px;">
    Nullam quis risus eget urna mollis ornare vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam id dolor id nibh ultricies vehicula ut id elit.
  </div>
</div>​

Please note that here the draggable div has the overflow, not the content div. For the solution it doesn't really matter, but I didn't want to have to add an extra div-level, since it's not strictly necessary to make the point.

Here is the jsfiddle.

[1] - listen for mouse events … except a div's overflow:scroll scrollbar?

终弃我 2025-01-04 22:17:56

解决方案是绑定到您初始化的元素以及任何该元素子元素上的滚动事件。然后,当任何子元素调用滚动命令时,找到该元素的所有可拖动父元素,并在该元素上设置滚动数据元素。

在 jQuery UI 的当前版本 (1.8.16) 下,当您将鼠标放在滚动条上时,启动事件总是会启动,并沿树向上传播,因此该解决方案在我的测试中效果很好。

$(".draggable").draggable({
    start: function() {
        // if we're scrolling, don't start and cancel drag
        if ($(this).data("scrolled")) {
            $(this).data("scrolled", false).trigger("mouseup");
            return false;
        }
    }
}).find("*").andSelf().scroll(function() {               
    // bind to the scroll event on current elements, and all children.
    //  we have to bind to all of them, because scroll doesn't propagate.

    //set a scrolled data variable for any parents that are draggable, so they don't drag on scroll.
    $(this).parents(".ui-draggable").data("scrolled", true);

});

为了您的观看/涉猎乐趣,我还包含了该问题的jsfiddle

The solution is to bind to the scroll event on the elements your initializing, and any of that elements children. Then, when any of the children invoke a scroll command, find all of the draggable parents of that element, and set a scrolled data element on that element.

Under jQuery UI's current version (1.8.16), the start event always kicks off when you mouseup on the scrollbar, and progates up the tree, so this solution works pretty well in my testing.

$(".draggable").draggable({
    start: function() {
        // if we're scrolling, don't start and cancel drag
        if ($(this).data("scrolled")) {
            $(this).data("scrolled", false).trigger("mouseup");
            return false;
        }
    }
}).find("*").andSelf().scroll(function() {               
    // bind to the scroll event on current elements, and all children.
    //  we have to bind to all of them, because scroll doesn't propagate.

    //set a scrolled data variable for any parents that are draggable, so they don't drag on scroll.
    $(this).parents(".ui-draggable").data("scrolled", true);

});

For your viewing / dabbling pleasures, I've included a jsfiddle of the issue as well.

〆凄凉。 2025-01-04 22:17:56

我正在寻找这个问题并找到了一个更适合我的更小的解决方案,我想分享它。
我的解决方案是,停止在子/内容上传播“mousedown”事件。
没有鼠标按下意味着没有拖动;)

$(".draggable").draggable();
$("#content").mousedown(function(event) {
    event.stopPropagation();
});

I was searching for this problem and found a smaller solution which works perfectly for me and I want to share it.
My solution is, to stop propagate the "mousedown" event on the child/content.
No mousedown means no dragging ;)

$(".draggable").draggable();
$("#content").mousedown(function(event) {
    event.stopPropagation();
});
罪#恶を代价 2025-01-04 22:17:56

这是一个很好的解决方案,但它有一个错误。
一旦设置为滚动,则需要第二次拖动才能真正拖动元素。

This is pretty solution but it has one bug.
Once it is set to scrolled, it takes second drag to actually drag the element.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文