ÖZET:
Burada, mevcut tarayıcılarda mümkün olmayan bir şey olan aralık / kaydırıcı etkileşimlerine sürekli olarak yanıt vermek için no-jQuery çapraz tarayıcı masaüstü ve mobil yeteneği sağlıyorum. Temel olarak tüm tarayıcıları IE11'in on("change"...
etkinliğinion("change"...
on("input"...
olaylarını veya olayları . Yeni fonksiyon ...
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);});
}
...nerede r
aralık giriş elemanınız ve f
dinleyiciniz. Dinleyici, aralık / kaydırıcı değerini değiştiren herhangi bir etkileşimden sonra ancak geçerli kaydırıcı konumundaki ilk fare veya dokunma etkileşimleri dahil veya kaydırıcının her iki ucundan çıktıktan sonra bu değeri değiştirmeyen etkileşimlerden sonra çağrılmaz.
Sorun:
Haziran 2016 başından itibaren, farklı tarayıcılar aralık / kaydırıcı kullanımına nasıl yanıt verdikleri açısından farklılık gösterir. Beş senaryo önemlidir:
- geçerli kaydırıcı konumunda ilk fare aşağı (veya dokunmatik başlat)
- yeni bir kaydırıcı konumunda fareyle üzerine gelme (veya dokunmaya başlama)
- kaydırıcı boyunca 1 veya 2'den sonraki herhangi bir fare (veya dokunma) hareketi
- kaydırıcının her iki ucundan 1 veya 2 sonra herhangi bir sonraki fare (veya dokunma) hareketi
- son mouse-up (veya dokunma ucu)
Aşağıdaki tabloda, en az üç farklı masaüstü tarayıcısının yukarıdaki senaryolardan hangilerine yanıt verdiklerine göre davranışlarında nasıl farklılıklar gösterdiği gösterilmiştir:
Çözüm:
onRangeChange
Fonksiyon aralığı / sürgü etkileşimleri için istikrarlı ve tahmin edilebilen bir çapraz tarayıcı tepkisi sağlar. Tüm tarayıcıları aşağıdaki tabloya göre davranmaya zorlar:
IE11'de, kod temelde her şeyin statükoya göre çalışmasına izin verir, yani "change"
olayın standart şekilde çalışmasına izin verir ve olay "input"
hiçbir zaman tetiklenmediğinden önemsizdir. Diğer tarayıcılarda, "change"
etkinlik etkili bir şekilde susturulur (fazladan ve bazen kolayca görünmeyen olayların tetiklenmesini önlemek için). Ayrıca, "input"
olay dinleyicisini yalnızca aralık / kaydırıcının değeri değiştiğinde tetikler. Bazı tarayıcılarda (örn. Firefox), bu durum dinleyicinin yukarıdaki listeden 1, 4 ve 5 senaryolarında etkili bir şekilde susturulması nedeniyle oluşur.
(Senaryo 1, 4 ve / veya 5'te gerçekten bir dinleyicinin etkinleştirilmesini istiyorsanız, "mousedown"
/ "touchstart"
, "mousemove"
/ "touchmove"
ve / veya "mouseup"
/ "touchend"
olaylarını birleştirmeyi deneyebilirsiniz . Böyle bir çözüm bu cevabın kapsamı dışındadır.)
Mobil Tarayıcılarda İşlevler:
Bu kodu masaüstü tarayıcılarda test ettim ancak mobil tarayıcılarda test etmedim. Ancak, bu sayfadaki başka bir cevapta MBourne buradaki çözümümün "... bulabildiğim her tarayıcıda çalıştığını gösteriyor (Masaüstü kazan: IE, Chrome, Opera, FF; Android Chrome, Opera ve FF, iOS Safari) " . (Teşekkürler MBourne.)
Kullanımı:
Bu çözümü kullanmak için, onRangeChange
yukarıdaki özetten (basitleştirilmiş / küçültülmüş) işlevi veya aşağıdaki demo kod snippet'ini (işlevsel olarak özdeş ancak daha açıklayıcı) kendi kodunuza ekleyin. Aşağıdaki gibi çağırın:
onRangeChange(myRangeInputElmt, myListener);
myRangeInputElmt
istediğiniz <input type="range">
DOM öğesi nerede ve benzeri etkinliklerde myListener
çağrılmasını istediğiniz dinleyici / işleyici işlevidir "change"
.
Dinleyiciniz istenirse parametresiz olabilir veya event
parametreyi kullanabilir , yani ihtiyaçlarınıza bağlı olarak aşağıdakilerden biri işe yarayabilir:
var myListener = function() {...
veya
var myListener = function(evt) {...
(Olay dinleyicisini input
öğeden kaldırmak (örn. Kullanmak removeEventListener
) bu cevapta ele alınmamıştır.)
Demo Açıklaması:
Aşağıdaki kod snippet'inde işlev onRangeChange
, evrensel bir çözüm sağlar. Kodun geri kalanı sadece kullanımını göstermek için bir örnektir. my...
İle başlayan herhangi bir değişken evrensel çözümle ilgisizdir ve sadece demo için mevcuttur.
Demo aralığı / kaydırıcı değeri olarak kez standart sayısı gösterir "change"
, "input"
ve özel "onRangeChange"
etkinlikleri tetiklenene (sıra, sırasıyla A, B ve C). Bu snippet'i farklı tarayıcılarda çalıştırırken, aralık / kaydırıcıyla etkileşime girerken aşağıdakilere dikkat edin:
- IE11'de, A ve C satırlarındaki değerlerin her ikisi de yukarıdaki senaryo 2 ve 3'te değişirken, B satırı asla değişmez.
- Chrome ve Safari'de, B ve C satırlarındaki değerlerin ikisi de senaryo 2 ve 3'te değişirken, satır A yalnızca senaryo 5 için değişir.
- Firefox'ta, A satırındaki değer yalnızca senaryo 5 için değişir, B satırı beş senaryo için değişir ve C satırı yalnızca senaryo 2 ve 3 için değişir.
- Yukarıdaki tüm tarayıcılarda, C satırındaki (önerilen çözüm) değişiklikler aynıdır, yani yalnızca senaryo 2 ve 3 için.
Demo Kodu:
// 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>
Kredi:
Buradaki uygulama büyük ölçüde kendim olsa da, MBourne'nin cevabından ilham aldı . Bu diğer yanıt, "giriş" ve "değişiklik" olaylarının birleştirilebileceğini ve ortaya çıkan kodun hem masaüstü hem de mobil tarayıcılarda çalışabileceğini gösterdi. Bununla birlikte, bu yanıttaki kod, kendi başına sorunlu olan gizli "ekstra" olayların tetiklenmesine neden olur ve tetiklenen olaylar tarayıcılar arasında farklıdır, bu da bir başka sorundur. Buradaki uygulamam bu sorunları çözüyor.
Anahtar Kelimeler:
JavaScript giriş türü aralığı kaydırıcı olayları giriş tarayıcı uyumluluğunu değiştir çapraz tarayıcı masaüstü mobil no-jQuery
onchange
ateş etmiyor. Bu sorunu giderirken bu soruyu buldum.