HTML <select>是否存在onSelect事件或等效事件?


213

我有一个输入表单,可让我从多个选项中进行选择,并在用户更改选择时执行一些操作。例如,

<select onChange="javascript:doSomething();">
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

现在,doSomething()仅当选择更改时才会触发。

我想doSomething()在用户选择任何选项时触发,可能再次相同

我尝试使用“ onClick”处理程序,但是在用户开始选择过程之前触发了该处理程序。

那么,有没有一种方法可以在用户的​​每次选择上触发功能?

更新:

达里尔(Darryl)提出的答案似乎行得通,但并不一致。有时,甚至在用户完成选择过程之前,只要用户单击下拉菜单,就会触发该事件!


1
我能理解你为什么这么认为。我会简短。我的表格上有两个输入。城市(文本字段)和州(选择)。最初,显示城市及其州。当用户选择州时,搜索过滤器会将其范围扩展到“州范围”而不是“特定于城市”。
ePharaoh

9
更强大,这不是一个罕见的UI元素。在某些情况下非常有意义。另一个例子将撰写群发电子邮件,那么你有“特殊领域”右侧的下拉您可以快速添加到电子邮件,第一个名字,选择退出链接等
布赖恩·阿姆斯特朗

2
只是作为一个注释...对于onclick,onchange等内联事件,您不需要“ javascript:”协议前缀。on {event} =“ doSomething();” 很好
scunliffe

未经测试:onClick应用于选项标签怎么样?显然是通过课堂,以一种不显眼的方式
The Disintegrator

6
@The Disintegrator仅使用click事件无法处理通过键盘选择选项的用例。(意识到这是一个古老的问题-为将来的访客添加...)
peteorpeter 2011年

Answers:


85

这是最简单的方法:

<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>

选择时,鼠标选择和键盘上/下键均可使用。


36
但这对“当用户再次选择...相同的对象时”不会起作用,对吗?
LarsH 2012年

3
请注意,@ KayZhu的注释仅是正确的一半:正确的做法是检查“ selectedIndex”是否大于或等于零(或大于-1)。没有“ type()”函数,“ selectedIndex”将永远不会存在undefined
尖尖的

2
@TJCrowder你是正确的-不确定我写第二部分时的想法。我删除了原始注释,为了不引起其他人的混淆,这是原始注释(请注意,上半部分是正确的,而第二部分是错误的): 这对于第一个选项不起作用索引为0:0在JS中为false,因此不会执行doSomething()。相反,请使用if(type(this.selectedIndex) != undefined; doSomething()
KZ

14
这个答案最多,但不能解决问题!doSomething()当用户选择已选择的选项时,不会触发该功能。看到这个普拉克,在那里,如果你选择一个背景颜色只改变不同比当前选定的一个选项。
skot 2015年

FWIW:如果仅doSomething()在选择一个特定选项时才调用,例如上例中的“ option 3”,则使用if (this.selectedIndex==4)数字“ 4”表示选项的数字索引,而不是指定的value!(即,“选项3”是的第四个选项<select name="ab">)。
rvrvrv

66

我需要完全一样的东西。这对我有用:

<select onchange="doSomething();" onfocus="this.selectedIndex = -1;">
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

支持以下内容:

当用户选择任何选项时,可能再次选择相同的选项


4
jsfiddle.net/ecmanaut/335XK工作在OSX的Chrome 30,Safari浏览器6.0版,Firefox 17
ecmanaut

2
也可以在Win8 IE10,Win7 IE9,Win7 IE8,WinXP IE7和IE6中使用。Jsfiddle或IE恶作剧迫使您直接将fiddle.jshell.net/ecmanaut/335XK/show/light用于测试,尽管-他们的编辑器视图无法加载示例中使用的jQuery以提高可读性。以上只是通过鼠标交互进行了测试;为了使这种键盘友好,此黑客可能需要更多的工作,因为至少在您有机会选择“ C”之前,旧的IE会愉快地触发change事件。
ecmanaut

3
真的很棒的提示。帮助我解决了无法选择第一个选项的问题
naoru 2014年

7
如果已经选择一个值,则逐个浏览将导致问题。一旦将字段导航到该值,该值就会消失,这是用户非常意外的行为。同样,当您取消选中该标签时,即使您没有进行任何操作,也将丢失选择。否则,好主意。
KyleMit 2014年

1
使用例如jQuery .blur()可以在失去焦点时恢复原始选择(如果它为-1)。
mheinzerling

12

几个月前创建设计时,我遇到了同样的问题。我发现的解决方案是.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事件将触发两次。
2012年

7
这如何解决问题中表达的问题,即在更改选择之前什么也没有发生?
LarsH 2012年

2
@LarsH这个问题已经过去好几年了,不确定-我可能读错了这个问题,感到困惑。
科迪

对于现在看的任何人,.live自1.9 api.jquery.com/live/#live-events-handler都已被完全删除。使用.change作为快捷方式api.jquery.com/change/#change-handler
parttimeturtle

9

只是一个想法,但是是否可以对每个<option>元素进行onclick ?

<select>
  <option onclick="doSomething(this);">A</option>
  <option onclick="doSomething(this);">B</option>
  <option onclick="doSomething(this);">C</option>
</select>

另一种选择是在选择上使用onblur。只要用户单击选择项,就会触发该事件。此时,您可以确定选择了哪个选项。为了使此事件在正确的时间触发,该选项的onclick可能会使字段模糊(使其他内容处于活动状态,或者只是在jQuery中使用.blur())。


1
该死!“为什么我没想到那个”时刻。谢谢!
ePharaoh

@Darryl这实际上没有按预期工作。有时甚至在用户完成选择之前触发事件。请参阅我添加到该问题的更新。
ePharaoh

8
在所有版本的IE中,将事件处理程序放在选项上都将失败!webbugtrack.blogspot.com/2007/11/…–
scunliffe

8
chrome也失败:)
thinklinux 2011年

