Javascript 将焦点从最后一个元素循环到第一个表单元素&;反之亦然

Javascript 将焦点从最后一个元素循环到第一个表单元素&;反之亦然,javascript,jquery,ajax,focus,keydown,Javascript,Jquery,Ajax,Focus,Keydown,我用malsup的表单插件创建了一个表单,它在输入发生变化时提交。我已经将jQuery脚本设置为索引下拉菜单和可见输入,并使用该索引确定tab的keydown是应该将焦点移动到下一个元素还是第一个元素,同样地,使用shift+tab keydown。但是,它没有像我所希望的那样将焦点从tab键上的最后一个元素移动到第一个元素,而是将焦点移动到第二个元素。如何将其更改为将焦点循环到实际的第一个和最后一个元素?以下是指向我的表单的实时链接:。感谢所有想帮忙的人。这是我的剧本: $(document)

我用malsup的表单插件创建了一个表单,它在输入发生变化时提交。我已经将jQuery脚本设置为索引下拉菜单和可见输入,并使用该索引确定tab的keydown是应该将焦点移动到下一个元素还是第一个元素,同样地,使用shift+tab keydown。但是,它没有像我所希望的那样将焦点从tab键上的最后一个元素移动到第一个元素,而是将焦点移动到第二个元素。如何将其更改为将焦点循环到实际的第一个和最后一个元素?以下是指向我的表单的实时链接:。感谢所有想帮忙的人。这是我的剧本:

