สรุป:
ฉันมอบความสามารถแบบเดสก์ท็อปและเบราว์เซอร์ข้ามมือถือที่ไม่ใช่ 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
ไฟไม่ได้ มันเป็นการแก้ไขปัญหาที่ฉันพบคำถามนี้