javascript - 禁用聚焦按钮不会将焦点移至下一个可聚焦项目

标签 javascript jquery html

根据标题,我有一个按钮,只能点击 3 次,然后它会自行禁用(使用 jQuery)。

test.html

<div class="main">
  <input  class="one" type="text" />
  <button class="two" >If you hit me I will disabling myself...</button>
  <button class="three">...and focus should be moved to me!</button>
</div>

test.js

$('.two').on('keyup', function(event) {
    $(event.target).attr('disabled', true);
});

假设用户使用键盘按 Enter 键来执行此操作

当当前焦点按钮被禁用时,为什么焦点不会移动到下一个按钮?

这里有一个 fiddle 链接,显示了我的意思:https://jsfiddle.net/8dyk2b2m/

编辑 1

假设:

  1. 您不知道下一个可聚焦的项目是什么,但您希望它成为焦点
  2. 在某些情况下,下一个可聚焦项目不是当前项目的同级项目(next() 不起作用)

编辑2

我的 DOM 是动态生成的,这就是为什么我无法逐案管理,但我需要一个更通用的算法。对我来说,奇怪的事情仍然是,当我禁用当前聚焦的字段时,浏览器无法移动焦点。

编辑3

在下面的评论中,链接的解决方案来自此 StackOverflow question不涵盖所有情况,因为 disable action 会阻止触发 keyup 事件,而另一方面 - keydown 事件会早些时候,因为当按下按钮时,会创建一个新部分(显然是由其他地方的另一个 keydown 处理程序创建的,,我无法直接修改该处理程序)

最佳答案

好吧,终于得到了一个好的结果。我将在这里发布我的答案,以防万一有人想做同样的事情或改进它:

utils.js

function setFocusToClosestTabbableField(target, forward) {
    var promise = $timeout(function () {
        // Find the focused element in case of the given target is not valid
        var $focused = (target instanceof Element || target instanceof jQuery) ? $(target) : $(document.activeElement);

        // Check if the element is visible and enabled
        var isDisabled = $focused.is(':disabled');
        var isHidden   = $focused.is(':hidden');
        if (isDisabled || isHidden) {
            // If the focused element is disabled we have to enable it temporarily in order to find it 
            // in the list of the tabbable elements
            if (isDisabled) {
                $focused.attr('disabled', false);
            }

            // Retrieving now the list of tabbable elements and restore the status of the focused one if needed
            var $tabbables = $(':tabbable');
            if (isDisabled) {
                $focused.attr('disabled', true);
            }

            // Find the index of the current focused element and retrieve the index of the next on tabbable 
            // in the list
            var focusedIndex = $tabbables.index($focused);
            var nextIndex    = focusedIndex + ((forward == null || forward == true) ? 1 : -1);
            if (nextIndex < 0 || nextIndex > $tabbables.length - 1) {
                nextIndex = (forward == null || forward == true) ? 0 : $tabbables.length - 1;
            }

            // Get the next element focusable and put the focus on it
            $focused = $($tabbables.get(nextIndex));
            $focused.focus();

            // If the field is disable force a keyup event because the browser engine prevents it
            if (isDisabled) {
                $focused.keyup();
            }
        }

        // Return the focused element
        return $focused;
    }, 200);

    return promise;
}

ma​​in.js

// Registering both keydown and keyup since the browser will prevent the second one if the 
// focused field becomes disabled in a previously attache handler to the keydown event
$('body').on('keydown keyup', function() {
    var key = event.keyCode | -1
    var managedKeys = [
        -1,  // Manually triggered key event
        9,   // Tab
        13,  // Enter
        32   // Space
    ];

    // I check also Enter and Space since if I hit one of them while the focus is on a button and this 
    // button will get disabled, then I have to find the next tabbable field and put the focus on it
    if (managedKey.indexOf(key) > -1) {
        var $target = $(event.target);
        setFocusToClosestTabbableField($target, !event.shiftKey);
    }
});

注释

如果有人想讨论我的解决方案或想要改进它,请不要犹豫!干杯!

关于javascript - 禁用聚焦按钮不会将焦点移至下一个可聚焦项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48656681/

相关文章:

jquery - jQTouch - 无法粘贴到输入字段 : have anyone seen this?

html - CSS 过渡不一致

javascript - 从不同的文件夹加载图像

javascript - 函数带有标签和值的东西需要两个字符串

javascript - 选择类中的第一个子元素

javascript - CSS:在 IE 中使用 jquery 定位元素

javascript - 如何停止速度动画重复自身

javascript - 将 PHP 变量检索到 Bootstrap Modal

javascript - 下拉列表 fromtime 选择之前的时间 禁用 totime

javascript - Canvas 仅显示在 slider 的第一个图像上或连接到每个图像的底部