2011-04-26 408 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 ; 

}