Есть ли событие DOM, которое срабатывает, когда элемент выбора HTML закрыт?
Я ищу событие DOM, которое я могу прослушивать с помощью JavaScript, когда открывается выбранный элемент (но никаких параметров не изменен) закрывается нажатием элемента select где-нибудь (где угодно) на стр.
Это не событие blur
для выбора, так как выбор сохраняет фокус. Точно так же это не событие focus
какого-либо другого элемента или документа, или mousedown
или click
в окне, документе или теле.
Это не событие change
для выбора, так как никакая опция в выборе не была изменена.
Меня не интересуют устаревшие Internet Explorers - просто что-то для работы в современных браузерах, совместимых с стандартами. Однако запатентованные хаки могут быть полезны.
Я создал JSFiddle, чтобы продемонстрировать проблему: http://jsfiddle.net/premasagar/FpfnM/
- Нажмите кнопку выбора на панели "Результат"
- Нажмите на текст с надписью "ЗДЕСЬ" (или где-нибудь еще) одним щелчком мыши и посмотрите, добавлено ли какое-либо событие в журнал. В последних версиях Chrome или Firefox нет события.
Итак, вопрос: Какой JavaScript можно добавить, чтобы регистрировать событие при нажатии кнопки выбора?
(Я задал аналогичный, но другой вопрос здесь:
JavaScript на iOS: открытие элемента выбора HTML)
Ответы
Ответ 1
К сожалению, нет стандартного события для того, чтобы знать, когда окно выбора закрыто или открыто, поэтому ваш код будет довольно волосатым с размещением для разных браузеров. Тем не менее, я думаю, что это можно сделать, и я получил что-то для вас в Firefox, используя событие mouseup
:
http://jsfiddle.net/FpfnM/50/
В Firefox (и я предполагаю Chrome) вам нужно будет тщательно отслеживать состояние этого элемента. Когда нажата клавиша escape
или событие blur
, вам необходимо обновить состояние, чтобы идентифицировать его как закрытое. Я не реализовал это в своей демонстрации, и вы можете увидеть, что произойдет, если вы нажмете escape, а не щелкаете по выбору.
В Safari стало проще, где событие mousedown
в select означает открытие выбора, и любое закрытие выбора означает событие click
.
Если вы найдете браузер, в котором ни одно из этих событий не срабатывает, вы можете попробовать еще один трюк. Поскольку виджеты форм, такие как select и textarea, часто отображаются операционной системой, а не внутри браузера, возможно, что вы можете взаимодействовать с ними, а некоторые сообщения могут не попасть в обработчик событий браузера. Если бы вы разместили прозрачную текстовую область, закрывающую экран при более низком z-индексе, когда поле выбора открыто, вы можете использовать его для отслеживания этого закрытого клика. Он может улавливать события, которые может отсутствовать элемент DOM браузера.
Update:
Chrome видит мульдауны при выборе, когда он открывается, и кнопку мыши в документе, когда нажимается страница с помощью выбора. Здесь версия, которая работает с Chrome:
http://jsfiddle.net/FpfnM/51/
Опять же, вам нужно будет сделать некоторое обнаружение браузера, чтобы справляться с правильным поведением в каждом из них. Один улов с Chrome, в частности, заключается в том, что ни одно событие не запускается, когда вы нажмете второй раз, чтобы закрыть его. Однако вы можете обнаружить щелчок на странице.
Краткое описание:
Chrome/Safari: select.mousedown on open, document.mouseup on close
Firefox: select.click on open, document.mouseup on close
IE8/IE7: select.click on open, document.mouseup on close
Существует множество ошибок для других событий, которые означают закрытие (escape keypress, blur и т.д.), но это минимум для обработки сценария, когда пользователь нажимает кнопку выбора, а затем щелкает области документа.
Надеюсь, это поможет!
Ответ 2
Я получил следующие события, следуя указаниям вашего JSFiddle на письмо:
BODY, mousedown, STRONG
#document, mousedown, STRONG
window, mousedown, STRONG
SELECT, blur, SELECT
BODY, click, STRONG
#document, click, STRONG
window, click, STRONG
Это все события, которые были вызваны, когда я нажал "ЗДЕСЬ" после того, как меню выбора уже было в фокусе и расширено. Это было в последней версии Chrome.
Должно ли какое-либо из них достаточно для ваших целей?
Изменить: если вы хотите, чтобы ваш элемент Select потерял фокус, установите глобальную переменную Javascript "selectFocused" и установите для нее значение False. Установите его значение "Истина", когда ваше меню "Выбор" получает фокус, и установите значение "False" при возникновении любого из указанных выше событий. 'selectFocused' теперь можно использовать в любом месте вашего кода, чтобы определить, имеет ли ваш элемент Select в данный момент фокус, и когда он меняет значения, вы знаете, что ваш элемент Select был выбран или не выбран.
Ответ 3
Мой первый инстинкт - это немного окольный путь, чтобы достичь этого, было бы использовать код, который вы обычно используете для закрытия выпадающего меню (пользовательского), нажимающего снаружи:
function clickInBody(){
functionToCallOnBlur();
}
function clickInBodyStop(event){
event.stopPropagation();
}
Затем в теге body вы добавляете onClick="clickInBody()"
, а в элементе select вы добавляете onClick="clickInBodyStop(event)"
. Это должно вызывать событие каждый раз, когда вы нажимаете на страницу, но если вы нажмете на тег select, он остановит распространение и не вызовет functionToCallOnBlur()
Ответ 4
precondition: использование jQuery! Это, вероятно, только решает часть вашей проблемы, но если вы хотите, чтобы событие срабатывало при нажатии элемента, вы можете использовать оверлейный div.
Когда пользователь нажимает на поле выбора:
$('#mySelectBox').click(function () {
var myOverlayDiv = $('<div id="overlayDiv" class="overlayDiv"></div>')
.click(function () {
// call your "select lost focus" function here
// which should include $('#overlayDiv').remove() somewhere!
})
.show()
.appendTo(document.body);
});
Стиль для наложения div:
.overlayDiv {
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
opacity:0;
z-index:1000;
}
Вам нужно убедиться, что ваше меню выбора является более высоким Z-индексом, поэтому, когда пользователь нажимает на меню, они получают меню, а не наложение div:)
Ответ 5
Если у вас более 1 раскрывающегося списка:
$("select").each(function () {
var initDropdown = $(this);
initDropdown.data("open", false);
console.log(this.name + " closed");
initDropdown.on("blur", function () {
var blurDdopdown = $(this);
blurDdopdown.data("open", false);
console.log(this.name + " closed");
});
});
$("select").bind("click", function () {
var clickedDropdown = $(this);
if (clickedDropdown.data('open') == false) {
clickedDropdown.data('open', true);
console.log(this.name + " open");
} else {
clickedDropdown.data('open', false);
console.log(this.name + " closed");
}
});