2009-09-09 71 views
2

我有大致如下的HTML:设置显示后的输入元件上设置焦点:块

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

和Javascript事件(在jQuery的$就一个“更迭”方法触发()调用),需要使该div可见,然后将焦点置于控件上。例如:

this.DOMElements.divElement.className="showClass"; //a CSS class with display:block; 
this.DOMElements.hiddenInputElement.focus(); 
this.DOMElements.hiddenInputElement.select(); 

奇怪的是,此代码仅适用于部分时间。在某些情况下(有时只有!!),focus/select命令会产生关于聚焦/选择隐形控制的警告。控件将变为可见,但焦点不会移动,也不会选择文本。

我发现(有点)的溶液通过在一个单独的函数移动聚焦/选择代码,并通过

this.DOMElements.divElement.className="showClass"; //a CSS class with display:block; 
setTimeout("focusinput('hidddenInput')",1); 

好了,终于我的问题的手段延迟叫它:由于JavaScript是单线程..如何在我使父div可见的时间和可以在子输入元素上设置焦点/选择的时间之间存在延迟?这怎么可能是一个竞争条件?

编辑:偏偏IE8

+0

只发生在IE我认为? –

回答

1

如果你使用jQuery,用它来显示和设置重点:

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

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

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

基本上它正在淡化隐藏的div(如果你希望显示一个特定的div而不是所有的具有.hiddenClass的元素,你可以用一个id替换.hiddenClass),并且一旦完成它执行回调函数以将焦点集中到输入。

这样你就不会尝试给输入焦点,直到完全显示div后。

+0

经过测试,效果很好。但我相信jQuery fadeIn/show也在下面使用setTimeout,所以问题仍然存在,为什么会出现竞争条件? – Radu094

0

我不知道这里发生了什么,但它可能不是一个坏主意,抢你的使用div的引用,将其存储在一个变量,然后操作那就不要每次都用getElementByID()来抓取它。

所以你上面的代码将是:

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

另外:在有些情况下,浏览器允许旋转起来另一个THEAD某些JavaScript函数(例如,load()函数);只是要记住:)

+0

实际上,我在课堂上既有div又有输入元素,我只是简单地在我的例子中提供了一些东西。如果你认为这是相关的,我会继续前进,并改变 – Radu094

+0

的例子,我不知道。有可能。 你是否尝试直接改变风格而不是改变className?我仍然不确定这可能是一个竞争条件,但它绝对看起来像一个。 – neoncube

0

我以前曾遇到过这种情况。在大多数情况下,我发现通过在设置显示器后设置超时来修复IE中的问题。不幸的是,它不是最干净的修复程序。

1

好的,终于我的问题:因为JavaScript是单线程..怎么会有一个之间的时间,我做父母的div可见,以及我可以设置焦点/选择子输入元素?

你刚才已经回答你自己的问题:出现这种情况是因为JS是单线程的;也就是说,它会阻止浏览器更新其渲染,直到脚本执行完毕。

所以,当你执行该代码:

divElement.className="showClass"; 

元素的className属性已更新,但作为脚本仍在执行,该元素是不是立即可见重绘。因此,在执行时

hiddenInputElement.focus(); 

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

所以,在你的第一个版本,在单个线程执行的顺序是:

  1. 脚本设置的className;
  2. 脚本设置焦点;
  3. 浏览器抛出异常,因为被隐藏的焦点元素;
  4. 脚本因错误而结束;
  5. 浏览器根据脚本所做的更改来更新事件,直到故障点。

当您使用setTimeout方法,顺序是:

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

如果你说的是真的,那么原始代码应该总是失败,但它有时会起作用,所以这不可能。 – Radu094