Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Tab" key = bug #1237

Closed
meneldil opened this issue May 21, 2015 · 38 comments
Closed

"Tab" key = bug #1237

meneldil opened this issue May 21, 2015 · 38 comments

Comments

@meneldil
Copy link

Hello,
I discovered a bug.

If the website contains a link or a form when you press the "tab" key, the browser goes directly to the section concerned but the navigation is completely broken.

@alvarotrigo
Copy link
Owner

Yeah right.
I was aware of it.

The only solution is not simple... Depending on the browser some elements are able to receive the focus on tab and others don't.

In order to prevent it, fullPage.js would have to set tabIndex="-1" to any of those elements outside the current section plus any element containing the attribute tabindex.
And if you have many links or inputs in your site, this could decrease the performance of your site on every section / slide change.

The other option is just to disable the tab in fullPage.js. Or you manually setting tabindex to -1.

@ZackMattor
Copy link

A quick fix we implemented was this...

  $('a, input, select').prop('tabIndex', -1);

This basically does what alarotrigo said and disables tabbing globally on the page... We actually just got a complaint from a client saying that they couldn't tab through this one form so you might be getting a pull request if I can find a decent solution, but as you said it might affect performance if there are a ton of elements...

@alvarotrigo
Copy link
Owner

You can also set the wrapper of those elements to display:none or I believe you can even use opacity:0 and probably... visibility: hidden. This way you will only have to show the form on onLeave or just use the active class in the section to make it visible:

#section3 #myForm{
    display:none;
}
#section3.active #myForm{
    display: block;
}

@alvarotrigo
Copy link
Owner

I'll keep looking into this issue.
It might be able to be solved by using opacity:0 for all the non visible sections. I believe that's the way reveal.js deals with it.
Although they have a pretty ugly interval here to solve problems with iframes. (you can actually test it by setting opacity:1 to the next slide, you'll notice how it comes back after tabbing )

@ZackMattor
Copy link

I just did a test with the following.

$('.fp-section').not('.active').css('opacity', 0);

and I can still tab to the opaque elements, you might need to use display: none...

@alvarotrigo
Copy link
Owner

True.

@ZackMattor
Copy link

Seems to work pretty well doing the following..

// On load
$('.fp-section').not('.active').hide();

// On transition - To next slide
$('.fp-section.active').next().show();

Just need to make sure that it hides the previous after the animation is finished, and if you want to jump to a specific index you can't use .next obviously.. but as a proof of concept it seems to be functional.

@alvarotrigo
Copy link
Owner

It seems the interval is the solution they are using. That's why you can see a flickering although you don't see the next slide because it has opacity: 0.

@alvarotrigo
Copy link
Owner

@criten your solution might carry some problems. It would need to be tested. But hiding the section completely on load (before even calling fullPage.js) might make things such as $(SECTION_SEL).each(function(){ not work as expected.

@alvarotrigo
Copy link
Owner

In your case I would go for the CSS solution I provided.

@meneldil
Copy link
Author

Hello, sorry for the response time.
Thank you for the answer! :)

A nice feature is that the page scroll directly to the fields selected by the "tab" key.

@warapitiya
Copy link

What's the best solution for this?

@alvarotrigo
Copy link
Owner

What's the best solution for this?

There's not? The topic still open.

@pawelszewczak
Copy link

It working for me:

$(document).keydown(function (e) { var keycode1 = (e.keyCode ? e.keyCode : e.which); if (keycode1 == 0 || keycode1 == 9) { e.preventDefault(); e.stopPropagation(); } });

@warapitiya
Copy link

@pawelszewczak, Thanks for the fix but rather than saying it's a fix, it's a worker-round to disabling tab-index so fullpage will not break.

@alvarotrigo
Copy link
Owner

it's a worker-round to disabling tab-index so fullpage will not break.

Which is far from ideal within a form.

@pawelszewczak
Copy link

@warapitiya i didn't say that is fix, i said its working for me, of course its a some of workaround, but helps to dont breake fullpage.

Of course, I look forward to a solution.

@warapitiya
Copy link

@pawelszewczak Thanks alot. Really appropriate your hard work. Looking foreword so solid solution.

@eladh
Copy link

eladh commented Feb 2, 2017

Hi @alvarotrigo

Just to make sure - if i want to use fullPage.js section that contain a Form and my users need a Keyboard Accessibility support to navigate from section to section -> this is not an option ?

also i added the scrollBar:true and still using the tab still got this issue

@alvarotrigo
Copy link
Owner

@eladh as I said, I would recommend you to use scrollBar:true to avoid these kind of problems.
Otherwise, you should better disable the focus on those elements as I suggested above.

Browsers act weird when focusing elements within a non scrollable site.

@meneldil
Copy link
Author

meneldil commented Feb 2, 2017

Hi everyone,

I recently found a solution that I will share:

First, I cancel the navigation with the tab key (and create my variable):

$('a, input, select, textarea').attr('tabindex', -1);

var $loadedSection;

And I only activate the necessary fields when I arrive on the desired slide:

afterLoad: function(anchorLink, index){
	$loadedSection = $(this);

	if( $loadedSection.hasClass('form-section') ){
		$('input, select, textarea').removeAttr("tabindex");
	}
},
onLeave: function(index, nextIndex){
	if( $loadedSection.hasClass('form-section') ){
		$('input, select, textarea').attr('tabindex', -1);
	}
},

Voilà !
I hope this will help you. ;)

@sede1900
Copy link

sede1900 commented Sep 14, 2017

the plugin must work with tab navigation, it's really a problem because our sites must be accessible (level AA) and navigate with tabs is the minimum requirement. It's an obligation in my sector (e-government sites). And I think it will be an legal obligation in 2 years in europe for all sites.

@alvarotrigo
Copy link
Owner

@sede1971 suggestions for the solution will be more than welcome :)

