Preventing tab to cycle through address bar

前端 未结 8 1544
一生所求
一生所求 2021-02-20 06:54

I realize this is probably an accessibility issue that may best be left alone, but I\'d like to figure out if it possible to prevent the tab from visiting the address bar in the

8条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2021-02-20 07:44

    Not sure if this is still a issue, but I implemented my own solution that does not use jQuery, can be used in the case when all the elements have tabindex="0", and when the DOM is subject to change. I added an extra argument for a context if you want to limit the tabcycling to a specific element containing the tabindex elements.

    Some brief notes on the arguments:

    min must be less than or equal to max, and contextSelector is an optional string that if used should be a valid selector. If contextSelector is an invalid selector or a selector that doesn't match with any elements, then the document object is used as the context.

    function PreventAddressBarTabCyle(min, max, contextSelector) {
        if( isNaN(min) ) throw new Error('Invalid argument: first argument needs to be a number type.')
        if( isNaN(max) ) throw new Error('Invalid argument: second argument needs to be a number type.')
        if( max < min ) throw new Error('Invalid arguments: first argument needs to be less than or equal to the second argument.')
        min = min |0;
        max = max |0;
        var isDocumentContext = typeof(contextSelector) != 'string' || contextSelector == '';
    
        if( min == max ) {
            var tabCycleListener = function(e) {
                if( e.keyCode != 9 ) return;
    
                var context = isDocumentContext ? document : document.querySelector(contextSelector);
                if( !context && !('querySelectorAll' in context) ) {
                    context = document;
                }
    
                var tabindexElements = context.querySelectorAll('[tabindex]');
                if( tabindexElements.length <= 0 ) return;
                var targetIndex = -1;
                for(var i = 0; i < tabindexElements.length; i++) {
                    if( e.target == tabindexElements[i] ) {
                        targetIndex = i;
                        break;
                    }
                }
                // Check if tabbing backward and reached first element
                if( e.shiftKey == true && targetIndex == 0 ) {
                    e.preventDefault();
                    tabindexElements[tabindexElements.length-1].focus();
                }
                // Check if tabbing forward and reached last element
                if( e.shiftKey == false && targetIndex == tabindexElements.length-1 ) {
                    e.preventDefault();
                    tabindexElements[0].focus();
                }
            };
        } else {
            var tabCycleListener =  function(e) {
                if( e.keyCode != 9 ) return;
    
                var context = isDocumentContext ? document : document.querySelector(contextSelector);
                if( !context && !('querySelectorAll' in context) ) {
                    context = document;
                }
    
                var tabindex = parseInt(e.target.getAttribute('tabindex'));
                if( isNaN(tabindex) ) return;
                // Check if tabbing backward and reached first element
                if (e.shiftKey == true && tabindex == min) {
                    e.preventDefault();
                    context.querySelector('[tabindex="' + max + '"]').focus();
                } 
                // Check if tabbing forward and reached last element
                else if (e.shiftKey == false && tabindex == max) {
                    e.preventDefault();
                    context.querySelector('[tabindex="' + min + '"]').focus();
                }
            };
        }
        document.body.addEventListener('keydown', tabCycleListener, true);
    }
    

    More notes:

    If min is equal to max, then tab cycling will occur naturally until the last element in the context is reached. If min is strictly less than max, then tabbing will cycle naturally until either the min or the max is reached. If tabbing backwards and the min is reached, or tabbing forward and the max is reached, then the tabbing will cycle to the min element or max element respectively.

    Example usage:

    // For all tabindex elements inside the document
    PreventAddressBarTabCyle(0,0);
    // Same as above
    PreventAddressBarTabCyle(1,1);
    // NOTE: if min == max, the tabindex value doesn't matter
    //    it matches all elements with the tabindex attribute
    
    // For all tabindex elements between 1 and 15
    PreventAddressBarTabCyle(1,15);
    // For tabindex elements between 1 and 15 inside
    //   the first element that matches the selector: .some-form
    PreventAddressBarTabCyle(1,15, '.some-form');
    // For all tabindex elements inside the element
    //   that matches the selector: .some-form2
    PreventAddressBarTabCyle(1,1, '.some-form2');
    

提交回复
热议问题