HTML <select> 是不是有 onSelect 事件或等效事件?
Posted
技术标签:
【中文标题】HTML <select> 是不是有 onSelect 事件或等效事件?【英文标题】:Is there an onSelect event or equivalent for HTML <select>?HTML <select> 是否有 onSelect 事件或等效事件? 【发布时间】:2010-10-13 10:25:46 【问题描述】:我有一个输入表单,可让我从多个选项中进行选择,并在用户更改选择时执行某些操作。例如,
<select onChange="javascript:doSomething();">
<option>A</option>
<option>B</option>
<option>C</option>
</select>
现在,doSomething()
仅在选择更改时触发。
我想在用户选择任何选项时触发doSomething()
,可能再次相同。
我曾尝试使用“onClick”处理程序,但它会在用户开始选择过程之前触发。
那么,有没有办法在用户每次选择时触发一个函数?
更新:
Darryl 建议的答案似乎有效,但并不能始终如一。有时,一旦用户单击下拉菜单,甚至在用户完成选择过程之前,事件就会被触发!
【问题讨论】:
我能理解你为什么这么想。我会保持简短。我的表单上有两个输入。城市(文本字段)和州(选择)。最初,会显示一个城市及其州。当用户选择一个州时,某处的搜索过滤器会将其范围扩大到“全州”而不是“特定城市”。 strager,这不是一个不常见的 UI 元素。在某些情况下非常有意义。另一个例子是撰写大量电子邮件,然后您在右侧有一个带有“特殊字段”的下拉菜单,您可以快速将其添加到电子邮件中、名字、退出链接等。 作为旁注......对于onclick,onchange等内联事件,您不需要“javascript:”协议前缀。 onevent="doSomething();"很好。 未经测试:onClick 但应用于选项标签怎么样?显然是通过一个类,以一种不显眼的方式 @The Disintegrator 仅使用点击事件无法处理通过键盘选择选项的用例。 (意识到这是一个古老的问题 - 为未来的访客添加......) 【参考方案1】:这是最简单的方法:
<select name="ab" onchange="if (this.selectedIndex) doSomething();">
<option value="-1">--</option>
<option value="1">option 1</option>
<option value="2">option 2</option>
<option value="3">option 3</option>
</select>
既有鼠标选择和键盘向上/向下键,选择重点选择。
【讨论】:
但这不会做任何“当用户再次选择...相同的”,对吗? 请注意,@KayZhu 的评论只对了一半:正确的做法是检查“selectedIndex”是否大于或等于零(或大于-1)。没有“type()”函数,而且“selectedIndex”永远不会是undefined
。
@T.J.Crowder 你是对的——不知道我在写下半部分时在想什么。我已经删除了原始评论,为了不混淆其他人,这里是原始评论(请注意前半部分正确,后半部分错误):这不会按预期工作第一个索引为 0: 0 的选项在 JS 中为 false,因此 doSomething() 不会被执行。相反,请使用if(type(this.selectedIndex) != undefined; doSomething()
这个答案的支持率最高,但它并没有解决问题! doSomething()
函数在用户选择已经选择的选项时不会被触发。请参阅此plunk,仅当您选择与当前选择的选项不同的 选项时,背景颜色才会更改。
FWIW:如果您只想在选择一个特定选项时调用doSomething()
,例如上例中的“选项3”,请使用if (this.selectedIndex==4)
,其中数字“4”代表数字索引选项,而不是指定的value
! (即“选项 3”是<select name="ab">
的第四个选项)。【参考方案2】:
我需要完全相同的东西。这对我有用:
<select onchange="doSomething();" onfocus="this.selectedIndex = -1;">
<option>A</option>
<option>B</option>
<option>C</option>
</select>
支持这个:
当用户选择任何选项时,可能再次选择相同的选项
【讨论】:
jsfiddle.net/ecmanaut/335XK 适用于 osx Chrome 30、Safari 6、Firefox 17。 也适用于 Win8 IE10、Win7 IE9、Win7 IE8、WinXP IE7 和 IE6。 Jsfiddle 或 IE 恶作剧迫使您直接使用 fiddle.jshell.net/ecmanaut/335XK/show/light 进行测试,但他们的编辑器视图无法加载示例中使用的 jQuery 以提高可读性。以上只是用鼠标交互测试过的;为了让这个键盘友好,这个 hack 可能需要额外的工作,因为至少旧的 IE 会在你有机会选择“C”之前愉快地触发更改事件。 非常棒的小费,。帮我解决了无法选择第一个选项的问题 如果一个值已经被选中,那么在这个选项中切换会导致问题。一旦该字段被导航到该值,该值就会消失,这是一个非常出乎意料的用户行为。此外,当您关闭选项卡时,您将丢失选择,即使您没有执行任何此类操作。否则,好主意。 使用例如 jQuery .blur() 来恢复原始选择,如果它在失去焦点时为 -1。【参考方案3】:几个月前我在创建设计时遇到了同样的问题。我找到的解决方案是在您正在使用的元素上结合使用.live("change", function())
和.blur()
。
如果您希望它在用户单击时执行某些操作,而不是更改,只需将 change
替换为 click
。
我为下拉列表分配了一个 ID,selected
,并使用了以下内容:
$(function ()
$("#selected").live("change", function ()
// do whatever you need to do
// you want the element to lose focus immediately
// this is key to get this working.
$('#selected').blur();
);
);
我看到这个没有选定的答案,所以我想我会提供我的意见。这对我来说非常有效,所以希望其他人在遇到困难时可以使用此代码。
http://api.jquery.com/live/
编辑:使用on
选择器而不是.live
。见jQuery .on()
【讨论】:
谢谢! .blur() 有帮助。在IE7中,如果代码中没有.blur(),jQuery的change事件会被触发两次。 这对问题中表达的问题有何帮助,即在选择更改之前什么都没有发生? @LarsH 这个问题已经有好几年了,不确定——我可能读错了这个问题并且感到困惑。 对于现在正在查看的任何人,从 1.9 api.jquery.com/live/#live-events-handler 开始,.live 已被完全删除。使用 .change 作为快捷方式 api.jquery.com/change/#change-handler【参考方案4】:只是一个想法,但是否可以在每个 <option>
元素上单击一次?
<select>
<option onclick="doSomething(this);">A</option>
<option onclick="doSomething(this);">B</option>
<option onclick="doSomething(this);">C</option>
</select>
另一个选项可能是在选择上使用 onblur。这将在用户点击离开选择的任何时候触发。此时,您可以确定选择了哪个选项。为了在正确的时间触发此事件,该选项的 onclick 可能会模糊该字段(使其他内容处于活动状态或仅 .blur() 在 jQuery 中)。
【讨论】:
@Darryl 这实际上并没有按预期工作。有时甚至在用户完成选择之前事件就会被触发。查看我添加到问题中的更新。 将事件处理程序放在选项上将在所有版本的 IE 中失败! webbugtrack.blogspot.com/2007/11/… 在 Firefox 中工作。 这个列表可能很长。【参考方案5】:onclick 方法并不完全糟糕,但正如所说,当鼠标单击未更改值时,它不会被触发。 但是可以在 onchange 事件中触发 onclick 事件。
<select onchange="doSomething(...);if(this.options[this.selectedIndex].onclick != null)this.options[this.selectedIndex].onclick(this);">
<option onclick="doSomethingElse(...);" value="A">A</option>
<option onclick="doSomethingElse(..);" value="B">B</option>
<option onclick="doSomethingElse(..);" value="Foo">C</option>
</select>
【讨论】:
【参考方案6】:如果你真的需要这样工作,我会这样做(以确保它可以通过键盘和鼠标工作)
将 onfocus 事件处理程序添加到选择以设置“当前”值 将 onclick 事件处理程序添加到选择以处理鼠标更改 将 onkeypress 事件处理程序添加到 select 以处理键盘更改不幸的是,onclick 将运行多次(例如,在打开选择时...和在选择/关闭时)并且当没有任何变化时可能会触发 onkeypress...
<script>
function setInitial(obj)
obj._initValue = obj.value;
function doSomething(obj)
//if you want to verify a change took place...
if(obj._initValue == obj.value)
//do nothing, no actual change occurred...
//or in your case if you want to make a minor update
doMinorUpdate();
else
//change happened
getNewData(obj.value);
</script>
<select onfocus="setInitial(this);" onclick="doSomething();" onkeypress="doSomething();">
...
</select>
【讨论】:
【参考方案7】:将扩展 jitbit 的答案。当您单击下拉菜单然后单击下拉菜单而不选择任何内容时,我发现这很奇怪。最后得到了一些类似的东西:
var lastSelectedOption = null;
DDChange = function(Dd)
//Blur after change so that clicking again without
//losing focus re-triggers onfocus.
Dd.blur();
//The rest is whatever you want in the change.
var tcs = $("span.on_change_times");
tcs.html(+tcs.html() + 1);
$("span.selected_index").html(Dd.prop("selectedIndex"));
return false;
;
DDFocus = function(Dd)
lastSelectedOption = Dd.prop("selectedIndex");
Dd.prop("selectedIndex", -1);
$("span.selected_index").html(Dd.prop("selectedIndex"));
return false;
;
//On blur, set it back to the value before they clicked
//away without selecting an option.
//
//This is what is typically weird for the user since they
//might click on the dropdown to look at other options,
//realize they didn't what to change anything, and
//click off the dropdown.
DDBlur = function(Dd)
if (Dd.prop("selectedIndex") === -1)
Dd.prop("selectedIndex", lastSelectedOption);
$("span.selected_index").html(Dd.prop("selectedIndex"));
return false;
;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="Dd" onchange="DDChange($(this));" onfocus="DDFocus($(this));" onblur="DDBlur($(this));">
<option>1</option>
<option>2</option>
</select>
<br/>
<br/>Selected index: <span class="selected_index"></span>
<br/>Times onchange triggered: <span class="on_change_times">0</span>
这对用户来说更有意义,并允许 JavaScript 在他们每次选择任何选项(包括较早的选项)时运行。
这种方法的缺点是它破坏了在下拉菜单中使用选项卡并使用箭头键选择值的能力。这对我来说是可以接受的,因为所有用户一直点击所有内容,直到永恒结束。
【讨论】:
您可以通过传入this
而不是$(this)
来消除道具警告。但是,我并没有从中得到所有预期的行为;当我重新选择相同的选项时它不会提醒。
注意: onchange
在通过 JS 向选择框添加删除选项时触发。不仅仅是当用户选择一个项目时
@Noumenon 我修复了这里的错误,如果它仍然有用的话。我想我是在应用程序本身中测试它,当我把它复制出来时,我忘了重命名一个变量。应该在编辑器中工作并且现在更有意义。【参考方案8】:
要在每次用户选择某项(即使是相同的选项)时正确触发事件,您只需要欺骗选择框即可。
就像其他人所说的那样,在焦点上指定一个否定的selectedIndex
以强制更改事件。虽然这确实允许您欺骗选择框,但只要它仍然具有焦点,它就不会工作。简单的解决方法是强制选择框模糊,如下所示。
标准 JS/HTML:
<select onchange="myCallback();" onfocus="this.selectedIndex=-1;this.blur();">
<option>A</option>
<option>B</option>
<option>C</option>
</select>
jQuery 插件:
<select>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<script type="text/javascript">
$.fn.alwaysChange = function(callback)
return this.each(function()
var elem = this;
var $this = $(this);
$this.change(function()
if(callback) callback($this.val());
).focus(function()
elem.selectedIndex = -1;
elem.blur();
);
);
$('select').alwaysChange(function(val)
// Optional change event callback,
// shorthand for $('select').alwaysChange().change(function());
);
</script>
你可以看到working demo here。
【讨论】:
这适用于 Chrome,但不适用于 IE9:当我单击控件时,它的文本会消失并且不会下拉。 这样做的问题是它会破坏当前的选择。如果当前选择是 B 并且我单击下拉菜单,则复选标记会显示在 A 旁边!但是 A 并没有真正被选中,因为如果我滑出菜单并释放鼠标按钮(中止菜单),则选择变为空白。如果您点击到下拉菜单,选择也会变为空白,如果您正在点击表单的其他部分,您可能很容易做到这一点,并且不希望在此过程中造成任何损坏。 (按你的 jsfiddle 上的标签,你会明白我的意思。)【参考方案9】:这可能无法直接回答您的问题,但可以通过简单的设计级别调整来解决此问题。我知道这可能并非 100% 适用于所有用例,但我强烈建议您重新考虑您的应用程序的用户流程以及是否可以实施以下设计建议。
我决定做一些简单的事情,而不是使用并非真正用于此目的的其他事件(blur
、click
等)来破解 onChange()
的替代方案
我的解决方法:
只需在前面添加一个占位符选项标签,例如 select,它没有任何价值。
因此,不要只使用以下结构,这需要 hack-y 替代方案:
<select>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
考虑使用这个:
<select>
<option selected="selected">Select...</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
因此,这样一来,您的代码将大大简化,并且每次用户决定选择默认值以外的其他值时,onChange
都会按预期工作。如果您不希望他们再次选择它并强制他们从选项中选择某些内容,您甚至可以将disabled
属性添加到第一个选项,从而触发onChange()
触发。
在回答这个问题时,我正在编写一个复杂的 Vue 应用程序,我发现这种设计选择大大简化了我的代码。在解决这个问题之前,我花了几个小时解决这个问题,而且我不必重新编写很多代码。但是,如果我使用 hacky 替代方案,我将需要考虑边缘情况,以防止 ajax 请求的双重触发等。这也不会破坏默认浏览器行为作为一个不错的奖励(在移动设备上测试浏览器)。
有时,您只需要退后一步,从大局考虑最简单的解决方案。
【讨论】:
【参考方案10】:我知道这个问题现在已经很老了,但是对于仍然遇到这个问题的任何人,我通过在我的选项标签中添加一个 onInput 事件,然后在那个被调用的函数中检索它的值,在我自己的网站上实现了这一点选项输入。
<select id='dropdown' onInput='myFunction()'>
<option value='1'>1</option>
<option value='2'>2</option>
</select>
<p>Output: </p>
<span id='output'></span>
<script type='text/javascript'>
function myFunction()
var optionValue = document.getElementById("dropdown").value;
document.getElementById("output").innerHTML = optionValue;
</script>
【讨论】:
【参考方案11】:实际上,当用户使用键盘更改选择控件中的选择时,onclick 事件不会触发。您可能需要结合使用 onChange 和 onClick 来获得您正在寻找的行为。
【讨论】:
是的,我不得不......但我面临的问题是与您提出的问题正交的一个独立问题。 将所选内容移动到新项目后按 Enter 键时,Chrome 中会触发事件【参考方案12】:首先你使用 onChange 作为一个事件处理程序,然后使用标志变量让它在你每次进行更改时执行你想要的功能
<select
var list = document.getElementById("list");
var flag = true ;
list.onchange = function ()
if(flag)
document.bgColor ="red";
flag = false;
else
document.bgColor ="green";
flag = true;
<select id="list">
<option>op1</option>
<option>op2</option>
<option>op3</option>
</select>
【讨论】:
【参考方案13】:添加一个额外的选项作为第一个选项,如列的标题,这将是下拉下拉下拉按钮的默认值,然后在doSomething()
doSomething()
时重置,因此在选择A / B / C时, the onchange event always trigs, when the selection is State
, do nothing and return. onclick
就像很多人之前提到的那样非常不稳定。因此,我们需要做的就是制作一个与您的真实选项不同的初始按钮标签,这样 onchange 将适用于任何选项。
<select id="btnState" onchange="doSomething(this)">
<option value="State" selected="selected">State</option>
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
</select>
function doSomething(obj)
var btnValue = obj.options[obj.selectedIndex].value;
if (btnValue == "State")
//do nothing
return;
// Do your thing here
// reset
obj.selectedIndex = 0;
【讨论】:
【参考方案14】:选择标签(在这种情况下)的奇妙之处在于它会从选项标签中获取它的值。
试试:
<select onChange="javascript:doSomething(this.value);">
<option value="A">A</option>
<option value="B">B</option>
<option value="Foo">C</option>
</select>
对我来说工作得体。
【讨论】:
【参考方案15】:我在遇到类似问题时所做的是,我在选择框中添加了一个“onFocus”,它附加了一个新的通用选项(“选择一个选项”或类似的东西)并将其默认为选定选项。
【讨论】:
【参考方案16】:所以我的目标是能够多次选择相同的值,这实际上会覆盖 onchange() 函数并将其变成有用的 onclick() 方法。
根据上面的建议,我想出了这个对我有用的方法。
<select name="ab" id="hi" onchange="if (typeof(this.selectedIndex) != undefined) alert($('#hi').val()); this.blur();" onfocus="this.selectedIndex = -1;">
<option value="-1">--</option>
<option value="1">option 1</option>
<option value="2">option 2</option>
<option value="3">option 3</option>
</select>
http://jsfiddle.net/dR9tH/19/
【讨论】:
与其他onfocus="this.selectedIndex=-1"
解决方案相同的缺点:如果您选择组件,或者如果您在没有选择任何内容的情况下将鼠标从菜单上移开,则当前选择会被取消。按你的小提琴上的标签看看我的意思。 (另请注意,当您执行此操作时,您会得到一个空白值而不是“--”。那是因为 selectedIndex=-1
不会让您到达 <option value="-1">
;这里使用 onfocus="this.selectedIndex=0"
会略有改进。这是一半- 体面的解决方法,但我不喜欢仅仅因为我偷看菜单,甚至只是通过标签进入它而丢失当前选择。【参考方案17】:
使用 jquery:
<select class="target">
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<script>
$('.target').change(function() doSomething(); );
</script>
【讨论】:
【参考方案18】:这是我的解决方案,与此处的其他解决方案完全不同。它使用鼠标位置来确定是否单击了选项,而不是单击选择框以打开下拉列表。它利用 event.screenY 位置,因为这是唯一可靠的跨浏览器变量。必须先附加一个悬停事件,以便在单击事件之前确定控件相对于屏幕的位置。
var select = $("select");
var screenDif = 0;
select.bind("hover", function (e)
screenDif = e.screenY - e.clientY;
);
select.bind("click", function (e)
var element = $(e.target);
var eventHorizon = screenDif + element.offset().top + element.height() - $(window).scrollTop();
if (e.screenY > eventHorizon)
alert("option clicked");
);
这是我的 jsFiddle http://jsfiddle.net/sU7EV/4/
【讨论】:
在 OS X 的 Safari 或 Chrome 中不起作用。永远不会触发警报。【参考方案19】:你应该尝试使用option:selected
$("select option:selected").click(doSomething);
【讨论】:
【参考方案20】:什么对我有用:
<select id='myID' onchange='doSomething();'>
<option value='0' selected> Select Option </option>
<option value='1' onclick='if (!document.getElementById("myID").onchange()) doSomething();' > A </option>
<option value='2' onclick='if (!document.getElementById("myID").onchange()) doSomething();' > B </option>
</select>
这样,onchange 会在选项更改时调用“doSomething()”,并且 当 onchange 事件为 false 时,onclick 调用 'doSomething()',换句话说,当您选择相同的选项时
【讨论】:
在 Safari 或 OS X 的 Chrome 中对我不起作用。jsfiddle.net/drskot/wLvL4pkw【参考方案21】:试试这个(当你选择选项时触发事件,不改变选项):
$("select").mouseup(function()
var open = $(this).data("isopen");
if(open)
alert('selected');
$(this).data("isopen", !open);
);
http://jsbin.com/dowoloka/4
【讨论】:
【参考方案22】:<script>
function abc(selectedguy)
alert(selectedguy);
</script>
<select onchange="abc(this.selectedIndex);">
<option>option one</option>
<option>option two</option>
</select>
这里你有返回的索引,在 js 代码中你可以使用这个返回与一个开关或任何你想要的。
【讨论】:
【参考方案23】:请注意,IE 上的 OPTION 标签不支持事件处理程序,快速思考..我想出了这个解决方案,尝试一下并给我您的反馈:
<script>
var flag = true;
function resetIndex(selObj)
if(flag) selObj.selectedIndex = -1;
flag = true;
function doSomething(selObj)
alert(selObj.value)
flag = false;
</script>
<select onchange="doSomething(this)" onclick="resetIndex(this)">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
</select>
我在这里所做的实际上是重置选择索引,以便始终触发 onchange 事件,确实,当您单击时我们会丢失所选项目,如果您的列表很长,这可能会很烦人,但它可能会有所帮助你在某种程度上..
【讨论】:
【参考方案24】:试试这个:
<select id="nameSelect" onfocus="javascript:document.getElementById('nameSelect').selectedIndex=-1;" onchange="doSomething(this);">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
</select>
【讨论】:
【参考方案25】:很久以前,但在回答最初的问题时,这有帮助吗?
只需将onClick
放入SELECT
行。
然后将您希望每个OPTION
执行的操作放在OPTION
行中。
即:
<SELECT name="your name" onClick>
<option value ="Kilometres" onClick="YourFunction()">Kilometres
-------
-------
</SELECT>
【讨论】:
【参考方案26】:<select name="test[]"
onchange="if(this.selectedIndex < 1)this.options[this.selectedIndex].selected = !1">
<option>1</option>
<option>2</option>
<option>3</option>
</select>
【讨论】:
【参考方案27】:我也遇到过类似的需求,最终为此编写了一个 angularjs 指令 -
guthub link - angular select
使用element[0].blur();
将焦点从选择标签上移开。逻辑是在第二次点击下拉菜单时触发这种模糊。
as-select
被触发,即使用户在下拉列表中选择了相同的值。
演示 - link
【讨论】:
【参考方案28】:一个正确的答案是不使用选择字段(如果您在重新选择相同的答案时需要做某事。)
使用传统的 div、按钮、显示/隐藏菜单创建一个下拉菜单。链接:https://www.w3schools.com/howto/howto_js_dropdown.asp
如果能够将事件侦听器添加到选项,就可以避免。如果选择元素有一个 onSelect 侦听器。如果单击选择字段没有严重触发 mousedown、mouseup 和 mousedown 时同时单击。
【讨论】:
【参考方案29】:您需要在此处执行一些操作,以确保它记住旧值并触发 onchange 事件,即使再次选择相同的选项也是如此。
你想要的第一件事是一个常规的 onChange 事件:
$("#selectbox").on("change", function()
console.log($(this).val());
doSomething();
);
要让 onChange 事件在再次选择相同选项时触发,您可以在下拉菜单获得焦点时取消设置选定选项,方法是将其设置为无效值。但是您还希望存储先前选择的值以在用户没有选择任何新选项的情况下恢复它:
prev_select_option = ""; //some kind of global var
$("#selectbox").on("focus", function()
prev_select_option = $(this).val(); //store currently selected value
$(this).val("unknown"); //set to an invalid value
);
即使选择了相同的值,上面的代码也将允许您触发 onchange。但是,如果用户在选择框外单击,您希望恢复以前的值。我们在 onBlur 上做:
$("#selectbox").on("blur", function()
if ($(this).val() == null)
//because we previously set an invalid value
//and user did not select any option
$(this).val(prev_select_option);
);
【讨论】:
【参考方案30】:当元素获得焦点时如何更改选择的值,例如(使用 jquery):
$("#locationtype").focus(function()
$("#locationtype").val('');
);
$("#locationtype").change(function()
if($("#locationtype").val() == 1)
$(".bd #mapphp").addClass('show');
$("#invoerform").addClass('hide');
if($("#locationtype").val() == 2)
$(".lat").val('');
$(".lon").val('');
);
【讨论】:
以上是关于HTML <select> 是不是有 onSelect 事件或等效事件?的主要内容,如果未能解决你的问题,请参考以下文章
React Material <Select> 与常规 HTML <input> 或 <select>