jQuery选项卡的键盘导航

时间:2010-06-06 20:16:28

标签: jquery ajax keyboard tabs history

如何为带有历史记录的jQuery标签进行Keyboard导航左/上/右/下(如照片库)功能?在http://dl.dropbox.com/u/6594481/tabs/index.html

中没有键盘功能的演示

需要的功能:

    键盘上的
  1. top/down make select和CSS显示从{1到最后一级的active嵌套ajax标签
  2. 键盘上的
  3. left/right更改了back/forward嵌套ajax标签标签的active内容
  4. 一个额外的选项,在具体的嵌套ajax选项卡级别的'cursor-on'上创建active嵌套的ajax选项卡
  5. 使用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});
    });​
    

2 个答案:

答案 0 :(得分:2)

以下是我将如何为您的代码添加键盘功能。

但是,我希望在此之前两天查看几乎相同的question you posted之后添加它,该网站设置为帮助您在代码中发现问题,而不是全部写入您。如果您希望有人编写所有代码,请雇人执行此操作,否则您可能必须自己学习如何操作(根据需要提供我们的故障排除帮助)。

无论如何,我设置this demo来帮助您入门。希望有足够的评论,你可以理解我在做什么,你可以从那里采取它。

$(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);
 });

});

答案 1 :(得分:0)

您可以使用

将操作绑定到按键
$.keyup(function(e) {
    key = e.which;
    if (key == 37) //code for left arrow key
    {
        ...
    }
});

快速谷歌搜索为我提供了以下关键代码列表:http://www.cambiaresearch.com/c4/702b8cd1-e5b0-42e6-83ac-25f0306e3e25/Javascript-Char-Codes-Key-Codes.aspx