滚动可拖动项目的内容时禁用jQuery拖动
Posted
技术标签:
【中文标题】滚动可拖动项目的内容时禁用jQuery拖动【英文标题】:Disabling jQuery drag when scrolling contents of draggable item 【发布时间】:2012-02-19 06:46:22 【问题描述】:我通常不会提出这种问题/答案,但我想我会这样做,因为我已经看到这个问题被问了 20 多次,但实际上没有一个答案有效。简而言之,问题是如果你有可滚动的内容(overflow: auto;
在可拖动的 jQuery 项目内的任何地方,当你单击并拖动滚动条时,父可拖动容器也会随之拖动。所以,我花了一些时间制定解决方案.
下面是一些会出现此问题的 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()
【问题讨论】:
【参考方案1】:我建议基于 [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,而不是 content div。对于解决方案来说,这并不重要,但我不想添加额外的 div 级别,因为这不是绝对必要的。
这里是jsfiddle。
[1] - listen for mouse events … except a div's overflow:scroll scrollbar?
【讨论】:
哦,它适用于垂直滚动,但是当您尝试水平滚动时,它会出错!我怎样才能解决这个问题? :( 此解决方案使滚动工作,但呈现可拖动项目不可拖动。在 mac OSX 上的 FF21.0 上尝试过【参考方案2】:解决方案是绑定到您正在初始化的元素上的滚动事件,以及任何这些元素的子元素。然后,当任何子元素调用滚动命令时,找到该元素的所有可拖动父元素,并在该元素上设置滚动数据元素。
在 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。
【讨论】:
不幸的是,此答案仅在单击滚动条时实际发生一些滚动时才有效。如果您在不滚动的情况下按下滚动条,jQuery UI/Draggable 代码仍将开始拖动。(在已发布的 jsfiddle with Chrome 23 Beta 中尝试过此操作;只需单击滚动条而不滚动) 这个需要监听“*”(一切)的滚动事件,并添加滚动对数据是真实的。另一个答案更独立,以后可读性更好。 在 Firefox 45 esr 中左键单击滚动条时,整个窗口都会移动。这个解决方案解决了我的问题。谢谢!【参考方案3】:我正在寻找这个问题,并找到了一个更适合我的更小的解决方案,我想分享它。 我的解决方案是,停止在子/内容上传播“mousedown”事件。 没有鼠标按下意味着没有拖动;)
$(".draggable").draggable();
$("#content").mousedown(function(event)
event.stopPropagation();
);
【讨论】:
【参考方案4】:这是一个很好的解决方案,但它有一个错误。 一旦设置为滚动,实际拖动元素需要第二次拖动。
【讨论】:
以上是关于滚动可拖动项目的内容时禁用jQuery拖动的主要内容,如果未能解决你的问题,请参考以下文章