Pracuję na mobilnej stronie internetowej, która musi działać na różnych urządzeniach. Ten, który sprawia mi teraz ból głowy, to BlackBerry.
Musimy obsługiwać zarówno kliknięcia klawiatury, jak i zdarzenia dotykowe.
Idealnie byłoby po prostu użyć:
$thing.click(function(){...})
ale mamy problem z tym, że niektóre z tych urządzeń BlackBerry mają bardzo irytujące opóźnienie od momentu dotknięcia do uruchomienia kliknięcia.
Środkiem zaradczym jest zamiast tego użycie touchstart:
$thing.bind('touchstart', function(event){...})
Ale jak mam powiązać oba zdarzenia, ale tylko jedno? Nadal potrzebuję zdarzenia kliknięcia na urządzeniach z klawiaturą, ale oczywiście nie chcę uruchamiać zdarzenia kliknięcia, jeśli korzystam z urządzenia dotykowego.
Dodatkowe pytanie: czy można to zrobić i dodatkowo pomieścić przeglądarki, które nawet nie mają zdarzenia TouchStart? Badając to, wygląda na to, że BlackBerry OS5 nie obsługuje TouchStart, więc będzie musiał polegać na zdarzeniach kliknięcia w tej przeglądarce.
UZUPEŁNIENIE:
Być może bardziej kompleksowym pytaniem jest:
Czy w jQuery jest możliwe / zalecane, aby obsługiwać zarówno interakcje dotykowe, jak i interakcje myszy za pomocą tych samych powiązań?
Idealnie odpowiedź brzmi: tak. Jeśli nie, mam kilka opcji:
1) Korzystamy z WURFL, aby uzyskać informacje o urządzeniu, aby stworzyć własną matrycę urządzeń. W zależności od urządzenia użyjemy funkcji touchstart LUB kliknięcia.
2) Wykryj obsługę dotykową w przeglądarce przez JS (muszę zrobić więcej badań na ten temat, ale wydaje się, że jest to wykonalne).
Pozostaje jednak jeden problem: co z urządzeniami, które obsługują ZARÓWNO. Niektóre telefony, które obsługujemy (a mianowicie Nokias i BlackBerries) mają zarówno ekrany dotykowe, jak i klawiatury. W ten sposób zataczam pełne koło z powrotem do pierwotnego pytania ... czy jest sposób, aby pozwolić na oba na raz?
źródło
.bind('touchstart mouseup')
rozwiąże to (na podstawie jednego z poniższych komentarzy)Odpowiedzi:
Aktualizacja : Sprawdź projekt jQuery Pointer Events Polyfill , który umożliwia powiązanie ze zdarzeniami „wskaźnikowymi” zamiast wybierania między myszą a dotykiem.
Powiązaj oba, ale stwórz flagę, aby funkcja uruchamiała się tylko raz na około 100 ms.
źródło
click
zmień go namousedown
... może duże opóźnienie jest różnicą między tym,mousedown
amouseup
tymclick
określa się a.touchend
przez zastosowanie klasytouched
. Uruchamia się przed wywołaniem zdarzenia kliknięcia. Następnie dodaję zdarzenie kliknięcia, które najpierw sprawdza istnienie tej klasy. Jeśli tak, zakładamy, że uruchomiono zdarzenia dotykowe i nie klikamy nic poza kliknięciem nazwy klasy, aby „zresetować” ją do następnej interakcji. Jeśli klasy nie ma, zakładamy, że użyli klawiatury, aby kliknąć element i uruchomić funkcję od tego miejsca.To jest poprawka, którą „tworzę”, która usuwa GhostClick i implementuje FastClick. Spróbuj sam i daj nam znać, czy zadziałało.
źródło
event.handled
będzie równa zaundefined
każdym razem, gdy zdarzenie zostanie wyzwolone. Oto rozwiązanie: ustaw flagę „obsługiwane” w samym elemencie docelowym za pomocąjQuery.data()
.event.stopPropagation();
i wedługevent.preventDefault();
mojego zrozumienia (i testowania) wydarzenie można odpalić tylko raz. więc po co to sprawdzaćif(event.handled !== true)
? Dla mnie nie jest to konieczne, czy coś mi umknęło?event.handled
należy sprawdzać wartościtrue
? O ile mogę powiedzieć, to nigdyfalse
. Zaczyna się jakoundefined
, a następnie chcesz powiedzieć, czy zostało ustawionetrue
.Możesz spróbować czegoś takiego:
źródło
Zwykle działa to również:
źródło
Samo dodanie
return false;
na końcuon("click touchstart")
funkcji zdarzenia może rozwiązać ten problem.Z dokumentacji jQuery na .on ()
źródło
Musiałem zrobić coś podobnego. Oto uproszczona wersja tego, co dla mnie zadziałało. Jeśli zostanie wykryte zdarzenie dotykowe, usuń powiązanie kliknięcia.
W moim przypadku zdarzenie click było powiązane z
<a>
elementem, więc musiałem usunąć powiązanie click i ponownie powiązać zdarzenie click, które uniemożliwiło domyślną akcję dla tego<a>
elementu.źródło
Udało mi się w następujący sposób.
Bułka z masłem...
źródło
e
parametru wfunction()
Uważam, że najlepszą praktyką jest teraz stosowanie:
PRZYKŁAD
EDYCJA (2017)
Od 2017 r. Przeglądarki zaczynające się od Chrome i podejmujące kroki w kierunku zdarzenia kliknięcia
.on("click")
bardziej zgodnym zarówno dla myszy, jak i dotyku, eliminując opóźnienie generowane przez zdarzenia stuknięcia w żądaniach kliknięcia.Prowadzi to do wniosku, że powrót do korzystania ze zdarzenia „click” byłoby najprostszym rozwiązaniem w przyszłości.
Nie przeprowadziłem jeszcze żadnych testów w różnych przeglądarkach, aby sprawdzić, czy jest to praktyczne.
źródło
mouseup
się, że mam nieprzewidywalne wyniki, szczególnie gdy używam gładzika zamiast tradycyjnej myszy.Zasadniczo nie chcesz mieszać domyślnego interfejsu dotykowego i bezdotykowego (kliknięcia). Po przejściu do świata dotyku łatwiej jest poradzić sobie tylko z funkcjami dotykowymi. Poniżej znajduje się pseudo kod, który zrobiłby to, co chcesz.
Jeśli połączysz się w zdarzeniu touchmove i śledzisz lokalizacje, możesz dodać więcej elementów w funkcji doTouchLogic, aby wykryć gesty i tak dalej.
źródło
sprawdź szybkie przyciski i kliknięcia Chost z Google https://developers.google.com/mobile/articles/fast_buttons
źródło
Cóż ... Wszystko to jest bardzo skomplikowane.
Jeśli masz modernizatora, nie musisz się zastanawiać.
źródło
Kolejne wdrożenie dla lepszej konserwacji. Jednak ta technika wykona również event.stopPropagation (). Kliknięcie nie jest rejestrowane w żadnym innym elemencie, który klikał przez 100 ms.
źródło
Tylko w celach dokumentacyjnych, oto co zrobiłem dla najszybszego / najbardziej responsywnego kliknięcia na komputerze / dotknij rozwiązania mobilnego, o którym mogłem pomyśleć:
Zastąpiłem
on
funkcję jQuery zmodyfikowaną, która za każdym razem, gdy przeglądarka obsługuje zdarzenia dotykowe, zamieniła wszystkie moje zdarzenia kliknięcia na start dotykowy.Użycie, które byłoby dokładnie takie samo jak poprzednio, takie jak:
Ale użyłby touchstart, gdy jest dostępny, kliknij, gdy nie. Żadne opóźnienia nie są potrzebne: D
źródło
Właśnie wpadłem na pomysł, aby zapamiętać, czy
ontouchstart
kiedykolwiek został uruchomiony. W tym przypadku jesteśmy na urządzeniu, które je obsługuje i chcemy zignorowaćonclick
zdarzenie. Ponieważontouchstart
zawsze powinno być uruchamiane wcześniejonclick
, używam tego:źródło
Możesz spróbować w ten sposób:
źródło
W moim przypadku działało to idealnie:
Główny problem polegał na tym, że zamiast klikania myszką próbowałem za pomocą kliknięcia, na urządzeniach dotykowych wywoływałem kliknięcie i dotknięcie w tym samym czasie, jeśli korzystam z wyłączenia, niektóre funkcje w ogóle nie działały na urządzeniach mobilnych. Problem z kliknięciem polega na tym, że jest to globalne wydarzenie, które uruchamia resztę wydarzenia, w tym retusz.
źródło
To działało dla mnie, mobile słucha obu, więc zapobiegaj temu, który jest zdarzeniem dotykowym. słuchaj tylko na pulpicie myszy.
źródło
Będąc dla mnie najlepszą odpowiedzią udzieloną przez Mottie, po prostu staram się, aby jego kod był bardziej przydatny, więc oto mój wkład:
źródło
Pracuję również nad aplikacją internetową na Androida / iPada i wydaje się, że samo użycie „touchmove” wystarczy, aby „przenieść komponenty” (nie trzeba dotykać). Wyłączając touchstart, możesz użyć .click (); z jQuery. W rzeczywistości działa, ponieważ nie został przeciążony przez touchstart.
Na koniec możesz binb .live („touchstart”, funkcja (e) {e.stopPropagation ();}); aby poprosić zdarzenie touchstart, aby przestało się propagować, w salonie kliknij (), aby się uruchomić.
To zadziałało dla mnie.
źródło
touchstart
?Próbując rozwiązać ten problem, należy wziąć pod uwagę wiele kwestii. Większość rozwiązań albo przerywa przewijanie, albo nie obsługuje poprawnie zdarzeń kliknięcia ducha.
Pełne rozwiązanie można znaleźć na stronie https://developers.google.com/mobile/articles/fast_buttons
Uwaga: Nie można obsługiwać zdarzeń kliknięć duchów dla poszczególnych elementów. Opóźnione kliknięcie jest uruchamiane według lokalizacji na ekranie, więc jeśli zdarzenia dotykowe zmodyfikują stronę w jakiś sposób, zdarzenie kliknięcia zostanie wysłane do nowej wersji strony.
źródło
Skuteczne może być przypisanie do zdarzeń
'touchstart mousedown'
lub'touchend mouseup'
uniknięcie niepożądanych skutków ubocznych używaniaclick
.źródło
Korzystając z faktu, że kliknięcie zawsze następuje po zdarzeniu dotykowym, oto co zrobiłem, aby pozbyć się „kliknięcia ducha” bez konieczności używania limitów czasu lub flag globalnych.
Zasadniczo za każdym razem, gdy
ontouchstart
zdarzenie uruchamia się na elemencie, oflaguj zestaw, a następnie usuń (i zignoruj), gdy nadejdzie kliknięcie.źródło
Dlaczego nie skorzystać z interfejsu API jQuery Event?
http://learn.jquery.com/events/event-extensions/
Z powodzeniem wykorzystałem to proste wydarzenie. Jest czysty, możliwy do nazewnictwa i wystarczająco elastyczny, aby go ulepszyć.
źródło
Jeśli używasz jQuery, działało to dla mnie całkiem dobrze:
Inne rozwiązania są również dobre, ale wiązałem wiele zdarzeń w pętli i potrzebowałem funkcji wywoływania, aby utworzyć odpowiednie zamknięcie. Ponadto nie chciałem wyłączać wiązania, ponieważ chciałem, aby można je było wywoływać przy następnym kliknięciu / uruchomieniu.
Może pomóc komuś w podobnej sytuacji!
źródło
W przypadku prostych funkcji wystarczy rozpoznać dotyk lub kliknąć Używam następującego kodu:
To zwróci „dotyk”, jeśli zdefiniowano zdarzenie touchstart, i „brak dotyku”, jeśli nie. Tak jak powiedziałem, jest to proste podejście do zdarzeń typu „kliknij / dotknij”.
źródło
Próbuję tego i jak dotąd działa (ale jestem tylko na Androidzie / Phonegap, więc zastrzeżenie emptor)
Nie podoba mi się fakt, że ponownie wiążę procedury obsługi za każdym dotknięciem, ale wszystkie rzeczy uważane za dotknięcia nie zdarzają się zbyt często (w czasie komputera!)
Mam TON programów obsługi, takich jak ten dla „#keypad”, więc posiadanie prostej funkcji, która pozwala mi poradzić sobie z problemem bez zbyt dużej ilości kodu, jest powodem, dla którego poszedłem w ten sposób.
źródło
Spróbuj użyć
Virtual Mouse (vmouse) Bindings
zjQuery Mobile
. To wirtualne wydarzenie specjalnie dla Twojej sprawy:http://api.jquerymobile.com/vclick/
Lista obsługiwanych przeglądarek: http://jquerymobile.com/browser-support/1.4/
źródło
EDYTOWAĆ: Moja poprzednia odpowiedź (oparta na odpowiedziach w tym wątku) nie była dla mnie właściwą drogą. Chciałem, aby podmenu rozwijało się po kliknięciu myszą lub kliknięciu i zwinięciu po opuszczeniu myszy lub kliknięciu innym przyciskiem. Ponieważ zdarzenia myszy zwykle są uruchamiane po zdarzeniach dotykowych, pisanie detektorów zdarzeń obsługujących jednocześnie ekran dotykowy i mysz było trochę trudne.
Wtyczka jQuery: Touch Or Mouse
W końcu napisałem wtyczkę jQuery o nazwie „ Touch Or Mouse ” (897 bajtów zminimalizowane), która może wykryć, czy zdarzenie zostało wywołane przez ekran dotykowy lub mysz (bez testowania obsługi dotykowej!). To umożliwia obsługę zarówno ekran dotykowy i myszy w tym samym czasie i całkowicie oddziela ich zdarzenia.
W ten sposób OP może używać
touchstart
lubtouchend
do szybkiego reagowania na kliknięcia dotykowe orazclick
na kliknięcia wywoływane tylko myszą.Demonstracja
Najpierw trzeba zrobić tj. element ciała śledzi zdarzenia dotykowe:
Zdarzenia myszy są domyślnie powiązane z elementami, a dzwoniąc
$body.touchOrMouse('get', e)
możemy dowiedzieć się, czy zdarzenie zostało wywołane za pomocą ekranu dotykowego czy myszy.Zobacz wtyczkę w pracy pod adresem http://jsfiddle.net/lmeurs/uo4069nh .
Wyjaśnienie
touchstart
itouchend
zdarzenia, w ten sposóbtouchend
zdarzenie nie musi być uruchamiane na elemencie wyzwalającym (tj. łączu lub przycisku). Pomiędzy tymi dwoma zdarzeniami dotykowymi wtyczka uważa, że każde zdarzenie myszy jest wywoływane dotykiem.touchend
, gdy zdarzenie myszy jest uruchamiane w ciągughostEventDelay
(opcja, domyślnie 1000 ms) późniejtouchend
, ta wtyczka uznaje zdarzenie myszy za wywołane dotykiem.:active
stan.mouseleave
Zdarzenie jest zwolniony dopiero po element traci ten stan przez IE. klikając inny element. Ponieważ możemouseenter
to potrwać kilka sekund (lub minut!) Po uruchomieniu zdarzenia, wtyczka ta śledzi ostatniemouseenter
zdarzenie elementu : jeśli ostatniemouseenter
zdarzenie zostało wywołane dotykiem, następującemouseleave
zdarzenie jest również wywoływane przez dotyk.źródło
Oto prosty sposób, aby to zrobić:
Zasadniczo zapisujesz pierwszy typ zdarzenia, który jest wyzwalany we właściwości „trigger” w obiekcie danych jQuery, który jest dołączony do dokumentu głównego, i wykonujesz go tylko wtedy, gdy typ zdarzenia jest równy wartości w „trigger”. Na urządzeniach dotykowych łańcuchem zdarzeń będzie prawdopodobnie „start dotykowy”, a następnie „kliknięcie”; jednak procedura „kliknięcia” nie zostanie wykonana, ponieważ „kliknięcie” nie odpowiada początkowemu typowi zdarzenia zapisanego w „wyzwalaczu” („touchstart”).
Zakładam, i uważam, że jest to bezpieczne, że smartfon nie zmieni się spontanicznie z urządzenia dotykowego na urządzenie myszy, w przeciwnym razie stuknięcie nigdy się nie zarejestruje, ponieważ typ zdarzenia „wyzwalającego” jest zapisywany tylko raz na ładowanie strony i „kliknięcie” nigdy nie pasują do „startu dotykowego”.
Oto kodepen, z którym możesz się bawić (spróbuj nacisnąć przycisk na urządzeniu dotykowym - nie powinno być opóźnienia kliknięcia): http://codepen.io/thdoan/pen/xVVrOZ
Zaimplementowałem to również jako prostą wtyczkę jQuery, która obsługuje również filtrowanie potomków jQuery, przekazując ciąg selektora:
Codepen: http://codepen.io/thdoan/pen/GZrBdo/
źródło
$.data()
do przechowywania danych, do których można uzyskać dostęp za pomocą wielu funkcji, ale nie należą one do zakresu globalnego. Plusem jest to, że ponieważ przechowuję go w elemencie, naturalnie zapewnia mi to większy kontekst.Najlepszą metodą, jaką znalazłem, jest zapisanie zdarzenia dotyku i zaprogramowanie go jako zdarzenia normalnego kliknięcia. W ten sposób masz wszystkie normalne zdarzenia kliknięcia, a następnie musisz dodać tylko jedną procedurę obsługi zdarzeń dla wszystkich zdarzeń dotykowych. Dla każdego węzła, który chcesz, aby można go było dotykać, po prostu dodaj do niego klasę „dotykalną”, aby wywołać procedurę obsługi dotykowej. Z Jquery działa tak z pewną logiką, aby upewnić się, że jest to prawdziwe zdarzenie dotykowe, a nie fałszywie pozytywne.
źródło