暂时删除“onblur” IE 中的处理程序

发布于 2024-10-21 01:05:54 字数 4706 浏览 8 评论 0原文

我想知道这里是否有人可以帮我解决这个问题。

我需要暂时禁用输入字段的“onblur”属性中的代码,然后重新启用它。我需要这样做的原因是我的工作流程如下:

1)AJAX 事件是由输入字段的“onblur”属性触发的,这是由于用户从该字段切换到下一个字段而导致的一个。
2) 页面已更新,并且从“onafterajax”挂钩调用我的 Javascript 代码。
3)我的代码对 DOM 进行了一些严重的重新排列,这导致当前输入字段失去焦点。所以,我必须手动恢复焦点。我已将焦点处理程序附加到所有输入字段,这样我就可以跟踪哪个字段最后获得焦点,这样我就知道将焦点放在哪里。
4) 我在正确的输入字段上调用.focus(),由于某种原因,这会导致“onblur”在同一输入字段上触发。所有浏览器中都会发生这种情况。这 a) 表明该领域仍然有焦点?! b) 创建无限循环,因为步骤 1 再次执行...

为了避免无限循环,我做了以下操作。在执行任何 DOM 重新排列之前,我会执行以下操作:

if ( window.currentFocusId ) {
   this.savedFocusId = currentFocusId;

   this.onblur_bak = $(this.savedFocusId).onblur;
   $(this.savedFocusId).onblur = null;
   LOG.warn(" --- Disabling blur on " + this.savedFocusId);
}

然后,在完成 DOM hackery 后,我会执行以下操作:

setFocusAndRestoreBlur : function(req) {
    if ( this.savedFocusId ) {
      var focusElement = req.form.elements[this.savedFocusId];
      LOG.warn(" ------ Focusing on " + focusElement.id);
      if (focusElement) {
        focusElement.focus();
        if (focusElement.select) {
          focusElement.select();
        }
      }

      LOG.warn(" ---  Enabling blur on " + this.savedFocusId);
      $(this.savedFocusId).onblur = this.onblur_bak;

      delete this.onblur_bak;
      delete this.savedFocusId;
    }
}

这在所有浏览器(FF、Chrome、Opera)中都运行良好,除了 IE6。

在 IE6 中,它有点可以工作。首先,为了使其在 IE 中工作,我必须像这样修改对“setFocusAndRestoreBlur”的调用:

setTimeout(function() {
  this.setFocusAndRestoreBlur(req);
}.bind(this), 0)

这具有在当前线程完成后运行代码的效果。由于某种原因,如果我尝试在同一线程中设置焦点,IE 不尊重我已删除 onblur 处理程序的事实!

因此,通过此修改,当我第一次在几个字段中输入一些数字时,一切都很好。我得到的日志输出如下所示:

在 j_id390 中输入一些内容 并关闭:

warn[16:35:33,091]: blur fired from statementProgramsDataTable:0:j_id390
warn[16:35:33,092]: --- Disabling blur on statementProgramsDataTable:0:j_id397
warn[16:35:33,225]: ------ Focusing on statementProgramsDataTable:0:j_id397
warn[16:35:33,225]: --- Enabling blur on statementProgramsDataTable:0:j_id397

在 j_id397 中输入一些内容并关闭:< /em>

warn[16:35:38,259]: blur fired from statementProgramsDataTable:0:j_id397
warn[16:35:38,260]: --- Disabling blur on statementProgramsDataTable:0:j_id446
warn[16:35:38,390]: ------ Focusing on statementProgramsDataTable:0:j_id446
warn[16:35:38,390]: --- Enabling blur on statementProgramsDataTable:0:j_id446

但是,当我返回到第一个输入字段,覆盖值并关闭选项卡时,我得到以下结果:

warn[17:18:15,454]: blur fired from statementProgramsDataTable:0:j_id390
warn[17:18:15,469]:  --- Disabling blur on statementProgramsDataTable:0:j_id397
warn[17:18:16,870]:  ------ Focusing on statementProgramsDataTable:0:j_id397
warn[17:18:16,874]:  ---  Enabling blur on statementProgramsDataTable:0:j_id397
warn[17:18:18,097]: blur fired from statementProgramsDataTable:0:j_id397
warn[17:18:18,112]:  --- Disabling blur on statementProgramsDataTable:0:j_id397
warn[17:18:19,550]:  ------ Focusing on statementProgramsDataTable:0:j_id397
warn[17:18:19,555]:  ---  Enabling blur on statementProgramsDataTable:0:j_id397
warn[17:18:24,492]: blur fired from statementProgramsDataTable:0:j_id397 
warn[17:18:24,187]:  --- Disabling blur on statementProgramsDataTable:0:j_id397
warn[17:18:24,531]:  ------ Focusing on statementProgramsDataTable:0:j_id397
warn[17:18:24,545]:  ---  Enabling blur on statementProgramsDataTable:0:j_id397

