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

Предотвращать прикосновение

У меня есть прокручиваемый список на мобильном устройстве. Они хотят, чтобы люди могли прокручивать список с помощью прокрутки, а также выбирать строку, нажав.

Улов объединяет два. Я не хочу, чтобы строка была выбрана, если вы на самом деле прокручиваете список. Вот что я нашел:

Не запускается при прокрутке:

  • выберите
  • mouseup

Включается при прокрутке:

  • mousedown
  • touchstart
  • touchhend

Простое решение - просто придерживаться события click. Но то, что мы находим, это то, что на некоторых устройствах Blackberry существует очень заметное отставание между touchstart, а затем срабатывание либо щелчка, либо мыши. Эта задержка достаточно значительна, чтобы сделать ее непригодной для использования на этих устройствах.

Итак, это оставляет нам другие варианты. Однако с этими параметрами вы можете прокручивать список, не запуская строку, которую вы коснулись, чтобы запустить прокрутку.

Какова наилучшая практика для решения этой проблемы?

4b9b3361

Ответ 1

var touchmoved;
$('button').on('touchend', function(e){
    if(touchmoved != true){
        // you're on button click action
    }
}).on('touchmove', function(e){
    touchmoved = true;
}).on('touchstart', function(){
    touchmoved = false;
});

Ответ 2

Что вы в основном хотите сделать, так это определить, что такое салфетки и какой щелчок.

Мы можем установить некоторые условия:

  • Проведите по экрану, когда вы касаетесь точки p1, затем переместите палец в точку p2, продолжая при этом палец на экране, затем отпустите.
  • Щелчок - это когда вы нажимаете "начать" и нажимаете на тот же элемент.

Итак, если вы храните координаты, где произошел ваш touchStart, вы можете измерить разницу в touchEnd. Если изменение достаточно велико, рассмотрите его как прокрутку, иначе рассмотрите его щелчком.

Кроме того, если вы хотите сделать это очень аккуратно, вы также можете определить, какой элемент вы "парили" пальцем во время touchMove, и если вы еще не находитесь в элементе, на котором вы начали щелкните, вы можете запустить метод clickCancel, который удаляет подсветку и т.д.

// grab an element which you can click just as an example
var clickable = document.getElementById("clickableItem"),
// set up some variables that we need for later
currentElement,
clickedElement;

// set up touchStart event handler
var onTouchStart = function(e) {
    // store which element we're currently clicking on
    clickedElement = this;
    // listen to when the user moves finger
    this.addEventListener("touchMove" onTouchMove);
    // add listener to when touch end occurs
    this.addEventListener("touchEnd", onTouchEnd);
};
// when the user swipes, update element positions to swipe
var onTouchMove = function(e) {
    // ... do your scrolling here

    // store current element
    currentElement = document.elementFromPoint(x, y);
    // if the current element is no longer the same as we clicked from the beginning, remove highlight
    if(clickedElement !== currentElement) {
        removeHighlight(clickedElement);
    }
};
// this is what is executed when the user stops the movement
var onTouchEnd = function(e) {
    if(clickedElement === currentElement) {
        removeHighlight(clickedElement);
        // .... execute click action
    }

    // clean up event listeners
    this.removeEventListener("touchMove" onTouchMove);
    this.removeEventListener("touchEnd", onTouchEnd);
};
function addHighlight(element) {
    element.className = "highlighted";
}
function removeHighlight(element) {
    element.className = "";
}
clickable.addEventListener("touchStart", onTouchStart);

Затем вам также придется добавить слушателей к прокручиваемому элементу, но вам не придется беспокоиться о том, что произойдет, если палец переместился между touchStart и touchEnd.

var scrollable = document.getElementById("scrollableItem");

// set up touchStart event handler
var onTouchStartScrollable = function(e) {
    // listen to when the user moves finger
    this.addEventListener("touchMove" onTouchMoveScrollable);
    // add listener to when touch end occurs
    this.addEventListener("touchEnd", onTouchEndScrollable);
};
// when the user swipes, update element positions to swipe
var onTouchMoveScrollable = function(e) {
    // ... do your scrolling here
};
// this is what is executed when the user stops the movement
var onTouchEndScrollable = function(e) {
    // clean up event listeners
    this.removeEventListener("touchMove" onTouchMoveScrollable);
    this.removeEventListener("touchEnd", onTouchEndScrollable);
};
scrollable.addEventListener("touchStart", onTouchStartScrollable);

//Саймон А.

Ответ 3

Вот то, что я в конце концов придумал, чтобы разрешить прокручивание списка элементов с помощью салфетки, но также каждый элемент, который можно "запускать" с помощью крана. Кроме того, вы все равно можете использовать клавиатуру (используя onclick).

Я думаю, что это похоже на ответ Netlight_Digital_Media. Мне нужно изучить это немного больше.

$(document)
// log the position of the touchstart interaction
.bind('touchstart', function(e){ 
  touchStartPos = $(window).scrollTop();
})
// log the position of the touchend interaction
.bind('touchend', function(e){
  // calculate how far the page has moved between
  // touchstart and end. 
  var distance = touchStartPos - $(window).scrollTop();

  var $clickableItem; // the item I want to be clickable if it NOT a swipe

  // adding this class for devices that
  // will trigger a click event after
  // the touchend event finishes. This 
  // tells the click event that we've 
  // already done things so don't repeat

  $clickableItem.addClass("touched");      

  if (distance > 20 || distance < -20){
        // the distance was more than 20px
        // so we're assuming they intended
        // to swipe to scroll the list and
        // not selecting a row. 
    } else {
        // we'll assume it was a tap 
        whateverFunctionYouWantToTriggerOnTapOrClick()
    }
});


