2013-01-18 45 views
11

Tak, natknąłem się na interesujący problem podczas pracy nad aplikacją internetową dla Microsoft Surface.Słuchanie mousedown I touchstart na urządzeniach, które używają dotyku i myszy (np. Surface)

Chcę dodać detektory zdarzeń, gdy użytkownik wejdzie w interakcję z elementem DOM. Teraz mogę zrobić:

if ('ontouchstart' in document.documentElement) { 
    //Attach code for touch event listeners 
    document.addEventListener("touchstart" myFunc, false); 
} else { 
    //Attach code for mouse event listeners 
    document.addEventListener("mousedown" myFunc, false); 
} 

Jeśli urządzenie nie ma wejścia myszy, problem ten byłby prosty i powyższy kod działałby dobrze. Ale Surface (i wiele nowych komputerów z Windows 8) ma ZARÓWNO dotykiem i myszą. Powyższy kod zadziała tylko wtedy, gdy użytkownik dotknie urządzenia. Słuchacze zdarzeń myszy nigdy nie zostaną dołączeni.

Więc pomyślałem, dobrze, mogę to zrobić:

if ('ontouchstart' in document.documentElement) { 
    //Attach code for touch event listeners 
    document.addEventListener("touchstart" myFunc, false); 
} 
//Always attach code for mouse event listeners 
document.addEventListener("mousedown" myFunc, false); 

urządzeń, które nie obsługują dotyk nie miałyby wydarzenia związane, ale urządzenie, które wykorzystuje dotyk zarejestruje swoje ładowarki. Problem z tym jest jednak, że myFunc() zostanie wywołana dwukrotnie na dotykowym urządzenia:

  1. myFunc() będzie ogień, gdy „touchstart” jest podniesiony
  2. Ponieważ przeglądarki dotykowe zazwyczaj przejść przez cykl touchstart ->touchmove ->touchend ->mouseDown ->mousemove ->mouseUp ->kliknięcie, myFunc() zostanie ponownie wezwany "mousedown"

mam uznać dodanie kodu do myFunc() taki sposób, że wywołuje ona e.preventDefault() ale to wydaje się również zablokować touchend jak również mouseDown/mousemove/mouseUp w niektórych przeglądarkach (link).

Nienawidzę robić snifferów useragent, ale wygląda na to, że przeglądarki dotykowe różnią się sposobem implementacji zdarzeń dotykowych.

Pewnie czegoś mi brakuje, bo wydaje się, że z pewnością te implementacje JavaScript zostały zdecydowane z możliwością przeglądarki obsługującej zarówno mysz jak i dotyk!

+0

Co to ma wspólnego z Androidem, biorąc pod uwagę, że Surface nie uruchamia Androida? – CommonsWare

+0

@CommonsWare - Moje pytanie dotyczy wszystkich urządzeń dotykowych obsługujących mysz, dlatego wydaje się mieć zastosowanie w systemach Windows 8 i Android. – userx

+0

Tak, a co z ChromeOS? –

Odpowiedz

-3

edycja: Jeśli używasz jQuery, będzie można zrobić tak:

var clickEventType=((document.ontouchstart!==null)?'mousedown':'touchstart'); 

$("a").bind(clickEventType, function() { 
    //Do something 
}); 

To zadziała tylko jeden zdarzenia wiążą za.

znaleźć tutaj: How to bind 'touchstart' and 'click' events but not respond to both?

+1

To nie rozwiązuje problemu. Po prostu dołącza procedury obsługi do obu zdarzeń i nie uważam, że zapobiega to możliwości uruchamiania OBU zdarzenia (a co za tym idzie dołączonej funkcji uruchamianej dwa razy). – userx

+0

Masz rację –

0

Wewnątrz myFunc sprawdzić typ zdarzenia. Jeśli jest to touchstart, to wykonaj e.stopPropagation().

+0

To niestety też nie działa, ponieważ może to być wydarzenie "mousedown" na laptopie z Windows 8, który ma zarówno mysz, jak i ekran dotykowy. – userx

+0

Edytowałem moją odpowiedź. – noypiscripter

2

W systemie Windows 8 można użyć zdarzenia "MSPointerDown".

if (window.navigator.msPointerEnabled) { 
    document.addEventListener("MSPointerDown" myFunc, false); 
} 

dodać również następujące do stylu:

html { 
    -ms-touch-action: none; /* Direct all pointer events to JavaScript code. */ 
    } 

Zobacz http://msdn.microsoft.com/en-us/library/ie/hh673557(v=vs.85).aspx aby uzyskać więcej informacji.

+0

może wyłączyć przewijanie –

Powiązane problemy