检查DOM元素是否具有焦点

12

我有一个灯箱文本框,它使用ASP.NET UpdatePanel的AJAX调用显示。当灯箱显示时,我使用位于灯箱中的文本框的focus()方法立即将焦点放在文本框上。

在Firefox中,文本框没有问题地获得焦点。在IE中,除非我使用setTimeout()函数,否则文本框不会获得焦点。

setTimeout(function(){txtBx.focus()}, 500);

为了稍后触发焦点方法,我假设DOM元素已经被加载。

问题是,在该行代码上方,我已经检查了该元素是否为null/undefined,因此如果它达到了该行代码,该对象应该已经存在,只是由于某种原因它无法立即获得焦点。

显然,设置定时器来“修复”这个问题并不是解决问题的最佳或最优雅的方法。我想能够执行以下操作:

var txtBx = document.getElementById('txtBx');

if (txtPassword != null) {
    txtPassword.focus();
    while (txtPassword.focus === false) {
        txtPassword.focus();
    }
}
有没有办法判断文本框是否正在聚焦,以便执行类似上面的操作?
或者我是在错误地处理这个问题吗?
编辑 为了澄清,我不是在页面加载时调用代码。该脚本确实位于页面顶部,但它位于一个函数内部,该函数在ASP.NET的异步回发完成时调用,而不是在页面加载时调用。
由于这是Ajax更新后显示的,因此DOM应已加载,因此我假设jQuery的 $(document).ready() 事件在此处不会有帮助。

脚本在灯箱和文本框渲染之前执行了吗?你是如何打开灯箱的?也许可以发布一些代码。 - Diodeus - James MacFarlane
当然可以,我只是不确定该怎么解决这个问题。 - Dan Herbert
如果您使用0的延迟setTimeout(),该方法是否有效? - Aintaer
6个回答

1
似乎IE在脚本运行完成之前不会更新DOM。因此,测试焦点的循环将不允许DOM更新。使用setTimeout可能是唯一可行的解决方案。 您使用.focus()的示例是一个众所周知的例子,请参见this answer

1

你是否尝试在通过Ajax调用的文本框元素中添加autofocus="autofocus"属性?

通常,当我需要在动态内容上运行某些额外的JavaScript功能时,我会将该JavaScript添加到被调用的内容中。

该JavaScript也将在添加到DOM后执行。我不认为编写JavaScript到父文件然后“监听”DOM的更改有任何意义。就像你提到的,setTimeout()对于这种情况来说更像是一个hack而不是其他什么 :)


1

尝试将设置焦点的javascript放在页面末尾而不是开头,或者在页面加载事件之后再触发它。这将有助于确保DOM在设置焦点之前完全加载。

我使用FastInit来实现这一点。JQuery $(document).ready()也可以。


1

IE有一些技巧可以解决问题:

  1. 如果焦点元素具有不同的z-index - 您可以快速将z-index设置为当前聚焦元素的z-index(可能设置hidden属性),设置焦点,然后将其恢复到原始z-index

  2. 尝试使用blur()取消当前聚焦的元素。

  3. 如果元素被“shimmed” - 焦点“shim”元素。


“shimmed”是什么意思? - Dan Herbert

1

你可以尝试这样做 [仅限IE]。(未经测试)

theAjaxCreatedElement.onreadystatechange = function() {
    if ( this.readyState != "complete" ) 
        return;
    this.focus();
};

另一种方法可能是通过onfocus更改元素的背景颜色,然后使用js检查并确定它是否正确,如果不正确,则重新聚焦该元素。


我尝试过了。readyState 已经是“complete”了,这真的让我很困扰。IE说DOM元素已经准备好了,但在它“真正准备好”之前,你不能对它进行特定的操作,我想这是最好的描述方式。 - Dan Herbert

1
你可以尝试这个方法:
  1. 使用PageRequestManagerendRequest事件。该事件在Ajax更新完成后触发。
  2. 在事件处理程序中聚焦文本框。
下面是一些示例代码:
<script type="text/javascript">
    function onRequestEnd()
    {
     var txtBx = $get('txtBx');
     txtBx.focus();
    }  
    Sys.WebForms.PageRequestManager.getInstance().add_endRequest(onRequestEnd);
</script>

为了使文本框最初获得焦点,您可以使用pageLoad函数(Application客户端对象的load事件的快捷方式):

<script type="text/javascript">
function pageLoad()
{
    var txtBx = $get('txtBx');
    txtBx.focus();
}
</script>

这实际上就是我正在使用的方法。在onRequestEnd()方法中调用了该元素的focus()方法。 - Dan Herbert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接