Сделать div как input

Добавил пользователь Morpheus
Обновлено: 16.09.2024

Довольно часто приходится сталкиваться с созданием форм, где в зависимости от выбора юзера нужно показать/скрыть блок, например, с другим input. Ну не интересно обычному пользователю, что специалисту, компании, организации и тд нужно заполнить дополнительные поля. Поэтому делаем select и radio button со скрытыми блоками div!

Создаём select открывающий при выборе скрытые блоки

Начнём с JS. Тут всё исключительно просто. Пишем функцию Selected, где в зависимости от значения будут скрыты или показаны определённые блоки. При значении 1 - блок 1 показан, а блок 2 скрыт и так далее. Внимание! Всё равно важно указать состояние для ВСЕХ блоков, так как пользователь может перебирать варианты.

Код Java Script


Код сверху (Java Script) и код снизе (HTML) можно включить в body.

Код HTML

Radio кнопки, открывающие при выборе скрытые блоки

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

Код Java Script

Код HTML


Для динамичного, без перезагрузки страницы, изменения содержания контейнера DIV можно использовать getElementById и innerHTML.

С помощью getElementById мы находим нужный нам контейнер, после чего присваиваем ему нужное значение с помощь innerHTML.

Новое значение может быть задано по умолчанию.
Рассмотрим пример, в котором, при нажатии на ссылку, меняется текст в DIV с заданном ID:

Новое значение, в режиме реального времени, может быть взято из формы.
Точнее – из поля INPUT (или TEXTAREA).

Ниже показан скрипт, который отображает, в блоке DIV, текст, набираемый пользователем:

Этот скрипт может быть использован в качестве примитивного визуального редактора HTML – Вы сразу видите отображение вводимых HTML тэгов.
Вместо INPUT используем TEXTAREA и делаем небольшую задержку отображения результата с помощью функции setTimeout().

Разместить кнопку отправки формы внутри рамки для ввода текста.

Решение

Надо понимать, что напрямую добавить кнопку внутрь поля формы нельзя. Поэтому любые методы лишь имитируют этот эффект. Для создания подобной иллюзии следует убрать исходную рамку вокруг поля для поиска и добавить её к элементу, внутри которого располагается поле и кнопка. Данный метод лучше всего работает когда все размеры у нас имеют фиксированные значения. В примере 1 общая ширина формы задана как 300 пикселов, поле имеет ширину 274 пиксела, а кнопка — 20 пикселов. Ширина поля подобрана с учётом того, чтобы не возникало переносов в форме, это негативно скажется на общем виде.

Некоторых добавлений в код CSS потребуют браузеры Safari и Chrome. При получении фокуса поля формы подсвечиваются цветной рамкой, которая разрушает нашу иллюзию единого поля. Чтобы этого не возникало, в стиле поля для поиска добавим outline со значением none , это позволит заблокировать появление рамки в указанных браузерах. Вокруг поля поиска ( ) в любом случае останется тонкая рамка, её можно удалить с помощью специфического свойства -webkit-appearance опять же со значением none .

Пример 1. Форма поиска

HTML5 CSS 2.1 IE Cr Op Sa Fx

Результат примера показан на рис. 1.

Вид поля для поиска с кнопкой

Рис. 1. Вид поля для поиска с кнопкой

Саму кнопку можно добавить по разному. Например, сделать её обычной кнопкой с надписью, через , или, как в примере выше, в виде кнопки с фоновым рисунком.

Проблема

Прежде чем кидаться решать проблему — ее нужно осознать. С чего бы начать? Все зависит от поставленной вам задачи. Например: если требуется, чтобы инпут расширялся в ширину — это одна проблема. Если нужно чтобы он рос в высоту — это проблема другая. А если нужно чтобы сразу во все стороны, тут можно начинать страдать, дело-то непростое.

Главная проблема состоит в том, что элементы ввода не умеют растягиваться по своему содержимому. Это очень досадно и конечно мир был бы лучше, если бы они умели, но увы. Более того, однострочное текстовое поле — input вообще бессмысленно растягивать в высоту, содержимое все равно не ляжет в несколько строк, так уж он устроен. Поэтому дальше начинаются любимые фронтендерами лайфхаки.

Варианты решения

Самый первый, приходящий в топ выдачи гугла — это просто взять и заменить инпут на div с атрибутом contenteditable — и вот оно, проблема решена! Вот вам адаптивный по высоте/ширине див и редактируемое содержимое. Но если для вас (как и для меня) это не вариант, то смотрим дальше.

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

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

Выбираем правильный инпут

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

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

Тут следует обратить внимание на три обязательных параметра, без которых ничего не сработает: box-sizing, height, min-height.

box-sizing: border-box

В обязательном порядке box-sizing должен быть в значении border-box, чтобы когда вы добавите паддинг в текстовом поле, а вы его обязательно добавите, он не увеличивал дополнительно высоту или ширину текстового поля, а откладывался бы вовнутрь.

height и min-height (width и min-width)

Тут все просто: height — чтобы изначально textarea выглядела бы как input. min-height — чтобы при сбросе значения высоты текстовое поле не прыгало, а оставалось минимально необходимого размера. Все это справедливо и для свойств width и min-width.

Немного теории

Принцип действия очень простой. У каждого DOM-элемента, который может содержать контент, есть readonly-свойство scrollHeight (scrollWidth) которое и содержит так нужную нам, истинную высоту элемента, такую, при которой все содержимое этого элемента будет видно пользователю. Все, что нам требуется — при изменении текстового поля, вычислять значение scrollHeight/scrollWidth и присваивать его текстовому полю.

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

Немного vanilla JS-практики

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

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

Ну и давайте для ширины тоже сделаем. Все то же самое, только тут уже берем input, и высоту меняем на ширину.

Результат

Вот такие поля получились. Несложно и недолго.

Адаптивный инпут, растущий в высоту:

Адаптивный инпут, растущий в ширину:

Angular Директива

Для тех, кто дочитал аж до сюда — бонус. Если лень самостоятельно упаковать все это в директиву, я уже все сделала за вас, смотрите:

Здесь используется уже знакомый вам декоратор @HostListener. А если еще не знакомый, то обязательно почитайте статью об этом.

Пример использования:

Да, можно обойтись одним элементом — textarea. Просто, если нужна адаптивность в ширину — добавим CSS-свойство white-space: nowrap — запрет на перенос строк.

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

Читайте также: