设置display:block后,将焦点设置在输入元素上

时间:2009-09-09 18:21:11

标签: javascript css multithreading

我有以下几行HTML:

<div class="hiddenClass"> // this implies display:none
 <span>
    <input type="text" id="hiddenInput"/>
 </span>
</div>

和一个Javascript事件(在jQuery $ .ajax()调用的“succes”方法中触发),需要使该div可见,然后将焦点设置为控件。类似的东西:

 this.DOMElements.divElement.className="showClass"; //a CSS class with display:block;
 this.DOMElements.hiddenInputElement.focus();
 this.DOMElements.hiddenInputElement.select();
很奇怪,这段代码只在部分时间内有效。在某些情况下(仅有时!!),焦点/选择命令会生成有关聚焦/选择不可见控件的警告。控件将可见,但焦点不会移动,文本也不会被选中。

我通过在单独的函数中移动焦点/选择代码并通过

延迟调用来找到(某种程度上)解决方案
this.DOMElements.divElement.className="showClass"; //a CSS class with display:block;
setTimeout("focusinput('hidddenInput')",1);

好的,最后我的问题:因为javascript是单线程的..为什么在我使父div可见的时间和我可以在子输入元素上设置焦点/选择的时间之间有延迟?这怎么可能是竞争条件?

编辑:在IE8中发生

4 个答案:

答案 0 :(得分:1)

如果您正在使用jQuery,请使用它来显示和设置焦点:

$(".hiddenClass").fadeIn("fast", 
    function() {
        $("#hiddenInput").focus();
    }
);

$(".hiddenClass").show(0, 
    function() {
        $("#hiddenInput").focus();
    }
);

如果你想显示它而没有任何淡入。

基本上它正在淡化隐藏的div(如果你想要显示一个特定的div而不是所有带有.hiddenClass的元素,你可以用id替换.hiddenClass),一旦完成它就会执行回调函数来给出专注于输入。

这样你就不会在完全显示div之前尝试给出输入焦点。

答案 1 :(得分:1)

  

好的,最后我的问题:因为javascript是单线程的..为什么在我使父div可见的时间和我可以在子输入元素上设置焦点/选择的时间之间存在延迟? / p>

你刚回答了自己的问题:这发生了,因为 JS是单线程的;也就是说,它阻止浏览器更新其呈现,直到脚本完成执行。

所以当你执行代码时:

divElement.className="showClass";

元素的className属性已更新,但由于您的脚本仍在执行,因此元素不会立即重新绘制为可见。因此,当您执行

hiddenInputElement.focus();

该元素仍然隐藏,您收到错误。

因此,在您的第一个版本中,单个线程中的执行顺序是:

  1. 脚本设置className;
  2. 脚本设置焦点;
  3. 浏览器抛出异常,因为隐藏了focus元素;
  4. 脚本因错误而结束;
  5. 浏览器根据脚本所做的更改直至故障点更新内容。
  6. 使用setTimeout方法时,序列为:

    1. 脚本设置className;
    2. 脚本结束;
    3. 浏览器根据脚本所做的更改更新内容;
    4. 超时火灾;
    5. 超时脚本设置焦点,现在成功。

答案 2 :(得分:0)

我不确定这里发生了什么,但是获取对你使用的div的引用,将它存储在变量中,然后对其进行操作,而不是使用getElementByID获取它可能不是一个坏主意( )每一次。

所以你的代码就是:

 var myDiv = document.getElementById("hiddenInput");
 if(myDiv)
 {
    myDiv.className="showClass"; //a CSS class with display:block;
    myDiv.focus();
    myDiv.select();
 }

另外:有一些javascript函数允许浏览器启动另一个thead(例如,load()函数);只需要记住一些事情:)

答案 3 :(得分:0)

我之前遇到过这种情况。在大多数情况下,我发现通过在设置后设置超时来解决IE中的问题。不幸的是,这不是最干净的解决方案。