javascript 使用 jQuery 进行上/下/左/右键盘导航?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17404175/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 08:12:01  来源:igfitidea点击:

Up/Down/Left/Right keyboard navigation with jQuery?

javascriptjqueryjquery-uijquery-selectorskeyboard-navigation

提问by Hailwood

I have a list of div's all with a set and equal height/width that are float:leftso they sit next to each other and fold under if that parent is smaller than the combined with of the items.

我有一个 div 的列表,所有的 div 都具有一组相等的高度/宽度,float:left因此如果该父项小于项目的总和,则它们彼此相邻并折叠。

Pretty standard. This is to create a list of the twitter bootstrap icons, it gives something like this: enter image description here

很标准。这是为了创建一个 twitter bootstrap 图标列表,它给出了这样的东西: 在此处输入图片说明

I have added next/previous keyboard navigation using the code below, however you will notice that the up/down arrow keys are mapped to call the left/right functions. What I have no idea how to do is to actually do the up/down navigation?

我使用下面的代码添加了下一个/上一个键盘导航,但是您会注意到向上/向下箭头键被映射为调用左/右功能。我不知道该怎么做是实际进行向上/向下导航?

JsFiddle

JsFiddle

(function ($) {
    $.widget("ui.iconSelect", {

        // default options
        options: {

        },

        $select: null,

        $wrapper: null,

        $list: null,

        $filter: null,

        $active: null,

        icons: {},

        keys: {
            left: 37,
            up: 38,
            right: 39,
            down: 40

        },

        //initialization function
        _create: function () {

            var that = this;
            that.$select = that.element;

            that.$wrapper = $('<div class="select-icon" tabindex="0"></div>');
            that.$filter = $('<input class="span12" tabindex="-1" placeholder="Filter by class name..."/>').appendTo(that.$wrapper);
            that.$list = $('<div class="select-icon-list"></div>').appendTo(that.$wrapper);


            //build the list of icons
            that.element.find('option').each(function () {
                var $option = $(this);
                var icon = $option.val();

                that.icons[icon] = $('<a data-class="' + icon + '"><i class="icon ' + icon + '"></i></a>');

                if ($option.is(':selected')) {
                    that.icons[icon].addClass('selected active');
                }

                that.$list.append(that.icons[icon]);
            });

            that.$wrapper.insertBefore(that.$select);
            that.$select.addClass('hide');



            that._setupArrowKeysHandler();
            that._setupClickHandler();
            that._setupFilter();
            that.focus('selected');
        },

        focus: function (type) {
            var that = this;
            if (that.$active === null || that.$active.length == 0) {
                if (type == 'first') {
                    that.$active = that.$list.find('a:visible:first');
                } else if (type == 'last') {
                    that.$active = that.$list.find('a:visible:last');
                } else if (type == 'selected') {
                    that.$active = that.$list.find('a.selected:visible:first');
                    that.focus('first');
                }
            }
            that.$active.addClass('active');
            var toScroll = ((that.$list.scrollTop() + that.$active.position().top)-that.$list.height()/2)+that.$active.height()/2;
            //that.$list.scrollTop((that.$list.scrollTop() + top)-that.$list.height()/2);
            that.$list.stop(true).animate({
                scrollTop: toScroll,
                queue: false,
                easing: 'linear'
            }, 200);

            if (type === 'selected') {
                return false;
            }

            that.$select.val(that.$active.data('class'));
            that.$select.trigger('change');

        },

        _setupArrowKeysHandler: function () {
            var that = this;

            that.$wrapper.on('keydown', function (e) {
                switch (e.which) {
                    case that.keys.left:
                        that.moveLeft();
                        break;
                    case that.keys.up:
                        that.moveUp();
                        break;
                    case that.keys.right:
                        that.moveRight();
                        break;
                    case that.keys.down:
                        that.moveDown();
                        break;
                    case 16:
                        return true;
                    case 9:
                        return true;
                    break;
                    default:
                        that.$filter.focus();
                        return true;
                }
                return false;
            });
        },

        _setupFilter: function(){
            var that = this;

            that.$filter.on('keydown keyup keypress paste cut change', function(e){
                that.filter(that.$filter.val());
            });
        },

        _setupClickHandler: function () {
            var that = this;
            that.$list.on('click', 'a', function () {
                that.$wrapper.focus();
                that.$active.removeClass('active');
                that.$active = $(this);
                that.focus('first');
            });
        },

        moveUp: function () {
            var that = this;
            return that.moveLeft();
        },

        moveDown: function () {
            var that = this;
            return that.moveRight();
        },

        moveLeft: function () {
            var that = this;
            that.$active.removeClass('active');
            that.$active = that.$active.prevAll(':visible:first');
            that.focus('last');
            return false;
        },

        moveRight: function () {
            var that = this;
            that.$active.removeClass('active');
            that.$active = that.$active.nextAll(':visible:first');
            that.focus('first');
            return false;
        },

        filter: function(word){
            var that = this;
            var regexp = new RegExp(word.toLowerCase());
            var found = false;
            $.each(that.icons, function(i, $v){
                found = regexp.test(i);
                if(found && !$v.is(':visible')){
                    $v.show();
                } else if(!found && $v.is(':visible')){
                    $v.hide();
                }
            });
        }

    });
})(jQuery);

回答by mibbler

Perhaps something like this: http://jsfiddle.net/QFzCY/

也许是这样的:http: //jsfiddle.net/QFzCY/

var blocksPerRow = 4;

$("body").on("keydown", function(e){
    var thisIndex = $(".selected").index();
    var newIndex = null;
    if(e.keyCode === 38) {
        // up
       newIndex = thisIndex - blocksPerRow;
    }
    else if(e.keyCode === 40) {
        // down
        newIndex = thisIndex + blocksPerRow;       
    }
    if(newIndex !== null) { 
        $(".test").eq(newIndex).addClass("selected").siblings().removeClass("selected");   
    }    
 });

Basically, you set how many items there are in a row and then find the current index and subtract or add that amount to select the next element via the new index.

基本上,您设置一行中有多少个项目,然后找到当前索引并减去或添加该数量以通过新索引选择下一个元素。

If you need to know how many blocks per row there are, you could do this:

如果你需要知道每行有多少块,你可以这样做:

var offset = null;
var blocksPerRow = 0;
$(".test").each(function(){
    if(offset === null) {
        offset = $(this).offset().top;
    }
    else if($(this).offset().top !== offset) {
        return false;
    }
    blocksPerRow++;
});

To deal with your 'edge' cases, you could do:

要处理您的“边缘”情况,您可以执行以下操作:

if(newIndex >= $(".test").length) {
    newIndex = $(".test").length - newIndex;
}

回答by sabithpocker

    moveUp: function () {
        var that = this;
        var index = $(this).index();
        var containerWidth = parseInt( $('.select-icon-list').innerWidth(), 10);
        var iconWidth = parseInt( $('.select-icon-list > a').width(), 10);
        var noOfCols = Math.floor( containerWidth / iconWidth );
        var newIndex = ( (index - noOfCols) < 0 ) ? index : (index - noOfCols);
        var elem = $('.select-icon-list > a')[index];
    },

Cache what ever remains static.

缓存一直保持静态的内容。