在Firefox中工作。
lezsakdomi

6

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>

5

将扩展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)。但是,我并没有从中得到所有预期的行为。当我重新选择相同的选项时,它不会发出警报。
Noumenon

1
注意: onchange通过JS向选择框添加删除选项时触发。不仅仅是用户选择项目时
zanderwar '16

@Noumenon如果仍然有用,我已修复了此错误。我想我正在应用程序本身中进行测试,当我将其复制出来时,我忘记了重命名变量。应该在编辑器中工作,并且现在更加有意义。
Tyler Stahlhuth '17

4

如果您真的需要这样才能工作,我会这样做(以确保它可以通过键盘和鼠标工作)

  • 将onfocus事件处理程序添加到选择中以设置“当前”值
  • 在选择中添加onclick事件处理程序以处理鼠标更改
  • 向选择添加onkeypress事件处理程序以处理键盘更改

不幸的是,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>

4

为了在用户每次选择某项(即使是相同的选项)时正确触发事件,您只需要欺骗选择框即可。

就像其他人所说的,指定否定 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>

您可以在此处查看有效的演示


这适用于Chrome,但不适用于IE9:当我单击控件时,其文本消失,并且没有下拉菜单。
ChrisW 2013年

问题在于它使当前选择无效。如果当前选择为B,然后单击下拉列表,则复选标记将显示在A旁边!但是并没有真正选择A,因为如果我滑下菜单并释放鼠标键(中止菜单),则选择将变为空白。如果您选择下拉菜单,选择也将变为空白;如果您选择了表格的其他部分,并且不希望在此过程中造成任何损坏,则可以轻松地进行选择。(按一下jsfiddle上的标签,您将明白我的意思。)
skot 2015年

3

实际上,当用户使用键盘更改选择控件中的选择时,onclick事件不会触发。您可能必须结合使用onChange和onClick来获取所需的行为。


是的,我将不得不..但是我面临的问题是一个与您提出的关注正交的问题。<option>上的onclick事件甚至在用户完成选择之前就被触发,这似乎使它无法使用。
ePharaoh

事件触发时在Chrome中按已经移动的选择,以一个新的项目后,输入
基因Golovchinsky

3

这可能无法直接回答您的问题,但是可以通过简单的设计级别调整来解决此问题。我了解这可能并非100%适用于所有用例,但我强烈建议您考虑重新考虑应用程序的用户流程,以及是否可以实施以下设计建议。

我决定做一些简单的黑客比替代品onChange()使用并不真正意味着用于此目的的其他事件(blurclick,等)

我解决的方式:

只需在前面附加一个没有任何价值的占位符选项标签(例如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应用程序,我发现这种设计选择大大简化了我的代码。在解决该问题之前,我花了几个小时解决这个问题,而不必重新编写很多代码。但是,如果我选择了别具一格的替代方案,则需要考虑一些极端情况,以防止再次触发ajax请求等。这也不会破坏默认的浏览器行为,这是一个不错的收获(在移动设备上进行了测试)浏览器)。

