programing

'터치 시작' 및 '클릭' 이벤트를 바인딩하지만 둘 다에 응답하지 않는 방법은 무엇입니까?

muds 2023. 10. 8. 10:23
반응형

'터치 시작' 및 '클릭' 이벤트를 바인딩하지만 둘 다에 응답하지 않는 방법은 무엇입니까?

저는 다양한 장치들을 작업해야 하는 모바일 웹사이트를 작업하고 있습니다.지금 머리가 아픈 것은 블랙베리입니다.

키보드 클릭은 물론 터치 이벤트도 지원해야 합니다.

이상적으로 저는 다음을 사용합니다.

$thing.click(function(){...})

하지만 우리가 직면하고 있는 문제는 이러한 블랙베리 기기들 중 일부가 터치할 때부터 클릭을 시작할 때까지 매우 성가신 지연을 가지고 있다는 것입니다.

대신 터치 스타트를 사용하는 것이 해결책입니다.

$thing.bind('touchstart', function(event){...})

하지만 어떻게 하면 두 종목을 묶고, 한 종목만 발사할 수 있을까요?키보드 장치에 대한 클릭 이벤트는 여전히 필요하지만, 터치 장치를 사용하는 경우 클릭 이벤트가 발생하는 것은 물론 원하지 않습니다.

보너스 질문:터치 시작 이벤트도 없는 브라우저를 추가로 수용할 수 있는 방법이 있을까요?이를 조사하는 과정에서 BlackBerry OS5가 터치 시작을 지원하지 않는 것으로 보이며, 따라서 해당 브라우저의 클릭 이벤트에도 의존해야 합니다.

부록:

보다 포괄적인 질문은 다음과 같습니다.

jQuery를 사용하면 동일한 바인딩으로 터치 상호 작용과 마우스 상호 작용을 모두 처리할 수 있습니까?

이상적으로, 대답은 '네'입니다' 입니다.그렇지 않다면 몇 가지 옵션이 있습니다.

  1. 우리는 장치 정보를 얻기 위해 WURFL을 사용하여 자체적인 장치 매트릭스를 만들 수 있습니다.단말기에 따라 터치 시작 또는 클릭을 사용합니다.

  2. JS를 통해 브라우저에서 터치 지원 여부를 탐지합니다(조사를 좀 더 해봐야겠지만 가능할 것 같습니다).

그러나 이 문제는 여전히 하나의 문제로 남아 있습니다. 두 가지를 모두 지원하는 장치는 어떨까요?저희가 지원하는 일부 전화기(즉, 노키아와 블랙베리)에는 터치 스크린과 키보드가 모두 있습니다.그럼 다시 원래 질문으로 돌아가도록 하죠 어떻게든 두 가지를 동시에 허용할 수 있는 방법이 있을까요?

업데이트: 마우스와 터치 중 하나를 선택하는 대신 "포인트" 이벤트에 바인딩할 수 있는 jQuery Pointer Events Polyfill 프로젝트를 확인합니다.


둘 다 바인딩하되 플래그를 만들어 100ms 당 한 번만 실행되도록 합니다.

var flag = false;
$thing.bind('touchstart click', function(){
  if (!flag) {
    flag = true;
    setTimeout(function(){ flag = false; }, 100);
    // do something
  }

  return false
});

이것이 제가 "만드는" 수정사항이고, 고스트클릭을 제거하고 패스트클릭을 구현합니다.직접 해보시고 효과가 있는지 알려주세요.

$(document).on('touchstart click', '.myBtn', function(event){
        if(event.handled === false) return
        event.stopPropagation();
        event.preventDefault();
        event.handled = true;

        // Do your magic here

});

당신은 다음과 같은 것을 시도해 볼 수 있습니다.

var clickEventType=((document.ontouchstart!==null)?'click':'touchstart');
$("#mylink").bind(clickEventType, myClickHandler);

일반적으로 이 기능은 다음과 같이 작동 방법을 사용합니다.

$('#buttonId').on('touchstart click', function(e){
    e.stopPropagation(); e.preventDefault();
    //your code here

});