大多数情况下,此循环会持续进行可变次数的迭代,然后停止并正确聚焦输入字段。我见过几次循环似乎是无限的。

看起来 IE 不再考虑 onblur 处理程序的缺失?但只是有时?!

所以,这就是我感到困惑的地方。为什么 IE 表现不一致?我做错了什么?有更好的办法吗?

任何想法将不胜感激。

Val

编辑:

我已经尝试过JeanK建议的方法。它仍然不起作用,但我从这次尝试中学到了一些可能有用的东西。

我用代理包装了原始的“onblur”函数,如下所示:

this.allowBlur = false;
if ( !this._functionsEqual($(this.savedFocusId).onblur, this._proxiedBlur) ) {
  $(this.savedFocusId).onblur = this.proxyOnBlur($(this.savedFocusId).onblur);
}

代理函数本身:

proxyOnBlur : function(method) {
  var object = this;

  this._proxiedBlur = function(event) {
    if ( object.allowBlur ) {
      return method.apply(this, [event || window.event])
    }
  };

  return this._proxiedBlur;
},

现在,我所要做的就是将 this.allowBlur 设置为最后一件事,我应该没问题。问题就在这里。在所有其他浏览器中,当我修改 DOM 树时,会触发 onblur 事件,因此它会被正确阻止。但在 IE6 中,无论我做什么,它都会在我的所有代码之后触发 onblur 事件。我什至尝试过这个:

setTimeout(function() {
  this.allowBlur = true;
}.bind(this), 2)

在我将标志设置为 true 后,我的 this._proxiedBlur 仍然被调用!

所以,问题变成了 - 我需要在哪里重置我的标志,以便它在 IE6 对 DOM 更改做出反应后执行?

I wonder if someone here can help me figure out this problem.

I need to temporarily disable the code in the 'onblur' attribute of an input field, and then re-enable it after. The reason I need to do this is b/c my workflow is as follows:

1) An AJAX event is triggered by the "onblur" attribute of an input field, which resulted from the user tabbing off of the field to go to the next one.
2) The page is updated and my Javascript code is called from the "onafterajax" hook.
3) My code does some serious re-arranging of the DOM, which results in loss of focus on the current input field. So, I must restore focus manually. I've attached a focus handler to all input fields, so I can keep track of which field had focus last, so I know where to put the focus.
4) I call .focus() on the correct input field, which for some reason causes 'onblur' to fire on that same input field. This happens in all browsers. This a) suggests that the field still had focus?! and b) Creates an infinite loop, since Step 1 executes again...

In order to avoid the infinite loop, I've done the following. Before performing any DOM rearrangements, I do this:

if ( window.currentFocusId ) {
   this.savedFocusId = currentFocusId;

   this.onblur_bak = $(this.savedFocusId).onblur;
   $(this.savedFocusId).onblur = null;
   LOG.warn(" --- Disabling blur on " + this.savedFocusId);
}

Then, after I've completed my DOM hackery, I do this:

setFocusAndRestoreBlur : function(req) {
    if ( this.savedFocusId ) {
      var focusElement = req.form.elements[this.savedFocusId];
      LOG.warn(" ------ Focusing on " + focusElement.id);
      if (focusElement) {
        focusElement.focus();
        if (focusElement.select) {
          focusElement.select();
        }
      }

      LOG.warn(" ---  Enabling blur on " + this.savedFocusId);
      $(this.savedFocusId).onblur = this.onblur_bak;

      delete this.onblur_bak;
      delete this.savedFocusId;
    }
}

This works well in all browsers (FF, Chrome, Opera), except for IE6.

In IE6 it kind of works. First of all, in order to make it work in IE at all, I had to modify the call to "setFocusAndRestoreBlur" like so:

setTimeout(function() {
  this.setFocusAndRestoreBlur(req);
}.bind(this), 0)

This has the effect of running the code after the current thread finishes. For some reason IE does not respect the fact that I have removed the onblur handler, if I try to set the focus in the same thread!

So, with this modification, the first time I enter some numbers into a few fields, everything is fine. I get log output that looks like this:

Type something into j_id390 and tab off:

warn[16:35:33,091]: blur fired from statementProgramsDataTable:0:j_id390
warn[16:35:33,092]: --- Disabling blur on statementProgramsDataTable:0:j_id397
warn[16:35:33,225]: ------ Focusing on statementProgramsDataTable:0:j_id397
warn[16:35:33,225]: --- Enabling blur on statementProgramsDataTable:0:j_id397

Type something into j_id397 and tab off:

warn[16:35:38,259]: blur fired from statementProgramsDataTable:0:j_id397
warn[16:35:38,260]: --- Disabling blur on statementProgramsDataTable:0:j_id446
warn[16:35:38,390]: ------ Focusing on statementProgramsDataTable:0:j_id446
warn[16:35:38,390]: --- Enabling blur on statementProgramsDataTable:0:j_id446

