Chrome считает неправильно символы в текстовой области с атрибутом maxlength

Вот пример:

$(function() {
  $('#test').change(function() {
    $('#length').html($('#test').val().length)
  })
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id=test maxlength=10></textarea>
length = <span id=length>0</span>

Заполните текстовое поле строками (по одному символу в строке), пока браузер не разрешит. Когда вы закончите, оставьте textarea, и js code будет также вычислять символы.

Так что в моем случае я мог ввести только 7 символов (включая пробелы), прежде чем Chrome остановил меня. Хотя значение атрибута maxlength равно 10:

Imgur

10 ответов

Решение

Ваши возвраты каретки считаются 2 символами каждый, когда дело доходит до длины.

1\r\n
1\r\n
1\r\n
1

Но кажется, что JavaScript мог только один из \r\n (Я не уверен, какой из них), который только добавляет до 7.

Вот как сделать так, чтобы ваш код JavaScript соответствовал количеству символов, которое, по мнению браузера, находится в текстовой области:

http://jsfiddle.net/FjXgA/53/

$(function () {
    $('#test').keyup(function () {
        var x = $('#test').val();

        var newLines = x.match(/(\r\n|\n|\r)/g);
        var addition = 0;
        if (newLines != null) {
            addition = newLines.length;
        }

        $('#length').html(x.length + addition);
    })
})

Обычно вы просто подсчитываете количество разрывов строк в текстовом поле и добавляете 1 к числу символов для каждого.

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

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

var len = $('#test').val().replace(/\r(?!\n)|\n(?!\r)/g, "\r\n").length;

Затем используйте эту переменную, чтобы отобразить длину значения текстовой области, или ограничить ее и т. Д.

По неизвестным причинам jQuery всегда преобразует все новые строки в значение <textarea> одному персонажу. То есть, если браузер дает это \r\n для новой строки jQuery гарантирует, что это просто \n в возвращаемом значении .val(),

Chrome и Firefox считают длину <textarea> теги таким же образом для целей "maxlength".

Однако спецификация HTTP настаивает на том, что переводы строк должны быть представлены как \r\n, Таким образом, jQuery, webkit и Firefox все ошибаются.

В результате "maxlength" на <textarea> Тэги практически бесполезны, если ваш серверный код действительно имеет фиксированный максимальный размер значения поля.

изменить - на данный момент (в конце 2014 года) похоже, что Chrome (38) ведет себя правильно. Firefox (33), тем не менее, не считает каждый жесткий возврат 2-мя символами.

Похоже, что javascript также учитывает длину символа новой строки.

Попробуйте использовать:


var x = $('#test').val();

x = x.replace(/(\r\n|\n|\r)/g,"");    

$('#length').html(x.length);

Я использовал это в твоей скрипке, и это работало. Надеюсь это поможет.

Это потому, что новая строка на самом деле 2 байта, и, следовательно, 2 длинные. JavaScript не видит это таким образом, и поэтому он будет считать только 1, что в сумме составляет 7 (3 новых строки)

Вот более универсальное решение, которое переопределяет функцию val в jQuery. В скором времени сделаем эту проблему в блоге и разместим ссылку здесь.

var originalVal = $.fn.val;
$.fn.val = function (value) {
    if (typeof value == 'undefined') {
        // Getter

        if ($(this).is("textarea")) {
            return originalVal.call(this)
                .replace(/\r\n/g, '\n')     // reduce all \r\n to \n
                .replace(/\r/g, '\n')       // reduce all \r to \n (we shouldn't really need this line. this is for paranoia!)
                .replace(/\n/g, '\r\n');    // expand all \n to \r\n

            // this two-step approach allows us to not accidentally catch a perfect \r\n
            //   and turn it into a \r\r\n, which wouldn't help anything.
        }

        return originalVal.call(this);
    }
    else {
        // Setter
        return originalVal.call(this, value);
    }
};

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

HTML:

<textarea id="content" rows="5" cols="15" maxlength="250"></textarea>

JS:

var getContentWidthWithNextLine = function(){
    return 250 - content.length + (content.match(/\n/g)||[]).length;
}
var value = $('#textarea').val();
var numberOfLineBreaks = (value.match(/\n/g)||[]).length;
$('#textarea').attr("maxlength",500+numberOfLineBreaks);

отлично работает на гугле уже в IE надо избегать скрипта! В IE "разрыв строки" считается только один раз, поэтому избегайте этого решения в IE!

Текстовые области все еще не полностью синхронизированы между браузерами. Я заметил две основные проблемы: возврат каретки и кодировка символов

Возврат каретки

По умолчанию обрабатываются как 2 символа \ r \ n (стиль Windows).

Проблема в том, что Chrome и Firefox будут считать его одним символом. Вы также можете выбрать его, чтобы увидеть, что в качестве пробела выбран невидимый символ.

Обходной путь найден здесь:

var length = $.trim($(this).val()).split(" ").join("").split('\n').join('').length;

Слово JQuery учитывается при разрыве строки пользовательского типа

Internet Explorer, с другой стороны, будет считать его за 2 символа.

Их представление:

Двоичный код : 00001101 00001010

Hex: 0D0A

и представлены в UTF-8 как 2 символа и рассчитаны для максимальной длины как 2 символа.

HTML-сущности могут быть

1) Создано из кода JavaScript:

<textarea id='txa'></textarea>

document.getElementById("txa").value = String.fromCharCode(13, 10);

2) Разобрано с содержания текстовой области:

Код Анси: & # 13; & # 10;

<textarea>Line one.&#13;&#10;Line two.</textarea>

3) Вставлено с клавиатуры Клавиша Enter

4) Определяется как многострочное содержимое текстового поля

<textarea>Line one.
Line two.</textarea>

Кодировка символов

Кодировка символов поля ввода, такого как textarea, не зависит от кодировки символов страницы. Это важно, если вы планируете считать байты. Таким образом, если у вас есть мета-заголовок для определения кодировки ANSI вашей страницы (с 1 байтом на символ), содержимое вашего текстового поля будет по-прежнему UTF-8 с 2 байтами на символ.

Обходной путь для кодировки символов представлен здесь:

function htmlEncode(value){
  // Create a in-memory div, set its inner text (which jQuery automatically encodes)
  // Then grab the encoded contents back out. The div never exists on the page.
  return $('<div/>').text(value).html();
}

function htmlDecode(value){
  return $('<div/>').html(value).text();
}

HTML-кодировка теряется при чтении атрибута из поля ввода

Другие вопросы по тегам