Захватить *все* отображаемые символы в JavaScript?

Недавно мне дали необычный запрос, с которым мне было очень трудно справиться, который включает в себя захват всех отображаемых символов при вводе в текстовое поле. Настройка выглядит следующим образом:

У меня есть текстовое поле с maxlength 10 символами. Когда пользователь пытается ввести более 10 символов, мне нужно уведомить пользователя о том, что он вводит больше, чем ограничение на количество символов.

Самым простым решением было бы указать maxlength 11, проверить длину для каждого нажатия клавиши и урезать до 10 символов, но это решение кажется немного неуклюжим. Я бы предпочел захватить символ перед keyup и, в зависимости от того, является ли он отображаемым символом, представить уведомление пользователю и предотвратить действие по умолчанию.

Белый список будет сложной задачей, поскольку мы обрабатываем много международных данных.

Я играл с каждой комбинацией keydown, keypress и keyup, читая event.keyCode, < strong>event.charCode и event.what, но я не могу найти ни одной комбинации, которая работала бы во всех браузерах. Лучшее, что я мог сделать, это следующее, которое правильно работает в> = IE6, Chrome5, FF3.6, но не работает в Opera:

ПРИМЕЧАНИЕ. В следующем коде используется jQuery.

$(function(){
  $('#textbox').keypress(function(e){
    var $this = $(this);
    var key = ('undefined'==typeof e.which?e.keyCode:e.which);
    if ($this.val().length==($this.attr('maxlength')||10)) {
      switch(key){
        case 13: //return
        case 9:  //tab
        case 27: //escape
        case 8:  //backspace
        case 0:  //other non-alphanumeric
          break;
        default:
          alert('no - '+e.charCode+' - '+e.which+' - '+e.keyCode);
          return false;
      };
    }
  });
});

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


person Jean-Charles    schedule 21.04.2010    source источник
comment
Также не забывайте, что данные пользователя ВСТАВЛЯЮТСЯ в ваш элемент управления.   -  person vladr    schedule 21.04.2010
comment
Спасибо за совет. Я уже думал реализовать обработчик onPaste, но, учитывая контекст ввода, вероятность того, что пользователь будет вставлять в него, невелика (не говоря уже о том, насколько несовершенна поддержка onPaste).   -  person Jean-Charles    schedule 21.04.2010


Ответы (4)


Самым простым решением было бы указать максимальную длину 11, проверить длину при каждом нажатии клавиши и урезать до 10 символов, но это решение кажется немного неуклюжим.

Его также легко победить с помощью вырезания/вставки, перетаскивания, щелчка правой кнопкой мыши-отмены/повторения и т. д. Не существует надежного способа получить каждый потенциальный бит ввода, кроме опроса.

Почему бы не установить для maxlength значение 10, чтобы браузер правильно применял ограничение и просто показывал предупреждение при еще одной попытке нажатия клавиши? Вам не нужно предотвращать какие-либо действия по умолчанию, потому что браузер уже позаботится о длине, поэтому количество проверок ключей, которые вам нужно выполнить, меньше.

<input id="x" maxlength="10"/>
<div id="x-warning" style="display: none;">can't type any more!</div>
<script type="text/javascript">
    function LengthMonitor(element, warning) {
        element.onkeypress= function(event) {
            if (event===undefined) event= window.event;
            var code= 'charCode' in event? event.charCode : 'which' in event? event.which : event.keyCode;
            var full= element.value.length===element.maxLength;
            var typed= !(code<32 || event.ctrlKey || event.altKey || event.metaKey);
            warning.style.display= (full & typed)? 'block' : 'none';
        };
        element.onblur= function() {
            warning.style.display= 'none';
        };
    }

    LengthMonitor(document.getElementById('x'), document.getElementById('x-warning'));
</script>
person bobince    schedule 21.04.2010
comment
До некоторой степени работает, но свойство charCode не поддерживается в IE и Opera. - person Jean-Charles; 21.04.2010
comment
Да, вы можете попробовать вернуться к which, а затем к keyCode для этих браузеров. К сожалению, keypress шаткий (например, в IE вы не видите разницы между page-up и !). Если вы хотите сделать это надежно, вам придется вместо этого перехватить keydown и сохранить список кодов клавиш, которые означают или не означают реальный символ. Не очень весело. - person bobince; 21.04.2010

Поскольку вы уже используете JQuery, .validate() отлично подходит для форм. Просто установите правило maxlength для своего поля, и все готово. Например.

$("form[name='myform']").validate({
    rules: {
        myfield: {required:true, maxlength:10}
    }
});
person dnagirl    schedule 21.04.2010
comment
Спасибо за подсказку, но это не решает проблему. 10 символов — это жесткое ограничение, мне нужно проверить, пытается ли пользователь ввести больше жесткого ограничения. - person Jean-Charles; 21.04.2010

У меня возникла смутно похожая ситуация в веб-приложении, над которым я работаю, где мне нужно было дать обратную связь пользователю в режиме реального времени, когда они вводили данные во входные данные.

Честно говоря, лучшим решением, которое я придумал, было просто использовать setTimeout для периодического опроса поля ввода. Я сделал несколько тестов, чтобы найти хороший баланс между скоростью отклика и эффективностью (я думаю, ~ 400 мс).

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

Это не так элегантно, как хотелось бы, но работает.

Если вы действительно хотите это сделать, я бы смотрел ввод в режиме реального времени, проверяя его длину. Если он превышает лимит, нарежьте его и предупредите пользователя.

Конечно, это не заменит другую проверку.

Я бы также подумал, что это может быть ненужным. Я полагаю, это хорошо, но большинство веб-сайтов обходятся жестким ограничением и проверкой при отправке.

person MisterMister    schedule 22.04.2010

Как насчет предоставления сообщения пользователю, когда он превышает лимит, но без усечения его ввода? Вы можете предотвратить отправку с помощью события onsubmit, и у пользователя никогда не будет плохого опыта maxlength или переходного ввода. Вы можете выделить поле красным цветом или отобразить значок, чтобы действительно донести суть.

Однако все это на стороне клиента, поэтому, если вам действительно нужно проверить ввод, это должно быть встроено в логику на стороне сервера цели отправки (в случае формы).

В качестве альтернативы, если это происходит в режиме реального времени, свяжите логику с переменной, которая устанавливается событием нажатия клавиши. Если предел длины превышен, представьте сообщение об ошибке, не усекайте и не обновляйте приватную переменную.

person Anthony DiSanti    schedule 27.04.2010