However, when I go back to the first input field, overwrite the value and tab off, I get this:

warn[17:18:15,454]: blur fired from statementProgramsDataTable:0:j_id390
warn[17:18:15,469]:  --- Disabling blur on statementProgramsDataTable:0:j_id397
warn[17:18:16,870]:  ------ Focusing on statementProgramsDataTable:0:j_id397
warn[17:18:16,874]:  ---  Enabling blur on statementProgramsDataTable:0:j_id397
warn[17:18:18,097]: blur fired from statementProgramsDataTable:0:j_id397
warn[17:18:18,112]:  --- Disabling blur on statementProgramsDataTable:0:j_id397
warn[17:18:19,550]:  ------ Focusing on statementProgramsDataTable:0:j_id397
warn[17:18:19,555]:  ---  Enabling blur on statementProgramsDataTable:0:j_id397
warn[17:18:24,492]: blur fired from statementProgramsDataTable:0:j_id397 
warn[17:18:24,187]:  --- Disabling blur on statementProgramsDataTable:0:j_id397
warn[17:18:24,531]:  ------ Focusing on statementProgramsDataTable:0:j_id397
warn[17:18:24,545]:  ---  Enabling blur on statementProgramsDataTable:0:j_id397

Most of the time this loop then goes on for a variable number of iterations and then stops with the input field correctly focused. I've seen a few times where the loop appeared to be infinite.

It looks like IE is not respecting the absence of the onblur handler again? But only sometimes?!

So, this is where I'm confused. Why is IE behaving inconsistently? What am I doing wrong? Is there a better way?

Any ideas would be appreciated.

Val

EDIT:

I have tried the approach suggested by JeanK. It still does not work, but I learned something potentially useful from this attempt.

I wrap the original 'onblur' function with a proxy, like this:

this.allowBlur = false;
if ( !this._functionsEqual($(this.savedFocusId).onblur, this._proxiedBlur) ) {
  $(this.savedFocusId).onblur = this.proxyOnBlur($(this.savedFocusId).onblur);
}

And the proxy function itself:

proxyOnBlur : function(method) {
  var object = this;

  this._proxiedBlur = function(event) {
    if ( object.allowBlur ) {
      return method.apply(this, [event || window.event])
    }
  };

  return this._proxiedBlur;
},

Now, all I have to do is set this.allowBlur as the very last thing, and I should be fine. And herein lies the problem. In all other browsers, the onblur event is fired as I modify the DOM tree, so it correctly gets blocked. But in IE6, no matter what I do, it fires the onblur event after all of my code. I even tried this:

setTimeout(function() {
  this.allowBlur = true;
}.bind(this), 2)

and my this._proxiedBlur still gets called after I set the flag to true!

So, the question becomes - Where do I need to put my flag reset so that it executes after IE6 reacts to the DOM changes?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

好久不见√ 2024-10-28 01:05:54

好吧,我明白了。诀窍是在单独的线程中设置焦点:

                setTimeout(function() {
                    this.setFocusAndRestoreBlur(req);
                }.bind(this), 0)

然后使用另一个嵌套的 setTimeout() 重置标志。这似乎在 IE6 中正确排序了事件:

setFocusAndRestoreBlur : function(req) {
  setFocus(req);

  setTimeout(function() {
    this.allowBlur = true;
  }.bind(this), 0)
}

ok, I figured it out. The trick was to set the focus in the separate thread:

                setTimeout(function() {
                    this.setFocusAndRestoreBlur(req);
                }.bind(this), 0)

and then reset the flag with another nested setTimeout(). This seems to sequence the events properly in IE6:

setFocusAndRestoreBlur : function(req) {
  setFocus(req);

  setTimeout(function() {
    this.allowBlur = true;
  }.bind(this), 0)
}
与他有关 2024-10-28 01:05:54

我建议您以逻辑方式禁用模糊。

我的意思是,像这样的事情:

假设这是您的 onblur 事件函数,您可以通过标志来控制它:

function myOnBlur() {
  if (ableToExecute) {
    executeWhatYouNeed();
  }
}

因此,当您执行请求时,您将标志设置为 false,然后在响应和所需的处理之后,您重置flat 为 true,因此您的 onblur 事件可以再次触发您的请求。

我不知道这个简单的控件是否可以帮助你,但是你可以尝试一下。

I suggest that you disable blur in a logic way.

I mean, something like this:

Suppose that this is your onblur event function, you can control it by flags:

function myOnBlur() {
  if (ableToExecute) {
    executeWhatYouNeed();
  }
}

So, when you do your request, you set the flag to false, and then after the response and your needed processing, you reset the flat to true, so your onblur event can trigger your request again.

I don't know if this simple control can help you, but you can try it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文