$($clickableItem).live('click',function(e){
 // for any non-touch device, we need 
 // to still apply a click event
 // but we'll first check to see
 // if there was a previous touch
 // event by checking for the class
 // that was left by the touch event.
if ($(this).hasClass("touched")){
  // this item event was already triggered via touch
  // so we won't call the function and reset this for
  // the next touch by removing the class
  $(this).removeClass("touched");
} else {
  // there wasn't a touch event. We're
  // instead using a mouse or keyboard
  whateverFunctionYouWantToTriggerOnTapOrClick()
}
});

Ответ 4

Цитата из DA.:

Это рабочий пример:

var touch_pos;
$(document).on('touchstart', '.action-feature', function(e) {
  e.preventDefault();
  touch_pos = $(window).scrollTop();
}).on('click touchend', '.action-feature', function(e) {
  e.preventDefault();
  if(e.type=='touchend' && (Math.abs(touch_pos-$(window).scrollTop())>3)) return;
  alert("only accessed when it a click or not a swipe");
});

Ответ 5

У меня была та же проблема, вот быстрое решение, которое работает для меня

$(document).on('touchstart', 'button', function(evt){ 
    var oldScrollTop = $(window).scrollTop();
    window.setTimeout( function() {
        var newScrollTop = $(window).scrollTop();
        if (Math.abs(oldScrollTop-newScrollTop)<3) $button.addClass('touchactive');
    }, 200);
});

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

Ответ 6

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

Tocca.js: https://github.com/GianlucaGuarini/Tocca.js

Он довольно гибкий и обнаруживает прикосновение, а также салфетки, двойное нажатие и т.д.

Ответ 7

Я наткнулся на это элегантное решение, которое работает как прелесть, используя jQuery. Моя проблема заключалась в том, что элементы списка не вызывали событие касания при прокрутке. Это также должно работать для прокрутки.

  • привязать touchstart к каждому элементу, который будет прокручиваться или прокручиваться с помощью класса listObject

    $('.listObject').live('touchstart', touchScroll);
    
  • Затем каждому элементу присваивается объект-объект attr, определяющий функцию, которая будет называться

    <button class='listObject' data-object=alert('You are alerted !')>Alert Me</button>
    

Следующая функция будет эффективно различать нажатие и прокрутку или прокрутку.

function touchScroll(e){

    var objTarget = $(event.target);

    if(objTarget.attr('data-object')){
        var fn = objTarget.attr('data-object'); //function to call if tapped    
    }   

    if(!touchEnabled){// default if not touch device
        eval(fn);
        console.log("clicked", 1);
        return;
    }

    $(e.target).on('touchend', function(e){
        eval(fn); //trigger the function
        console.log("touchEnd")      
        $(e.target).off('touchend');
    });

    $(e.target).on('touchmove', function(e){
        $(e.target).off('touchend');
        console.log("moved")
    }); 

}

Ответ 8

Я сделал это с немного другой работой. Это определенно не очень элегантно и, конечно, не подходит для большинства ситуаций, но это сработало для меня.

Я использую jQuery toggleSlide(), чтобы открывать и закрывать входные divs, запуская слайд на touchstart. Проблема заключалась в том, что когда пользователь хотел прокрутить, косвенный div откроется. Чтобы остановить это, (или отменить его перед тем, как пользователь заметил), я добавил событие touchslide в документ, который закроет последний коснутый div.

Более подробно здесь приведен фрагмент кода:

var lastTouched;

document.addEventListener('touchmove',function(){
    lastTouched.hide();
});

$('#button').addEventListener('touchstart',function(){
    $('#slide').slideToggle();
    lastTouched = $('#slide');
});

Глобальная переменная хранит последний коснутый div, и если пользователь выполняет поиск, событие document.touchmove скрывает этот div. Иногда вы получаете мерцание разворота, но оно работает для того, что мне нужно, и достаточно просто для того, чтобы я мог придумать.

Ответ 9

Я использую этот бит кода, так что кнопки запускаются только (по касанию), если не были прокручены:

var startY;
var yDistance;

function touchHandler(event) {
    touch = event.changedTouches[0];
    event.preventDefault();
}

$('.button').on("touchstart", touchHandler, true);
$('.button').on("touchmove", touchHandler, true);

$('.button').on("touchstart", function(){
    startY = touch.clientY;
});

$('.button').on('touchend', function(){

    yDistance = startY - touch.clientY;

    if(Math.abs(yDist) < 30){

        //button response here, only if user is not swiping
        console.log("button pressed")
    }
});

Ответ 10

jQuery Mobile имеет .tap() событие, которое, похоже, имеет поведение, которое вы ожидаете:

Событие события переключения jQuery Mobile запускается после быстрого, полного события касания, которое происходит на одном целевом объекте. Это эквивалент жеста стандартного события клика, который запускается в состоянии выпуска жестов касания.

Возможно, это не обязательно ответит на вопрос, но может быть полезной альтернативой некоторым.

Ответ 11

если вы хотите сделать это для нескольких элементов, а также нужны события мыши и указателя:

var elems = $('YOURMULTISELECTOR'); // selector for multiple elements
elems.unbind('mousdown pointerdown touchstart touchmove mouseup pointerup touchend');
var elem = null;
elems.on('mousdown pointerdown touchstart', function (e) {
    elem = yourSingleSelector(e);
}).on('touchmove', function (e) {
    elem = null;                
}).on('mouseup pointerup touchend', function (e) { 
    if (elem == yourSingleSelector(e)) {                    
        // do something
    }
});

Ответ 12

Я выполнил более легкое решение, выполнив следующие действия:

$el.mouseover(function() {
    if (jQuery.browser.mobile) {
        //your javscript function
    }
});