Есть ли событие onSelect или эквивалент для HTML <select>? - PullRequest
181 голосов
/ 15 марта 2009

У меня есть форма ввода, которая позволяет мне выбирать из нескольких вариантов и что-то делать, когда пользователь меняет выбор. Например,

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

Теперь doSomething() срабатывает только тогда, когда выбор меняет .

Я хочу вызвать doSomething(), когда пользователь выбирает любую опцию, возможно, снова такую ​​же .

Я пытался использовать обработчик onClick, но он срабатывает до того, как пользователь начинает процесс выбора.

Итак, есть ли способ вызвать функцию при каждом выборе пользователем?

Обновление:

Ответ, предложенный Дэррилом, казалось, работает, но он не работает последовательно. Иногда событие запускается, как только пользователь щелкает раскрывающееся меню, даже до того, как пользователь завершил процесс выбора!

Ответы [ 29 ]

80 голосов
/ 22 октября 2011

Вот самый простой способ:

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

Работает как с выделением мыши, так и с клавишами вверх / вниз, когда выбор сфокусирован.

54 голосов
/ 13 сентября 2012

Мне нужно что-то точно такое же. Вот что у меня сработало:

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

Поддерживает это:

когда пользователь выбирает любую опцию, возможно, снова тот же

11 голосов
/ 02 февраля 2012

У меня была такая же проблема, когда я создавал дизайн несколько месяцев назад. Я нашел решение использовать .live("change", function()) в сочетании с .blur() для элемента, который вы используете.

Если вы хотите, чтобы он что-то делал, когда пользователь просто щелкает, а не изменяет, просто замените change на click.

Я назначил в раскрывающемся списке идентификатор 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 ()

8 голосов
/ 15 марта 2009

Просто идея, но возможно ли навести на клик каждый из <option> элементов?

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

Другим вариантом может быть использование onblur для выбора. Это будет срабатывать каждый раз, когда пользователь щелкает мышью вдали от выбора. На данный момент вы можете определить, какой вариант был выбран. Чтобы это срабатывало даже в нужное время, нажатие опции может размыть поле (сделать что-то еще активным или просто .blur () в jQuery).

6 голосов
/ 22 ноября 2012

Подход 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 голосов
/ 09 июня 2016

Собираюсь расширить ответ 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 каждый раз, когда они выбирают любую опцию, включая более раннюю опцию.

Недостатком этого подхода является то, что он лишает возможности вкладываться в выпадающий список и использовать клавиши со стрелками для выбора значения. Это было приемлемо для меня, так как все пользователи все время кликают до конца вечности.

4 голосов
/ 21 января 2013

Чтобы правильно инициировать событие каждый раз, когда пользователь выбирает что-то (даже ту же опцию), вам просто нужно обмануть поле выбора.

Как уже говорили другие, укажите отрицательный 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>

Рабочую демонстрацию можно посмотреть здесь .

4 голосов
/ 24 июля 2009

Если вам действительно нужно, чтобы это работало так, я бы сделал это (чтобы убедиться, что оно работает с помощью клавиатуры и мыши)

  • Добавить обработчик события onfocus к селекту, чтобы установить «текущее» значение
  • Добавить обработчик события onclick в select для обработки изменений мыши
  • Добавить обработчик события onkeypress в select для обработки изменений клавиатуры

К сожалению, onclick будет запускаться несколько раз (например, при закрытии выбора ... и при выборе / закрытии), и при нажатии клавиши onkey может произойти ничего ...

<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>
3 голосов
/ 08 апреля 2009

На самом деле события onclick НЕ будут срабатывать, когда пользователь использует клавиатуру для изменения выбора в элементе управления select. Возможно, вам придется использовать комбинацию onChange и onClick, чтобы получить поведение, которое вы ищете.

2 голосов
/ 10 апреля 2012

Что я сделал, столкнувшись с подобной проблемой, так это то, что я добавил «onFocus» в поле выбора, которое добавляет новый универсальный параметр («выбрать параметр» или что-то подобное) и по умолчанию выбрал его в качестве выбранного параметра.

...