Disable navigating with the arrow keys
Asked Answered
G

3

6

jQuery UI Tabs has this "feature" where if i press the up/left or down/right key arrows it switches the tabs and loads that tab.

Generally for horizontal tabs, users are more acquainted with having the up and down keys scroll the page vs moving tabs. Is it possible to disable tab navigation for only the up and down keys?

UPDATE

Based on Konstantin's suggestion i tried the following code. It blocks the event when I click the up or down key, right after clicking the anchor tab. If i hit another key though like the left/right keys and then hit the up/down keys again. It registers the event, but doesn't seem to stop propagation. Could the event be firing from another element? Here's my code:

   $('#tabs').keydown(function (event) {
        console.log("in tabs");
        if (event.keyCode == 40 || event.keyCode == 38) {
          event.stopPropagation();
          event.preventDefault();
          return false;
        };
    });
    $('.ui-tabs-anchor').keydown(function (event) {
      console.log("in ui tabs anchor");
        if (event.keyCode == 40 || event.keyCode == 38) {
          event.stopPropagation();
          event.preventDefault();
          return false;
        };
    });

    $('.ui-tabs-nav').keydown(function (event) {
      console.log("in ui tabs nav");
        if (event.keyCode == 40 || event.keyCode == 38) {
          event.stopPropagation();
          event.preventDefault();
          return false;
        };
    });
Graber answered 1/8, 2013 at 10:42 Comment(4)
are you using a cdn for jQuery-UI?Logography
Hmm... do you think it's a version issue? Would pointing to a CDN matter?Graber
If you're hosting it yourself I can show you where to edit the jQuery-ui fileLogography
ah, sure. That's definitely doable.Graber
L
2

Search for the following code in your jQuery-UI file and comment out case $.ui.keyCode.DOWN: and case $.ui.keyCode.UP:

Pretty much you will be removing the unwanted functionality at its source.

_tabKeydown: function( event ) {
        var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
            selectedIndex = this.tabs.index( focusedTab ),
            goingForward = true;

        if ( this._handlePageNav( event ) ) {
            return;
        }

        switch ( event.keyCode ) {
            case $.ui.keyCode.RIGHT:
//IMPORTANT BIT case $.ui.keyCode.DOWN: 
                selectedIndex++;
                break;
//IMPORTANT BIT case $.ui.keyCode.UP:
            case $.ui.keyCode.LEFT:
                goingForward = false;
                selectedIndex--;
                break;
            case $.ui.keyCode.END:
                selectedIndex = this.anchors.length - 1;
                break;
            case $.ui.keyCode.HOME:
                selectedIndex = 0;
                break;
            case $.ui.keyCode.SPACE:
                // Activate only, no collapsing
                event.preventDefault();
                clearTimeout( this.activating );
                this._activate( selectedIndex );
                return;
            case $.ui.keyCode.ENTER:
                // Toggle (cancel delayed activation, allow collapsing)
                event.preventDefault();
                clearTimeout( this.activating );
                // Determine if we should collapse or activate
                this._activate( selectedIndex === this.options.active ? false : selectedIndex );
                return;
            default:
                return;
        }
Logography answered 7/8, 2013 at 3:19 Comment(3)
Rockstar! Thanks for that. Another reason I should be looking at the source code more often. Out of curiosity, is there a way to do this without touching jquery-ui directly?Graber
@KaushikGopal I'm sure that there is... I played around with it for a few hours till it drove me crazy. I think the difficulty has something to do with the way that jQuery changes the keycodes. I finally gave up and went with this idea because it seemed a little cleaner and more efficient to remove unwanted code rather than add code to remove other code, if that makes any sense.Logography
Neat as this solution may be at face value, I see a fundamental flaw: What happens after I've upgraded jQuery UI? Then I'll have to go back and look for these lines and re-comment them out, for as often as I upgrade, and for as many code bases as there are!Slipstream
H
4

Yes you can handle the keydown event and prevent it. It's attached to the ui-tabs anchor:

$('.ui-tabs-anchor').keydown(function (event) {
    return false;
});
Holiness answered 1/8, 2013 at 10:47 Comment(1)
That's pretty helpful. I am finding a weird behavior though. After I click the anchor and then try to hit the up/down key (by tracking the keycodes it prevents the event from firing). However, if i hit any other key like the left/right and then hit the up/down, it allows the event to propogate. This leads me to believe that the event is firing from somewhere else now and not from (".ui-tabs-anchor'). Updated the post with my code. CheersGraber
L
2

Search for the following code in your jQuery-UI file and comment out case $.ui.keyCode.DOWN: and case $.ui.keyCode.UP:

Pretty much you will be removing the unwanted functionality at its source.

_tabKeydown: function( event ) {
        var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
            selectedIndex = this.tabs.index( focusedTab ),
            goingForward = true;

        if ( this._handlePageNav( event ) ) {
            return;
        }

        switch ( event.keyCode ) {
            case $.ui.keyCode.RIGHT:
//IMPORTANT BIT case $.ui.keyCode.DOWN: 
                selectedIndex++;
                break;
//IMPORTANT BIT case $.ui.keyCode.UP:
            case $.ui.keyCode.LEFT:
                goingForward = false;
                selectedIndex--;
                break;
            case $.ui.keyCode.END:
                selectedIndex = this.anchors.length - 1;
                break;
            case $.ui.keyCode.HOME:
                selectedIndex = 0;
                break;
            case $.ui.keyCode.SPACE:
                // Activate only, no collapsing
                event.preventDefault();
                clearTimeout( this.activating );
                this._activate( selectedIndex );
                return;
            case $.ui.keyCode.ENTER:
                // Toggle (cancel delayed activation, allow collapsing)
                event.preventDefault();
                clearTimeout( this.activating );
                // Determine if we should collapse or activate
                this._activate( selectedIndex === this.options.active ? false : selectedIndex );
                return;
            default:
                return;
        }
Logography answered 7/8, 2013 at 3:19 Comment(3)
Rockstar! Thanks for that. Another reason I should be looking at the source code more often. Out of curiosity, is there a way to do this without touching jquery-ui directly?Graber
@KaushikGopal I'm sure that there is... I played around with it for a few hours till it drove me crazy. I think the difficulty has something to do with the way that jQuery changes the keycodes. I finally gave up and went with this idea because it seemed a little cleaner and more efficient to remove unwanted code rather than add code to remove other code, if that makes any sense.Logography
Neat as this solution may be at face value, I see a fundamental flaw: What happens after I've upgraded jQuery UI? Then I'll have to go back and look for these lines and re-comment them out, for as often as I upgrade, and for as many code bases as there are!Slipstream
A
1

Just had to do this myself. This is what worked for me:

$.widget("ui.tabs", $.ui.tabs, {
    _tabKeydown: function (event) {
        if (event.keyCode !== 38 && event.keyCode !== 40) {
            this._super(event);
        }
    }
});
Approbate answered 19/8, 2014 at 19:18 Comment(1)
This seems much better than going in to hack the source code!Slipstream

© 2022 - 2024 — McMap. All rights reserved.