Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 845553
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 15, 20262026-05-15T06:28:15+00:00 2026-05-15T06:28:15+00:00

How to make Keyboard navigation left/up/right/down (like for photo gallery) feature for jQuery Tabs

  • 0

How to make Keyboard navigation left/up/right/down (like for photo gallery) feature for jQuery Tabs with history? Demo without keyboard feature in http://dl.dropbox.com/u/6594481/tabs/index.html

Needed functions:

  1. on keyboard top/down make select and CSS showactivenested ajax tabs from 1-st to last level
  2. on keyboard left/right changeback/forwardcontent ofactivenested ajax tabs tab
  3. an extra option, make active nested ajax tab on ‘cursor-on’ on concrete nested ajax tabs level

Read more detailed question with example pictures in https://stackoverflow.com/questions/2975003/jquery-tools-to-make-keyboard-and-cookies-feature-for-ajaxed-tabs-with-history

/**
 * @license 
 * jQuery Tools @VERSION Tabs- The basics of UI design.
 * 
 * NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
 * 
 * http://flowplayer.org/tools/tabs/
 *
 * Since: November 2008
 * Date: @DATE 
 */  
(function($) {

    // static constructs
    $.tools = $.tools || {version: '@VERSION'};

    $.tools.tabs = {

        conf: {
            tabs: 'a',
            current: 'current',
            onBeforeClick: null,
            onClick: null, 
            effect: 'default',
            initialIndex: 0,            
            event: 'click',
            rotate: false,

            // 1.2
            history: false
        },

        addEffect: function(name, fn) {
            effects[name] = fn;
        }

    };

    var effects = {

        // simple "toggle" effect
        'default': function(i, done) { 
            this.getPanes().hide().eq(i).show();
            done.call();
        }, 

        /*
            configuration:
                - fadeOutSpeed (positive value does "crossfading")
                - fadeInSpeed
        */
        fade: function(i, done) {        

            var conf = this.getConf(),            
                 speed = conf.fadeOutSpeed,
                 panes = this.getPanes();

            if (speed) {
                panes.fadeOut(speed);    
            } else {
                panes.hide();    
            }

            panes.eq(i).fadeIn(conf.fadeInSpeed, done);    
        },

        // for basic accordions
        slide: function(i, done) {
            this.getPanes().slideUp(200);
            this.getPanes().eq(i).slideDown(400, done);             
        }, 

        /**
         * AJAX effect
         */
        ajax: function(i, done)  {            
            this.getPanes().eq(0).load(this.getTabs().eq(i).attr("href"), done);    
        }        
    };       

    var w;

    /**
     * Horizontal accordion
     * 
     * @deprecated will be replaced with a more robust implementation
     */
    $.tools.tabs.addEffect("horizontal", function(i, done) {

        // store original width of a pane into memory
        if (!w) { w = this.getPanes().eq(0).width(); }

        // set current pane's width to zero
        this.getCurrentPane().animate({width: 0}, function() { $(this).hide(); });

        // grow opened pane to it's original width
        this.getPanes().eq(i).animate({width: w}, function() { 
            $(this).show();
            done.call();
        });

    });    


    function Tabs(root, paneSelector, conf) {

        var self = this, 
             trigger = root.add(this),
             tabs = root.find(conf.tabs),
             panes = paneSelector.jquery ? paneSelector : root.children(paneSelector),             
             current;


        // make sure tabs and panes are found
        if (!tabs.length)  { tabs = root.children(); }
        if (!panes.length) { panes = root.parent().find(paneSelector); }
        if (!panes.length) { panes = $(paneSelector); }


        // public methods
        $.extend(this, {                
            click: function(i, e) {

                var tab = tabs.eq(i);                                                 

                if (typeof i == 'string' && i.replace("#", "")) {
                    tab = tabs.filter("[href*=" + i.replace("#", "") + "]");
                    i = Math.max(tabs.index(tab), 0);
                }

                if (conf.rotate) {
                    var last = tabs.length -1; 
                    if (i < 0) { return self.click(last, e); }
                    if (i > last) { return self.click(0, e); }                        
                }

                if (!tab.length) {
                    if (current >= 0) { return self; }
                    i = conf.initialIndex;
                    tab = tabs.eq(i);
                }                

                // current tab is being clicked
                if (i === current) { return self; }

                // possibility to cancel click action                
                e = e || $.Event();
                e.type = "onBeforeClick";
                trigger.trigger(e, [i]);                
                if (e.isDefaultPrevented()) { return; }

                // call the effect
                effects[conf.effect].call(self, i, function() {

                    // onClick callback
                    e.type = "onClick";
                    trigger.trigger(e, [i]);                    
                });            

                // default behaviour
                current = i;
                tabs.removeClass(conf.current);    
                tab.addClass(conf.current);                

                return self;
            },

            getConf: function() {
                return conf;    
            },

            getTabs: function() {
                return tabs;    
            },

            getPanes: function() {
                return panes;    
            },

            getCurrentPane: function() {
                return panes.eq(current);    
            },

            getCurrentTab: function() {
                return tabs.eq(current);    
            },

            getIndex: function() {
                return current;    
            }, 

            next: function() {
                return self.click(current + 1);
            },

            prev: function() {
                return self.click(current - 1);    
            }        

        });

        // callbacks    
        $.each("onBeforeClick,onClick".split(","), function(i, name) {

            // configuration
            if ($.isFunction(conf[name])) {
                $(self).bind(name, conf[name]); 
            }

            // API
            self[name] = function(fn) {
                $(self).bind(name, fn);
                return self;    
            };
        });


        if (conf.history && $.fn.history) {
            $.tools.history.init(tabs);
            conf.event = 'history';
        }    

        // setup click actions for each tab
        tabs.each(function(i) {                 
            $(this).bind(conf.event, function(e) {
                self.click(i, e);
                return e.preventDefault();
            });            
        });

        // cross tab anchor link
        panes.find("a[href^=#]").click(function(e) {
            self.click($(this).attr("href"), e);        
        }); 

        // open initial tab
        if (location.hash) {
            self.click(location.hash);
        } else {
            if (conf.initialIndex === 0 || conf.initialIndex > 0) {
                self.click(conf.initialIndex);
            }
        }                

    }


    // jQuery plugin implementation
    $.fn.tabs = function(paneSelector, conf) {

        // return existing instance
        var el = this.data("tabs");
        if (el) { return el; }

        if ($.isFunction(conf)) {
            conf = {onBeforeClick: conf};
        }

        // setup conf
        conf = $.extend({}, $.tools.tabs.conf, conf);        

        this.each(function() {                
            el = new Tabs($(this), paneSelector, conf);
            $(this).data("tabs", el); 
        });        

        return conf.api ? el: this;        
    };        

}) (jQuery); 

