【问题标题】:What is a FORM's equivalent to DOM's getNextSibling?什么是 FORM 等价于 DOM 的 getNextSibling?
【发布时间】:2016-06-19 11:43:46
【问题描述】:

我有一个表格,如下:

<FORM name="form1">
    <TABLE onkeypress="focusNextFormElement(event)">
        <TR>
            <TD><INPUT name="SomeObscureName"></TD><TD>Some data</TD>
        </TR>
        <TR>
            <TD><INPUT name="ThisName"><span>Here's some obscure text.</span></TD><TD>Some data</TD>
        </TR>
        <TR>
            <TD><INPUT name="someNameIdontKnow"></TD><TD>Some data</TD>
        </TR>
    </TABLE>
</FORM>

有没有更好、更有效的方法来编写这个函数? (当然,这是一个简化的例子)

function focusNextFormElement(ev){
    var el = ev.target;
    var f = el.form;
    var xx = f.elements.length - 1;
    for(var x = 0; x < xx; x++){
        if(f.elements[x] === el){
            f.elements[x+1].focus();
        }
    }
}

这个表单上可能有数千个元素,我认为每次函数运行时都循环遍历它们并不是特别有效。

另外,我可以用鼠标任意选择输入,所以跟踪数组可能没有多大用处。

我无法控制页面的生成,因为它是一个油脂猴脚本,可帮助自动化另一个页面。

编辑 感谢@Trincot,从更广泛的角度来看,@Oriol 找到了答案。

function nextFormSibling(el){
    var elems = el.form.elements;
    var idx = [].indexOf.call(elems, el);
    return elems[idx+1] || el;
}

function previousFormSibling(el){
    var elems = el.form.elements;
    var idx = [].indexOf.call(elems, el);
    return elems[idx-1] || el;
}

【问题讨论】:

    标签: javascript forms dom


    【解决方案1】:

    您可以在表单的元素集合上调用 indexOf() 来获取元素的索引。尽管此集合不是原生 JavaScript 数组,但您可以像这样使用 indexOf.call

    function nextFormElement(el) {
        var f = el.form;
        if (f) return f.elements[1+[].indexOf.call(f.elements, el)];
    }
    

    这是一个演示 sn-p 使用此函数在单击表单元素时将焦点移动到下一个元素。这显然是相当无用的,但它表明它是有效的:

    function nextFormElement(el) {
        var f = el.form;
        if (f) return f.elements[1+[].indexOf.call(f.elements, el)];
    }
    
    function focusNextFormElement(ev){
        var el = nextFormElement(ev.target);
        if (el) el.focus();
    }
    
    document.querySelector('form').onclick = focusNextFormElement;
    <FORM name="form1">
        <TABLE onkeypress="focusNextFormElement(event)">
            <TR>
                <TD><INPUT name="SomeObscureName"></TD><TD>Some data</TD>
            </TR>
            <TR>
                <TD><INPUT name="ThisName"><span>Here's some obscure text.</span></TD><TD>Some data</TD>
            </TR>
            <TR>
                <TD><INPUT name="someNameIdontKnow"></TD><TD>Some data</TD>
            </TR>
        </TABLE>
    </FORM>

    【讨论】:

      【解决方案2】:

      基本上,不,在不知道 DOM 的结构的情况下,您需要 elements 集合中元素的索引才能访问下一个。迭代它似乎是唯一的方法,但请考虑使用indexOf 而不是手动进行。

      但是,如果你想多次访问下一个元素,你可以只做一次并缓存结果:

      var nextFormElement = (function() {
        var cache = new WeakMap();
        return function(el) {
          if(!cache.has(el)) {
            var els = el.form.elements,
                idx = [].indexOf.call(els, el);
            cache.set(el, els[idx+1] || null);
          }
          return cache.get(el);
        };
      })();
      

      如果不支持 ES6,您可以使用普通对象而不是弱映射,其中值是下一个元素,键是一些标识符,您可以将它们作为 data-* 属性存储在元素中。

      然后,像这样使用它

      var next = nextFormElement(event.target);
      if(next) next.focus();
      

      var nextFormElement = (function() {
        var cache = new WeakMap();
        return function(el) {
          if(!cache.has(el)) {
            var els = el.form.elements,
                idx = [].indexOf.call(els, el);
            cache.set(el, els[idx+1] || null);
          }
          return cache.get(el);
        };
      })();
      document.forms.form1.addEventListener('keypress', function(event) {
        var next = nextFormElement(event.target);
        if(next) next.focus();
      });
      <form name="form1">
        <div>
          <input name="SomeObscureName" />
          <span>Some data</span>
        </div>
        <div>
          <input name="ThisName" />
          <span>Here's some obscure text.</span>
          <span>Some data</span>
        </div>
        <div>
          <input name="someNameIdontKnow" />
          <span>Some data</span>
        </div>
      </form>

      也就是说,这段代码完全突兀,我不推荐它。如果用户想要聚焦下一个文本可聚焦字段,他可以使用 tab 键。如果他不想改变焦点,而你为他做,那就太烦人了。

      【讨论】:

      • 您的代码鼓励我学习一些我不知道的东西:weekMap 和 indexOf.call。碰巧以下内容完全有效:return el.form.elements[[].indexOf.call(el.form.elements, el)+1] 我不确定 weekMap 会为我买多少,因为这值得怀疑我将每页选择两次相同的元素,但我感谢您鼓励我了解它。非常感谢!
      【解决方案3】:

      您能否详细说明您计划实现的目标?您想继续将输入焦点转移到输入元素吗?如果是这样,最好使用 'tabindex' 属性。

      回复:http://www.wufoo.com/html5/attributes/27-tabindex.html

      如果没有,那么想了解更多有关问题的信息。

      注意:'TABLE' 元素上的 'onkeypress' 存在更多问题,因为对于输入字段中按下的每个键,它都会立即切换到下一个输入字段。

      【讨论】:

      • 我正在寻找最快的方法来将下一个 FORM 兄弟放入变量中。 element.nextSibling,而是一个 FORM 的元素列表,而不是一个元素的 parentElement。
      【解决方案4】:

      假设 HTML 严格遵守您的示例,您可以尝试:

      function focusNextFormElement (ev) {
        // First find the tr element of this input...
        var tr = ev.target.parentNode.parentNode; // find the tr node
        // Advance to the next table row ...
        tr = tr.nextElementSibling
        // Then focus the input element in that row...  
        tr.querySelector ('input').focus ();
      

      }

      【讨论】:

      • 是的,遍历 DOM 是一种方法,但我希望遍历 form.elements。
      猜你喜欢
      • 2018-03-18
      • 1970-01-01
      • 2010-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-21
      • 2014-06-19
      • 2021-05-01
      相关资源
      最近更新 更多