1

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

我需要暂时禁用输入字段的“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);
}

然后,在我完成了我的 DOM 黑客之后,我会这样做:

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 中输入一些内容并关闭:

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

任何想法,将不胜感激。

瓦尔

编辑:

我已经尝试过 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 更改做出反应后执行?

4

2 回答 2

1

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

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

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

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

  setTimeout(function() {
    this.allowBlur = true;
  }.bind(this), 0)
}
于 2011-03-12T00:58:27.943 回答
0

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

我的意思是,像这样:

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

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

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

不知道这个简单的控件能不能帮到你,不过你可以试试。

于 2011-03-10T00:06:02.350 回答