/**
 * @license 
 * jQuery Tools @VERSION History "Back button for AJAX apps"
 * 
 * NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
 * 
 * http://flowplayer.org/tools/toolbox/history.html
 * 
 * Since: Mar 2010
 * Date: @DATE 
 */
(function($) {

    var hash, iframe, links, inited;        

    $.tools = $.tools || {version: '@VERSION'};

    $.tools.history = {

        init: function(els) {

            if (inited) { return; }

            // IE
            if ($.browser.msie && $.browser.version < '8') {

                // create iframe that is constantly checked for hash changes
                if (!iframe) {
                    iframe = $("<iframe/>").attr("src", "javascript:false;").hide().get(0);
                    $("body").append(iframe);

                    setInterval(function() {
                        var idoc = iframe.contentWindow.document, 
                             h = idoc.location.hash;

                        if (hash !== h) {                        
                            $.event.trigger("hash", h);
                        }
                    }, 100);

                    setIframeLocation(location.hash || '#');
                }


            // other browsers scans for location.hash changes directly without iframe hack
            } else { 
                setInterval(function() {
                    var h = location.hash;
                    if (h !== hash) {
                        $.event.trigger("hash", h);
                    }                        
                }, 100);
            }

            links = !links ? els : links.add(els);

            els.click(function(e) {
                var href = $(this).attr("href");
                if (iframe) { setIframeLocation(href); }

                // handle non-anchor links
                if (href.slice(0, 1) != "#") {
                    location.href = "#" + href;
                    return e.preventDefault();        
                }

            }); 

            inited = true;
        }    
    };  


    function setIframeLocation(h) {
        if (h) {
            var doc = iframe.contentWindow.document;
            doc.open().close();    
            doc.location.hash = h;
        }
    } 

    // global histroy change listener
    $(window).bind("hash", function(e, h)  { 
        if (h) {
            links.filter(function() {
              var href = $(this).attr("href");
              return href == h || href == h.replace("#", ""); 
            }).trigger("history", [h]);    
        } else {
            links.eq(0).trigger("history", [h]);    
        }

        hash = h;
    window.location.hash = hash;
    });


    // jQuery plugin implementation
    $.fn.history = function(fn) {

        $.tools.history.init(this);

        // return jQuery
        return this.bind("history", fn);        
    };    

})(jQuery);
$(function() {
$("#list").tabs("#content > div", {effect: 'ajax', history: true});
});​
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-15T06:28:16+00:00Added an answer on May 15, 2026 at 6:28 am

    Here is how I would add the keyboard functionality to your code.

    But, I want to add that after looking at pretty much the same question you posted two days prior to this one, that this site is set up to help you find problems in your code, not to write it all for you. If you want someone to write all the code, hire someone to do it or you’ll probably have to learn how to do it yourself (with troubleshooting help from us as needed).

    Anyway, I set up this demo to help you get started. Hopefully there are enough comments that you can understand what I was doing and you can take it from there.

    $(function() {
     var list = $('#list'),
         imgPerRow = -1,
         loop = true;
     // find first image y-offset to find the number of images per row
     var topOffset = list.find('img:eq(0)').offset().top,
         numTabs = list.find('a').length - 1,
         current, newCurrent;
    
     function changeTab(diff){
      current = list.find('a.current').index();
      newCurrent = (loop) ? (current + diff + numTabs + 1) % (numTabs + 1) : current + diff;
      if (loop) {
       if (newCurrent > numTabs) { newCurrent = 0; }
       if (newCurrent < 0) { newCurrent = numTabs; }
      } else {
       if (newCurrent > numTabs) { newCurrent = numTabs; }
       if (newCurrent < 0) { newCurrent = 0; }
      }
      // don't trigger change if tab hasn't changed (for non-looping mode)
      if (current != newCurrent) {
       list.find('a').eq(newCurrent).trigger('click'); // trigger click on tab
      }
     }
    
     list
      // set up tabs
      .tabs("#content > div", {effect: 'ajax', history: true})
    
      // find number of images on first row
      .find('img').each(function(i){
       if (imgPerRow < 0 && $(this).offset().top > topOffset ) {
        imgPerRow = i;
       }
      });
    
      // Set up arrow keys
      // Set to document for demo, probably better to use #list in the final version.
      $(document).bind('keyup', function(e){
       var key = e.which;
       if (key > 36 && key < 41) {
        if (key == 37) { changeTab(-1); }         // Left
        if (key == 38) { changeTab(-imgPerRow); } // Up
        if (key == 39) { changeTab(+1); }         // Right
        if (key == 40) { changeTab(+imgPerRow); } // Down
        e.preventDefault();
       }
      });
    
     // toggle looping through tabs
     $(':button').click(function(){
      loop = !loop;
      $('#loopStatus').text(loop);
     });
    
    });
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I want To make a square that has keyboard movement (up, down, left, right)
I'm using a script to make a user's keyboard control left/right slide navigation on
Is there a way to make a keyboard disappear without resignFirstResponder ? I have
I'm trying to add keyboard shortcuts on my website to make fast navigation possible
When I try to make a JSpinner un-editable by keyboard or mouse like this:
Possible Duplicate: How to make return key on iphone make keyboard disappear? I have
I want to make a smart keyboard that can learn and save new words
I'm new. I've determined I cannot make a label active and accept keyboard input,
I make a keyboard from UIButtons. On this keyboard there are 49 UIButtons, which
now I'm trying to make the keyboard events to stop repeating. My idea was

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.