를 거예요.return false;on("click touchstart")이벤트 함수는 이 문제를 해결할 수 있습니다.

$(this).on("click touchstart", function() {
  // Do things
  return false;
});

.on()의 jQuery 설명서에서

false합니다를 합니다.event.stopPropagation()그리고.event.preventDefault().A.false될 수 .function(){ return false; }.

저도 비슷한 일을 해야 했어요.여기 저에게 효과가 있었던 내용을 간략하게 소개합니다.터치 이벤트가 감지되면 클릭 바인딩을 제거합니다.

$thing.on('touchstart click', function(event){
  if (event.type == "touchstart")
    $(this).off('click');

  //your code here
});

내 는 에 .<a>다에 를 다시 .합니다.<a>요소.

$thing.on('touchstart click', function(event){
  if (event.type == "touchstart")
    $(this).off('click').on('click', function(e){ e.preventDefault(); });

  //your code here
});

저는 다음과 같은 방법으로 성공했습니다.

쉬운 완두콩...

$(this).on('touchstart click', function(e){
  e.preventDefault();
  //do your stuff here
});

최선의 방법은 다음과 같습니다.

$('#object').on('touchend mouseup', function () { });

만지다

터치 지점을 터치 표면에서 제거하면 터치 이벤트가 발생합니다.

터치다운 이벤트는 마우스 이벤트를 트리거하지 않습니다.


마우스를 갖다 대다

마우스 포인터가 요소 위에 있고 마우스 버튼이 해제되면 마우스 업 이벤트가 요소로 전송됩니다.모든 HTML 요소는 이 이벤트를 수신할 수 있습니다.

마우스 업 이벤트는 터치 이벤트를 트리거하지 않습니다.

$('#click').on('mouseup', function () { alert('Event detected'); });
$('#touch').on('touchend', function () { alert('Event detected'); });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1 id="click">Click me</h1>
<h1 id="touch">Touch me</h1>


EDIT (2017)

으로 한 2017을 로 만들기 위한 ..on("click")클릭 요청 시 탭 이벤트로 인해 발생하는 지연을 제거하여 마우스와 터치 모두에 더 적합합니다.

따라서 클릭 이벤트만으로 다시 돌아가는 것이 앞으로 나아가는 가장 간단한 해결책이 될 것이라는 결론에 이릅니다.

이것이 실용적인지 알아보기 위해 아직 교차 브라우저 테스트를 하지 않았습니다.

구글 https://developers.google.com/mobile/articles/fast_buttons 에서 빠른 버튼과 클릭을 확인합니다.

뭐.. 이 모든게 엄청 복잡해요

모더니즘이 있다면 쉽게 생각할 수 있습니다.

ev = Modernizr.touch ? 'touchstart' : 'click';

$('#menu').on(ev, '[href="#open-menu"]', function(){
  //winning
});

일반적으로 기본 터치와 비터치(클릭) api를 혼용하고 싶지 않습니다.터치의 세계로 넘어가면 터치와 관련된 기능만 다루기가 쉬워집니다.아래는 당신이 원하는 것을 할 수 있는 의사 코드입니다.

터치 이동 이벤트에서 연결하고 위치를 추적하면 DoTouchLogic 기능에서 더 많은 항목을 추가하여 제스처 등을 감지할 수 있습니다.

var touchStartTime;
var touchStartLocation;
var touchEndTime;
var touchEndLocation;

$thing.bind('touchstart'), function() {
     var d = new Date();
     touchStartTime = d.getTime();
     touchStartLocation = mouse.location(x,y);
});

$thing.bind('touchend'), function() {
     var d = new Date();
     touchEndTime= d.getTime();
     touchEndLocation= mouse.location(x,y);
     doTouchLogic();
});

function doTouchLogic() {
     var distance = touchEndLocation - touchStartLocation;
     var duration = touchEndTime - touchStartTime;

     if (duration <= 100ms && distance <= 10px) {
          // Person tapped their finger (do click/tap stuff here)
     }
     if (duration > 100ms && distance <= 10px) {
          // Person pressed their finger (not a quick tap)
     }
     if (duration <= 100ms && distance > 10px) {
          // Person flicked their finger
     }
     if (duration > 100ms && distance > 10px) {
          // Person dragged their finger
     }
}

