Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!

Ситуация с табами очень напоминает историю про хакера и солонки в кафе.Вы под лозунгом «всё не предусмотришь» предлагаете всё делать по принципу «и так сойдёт»?
Смысл статьи не в том, чтобы сделать полностью рабочую версию в виде плагина. В этой статье рассказывается, как именно это можно реализоватьНе важно, насколько хорошо исполнено что-то, если оно плохо делает то, для чего предназначается.
mounted() {
// подписываемся на событие keydown
if (typeof document !== 'undefined') {
document.body.addEventListener('keydown', this.handleTabKey)
}
}
destroyed() {
// отписываемся
if (typeof document !== 'undefined') {
document.body.removeEventListener('keydown', this.handleTabKey)
}
},
methods: {
handleTabKey(e) {
if (e.keyCode === 9 && this.modals.length) {
e.preventDefault() // если есть окна, глушим Tab/Shift-Tab
}
}
// пока полностью отключаю Tab. Надо подумать, как лучше его глушить только вне активного окна.
}
mounted() {
if(this.$el.focus) {
this.$el.focus() // фокус переводим на окно, при монтировании
}
},
render(h) {
...
return h('div', {
style,
attrs: { tabindex: -1}, // цепляем tabindex
class: ['vu-modal__cmp', {
...
},
пока полностью отключаю Tab. Надо подумать, как лучше его глушить только вне активного окна.Это как раз понятно:
function nodeContains(parentNode, node) {
return parentNode && node && (node === parentNode || contains());
function contains() {
return parentNode.contains ? parentNode.contains(node) : !!(parentNode.compareDocumentPosition(node) & Node.DOCUMENT_POSITION_CONTAINED_BY);
}
}
if (nodeContains(activeWindow.node, document.activeElement)) {
// сфокусированный элемент находится в activeWindow
} else {
// сфокусированный элемент находится вне activeWindow
}
Я делал однопиксельные скрытые поля ввода в начале и конце модального окна, которые при фокусе перекидывали фокус обратно в окно.
Так же, чтобы нельзя было из адресной строки перейти табом к контролам позади модального окна, можно вставить спрятанные поля ввола в начале и конце документа.
А как быть в случае, если поп-ап является частью формы?
К примеру в нём происходит выбор адреса или режима работы. (реальный случай)
То есть как раз такой случай, когда поп-ап должен иметь доступ к родительской модели. И при этом в разметке он там совсем плохо размещается.
Решал такие задачи через vue-portal, но у него минусов хватает.
// запускаем из формы окно
this.$modals.open({
component: ModalForm // компонент, отображаемый в окне, где происходит выбор чего-то,
props: {
params1, // родительские данные, которые будут использоваться в окне
params2,
...
},
onClose(data) { // data мы будем передавать при закрытии окна
// здесь мы уже в родительской области видимости, и используем data как нам нужно
...
return false // если здесь мы вернем false, то окно не закроется. Например при каком-то условии, по значениям из data
}
})
// а в окне, например, при клике по кнопке 'Сохранить' вызываем
this.$modals.close(data)
// тем самым запуская закрытие окна, но прежде чем окно закроется, запускается коллбек onClose, если он есть в опциях окна, c переданными в него данными
Ох уж эти модальные окна или почему я полюбил render-функции в VueJs