it-swarm.com.ru

Есть ли событие onSelect или эквивалент для HTML <select>?

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

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

Теперь doSomething() срабатывает только при изменении выбора .

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

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

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

Обновление:

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

181
ePharaoh

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

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

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

80
freezethrower

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

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

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

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

54
Alex

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

11
Cody

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

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

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

8
Darryl Hein

Подход onclick не совсем плох, но, как уже было сказано, он не будет срабатывать, когда значение не изменяется щелчком мыши.
Однако можно вызвать событие onclick в событии onchange.

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

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

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

5
Tyler Stahlhuth

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

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

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

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

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

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

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

3
Brandon Montgomery

Поэтому моей целью было иметь возможность выбрать одно и то же значение несколько раз, что по существу перезаписывает функцию 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
Sean D

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

2
David Polehonski

Что работает для меня:

<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 () при изменении параметра, а onclick вызывает doSomething (), когда событие onchange равно false, другими словами, когда вы выбираете ту же опцию

1
antoniobh

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

используйте jquery:

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

<script>
    $('.target').change(function() { doSomething(); });
</script>
1
ladookie
<script>
function abc(selectedguy) {
alert(selectedguy);
}
</script>

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

Здесь у вас есть возвращенный индекс, и в коде js вы можете использовать этот возврат с одним переключателем или чем угодно.

1
JMFDB

Замечательная вещь в теге 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
Tzshand

Попробуйте это (событие срабатывает точно при выборе опции, без изменения опции):

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

http://jsbin.com/dowoloka/4

1
WebBrother

вы должны попробовать использовать option:selected

$("select option:selected").click(doSomething);
1
Pragnesh Chauhan

в первую очередь вы используете onChange в качестве обработчика событий, а затем используете переменную flag, чтобы она выполняла функцию, которую вы хотите каждый раз, когда вносите изменения

<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>
1
Paula George
<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
xicooc

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

Создайте выпадающее меню с обычными элементами div, button, show/hide. Ссылка: https://www.w3schools.com/howto/howto_js_dropdown.asp

Этого можно было бы избежать, если бы можно было добавлять прослушиватели событий в параметры. Если был прослушиватель onSelect для элемента select. И если нажатие на поле выбора не отягчает работу mousedown, mouseup, и нажмите все одновременно на mousedown.

0
Shinjitsu

Попробуй это:

<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
Jesús López

Я столкнулся с аналогичной необходимостью и закончил тем, что написал директиву angularjs для того же самого -

ссылка на guthub - angular select

Использовал element[0].blur();, чтобы убрать фокус с тега select. Логика заключается в том, чтобы вызвать размытие при втором щелчке раскрывающегося списка.

as-select срабатывает даже тогда, когда пользователь выбирает то же значение в раскрывающемся списке.

ДЕМО - ссылка

0
Nithin Kumar Biliya

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

Я решил сделать что-то более простое, чем взлом альтернатив onChange(), используя другие события, которые на самом деле не предназначались для этой цели (blur, click и т.д.)

То, как я это решил:

Просто предварительно ожидайте тег-опцию-заполнитель, например select, который не имеет значения.

Таким образом, вместо использования следующей структуры, которая требует хакерских альтернатив:

<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 и ​​обнаружил, что этот выбор дизайна значительно упростил мой код. Я потратил часы на эту проблему, прежде чем освоился с этим решением, и мне не пришлось переписывать много кода. Однако, если бы я использовал альтернативные варианты, мне пришлось бы учитывать случаи Edge, предотвращать двойное срабатывание запросов ajax и т.д. Это также не портит поведение браузера по умолчанию в качестве приятного бонуса (протестировано на мобильных устройствах). браузеры также).

Иногда вам просто нужно сделать шаг назад и подумать над общей картиной для самого простого решения.

0
dsignr

Давным-давно, но в ответ на первоначальный вопрос, это поможет? Просто поместите onClick в строку SELECT. Затем поместите то, что вы хотите, чтобы каждый OPTION делал в строках OPTION. то есть:

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