2011-04-26 122 views
27

我们有一个纸牌游戏网站,广泛使用jQuery Draggable & Droppable和几乎完美(使用鼠标时)近一年的工作。jQuery拖放触摸设备(iPad,Android)

我们真的很想让网站在触摸屏设备上工作,但我们似乎无法获得jQuery的拖动功能,特别是拖放功能可靠地工作。

拖动工程“ok”,除非被拖动的div在另一个dom元素内,并且具有任何偏移量,边距,填充等等。如果是,拖动元素也会从用户的手指偏移相似的量。听起来不是什么大不了的事,但它使界面变得不可用。

丢弃似乎不起作用。

我们已经研究了这里介绍的各种选项(如果可以的话,会尝试更新这篇文章的链接,但如果可以的话),但是没有一篇适合我们。

我们也研究过jQuery Mobile,但这仍然是alpha版本,所以它似乎更像是一个让网站模拟手机用户界面和我们正在寻找的框架。

大多数关于此主题的SO和Google帖子似乎都在2010年底发布,这让我觉得有一个明显的答案,也许我们错过了。

顺便说一句,我们正在寻找的功能在技术上显然是可行的,因为用于拖放的YUI库按预期工作。不幸的是,我们无法将重构网站从jQuery切换到YUI。

有没有人有任何想法?我们会解决只支持iPad的答案,但它确实不需要我们重构现有的网站。

谢谢!

+0

的[可能重复我怎样才能让一个jQuery UI“拖动()'div draggable for touchscreen?](http://stackoverflow.com/questions/3026915/how-can-i-make-a-jquery-ui-draggable-div-draggable-for-touchscreen) – ahsteele 2011-04-26 20:41:36

+0

这确实是我们研究过的SO帖子之一,但在帖子中引用的可拖拽修复程序没有为我们工作。 – Pat 2011-04-26 21:17:51

+0

我们看到的另一个SO帖子是; http://stackoverflow.com/questions/4755505/how-to-recogized-touch-event-using-jquery-for-ipad-safari-browser-is-it-possible – Pat 2011-04-26 21:20:09

回答

0

你可以试试这个插件,但似乎适用于iphone,ipod和ipad。不知道如果解决你的问题。可以是特定的...

http://code.google.com/p/jquery-ui-for-ipad-and-iphone/

而Android仍然在寻找一个解决方案。

让我知道它是否有帮助。问候里卡多·罗德里格斯

+1

发现这解决了android问题。但在旧版本中仍然是个问题..例如2.1 Android HTC Hero。猜得慢。 – 2011-08-03 02:15:00

34

在你的.js文件的开头粘贴此:

(function ($) { 
    // Detect touch support 
    $.support.touch = 'ontouchend' in document; 
    // Ignore browsers without touch support 
    if (!$.support.touch) { 
    return; 
    } 
    var mouseProto = $.ui.mouse.prototype, 
     _mouseInit = mouseProto._mouseInit, 
     touchHandled; 

    function simulateMouseEvent (event, simulatedType) { //use this function to simulate mouse event 
    // Ignore multi-touch events 
     if (event.originalEvent.touches.length > 1) { 
     return; 
     } 
    event.preventDefault(); //use this to prevent scrolling during ui use 

    var touch = event.originalEvent.changedTouches[0], 
     simulatedEvent = document.createEvent('MouseEvents'); 
    // Initialize the simulated mouse event using the touch event's coordinates 
    simulatedEvent.initMouseEvent(
     simulatedType, // type 
     true,    // bubbles      
     true,    // cancelable     
     window,   // view      
     1,    // detail      
     touch.screenX, // screenX      
     touch.screenY, // screenY      
     touch.clientX, // clientX      
     touch.clientY, // clientY      
     false,   // ctrlKey      
     false,   // altKey      
     false,   // shiftKey     
     false,   // metaKey      
     0,    // button      
     null    // relatedTarget    
     ); 

    // Dispatch the simulated event to the target element 
    event.target.dispatchEvent(simulatedEvent); 
    } 
    mouseProto._touchStart = function (event) { 
    var self = this; 
    // Ignore the event if another widget is already being handled 
    if (touchHandled || !self._mouseCapture(event.originalEvent.changedTouches[0])) { 
     return; 
     } 
    // Set the flag to prevent other widgets from inheriting the touch event 
    touchHandled = true; 
    // Track movement to determine if interaction was a click 
    self._touchMoved = false; 
    // Simulate the mouseover event 
    simulateMouseEvent(event, 'mouseover'); 
    // Simulate the mousemove event 
    simulateMouseEvent(event, 'mousemove'); 
    // Simulate the mousedown event 
    simulateMouseEvent(event, 'mousedown'); 
    }; 

    mouseProto._touchMove = function (event) { 
    // Ignore event if not handled 
    if (!touchHandled) { 
     return; 
     } 
    // Interaction was not a click 
    this._touchMoved = true; 
    // Simulate the mousemove event 
    simulateMouseEvent(event, 'mousemove'); 
    }; 
    mouseProto._touchEnd = function (event) { 
    // Ignore event if not handled 
    if (!touchHandled) { 
     return; 
    } 
    // Simulate the mouseup event 
    simulateMouseEvent(event, 'mouseup'); 
    // Simulate the mouseout event 
    simulateMouseEvent(event, 'mouseout'); 
    // If the touch interaction did not move, it should trigger a click 
    if (!this._touchMoved) { 
     // Simulate the click event 
     simulateMouseEvent(event, 'click'); 
    } 
    // Unset the flag to allow other widgets to inherit the touch event 
    touchHandled = false; 
    }; 
    mouseProto._mouseInit = function() { 
    var self = this; 
    // Delegate the touch handlers to the widget's element 
    self.element 
     .on('touchstart', $.proxy(self, '_touchStart')) 
     .on('touchmove', $.proxy(self, '_touchMove')) 
     .on('touchend', $.proxy(self, '_touchEnd')); 

    // Call the original $.ui.mouse init method 
    _mouseInit.call(self); 
    }; 
})(jQuery); 

叫我在早晨)(这真是狂妄,但我希望我有我没有写这个解决方案,我想引用它,如果我记得在那里我发现,如果有人知道这个代码请评论和信贷的那个人)

