LINUX.ORG.RU

maxlength, value.length и неправильная работа с переносами строк в textarea

 , , , ,


1

1

Столкнулся с тем что атрибут maxlength и js-свойство value.length неправильно работают с textarea: если в поле есть двухсимвольные переносы строк (\r\n) — они считают их одним символом, соответственно есть риск не вписаться в ограничение на количество символов на бэкенде. Наговнокодил костыль-функцию для решения проблемы, возвращающую скорректированное значение maxlength в соответствии с количеством переносов строк в поле:

function maxlengthfix(str, maxlength)
	{
	var newlines = (str.split(/\r/).length - 1) + (str.split(/\n/).length - 1);
	maxlength = maxlength-newlines;
	return (maxlength);
	} 
Но всё же интересно: такое поведение — это задокументированная бага фича или таки баг?

Если смотреть в спек, то должно работать. Все переносы должны считаться за два символа и в двухсимвольном же виде отправляться при сабмите форме. Забавно, что element.value и то, что отправляется с формой по разному нормализуются.

http://www.w3.org/TR/html5/forms.html#the-textarea-element

zz ★★★★
()

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

s="foo\r\nbar"
console.log(s.length, s.replace(/\r/g, "").length)
//  8 7
J-yes-sir
()

запусти вот эту хрень


<!DOCTYPE html>
<html>
  <head>
<meta charset="windows-1251" />
  </head>
  <body>

<textarea maxlength="5">
</textarea>
<button>
push
</button>

<script>
s="foo\r\nbar"
textarea=document.querySelector("textarea")
textarea.value=s
button=document.querySelector("button")
button.onclick=function(){
   console.log(
   /\n/.test(textarea.value),
   /\r/.test(textarea.value),
   textarea.value.length,
   s.length
)}

</script>
  </body>

</html>

должно быть true false 7 8

J-yes-sir
()

А вообще maxlength — фуфельное св-во. Как видно из примера выше, при динамической вставке скриптом, оно ложит х на проверку.

J-yes-sir
()
Ответ на: комментарий от J-yes-sir

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

4.2, если бы проблема не проявлялась — я бы и не извращался. Возможно зависит от используемой платформы, я проверял при вставке текста на жиролисе в оффтопе.

А если бы даже было так как ты думаешь, достаточно было просто фильтрануть \r, выкинуть их и все

Написал же что наговнокодил на скорую руку в поисках причины этой проблемы. Костыльной проблеме — костыльное решение!

h578b1bde ★☆
() автор топика
Ответ на: комментарий от J-yes-sir

А если бы даже было так как ты думаешь, достаточно было просто фильтрануть \r, выкинуть их и все

Нет, тут проблема не в этом. Накатал тестовый скрипт:

<?php
	define('maxlength', 100);
	if (isset($_POST['str']))
		{
		$str = &$_POST['str'];
		file_put_contents('maxlength.txt', $str);
		}
	else $str = '';
?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<title>maxlength</title>
		<script type="text/javascript">
			<!--
				function maxlength()
					{
					document.getElementById('wtf').value = 'all: '+ document.getElementById('str').value.length + "\n";
					document.getElementById('wtf').value += 'w/o r: '+ document.getElementById('str').value.replace(/\r/g, '').length + "\n";
					document.getElementById('wtf').value += 'w/o n: '+ document.getElementById('str').value.replace(/\n/g, '').length + "\n";
					document.getElementById('send').onclick = 'return true';
					document.getElementById('send').value = 'Send!';
					}
			//-->
		</script>
	</head>
	
	<body>
		<p><?= strlen($str); ?></p>
		<form action="" method="post">
		<textarea name="str" id="str" rows="15" cols="50" maxlength="<?= maxlength; ?>"></textarea><br>
		<input type="submit" value="Test!" id="send" onclick="maxlength(); return false;"><br>
		<textarea id="wtf" rows="5" cols="20"></textarea>
	</body>
</html>

Сохраняем с переносами строк Unix. Теперь вставляем код этого же скрипта в textarea, через js получаем:

all: 100
w/o r: 100
w/o n: 95

И на сервере получаем значение 105 и файл maxlength.txt с переносами строк Windows и таким же количеством символов, т.е. в element.value и в том, что отправляет форма — разные переносы, о чём и говорил zz. Поэтому мой вариант с корректированием maxlength работает, а твой с фильтрацией \r — нет.

h578b1bde ★☆
() автор топика
Ответ на: комментарий от zz

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

function maxlengthfix(str, maxlength)
	{
	if (((navigator.product == 'Gecko') && (!window.chrome)) || (window.opera))
		{
		var newlines = (str.split(/\r/).length - 1) + (str.split(/\n/).length - 1);
		maxlength = maxlength-newlines;
		}
	return (maxlength);
	}

h578b1bde ★☆
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.