PODSUMOWANIE:
Zapewniam tutaj możliwość korzystania z przeglądarki internetowej i mobilnej bez jQuery do konsekwentnego reagowania na interakcje zakresu / suwaka, co jest niemożliwe w obecnych przeglądarkach. Zasadniczo zmusza wszystkie przeglądarki do emulacji on("change"...
zdarzenia IE11 dla ich zdarzeń on("change"...
lub on("input"...
zdarzeń. Nowa funkcja to ...
function onRangeChange(r,f) {
var n,c,m;
r.addEventListener("input",function(e){n=1;c=e.target.value;if(c!=m)f(e);m=c;});
r.addEventListener("change",function(e){if(!n)f(e);});
}
... gdzie r
jest twój element wejściowy zakresu i f
twój słuchacz. Słuchacz zostanie wywołany po każdej interakcji, która zmienia wartość zakresu / suwaka, ale nie po interakcjach, które nie zmieniają tej wartości, w tym początkowych interakcji myszy lub dotyku w bieżącej pozycji suwaka lub po zejściu z dowolnego końca suwaka.
Problem:
Na początku czerwca 2016 r. Różne przeglądarki różnią się pod względem reakcji na użycie zakresu / suwaka. Pięć scenariuszy jest istotnych:
- początkowe przesuwanie myszą w dół (lub touch-start) w bieżącej pozycji suwaka
- początkowe przesuwanie myszą w dół (lub touch-start) w nowej pozycji suwaka
- każdy kolejny ruch myszy (lub dotyku) po 1 lub 2 wzdłuż suwaka
- każdy kolejny ruch myszy (lub dotyku) po 1 lub 2 za dowolnym końcem suwaka
- końcowe najechanie myszą (lub touch-end)
Poniższa tabela pokazuje, w jaki sposób różnią się zachowanie co najmniej trzech różnych przeglądarek na komputery, w odniesieniu do których z powyższych scenariuszy odpowiadają:
Rozwiązanie:
Ta onRangeChange
funkcja zapewnia spójną i przewidywalną reakcję różnych przeglądarek na interakcje zakresu / suwaka. Wymusza zachowanie wszystkich przeglądarek zgodnie z poniższą tabelą:
W IE11 kod zasadniczo pozwala wszystkim działać zgodnie ze status quo, tzn. Pozwala "change"
zdarzeniu funkcjonować w standardowy sposób, a "input"
zdarzenie jest nieistotne, ponieważ i tak nigdy się nie uruchamia. W innych przeglądarkach "change"
zdarzenie jest skutecznie wyciszane (aby zapobiec uruchamianiu dodatkowych, a czasem niezbyt widocznych zdarzeń). Ponadto "input"
zdarzenie uruchamia detektor tylko wtedy, gdy zmienia się wartość zakresu / suwaka. W przypadku niektórych przeglądarek (np. Firefox) dzieje się tak, ponieważ słuchacz jest skutecznie wyciszony w scenariuszach 1, 4 i 5 z powyższej listy.
(Jeśli naprawdę potrzebujesz aktywacji słuchacza w jednym ze scenariuszy 1, 4 i / lub 5, możesz spróbować włączyć "mousedown"
/ "touchstart"
, "mousemove"
/ "touchmove"
i / lub "mouseup"
/ "touchend"
zdarzenia. Takie rozwiązanie jest poza zakresem tej odpowiedzi).
Funkcjonalność w przeglądarkach mobilnych:
Testowałem ten kod w przeglądarkach komputerowych, ale nie w żadnych przeglądarkach mobilnych. Jednak w innej odpowiedzi na tej stronie MBourne pokazał, że moje rozwiązanie tutaj „... wydaje się działać w każdej przeglądarce, jaką mogłem znaleźć (Win Desktop: IE, Chrome, Opera, FF; Android Chrome, Opera i FF, iOS Safari) „ . (Dzięki MBourne.)
Stosowanie:
Aby skorzystać z tego rozwiązania, włącz onRangeChange
funkcję z powyższego podsumowania (uproszczonego / zminimalizowanego) lub fragment kodu demonstracyjnego poniżej (funkcjonalnie identyczny, ale bardziej zrozumiały) we własnym kodzie. Wywołaj go w następujący sposób:
onRangeChange(myRangeInputElmt, myListener);
gdzie myRangeInputElmt
jest pożądany <input type="range">
element DOM i myListener
jest funkcją nasłuchiwania / obsługi, która ma być wywoływana po "change"
zdarzeniach podobnych do tego.
W razie potrzeby Twój detektor może być pozbawiony parametrów lub może użyć event
parametru, tzn. Zadziała dowolna z poniższych opcji, w zależności od potrzeb:
var myListener = function() {...
lub
var myListener = function(evt) {...
(Usunięcie detektora zdarzeń z input
elementu (np. Użycie removeEventListener
) nie jest uwzględnione w tej odpowiedzi.)
Opis wersji demo:
W poniższym fragmencie kodu funkcja onRangeChange
zapewnia uniwersalne rozwiązanie. Reszta kodu jest po prostu przykładem demonstrującym jego użycie. Każda zmienna, która zaczyna się od, nie my...
ma znaczenia dla uniwersalnego rozwiązania i jest obecna tylko na potrzeby wersji demonstracyjnej.
Pokazy demo wartość zakres / suwak, a także ile razy średnia "change"
, "input"
i niestandardowych "onRangeChange"
zdarzeń mają opalane (wiersze A, B i C, odpowiednio). Podczas korzystania z tego fragmentu w różnych przeglądarkach podczas interakcji z suwakiem zakresu / suwaka zwróć uwagę na następujące kwestie:
- W IE11 wartości w wierszach A i C zmieniają się w scenariuszach 2 i 3 powyżej, podczas gdy wiersz B nigdy się nie zmienia.
- W Chrome i Safari zarówno wartości w wierszach B, jak i C zmieniają się w scenariuszach 2 i 3, podczas gdy wiersz A zmienia się tylko w scenariuszu 5.
- W przeglądarce Firefox wartość w wierszu A zmienia się tylko dla scenariusza 5, wiersz B zmienia się dla wszystkich pięciu scenariuszy, a wiersz C zmienia się tylko dla scenariuszy 2 i 3.
- We wszystkich powyższych przeglądarkach zmiany w wierszu C (proponowane rozwiązanie) są identyczne, tj. Tylko w scenariuszach 2 i 3.
Kod demonstracyjny:
// main function for emulating IE11's "change" event:
function onRangeChange(rangeInputElmt, listener) {
var inputEvtHasNeverFired = true;
var rangeValue = {current: undefined, mostRecent: undefined};
rangeInputElmt.addEventListener("input", function(evt) {
inputEvtHasNeverFired = false;
rangeValue.current = evt.target.value;
if (rangeValue.current !== rangeValue.mostRecent) {
listener(evt);
}
rangeValue.mostRecent = rangeValue.current;
});
rangeInputElmt.addEventListener("change", function(evt) {
if (inputEvtHasNeverFired) {
listener(evt);
}
});
}
// example usage:
var myRangeInputElmt = document.querySelector("input" );
var myRangeValPar = document.querySelector("#rangeValPar" );
var myNumChgEvtsCell = document.querySelector("#numChgEvtsCell");
var myNumInpEvtsCell = document.querySelector("#numInpEvtsCell");
var myNumCusEvtsCell = document.querySelector("#numCusEvtsCell");
var myNumEvts = {input: 0, change: 0, custom: 0};
var myUpdate = function() {
myNumChgEvtsCell.innerHTML = myNumEvts["change"];
myNumInpEvtsCell.innerHTML = myNumEvts["input" ];
myNumCusEvtsCell.innerHTML = myNumEvts["custom"];
};
["input", "change"].forEach(function(myEvtType) {
myRangeInputElmt.addEventListener(myEvtType, function() {
myNumEvts[myEvtType] += 1;
myUpdate();
});
});
var myListener = function(myEvt) {
myNumEvts["custom"] += 1;
myRangeValPar.innerHTML = "range value: " + myEvt.target.value;
myUpdate();
};
onRangeChange(myRangeInputElmt, myListener);
table {
border-collapse: collapse;
}
th, td {
text-align: left;
border: solid black 1px;
padding: 5px 15px;
}
<input type="range"/>
<p id="rangeValPar">range value: 50</p>
<table>
<tr><th>row</th><th>event type </th><th>number of events </th><tr>
<tr><td>A</td><td>standard "change" events </td><td id="numChgEvtsCell">0</td></tr>
<tr><td>B</td><td>standard "input" events </td><td id="numInpEvtsCell">0</td></tr>
<tr><td>C</td><td>new custom "onRangeChange" events</td><td id="numCusEvtsCell">0</td></tr>
</table>
Kredyt:
Chociaż implementacja tutaj jest w dużej mierze moja, zainspirowała ją odpowiedź MBourne . Ta inna odpowiedź sugerowała, że zdarzenia „wejściowe” i „zmieniające” mogą zostać połączone, a wynikowy kod będzie działał zarówno w przeglądarkach stacjonarnych, jak i mobilnych. Jednak kod w tej odpowiedzi powoduje, że uruchamiane są ukryte „dodatkowe” zdarzenia, co samo w sobie jest problematyczne, a wyzwalane zdarzenia różnią się między przeglądarkami, co stanowi kolejny problem. Moja implementacja rozwiązuje te problemy.
Słowa kluczowe:
JavaScript wejściowy typ zakresu suwak zdarzenia zmieniają wejście kompatybilność z przeglądarką przeglądarka stacjonarna mobilny no-jQuery
onchange
nie strzela. Znalazłem to pytanie podczas rozwiązywania tego problemu.