Подтвердить что ты не робот

JQuery Перетаскивание на сенсорных устройствах (iPad, Android)

У нас есть сайт с карточной игрой, который широко использует jQuery Draggable и Droppable и который почти безупречно работал (при использовании мыши) почти год.

Мы бы ДЕЙСТВИТЕЛЬНО хотели, чтобы сайт работал на устройствах с сенсорным экраном, но мы не можем заставить jQuery перетащить и особенно отказаться от функциональности для надежной работы.

Перетаскивание работает "ok", если div не перетаскивается внутри другого элемента dom с любым видом смещения, поля, отступов и т.д. Если это так, перемещенный элемент также смещается от пальца пользователя на аналогичную сумму. Может показаться не очень удачным, но это делает интерфейс непривлекательным.

Отбрасывание просто не работает.

Мы изучили различные варианты, представленные здесь на SO (попробуем обновить это сообщение со ссылками на некоторые из них, если смогу), но никто не работает для нас.

Мы также изучили jQuery Mobile, но это все еще в альфе, и, похоже, это больше похоже на рамки для создания сайта для эмуляции пользовательского интерфейса телефона по сравнению с тем, что мы ищем.

Большинство сообщений SO и Google по этой теме, похоже, заканчиваются в конце 2010 года, что заставляет меня думать, что есть очевидный ответ, который, возможно, мы просто не встречаем.

BTW, функциональность, которую мы ищем, явно технически возможна, потому что библиотеки YUI для перетаскивания работают так, как ожидалось. К сожалению, мы не можем упростить рефакторинг сайта, чтобы переключиться с jQuery на YUI.

У кого-нибудь есть идеи? Мы согласились бы на ответ, который поддерживает только iPad, но для этого действительно не требуется реорганизация существующего сайта.

Спасибо!

4b9b3361

Ответ 1

Вставьте это в начало вашего .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 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 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);

Позвони мне по утрам;) (это действительно высокомерное, я не написал это решение, хотя я бы хотел, чтобы у меня было это, я бы обратился к нему, если бы вспомнил, где я его нашел, если кто-нибудь знает, откуда этот код пришел прокомментируйте и запишите этого человека)

ОБНОВЛЕНИЕ: Здесь вы найдете: Здесь я нашел это

Ответ 2

Я предлагаю jQuery UI Touch Punch. Я тестировал его на iOS 5 и Android 2.3, и он отлично работает на обоих.

Ответ 3

Старый поток, который я знаю.......

Проблема с ответом @likwid_t заключается в том, что он блокирует также любой вход или другой элемент, который должен реагировать на "клики" (например, входы), поэтому я написал это решение. Это решение позволило использовать любую существующую библиотеку перетаскивания, которая основана на событиях mousedown, mousemove и mouseup на любом сенсорном устройстве (или в кумпане). Это также кросс-браузерное решение.

Я тестировал несколько устройств и работает быстро (в сочетании с функцией перетаскивания ThreeDubMedia (см. также http://threedubmedia.com/code/event/drag)). Это решение jQuery, поэтому вы можете использовать его только с jQuery libs. Я использовал 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 и т.д., Он пропускает перевод, или если к нему прикреплено стандартное событие мыши, оно также пропустит перевод.

Результат: Каждый элемент перетаскиваемого элемента все еще работает.

Счастливое кодирование, greetz, Эрвин Хаантес

Ответ 5

Вы можете попробовать этот плагин, но, похоже, работают на iphone, ipod и ipad. Не уверен, решает ли вы проблему. Может быть конкретным...

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

Но андроид все еще ищет решение.

Сообщите мне, если это поможет. С уважением Рикардо Родригес

Ответ 6

У LikWidT есть простейшее решение, сбрасывающее с сайта ссылки. Было бы здорово, если бы какой-либо из программистов JQuery UI мог добавить этот код или аналогичный их пакет. JQuery - это, безусловно, самый простой пакет для создания контента перетаскивания для веб-разработчиков... это, к сожалению, главный недостаток почти всех устройств, имеющих сенсорные экраны в настоящее время. Теперь я кодирую Surface Pro, который лично открывает глаза на эти проблемы.

Просто чтобы снова ссылаться на сайт: https://github.com/furf/jquery-ui-touch-punch

Изменить: Также выяснить, насколько просто это исправление. Я должен был сначала гарантировать, что я повторно заказал свои включенные файлы, чтобы JQuery Javascript файл был сначала JQuery UI Javascript, а затем мои файлы CSS. Затем я просто копировал/вставлял ниже включенных файлов код Javascript в сообщение выше, и это все. Я не модифицировал код, это просто функция, которая ищет любые касания в реальном времени и преобразует их в эквивалентные действия мыши. Следовательно, мои предыдущие утверждения для JQuery-кодеров.

Ответ 7

Работала для меня:

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

Ответ 8

Протестировано на HTC One M8 под Android 6.13/Samsung 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 ;

}