Деактивация input с введенными данными по кнопке
На сайте создал поиск с полем input и type="search", разметка Bootstrap 4
В мобильных приложениях где есть Поиск, когда нажимаешь в поле Поиск появляется клавиатура для ввода. Чтоб её закрыть - вверху окна клавиатуры есть кнопка Готово или Ввод - разная реализация, смысл один. Второй способ - это нажать кнопку Отмена, которая появляется справа от поля Поиск
Еще вариант нажать "вне" поля Поиск. Важное замечание, при введенных данных в Поиск, закрыть клавиатуру нажатием "вне" поля Поиск не выйдет, так как "вне" - это ссылки с вариантами ответов на запрос
Хочу подобное реализовать для сайта
$(document).on('ready', function () {
/* Изменение ширины input при фокусе */
$('#search').on('focus', function (event) {
var input = $('#search').outerWidth()
if ($('#search').val() === '') {
$('#search').after($('<button>', {
'class': 'btn btn-primary close-btn',
'text': 'Отмена'
}))
console.log('#1 - (focus) input пустой')
} else {
$('#search').after($('<button>', {
'class': 'btn btn-primary close-btn',
'text': 'Отмена'
}))
console.log('#2 - (focus) input не пустой, введенно ->', $('#search').val())
}
var button = $('.close-btn').outerWidth()
var result = input - button
$('#search').outerWidth(result)
})
/* Деактивация input при нажатии вне input */
/* Если input не пуст, ждем выбора одного из */
/* ответов "Поиска" что вызовет переход на другую */
/* страницу или "Очистки" поля input */
$('#search').on('blur', function (event) {
if ($('#search').val() === '') {
$('.close-btn').detach()
$('#search').css('width', '100%')
console.log('#3 - (blur) input пустой')
} else {
$('.close-btn').detach()
$('#search').css('width', '100%')
console.log('#4 - (blur) input не пустой, введенно ->', $('#search').val())
}
})
/* Деактивация input при нажатии на кнопку "Отмена" */
$('.close-btn').on('click', function (event) {
$('.close-btn').detach()
console.log('#5 - (click) input закрыт кнопкой')
})
})
.btn {
margin-left: 15px;
}
/* Не работает */
#search {
transition: width 1s;
-webkit-transition: width 0.4s;
-moz-transition: width 0.4s;
-o-transition: width 0.4s;
}
/* Не работает */
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<!-- JQuery JS -->
<script src="https://code.jquery.com/jquery-2.2.4.js" integrity="sha256-iT6Q9iMJYuQiMWNd9lDyBUStIq/8PuOW33aOqmvFpqI=" crossorigin="anonymous"></script>
</head>
<body class="bg-dark">
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-primary">
<div class="container">
<input type="search" id="search" class="form-control" placeholder="Поиск..." aria-label="Search">
</div>
</nav>
</body>
</html>
Практически получилось. Попытка сделать проверку на пустоту поля input не удалась. Кнопка Отмена и событие click никак не хотят работать. Вместо этого срабатывают только события focus - нажатие на поле input, так же событие blur - нажатие "вне" поля input. Причем не зависимо пуст input или нет
1). Как правильно рассчитать ширину поле input так, чтоб в дескпотной и мобильном варианте сайта, кнопка Отмена появлялась только справа поля input?
2). Как исправить ошибку с проверкой поля input на пустоту, чтоб при введенных данных в поле input его можно было закрыть только кнопкой Отмена => событием click?
Возможно проблема из-за того, что события focus и blur работают с элементами по id, а событие click по class
Update
Не понимаю как это работает --padding в формуле расчета ширины input. И почему внутренние отступы --padding, а не внешние --margin. Правда в Bootstrap 4 нету внешних --margin отступов как Я увидел, только в conteiner родительском блоке. У button еще по умолчанию display: inline-block; он только в десктоп расширении работает, тоже не понимаю как, раз input постоянно width: 100%; и display: block;. Родительский conteiner имеет display: flex;. Вышло так у меня https://jsfiddle.net/15ey34m6/7/
Ответы (2 шт):
Написал свой велосипед по расчету ширины поля input, для мобильной версии
В десктопной версии для блока с классом container присваивается свойство flex-wrap: nowrap;, что позволяет кнопке Отмена занять нужную ширину справа от поля input
В мобильной версии, блоку с классом container присваивается свойство flex-wrap: wrap; назначается оно с расширения экрана <= 768px, что не дает кнопке Отмена расположиться в одну линию с полем input
Для решения задачи сделал проверку - меньше ли ширина блока с классом container чем 768px или нет. Если да, добавлял кнопку Отмена и делал расчет, который менял ширину поля input. Если нет, просто добавлял кнопку Отмена
Спасибо пользователю @h за совет, изучить Bootstrap или выкинуть его вовсе =)
Я немного покопался в Bootstrap разметке, заметил изменение свойств нужных блоков, и немного переделал один из предложенных вариантов решений от пользователя @h
При анимации правда кнопка Отмена прыгает, видно, как поле input ссужается потом поднимается кнопка Отмена. Как исправить не знаю. В целом все работает не совсем верно https://jsfiddle.net/ukh30mgy/2/
var containerSearch = document.querySelector('#container-search')
var inputSearch = document.querySelector('#input-search')
var containerWidth = containerSearch.offsetWidth
var inputWidth = inputSearch.getBoundingClientRect().width
var button = document.createElement('button')
button.className = 'btn bg-primary'
button.textContent = 'Отмена'
inputSearch.addEventListener('focus', function() {
containerSearch.appendChild(button)
if (containerWidth <= 768) {
containerSearch.appendChild(button)
var buttonWidth = button.getBoundingClientRect().width
var result = Math.floor((inputWidth - buttonWidth - 15) * 100) / 100 + 'px'
inputSearch.style.setProperty('width', result)
}
})
inputSearch.addEventListener('blur', function() {
if (inputSearch.value.trim() === '') {
inputSearch.style.setProperty('width', '100%')
button.remove()
}
})
button.addEventListener('click', function() {
inputSearch.style.setProperty('width', '100%')
button.remove()
})
#input-search, .btn {
transition: width 0.2s;
-webkit-transition: width 0.2s;
-moz-transition: width 0.2s;
-o-transition: width 0.2s;
}
.btn {
margin-left: 15px;
color: white;
}
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<body class="bg-dark">
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-primary">
<div id="container-search" class="container">
<input type="search" id="input-search" class="form-control" placeholder="Поиск">
</div>
</nav>
</body>
Update
Нужно сначала изменить ширину поля input после показать кнопку Отмена - как реализовать не понимаю, ведь для расчета ширины поля input нужно знать ширину кнопки Отмена - которую можно узнать только после добавления кнопки Отмена в DOM дерево. Помогите, или совет дайте
Еще одно решение, без каких либо расчетов ширины блока. Только определение ширины родительского блока с классом container
После делается проверка текущего расширения экрана, и назначается свойство родительскому блоку с классом container свойство flex-wrap: nowrap;. Кнопка Отмена просто прячется/открывается
var containerSearch = document.querySelector('#container-search')
var containerWidth = containerSearch.offsetWidth
var inputSearch = document.querySelector('#input-search')
var closeSearch = document.querySelector('#close-search')
var closeButonSearch = closeSearch.hidden = true
inputSearch.addEventListener('focus', function() {
closeSearch.hidden = false
if (containerWidth <= 768) {
containerSearch.style.flexWrap = 'nowrap'
closeSearch.hidden = false
}
})
inputSearch.addEventListener('blur', function() {
if (inputSearch.value.trim() === '') {
closeSearch.hidden = true
}
})
closeSearch.addEventListener('click', function() {
closeSearch.hidden = true
})
.btn {
color: white;
}
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<body class="bg-dark">
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-primary">
<div id="container-search" class="container">
<input type="search" id="input-search" class="form-control" placeholder="Поиск">
<button id="close-search" class="btn bg-primary">Отмена</button>
</div>
</nav>
</body>
Один минус, анимация никак работать не хочет