'touchstart'및 'click'이벤트를 바인딩하지만 둘 다에 응답하지 않는 방법은 무엇입니까?


198

다양한 장치에서 작동해야하는 모바일 웹 사이트에서 작업하고 있습니다. 지금 당장 나에게 두통을주는 것은 BlackBerry입니다.

키보드 클릭과 터치 이벤트를 모두 지원해야합니다.

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

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

그러나 우리가 겪고있는 문제는 이러한 블랙 베리 장치 중 일부는 터치 시간부터 클릭 트리거까지 매우 성가신 지연이 있다는 것입니다.

해결 방법은 touchstart를 대신 사용하는 것입니다.

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

그러나 두 이벤트를 바인딩하고 어떻게 시작합니까? 키보드 장치에는 여전히 클릭 이벤트가 필요하지만 터치 장치를 사용하는 경우 클릭 이벤트 발생을 원하지 않습니다.

보너스 질문 : 어쨌든 터치 스타트 이벤트가없는 브라우저를 추가로 수용 할 수 있습니까? 이를 조사 할 때 BlackBerry OS5는 터치 스타트를 지원하지 않는 것 같으므로 해당 브라우저의 클릭 이벤트에 의존해야합니다.

추가:

아마도 더 포괄적 인 질문은 다음과 같습니다.

jQuery를 사용하면 동일한 바인딩으로 터치 상호 작용과 마우스 상호 작용을 모두 처리하는 것이 가능 / 권장됩니까?

이상적으로 대답은 '예'입니다. 그렇지 않은 경우 몇 가지 옵션이 있습니다.

1) WURFL을 사용하여 장치 정보를 얻으므로 자체 장치 행렬을 만들 수 있습니다. 기기에 따라 터치 스타트 또는 클릭을 사용합니다.

2) JS를 통해 브라우저에서 터치 지원을 감지하십시오 (더 많은 연구가 필요하지만 그렇게 할 수있는 것처럼 보입니다).

그러나 여전히 한 가지 문제가 남아 있습니다. BOTH를 지원하는 장치는 어떻습니까? 당사가 지원하는 일부 전화 (즉, Nokias 및 BlackBerries)에는 터치 스크린 키보드 가 모두 있습니다. 그래서 그런 종류의 원조로 다시 원래 질문으로 돌아갑니다 ... 어쨌든 두 가지를 동시에 허용 할 수있는 방법이 있습니까?


2
터치 스타트 및 터치 엔드에 바인딩하고 터치 로직과 함께 자신의 클릭 로직을 작성하는 것이 좋습니다. 터치에 대한 지식이없는 내장 클릭 콜백
Justin808

잘 모르겠어요, 저스틴 터치 스타트 및 클릭 이벤트가 모두 바인딩되어 있지 않습니까?
DA.

@DA-아니요, .click () 콜백에 전혀 바인딩하지 않습니다. 나는 sudo 코드로 답을 쓰려고 노력할 것이다. 나는 실제 코드를 작성하는 데 편리한 터치 장치가 없다 :)
Justin808

아, 그러나 명확히하기 위해 터치 장치가 아닌이 사이트에 액세스하는 사람들이 있기 때문에 클릭 이벤트가 여전히 필요합니다.
DA.

2
를 사용 .bind('touchstart mouseup')하면 문제가 해결됩니다 (아래 설명 중 하나를 기반으로 함)
oriadam

답변:


135

업데이트 : 마우스와 터치 중 하나를 선택하는 대신 "포인터"이벤트에 바인딩 할 수 있는 jQuery 포인터 이벤트 폴리 필 프로젝트를 확인하십시오 .


둘 다 바인딩하지만 플래그를 만들어서 함수가 100ms마다 한 번만 실행되도록하십시오.

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

  return false
});

7
흠 ... 해키 느낌이지만, 그것은 효과가 있습니다. 이 장치 중 일부에서는 눈에 띄는 지연이 발생합니다. 아마도 거의 1 초입니다.
DA.

15
사용하는 대신 click에 변화를 mousedown... 어쩌면 긴 지연 사이의 차이는 mousedown하고 mouseup이는이 어떻게 click결정된다.
Mottie

7
이것이 내가 함께했던 해결책입니다. 감사! 내가하는 일은 touchend의 클래스를 적용 하여 항목을 플래그 지정하는 것 입니다 touched. 클릭 이벤트가 호출되기 전에 발생합니다. 그런 다음 해당 클래스가 있는지 먼저 확인하는 클릭 이벤트를 추가하십시오. 거기에 있다면 터치 이벤트가 시작되었다고 가정하고 다음 상호 작용을 위해 클래스 이름을 제거하여 '재설정'하는 것 외에 클릭으로 아무것도하지 않습니다. 수업이 없으면 키보드를 사용하여 항목을 클릭하고 해당 기능을 트리거했다고 가정합니다.
DA.

7
대부분의 전화 브라우저는 클릭 이벤트 에서 300ms 지연이 발생하므로 지연을 300 이상으로 늘려야합니다. 이 기사에서 300ms 지연 문제를 참조하십시오 . 이것은 기본적으로 대부분의 웹 사이트가 큰 데스크탑 화면에서 볼 수 있도록 설계된 초기 iPhone 시대에 매우 중요한 기능인 "더블 클릭 투 줌"기능을 활성화하는 것입니다.
awe

12
이 질문은이 시점에서 거의 10 만 번에 달했습니다. 이것은 매우 일반적인 유스 케이스 / 문제처럼 보입니다. 그러나이 답변과 이와 비슷한 질문에 대한 다른 사람들은 모두 해키처럼 보입니다. 구글 솔루션은 대부분의 것보다 더 철저하게 생각하지만 더 강력한 해킹처럼 보입니다. 클릭 핸들러처럼 단순한 것은 솔루션이 간단해야합니다. 이 문제에 대한 비 핵심 솔루션을 찾지 못했습니까?
jinglesthula

73

이것은 내가 "만든"수정이며 GhostClick을 꺼내고 FastClick을 구현합니다. 직접 시도해보고 효과가 있는지 알려주십시오.

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

        // Do your magic here

});

2
helgatheviking : jsbin.com/ijizat/25 JavaScript에는 위의 기능을 포함하는 TouchClick이라는 기능이 있습니다.
매트 파 킨스

5
a) 장치 기능을 테스트하지 않고 b) setTimeout을 사용하지 않기 때문에이 질문에 대한 모든 답변에 대해이 방법을 선호합니다. 내 경험상 setTimeout을 사용하는 이와 같은 문제에 대한 솔루션은 대부분의 경우 작동하지만 이벤트 타이밍은 상당히 임의적이며 장치마다 다릅니다.
itsmequinn

7
익명 함수에서 'event'를 전달하면 해당 함수 내에서 로컬 객체가되므로 이벤트가 트리거 될 때마다 event.handled동일 하므로 undefined작동하지 않습니다. 해결책은 다음과 같습니다 jQuery.data(). 를 사용하여 대상 요소 자체에서 'handled'플래그를 설정하십시오 .
thdoan

3
당신은이 event.stopPropagation();event.preventDefault();나의 이해 (테스트)에서 이벤트는이 한 번 발사 할 수있다. 그래서 왜 확인 if(event.handled !== true)합니까? 나를 위해 필요하지 않거나 뭔가를 그리워합니까?
nbar

2
event.handled값을 확인 해서는 안 true됩니까? 내가 알 수있는 한 결코 그렇지 않습니다 false. 로 시작한 undefined다음이로 설정되어 있는지 알려고합니다 true.
ACJ

49

다음과 같이 시도해보십시오.

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

5
문제는 사용자가하는 것이 아니라 장치 기능을 테스트하는 것입니다. 문제는 키보드가있는 터치 장치 (두 가지 모두 사용 가능)
DA

8
이 방법은 좋지 않습니다. 마우스를 사용할 때 터치 스크린과 마우스를 사용하는 사용자의 경우 이벤트가 중단됩니다 (터치 스크린이있는 랩탑이 점점 일반화되고 있음).
Kristian J.


'ontouchstart'가이 OS에 대해 'true'를 반환하므로 Windows 8은 'touchstart'이벤트를 사용하는 경우 항상 연결합니다. 따라서 코드가 실제 터치 스크린 장치에서만 실행되지 않는 한 가장 좋은 대답은 아니지만 확인이 필요한 경우 전혀 확인하지 않아도됩니다.
Neil Monroe

터치 스크린이있는 랩톱에서는 사용자가 크롬 (최소한 크롬 46)에서이 코드를 사용하여 아무 것도 클릭 할 수 없습니다. IE 11은 작동하는 것 같습니다.
David Sherret

42

일반적으로 이것은 다음과 같이 작동합니다.

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

});

8
최신 jQuery 버전을 사용하는 경우 @Jonathan이 잘못되었습니다. 버전 1.7에서는 라이브가 더 이상 사용되지 않습니다.
Mike Barwick

나는 또한 e.stopPropagation ()을 사용해 보았습니다 (내 아이디어가 아닌 다른 곳에서 읽었습니다). e.preventDefault (); 그리고 그것은 (나에게) 거의 작동하지만 나중에 20 번 예상되지만 1 번 작동하지 않는다는 것을 나중에 알게되었습니다. 여기를보십시오 : stackoverflow.com/questions/25671053/… 해당 문제에 대한 의견을 보내주십시오!
Garavani

@MikeBarwick 의견을 설명하거나 설명하는 링크를 제공해 주시겠습니까? 미리 감사드립니다.
Billal Begueradj

22

이벤트 함수 return false;끝에 추가하면 on("click touchstart")이 문제를 해결할 수 있습니다.

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

.on () 의 jQuery 문서에서

false이벤트 핸들러에서 복귀 하면 자동으로 event.stopPropagation()및을 호출 event.preventDefault()합니다. false핸들러 의 값을 약식으로 전달할 수도 있습니다 function(){ return false; }.


2
모두 장치에서 한 번만 큰 화재를 작동 -이 나에게 깨끗한 적어도 해키 솔루션처럼 보인다
아담 쿠퍼

나를 위해 최선을 다했고 실제로 이유를 이해했습니다.
Amir5000

이것의 단점은 무엇입니까? 왜 그렇게 간단한 해결책이 널리 알려지지 않았습니까?
ESR

10

나는 비슷한 것을해야했습니다. 여기 나를 위해 일한 것의 단순화 된 버전이 있습니다. 터치 이벤트가 감지되면 클릭 바인딩을 제거하십시오.

$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)는 당신이 생각하는 것을 가리 키지 않습니다.
Dave Lowerre

8

나는 다음과 같은 방법으로 성공했다.

쉬워요...

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

4
클릭과 터치 스타트를 모두 등록하는 장치에서 두 번 실행되지 않습니까?
DA.

8
죄송합니다. 예, 터치하면 터치 스타트 이벤트와 클릭 이벤트도 생성됩니다. 이것을 고스트 클릭이라고합니다. Google은이를위한 솔루션을 구현했습니다. 간단하지는 않지만 완벽하게 작동합니다. 여기 링크가 있습니다. code.google.com/mobile/articles/fast_buttons.html#ghost
Hasanavi

2
사소한 될 수 있지만이 누락 e에 매개 변수를function()
ProblemsOfSumit

@Hasanavi 이것은 훌륭한 수정이지만 .on을 사용하여 더 나은 결과를 찾았습니다.
Neil

1
@ 닐 감사합니다. 예. .on을 사용하는 것이 향후 버전에서 제거 될 수 있으므로 더 좋습니다. 예제를 bind에서 on으로 변경했습니다.
Hasanavi

5

모범 사례는 이제 사용하는 것입니다.

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

터치

터치 표면에서 터치 포인트가 제거되면 터치 엔드 이벤트가 시작됩니다.

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


마우스

마우스 포인터가 요소 위에 있고 마우스 버튼을 놓으면 mouseup 이벤트가 요소로 전송됩니다. 모든 HTML 요소가이 이벤트를 수신 할 수 있습니다.

mouseup 이벤트는 터치 이벤트를 트리거하지 않습니다 .

$('#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>


편집 (2017)

2017 년부터 Chrome을 시작 .on("click")으로 클릭 요청시 탭 이벤트로 인해 발생하는 지연을 제거하여 클릭 이벤트를 마우스와 터치 모두에 대해 더 호환 가능 하게 만드는 단계를 수행하는 브라우저 입니다.

클릭 이벤트만으로 되 돌리는 것이 가장 간단한 해결책이라는 결론에 이르게됩니다.

이것이 실제적인지 확인하기 위해 아직 크로스 브라우저 테스트를 수행하지 않았습니다.


이것은 나에게 유망한 것처럼 보였으므로 무리로 엉망 이었지만 궁극적 mouseup으로는 특히 전통적인 마우스 대신 트랙 패드를 사용할 때 예기치 않은 결과가있는 것으로 나타났습니다 .
skybondsor

4

일반적으로 기본 터치와 비 터치 (클릭) API를 혼합하고 싶지 않습니다. 터치의 세계로 이동하면 터치 관련 기능 만 쉽게 처리 할 수 ​​있습니다. 아래는 원하는 것을 수행하는 의사 코드입니다.

touchmove 이벤트에 연결하고 위치를 추적하면 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
     }
}

