#jquery #jquery-ui #jquery-ui-datepicker
#jquery #jquery-ui #jquery-ui-datepicker
Вопрос:
На моей странице есть jQuery UI datepicker, и должна быть возможность вводить даты вручную. Чтобы упростить задачу для пользователя, также должна быть возможность ввести краткую форму даты (только день и месяц), и она будет разрешена со следующей возможной датой, как только фокус будет смещен с поля.
Пример (немецкий формат даты):
29092019 должен быть разрешен до 29.09.2019
2909 должен быть разрешен до 29.09.2019
0103 следует перенести на 01.03.2020, когда 1 марта в этом году уже закончится.
Как мне начать с подобной проблемы?
$( function() {
$("#myDate").datepicker({
dateFormat : "dd.mm.yy"
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<input type="text" id="myDate" />
Комментарии:
1. «29042019 должен быть разрешен до 24.09.2019» это верно? Разве это не должно быть
24092019 -> 24.09.2019
?2. вы правы, это опечатка. Измените это сейчас!
3. Хорошо, благодаря предоставленным ответам мы довольно близки. Мне просто нужно выяснить, как я могу проверить проанализированные даты! В настоящее время можно получить значения, подобные, например, «40.15.2050» или «30.02.2019», чего не должно быть. Есть идеи?
4. Посмотрите, что происходит, когда вы запускаете это в консоли:
new Date("30.02.2019")
— оно возвращаетInvalid Date
— используйте это для проверки. Вы должны прочитать об объекте Date в JavaScript.5. **** ЭТОТ ВОПРОС ЗАКРЫТ — БОЛЬШЕ ОТВЕТОВ НЕ ТРЕБУЕТСЯ! **** Вознаграждение получит @scott6 за его удивительную помощь в течение последних нескольких недель. Мне просто нужно подождать 24 часа, пока я не смогу его наградить…
Ответ №1:
Вот один из способов сделать это — комментарии ниже:
// Some sample dates
let userDates = [
"29092019",
"2909",
"0103",
"1303",
"1403"
];
// Run the sample dates through parseUserDate()
for (let userDate of userDates) {
console.log(userDate ":");
console.log(parseUserDate(userDate));
}
function parseUserDate(dateStr) {
let parsedDate;
// If it's 8 characters long, slice into YYYY-MM-DD
if (dateStr.length === 8) {
let dateSplit = [
dateStr.slice(4),
dateStr.slice(2, 4),
dateStr.slice(0, 2)
];
parsedDate = new Date(dateSplit.join("-"));
}
// 4 characters long - slice into MM-DD and prefix with YYYY later.
else if (dateStr.length === 4) {
let monthDay = [
dateStr.slice(2, 4),
dateStr.slice(0, 2)
].join("-");
// The current date - this is used to check if the user date should be next year.
let now = new Date();
// MM-DD with the current year.
let userDateCurrentYear = new Date(now.getFullYear() "-" monthDay);
// MM-DD with next year.
let userDateNextYear = new Date((now.getFullYear() 1) "-" monthDay);
// If the current date is past the MM-DD this year, set parsedDate to next year's date.
if (now > userDateCurrentYear) {
parsedDate = userDateNextYear;
} else {
parsedDate = userDateCurrentYear;
}
}
return parsedDate;
}
Комментарии:
1. Как я могу сохранить гибкость синтаксического анализатора для разных форматов дат?
2. @JonSnow Вы могли бы добавить дополнительный параметр к вызову функции:
parseUserDate(dateStr, dateFormat)
затем разделитьdateStr
соответствующим образом.
Ответ №2:
Попробуйте это..
для интеграции со средством выбора даты jQuery вы можете сделать это, как показано ниже
Правки:
- добавьте неверную проверку даты и верните пустую строку для недопустимых дат
- исправлена проверка даты: добавлена проверка високосного дня
- исправьте переменную monDt (добавьте getMonth 1, поскольку месяц в JS начинается с 0)
$(function(){
$('.datepicker').datepicker({
dateFormat:'dd.mm.yy'
});
$('.datepicker').on('blur',function(){parseInputDate(this);});
})
function parseInputDate(elm) {
var currDate = new Date(),
monDt = (('0' (currDate.getMonth() 1)).slice(-2) ('0' currDate.getDate()).slice(-2)), // get current month date to compare
inputVal = $(elm).val().match(/d{2}/gi); // split date components into array of [dd,mm,yy,yy]
// another date validation, by comparing parameters and date object result
var isValidDate = function(yyyy,mm,dd) {
var dt = new Date(yyyy,parseInt(mm,10)-1,dd);
return (dt.getFullYear() '-' ('0' (dt.getMonth() 1)).slice(-2) '-' ('0' dt.getDate()).slice(-2)) == yyyy '-' mm '-' dd;
}
if (inputVal!=null amp;amp; inputVal.length>=2) {
var year = currDate.getFullYear();
if (monDt>(inputVal[1] inputVal[0])) year ;
// generate formatted text based on date component count
// add date validation to catch invalid dates using (new Date('yyyy-mm-dd')).getTime() which will return NaN on invalid date
var result = (inputVal.length==2 amp;amp; isValidDate(year,inputVal[1],inputVal[0]) amp;amp; inputVal[0] '.' inputVal[1] '.' year) ||
(inputVal.length==3 amp;amp; isValidDate('20' inputVal[2],inputVal[1],inputVal[0]) amp;amp; inputVal[0] '.' inputVal[1] '.20' inputVal[2]) ||
(inputVal.length==4 amp;amp; isValidDate(inputVal[2] inputVal[3],inputVal[1],inputVal[0]) amp;amp; inputVal[0] '.' inputVal[1] '.' inputVal[2] inputVal[3]) ||
''; // set empty on invalid dates
$(elm).val(result);
} else $(elm).val('');
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<input type="text" id="myDate" class="datepicker" />
И это пример для множественного выбора даты с некоторыми ограничениями. Вы можете приспособиться к тому, что вам нужно 🙂
amp; возвращает строку даты на основе формата datepicker
$(function(){
initDatePicker();
})
function initDatePicker(){
// do a loop for custom property on each element
$('.datepicker').each(function(){
// you can find available formats here : http://api.jqueryui.com/datepicker/#utility-formatDate
$(this).datepicker({
dateFormat:'yy.mm.dd'
});
// set minimum date from data attribute.
if (typeof $(this).data('mindate') != 'undefined') {
$(this).datepicker('option','minDate',$(this).data('mindate'));
}
// set maximum date from data attribute.
if (typeof $(this).data('maxdate') != 'undefined') {
$(this).datepicker('option','maxDate',$(this).data('maxdate'));
}
$(this).on('change',function(){
parseInputDate(this);
// now, set date relations :)
if (typeof $(this).data('nextelem') != 'undefined') {
$($(this).data('nextelem')).datepicker( "option", "minDate", getDate( this ) );
}
if (typeof $(this).data('prevelem') != 'undefined') {
$($(this).data('prevelem')).datepicker( "option", "maxDate", getDate( this ) );
}
});
});
}
// get date function taken from : http://jqueryui.com/datepicker/#date-range
function getDate( element ) {
var date;
try {
date = $.datepicker.parseDate( $(element).datepicker('option','dateFormat'), element.value );
} catch( error ) {
date = null;
}
return date;
}
function parseInputDate(elm) {
var currDate = new Date(),
monDt = (('0' (currDate.getMonth() 1)).slice(-2) ('0' currDate.getDate()).slice(-2)), // get current month date to compare
inputVal = $(elm).val().match(/d{2}/gi), // split date components into array of [dd,mm,yy,yy]
format = $(elm).datepicker("option", "dateFormat"); // get current element's datepicker format
// check if it's already a valid entry, then do nothing
if ($(elm).val() == $.datepicker.formatDate(format,$(elm).datepicker('getDate'))) return;
var isValidDate = function(yyyy,mm,dd) {
var dt = new Date(yyyy,parseInt(mm,10)-1,dd);
return (dt.getFullYear() '-' ('0' (dt.getMonth() 1)).slice(-2) '-' ('0' dt.getDate()).slice(-2)) == yyyy '-' mm '-' dd;
}
var getDateString = function(yyyy,mm,dd) {
var dt = new Date(yyyy,parseInt(mm,10)-1,dd);
// get datepicker format amp; get date string using datepicker's formatDate function
return $.datepicker.formatDate($(elm).datepicker("option", "dateFormat"),dt);
}
if (inputVal!=null amp;amp; inputVal.length>=2) {
var year = currDate.getFullYear();
if (monDt>(inputVal[1] inputVal[0])) year ;
// generate formatted text based on date component count
// add date validation to catch invalid dates, amp; generate date string according to datepicker format
var result = (inputVal.length==2 amp;amp; isValidDate(year,inputVal[1],inputVal[0]) amp;amp; getDateString(year,inputVal[1],inputVal[0])) ||
(inputVal.length==3 amp;amp; isValidDate('20' inputVal[2],inputVal[1],inputVal[0]) amp;amp; getDateString('20' inputVal[2],inputVal[1],inputVal[0])) ||
(inputVal.length==4 amp;amp; isValidDate(inputVal[2] inputVal[3],inputVal[1],inputVal[0]) amp;amp; getDateString(inputVal[2] inputVal[3],inputVal[1],inputVal[0])) ||
''; // set empty on invalid dates
$(elm).val(result);
} else $(elm).val('');
// add validation to invalidate out-of-range value
// get selected/entered date
var cdate = $(elm).datepicker('getDate');
// get range
var minDateAttr = $(elm).datepicker("option", "minDate");
var maxDateAttr = $(elm).datepicker("option", "maxDate");
// get datepicker instance
var inst = $('#myDate').data("datepicker");
var isValid = false;
if (minDateAttr!=null) {
// get range as date object
var minDateObj = $.datepicker._determineDate(inst, minDateAttr, new Date());
if (minDateObj<=cdate) isValid = true
}
if (isValid amp;amp; maxDateAttr!=null) {
// get range as date object
var maxDateObj = $.datepicker._determineDate(inst, maxDateAttr, new Date());
if (maxDateObj>=cdate) isValid = true
}
if (!isValid) $(elm).val('');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
Dates :
<input type="text" id="myDate" class="datepicker" data-nextelem="#myDate2" data-mindate="-20" maxlength="10" style="width:80px" /> -
<input type="text" id="myDate2" class="datepicker" data-prevelem="#myDate" data-nextelem="#myDate3" maxlength="10" style="width:80px"/> -
<input type="text" id="myDate3" class="datepicker" data-prevelem="#myDate2" data-maxdate=" 2y" maxlength="10" style="width:80px"/>
Комментарии:
1. Этот пример работает замечательно и почти так, как описано. Не хватает только одной маленькой вещи: поле ввода также должно работать со стандартным jQuery UI datepicker. Должна быть возможность использовать средство выбора или прямой ввод. Когда я добавляю вашу функцию в свое текущее текстовое поле, она работает только для datepicker, но НЕ для прямого ввода. Я тестировал с помощью селектора «.datepicker», а также с помощью «.hasDatepicker». Первый класс — это класс, который jQuery datepicker использует для создания средства выбора вообще, второй класс — сгенерированный.
2. ПОЧТИ ХОРОШО!! Мне просто нужно выяснить, как я могу проверить проанализированные даты! В настоящее время можно получить значения, подобные, например, «40.15.2050» или «30.02.2019», чего не должно быть.
3. @SchweizerSchoggi проблем возникнуть не должно. Пожалуйста, посмотрите мой обновленный ответ 🙂
4. да, это работает. Единственная оставшаяся проблема заключается в том, что пользователь все еще может вводить недопустимые даты
5. @SchweizerSchoggi : oops.. извините за это, getMonth должен быть добавлен к 1 .. ответ обновлен 🙂