$(document).ready(function() {
var options = {
    target: '#c_main',
    success: setFocus
};
$('#calculator').live('submit', function() {
    $(this).ajaxSubmit(options);
    return false;
});
$(this).focusin(function(event) {
    var shiftDown = false;
    $('input, select').each(function (i) {
        $(this).data('initial', $(this).val());
    });
    $('input, select').keyup(function(event) {
        if (event.keyCode==16) {
            shiftDown = false;
            $('#shiftCatch').val(shiftDown);
        }
    });
    $('input, select').keydown(function(event) {
        if (event.keyCode==16) {
            shiftDown = true;
            $('#shiftCatch').val(shiftDown);
        }
        if (event.keyCode==13) {
            $('#captured').val(event.target.id);
        } else if (event.keyCode==9 && shiftDown==false) {
            return $(event.target).each(function() {
                var fields = $(this).parents('form:eq(0),calculator').find('select, input:visible');
                var index = fields.index(this);
                var nextEl = fields.eq(index+1).attr('id');
                var firstEl = fields.eq(0).attr('id');
                var focusEl = '#'+firstEl;
                if (index>-1 && (index+1)<fields.length) {
                    $('#captured').val(nextEl);
                } else if(index+1>=fields.length) {
                    if ($(this).val() != $(this).data('initial')) {
                        $('#captured').val(firstEl);
                    } else {
                        event.preventDefault();
                        $(focusEl).focus();
                    }
                }
                return false;
            });
        } else     if (event.keyCode==9 && shiftDown==true) {
            return $(event.target).each(function() {
                var fields = $(this).parents('form:eq(0),calculator').find('select, input:visible');
                var index = fields.index(this);
                var prevEl = fields.eq(index-1).attr('id');
                var lastEl = fields.eq(fields.length-1).attr('id');
                var focusEl = '#'+lastEl;
                if (index<fields.length && (index-1)>-1) {
                    $('#captured').val(prevEl);
                } else if (index==0) {
                    if ($(this).val() != $(this).data('initial')) {
                        $('#captured').val(lastEl);
                    } else {
                        event.preventDefault();
                        $(focusEl).select();
                    }
                }
                return false;
            });
        }
    });
});
这类作品。加载页面后,如果用户在最后一个元素上按tab键而不更改其值,则焦点将设置为第二个元素。但是,当用户第二次按最后一个元素上的tab键而不更改其值时,以及此后的每一次,焦点都将设置为第一个元素,正如我所希望的那样

Edit#2:我将Edit#1中的代码替换为使用event.preventDefault()的代码,这样效果更好。而如果用户在第一个元素中按下shift+tab键,则焦点会按应有的方式移动到最后一个元素。但是,如果用户继续按住shift键并再次按tab键,焦点将设置回第一个元素。如果用户继续按住shift键并点击tab,焦点将移回最后一个元素。焦点将在第一个和最后一个元素之间来回移动,直到用户抬起shift键。仅按tab键时不会出现此问题。以下是新的代码片段:

event.preventDefault();
$(focusEl).focus();

你有很多代码我没有完全了解,所以我不知道我是否错过了一些你想要集成的功能,但是对于通过表单元素进行制表/移位制表,这应该可以完成以下工作:

var elements = $("#container :input:visible");
var n = elements.length;
elements
.keydown(function(event){
    if (event.keyCode == 9) { //if tab
        var currentIndex = elements.index(this);
        var newIndex = event.shiftKey ? (currentIndex - 1) % n : (currentIndex + 1) % n;
        var el = elements.eq(newIndex);
        if (el.attr("type") == "text")
            elements.eq(newIndex).select();
        else
            elements.eq(newIndex).focus();
        event.preventDefault();
    }
});
元素
将是包含所有输入字段的jQuery对象,在我的示例中,它是div
#容器中的所有输入字段

这里有一个演示:

这是解决方案,如果没有西门的帮助,我不可能实现它。再次感谢你,西门

$(document).ready(function() {
    var options = {
        target: '#c_main',
        success: setFocus
    };
    $('#calculator').live('submit', function() {
        $(this).ajaxSubmit(options);
        return false;
    });
    $(this).focusin(function(event) {
        $('#calculator :input:visible').each(function (i) {
            $(this).data('initial', $(this).val());
        });
        return $(event.target).each(function() {
            $('#c_main :input:visible').live(($.browser.opera ? 'keypress' : 'keydown'), function(event){
                var elements = $("#calculator :input:visible");
                var n = elements.length;
                var currentIndex = elements.index(this);
                if (event.keyCode == 13) { //if enter
                    var focusElement = elements.eq(currentIndex).attr('id');
                    $('#captured').val(focusElement);
                } else if (event.keyCode == 9) { //if tab
                    var newIndex = event.shiftKey ? (currentIndex - 1) % n : (currentIndex + 1) % n;
                    var el = elements.eq(newIndex);
                    var focusElement = el.attr('id');
                    if ($(this).val() != $(this).data('initial')) {
                        $('#captured').val(focusElement);
                    } else if ((currentIndex==0 && event.shiftKey) || (currentIndex==n-1 && !event.shiftKey)) { 
                        event.preventDefault();
                        if (el.attr('type')=='text') {
                            $.browser.msie ? "" : $(window).scrollTop(5000);
                            el.select().delay(800);
                        } else {
                            $.browser.msie ? "" : $(window).scrollTop(-5000);
                            el.focus().delay(800);
                        }
                    } else if (el.is('select')) {
                        event.preventDefault();
                        if (el.attr('type')=='text') {
                            el.select();
                        } else {
                            el.focus();
                        }
                    }
                }
            });
        });
    });
});

function setFocus() {
    with (document.calculator)
    var recap = document.getElementById(recaptured.value);
    if (recap!=null) {
        setTimeout(function() {
            if (recap.getAttribute('type')=='text') {
                recap.select();
            } else {
                recap.focus();
            }
        }, 1     );
    }
}

我把我的文件放在我的实时链接中供下载:

谢谢你的回复,西门。当用户不更改任何输入的值时,您的脚本非常适合在表单元素中循环焦点。然而,我的表单的一个关键功能是,它需要在更改时提交,然后在提交后回调期间将焦点重新应用到正确的元素。我是通过在一个文本字段中捕获正确元素的ID,将该值发布到另一个文本字段,然后调用一个函数,在post提交回调过程中使用该发布值将焦点应用到正确的元素来实现这一点的。也许它没有准确地回答OP问题,但作为一个通用解决方案,它很棒!我一直在与这种奇怪的行为作斗争(关注第二个控件而不是第一个)。谢谢你,西门!
$(document).ready(function() {
    var options = {
        target: '#c_main',
        success: setFocus
    };
    $('#calculator').live('submit', function() {
        $(this).ajaxSubmit(options);
        return false;
    });
    $(this).focusin(function(event) {
        $('#calculator :input:visible').each(function (i) {
            $(this).data('initial', $(this).val());
        });
        return $(event.target).each(function() {
            $('#c_main :input:visible').live(($.browser.opera ? 'keypress' : 'keydown'), function(event){
                var elements = $("#calculator :input:visible");
                var n = elements.length;
                var currentIndex = elements.index(this);
                if (event.keyCode == 13) { //if enter
                    var focusElement = elements.eq(currentIndex).attr('id');
                    $('#captured').val(focusElement);
                } else if (event.keyCode == 9) { //if tab
                    var newIndex = event.shiftKey ? (currentIndex - 1) % n : (currentIndex + 1) % n;
                    var el = elements.eq(newIndex);
                    var focusElement = el.attr('id');
                    if ($(this).val() != $(this).data('initial')) {
                        $('#captured').val(focusElement);
                    } else if ((currentIndex==0 && event.shiftKey) || (currentIndex==n-1 && !event.shiftKey)) { 
                        event.preventDefault();
                        if (el.attr('type')=='text') {
                            $.browser.msie ? "" : $(window).scrollTop(5000);
                            el.select().delay(800);
                        } else {
                            $.browser.msie ? "" : $(window).scrollTop(-5000);
                            el.focus().delay(800);
                        }
                    } else if (el.is('select')) {
                        event.preventDefault();
                        if (el.attr('type')=='text') {
                            el.select();
                        } else {
                            el.focus();
                        }
                    }
                }
            });
        });
    });
});

function setFocus() {
    with (document.calculator)
    var recap = document.getElementById(recaptured.value);
    if (recap!=null) {
        setTimeout(function() {
            if (recap.getAttribute('type')=='text') {
                recap.select();
            } else {
                recap.focus();
            }
        }, 1     );
    }
}