У меня проблемы с событием keydown и автозаполнением в Firefox на Mac - PullRequest
12 голосов
/ 21 февраля 2010

Это сводит меня с ума. Трудно объяснить, но я пойду.

У меня есть одно поле ввода текста на первой странице моего сайта. Я закодировал наблюдателя события keydown, который проверяет keyCode и, если его ENTER (или его эквивалент), он будет проверять входное значение (электронная почта). Если адрес электронной почты является действительным и уникальным в БД, он отправит форму. Базовые вещи, или вы так думаете.

Если я введу свой адрес электронной почты в поле и нажму клавишу ввода, он отлично работает во всех браузерах. Однако, если я наберу первые пару букв, а затем с помощью клавиш со стрелками выберите электронное письмо из выпадающего списка истории (надеюсь, вы понимаете, что я имею в виду здесь), а затем нажмите клавишу ВВОД, результат будет другим. Значение поля формы фиксируется как просто пара букв, которые я набрал, и поэтому проверка не проходит. Кажется, что когда я нажимаю клавишу ввода, чтобы «выбрать» электронное письмо из выпадающего списка истории, браузер прерывает его, как если бы я печатал.

В Chrome и Safari все работает как надо. Так как это должно означать, что когда вы нажимаете ввод, чтобы «выбрать» электронное письмо из выпадающего списка истории, все, что он делает, это помещает этот адрес электронной почты в текстовое поле. Только при втором нажатии клавиши ВВОД запускается наблюдатель события, и электронная почта проверяется.

Надеюсь, что кто-то может пролить свет на то, почему это происходит ... Мое инстинктивное чувство - это браузер, и я не смогу его исправить.

Спасибо Lee

EDIT: Чтобы внести ясность в мой вопрос, позвольте мне добавить, что я использую событие «keydown», чтобы зафиксировать момент, когда нажата клавиша ввода. Я пробовал событие «keyup», и это решило мою проблему выше, но затем я не могу остановить отправку формы самостоятельно. Событие «keyup» запускает ПОСЛЕ поведения по умолчанию, поэтому это неправильный выбор для этого.

ДОПОЛНИТЕЛЬНОЕ РЕДАКТИРОВАНИЕ:

Еще раз спасибо, и, между прочим, ваш английский отличный (в ответ на ваш комментарий о плохом английском).

Я изменил свой обработчик событий из этого:

$("emailInputBox").observe("keydown", function(event) {
    return submitViaEnter(event, submitSignupFormOne);
});

на это:

$("emailInputBox").observe("keydown", function(event) {
    setTimeout(submitViaEnter.curry(event, submitSignupFormOne),0);
});

submitViaEnter

function submitViaEnter(event, callback) {
var code = event.keyCode;
if (code == Event.KEY_RETURN) {
    event.stop();
    return callback(event);
}
return true;
}

Кажется, что работает, но проблема сейчас в том, что браузеру разрешено выполнять действие по умолчанию перед запуском функции submitViaEnter, которая означает, что форма отправляется, когда я нажимаю ENTER.

Ответы [ 2 ]

7 голосов
/ 21 февраля 2010

Ответ на оригинальный вопрос

Да, это ошибка Gecko (но не для Mac).

Последняя часть этого комментария содержит описание обходного пути: используйте время ожидания.

[править], так как вы попросили разъяснить ошибку

Когда вы нажимаете Enter, и автозаполнение активно, Firefox (ошибочно) сначала запускает обработчик ключа страницы, затем внутренний обработчик ключа браузера, который закрывает всплывающее окно автозаполнения и обновляет значение текстовой области, в то время как он, вероятно, должен просто срабатывать это во всплывающем окне автозаполнения и только дайте странице знать, что значение текстового поля изменилось.

Это означает, что когда вызывается ваш обработчик ключа, обработчик автозаполнения еще не запущен - всплывающее окно автозаполнения все еще открыто, а значение текстового поля похоже на то, которое было до того, как произошло автозаполнение.

Когда вы добавляете вызов setTimeout к своему обработчику клавиш, вы говорите браузеру: «Эй, запустите эту функцию сразу после того, как вы закончили делать вещи, уже находящиеся в вашем списке дел P1». Таким образом, обработчик автозаполнения запускается, поскольку он уже находится в списке дел, затем запускается код, который вы указали для тайм-аута - когда всплывающее окно автозаполнения уже закрыто и значение текстового поля обновлено.

[править] отвечая на вопрос в разделе «Дальнейшее редактирование»

правый. Вам нужно отменить действие по умолчанию в обработчике событий, а не в тайм-ауте, если вы хотите, чтобы оно работало:

function onKeyPress(ev) {
  if (... enter pressed ...) {
    setTimeout(function() {
      ... check the new textbox value after letting autocomplete work ...
    }, 0);
    // but cancel the default behavior (submitting the form) directly in the event listener
    ev.preventDefault();
    return false;
  }
}

Если бы вы все еще хотели отправить форму на Enter, это было бы более интересное упражнение, но, похоже, вы этого не делаете.

2 голосов
/ 21 февраля 2010

ок отсортировано. Большое спасибо за Вашу помощь. Это была функция карри, которую я пропустил раньше. Я пытался работать над событием в рамках функции setTimeout.

Это работает ниже. SubmitViaEnter вызывается из eventobserver и отвечает на событие keyDown:

function submitViaEnter(event, callback) {
var code = event.keyCode;
if (code == Event.KEY_RETURN) {
    event.stop();
    setTimeout(callback.curry(event),0);        
    // return callback(event);
    // return false;    
}
return true;
}

Остановка действия по умолчанию внутри eventObserver означала, что нельзя вводить символы. Поэтому я застрял внутри предложения if ENTER.

...