我有以下SelectOneRadio:

<p:selectOneRadio id="sex" tabindex="3" value="#{signUp.gender}" required="true">
    <f:selectItem itemLabel="Male" itemValue="M"  />
    <f:selectItem itemLabel="Female" itemValue="F" />
</p:selectOneRadio>


尽管表单中下一个元素的tabindex为4,当我使用Tab键选择“性别”组件时,使用空格键或单击鼠标选择任何selectItem,但是当我再次按Tab键时,焦点转到tabindex = 1的元素,而不是下一个元素。
我怎样才能解决这个问题?

我正在使用primefaces 4.0

谢谢!

最佳答案

我可以使用Primfaces showcase重现该错误,并且我还发现了有关仍在打开的空格键选择的bug

解决方法是,您可以覆盖Primefaces的默认SelectOneRadio小部件并进行所需的更改。为了测试该方法,我创建了一个名为customradio.js的文件,其内容如下:

PrimeFaces.widget.SelectOneRadio = PrimeFaces.widget.BaseWidget.extend({
    init: function(cfg) {
        this._super(cfg);

        //custom layout
        if (this.cfg.custom) {
            this.inputs = $('input:radio[name="' + this.id + '"]:not(:disabled)');
            this.outputs = this.inputs.parent().next('.ui-radiobutton-box:not(.ui-state-disabled)');
            this.labels = $();
            this.icons = this.outputs.find('.ui-radiobutton-icon');

            //labels
            for (var i = 0; i < this.outputs.length; i++) {
                this.labels = this.labels.add('label[for="' + this.outputs.eq(i).parent().attr('id') + '"]');
            }
        }
        //regular layout
        else {
            this.outputs = this.jq.find('.ui-radiobutton-box:not(.ui-state-disabled)');
            this.inputs = this.jq.find(':radio:not(:disabled)');
            this.labels = this.jq.find('label:not(.ui-state-disabled)');
            this.icons = this.jq.find('.ui-radiobutton-icon');
        }

        this.checkedRadio = this.outputs.filter('.ui-state-active');

        this.bindEvents();

        //pfs metadata
        this.inputs.data(PrimeFaces.CLIENT_ID_DATA, this.id);
    },
    bindEvents: function() {
        var $this = this;

        this.outputs.on('mouseover.selectOneRadio', function() {
            $(this).addClass('ui-state-hover');
        })
                .on('mouseout.selectOneRadio', function() {
                    $(this).removeClass('ui-state-hover');
                })
                .on('click.selectOneRadio', function() {
                    var radio = $(this),
                            input = radio.prev().children(':radio');

                    if (!radio.hasClass('ui-state-active')) {
                        $this.unselect($this.checkedRadio);
                        $this.select(radio);
                        input.trigger('click');
                        input.trigger('change');
                    }
                    else {
                        input.trigger('click');
                    }
                });

        this.labels.on('click.selectOneRadio', function(e) {
            var target = $(PrimeFaces.escapeClientId($(this).attr('for'))),
                    radio = null;

            //checks if target is input or not(custom labels)
            if (target.is(':input'))
                radio = target.parent().next();
            else
                radio = target.children('.ui-radiobutton-box'); //custom layout

            radio.trigger('click.selectOneRadio');

            console.log("click.selectOneRadio");

            e.preventDefault();
        });

        this.inputs.on('focus.selectOneRadio', function() {
            var input = $(this),
                    radio = input.parent().next();

            if (input.prop('checked')) {
                radio.removeClass('ui-state-active');
            }

            radio.addClass('ui-state-focus');
        })
                .on('blur.selectOneRadio', function() {
                    var input = $(this),
                            radio = input.parent().next();

                    if (input.prop('checked')) {
                        radio.addClass('ui-state-active');
                    }

                    radio.removeClass('ui-state-focus');
                })
                .on('keydown.selectOneRadio', function(e) {
                    var input = $(this),
                            currentRadio = input.parent().next(),
                            index = $this.inputs.index(input),
                            size = $this.inputs.length,
                            keyCode = $.ui.keyCode,
                            key = e.which;

                    switch (key) {
                        case keyCode.UP:
                        case keyCode.LEFT:
                            var prevRadioInput = (index === 0) ? $this.inputs.eq((size - 1)) : $this.inputs.eq(--index),
                                    prevRadio = prevRadioInput.parent().next();

                            input.blur();
                            $this.unselect(currentRadio);
                            $this.select(prevRadio);
                            prevRadioInput.trigger('focus').trigger('change');
                            e.preventDefault();
                            break;

                        case keyCode.DOWN:
                        case keyCode.RIGHT:
                            var nextRadioInput = (index === (size - 1)) ? $this.inputs.eq(0) : $this.inputs.eq(++index),
                                    nextRadio = nextRadioInput.parent().next();
                            input.blur();
                            $this.unselect(currentRadio);
                            $this.select(nextRadio);
                            nextRadioInput.trigger('focus').trigger('change');
                            e.preventDefault();
                            break;
                        case keyCode.SPACE:
                            if (!currentRadio.hasClass('ui-state-active')) {
                                $this.unselect($this.checkedRadio);
                                $this.select(currentRadio);
                                input.trigger('change');
                            }
                            break;
                    }
                });

        if (this.cfg.behaviors) {
            PrimeFaces.attachBehaviors(this.inputs, this.cfg.behaviors);
        }
    },
    unselect: function(radio) {
        radio.prev().children(':radio').prop('checked', false);
        radio.removeClass('ui-state-active').children('.ui-radiobutton-icon').removeClass('ui-icon ui-icon-bullet');
    },
    select: function(radio) {
        this.checkedRadio = radio;
        radio.addClass('ui-state-active').children('.ui-radiobutton-icon').addClass('ui-icon ui-icon-bullet');
        radio.prev().children(':radio').prop('checked', true).focus();
    }
});


主要变化是:


在keydown绑定上为keyCode.SPACE添加了一个案例
在选择功能上选择收音机时添加了额外的.focus()。


希望对您有所帮助。

10-08 08:01