如何以编程方式触发可拖动行为

发布于 2024-10-21 06:23:07 字数 1731 浏览 3 评论 0原文

我在 jQuery 中创建了一个“2d 滑块”,其中通过在边界框中拖动“手柄”来同时操作 2 个参数。

我通过在父 div 中嵌套一个“handle”div 并使用 jQuery UI 插件来促进拖动行为来实现这一点。 html 看起来像:

<div class="Slider2d" id="grid_spacing_both">
    <div class="Slider2dHandle" id="grid_spacing_both_handle"></div>
</div>

jQuery 看起来像:

$(".Slider2dHandle").draggable({
    containment: "parent",
    scroll: false,
    drag: function(event, ui) {
        // calculates position and updates value input boxes
    }
});

我还创建了一些代码,将句柄重新定位到父 div 内任何点击的位置:

$(".Slider2d").mousedown(function(event){
    // get location of click and reposition handle to click location
});

我想做的是修改上面的方法,以便用户可以点击某处在父 div 中,将手柄重新定位到单击位置,然后开始拖动手柄,不要松开鼠标按钮。基本上,我需要找出一种以编程方式触发拖动功能的方法。

我在此处此处,并尝试通过更改上述方法来实现他们的建议,如下所示:

$(".Slider2d").mousedown(function(event){
    // get location of click and reposition handle to click location
    handle = $(".Slider2d").children(".Slider2dHandle");
    handle.trigger(event);
});

这在最技术的意义上是有效的,但它非常慢,并且我从 Safari 收到一堆错误消息,告诉我“RangeError:超出了最大调用堆栈大小”。我认为正在发生的事情是,当我触发句柄上的事件时,它会冒泡到父级,然后父级再次调用触发器,依此类推。我试图通过在 .trigger() 调用之前和之后将 event.stopPropagation 扔到我的代码中来停止冒泡,但无济于事。

因此,如果有人对如何使其正常工作有任何建议,我将非常感激。我有一个备份计划此处,但是在我看来,这似乎不必要地复杂。

谢谢!

I've created a "2d slider" in jQuery in which 2 parameters are manipulated simultaneously by dragging a "handle" within a bounding box.

I've implemented this by nesting a "handle" div within a parent div, and using the jQuery UI plugin to facilitate the dragging behaviour. The html looks like:

<div class="Slider2d" id="grid_spacing_both">
    <div class="Slider2dHandle" id="grid_spacing_both_handle"></div>
</div>

The jQuery looks like:

$(".Slider2dHandle").draggable({
    containment: "parent",
    scroll: false,
    drag: function(event, ui) {
        // calculates position and updates value input boxes
    }
});

I've also created some code that repositions the handle to the location of any clicks within the parent div:

$(".Slider2d").mousedown(function(event){
    // get location of click and reposition handle to click location
});

What I would like to do is modify the above method so that the user can click somewhere in the parent div, have the handle repositioned to the click location, and then begin dragging the handle without letting the mouse button up. Basically, I need to figure out a way to programmatically trigger the drag functionality.

I found a few suggestions here and here, and attempted to implement their recommendations by changing the above method like so:

$(".Slider2d").mousedown(function(event){
    // get location of click and reposition handle to click location
    handle = $(".Slider2d").children(".Slider2dHandle");
    handle.trigger(event);
});

This works in the most technical sense, but its super slow and I get a bunch of error messages from Safari telling me "RangeError: Maximum call stack size exceeded." What I'm thinking is happening is that the when I trigger the event on the handle, it bubbles up to the parent, which then calls the trigger again and so on and so on. I've tried to stop the bubbling by throwing an event.stopPropagation into my code before and after the .trigger() call, but to no avail.

So, if anyone has any suggestions on how to get this working I'd really appreciate it. I have a backup plan here, but this seems to me to be unnecessarily complicated.

Thanks!

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

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

发布评论

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

评论(3

瞄了个咪的 2024-10-28 06:23:07

我设法让这个工作。正如我怀疑的那样,这与事件处理有关。

修复很简单:我修改了上面的代码来检查事件目标是否与回调绑定到的元素(即滑块边界框)相同。在重新定位手柄的初始单击中,这些是相同的元素。但是,当触发手柄的 mousedown 事件并且该事件向上冒泡到边界框时,该事件的目标是滑块手柄。因此,它们不匹配,并且不会再次调用触发事件,从而引发无限循环。

至少我认为这就是正在发生的事情。无论如何,这是有效的代码:

$(".Slider2d").mousedown(function(event){
    // get location of click and reposition handle to click location 

    handle = $(".Slider2d").children(".Slider2dHandle");
    if ($(this).attr("id") == $(event.target).attr("id")) {
        handle.trigger(event);
    }
});

I managed to get this working. As I suspected, it had something to do with event handling.

The fix was simple: I modified the above code to check if the event target was the same as the element to which the callback was bound (ie, slider bounding box). On the initial click that repositions the handle, these are the same elements. However, when the handle's mousedown event is triggered, and the event bubbles up to the bounding box, the target of that event is the slider handle. So, they don't match, and the trigger event isn't called again, setting off an infinite loop.

At least I think that's what's going on. In any case, here's the code that worked:

$(".Slider2d").mousedown(function(event){
    // get location of click and reposition handle to click location 

    handle = $(".Slider2d").children(".Slider2dHandle");
    if ($(this).attr("id") == $(event.target).attr("id")) {
        handle.trigger(event);
    }
});
一人独醉 2024-10-28 06:23:07

或者您可以在处理程序的 mousedown 事件处停止传播,这样它就不会冒泡到滑块的 mousedown 事件。

$(".Slider2d").mousedown(function(event) {
    // get location of click and reposition handle to click location 

    handle = $(".Slider2d").children(".Slider2dHandle");
    handle.trigger(event);
});

$(".Slider2dHandle").mousedown(function(event) {
    event.stopPropagation();
});

Or you could just stop propagation at the handler's mousedown event so it doesn't bubble up to the slider's mousedown event.

$(".Slider2d").mousedown(function(event) {
    // get location of click and reposition handle to click location 

    handle = $(".Slider2d").children(".Slider2dHandle");
    handle.trigger(event);
});

$(".Slider2dHandle").mousedown(function(event) {
    event.stopPropagation();
});
初熏 2024-10-28 06:23:07

这对我不起作用,所以我认为我做错了什么。但我想知道,如果它适合你,为什么不设置:

if ($(this).attr("id") == $(event.target).attr("id"))

为此:

if (this === event.target)

一旦我弄清楚这一点,我就会更新。

仍然什么也没有:在无限循环期间,event.target 仍然是滑块,而不是手柄,只有那时第二个事件才会真正触发。

编辑:明白了,我从 jQuery 1.7.1 切换到 1.6.4 并且它可以工作。

This doesn't work for me, so I assume I'm doing something wrong. But I was wondering, if it works for you, why not set:

if ($(this).attr("id") == $(event.target).attr("id"))

To this:

if (this === event.target)

I'll update once I figure this out.

Still nothing: during that infinite loop, the event.target remains as the slider, not the handle, only then is the second event actually triggered.

EDIT: Got it, I switched from jQuery 1.7.1 to 1.6.4 and it works.

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