สรุป:
ฉันมอบความสามารถแบบเดสก์ท็อปและเบราว์เซอร์ข้ามมือถือที่ไม่ใช่ jQuery เพื่อตอบสนองต่อการโต้ตอบช่วง / ตัวเลื่อนอย่างต่อเนื่องซึ่งเป็นสิ่งที่เป็นไปไม่ได้ในเบราว์เซอร์ปัจจุบัน มันบังคับให้เบราว์เซอร์ทั้งหมดเลียนแบบon("change"...เหตุการณ์ของ IE11 ไม่ว่าจะเป็นของพวกเขาon("change"...หรือon("input"...เหตุการณ์ ฟังก์ชั่นใหม่คือ ...
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);});
}
... rองค์ประกอบการป้อนข้อมูลของคุณอยู่ที่ไหนและfเป็นผู้ฟังของคุณ ผู้ฟังจะถูกเรียกใช้หลังจากการโต้ตอบใด ๆ ที่เปลี่ยนค่าช่วง / ตัวเลื่อน แต่ไม่ใช่หลังจากการโต้ตอบที่ไม่เปลี่ยนค่านั้นรวมถึงเมาส์เริ่มต้นหรือการโต้ตอบแบบสัมผัสที่ตำแหน่งแถบเลื่อนปัจจุบัน
ปัญหา:
ตั้งแต่ต้นเดือนมิถุนายน 2559 เบราว์เซอร์ที่แตกต่างกันมีความแตกต่างกันในแง่ของการตอบสนองต่อการใช้งานช่วง / ตัวเลื่อน ห้าสถานการณ์ที่เกี่ยวข้อง:
- การเลื่อนเมาส์เริ่มต้น (หรือแตะเริ่ม) ที่ตำแหน่งตัวเลื่อนปัจจุบัน
- การเลื่อนเมาส์เริ่มต้น (หรือแตะเริ่ม) ที่ตำแหน่งตัวเลื่อนใหม่
- การเคลื่อนไหวของเมาส์ (หรือสัมผัส) ใด ๆ ที่ตามมาหลังจาก 1 หรือ 2 ไปตามแถบเลื่อน
- การเคลื่อนไหวของเมาส์ (หรือสัมผัส) ใด ๆ ที่ตามมาหลังจากผ่านไป 1 หรือ 2 ครั้งสุดท้ายทั้งสองด้านของแถบเลื่อน
- การเลื่อนเมาส์ครั้งสุดท้าย (หรือการสัมผัส)
ตารางต่อไปนี้แสดงให้เห็นว่าเบราว์เซอร์เดสก์ท็อปที่แตกต่างกันอย่างน้อยสามตัวแตกต่างกันอย่างไรในพฤติกรรมที่เกี่ยวข้องกับสถานการณ์ข้างต้น

สารละลาย:
onRangeChangeฟังก์ชั่นให้การตอบสนองที่เบราว์เซอร์ที่สอดคล้องกันและคาดการณ์ในช่วง / ปฏิสัมพันธ์เลื่อน มันบังคับให้เบราว์เซอร์ทั้งหมดทำงานตามตารางต่อไปนี้:

ใน IE11 รหัสนั้นอนุญาตให้ทุกอย่างทำงานตามสถานะเดิมคืออนุญาตให้"change"เหตุการณ์ทำงานในลักษณะมาตรฐานและ"input"เหตุการณ์ไม่เกี่ยวข้องเนื่องจากไม่เคยเกิดไฟเลย ในเบราว์เซอร์อื่น"change"กิจกรรมจะถูกปิดเสียงอย่างมีประสิทธิภาพ (เพื่อป้องกันเหตุการณ์พิเศษและบางครั้งไม่พร้อมที่จะยิง) นอกจากนี้"input"เหตุการณ์ยิงผู้ฟังเมื่อค่าของช่วง / แถบเลื่อนเปลี่ยนไป สำหรับบางเบราว์เซอร์ (เช่น Firefox) สิ่งนี้เกิดขึ้นเนื่องจากผู้ฟังถูกปิดเสียงอย่างมีประสิทธิภาพในสถานการณ์ 1, 4 และ 5 จากรายการด้านบน
(ถ้าคุณต้องการให้ผู้ฟังเปิดใช้งานจริงในสถานการณ์ 1, 4 และ / หรือ 5 คุณสามารถลองใช้การรวม"mousedown"/ "touchstart", "mousemove"/ "touchmove"และ / หรือ"mouseup"/ "touchend"เหตุการณ์การแก้ปัญหาดังกล่าวอยู่นอกเหนือขอบเขตของคำตอบนี้)
ฟังก์ชั่นในเบราว์เซอร์มือถือ:
ฉันทดสอบโค้ดนี้ในเบราว์เซอร์เดสก์ท็อป แต่ไม่ได้ใช้กับเบราว์เซอร์มือถือใด ๆ อย่างไรก็ตามในคำตอบอื่นในหน้านี้ MBourne แสดงให้เห็นว่าวิธีการแก้ปัญหาของฉันที่นี่"... ดูเหมือนจะทำงานในทุกเบราว์เซอร์ที่ฉันสามารถหาได้ (Win desktop: IE, Chrome, Opera, FF; Android Chrome, Opera และ FF, iOS Safari) " . (ขอบคุณ MBourne)
การใช้งาน:
ในการใช้โซลูชันนี้ให้รวมonRangeChangeฟังก์ชั่นจากข้อมูลสรุปด้านบน (แบบย่อ / ย่อขนาด) หรือตัวอย่างข้อมูลโค้ดด้านล่าง (เหมือนฟังก์ชั่นที่เหมือนกัน แต่มีการอธิบายตนเองมากกว่า) ในรหัสของคุณ เรียกใช้ดังนี้:
onRangeChange(myRangeInputElmt, myListener);
ที่myRangeInputElmtเป็น<input type="range">องค์ประกอบ DOM ที่คุณต้องการและmyListenerเป็นฟัง / ฟังก์ชั่นการจัดการที่คุณต้องการเรียกใช้เมื่อ"change"เหตุการณ์เหมือน
ผู้ฟังของคุณอาจมีพารามิเตอร์น้อยลงหากต้องการหรืออาจใช้eventพารามิเตอร์นั่นคือข้อใดข้อหนึ่งต่อไปนี้จะใช้งานได้ทั้งนี้ขึ้นอยู่กับความต้องการของคุณ:
var myListener = function() {...
หรือ
var myListener = function(evt) {...
(การลบผู้ฟังเหตุการณ์ออกจากinputองค์ประกอบ (เช่นใช้removeEventListener) ไม่ได้ระบุไว้ในคำตอบนี้)
คำอธิบายการสาธิต:
ในข้อมูลโค้ดด้านล่างฟังก์ชั่นonRangeChangeให้บริการโซลูชั่นสากล ส่วนที่เหลือของรหัสเป็นเพียงตัวอย่างเพื่อแสดงให้เห็นถึงการใช้งาน ตัวแปรใด ๆ ที่ขึ้นต้นด้วยmy...ไม่เกี่ยวข้องกับโซลูชันสากลและนำเสนอเพื่อการสาธิตเท่านั้น
การแสดงสาธิตค่าช่วง / เลื่อนเช่นเดียวกับจำนวนครั้งที่มาตรฐาน"change", "input"และกำหนดเอง"onRangeChange"เหตุการณ์ยิง (แถว A, B และ C ตามลำดับ) เมื่อเรียกใช้ตัวอย่างข้อมูลนี้ในเบราว์เซอร์ที่แตกต่างกันให้สังเกตสิ่งต่อไปนี้ในขณะที่คุณโต้ตอบกับช่วง / ตัวเลื่อน:
- ใน IE11 ค่าในแถว A และ C ทั้งสองเปลี่ยนแปลงในสถานการณ์ 2 และ 3 ข้างต้นในขณะที่แถว B ไม่เปลี่ยนแปลง
- ใน Chrome และ Safari ค่าในแถว B และ C ทั้งคู่จะเปลี่ยนไปในสถานการณ์ที่ 2 และ 3 ในขณะที่แถว A เปลี่ยนแปลงเฉพาะในสถานการณ์ที่ 5 เท่านั้น
- ใน Firefox ค่าในแถว A จะเปลี่ยนเฉพาะสำหรับสถานการณ์ 5, แถว B เปลี่ยนสำหรับทั้งห้าสถานการณ์และแถว C เปลี่ยนแปลงเฉพาะสำหรับสถานการณ์ 2 และ 3 เท่านั้น
- ในเบราว์เซอร์ทั้งหมดข้างต้นการเปลี่ยนแปลงในแถว C (โซลูชันที่เสนอ) เหมือนกันนั่นคือเฉพาะสำหรับสถานการณ์ 2 และ 3
รหัสตัวอย่าง:
// 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>
เครดิต:
ในขณะที่การดำเนินงานที่นี่เป็นส่วนใหญ่ของตัวเองมันก็แรงบันดาลใจจากคำตอบของ MBourne คำตอบอื่น ๆ ชี้ให้เห็นว่าเหตุการณ์ "อินพุต" และ "เปลี่ยน" อาจถูกรวมเข้าด้วยกันและโค้ดผลลัพธ์จะใช้ได้ทั้งบนเดสก์ท็อปและมือถือ อย่างไรก็ตามโค้ดในคำตอบนั้นส่งผลให้เกิดเหตุการณ์ "พิเศษ" ที่ซ่อนอยู่ซึ่งตัวมันเองมีปัญหาและเหตุการณ์ที่ถูกยิงแตกต่างกันระหว่างเบราว์เซอร์ซึ่งเป็นปัญหาเพิ่มเติม การใช้งานของฉันที่นี่แก้ปัญหาเหล่านั้นได้
คำสำคัญ:
เหตุการณ์ตัวเลื่อนช่วงประเภทอินพุต JavaScript เปลี่ยนความเข้ากันได้ของเบราว์เซอร์สำหรับการป้อนข้อมูลข้ามเบราว์เซอร์เดสก์ท็อปมือถือ no-jQuery
onchangeไฟไม่ได้ มันเป็นการแก้ไขปัญหาที่ฉันพบคำถามนี้