Интересно, может ли кто-нибудь здесь помочь мне разобраться с этой проблемой.
Мне нужно временно отключить код в атрибуте «onblur» поля ввода, а затем снова включить его. Причина, по которой мне нужно это сделать, потому что мой рабочий процесс следующий:
1) Событие AJAX инициируется атрибутом «onblur» поля ввода, что является результатом того, что пользователь ушел с поля, чтобы перейти к следующему.
2) Страница обновлена, и мой код Javascript вызывается из ловушки " onafterajax ".
3) Мой код выполняет серьезную реорганизацию DOM, что приводит к потере фокуса на текущем поле ввода. Итак, я должен восстановить фокус вручную. Я подключил обработчик фокуса ко всем полям ввода, чтобы я мог отслеживать, какое поле имело фокус в последний раз, и поэтому я знаю, куда поместить фокус.
4) Я вызываю .focus () в правильном поле ввода, что по какой-то причине вызывает ' onblur ' в этом же поле ввода. Это происходит во всех браузерах. Это а) говорит о том, что поле все еще было в фокусе ?! и б) Создает бесконечный цикл, так как Шаг 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 ведет себя непоследовательно? Что я делаю неправильно? Есть ли лучший способ?
Любые идеи приветствуются.
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 в качестве самой последней вещи , и я должен быть в порядке. И в этом заключается проблема. Во всех других браузерах событие onblur вызывается при изменении дерева DOM, поэтому оно корректно блокируется. Но в IE6, что бы я ни делал, он запускает событие onblur после всего моего кода. Я даже попробовал это:
setTimeout(function() {
this.allowBlur = true;
}.bind(this), 2)
и мой this._proxiedBlur по-прежнему вызывается после того, как я установил флаг в true!
Итак, возникает вопрос - Куда мне нужно поместить сброс флага, чтобы он выполнялся после того, как IE6 отреагирует на изменения DOM?