나는 그것이 문제의 요점이라고 생각합니다 : 하나의 코드베이스로 두 모델을 모두 지원하고 시도하는 것이 합리적입니까? 몇 가지 시나리오로 질문을 업데이트하겠습니다.
DA.

1
"일반적으로 기본 터치와 비 터치를 혼합하고 싶지 않습니다."이 과정을 거친 후에 동의합니다. 문제는 키보드를 사용하여 터치 장치를 계속 만들고 있다는 점입니다. 이는 개발자에게는 골치 아픈 일입니다.
DA.

나는 최종 js 의사 결정 터치 시작 또는 터치 없음이 훨씬 쉬울 것이라는 데 동의합니다. 얼마나 쉬운 세상일까요! 그러나 저주받은 장치의 클릭 및 터치가 현명한 것은 무엇입니까? 두통 때문에 두통이 생길만한 가치가 있습니까? 이것이 내가 미래인 나에게 미래인가?
Garavani

함수를 여러 개 정의한다는 아이디어가 마음에 들지 않습니다. 우리 회사는 현재 iPad가 모바일 장치로 특수하게 처리되지 않고 여전히 터치 엔드 이벤트가 필요한 프로젝트를 진행하고 있습니다. 그러나 일반 데스크톱 버전에서는 touchend가 작동하지 않습니다. 따라서 @mottie의 솔루션은 해당 시나리오에 절대적으로 적합합니다.
Pete


3

글쎄 ...이 모든 것은 매우 복잡합니다.

당신이 modernizr을 가지고 있다면, 그것은 쉬운 일이 아닙니다.

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

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

2
그것이 무엇을 설명 할 수 있습니까? 장치가 터치를 지원하는지 확인하고 그렇지 않은 경우 클릭을 사용한다고 확인합니다. 캐치는 (또는 적어도 이었다 내가 질문을 썼을 때) 일부 장치를 모두 지원이었다. 이러한 장치에서는 트리거가 터치 또는 클릭으로 발생할 수 있으므로 여전히 두 이벤트를 모두 처리해야합니다.
DA.

2
좀 더 설명해 드리겠습니다.
Aaron Hall

2

더 나은 유지 보수를위한 또 다른 구현입니다. 그러나이 기술은 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()) {
      ...
   }
}

2

문서화 목적으로, 내가 생각할 수있는 모바일 솔루션의 데스크탑 / 탭에서 가장 빠르고 반응이 빠른 클릭을 위해 내가 한 일은 다음과 같습니다.

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

$.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


1
여기에는 두 가지 상호 작용을 모두 수용 할 수있는 터치 및 키보드를 모두 지원하는 장치가 있습니다.
DA.

좋은 관찰 @DA. 터치 이벤트와 함께 터치 이벤트를 사용하지 않는 경우 클릭 이벤트 만 교체하도록 체크 표시를 추가했습니다. Stil은 모든 프로젝트에 대한 해결책은 아니지만 많은 사람들에게 적합 할 것이라고 확신합니다.
Gerson Goulart

2

나는 ontouchstart방아쇠를 당겼다 면 암기 할 아이디어를 생각해 냈습니다 . 이 경우 우리는 그것을 지원하는 장치에 있으며 onclick이벤트 를 무시하고 싶습니다 . ontouchstart항상 전에 트리거 해야하기 때문에 onclick이것을 사용하고 있습니다.

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


1
사용자는 동일한 페이지 방문 중에 터치 및 마우스를 사용할 수 있으므로이 스 니펫의 문제점은 이벤트 당 대신 touchAvailable 플래그를 한 번 등록한다는 것입니다. stackoverflow.com/a/26145343/328272 의 jQuery 플러그인은 코드와 동일하지만 이벤트를 기준으로 터치 또는 마우스로 트리거했는지 마우스 이벤트에 알릴 수 있습니다. 뿐만 아니라. 클릭시뿐만 아니라 마우스 입력 후 몇 초 (또는 몇 분)에 트리거 될 수있는 마우스 리브 (마우스 제스처로 마우스를 올리거나 터치를 사용할 때 클릭해야하는 플라이 아웃 메뉴에 이상적).
lmeurs

2

다음과 같이 시도해보십시오.

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

지원하는 터치와 마우스 장치에 대한 것
WALLE 시릴

2

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

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

