Javascript 暂时删除;onblur";IE中的处理程序

Javascript 暂时删除;onblur";IE中的处理程序,javascript,internet-explorer,onblur,Javascript,Internet Explorer,Onblur,我想知道这里是否有人能帮我解决这个问题 我需要暂时禁用输入字段的“onblur”属性中的代码,然后重新启用它。我需要这样做的原因是b/c我的工作流程如下: 1) AJAX事件由输入字段的“onblur”属性触发,这是由于用户从该字段切换到下一个字段而导致的。 2) 页面将被更新,我的Javascript代码将从“onafterajax”钩子中调用。 3) 我的代码对DOM进行了一些严重的重新安排,这会导致对当前输入字段失去焦点。所以,我必须手动恢复焦点。我已将焦点处理程序附加到所有输入字段,因此

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

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

1) AJAX事件由输入字段的“onblur”属性触发,这是由于用户从该字段切换到下一个字段而导致的。
2) 页面将被更新,我的Javascript代码将从“onafterajax”钩子中调用。
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);
}
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;
    }
}
然后,在我完成DOM hackery之后,我会这样做:

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

   this.onblur_bak = $(this.savedFocusId).onblur;
   $(this.savedFocusId).onblur = null;
   LOG.warn(" --- Disabling blur on " + this.savedFocusId);
}
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;
    }
}
这在除IE6之外的所有浏览器(FF、Chrome、Opera)中都能很好地工作

在IE6中,它可以正常工作。首先,为了让它在IE中工作,我必须修改对“setFocusAndRestoreBlur”的调用,如下所示:

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

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

this.allowBlur = false;
if ( !this._functionsEqual($(this.savedFocusId).onblur, this._proxiedBlur) ) {
  $(this.savedFocusId).onblur = this.proxyOnBlur($(this.savedFocusId).onblur);
}
在j_id390中键入一些内容,然后关闭选项卡:

在j_id397中键入一些内容并关闭选项卡:

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

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的行为不一致?我做错了什么?有更好的办法吗

任何想法都将不胜感激

瓦尔

编辑:

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

我将原始的“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设置为最后一件事,我应该没事了。问题就在这里。在所有其他浏览器中,onblur事件是在我修改DOM树时触发的,因此它会被正确地阻止。但在IE6中,无论我做什么,它都会在我的所有代码之后触发onblur事件。我甚至试过:

setTimeout(function() {
  this.allowBlur = true;
}.bind(this), 2)
我的这个._proxiedBlur在我将标志设置为true后仍然会被调用


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

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

我是说,像这样的事情:

this.allowBlur = false;
if ( !this._functionsEqual($(this.savedFocusId).onblur, this._proxiedBlur) ) {
  $(this.savedFocusId).onblur = this.proxyOnBlur($(this.savedFocusId).onblur);
}
假设这是onblur事件函数,您可以通过标志来控制它:

function myOnBlur() {
  if (ableToExecute) {
    executeWhatYouNeed();
  }
}
因此,在执行请求时,将标志设置为false,然后在响应和所需的处理之后,将平面重置为true,这样onblur事件就可以再次触发请求


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

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

我是说,像这样的事情:

this.allowBlur = false;
if ( !this._functionsEqual($(this.savedFocusId).onblur, this._proxiedBlur) ) {
  $(this.savedFocusId).onblur = this.proxyOnBlur($(this.savedFocusId).onblur);
}
假设这是onblur事件函数,您可以通过标志来控制它:

function myOnBlur() {
  if (ableToExecute) {
    executeWhatYouNeed();
  }
}
因此,在执行请求时,将标志设置为false,然后在响应和所需的处理之后,将平面重置为true,这样onblur事件就可以再次触发请求


我不知道这个简单的控件是否能帮助您,但您可以试试。

好的,我想出来了。诀窍是在单独的线程中设置焦点:

                setTimeout(function() {
                    this.setFocusAndRestoreBlur(req);
                }.bind(this), 0)
然后使用另一个嵌套的setTimeout()重置标志。这似乎是IE6中事件的正确顺序:

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

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

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

                setTimeout(function() {
                    this.setFocusAndRestoreBlur(req);
                }.bind(this), 0)
然后使用另一个嵌套的setTimeout()重置标志。这似乎是IE6中事件的正确顺序:

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

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

不幸的是,我不能控制onblur函数。这是由a4j框架编写的,因此我无法轻松修改其代码。当然,我可以做一个包装器函数,我想。。。我仍然需要替换这个函数,但我会尝试一下,看看是否有不同的行为Jean,我用你建议的结果更新了我的帖子。有什么想法吗?谢谢。不幸的是,我不能控制onblur函数。这是由a4j框架编写的,因此我无法轻松修改其代码。当然,我可以做一个包装器函数,我想。。。我仍然需要替换这个函数,但我会尝试一下,看看是否有不同的行为Jean,我用你建议的结果更新了我的帖子。有什么想法吗?谢谢。最好的解决方案应该是,从您的范围中删除IE6。我从未遇到过这种情况,但如果它起作用,我会记住这一点。最好的解决方案应该是,将IE6从您的范围中删除EHH。我从来没有遇到过这种情况,但如果它起作用,我会记住这一点。