有时,您只需要退后一步,考虑一下最简单的解决方案的概况。


2

遇到类似问题时,我所做的是在选择框中添加了“ onFocus”,该附加新的通用选项(“选择一个选项”或类似选项)并将其默认为选中的选项。


2

因此,我的目标是能够多次选择相同的值,这实际上将覆盖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/


2
与其他onfocus="this.selectedIndex=-1"解决方案相同的缺点:如果您使用Tab键选择该组件,或者在没有选择任何内容的情况下将鼠标移出菜单,则当前选择被取消。在您的小提琴上按Tab以查看我的意思。(还请注意,执行此操作时会得到一个空白值而不是'-'。这是因为selectedIndex=-1无法达到目标<option value="-1">;在这里使用会有所改善onfocus="this.selectedIndex=0"。这是一个不错的解决方法,但我没有就像失去只是因为我在偷看菜单,或者它甚至只是标签当前的选择。
SKOT

2

首先添加一个额外的选项,例如一列的标题,这将是下拉按钮的默认值,然后单击它并在末尾进行重置doSomething(),因此,在选择A / B / C时,onchange事件总是触发,当选择为时State,不执行任何操作,然后返回。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;
}

1

关于select标签(在这种情况下)的妙处在于,它将从option标签中获取其值。

尝试:

<select onChange="javascript:doSomething(this.value);">
<option value="A">A</option>
<option value="B">B</option>
<option value="Foo">C</option>
</select>

为我工作得体面。


1

使用jQuery:

<select class="target">
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

<script>
    $('.target').change(function() { doSomething(); });
</script>

1

这是我的解决方案,与这里的其他解决方案完全不同。它使用鼠标的位置来确定是否单击了选项,而不是单击选择框以打开下拉菜单。它利用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/


1
在OS X的Safari或Chrome中不起作用。永远不会触发警报。
skot 2015年


1

什么对我有用:

<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或Chrome OS X版。jsfiddle.net
drskot/

1

尝试以下操作(事件在您选择选项时准确触发,而无需更改选项):

$("select").mouseup(function() {
    var open = $(this).data("isopen");
    if(open) {
        alert('selected');
    }
    $(this).data("isopen", !open);
});

http://jsbin.com/dowoloka/4


1
<script>
function abc(selectedguy) {
alert(selectedguy);
}
</script>

<select onchange="abc(this.selectedIndex);">
<option>option one</option>
<option>option two</option>
</select>

在这里,您有返回的索引,并且在js代码中,您可以通过一个开关或任何您想要的东西使用此返回。


1

首先,您将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>


0

试试这个:

<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>

0

现在很久以前,但在回答原始问题时,这会有所帮助吗?只要把onClickSELECT线。然后将您想让每个OPTION人做的事放在OPTION行中。即:

<SELECT name="your name" onClick>
<option value ="Kilometres" onClick="YourFunction()">Kilometres
-------
-------
</SELECT>

0
<select name="test[]" 
onchange="if(this.selectedIndex < 1){this.options[this.selectedIndex].selected = !1}">
<option>1</option>
<option>2</option>
<option>3</option>
</select>

0

我曾经遇到过类似的需求,最终为相同的代码编写了angularjs指令-

guthub链接-角度选择

用于element[0].blur();将焦点从选择标签上移开。逻辑是在第二次单击下拉菜单时触发此模糊。

as-select 即使用户在下拉菜单中选择了相同的值也会被触发。

演示- 链接


0

一个正确的答案是不使用选择字段(如果您在重新选择相同的答案时需要执行某些操作。)

使用常规的div,按钮,显示/隐藏菜单创建一个下拉菜单。链接:https//www.w3schools.com/howto/howto_js_dropdown.asp

如果能够将事件侦听器添加到选项中,就可以避免。如果选择元素存在一个onSelect侦听器。而且,如果在选择字段上单击并没有严重触发mousedown,mouseup和在mousedown上同时单击全部,则全部关闭。


0

您需要在此处做一些事情,以确保即使再次选择相同的选项,它也能记住较旧的值并触发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);
    }
});

-1

请注意,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事件,的确,单击时我们丢失了选择的项目,如果列表很长,可能会很烦人,但这可能会在某种程度上对您有所帮助..


-1

如何在元素获得焦点时更改select的值,例如(使用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('');
    }
});

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.