Я удивлен, что есть только один ответ с подходом, аналогичным тому, который я использовал.
Я получил вдохновение из комментария @Dtipson к ответу @Mumthezir VP.
Я использую для этого два ввода: один - это поддельный ввод, type="text"
на котором я установил заполнитель, а другой - настоящее поле с type="date"
.
В mouseenter
событии в их контейнере я скрываю фальшивый ввод и показываю реальный, а с mouseleave
событием делаю наоборот . Очевидно, я оставляю реальный ввод видимым, если для него установлено значение.
Я написал код для использования чистого Javascript, но если вы используете jQuery (я использую), его очень легко «преобразовать».
// "isMobile" function taken from this reply:
// https://stackoverflow.com/a/20293441/3514976
function isMobile() {
try { document.createEvent("TouchEvent"); return true; }
catch(e) { return false; }
}
var deviceIsMobile = isMobile();
function mouseEnterListener(event) {
var realDate = this.querySelector('.real-date');
// if it has a value it's already visible.
if(!realDate.value) {
this.querySelector('.fake-date').style.display = 'none';
realDate.style.display = 'block';
}
}
function mouseLeaveListener(event) {
var realDate = this.querySelector('.real-date');
// hide it if it doesn't have focus (except
// on mobile devices) and has no value.
if((deviceIsMobile || document.activeElement !== realDate) && !realDate.value) {
realDate.style.display = 'none';
this.querySelector('.fake-date').style.display = 'block';
}
}
function fakeFieldActionListener(event) {
event.preventDefault();
this.parentElement.dispatchEvent(new Event('mouseenter'));
var realDate = this.parentElement.querySelector('.real-date');
// to open the datepicker on mobile devices
// I need to focus and then click on the field.
realDate.focus();
realDate.click();
}
var containers = document.getElementsByClassName('date-container');
for(var i = 0; i < containers.length; ++i) {
var container = containers[i];
container.addEventListener('mouseenter', mouseEnterListener);
container.addEventListener('mouseleave', mouseLeaveListener);
var fakeDate = container.querySelector('.fake-date');
// for mobile devices, clicking (tapping)
// on the fake input must show the real one.
fakeDate.addEventListener('click', fakeFieldActionListener);
// let's also listen to the "focus" event
// in case it's selected using a keyboard.
fakeDate.addEventListener('focus', fakeFieldActionListener);
var realDate = container.querySelector('.real-date');
// trigger the "mouseleave" event on the
// container when the value changes.
realDate.addEventListener('change', function() {
container.dispatchEvent(new Event('mouseleave'));
});
// also trigger the "mouseleave" event on
// the container when the input loses focus.
realDate.addEventListener('blur', function() {
container.dispatchEvent(new Event('mouseleave'));
});
}
.real-date {
display: none;
}
/* a simple example of css to make
them look like it's the same element */
.real-date,
.fake-date {
width: 200px;
height: 20px;
padding: 0px;
}
<div class="date-container">
<input type="text" class="fake-date" placeholder="Insert date">
<input type="date" class="real-date">
</div>
Я тестировал это также на телефоне Android, и он работает, когда пользователь нажимает на поле, отображается датапикер. Единственное, что если реальный ввод не имел значения, и пользователь закрывает datepicker, не выбирая дату, ввод будет оставаться видимым, пока они не коснутся вне его. Нет события, которое можно было бы слушать, чтобы узнать, когда закроется датапикер, поэтому я не знаю, как это решить.
У меня нет устройства iOS, на котором можно его протестировать.