Скрыть функцию всплывающего окна, возвращая функцию открытого всплывающего окна - PullRequest
0 голосов
/ 17 марта 2020

Я хочу сделать всплывающее окно активируемым кнопкой, которая уменьшает непрозрачность всех других элементов. Когда пользователь щелкает мышью из поля, оно должно исчезнуть, а непрозрачность должна go вернуться к нормальной. Однако эти две функции конфликтуют друг с другом. Требуется, чтобы я нажал кнопку ДВАЖДЫ для вызова showBox(). И щелчок «из коробки» ничего не делает, если я не вызову hideOnClickOutside(document.querySelector('div')); в консоли браузера.

Почему я должен дважды щелкнуть «Новое аудио» и почему hideOnClickOutside() не работает, если его не повторно вызывать?

function showBox() {
  document.body.style.opacity = "0.5";
  document.querySelector('div').style.display = "block";
}

document.querySelector('button').addEventListener('click', showBox);
const isVisible = elem => !!elem && !!(elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length); // source (2018-03-11): https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js
function hideOnClickOutside(element) {
  const outsideClickListener = event => {
    if (!element.contains(event.target) && isVisible(element)) { // or use: event.target.closest(selector) === null
      element.style.display = 'none';
      removeClickListener()
      document.body.style.opacity = "1";
    }
  }

  const removeClickListener = () => {
    document.removeEventListener('click', outsideClickListener)
  }

  document.addEventListener('click', outsideClickListener)
}

hideOnClickOutside(document.querySelector('div'));
<button>New Audio</button>

<div style="display: none">
  <button>Record Directly</button>
</div>

hideOnClickOutside() функция была взята из другой ответ StackOverflow

Редактировать

Я понял что для этого требуется два щелчка, потому что при первом щелчке вызывается showBox() , но сразу после него, как и outsideClickListener, и в этот момент элемент становится СЕЙЧАС видимым, и пользователь нажал «снаружи» элемента , Это отменяет изменения стиля showBox().

1 Ответ

1 голос
/ 18 марта 2020

Самое простое решение - сохранить ссылку на «Новое аудио» button и проверить, является ли это target кликом по document. Если это так, то return из функции без обновления DOM.

const button = document.querySelector('button')
button.addEventListener('click', showBox);
// ..
function hideOnClickOutside(element) {
  const outsideClickListener = event => {
    if (event.target === button) return 
// ..

Имейте в виду, что при текущем имеющемся коде функция hideOnClickOutside работает только до первого раза isVisible Значение true, а target не равно button, так как вы удаляете прослушиватель событий при этом условии.

function showBox(e) {
  document.body.style.opacity = "0.5";
  document.querySelector('div').style.display = "block";
}
const button = document.querySelector('button')
button.addEventListener('click', showBox);
const isVisible = elem => !!elem && !!(elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length); // source (2018-03-11): https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js
function hideOnClickOutside(element) {
  const outsideClickListener = event => {
    if (event.target === button) return 
    if (!element.contains(event.target) && isVisible(element)) { // or use: event.target.closest(selector) === null
      element.style.display = 'none';
      removeClickListener()
      document.body.style.opacity = "1";
    }
  }

  const removeClickListener = () => {
    document.removeEventListener('click', outsideClickListener)
  }

  document.addEventListener('click', outsideClickListener)
}

hideOnClickOutside(document.querySelector('div'));
<button>New Audio</button>

<div style="display: none">
  <button>Record Directly</button>
</div>

Другая проблема заключается в том, что после вызова функции showBox вы, вероятно, захотите, чтобы button рассматривался снаружи. Давайте сделаем рефакторинг вашего кода для хранения ссылок на showButton и box, добавим флаг к disable showButton и добавим прослушиватель событий в документ только при нажатии showButton и удалим только прослушиватель событий когда отображается поле.

Позже вы можете выполнить рефакторинг, чтобы соответствовать вашему конкретному случаю использования. Идея состоит в том, чтобы подумать о различных состояниях, в которых может находиться это приложение, и создать функции для управления этим состоянием.

const box = document.querySelector('#box');
const showButton = document.querySelector('#show-button');
showButton.addEventListener('click', showBox);

let isDisabled = false;
const isVisible = elem => !!elem && !!(elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length); // source (2018-03-11): https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js

function toggleDisabled(bool) {
    showButton.attributes.disabled = bool;
    isDisabled = bool;
}

function toggleDisplay(display, opacity) {
    document.body.style.opacity = opacity;
    box.style.display = display;
}

function showBox(event) {
  if (!isDisabled) {
    event.preventDefault();
    event.stopPropagation();
    toggleDisplay("block", 0.5);
    toggleDisabled(true);
    document.addEventListener('click', outsideClickListener);
  }
}

function outsideClickListener(event) {
  if (!box.contains(event.target) && isVisible(box)) { // or use: event.target.closest(selector) === null
    toggleDisplay("none", 1);
    toggleDisabled(false);
    document.removeEventListener('click', outsideClickListener)
  }
}
<button id="show-button">New Audio</button>

<div id="box" style="display: none">
  <button>Record Directly</button>
</div>
...