Jak w jQuery odróżnić kliknięcie programistyczne od kliknięcia przez użytkownika?

91

Załóżmy, że zdefiniowałem moduł obsługi kliknięć:

$("#foo").click(function(e){

});

W jaki sposób w ramach procedury obsługi funkcji mogę stwierdzić, czy zdarzenie zostało uruchomione programowo, czy przez użytkownika?

Kevin Owocki
źródło
W jaki sposób program zajmuje się programowym uruchamianiem zdarzenia?
Clayton,
5
Dlaczego musisz rozróżniać przypadki?
Damien_The_Unbeliever
@Clayton: $x.click()lub $x.trigger('click').
mu jest za krótkie
Miałem sytuację z suwakiem obrazu, który automatycznie przewijał obrazy, a zrobiłem to, wywołując kliknięcia odpowiedniego elementu nawigacyjnego skojarzonego z obrazem. Problem polega na tym, że gdy użytkownik kliknie na nawigację, automatyczne obracanie powinno się zatrzymać.
Kasapo
2
Działa to w najnowszych przeglądarkach Firefox, Chrome i IE9. Dlaczego nie przyjąć odpowiedzi poniżej z największą liczbą głosów? @kevino
OZZIE

Odpowiedzi:

119

Możesz rzucić okiem na obiekt zdarzenia e. Jeśli zdarzenie zostało wywołane przez prawdziwego kliknięcia, trzeba takie rzeczy jak clientX, clientY, pageX, pageY, itd. Wewnątrz ei oni będą numery; liczby te są związane z pozycją myszy w momencie uruchomienia kliknięcia, ale prawdopodobnie będą obecne, nawet jeśli kliknięcie zostało zainicjowane z klawiatury. Jeśli zdarzenie zostało wywołane przez $x.click(), nie będziesz mieć zwykłych wartości pozycji w e. Możesz też spojrzeć na originalEventnieruchomość , której nie powinno tam być, gdyby wydarzenie pochodziło $x.click().

Może coś takiego:

$("#foo").click(function(e){
    if(e.hasOwnProperty('originalEvent'))
        // Probably a real click.
    else
        // Probably a fake click.
});

A oto mała piaskownica do zabawy: http://jsfiddle.net/UtzND/

mu jest za krótkie
źródło
4
To niesamowite ... Pomyślałem sobie "może zdarzenia wyzwalane przez jQuery nie mają informacji o pozycji myszy"! w00t!
Kasapo
2
Można to pokonać w przeglądarkach obsługujących createEvent. jsfiddle.net/UtzND/26
Joe Enzminger
2
@JoeEnzminger tak, ale dlaczego miałbyś pokonać własny scenariusz, że tak powiem ...?
OZZIE
3
Niepokoi mnie skrypt innej firmy generujący zdarzenie kliknięcia i mój skrypt obsługujący je przy założeniu, że został wygenerowany przez użytkownika (rzeczywiste kliknięcie).
Joe Enzminger,
2
@JoeEnzminger: Wszystkie zakłady są wyłączone, gdy kod znajduje się w przeglądarce, nie możesz zrobić nic, co nie może zostać pokonane przez wystarczająco sprytną osobę. Myślę, że najlepsze, co możesz zrobić, to sprawdzić kilka rzeczy: czy istnieje originalEvent? Czy to właściwa rzecz? Czy są gdzieś współrzędne? Czy współrzędne są zgodne? Czy współrzędne są w środku #foo? ...
mu jest za krótkie
44

Możesz użyć dodatkowego parametru zgodnie z instrukcją wyzwalacza jQuery :

$("#foo").click(function(e, from){
    if (from == null)
        from = 'User';
    // rest of your code
});