UPDATE传来:在这里你去:This is where I found this

+1

+1生病了,在我的iPad上效果不错 – 2012-01-27 16:18:59

+0

除了BB w /轨迹球以外,大部分东西都很好Woorks – 2012-01-27 18:47:51

+1

非常好,但是你能告诉我为什么这会破坏我的双击吗? jquery'.dblclick()' – 2012-09-07 10:13:41

16

我建议jQuery UI Touch Punch。我已经在iOS 5和Android 2.3上测试过它,并且它在两者上都很好。

+0

但是它在拖动开始之前有点滞后/延迟(在Chrome Andriod上测试过) – ProblemsOfSumit 2013-07-25 09:07:56

+0

不能在安卓设备上工作范围滑块平滑,请帮助我 – ShibinRagh 2015-02-06 10:49:21

4

我知道的老线程.......

问题与@likwid_t的答案是,它也阻止任何输入或其他元素,必须对'点击'作出反应(例如输入),所以我写了这个解决方案。该解决方案可以使用任何基于任何触摸设备(或cumputer)上的mousedown,mousemove和mouseup事件的现有拖放库。这也是一个跨浏览器的解决方案。

我已经测试过几种设备,它的工作速度很快(与ThreeDubMedia的拖放功能结合使用(另请参阅http://threedubmedia.com/code/event/drag))。这是一个jQuery解决方案,因此您只能在jQuery库中使用它。我使用了jQuery 1.5.1,因为有些新功能在IE9和以上(没有使用新版本的jQuery测试)无法正常工作。

在添加任何拖动或下降操作事件你必须调用这个函数首先

simulateTouchEvents(<object>); 

您还可以阻止所有组件/儿童为输入或加快事件处理使用以下语法:

simulateTouchEvents(<object>, true); // ignore events on childs 

这是我写的代码。我使用了一些不错的技巧来加速评估事物(参见代码)。

function simulateTouchEvents(oo,bIgnoreChilds) 
{ 
if(!$(oo)[0]) 
    { return false; } 

if(!window.__touchTypes) 
{ 
    window.__touchTypes = {touchstart:'mousedown',touchmove:'mousemove',touchend:'mouseup'}; 
    window.__touchInputs = {INPUT:1,TEXTAREA:1,SELECT:1,OPTION:1,'input':1,'textarea':1,'select':1,'option':1}; 
} 

$(oo).bind('touchstart touchmove touchend', function(ev) 
{ 
    var bSame = (ev.target == this); 
    if(bIgnoreChilds && !bSame) 
    { return; } 

    var b = (!bSame && ev.target.__ajqmeclk), // Get if object is already tested or input type 
     e = ev.originalEvent; 
    if(b === true || !e.touches || e.touches.length > 1 || !window.__touchTypes[e.type] ) 
    { return; } //allow multi-touch gestures to work 

    var oEv = (!bSame && typeof b != 'boolean')?$(ev.target).data('events'):false, 
     b = (!bSame)?(ev.target.__ajqmeclk = oEv?(oEv['click'] || oEv['mousedown'] || oEv['mouseup'] || oEv['mousemove']):false):false; 

    if(b || window.__touchInputs[ev.target.tagName]) 
    { return; } //allow default clicks to work (and on inputs) 

    // https://developer.mozilla.org/en/DOM/event.initMouseEvent for API 
    var touch = e.changedTouches[0], newEvent = document.createEvent("MouseEvent"); 
    newEvent.initMouseEvent(window.__touchTypes[e.type], true, true, window, 1, 
      touch.screenX, touch.screenY, 
      touch.clientX, touch.clientY, false, 
      false, false, false, 0, null); 

    touch.target.dispatchEvent(newEvent); 
    e.preventDefault(); 
    ev.stopImmediatePropagation(); 
    ev.stopPropagation(); 
    ev.preventDefault(); 
}); 
return true; 
}; 

做些什么: 起初,它转换单点触摸事件转换成鼠标事件。它检查事件是否由必须拖动的元素上/上的元素引起。如果它是input,textarea等input元素,它会跳过翻译,或者如果标准鼠标事件附加到它,它也会跳过翻译。

结果: 可拖动元素上的每个元素仍在工作。

快乐编码,格尔茨, 欧文Haantjes

+0

您的代码是最有帮助的。我已经使用FullCalendar,但不是开箱即用。我做到了这一点,只有在你保持半秒之后才能模拟鼠标。这是滚动仍然有效。我希望你把这个代码放在Github上,这样我就可以贡献。我认为它可以使用一些改进,例如“b”。变量正在为冗长的名字哭泣。 :-)但是,嘿,它的作品!非常感激。 – RushPL 2012-11-30 14:26:20

+0

请参阅我的回答如下:http://stackoverflow.com/a/13649533/403571 – RushPL 2012-11-30 16:53:08

+0

详细名称是重要的,我知道,但我在此代码'b'中使用多用途布尔(b从布尔值)来检查一些条件使其更易于阅读并限制暂时的变数。不过谢谢你的贡献。 – Codebeat 2012-11-30 20:31:17

0

LikWidT具有最简单的解决方案手从引用的网站下载下来。如果任何JQuery UI程序员都可以将这些代码或类似代码添加到他们的包中,那将会很棒。 Jquery无疑是最简单的为Web开发人员构建拖放内容的软件包......这不幸是现今几乎所有具有触摸屏的设备的一个主要缺陷。我现在正在编写一个Surface Pro,它正在亲自面对这些问题。

只是为了再次参考网站: https://github.com/furf/jquery-ui-touch-punch

编辑:也阐明此修复程序是多么简单。我必须首先确保我重新排序了我的包含文件,例如JQuery Javascript文件先是Jquery UI Javascript然后是我的CSS文件。然后,我只是复制/粘贴在包含文件的Javascript代码在上面的帖子,就是这样。我修改了没有代码,它只是一个实时查找任何触摸并将它们转换为等效的鼠标操作的函数。因此我对JQuery编码器的上述断言。

0

鉴于工作对我来说:Android的下

eventAfterRender: function (event, element, view) { 
     element.draggable(); 
}, 
0

测试上的HTC One M8 6.13 /三星Galaxy Tab S2

function simulateMouseEvent (event, simulatedType) { //use this function to simulate mouse event 

// restriction to preserve input use 
    window.__touchInputs = {INPUT:1,TEXTAREA:1,SELECT:1,OPTION:1,'input':1,'textarea':1,'select':1,'option':1}; 
    if(window.__touchInputs[event.target.tagName]) return ; 

}