admin管理员组文章数量:1312991
I have an HTML along the following lines:
<div class="hiddenClass"> // this implies display:none
<span>
<input type="text" id="hiddenInput"/>
</span>
</div>
and a Javascript event (triggered in a "succes" method of an jQuery $.ajax() call ), that needs to make this div visible and then set the focus to the control. Something like:
this.DOMElements.divElement.className="showClass"; //a CSS class with display:block;
this.DOMElements.hiddenInputElement.focus();
this.DOMElements.hiddenInputElement.select();
strange enough, this code only works part of the time. In some cases (only sometimes!!) the focus/select mands generate warnings about focusing/selecting an invisible control. The control will be made visible, but the focus is not moved, nor is the text selected.
I found (somewhat) of a solution by moving the focus/select code in a separate function and delay-call it by means of a
this.DOMElements.divElement.className="showClass"; //a CSS class with display:block;
setTimeout("focusinput('hidddenInput')",1);
Ok, finally my question: since javascript is single-threaded.. how e there is a delay between the time I made the parent div visible, and the time I can set the focus/select on the child input element ? How could this be a race condition?
Edit: Happens in IE8
I have an HTML along the following lines:
<div class="hiddenClass"> // this implies display:none
<span>
<input type="text" id="hiddenInput"/>
</span>
</div>
and a Javascript event (triggered in a "succes" method of an jQuery $.ajax() call ), that needs to make this div visible and then set the focus to the control. Something like:
this.DOMElements.divElement.className="showClass"; //a CSS class with display:block;
this.DOMElements.hiddenInputElement.focus();
this.DOMElements.hiddenInputElement.select();
strange enough, this code only works part of the time. In some cases (only sometimes!!) the focus/select mands generate warnings about focusing/selecting an invisible control. The control will be made visible, but the focus is not moved, nor is the text selected.
I found (somewhat) of a solution by moving the focus/select code in a separate function and delay-call it by means of a
this.DOMElements.divElement.className="showClass"; //a CSS class with display:block;
setTimeout("focusinput('hidddenInput')",1);
Ok, finally my question: since javascript is single-threaded.. how e there is a delay between the time I made the parent div visible, and the time I can set the focus/select on the child input element ? How could this be a race condition?
Edit: Happens in IE8
Share Improve this question edited Sep 9, 2009 at 18:40 Radu094 asked Sep 9, 2009 at 18:21 Radu094Radu094 28.4k16 gold badges65 silver badges80 bronze badges 1- Happens only in IE I presume? – Crescent Fresh Commented Sep 9, 2009 at 18:24
4 Answers
Reset to default 2If you're using jQuery, use this to display and set focus:
$(".hiddenClass").fadeIn("fast",
function() {
$("#hiddenInput").focus();
}
);
or
$(".hiddenClass").show(0,
function() {
$("#hiddenInput").focus();
}
);
If you want to show it without any fade in.
Basically it's fading the hidden div in (you can replace .hiddenClass with an id if you one want a particular div to be shown and not all elements with .hiddenClass), and once it's done that it executes the callback function to give focus to the input.
That way you it will not try to give the input focus until after the div has been fully shown.
Ok, finally my question: since javascript is single-threaded.. how e there is a delay between the time I made the parent div visible, and the time I can set the focus/select on the child input element ?
You just answered your own question: this happens because JS is single-threaded; that is, it blocks the browser from updating its rendering until the script has finished executing.
So when you execute the code:
divElement.className="showClass";
the className property of the element has been updated, but as your script is still executing, the element is not immediately redrawn as visible. Therefore, when you execute
hiddenInputElement.focus();
the element is still hidden and you get the error.
So, in your first version, the sequence of execution in the single thread is:
- Script sets className;
- Script sets focus;
- Browser throws exception because focused element is hidden;
- Script ends because of error;
- Browser updates things based on the change(s) made by the script up to the point of failure.
When you use the setTimeout
approach, the sequence is:
- Script sets className;
- Script ends;
- Browser updates things based on the change(s) made by the script;
- Timeout fires;
- Timeout script sets focus, which now succeeds.
I'm not sure what's going on here, but it might not be a bad idea to grab a reference to the div your using, store it in a variable, and then operate on that, instead of grabbing it with getElementByID() each time.
So you're above code would be:
var myDiv = document.getElementById("hiddenInput");
if(myDiv)
{
myDiv.className="showClass"; //a CSS class with display:block;
myDiv.focus();
myDiv.select();
}
Also: There are certain javascript functions where the browser is allowed to spin up another thead (for instance, the load() function); just something to keep in mind :)
I've had this happen to me before. In most cases, I found that by setting a timeout after the setting the display fixes the issue in IE. Unfortunately, it isn't the cleanest fix.
本文标签: javascriptSetting focus on an input element after setting displayblockStack Overflow
版权声明:本文标题:javascript - Setting focus on an input element after setting display:block - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741901657a2403901.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论