@sede1900
Copy link

I have bought 2 extensions these 2 days, I will spend some times to see if I can have some results with tabs
. thanks for this great plugin alvatrigo.

@infloent
Copy link

My fix for this:
This makes only the elements from the active section focusable

.section {
    visibility: hidden;
}

.section.js--section-visible {
    visibility: visible;
}
var $leavedSection = null,
    makeSectionVisibleOrHidden = function($section) {
        $section.toggleClass('js--section-visible');
    };

//the first section on the page should have by default 'js--section-visible' class
$elem.fullpage({
    onLeave: function(index, nextIndex, direction) {
        var $leavingSection = $(this);
        $leavedSection = $leavingSection;

        //make next section we are scrolling to visible just before animating
        if (direction == 'down') {
           makeSectionVisibleOrHidden($leavingSection.next());
        } else if (direction == 'up') {
           makeSectionVisibleOrHidden($leavingSection.prev());
        }
    },
    afterLoad: function(anchorLink, index) {
        var loadedSection = $(this);

        //hide leaved section after animation ended
        if ($leavedSection) makeSectionVisibleOrHidden($leavedSection);
    }
});

@alvarotrigo
Copy link
Owner

alvarotrigo commented Jan 12, 2018

@infloent thanks for your contribution! Although your solution won't work for pages using fp-auto-height and contain multiple sections in the viewport. It would make other sections invisible.
Also, it might generate other related issues, such as developers wouldn't be able to use absolute positioned elements in one section that overflows to another one.

But... I've been taking another look at it and it seems finally I've found a proper solution!!
I'll implement it soon, but so far you can make use of it by using the following function and callbacks:

(function(){
    // taken from https://github.com/udacity/ud891/blob/gh-pages/lesson2-focus/07-modals-and-keyboard-traps/solution/modal.js
    // suggested here:
    //https://developers.google.com/web/fundamentals/accessibility/focus/using-tabindex
    var focusableElementsString = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex="0"], [contenteditable]';

    $(document).on('focusin', focusableElementsString, checkFocus);
    
    function checkFocus(){
        if (!$(this).closest('.fp-section.active').length) {
            $('.fp-section.active').focus();
        }
    }
})();
            onLeave: function(index, nextIndex, direction){
                $('.fp-section').eq(nextIndex - 1)
                    .attr('tabindex', 0)
                    .siblings().removeAttr('tabindex');
            },
            afterLoad: function(){
                $('.fp-section.active').attr('tabindex', 0);
            }

Basically I'm adding a tabindex="0" to the active section.
Then when an elements gets in focus, before it gets the focus I check if it is within the active section or not. If not, I focus back the previous section, which will fit the active section back in the viewport.

@alvarotrigo
Copy link
Owner

Ok, that solution only worked well for sections, not for slides. The focus of the slide won't get the right position of it and will only show the last bit of it.

I figured out other way.

@alvarotrigo
Copy link
Owner

Fixed on the dev branch 2.9.6! Will get merged in the next release.

@fuzin
Copy link

fuzin commented Feb 19, 2018

Updating did not help in my case. Using tab in fullpage section still focused next or previous section / link.

I used
keyboardScrolling: false

What worked for me:

$('.formContainer input').on('keydown', function (e) { if (event.keyCode == 9) { e.stopPropagation(); } });

which was fine in my use case since I do not use keyboard scrolling (Tab).

@alvarotrigo
Copy link
Owner

alvarotrigo commented Feb 19, 2018

@fuzin It won't work with iframes. So that might be your case?
In that case you have to set tabindex="-1" in the iframe.

If that's not your case, I would appreciate an isolated reproduction in jsfiddle or codepen because it works properly for me as you can see in this demo.

@tibigp
Copy link

tibigp commented Mar 18, 2018

In case of a bootstrap 3 modal which has a form in it, the tabbing on the form doesn't work. You cannot Tab from one input to another.
My fix was to add this line of code on the onTab(e) function after the variables:
if(activeElement.parents('.fullpage-wrapper').length == 0) return;

it checks if the 'action' happen in the fullPage block or outside of it (like in the case of a bootstrap modal)

@alvarotrigo
Copy link
Owner

@Tibigit related with the open issue #3144

it checks if the 'action' happen in the fullPage block or outside of it (like in the case of a bootstrap modal)

Nice idea! That might serve for fixed elements outside the fullpage layout!

@DanyPell
Copy link

Disabling tabbing globally is definitely not a solution. It prevents tabbing between input fields in login/signup forms. Current 2.9.6 version is not dist ready.

@ghost
Copy link

ghost commented May 1, 2018

UPDATE: This worked for us:

$('.form-container input').on('keydown', function (e) { if (event.keyCode == 9) { e.stopPropagation(); } });

We're running into this issue. We have a form in a div overlay, but not able to tab through the inputs. Any suggestions on how to attack?

  • Not sure if the modal fix from @Tibigit would work in this instance. (checking)

Thanks in advance!

@pixelmultiplo
Copy link

@lkorsun that's a partial solution, shift+tab does not work and I still can't tab to the submit button.
What's the source of this problem? How is the tab key hijacked? Maybe we can find a permanent solution, this a huge problem.

@emqfe5l
Copy link

emqfe5l commented Aug 15, 2018

Hello !
@alvarotrigo Can you plz update 'focusableElementsString' with adding input:not([disabled]):not([type="hidden"]) (for example wp7form has inputs which not need to trigger focus)

focusableElementsString = 'a[href], area[href], input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex="0"], [contenteditable]';

@alvarotrigo
Copy link
Owner

alvarotrigo commented Aug 15, 2018

:not([type="hidden"])

That was solved on the dev branch yesterday. You can try it out.
It also works as expected when using hidden parents and not only hidden inputs/focusable elements.

You can see the committed changes here.

@emqfe5l
Copy link

emqfe5l commented Aug 16, 2018

Thanks! I will try

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests