为什么在使用.focus()时我的onchange函数被调用了两次?

时间:2011-03-02 10:24:52

标签: javascript jquery google-chrome focus onchange

TLDR

  • 在Chrome中检查此example
  • 键入someting并按tab。看到一个新框出现
  • 输入内容并按enter。看到两个新框出现,其中一个是预期的。

简介
我注意到当使用enter而不是tab更改字段时,输入字段上的onchange函数会触发两次。这个页面相当大,并且仍在开发中(阅读:许多其他错误),所以我做了一个显示这种行为的最小例子,在这种情况下它甚至在'tab'上做了。据我所知,这只是 Chrome 中的一个问题。

它应该做什么
我想在输入字段中输入内容后进行新输入。这个领域应该得到关注。

示例:

javascript - 需要jquery

function myOnChange(context,curNum){
      alert('onchange start');
      nextNum = curNum+1;
      $(context.parentNode).append('<input type="text" onchange="return myOnChange(this,'+nextNum+')" id="prefix_'+nextNum+'" >');
      $('#prefix_'+nextNum).focus();
      return false;
}

HTML部分

<div>
    <input type="text" onchange="return myOnChange(this,1);" id="prefix_1">
</div>

完整代码为on pastebin。你需要在脚本中添加你的jquery路径

jFiddle

上有一个工作示例

onchange被调用两次:调用myOnChange函数,生成新输入,调用focus(),再次调用myOnChange,生成新输入,'内部'myOnChange退出,然后'外部'myOnchange退出。

我假设这是因为焦点变化触发onchange()?我知道浏览器之间的行为存在一些差异。

我想停止.focus()(这似乎是问题)不要调用onchange(),因此myOnChange()不会被调用两次。有谁知道怎么样?

6 个答案:

答案 0 :(得分:6)

有一种更简单,更合理的解决方案。正如您期望在输入值更改时onchange fire,您可以简单地检查它是否实际更改。

function onChangeHandler(e){
  if(this.value==this.oldvalue)return; //not changed really
  this.oldvalue=this.value;
  // .... your stuff
}

答案 1 :(得分:2)

快速修复(未经测试)应该是通过

将呼叫推迟到focus()
setTimeout(function() { ... }, 0);

直到事件处理程序终止。

然而,没有这样的黑客就可以使它工作; jQuery-free示例代码:

<head>
<style>
input { display: block; }
</style>
<body>
<div></div>
<script>
var div = document.getElementsByTagName('div')[0];

var field = document.createElement('input');
field.type = 'text';
field.onchange = function() {
    // only add a new field on change of last field
    if(this.num === div.getElementsByTagName('input').length)
        div.appendChild(createField(this.num + 1));

    this.nextSibling.focus();
};

function createField(num) {
    var clone = field.cloneNode(false);
    clone.num = num;
    clone.onchange = field.onchange;
    return clone;
}

div.appendChild(createField(1));
</script>

答案 2 :(得分:1)

我可以确认myOnChange在Chrome上被调用两次。但是context参数是两个调用的初始输入字段。

如果删除警报,它只会触发一次。如果您仅使用警报进行测试,请尝试使用控制台(尽管您需要将其删除以便在IE中进行测试)。

编辑:似乎更改事件在回车键上触发两次。以下添加了检查新字段是否存在的条件。

function myOnChange(context, curNum) {
      nextNum = curNum+1;

      if ($('#prefix_'+nextNum).length) return false;// added to avoid duplication

      $(context.parentNode).append('<input type="text" onchange="return myOnChange(this,'+nextNum+')" id="prefix_'+nextNum+'" >');
      $('#prefix_'+nextNum)[0].focus();
      return false;
}

更新:

$('#prefix_'+nextNum).focus();没有被调用,因为focus是dom对象的方法,而不是jQuery。用$('#prefix_'+nextNum)[0].focus();修正了它。

答案 3 :(得分:0)

试试这个例子:

var curNum = 1;
function myOnChange( context )
{
    curNum++;

    $('<input type="text" onchange="return myOnChange( this )" id="prefix_'+ curNum +'" >').insertAfter( context );
    $('#prefix_'+ curNum ).focus();

    return false;
}

jsFiddle

答案 4 :(得分:0)

问题确实是因为focus(),再次调用onchange。我不知道这是否是一个很好的溶剂,但是这个功能是一个快速的解决方案:

context.onchange = "";

(onchange再次被调用,但现在是空的。这也很好,因为这个函数永远不会被调用两次。最终产品中会有一些界面变化,有助于解决这个问题(错误和所有),但最终这是我可能会做的事情。)

sollution:http://jsfiddle.net/k4WKH/2/

正如@johnhunter所说,焦点在示例中不起作用,但它在我的完整代码中起作用。我没有调查那里发生了什么,但这似乎是一个单独的问题。

答案 5 :(得分:0)

也许这对任何人都有帮助,无论出于何种原因,当你将事件onchage附加到输入文本时,当你按下enterkey,事件中的函数,做两次,我解决了这个问题对于onkeypress并评估代码,如果我有一个输入然后执行该功能,因为我只等待一个enterkey用户,这不适用于tab键。

    input_txt.onkeypress=function(evt){ 
            evt = evt || window.event;
            var charCode = evt.which || evt.keyCode;
            if(charCode === 13)  evaluate( n_rows ); 
             };