Why is my onchange function called twice when using .focus()?
Solution 1
A quick fix (untested) should be to defer the call to focus()
via
setTimeout(function() { ... }, 0);
until after the event handler has terminated.
However, it is possible to make it work without such a hack; jQuery-free example code:
<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>
Solution 2
There's a way easier and more reasonable solution. As you expect onchange fire when the input value changes, you can simply explicitly check, if it was actually changed.
function onChangeHandler(e){
if(this.value==this.oldvalue)return; //not changed really
this.oldvalue=this.value;
// .... your stuff
}
Solution 3
I can confirm myOnChange
gets called twice on Chrome. But the context
argument is the initial input field on both calls.
If you remove the alert call it only fires once. If you are using the alert for testing only then try using console instead (although you need to remove it for testing in IE).
EDIT: It seems that the change event fires twice on the enter key. The following adds a condition to check for the existence of the new field.
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;
}
Update:
The $('#prefix_'+nextNum).focus();
does not get called because focus is a method of the dom object, not jQuery. Fixed it with $('#prefix_'+nextNum)[0].focus();
.
Nanne
Updated on March 12, 2020Comments
-
Nanne about 4 years
TLDR
- Check this example in chrome.
- Type someting and press
tab
. see one new box appear - type something and press
enter
. see two new boxes appear, where one is expected.
Intro
I noticed that when usingenter
rather thentab
to change fields, my onchange function on an input field was firing twice. This page was rather large, and still in development (read: numerous other bugs), so I've made a minimal example that shows this behaviour, and in this case it even does it on 'tab'. This is only a problem in Chrome as far as I can tell.What it should do
I want to make a new input after something is entered into the input-field. This field should get focus.Example:
javascript - needing 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-part
<div> <input type="text" onchange="return myOnChange(this,1);" id="prefix_1"> </div>
the complete code is on pastebin. you need to add your path to jquery in the script
A working example is here on jFiddle
The onchange gets called twice: The
myOnChange
function is called, makes the new input, calls thefocus()
, themyOnChange
gets called again, makes a new input, the 'inner'myOnChange
exits and then the 'outer'myOnchange
exits.I'm assuming this is because the focus change fires the
onchange()
?. I know there is some difference in behaviour between browsers in this.I would like to stop the .focus() (which seems to be the problem) to NOT call the
onchange()
, somyOnChange()
doesn't get called twice. Anybody know how?