Дао роста полей

    Немного пятничного веселья.
    Поля ввода, Textarea, которые молчат, когда с ними ничего не делают, на самом деле хотят расти. Когда объём вводимых текстов превышает их размеры, их тайное желание не всегда слышится дизайнерами и верстальщиками, потому что они уже далеко и думают о новых горизонтах. Оно есть, если прислушаться к кончикам пальцев пользователя, досадливо двигающих скролл мыши.

    Иногда об этом удаётся забыть, если размер поля ввода предоставлен в основном удовлетворительный. В 3 браузерах из 5 есть даже место для изменения размеров, которое верстальщик, оглушённый указанием свыше, иногда отключает (textarea{resize: none}). Есть и другие способы затруднить жизнь пользователю. И тогда он уходит берётся за скрипты и стили.

    Иногда рост поля ввода требует умеренности. К примеру, если он дошёл до 80% высоты окна или логического блока раскладки страницы. Этот крайний случай тоже требует внимания, но чаще возникает первая проблема — поля малы.

    История

    На известном новостном сайте Х. (имена изменены, совпадения случайны) изменяемость полей ввода подавляют не менее жёстко, чем политику. Подавление многопланово, словно они, на той стороне баррикады старались затруднить поползновение исправить это простыми средствами.

    Пока высота поля ввода составляла 6-7 строк, никто особо не задумывался, почему высота полей не изменяется. Но Safari, а затем Chrome подали плохой пример — у них появился уголок, за который пользователь мог потянуть и начать вводить в комментарий слишком много текста. Надо было что-то делать, чтобы ухудшить жизнь, чтобы они, эти толпы кликали куда надо и не писали куда не надо. Последней каплей стал Firefox около года назад. Когда и он стал ресайзить поле ввода, срочно надо было что-то предпринимать. И тут они вспомнили про resize: none.

    Начали с того, что в вопросах-ответах установили 3 строки ввода и вскоре запретили ресайз (resize: none). Но пользователи-то не лыком шиты, на каждый resize:none у них найдётся свой resize: vertical. Ощущения полной победы над пользователями полем ввода у дизайнера не оставалось.

    И тогда появилась находка (у верстальщика — дизайнер об этом даже не мечтал), опробованная в разделе писем:
    textarea {height: 120px!important};
    

    — Браво! — сказал Большой Босс верстальщику, — Молодец, брат, выручил! Теперь они попляшут у нас в пределах 120 пикселей! Теперь просто стилями не обойдёшься, чтобы таскать поле ввода за уголок и ресайзить на сколько хошь. Теперь они и письма будут стараться писать на 6 строк, а ответы, как обычно — на 3 строки. Мы им покажем, как не писать статьи, на которые отведено целых 400 пикселей! (Почему не 800 и вообще почему до сих пор нет автоувеличения поля ввода? Это тебе наш сеошник объяснит.)

    И тогда юзеры взялись за скрипты. Сами они не хотели резать и вообще мирные люди. Но пришлось. Небольшая магия скриптов со стилями — и поля снова стали ресайзиться вручную. Но этого показалось мало. Теперь в желаниях юзеров, опьянённых жаждой борьбы и вкусом победы, снова замаячил авторост.

    Авторост — это такое свойство поля ввода, не предусмотренное даже браузером (иначе, зачем были бы нужны программисты?). Если в обычный блок добавляешь текст, его границы растут в высоту (вниз) без всяких скриптов. У поля ввода этого нет. Только костыли скриптов помогут полю ввода подрастать и уж очень изысканно надо уметь позаботиться о том, чтобы этот рост был идеальным, кроссбраузерным и таким же точным, до пикселя, какой он изначально есть у блочного элемента (который, например, с тегом DIV). Правда, проблемы значительно уменьшаются, если не нужно обеспечивать автоуменьшение высоты, только автоувеличение.

    Реализация

    Скрипт HabrAjax дополнился функцией автоувеличения полей ввода по мере роста текстового содержания. Автоуменьшение сознательно не сделано, потому что имеется возможность регулировать высоту поля ввода вручную, двигая за нижний правый уголок (кроме Оперы, где нет такой функции, но в ней устроено автоуменьшение).

    Теоретически, этого хотелось давно — не смотреть на ограниченные рамки полей, но так, чтобы не писать 20 строк скрипта, если неудобство решается 1 строкой стилей. Поэтому 1.5-2 года обходились ресайзом стилями и руками. Поэтому и дополнение сейчас — не на 20 строк, а примерно на 7 содержательных, остальное — фарш для прочих эффектов — максимальная высота и отсутствие скролла, когда он не нужен, реалии DOMа. (Код адаптирован для чтения, не точная копия юзерскрипта.)
    var dQ = function(q){return document.querySelector(q);};
    var win = typeof unsafeWindow !='undefined'? unsafeWindow: window;
    var tAGrow = function(tA){ //авторост-обработчик
      if(!tA) return;
      var tSHPrev =0, tAInh, tATout
        maxH = Math.floor(win.innerHeight *0.8),
        tAF = function(ev){
          if(tSHPrev < maxH && tAInh)
            clearTimeout(tATout), tA.style.overflow ='hidden', tAInh =0;
          var tSH = tA.scrollHeight - (isChrome?6:!isFx?win.opera?2:6:0); //коссбраузерные подгонки
          if(win.opera){ //автоуменьшение для Оперы
            tA.blur();
            tA.style.height = 0;
            tA.style.marginBottom = tSH +'px';
            tSH = tA.scrollHeight -2;
            tA.style.height = tSH +'px';
            tA.style.marginBottom = 0;
            tA.focus();
          }
          if(tSHPrev <= tSH && tSHPrev < maxH){
            tA.style.height = tSH +'px';
            if(tSHPrev < maxH && tAInh)
              clearTimeout(tATout), tA.style.overflow ='hidden', tAInh =0;
          }else if(!tAInh)
            clearTimeout(tATout), tATout = setTimeout(function(){tA.style.overflow ='inherit'; tAInh =1}, 230);
          tSHPrev = tSH;
        };
      tA.addEventListener('keypress',tAF,!1); //контроль за ростом блока данных
      tA.addEventListener('keyup',tAF,!1);
      tA.style.resize ='vertical'; //чтобы уменьшать вручную (Fx, Chrome, Safari)
      tA.style.maxHeight = maxH +'px';
    };
    tAGrow(dQ('.editor #comment_text')||dQ('.editor #answer_text')||dQ('.editor #text_textarea') );
    tAGrow(dQ('.editor #text') );
    

    Известно, что если не дублировать в невидимом месте поле ввода для получения правильной высоты текста в Firefox/Chrome/Safari, можно заметить только увеличение высоты поля ввода, а не уменьшение. Уменьшать поле ввода нет частой необходимости, и это можно сделать тасканием за уголок. Поэтому решение — максимально ленивое, но, наверное, будет достаточно удобным. В любом случае, может быть доработано или отключено.

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

    Увидеть авторост в действии и пользоваться им на сайте можно, установив версию юзерскрипта Habrajax 0.87 или выше.

    Отключается возможность автороста при сохранении других функций скрипта — в настройках; по умолчанию — включено. Проверялось в Fx, Chrome, но остальные 2 браузера должны работать, а в Опере высота должна автоуменьшаться, без необходимости тянуть обратно за уголок (там и возможности такой нет). Могут быть небольшие малоприятные прыжки высоты поля в начале ввода символов из-за многочисленных разных сайтовых вёрсток, это будет решаться чуть позже стилями. Могут всплыть и другие побочные эффекты роста — всё будет тестироваться в реальной работе.

    UPD 02:00: проверено в Опере — она пока не автоуменьшает высоту, но это будет решено в следующем апдейте. Опера с какого-то времени (например, наблюдается в 11.62) повела себя, как все остальные, кроме IE, со scrollHeight — теперь по нему нельзя узнать высоту текста!

    UPD 06:00: — версия 0.872 — вставлено автоуменьшение textarea для Оперы как самая малая нагрузка на скрипты. Сделано методом, описанным в habrahabr.ru/post/132872. Он нагружает скрипты и DOM, из-за чего могут быть эффекты мерцания и другие, поэтому в других браузерах автоуменьшение не включено (лучше, если делать, то методом с 2 textarea, который реализован, кстати, в Цитатнике-корректоре HabrAjax — растущая textarea в ширну и высоту для ввода контекстных комментариев).

    Проверено в Safari 5.1.4 Win +NinjaKit — там большие критические баги — неввод пробелов, Enter, несохранение настроек и ряд других недостатков, поэтому пока не рекомендуется. Вообще, NinjaKit уже недостаточен для поддержки этого скрипта, и лучшее решение — отдельный аддон, делать который неоправданно из-за малого количества пользователей (потенциальных 2-3 человека).
    • +32
    • 1,7k
    • 9
    Поделиться публикацией

    Похожие публикации

    Комментарии 9

      +13
      Мир спасет красота, любовь и массовые расстрелы тех, кто делает textarea { resize: none }.
        +1
        Все таки ТМ надо помиловать, а то как же мы без хабра жить будем…
          +7
          — Нет, уж кого-кого, а тебя-то я не помилую, — с тихой ненавистью сказал Иван Николаевич.
          0
          Или max-height min-height max-width min-width
            +1
            Бывают случаи, когда по дизайну не положено тянуться, скажем форме контактов в модальном окне.
            +2
            бывает нужно из-за дизайна, пишу resize: none, ощущение ужасное, как ногтем по стеклу
              +1
              За такой дизайн надо прищемлять пальцы крышкой макбука:)
            –1
            dddd
              0
              Пост своевременный и на больную тему) Для разнообразия, предлагаю тёплый ламповый плагин к jQuery: www.jacklmoore.com/autosize

              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

              Самое читаемое