Javascript 在div中查找任何类型的第一个可聚焦项

Javascript 在div中查找任何类型的第一个可聚焦项,javascript,dom,prototype,Javascript,Dom,Prototype,我在Javascript中有一个要求(使用Prototype)将光标集中在特定div中的第一个表单项上 简单的例子: <form id="theForm"> <div id="part1"> <input id="aaa" .../> <select id="bbb">...</select> </div> <div id="part2"> <select id="ccc

我在Javascript中有一个要求(使用Prototype)将光标集中在特定div中的第一个表单项上

简单的例子:

<form id="theForm">
  <div id="part1">
    <input id="aaa" .../>
    <select id="bbb">...</select>
  </div>
  <div id="part2">
    <select id="ccc">...</select>
    <input id="ddd" .../>
  </div>
</form>
我想我可以使用Prototype的选择方法,如下所示:

$(pDiv).select('input','select',...etc.);
但是,这将返回一个数组,其中包含所有输入,然后是所有选择,等等。它不会按照项目在div中出现的顺序返回项目。在上面的示例中,这将导致将焦点放在输入“ddd”上,而不是选择“ccc”

另一种可能性是表单getElements方法:

$('theForm').getElements();
但现在我需要询问返回的每个项目,看看它是否在所需的分区内。目前我知道的唯一方法是获取其所有祖先并查看是否有所选分区。我可以这样做,但我担心这不是最有效的解决方案


有人能提出更好的方法吗?

使用CSS3选择器怎么样:

$$('#theForm input:first-of-type')[0].focus()
它返回一个数组,即使我们知道它只包含一个元素,所以只需要抓住第一个元素并聚焦它

--编辑OK,我刚刚意识到它遗漏了select元素

--编辑此项似乎有效-选择第一个具有
name
属性的元素(假设您有name属性,可以使用其他属性):

我已经更新了我的链接示例,以包括这一点以及我错误的第一次尝试

--最后编辑一次:)

我已经使用了您的函数,并尝试将其转换为基于div的子级而不是表单的子级进行搜索。我对它进行了100次循环调用,看到IE有45%的改进,我不确定在现实世界中它是否会更好:

function focusFirstItem (divId)
{
    if ($(divId))
    {
        var elems = $('myForm').getElements();
        var elems2 = $(divId).select('*');
        for (i=0, l=elems2.length; i<l; ++i) {
            var item = elems2[i];
            if (item.id && !item.disabled && !item.readOnly && item.visible) {
                if (elems.find(function(s){return s.id = item.id}))
                item.focus();
                break;
            }
        }
    }
}
函数焦点第一项(divId)
{
如果($(divId))
{
var elems=$('myForm').getElements();
var elems2=$(divId).select('*');

对于(i=0,l=elems2.length;i这是我到目前为止设法想到的:

focusFirstItem (divId)
{
    if ($(divId))
    {
        var elems = $('myForm').getElements();
        for (i=0, l=elems.length; i<l; ++i) {
            var item = $(elems[i]);
            if (!item.disabled && !item.readOnly && item.visible) {
                if (item.ancestors().find(function(s){return s.id == divId})) {
                    $(item).focus();
                    break;
                }
            }
        }
    }
}
focusFirstItem(divId)
{
如果($(divId))
{
var elems=$('myForm').getElements();

对于(i=0,l=elems.length;iThanks,特别是对于添加示例。但是,当项目可以输入或选择(或文本区域等)时,我仍然遇到同样的问题:根据指定它们的顺序,您会得到不同的结果。如果您将项目“三”更改为选择列表,并将代码更改为$$(“#”+divName+”输入:类型的第一个“,“#”+divName+”选择:类型的第一个“)[0]。focus()”然后DivTwo按钮将焦点放在项目“四”而不是“三”,除非您交换这两个参数。尽管原型文档说“返回扩展DOM元素的文档顺序数组”是的,我刚刚意识到-根本没有考虑选择元素。你在上面的代码中没有名称属性,我想如果你必须添加属性,你也可以添加一个类名并选择。我的真实代码中有名称和类,这只是一个快速而肮脏的示例!不幸的是,我正在尝试编写一些泛型可以在许多现有页面上工作的代码,所以我不想修改现有的HTML。很公平-我使用了name属性,因为我的所有表单元素都有一个,不能准确地回忆起,但我认为这是因为IE6在发布时没有标识元素,除非有名称。我认为.祖先调用可能是很好的目标或者优化-它每次都会通过循环收集大量相同的元素?你能计算一下$('myForm').getElements()本身需要多长时间吗?我试着将你的方法稍微转向一边,补充了我的答案。
function focusFirstItem (divId)
{
    if ($(divId))
    {
        var elems = $('myForm').getElements();
        var elems2 = $(divId).select('*');
        for (i=0, l=elems2.length; i<l; ++i) {
            var item = elems2[i];
            if (item.id && !item.disabled && !item.readOnly && item.visible) {
                if (elems.find(function(s){return s.id = item.id}))
                item.focus();
                break;
            }
        }
    }
}
focusFirstItem (divId)
{
    if ($(divId))
    {
        var elems = $('myForm').getElements();
        for (i=0, l=elems.length; i<l; ++i) {
            var item = $(elems[i]);
            if (!item.disabled && !item.readOnly && item.visible) {
                if (item.ancestors().find(function(s){return s.id == divId})) {
                    $(item).focus();
                    break;
                }
            }
        }
    }
}