Переключить видимость элемента onblur и onclick - PullRequest
0 голосов
/ 23 октября 2019

У меня есть элемент div, используемый в качестве переключателя, и элемент select, который должен отображаться / скрываться таким образом:

(1) При нажатии на переключатель, selectдолжен отображаться и фокусироваться, если он был скрыт

(2) При нажатии на переключатель, select должен быть скрыт, если он был виден

(3) Когда селектор теряет фокус, он должен быть скрыт.

Теперь есть этот крайний случай, когда select имеет фокус и пользователь нажимает на переключатель - тогда оба события, onclick и onblur, запускаются и отменяют друг другаПо крайней мере, в Firefox:

<div id="toggle">toggle</div>
<div>foobar</div>
<select id="select" multiple>
    <option>foo</option>
    <option>bar</option>
</select>
document.getElementById('toggle').onclick = function () {
    var select = document.getElementById('select');
    select.style.display = select.style.display === 'none' ? 'inline' : 'none';
        select.focus();
    };

document.getElementById('select').onblur = function () {
    this.style.display = 'none';
};

https://jsfiddle.net/2wrxykpd/

Я пытался проверить event.explicitOriginalTarget в функции onblur (онлайн скрыть select, если цель onblur событие не является переключателем), которое будет работать в Firefox, но не в Chrome.

Так что же будет правильным для этого?

Ответы [ 2 ]

0 голосов
/ 23 октября 2019

Я сам нашел решение, также см. Этот связанный вопрос .

Идея состоит в том, чтобы добавить к переключателю события mousedown и mouseup. Тогда порядок выполнения будет

(1) toggle.onmousedown

(2) select.onblur

(3) toggle.onmouseup

(4) toggle.onclick

То есть внутри событий mousedown / mouseup мы можем установить и сбросить флаг игнорирования;флаг будет установлен только внутри onblur, в onclick он уже будет сброшен.

Итак, мы получили

document.getElementById('toggle').onclick = function () {
  var select = document.getElementById('select');
  select.style.display = select.style.display === 'none' ? 'inline' : 'none';
  select.focus();
};
document.getElementById('toggle').onmousedown = function () {
  document.getElementById('select').ignoreClickEvent = true;
};
document.getElementById('toggle').onmouseup = function () {
  document.getElementById('select').ignoreClickEvent = false;
};

document.getElementById('select').onblur = function () {
  if (!this.ignoreClickEvent) {
    this.style.display = 'none';
  }
};

https://jsfiddle.net/ezt0sonj/

0 голосов
/ 23 октября 2019

Вы можете выполнить привязку, чтобы сфокусироваться на переключателе, а затем проверить по связанной цели:

var select = document.getElementById('select');
var toggle = document.getElementById('toggle');

toggle.addEventListener('focus', function (event) {
	if (event.relatedTarget !== select) {
  	var isHidden = select.classList.toggle('hidden')

    if (!isHidden) {
      select.focus();
    }
  }
  
  toggle.blur()
});

select.addEventListener('blur', function () {
	select.classList.add('hidden')
});
.hidden {
  display: none !important;
}
<div>
  <button id="toggle">toggle</button>
</div>
<div>
  <select id="select" class="hidden" multiple>
    <option>foo</option>
    <option>bar</option>
  </select>
</div>
...