주요 문제는 마우스 클릭 대신 터치 장치에서 클릭과 터치 엔드를 동시에 트리거했을 때 클릭 오프를 사용하면 모바일 장치에서 일부 기능이 전혀 작동하지 않았다는 것입니다. 클릭 문제는 터치 엔드를 포함한 나머지 이벤트를 발생시키는 글로벌 이벤트입니다.


1

이것은 나를 위해 일했습니다. 모바일은 두 가지를 모두 청취하므로 터치 이벤트 인 것을 피하십시오. 데스크탑은 마우스 만 청취합니다.

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

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

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

1

Mottie가 제공 한 답변 중 가장 좋은 답변이기 때문에 코드를 더 재사용 할 수 있도록 노력하고 있습니다.

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;
});

0

또한 Android / iPad 웹 앱에서 작업 중이며 "touchmove"만 사용하면 "구성 요소를 이동"하기에 충분합니다 (touchstart 필요 없음). touchstart를 비활성화하면 .click (); jQuery에서. touchstart에 의해 과부하되지 않았기 때문에 실제로 작동합니다.

마지막으로 .live ( "touchstart", function (e) {e.stopPropagation ();}); 터치 스타트 이벤트가 전파를 멈추도록 요청하고 거실을 click ()하여 트리거합니다.

그것은 나를 위해 일했다.


어떻게 비활성화 touchstart합니까?
punkrockbuddyholly

나는 당신이 다음과 같은 것을 할 수 있다고 믿는다 : jQuery ( "# my_element"). on ( 'touchstart', function (e) {e.preventDefault ()});
nembleton

0

이 문제를 해결하려고 할 때 고려해야 할 사항이 많이 있습니다. 대부분의 솔루션은 스크롤을 끊거나 고스트 클릭 이벤트를 올바르게 처리하지 않습니다.

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

주의 : 요소별로 고스트 클릭 이벤트를 처리 할 수 ​​없습니다. 지연된 클릭은 화면 위치에 따라 실행되므로 터치 이벤트가 어떤 방식 으로든 페이지를 수정하면 클릭 이벤트가 새 버전의 페이지로 전송됩니다.


0

이 이벤트에 할당하는 것이 효과적 일 수 'touchstart mousedown'또는 'touchend mouseup'사용의 바람직하지 않은 부작용을 피하기 위해 click.


0

클릭이 항상 터치 이벤트를 따른다 는 사실을 활용 하면 시간 초과 또는 전역 플래그를 사용하지 않고 "고스트 클릭"을 제거하기 위해 수행 한 작업이 있습니다.

$('#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이벤트가 요소에서 발생할 때마다 세트에 플래그를 지정한 다음 클릭이 발생할 때 제거하고 무시합니다.


0

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
};

1
사용자 에이전트 스니핑보다 기능 감지를 사용하는 것이 좋습니다.
jinglesthula

캐치는 터치와 클릭을 모두 지원하는 장치입니다.
DA.

0

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));

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

비슷한 상황에있는 사람을 도울 수 있습니다!


0

간단한 기능을 사용하려면 터치를 인식하거나 클릭하십시오. 다음 코드를 사용합니다.

var element = $("#element");

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

터치 스타트 이벤트가 정의되어 있으면 "touch"를, 그렇지 않으면 "no touch"를 반환합니다. 내가 말했듯이 이것은 클릭 / 탭 이벤트에 대한 간단한 접근법입니다.


0

나는 이것을 시도하고 있으며 지금까지는 효과가있다 (그러나 나는 안드로이드 / Phonegap에만주의해야 함)

  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...
  }

나는 모든 터치에서 핸들러를 리 바인드한다는 사실을 좋아하지 않지만 터치로 간주되는 모든 것은 (컴퓨터 시간에) 자주 발생하지 않습니다!

나는 '#keypad'와 같은 처리기 톤을 가지고 있으므로 너무 많은 코드없이 문제를 해결할 수있는 간단한 기능을 가지고 있기 때문에이 방법을 사용했습니다.



0

편집 : 내 이전 답변 (이 스레드의 답변을 기반으로 함)은 나를 위해 갈 길이 없었습니다. 마우스 입력 또는 터치 클릭시 하위 메뉴가 확장되고 마우스 종료 또는 다른 터치 클릭시 축소되는 하위 메뉴가 필요했습니다. 마우스 이벤트는 일반적으로 터치 이벤트 후에 시작되므로 터치 스크린과 마우스 입력을 동시에 지원하는 이벤트 리스너를 작성하는 것은 까다로 웠습니다.

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

