使用Tab键改善UX

在开发应用程序时,前端供应商很少关注用户如何使用浏览器提供的键盘功能。 我也不例外,但是有一天,我通过按“ Tab”和“ Shift + Tab”获得了有关UX和过渡的一项任务。

该任务的本质是透明且干净的:有一个界面,其界面显示在下面。 从概念上讲,一页可以包含2种不同的形式,并且要求“使用Tabs运行不能从一种形式转换为另一种形式”。

图片

如果浏览器知道如何“本地”阻止表单焦点,那么一切都会很好。 下图显示了一个示例,其中橙色的“ border” om标记当前元素,而灰色的则是前一个元素。

图片

如您所见,“本机”行为不符合要求。 因此,让我们解决这个问题。 解决方案并不复杂,因此请考虑一下。

如果有一些“门”可以阻止焦点从最后一个带有“ tabindex”的元素(带有“ Tab”)或第一个(带有“ Shift + Tab”)的元素“跳出”,或者默认情况下支持焦点,那将是理想的。 因此,本质很简单:我们的“门”是隐藏的“输入元素”,它们在“ onFocus”事件期间作为参数接收“事件”事件,并将焦点返回到它来自的元素。 下图。

图片

使用“事件”对象的“ relatedTarget”属性来获取上一个元素是可行的。 可视化以下解决方案。

图片

这是代码本身。 值得注意的是,没有“ ES6 +”语法,因为其思想是在不连接Babel等不同“编译器”的情况下,使用不同的浏览器支持代码。

function getGateInput(handleTabOut) { var input = document.createElement("input"); // not visibiliy:hidden or display:none as need to focus on this element var hiddingStyle = "opacity: 0;cursor: none;position: absolute;top: -10px;left: -10px;"; input.setAttribute("style", hiddingStyle); input.addEventListener("focus", handleTabOut); return input; } 

没什么复杂的:创建“输入”,设置样式以“隐藏”我们的“门”。 此处,由于浏览器未将“制表符”集中在此类元素上,因此未使用“显示:无”。 由于此行为,需要使该元素透明并将其移出浏览器窗口。

 function getTabOutHandler(element, GATES) { return function(event) { var relatedTarget = event.relatedTarget || event.fromElement; var target = event.target; var gatesTrapped = target === GATES[0] || target === GATES[1]; if (gatesTrapped && isChild(relatedTarget, element)) { event.preventDefault(); relatedTarget.focus(); } }; } 

要将焦点返回到上一个项目,请使用getTabOutHandler。 这就是HOC 。 它的第一个参数是我们的容器(在其周围设置“门”),第二个参数期望使用getGateInput创建的“门”数组。 该函数返回事件处理程序,该事件处理程序根据上述原理工作。

为了使焦点进入容器,我们需要打开和关闭“门”。 我们将通过设置“ tabindex”属性来做到这一点。 (-1-不使用制表符聚焦,0-根据流聚焦)

 function moveGates(open, GATES) { GATES[0].setAttribute("tabindex", open ? -1 : 0); GATES[1].setAttribute("tabindex", open ? -1 : 0); } 

为了控制门,我们将设置一个处理程序,该处理程序将“监听” Tab(代码9),如果焦点元素(activeElement)在容器内,则关闭“门”,否则将其打开。

 window.addEventListener("keydown", function(event) { if (event.keyCode === 9) { if (isChild(document.activeElement, element)) { moveGates(false, GATES); } else { moveGates(true, GATES); } } }); 

合计


考虑了一种将焦点锁定在表单中的方法,该方法包括将焦点返回到先前的焦点元素。 为了“捕获”焦点,我们使用了隐藏的“输入元素”,使用“ tabindex”控制了焦点。 上面的代码是我为解决问题而编写的tab-out-catcher库的一部分。 使用示例可以在这里找到。 还有一个针对React应用程序的解决方案

Source: https://habr.com/ru/post/zh-CN469749/


All Articles