Ошибка с $ (this) .val (). Length в chrome - неверное значение - PullRequest
1 голос
/ 28 декабря 2010

Я использую следующий JQuery в Chrome: $(this).val().length это представляет поле ввода.Теперь в любом другом браузере это работает нормально, но в Chrome он иногда возвращает неправильное значение.Скажем, у меня есть 3 символа в поле ввода, но alert($(this).val().length); скажет 4.

Кто-нибудь знает, почему это происходит и возможное решение?

edit: некоторый код

$("#fieldset1 input[type=text]").keyup(function(e){
    if($(this).val().length == $(this).attr('maxlength')){
                if($(this).parent().children().last().attr('id') == $(this).attr("id")){
                    $(this).parent().next().find(':input').focus();
                }else{
                    $(this).next("input").focus();
                }
            }
});

Я добавил предупреждение после первого, если когда заметил это поведение.

edit2: поместил его в JSFiddle: http://jsfiddle.net/QyyBV/

HTML:

<fieldset id ="test">
  <input type="text" id="1" maxlength="5" size="5"/>
  <input type="text" id="2" maxlength="5" size="5"/>
  <input type="text" id="3" maxlength="5" size="5"/>
  <input type="text" id="4" maxlength="5" size="5"/>
  <input type="text" id="5" maxlength="5" size="5"/>
</fieldset>

JavaScript:

      $(document).ready(function() {

          $("#test input[type=text]").keydown(function(e){
            if(e.which == 8){
              if($(this).val().length == 0){
                $(this).prev().focus().val($(this).prev().val());
              }
            }
          });

          $("#test input[type=text]").keyup(function(e){


if($(this).val().length == $(this).attr('maxlength') ){
          if($(this).parent().children().last().attr('id') == $(this).attr("id")){
            $(this).parent().next().find(':input').focus();
          }else{
            $(this).next("input").focus();
          }
        }
      });

  });

Сценарий : я ввожу 5 4 раза, а затем 5 раз, я возвращаюсь, пока 4-е поле также не пусто.Иногда (но не всегда), когда я снова вхожу в 4 5, я прыгаю, несмотря на то, что он должен прыгать в 5 5.Но это не всегда происходит.Иногда мне нужно сделать это снова, чтобы увидеть эту проблему в Chrome.

1 Ответ

9 голосов
/ 28 декабря 2010

Обновление 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...