" 터치 지원을 테스트하지 않고 터치 스크린 또는 마우스로 이벤트를 호출했는지 여부를 감지 할 수있는 " Touch Or Mouse "(897 바이트 축소) 라는 jQuery 플러그인을 작성했습니다 . 이를 통해 터치 스크린과 마우스 동시에 지원 하고 이벤트를 완전히 분리 할 수 ​​있습니다.

이런 식으로 OP는 터치 클릭과 마우스 호출하는 클릭에 사용 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. 이 플러그인은 즉, 호출해야합니다. 추적 할 본문 요소 touchstarttouchend이벤트 touchend를 사용하면 트리거 요소 (예 : 링크 또는 단추) 에서 이벤트를 실행할 필요가 없습니다. 이 두 터치 이벤트 사이에서이 플러그인은 마우스 이벤트가 터치로 호출되는 것으로 간주합니다.
  2. 마우스 이벤트는 이후에만 발생하며, 이후 touchendghostEventDelay(옵션, 기본적으로 1000ms) 마우스 이벤트가 발생 touchend하면이 플러그인은 마우스 이벤트가 터치로 호출 된 것으로 간주합니다.
  3. 터치 스크린을 사용하여 요소를 클릭하면 요소가 :active상태를 얻습니다 . mouseleave요소, 즉하여이 상태를 상실 후 이벤트는 발생합니다. 다른 요소를 클릭하십시오. mouseenter이벤트가 시작된 후 몇 초 (또는 몇 분) 일 수 있으므로이 플러그인은 요소의 마지막 mouseenter이벤트 를 추적 합니다. 마지막 mouseenter이벤트가 터치로 호출 된 경우 다음 mouseleave이벤트도 터치로 호출 된 것으로 간주됩니다.

0

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

// 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
  }
});

기본적으로 루트 문서에 첨부 된 jQuery의 데이터 객체에서 'trigger'속성에 트리거되는 첫 번째 이벤트 유형을 저장하고 이벤트 유형이 'trigger'의 값과 동일한 경우에만 실행됩니다. 터치 장치에서 이벤트 체인은 'touchstart'와 'click'이 될 것입니다. 그러나 "click"이 "trigger"에 저장된 초기 이벤트 유형 ( "touchstart")과 일치하지 않기 때문에 'click'핸들러는 실행되지 않습니다.

가정은 안전하다고 생각합니다. 스마트 폰이 터치 장치에서 마우스 장치로 자발적으로 변경되지 않거나 '트리거'이벤트 유형이 한 번만 저장되기 때문에 탭이 등록되지 않습니다 페이지로드 및 "클릭"은 "touchstart"와 일치하지 않습니다.

다음은 재생할 수있는 코드 펜입니다 (터치 장치의 버튼을 눌러보십시오. 클릭 지연이 없어야합니다) : 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/


변수를 사용하는 대신 왜 문서에서 데이터 속성을 사용 했습니까?
Raphael Schweikert

@RaphaelSchweikert 아마 습관이 없을 것입니다. 옳고 그른 방법은 없지만 $.data()여러 기능으로 액세스 할 수는 있지만 전역 범위에 속하지 않는 데이터를 저장하는 데 사용 하고 싶습니다 . 플러스는 요소에 저장하기 때문에 자연스럽게 더 많은 컨텍스트를 제공한다는 것입니다.
thdoan

0

내가 찾은 가장 좋은 방법은 터치 이벤트를 작성하고 해당 이벤트를 프로그래밍 방식으로 일반 클릭 이벤트로 호출하는 것입니다. 이 방법으로 모든 일반적인 클릭 이벤트가 있고 모든 터치 이벤트에 대해 하나의 이벤트 핸들러 만 추가하면됩니다. 터치 가능하게 만들려는 모든 노드에 대해 "touchable"클래스를 추가하여 터치 핸들러를 호출하십시오. Jquery를 사용하면 일부 논리와 마찬가지로 작동하여 오탐이 아닌 실제 터치 이벤트를 보장합니다.

$("body").on("touchstart", ".touchable", function() { //make touchable  items fire like a click event
var d1 = new Date();
var n1 = d1.getTime();
setTimeout(function() {
    $(".touchable").on("touchend", function(event) {
        var d2 = new Date();
        var n2 = d2.getTime();
        if (n2 - n1 <= 300) {
            $(event.target).trigger("click"); //dont do the action here just call real click handler
        }
    });
}, 50)}).on("click", "#myelement", function() {
//all the behavior i originally wanted
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.