Pull to refresh

Очень длинные слова — что делать?

Reading time 2 min
Views 16K

Суть проблемы


Возможность пользователя ввести оооочень длинное слово без пробелов, и тем самым «взорвать» layout — это старая проблема. Вот так она решается на Хабре.

Решать её можно несколькими способами.

Через стили конечного div


1) style="word-wrap: break-word" — но этот способ IE-only
2) style="overflow: auto; white-space: nowrap" — работает везде, стандартное решение. Но появляются полосы прокрутки
3) style="overflow: hidden; white-space: nowrap" — работает везде, стандартное решение. «Теряется» часть слова (невидна).

Из PHP


4) разбить слово мягкими переносами через каждые N символов. Где N — максимально допустимая длина слова, которую вы установили.
5) удалить такое слово

В текущем проекте я использовал первые четыре подхода. Последний не казался мне необходимым.

Казнить нельзя помиловать


По требованию заказчика был добавлен скрипт контекстной рекламы. И тестер сразу нашёл проблему — он вводил слишком длинное слово, и рекламная система (она ведь контекстная) при попытке отправить такое слово для обработки себе на сервер (даже, если слово было разбито мягкими переносами) просто вешала браузер. Точнее, не то чтобы совсем вешала. IE реагировал и через секунд 20 предлагал оборвать работу скрипта. Firefox почему-то не справился и просто вешался :(

В общем, встала проблема тотального вырезания слишком длинных слов. Конечно, можно было это сделать стандартным способом — разбить строку по пробелам (\s+) а потом замерив длину каждого слова выкинуть слишком длинные и склеить строку обратно. Но это некрасиво :) Хотелось сделать это только регулярками.

Решение


Я ожидал что сработает конструкция вида [^\s]{512,}, где 512 — максимальная разрешённая длина «слова». Однако эта конструкция работать отказалась. Конструкция же [^\s]{512} не подходила, поскольку после неё оставались «хвосты» (например, если слово длиной в 600 символов).

Немного помучившись пришли к выходу, который удовлетворил всем запросам:

preg_replace('/[^\s]{512}[^\s]+/', '', $string)

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

preg_replace('/([^\s]{512})[^\s]+/', '$1...', $string)

А как Вы решали подобную проблему?

UPD: в комментариях так-же предлагают использовать overflow:hidden для всех мест, где пользовательские данные отображаются не в поля ввода.

UPD2: atukai предложил в усовершенствовании не только ставить многоточие, после позволенного количества символов, но и показывать полное слово в Hint-e.
То есть будет выглядеть где-то так:
    preg_replace('/([^\s]{25})[^\s]+/', '<span title="$0">$1...</span>', $string)


UPD3: dandelion напомнил, что я совсем забыл о функции wordwrap. Для данной проблемы ее можно использовать так:
    $string = wordwrap($string, 512, '&shy;', true);
Однако нужно помнить, что эта функция некорректно работает с UTF-8.
Tags:
Hubs:
+62
Comments 80
Comments Comments 80

Articles