Обновление 4 :
Я не могу воспроизвести проблему, используя Chrome (для Linux) с вашей скрипкой.
Но я заметил, что вы используете keydown
для одного аспекта замаскированного редактирования, а keyup
для другого аспекта. Если бы не веская причина для использования keyup
вместо keydown
, я бы использовал keydown
для обоих & mdash; не в последнюю очередь потому, что тогда повторение клавиш работает правильно с созданным вами замаскированным редактором (например, если я нажимаю «5» и удерживаю его, я переключаюсь с поля на поле, как я ожидаю, вместо остановки в конце первого поля ).
Вот моя слегка отредактированная версия с использованием keydown
. Кажется, работает нормально (но тогда ваш оригинал также не показал проблему для меня, может быть для конкретной ОС):
$(document).ready(function() {
$("#test input[type=text]").keydown(function(e){
var $this = $(this),
val = $this.val(),
$prev,
$parent;
if(e.which == 8){
if(val.length == 0){
$prev = $this.prev();
$prev.focus().val($prev.val());
}
}
else if(val.length == $this.attr('maxlength') ){
$parent = $this.parent();
if($parent.children().last().attr('id') == $this.attr("id")){
$parent.next().find(':input').focus();
}else{
$this.next("input").focus();
}
}
});
});
Кто знает, возможно, это работает вокруг странной проблемы, которую вы видите.
Не по теме 1 :
Я не делал этого выше, но поскольку next()
вернет пустой объект jQuery, если для селектора не найдено совпадений, вы можете заменить
if($parent.children().last().attr('id') == $this.attr("id")){
$parent.next().find(':input').focus();
}else{
$this.next("input").focus();
}
с
$next = $this.next("input");
if($next.length == 0) {
$next = $parent.next().find(':input:first');
}
$next.focus();
... (объявив $next
с var
наверху, конечно). Это устраняет необходимость в $parent.children().last().attr('id') == $this.attr("id")
, что требует больше работы, чем необходимо. И вы можете добавить эквивалентную функциональность в Backspace:
if(val.length == 0){
$prev = $this.prev();
if($prev.length == 0) {
$prev = $this.parent().prev().find(':input:last');
}
$prev.focus().val($prev.val());
}
Живой пример . FWIW.
Не по теме 2 : идентификаторы, которые вы задали для полей в своем примере (1
, 2
и т. Д.), В то время как действительные HTML идентификаторы недопустимо для использования с селекторами CSS . Идентификаторы в CSS не могут начинаться с цифры (или несколько других вещей, см. Ссылку для подробностей). Я упоминаю об этом, потому что мы часто используем CSS-селекторы в jQuery ...
Не по теме 3 : Многократный вызов $(this)
делает ваш браузер работать тяжелее, чем нужно. Каждый раз, когда вы делаете это, jQuery завершает выполнение двух вызовов функций и выделение памяти. Это может не быть проблемой, но редко есть причина не кэшировать результат в локальной переменной, например var $this = $(this);
.
Предыдущие обновления ответа :
Обновление 3 :
Вы упоминали, что это происходило время от времени, и упомянули backspace, но цитируемый код ничего не делает с backspace. Так что действительно, урезанный, автономный, функциональный пример будет ключом к поиску этого. Звучит как разница между браузерами в порядке событий и фокуса (так как вы изменяете фокус), но ...
Обновление 2 :
Повторяйте ваш комментарий, что это обработчик keyup
, я все еще не вижу такого поведения:
$('#theField').keyup(function() {
if ($(this).val().length == $(this).attr("maxlength")) {
display("Field is at maximum, length = " +
$(this).val().length);
}
else {
display("Field is not at maximum, length = " +
$(this).val().length);
}
});
Живая копия
Обратите внимание, что ваш последний опубликованный код (на момент написания статьи) имеет синтаксическую ошибку (должна заканчиваться });
, а не просто };
), но я предполагаю, что это побочный эффект копирования и вставки.
Рекомендуйте сократить код до минимума, разместив его в JSBin или jsFiddle или аналогичном, и мы поможем вам найти проблему.
Обновление 1 :
Полагаю ( больше контекста помогло бы! Что это за обработчик событий? ), вы делаете это в обработчике keypress
. На момент события keypress
персонаж еще не был добавлен в поле. Живой пример :
$('#theField').keypress(function() {
if ($(this).val().length == $(this).attr("maxlength")) {
display("Field is at maximum, length = " +
$(this).val().length);
}
else {
display("Field is not at maximum, length = " +
$(this).val().length);
}
});
function display(msg) {
$('<p/>').html(msg).appendTo(document.body);
}
Насколько я знаю, это надежное поведение во всех браузерах, поэтому, если вы действительно просматриваете только Chrome, возможно, вы используете другое событие, с которым у меня мало опыта. Например, в Firefox все вышеперечисленное прекрасно.
В любом случае, если проблема в том, что событие происходит слишком рано для того, что вы пытаетесь сделать, вы можете легко отложить его:
$('#theField').keypress(function() {
var $this = $(this);
setTimeout(function() {
if ($this.val().length == $this.attr("maxlength")) {
display("Field is at maximum, length = " +
$this.val().length);
}
else {
display("Field is not at maximum, length = " +
$this.val().length);
}
}, 0);
});
Живой пример
Оригинальный ответ :
Я подозреваю, что в поле действительно четыре символа. Конечно, он работает, как и ожидалось, в Chrome, с этим живым примером :
HTML:
<form>
<input type='text' id='theField' value='123'>
</form>
JavaScript:
display('Length is ' + $('#theField').val().length);
function display(msg) {
$('<p/>').html(msg).appendTo(document.body);
}