더 나은 유지보수를 위한 또 다른 구현.그러나 이 기법은 event.stopPropagation()도 수행합니다.클릭은 100ms 동안 클릭한 다른 요소에는 잡히지 않습니다.

var clickObject = {
    flag: false,
    isAlreadyClicked: function () {
        var wasClicked = clickObject.flag;
        clickObject.flag = true;
        setTimeout(function () { clickObject.flag = false; }, 100);
        return wasClicked;
    }
};

$("#myButton").bind("click touchstart", function (event) {
   if (!clickObject.isAlreadyClicked()) {
      ...
   }
}

문서화 목적으로만 데스크톱/탭 온 모바일 솔루션에서 가장 빠르고 반응이 좋은 클릭을 위해 수행한 작업은 다음과 같습니다.

는 jQuery 의했습니다를 하였습니다.on브라우저가 터치 이벤트를 지원할 때마다 모든 클릭 이벤트를 터치 시작으로 대체하는 수정된 기능이 있습니다.

$.fn.extend({ _on: (function(){ return $.fn.on; })() });
$.fn.extend({
    on: (function(){
        var isTouchSupported = 'ontouchstart' in window || window.DocumentTouch && document instanceof DocumentTouch;
        return function( types, selector, data, fn, one ) {
            if (typeof types == 'string' && isTouchSupported && !(types.match(/touch/gi))) types = types.replace(/click/gi, 'touchstart');
            return this._on( types, selector, data, fn);
        };
    }()),
});

이전과 동일한 사용량: 다음과 같은 용도로 사용할 수 있습니다.

$('#my-button').on('click', function(){ /* ... */ });

그러나 사용 가능할 때는 터치 시작을 사용하고, 사용 가능하지 않을 때는 클릭합니다.어떤 종류의 지연도 필요 없습니다 :D

요 하면 요.ontouchstart유발된 적이 있습니다 경우 이 경우 우리는 이를 지원하는 장치에 있으며 이를 무시하고자 합니다무시하고자 .onclick트 로. 그 이후로ontouchstart항상 트리거 전에 실행해야 합니다. onclick, 이걸 사용하고 있습니다.

<script> touchAvailable = false; </script>
<button ontouchstart="touchAvailable=true; myFunction();" onclick="if(!touchAvailable) myFunction();">Button</button>

다음과 같이 시도할 수 있습니다.

var clickEvent = (('ontouchstart' in document.documentElement)?'touchstart':'click');
$("#mylink").on(clickEvent, myClickHandler);

제 경우에는 완벽하게 작동했습니다.

jQuery(document).on('mouseup keydown touchend', function (event) {
var eventType = event.type;
if (eventType == 'touchend') {
    jQuery(this).off('mouseup');
}
});

가장 큰 문제는 대신 클릭으로 마우스업을 시도하고 터치 장치에서 클릭과 터치를 동시에 트리거하는 경우, 클릭 오프를 사용하면 모바일 장치에서 일부 기능이 전혀 작동하지 않는다는 것입니다.클릭의 문제는 터치를 포함한 나머지 이벤트를 해고하는 글로벌 이벤트라는 것입니다.

이것은 저에게 효과가 있었습니다. 모바일은 둘 다 듣고 있으므로 터치 이벤트인 하나를 방지하십시오. 데스크톱은 마우스만 듣습니다.

 $btnUp.bind('touchstart mousedown',function(e){
     e.preventDefault();

     if (e.type === 'touchstart') {
         return;
     }

     var val = _step( _options.arrowStep );
               _evt('Button', [val, true]);
  });

이것은 여기서 언급되지 않았지만, 당신은 이 링크를 확인하고 싶을지도 모릅니다: https://joshtronic.com/2015/04/19/handling-click-and-touch-events-on-the-same-element/

후세를 위해 요약하자면, 두 핸들러에 할당한 다음 결과를 분류하는 대신 장치가 터치스크린인지 여부를 확인하고 관련 이벤트에만 할당할 수 있습니다.관찰:

var clickEvent = (function() {
  if ('ontouchstart' in document.documentElement === true)
    return 'touchstart';
  else
    return 'click';
})();

// and assign thusly:

el.addEventListener( clickEvent, function( e ){ 
    // things and stuff
});

를 할 수 데 .touchstart그리고.click들만 내서를발합니다.click

그러나 이 링크의 저자가 언급한 한 가지 문제는 두 가지 이벤트를 모두 처리하도록 설계된 터치스크린 노트북입니다.

제가 고려하지 않았던 세 번째 장치인 터치스크린 노트북에 대해 알게 되었습니다.터치 이벤트와 클릭 이벤트를 모두 지원하는 하이브리드 장치입니다.하나의 이벤트를 바인딩한다는 것은 해당 이벤트만 지원된다는 것을 의미합니다.그 말은 터치스크린과 마우스를 가진 사람이 내가 다루는 유일한 이벤트이기 때문에 명백하게 터치해야 한다는 뜻입니까?

touchstart그리고.click이 하이브리드 장치를 다루는 데 이상적인 것 같습니다.이벤트가 두 번 발사되는 것을 막기 위해, 저는 덧붙였습니다.e.stopPropagation()그리고.e.preventDefault()콜백 함수에 적용할 수 있습니다.e.stopPropagation()이벤트가 부모에게 "거품이 되는" 것을 방지할 뿐만 아니라 두 번째 이벤트가 발생하는 것을 방지합니다.했습니다.e.preventDefault()"혹시 모르니"라고 생각하지만 생략될 수도 있을 것 같습니다.

모티가 제시한 최고의 답이 된 저는 그의 코드를 재사용하기 위해 노력하고 있습니다. 그래서 이것이 제 기여입니다.

bindBtn ("#loginbutton",loginAction);

function bindBtn(element,action){

var flag = false;
$(element).bind('touchstart click', function(e) {
    e.preventDefault();
    if (!flag) {
        flag = true;
        setTimeout(function() {
            flag = false;
        }, 100);
        // do something
        action();
    }
    return false;
});

Android/iPad 웹 앱에서도 작업 중인데, "터치 무브"만 사용하면 "구성 요소를 이동"할 수 있는 것 같습니다(터치 스타트 필요 없음).터치 시작을 사용하지 않도록 설정하면 jQuery의 .click();을(를) 사용할 수 있습니다.터치 스타트로 과부하가 걸리지 않았기 때문에 실제로 작동합니다.

마지막으로 binb.live("touchstart", 함수(e) {e.stopPropagation(); }); 터치 시작 이벤트에 전파를 중지하도록 요청하고 거실을 클릭하여 트리거할 수 있습니다.

그것은 나에게 효과가 있었다.

이 문제를 해결하기 위해 노력할 때 고려해야 할 점이 많습니다.대부분의 솔루션은 스크롤을 끊거나 고스트 클릭 이벤트를 제대로 처리하지 못합니다.

전체 솔루션은 https://developers.google.com/mobile/articles/fast_buttons 을 참조하십시오.

NB: 고스트 클릭 이벤트는 요소별로 처리할 수 없습니다.화면 위치별로 지연된 클릭이 발생하므로 터치 이벤트가 페이지를 수정하는 경우 클릭 이벤트가 새 버전의 페이지로 전송됩니다.

일 수 .'touchstart mousedown'아니면'touchend mouseup'는 하는 데 따른 s을 click.

터치 이벤트 뒤에는 항상 클릭이 뒤따른다는 점을 이용해 타임아웃이나 글로벌 플래그를 사용하지 않고 '유령 클릭'을 없애기 위해 한 일은 이렇다.

$('#buttonId').on('touchstart click', function(event){
    if ($(this).data("already")) {
        $(this).data("already", false);
        return false;
    } else if (event.type == "touchstart") {
        $(this).data("already", true);
    }
    //your code here
});

으로 가 있을 때마다ontouchstart이벤트는 요소에 대해 실행되며, 플래그 집합에 플래그를 지정한 다음 클릭 시 제거(및 무시)됩니다.

왜 jQuery Event API를 사용하지 않습니까?

http://learn.jquery.com/events/event-extensions/

저는 이 간단한 행사를 성공적으로 사용했습니다.깨끗하고 네임스페이스가 가능하며 개선할 수 있을 만큼 유연합니다.

var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent);
var eventType = isMobile ? "touchstart" : "click";

jQuery.event.special.touchclick = {
  bindType: eventType,
  delegateType: eventType
};

당신이 jQuery를 사용하고 있다면 다음이 저에게 꽤 잘 맞았습니다.

var callback; // Initialize this to the function which needs to be called

$(target).on("click touchstart", selector, (function (func){
    var timer = 0;
    return function(e){
        if ($.now() - timer < 500) return false;
        timer = $.now();
        func(e);
    }
})(callback));

다른 솔루션도 좋지만 여러 이벤트를 하나의 루프로 묶고 있었고 적절한 클로징을 만들기 위해 셀프 콜링 기능이 필요했습니다.또한 다음 클릭/터치 시작 시 호출이 가능하기를 원했기 때문에 바인딩을 비활성화하고 싶지 않았습니다.

비슷한 상황에 있는 누군가를 도와줄 수도 있습니다!

간단한 기능의 경우 터치를 인식하거나 다음 코드 사용을 클릭합니다.

var element = $("#element");

element.click(function(e)
{
  if(e.target.ontouchstart !== undefined)
  {
    console.log( "touch" );
    return;
  }
  console.log( "no touch" );
});

터치 시작 이벤트가 정의되면 "터치"가 반환되고 그렇지 않으면 "터치 안 함"이 반환됩니다.이것은 클릭/탭 이벤트에 대한 간단한 접근 방식이라고 말씀드렸습니다.

나는 이것을 시도하고 있고 지금까지 작동합니다 (하지만 나는 Android/Phonegap에만 있으므로 emptor에 주의하십시오)

  function filterEvent( ob, ev ) {
      if (ev.type == "touchstart") {
          ob.off('click').on('click', function(e){ e.preventDefault(); });
      }
  }
  $('#keypad').on('touchstart click', '.number, .dot', function(event) {
      filterEvent( $('#keypad'), event );
      console.log( event.type );  // debugging only
           ... finish handling touch events...
  }

모든 터치에서 핸들러를 다시 바인딩한다는 사실이 마음에 들지는 않지만, 모든 터치로 간주되는 경우는 그리 자주 발생하지는 않습니다(컴퓨터 시간에!).

저는 '#키패드'용 핸들러와 같은 수많은 핸들러를 가지고 있기 때문에 너무 많은 코드 없이 문제를 해결할 수 있는 간단한 기능을 가지고 있기 때문에 이런 길을 가게 되었습니다.

사용해 봅니다.Virtual Mouse (vmouse) BindingsjQuery Mobile 고객의 특히 고객의 경우 가상 이벤트입니다.

$thing.on('vclick', function(event){ ... });

http://api.jquerymobile.com/vclick/

브라우저 지원 목록: http://jquerymobile.com/browser-support/1.4/

편집: (이 스레드에서 답변을 기반으로) 이전의 답변은 제게 맞는 방법이 아니었습니다.마우스 입력 또는 터치 클릭 시 확장하고 마우스 이탈 또는 다른 터치 클릭 시 축소하는 하위 메뉴를 원했습니다.마우스 이벤트는 일반적으로 터치 이벤트 후에 발사되기 때문에, 터치스크린과 마우스 입력을 동시에 지원하는 이벤트 청취자를 작성하는 것이 다소 까다로웠습니다.

jQuery 플러그인:터치 또는 마우스

터치 스크린 또는 마우스에서 이벤트가 호출되었는지(터치 지원 테스트 없이) 감지할 수 있는 "터치 또는 마우스"(최소화된 897바이트)라는 jQuery 플러그인을 작성했습니다.이를 통해 터치스크린과 마우스를 동시에 지원하고 이벤트를 완전히 분리할 수 있습니다.

를 사용할 수 .touchstart아니면touchend및다에 할 수 .click마우스에서만 호출되는 클릭의 경우.

데모

먼저 신체 요소 트랙 터치 이벤트를 만들어야 합니다.

$(document.body).touchOrMouse('init');

는 기본 을 를 호출하여 합니다.$body.touchOrMouse('get', e)우리는 이벤트가 터치스크린에 의해 호출되었는지 마우스에 의해 호출되었는지 알 수 있습니다.

$('.link').click(function(e) {
  var touchOrMouse = $(document.body).touchOrMouse('get', e);

  if (touchOrMouse === 'touch') {
    // Handle touch click.
  }
  else if (touchOrMouse === 'mouse') {
    // Handle mouse click.
  }
}

http://jsfiddle.net/lmeurs/uo4069nh 에서 플러그인을 참조하십시오.

설명.

  1. 이 플러그인을 호출해야 합니다.추적할 신체 요소touchstart그리고.touchend,touchend트리거 요소(즉, 링크 또는 버튼)에서 이벤트를 실행할 필요가 없습니다.이 두 터치 이벤트 사이에서 이 플러그인은 마우스 이벤트가 터치에 의해 호출되는 것으로 간주합니다.
  2. 마우스 이벤트는 다음 시간 이후에만 실행됩니다.touchend가 에서 때 , ghostEventDelay션,값 1000ms)이후touchend 합니다에 합니다.
  3. 를 .:active.mouseleave이벤트는 요소가 이 상태를 상실한 후(즉, 다른 요소를 클릭하는 경우)에만 발생합니다.분입니다)초 몇 초 몇 분가 될 수 있기 입니다.mouseenter 이 되었습니다를 합니다.합니다.mouseenter트일 :mouseenter 며다.mouseleave이벤트는 터치에 의해서도 호출되는 것으로 간주됩니다.

간단한 방법은 다음과 같습니다.

// A very simple fast click implementation
$thing.on('click touchstart', function(e) {
  if (!$(document).data('trigger')) $(document).data('trigger', e.type);
  if (e.type===$(document).data('trigger')) {
    // Do your stuff here
  }
});

기본적으로 'trigger' 속성에 트리거된 첫 번째 이벤트 유형을 루트 문서에 첨부된 jQuery의 데이터 개체에 저장하고, 이벤트 유형이 'trigger'의 값과 같을 때만 실행합니다.터치 장치에서 이벤트 체인은 '터치 시작' 다음에 '클릭'이 오는 경우가 많지만 '클릭' 핸들러는 '트리거'("터치 시작")에 저장된 초기 이벤트 유형과 일치하지 않으므로 '클릭' 핸들러는 실행되지 않습니다.

제 생각에는 스마트폰이 터치 장치에서 마우스 장치로 자발적으로 변경되지 않을 것이고 그렇지 않을 경우 '트리거' 이벤트 유형이 페이지 로드당 한 번만 저장되고 '클릭'은 '터치 시작'과 일치하지 않을 것이기 때문입니다.

사용할 수 있는 코드 펜은 다음과 같습니다(터치 장치의 버튼을 눌러 보십시오. 클릭 지연이 없어야 합니다.).http://codepen.io/thdoan/pen/xVVrOZ

저는 이를 단순한 jQuery 플러그인으로 구현하기도 했는데, 이 플러그인은 선택기 문자열을 전달하여 jQuery의 하위 필터링도 지원합니다.

// A very simple fast click plugin
// Syntax: .fastClick([selector,] handler)
$.fn.fastClick = function(arg1, arg2) {
  var selector, handler;
  switch (typeof arg1) {
    case 'function':
      selector = null;
      handler = arg1;
      break;
    case 'string':
      selector = arg1;
      if (typeof arg2==='function') handler = arg2;
      else return;
      break;
    default:
      return;
  }
  this.on('click touchstart', selector, function(e) {
    if (!$(document).data('trigger')) $(document).data('trigger', e.type);
    if (e.type===$(document).data('trigger')) handler.apply(this, arguments);
  });
};

코드펜: http://codepen.io/thdoan/pen/GZrBdo/

언급URL : https://stackoverflow.com/questions/7018919/how-to-bind-touchstart-and-click-events-but-not-respond-to-both

반응형