Подтвердить что ты не робот

Ограничить привязку tabindex к разделу страницы

Ситуация:

У меня есть веб-страница, которая открывает модальные окна (световые короба), которые содержат формы, в которых пользователь может вводить данные. Обычно пользователи перемещаются с помощью клавиатуры, перемещаясь из одного поля в другое.

Проблема:

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

Вопрос:

Как я могу ограничить перемещение, используя кнопку вкладки только для элементов в окне формы?

Единственное, о чем я могу думать, это использовать Javascript для установки tabindex=-1 для всех элементов формы (и других элементов с возможностью фокусировки) при открытии модального окна, а затем вернуть значения tabindex к их предыдущим значениям, когда модальные окно закрыто. Есть ли более простой/лучший способ?

4b9b3361

Ответ 1

Нет, это единственный способ.

  • Найдите все элементы, у которых tabIndex больше, чем -1 & dagger; и не принадлежат вашему модальному.
  • Создайте массив & ddagger; и заполните его ссылками на каждый элемент вместе с его оригинальным tabIndex.
  • Установите каждый элемент tabIndex на -1, чтобы он больше не мог получать фокус с клавиатуры.
  • Когда модальное диалоговое окно закрывается, перебирайте массив и восстанавливайте исходный tabIndex.

Вот быстрая демонстрация:

function isDescendant(ancestor, descendant) {
  do {
    if (descendant === ancestor) return true;
  } while (descendant = descendant.parentNode);
  return false;
}

var tabIndexRestoreFunctions;
var lastFocused;

document.getElementById("btn-show-modal").addEventListener("click", function(e) {
  lastFocused = document.activeElement;
  var modal = document.querySelector(".modal");
  tabIndexRestoreFunctions = Array.prototype
  // get tabable items which aren't children of our modal
  .filter.call(document.all, o => o.tabIndex > -1 && !isDescendant(modal, o))
  // iterate over those items, set the tabIndex to -1, and 
  // return a function to restore tabIndex
  .map(o => {
    var oldTabIndex = o.tabIndex;
    o.tabIndex = -1;
    return () => o.tabIndex = oldTabIndex;
  });
  // show modal
  modal.classList.add("shown");
  // focus modal autofocus
  modal.querySelector("[autofocus]").focus();
});

document.getElementById("btn-close-modal").addEventListener("click", function(e) {
  // restore tabs
  tabIndexRestoreFunctions && tabIndexRestoreFunctions.forEach(f => f());
  tabIndexRestoreFunctions = null;
  // hide modal
  document.querySelector(".modal").classList.remove("shown");
  // restore focus
  lastFocused && lastFocused.focus();
});
.modal {
  display: none;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background-color: rgba(128, 128, 128, .75);
}
.modal.shown {
  display: flex;
}
.modal-content {
  margin: auto;
  width: 500px;
  padding: 30px;
  border: 1px solid #333;
  background-color: #fdfdfd;
}
<label>test
  <input autofocus />
</label>
<button>dummy button</button>
<hr/>
<button id="btn-show-modal">open modal</button>
<div class="modal">
  <div class="modal-content">
    <label>test
      <input autofocus />
    </label>
    <button id="btn-close-modal">close modal</button>
  </div>
</div>

Ответ 2

Как насчет улавливания tab-key? На последнем элементе, а затем положите фокус на первый и наоборот shift-tab

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

inputs=".editing, input, textarea, button, a, select"
no_tab="[type='hidden'], :disabled"

$focusable=dlg.$form.find(inputs).not(no_tab)


$fa_first=$focusable.first()
$fa_last=$focusable.last()

$fa_last.on("keydown", (evt) =>
    if evt.keyCode==9 && ! evt.shiftKey
        $fa_first.focus()
        evt.preventDefault()
        false
)
$fa_first.on("keydown", (evt) =>
    if evt.keyCode==9 && evt.shiftKey
        $fa_last.focus()
        evt.preventDefault()
        false
)

small edit: заменил my на "unibind()" (=.off(x).on(x)) функция через jQuery "on()"

Ответ 3

Посмотрите jQuery BlockUI Plugin. У них пример с использованием модального блока с двумя кнопками, и он также ограничивает табуляцию.

Он может или не может работать из-за коробки с вашими модальными окнами, но стоит взглянуть вместо того, чтобы реализовать свою собственную работу.

Ответ 4

Несмотря на то, что это старый пост, я искал решение этой проблемы и сделал следующее для его решения.

Используя JQuery, я отключил все поля ввода в разных формах и div, как только откроется модальное окно (кроме тех, которые есть в самой модальной форме).

$('#formId :input').prop('disabled',true);

когда модальная форма закрыта, вы можете снова включить элементы ввода.

Отключенные поля не учитываются при "табуляции" вокруг вашей страницы.