$('#foo').trigger('click', ['Trigger']);
Shikiryu
źródło
3
Jedyny problem, jaki widzę w tym przypadku, polega na tym, że nie możesz odróżnić zwykłego kliknięcia $x.click(), a .click()dzwoniący musi wyraźnie powiedzieć, że udaje. Może to stanowić problem, ale nie musi, w zależności od tego, co robi Kevin Owocki.
mu jest za krótkie
1
@mu: Nie do końca rozumiem różnicę między „normalnym” kliknięciem (użytkownik?) a tym, $x.click()który jest eventHandler (dla kliknięcia użytkownika, które może być „normalne”)
Shikiryu,
1
Różnica polega na tym, że jeden pochodzi od użytkownika, a drugi z oprogramowania. Fałszywe kliknięcie może pochodzić z wtyczki lub innego kodu, którego nie można zmodyfikować w celu dodania dodatkowych argumentów. Nie krytykuję twojego rozwiązania, po prostu zwracam uwagę na kilka możliwych dziur.
mu jest za krótkie
Chociaż mu jest poprawne i nie zadziała w każdej sytuacji, to było dokładnie to, czego szukałem, dziękuję! Nie wiedziałem, że mogę przekazać dodatkowy parametr, taki jak var, ale właśnie tego potrzebowałem, aby przetestować „rzeczywiste” kliknięcia w skomplikowanym interfejsie użytkownika, który traktuje niektóre „prawdziwe” kliknięcia jako automatyczne. Dzięki za oba niezwykle przydatne rozwiązania!
Phil
9

Istnieje już odpowiedź na inne pytanie.

Jak wykryć, czy kliknięcie () jest kliknięciem myszy lub wywołane przez jakiś kod?

Użyj whichwłaściwości obiektu zdarzenia. Powinien dotyczyć undefinedzdarzeń wyzwalanych przez kod

$("#someElem").click(function(e) {
    if (e.which) {
        // Actually clicked
    } else {
        // Triggered by code
    }
});

Przykład JsFiddle - http://jsfiddle.net/interdream/frw8j/

Mam nadzieję, że to pomoże!

Swanidhi
źródło
2
Nie zawsze działa. Np. selectDałoby nagrodę e.which==undefinedza prawdziwe wydarzenie.
JNF
5

Wypróbowałem wszystkie powyższe rozwiązania, w moim przypadku nic nie działa. Poniższe rozwiązanie zadziałało dla mnie. Mam nadzieję, że ci również pomoże.

$(document).ready(function(){
  //calling click event programmatically
    $("#chk1").trigger("click");
});

$(document).on('click','input[type=checkbox]',function(e) {
		if(e.originalEvent.isTrusted==true){
			alert("human click");
		}
		else{
			alert("programmatically click");
		}
    
    });
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js">
</script>

<input type="checkbox" id="chk1" name="chk1" >Chk1</input>
<input type="checkbox" id="chk2" name="chk2" >Chk2</input>
<input type="checkbox" id="chk3" name="chk3" >Chk3</input>

GSB
źródło
4

DOM Level 3 określa event.isTrusted. Jest to obecnie obsługiwane tylko w IE9 + i Firefoksie (na podstawie moich testów. Przeczytałem również (choć nie dogłębnie zbadane), że można to zmienić w niektórych przeglądarkach i prawdopodobnie nie jest jeszcze w 100% gotowy, aby faktycznie zaufać (niestety).

To jest zmodyfikowana wersja skrzypiec @ mu, która działa w przeglądarkach IE i Firefox.

Joe Enzminger
źródło
Słuszna uwaga. Nie sądzę jednak, żeby cokolwiek było w 100% solidne. Będziesz musiał mieszać w niektórych testach, aby sprawdzić, czy isTrustedjest obsługiwany i nie można go zapisać. Myślę, że prawdziwa odpowiedź zależy od przyczyny tego pytania i nigdy nie dowiedzieliśmy się, dlaczego.
mu jest za krótkie
@mu, doszedłem do tego pytania po zadaniu podobnego, ale bardziej ogólnego. Mój przypadek „dlaczego” polega na tym, że chcę się upewnić, że wykonuję czynność (transakcję finansową, choć niewielką) tylko wtedy, gdy użytkownik podjął bezpośrednie działanie potwierdzające na stronie.
Joe Enzminger
1

Rozwiązanie Vanila js:

document.querySelector('button').addEventListener('click', function (e){
    if(e.isTrusted){
        // real click.
    }else{
        // programmatic click
    }
});
Abhishek
źródło
-1

Nie zamierzam brać udziału w intelektualnej dyskusji, kod, który pracował dla mnie, filtrując .click()i .trigger('click')...

$(document).on('click touchstart', '#my_target', function(e) {
    if (e.pageX && e.pageY) { // To check if it is not triggered by .click() or .trigger('click')
        //Then code goes here
    }
});
Sahu V Kumar
źródło