触摸屏设备上的 jQuery UI Sortable 发生了什么?

发布于 2024-12-09 08:10:12 字数 846 浏览 0 评论 0原文

我正在使用 jQuery UI Sortable

我正在开发一个仅限移动设备的网站,因此我研究了如何将触摸事件映射到鼠标事件以使其工作,并最终使用了一些 Oleg Slobodskoi 的代码

这看起来效果很好。但是,在移动设备上(我使用 iPhone 进行测试,但它也会发生在 iPhone 模拟器上),当您尝试移动第二个项目(即已经排序了一个项目后要排序的下一个项目)时,它的初始值位置向两侧偏移大约元素的宽度。

Example

当我第二次尝试拖动这些粉色框之一时,而不是出现在我的手指下方并移动有了它,它开始大约一个盒子的宽度,向左或向右,然后到我的手指下。

我已经设置了一个jsFiddle 上的示例。点击附加按钮将 jQuery Sortable 添加到列表项。

我尝试了很多方法,包括使用 change 事件并尝试将其重新调整回来,但我无法让它可靠地工作。

我怎样才能阻止这个问题?

I am using jQuery UI Sortable.

I am developing a mobile only website, so I looked around how to map touch events to mouse events for this to work, and ended up using some code by Oleg Slobodskoi.

This appeared to work nicely. However, on a mobile device (I am using an iPhone to test, but it also happens on the iPhone simulator), when you attempt to shift a second item (i.e. the next item to sort after you have sorted one already), its initial position is offset either side by about the width of the element.

Example

When I attempt the second time to drag one of these pink boxes, instead of appearing underneath my finger and shifting with it, it starts about the width of a box away, to the left or right, and then jumps under my finger.

I've set up an example on jsFiddle. Hit the attach button to add jQuery Sortable to the list items.

I have tried many things, including playing with the change event and attempting to realign it back, but I couldn't get it to reliably work.

How can I stop this problem?

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

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

发布评论

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

评论(2

乖乖公主 2024-12-16 08:10:12

这个解决方案超级简单。我希望我能说它非常容易找到,但不……花了一段时间。

为了澄清这一症状,最初拖动的元素始终是后续拖动中被拖动的元素。如果您一开始拖动 b,则在后续拖动中,b 始终会移动。对于ac 也是如此。

这让我怀疑这个事件是否被“回收”了。我确认 touchstart(和 touchmove)事件中的 pageXpageY 值是正确的,但是这些值在 Sortable 中访问 _mouseDown 是错误的。因此,我转到 jquery.ui.mouse.js 并查看了 _mouseDown 。我确认传递了正确的值,但处理程序在方法顶部的这一行退出:

// don't let more than one widget handle mouseStart
if( mouseHandled ) { return };

因此,我开始查看 mouseHandled。只有一行将其重置为 false - 顶部的以下侦听器:

$( document ).mouseup( function( e ) {
    mouseHandled = false;
});

我意识到我必须接近。我回顾了您正在使用的兼容性加载项中的 _touchEnd 方法:

_touchEnd: function(event) {
   this.element.unbind("touchmove." + this.widgetName).unbind("touchend." + this.widgetName);
   this._mouseUp(event);
}, 

请注意,_mouseUp 仅在小部件本身上调用 - 而不是在 document 上调用!因此,显然 mouseHandled 从未被重置。因此,我向 _touchEnd 添加了一个 document 调度行:

_touchEnd: function(event) {
   this.element.unbind("touchmove." + this.widgetName).unbind("touchend." + this.widgetName);
   this._mouseUp(event);
   $(document).trigger('mouseup', event);
}, 

很快,一切正常。

所以,总而言之,这一行是最神奇的:

$(document).trigger('mouseup', event);

工作分叉小提琴这里 [用于 iOS 查看的直接链接]。


注意:我还更改了这一行:

/ iPad | iPhone /.test(navigator.userAgent) && (function($) {

至:

/iPad|iPhone|iPod/.test(navigator.userAgent) && (function($) {

因为它不能正常使用空格,并且您应该包括对 iPod touch 的支持。

Super simple solution for this one. I wish I could say it was super simple to find, but no... it took a while.

To clarify the symptom, it's that the initially-dragged element is always the one that is dragged on subsequent drags. If you start out dragging b, on subsequent drags b is the one that always moved. Likewise for a and c.

This made me question if perhaps the event was being "recycled." I confirmed that the pageX and pageY values were correct on the touchstart (and touchmove) event, but the values getting to _mouseDown in Sortable were wrong. So, I went to jquery.ui.mouse.js and looked at _mouseDown there. I confirmed that the proper values were coming through, but that the handler was exiting at this line at the top of the method:

// don't let more than one widget handle mouseStart
if( mouseHandled ) { return };

So, I started looking at mouseHandled. There was only one line where this was reset back to false - the following listener at the top:

$( document ).mouseup( function( e ) {
    mouseHandled = false;
});

I realized I must be close. I looked back at the _touchEnd method in the compatibility add-in you're using:

_touchEnd: function(event) {
   this.element.unbind("touchmove." + this.widgetName).unbind("touchend." + this.widgetName);
   this._mouseUp(event);
}, 

Note that _mouseUp is only called on the widget itself -- not the document! Thus, clearly mouseHandled was never being reset. So, I added a document dispatch line to _touchEnd:

_touchEnd: function(event) {
   this.element.unbind("touchmove." + this.widgetName).unbind("touchend." + this.widgetName);
   this._mouseUp(event);
   $(document).trigger('mouseup', event);
}, 

And presto, everything worked correctly.

So, in summary, this one line is the magic one:

$(document).trigger('mouseup', event);

Working forked fiddle here [direct link for iOS viewing].


Note: I also changed this line:

/ iPad | iPhone /.test(navigator.userAgent) && (function($) {

To:

/iPad|iPhone|iPod/.test(navigator.userAgent) && (function($) {

Because it didn't work properly with spaces, and you should include support for the iPod touch.

听风念你 2024-12-16 08:10:12

还有一件更重要的事情。
一切都很好,但前提是我们不向下滚动页面。
问题是 Y 触摸位置是相对于窗口顶部的,而不是相对于文档的。
我已经解决了这个问题,更改了行:

event.pageY = target.clientY;

改为:

event.pageY = target.clientY + $(window).scrollTop();

There is one more important thing.
Everything works great, but only as long as we don't scroll the page down.
The problem is that Y touch position is relative to window top, not the document.
I've fixed this changing the line:

event.pageY = target.clientY;

Into this:

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