Pra*_*K C 230 javascript firefox html5 input onchange
当我玩游戏时<input type="range">,只有当我们将滑块拖放到Chrome和其他人在拖动滑块时触发更改事件的新位置时,Firefox才会触发onchange事件.
如何在firefox中拖动它?
HTML
<span id="valBox"></span>
<input type="range" min="5" max="10" step="1" onchange="showVal(this.value)">
Run Code Online (Sandbox Code Playgroud)
脚本
function showVal(newVal){
document.getElementById("valBox").innerHTML=newVal;
}
Run Code Online (Sandbox Code Playgroud)
Fre*_*rik 421
显然Chrome和Safari是错误的:onchange只应在用户释放鼠标时触发.要获得持续更新,您应该使用该oninput事件,该事件将通过鼠标和键盘捕获Firefox,Safari和Chrome中的实时更新.
但是,oninput在IE10中不支持,所以最好的办法是组合两个事件处理程序,如下所示:
<span id="valBox"></span>
<input type="range" min="5" max="10" step="1"
oninput="showVal(this.value)" onchange="showVal(this.value)">
Run Code Online (Sandbox Code Playgroud)
查看此Bugzilla线程以获取更多信息.
And*_*ems 35
摘要:
我在这里提供了一个no-jQuery跨浏览器桌面和移动功能,可以持续响应范围/滑块交互,这在当前浏览器中是不可能的.它实质上强制所有浏览器模仿IE11的on("change"...事件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);});
}
Run Code Online (Sandbox Code Playgroud)
... r你的范围输入元素在哪里,f是你的倾听者.在任何更改范围/滑块值的交互之后,将调用侦听器,但不会在不更改该值的交互之后调用,包括在当前滑块位置或从滑块的任一端移开时的初始鼠标或触摸交互.
问题:
截至2016年6月初,不同的浏览器在响应范围/滑块使用方面有所不同.五种情况是相关的:
下表显示了至少三种不同的桌面浏览器在响应上述哪种场景时的行为不同:
解:
该onRangeChange功能为范围/滑块交互提供了一致且可预测的跨浏览器响应.它会强制所有浏览器按照下表行事:
在IE11中,代码基本上允许所有内容按照现状运行,即它允许"change"事件以标准方式运行,并且"input"事件无关紧要,因为它始终不会触发.在其他浏览器中,"change"事件被有效地静音(以防止发射额外的,有时不容易发生的事件).此外,"input"仅当范围/滑块的值更改时,事件才会触发其侦听器.对于某些浏览器(例如Firefox),会发生这种情况,因为在上面的列表中,侦听器在场景1,4和5中被有效地静音.
(如果你真的需要在方案1,4和/或5中激活一个监听器,你可以尝试合并"mousedown"/ "touchstart","mousemove"/ "touchmove"和/或"mouseup"/ "touchend"events.这样的解决方案超出了这个答案的范围.)
移动浏览器的功能:
我在桌面浏览器中测试过这段代码,但在任何移动浏览器中都没有.然而,在这个页面的另一个答案中, MBourne已经证明我的解决方案"...似乎适用于我能找到的每个浏览器(Win桌面:IE,Chrome,Opera,FF; Android Chrome,Opera和FF,iOS Safari) ".(感谢MBourne.)
用法:
要使用此解决方案,请onRangeChange在您自己的代码中包含上面摘要(简化/缩小)中的函数或下面的演示代码片段(功能相同但更加不言自明).按如下方式调用它:
onRangeChange(myRangeInputElmt, myListener);
Run Code Online (Sandbox Code Playgroud)
myRangeInputElmt你想要的<input type="range">DOM元素在哪里,是myListener你想要在"change"类似事件上调用的监听器/处理函数.
如果需要,您的监听器可以是无参数的,或者可以使用event参数,即根据您的需要,以下任何一种都可以使用:
var myListener = function() {...
Run Code Online (Sandbox Code Playgroud)
要么
var myListener = function(evt) {...
Run Code Online (Sandbox Code Playgroud)
(在此答案中未解决从input元素中删除事件侦听器(例如,使用removeEventListener).)
演示说明:
在下面的代码片段中,该函数onRangeChange提供了通用解决方案.其余的代码只是一个展示其用途的例子.任何my...以通用解决方案开头的变量都与通用解决方案无关,只是为了演示而存在.
该演示示出了范围/滑块值以及次数的标准"change","input"和自定义"onRangeChange"事件烧制(行A,B和C).在不同浏览器中运行此代码段时,请在与范围/滑块进行交互时注意以下事项:
演示代码:
// 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);Run Code Online (Sandbox Code Playgroud)
table {
border-collapse: collapse;
}
th, td {
text-align: left;
border: solid black 1px;
padding: 5px 15px;
}Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
信用:
虽然这里的实施主要是我自己的,但它的灵感来自MBourne的答案.另一个答案表明,可以合并"输入"和"更改"事件,并且生成的代码可以在桌面和移动浏览器中使用.但是,该答案中的代码导致隐藏的"额外"事件被触发,这本身就存在问题,并且触发的事件在浏览器之间有所不同,这是另一个问题.我在这里的实现解决了这些问题.
关键词:
JavaScript输入类型范围滑块事件更改输入浏览器兼容性跨浏览器桌面移动no-jQuery
And*_*ems 30
更新:我在这里留下这个答案作为如何使用鼠标事件在桌面(但不是移动)浏览器中使用范围/滑块交互的示例.但是,我现在还在本页的其他地方编写了一个完全不同的,我相信更好的答案,它使用不同的方法为这个问题提供跨浏览器的桌面和移动解决方案.
原始答案:
简介:跨浏览器,纯JavaScript(即无jQuery)解决方案,允许读取范围输入值,而无需使用on('input'...和/或on('change'...浏览器之间的工作不一致.
截至今天(2016年2月下旬),仍然存在浏览器不一致性,所以我在这里提供了一个新的解决方案.
问题:当使用范围输入(即滑块)时,on('input'...在Mac和Windows Firefox,Chrome和Opera以及Mac Safari中提供连续更新的范围值,同时on('change'...仅在鼠标向上时报告范围值.相反,在Internet Explorer(v11)中,on('input'...根本不起作用,并且on('change'...不断更新.
我在这里报告了两种策略,通过使用mousedown,mousemove和(可能)mouseup事件,使用vanilla JavaScript(即没有jQuery)在所有浏览器中获得相同的连续范围值报告.
策略1:更短但效率更低
如果您更喜欢使用更短的代码而不是更高效的代码,那么您可以使用第一个使用mousesdown和mousemove但不使用mouseup的解决方案.这会根据需要读取滑块,但在任何鼠标悬停事件期间会不必要地继续触发,即使用户没有单击也不会拖动滑块.它基本上在'mousedown'和'mousemove'事件之后读取范围值,稍微延迟每次使用requestAnimationFrame.
var rng = document.querySelector("input");
read("mousedown");
read("mousemove");
read("keydown"); // include this to also allow keyboard control
function read(evtType) {
rng.addEventListener(evtType, function() {
window.requestAnimationFrame(function () {
document.querySelector("div").innerHTML = rng.value;
rng.setAttribute("aria-valuenow", rng.value); // include for accessibility
});
});
}Run Code Online (Sandbox Code Playgroud)
<div>50</div><input type="range"/>Run Code Online (Sandbox Code Playgroud)
战略2:更长但更有效率
如果您需要更高效的代码并且可以容忍更长的代码长度,那么您可以使用以下使用mousedown,mousemove和mouseup的解决方案.这也会根据需要读取滑块,但只要释放鼠标按钮就会立即停止读取.本质的区别在于,只有在'mousedown'之后才开始听'mousemove',并且在'mouseup'之后停止听'mousemove'.
var rng = document.querySelector("input");
var listener = function() {
window.requestAnimationFrame(function() {
document.querySelector("div").innerHTML = rng.value;
});
};
rng.addEventListener("mousedown", function() {
listener();
rng.addEventListener("mousemove", listener);
});
rng.addEventListener("mouseup", function() {
rng.removeEventListener("mousemove", listener);
});
// include the following line to maintain accessibility
// by allowing the listener to also be fired for
// appropriate keyboard events
rng.addEventListener("keydown", listener);Run Code Online (Sandbox Code Playgroud)
<div>50</div><input type="range"/>Run Code Online (Sandbox Code Playgroud)
演示:富勒解释上述解决方案的必要性和实施
以下代码更全面地展示了该策略的许多方面.解释嵌入在演示中:
var select, inp, listen, unlisten, anim, show, onInp, onChg, onDn1, onDn2, onMv1, onMv2, onUp, onMvCombo1, onDnCombo1, onUpCombo2, onMvCombo2, onDnCombo2;
select = function(selctr) { return document.querySelector(selctr); };
inp = select("input");
listen = function(evtTyp, cb) { return inp. addEventListener(evtTyp, cb); };
unlisten = function(evtTyp, cb) { return inp.removeEventListener(evtTyp, cb); };
anim = function(cb) { return window.requestAnimationFrame(cb); };
show = function(id) {
return function() {
select("#" + id + " td~td~td" ).innerHTML = inp.value;
select("#" + id + " td~td~td~td").innerHTML = (Math.random() * 1e20).toString(36); // random text
};
};
onInp = show("inp" ) ;
onChg = show("chg" ) ;
onDn1 = show("mdn1") ;
onDn2 = function() {anim(show("mdn2")); };
onMv1 = show("mmv1") ;
onMv2 = function() {anim(show("mmv2")); };
onUp = show("mup" ) ;
onMvCombo1 = function() {anim(show("cmb1")); };
onDnCombo1 = function() {anim(show("cmb1")); listen("mousemove", onMvCombo1);};
onUpCombo2 = function() { unlisten("mousemove", onMvCombo2);};
onMvCombo2 = function() {anim(show("cmb2")); };
onDnCombo2 = function() {anim(show("cmb2")); listen("mousemove", onMvCombo2);};
listen("input" , onInp );
listen("change" , onChg );
listen("mousedown", onDn1 );
listen("mousedown", onDn2 );
listen("mousemove", onMv1 );
listen("mousemove", onMv2 );
listen("mouseup" , onUp );
listen("mousedown", onDnCombo1);
listen("mousedown", onDnCombo2);
listen("mouseup" , onUpCombo2);Run Code Online (Sandbox Code Playgroud)
table {border-collapse: collapse; font: 10pt Courier;}
th, td {border: solid black 1px; padding: 0 0.5em;}
input {margin: 2em;}
li {padding-bottom: 1em;}Run Code Online (Sandbox Code Playgroud)
<p>Click on 'Full page' to see the demonstration properly.</p>
<table>
<tr><th></th><th>event</th><th>range value</th><th>random update indicator</th></tr>
<tr id="inp" ><td>A</td><td>input </td><td>100</td><td>-</td></tr>
<tr id="chg" ><td>B</td><td>change </td><td>100</td><td>-</td></tr>
<tr id="mdn1"><td>C</td><td>mousedown </td><td>100</td><td>-</td></tr>
<tr id="mdn2"><td>D</td><td>mousedown using requestAnimationFrame</td><td>100</td><td>-</td></tr>
<tr id="mmv1"><td>E</td><td>mousemove </td><td>100</td><td>-</td></tr>
<tr id="mmv2"><td>F</td><td>mousemove using requestAnimationFrame</td><td>100</td><td>-</td></tr>
<tr id="mup" ><td>G</td><td>mouseup </td><td>100</td><td>-</td></tr>
<tr id="cmb1"><td>H</td><td>mousedown/move combo </td><td>100</td><td>-</td></tr>
<tr id="cmb2"><td>I</td><td>mousedown/move/up combo </td><td>100</td><td>-</td></tr>
</table>
<input type="range" min="100" max="999" value="100"/>
<ol>
<li>The 'range value' column shows the value of the 'value' attribute of the range-type input, i.e. the slider. The 'random update indicator' column shows random text as an indicator of whether events are being actively fired and handled.</li>
<li>To see browser differences between input and change event implementations, use the slider in different browsers and compare A and B.</li>
<li>To see the importance of 'requestAnimationFrame' on 'mousedown', click a new location on the slider and compare C (incorrect) and D (correct).</li>
<li>To see the importance of 'requestAnimationFrame' on 'mousemove', click and drag but do not release the slider, and compare E (often 1 pixel behind) and F (correct).</li>
<li>To see why an initial mousedown is required (i.e. to see why mousemove alone is insufficient), click and hold but do not drag the slider and compare E (incorrect), F (incorrect) and H (correct).</li>
<li>To see how the mouse event combinations can provide a work-around for continuous update of a range-type input, use the slider in any manner and note whichever of A or B continuously updates the range value in your current browser. Then, while still using the slider, note that H and I provide the same continuously updated range value readings as A or B.</li>
<li>To see how the mouseup event reduces unnecessary calculations in the work-around, use the slider in any manner and compare H and I. They both provide correct range value readings. However, then ensure the mouse is released (i.e. not clicked) and move it over the slider without clicking and notice the ongoing updates in the third table column for H but not I.</li>
</ol>Run Code Online (Sandbox Code Playgroud)
Dan*_*non 28
我发布这个作为答案,因为它应该是它自己的答案,而不是在一个不太有用的答案下的评论.我发现这种方法比接受的答案要好得多,因为它可以将所有js保存在与HTML不同的文件中.
Jamrelian在接受答复的评论中提供的答案.
$("#myelement").on("input change", function() {
//do something
});
Run Code Online (Sandbox Code Playgroud)
请注意Jaime的评论
请注意,使用此解决方案,在chrome中,您将获得两次对处理程序的调用(每个事件一次),因此如果您关心它,那么您需要防范它.
因为它会在您停止移动鼠标时触发事件,然后在释放鼠标按钮时再次触发事件.
Andrew Willem的解决方案与移动设备不兼容。
这是他第二种解决方案的修改,可以在Edge,IE,Opera,FF,Chrome,iOS Safari和移动等效设备(我可以测试)中使用:
更新1:删除了“ requestAnimationFrame”部分,因为我同意没有必要:
var listener = function() {
// do whatever
};
slider1.addEventListener("input", function() {
listener();
slider1.addEventListener("change", listener);
});
slider1.addEventListener("change", function() {
listener();
slider1.removeEventListener("input", listener);
});
Run Code Online (Sandbox Code Playgroud)
更新2:对安德鲁2016年6月2日更新的回答:
谢谢,安德鲁-似乎可以在我能找到的所有浏览器中使用(Win桌面:IE,Chrome,Opera,FF; Android Chrome,Opera和FF,iOS Safari)。
更新3:if(“在滑块上输入”)解决方案
以下似乎适用于所有上述浏览器。(我现在找不到原始来源。)我正在使用它,但是随后在IE上失败了,所以我一直在寻找另一个,因此我就到这里了。
if ("oninput" in slider1) {
slider1.addEventListener("input", function () {
// do whatever;
}, false);
}
Run Code Online (Sandbox Code Playgroud)
但是在检查您的解决方案之前,我注意到它在IE中又可以正常工作-也许还有其他冲突。
为了获得良好的跨浏览器行为和易于理解的代码,最好是将 onchange 属性与表单结合使用:
function showVal(){
valBox.innerHTML = inVal.value;
}Run Code Online (Sandbox Code Playgroud)
<form onchange="showVal()">
<input type="range" min="5" max="10" step="1" id="inVal">
</form>
<span id="valBox"></span>Run Code Online (Sandbox Code Playgroud)
同样使用oninput,直接改变值。
function showVal(){
valBox.innerHTML = inVal.value;
}Run Code Online (Sandbox Code Playgroud)
<form oninput="showVal()">
<input type="range" min="5" max="10" step="1" id="inVal">
</form>
<span id="valBox"></span>Run Code Online (Sandbox Code Playgroud)